C++ Save Bitmap file - c++

I'm working on an application that captures the user's screen and saved in bitmap.
I'm having problems when creating the file
HANDLE file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, 0,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
I am getting the following error in filename:
argument of type "LPCSTR" is incompatible with parameter of type "LPCWSTR"
below is the code:
#include <olectl.h>
bool saveBitmap(LPCSTR filename, HBITMAP bmp, HPALETTE pal)
{
bool result = false;
PICTDESC pd;
pd.cbSizeofstruct = sizeof(PICTDESC);
pd.picType = PICTYPE_BITMAP;
pd.bmp.hbitmap = bmp;
pd.bmp.hpal = pal;
LPPICTURE picture;
HRESULT res = OleCreatePictureIndirect(&pd, IID_IPicture, false,
reinterpret_cast<void**>(&picture));
if (!SUCCEEDED(res))
return false;
LPSTREAM stream;
res = CreateStreamOnHGlobal(0, true, &stream);
if (!SUCCEEDED(res))
{
picture->Release();
return false;
}
LONG bytes_streamed;
res = picture->SaveAsFile(stream, true, &bytes_streamed);
HANDLE file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, 0,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (!SUCCEEDED(res) || !file)
{
stream->Release();
picture->Release();
return false;
}
HGLOBAL mem = 0;
GetHGlobalFromStream(stream, &mem);
LPVOID data = GlobalLock(mem);
DWORD bytes_written;
result = !!WriteFile(file, data, bytes_streamed, &bytes_written, 0);
result &= (bytes_written == static_cast<DWORD>(bytes_streamed));
GlobalUnlock(mem);
CloseHandle(file);
stream->Release();
picture->Release();
return result;
}
void CaptureScreen()
{
int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
HWND hDesktopWnd = GetDesktopWindow();
HDC hDesktopDC = GetDC(hDesktopWnd);
HDC hCaptureDC = CreateCompatibleDC(hDesktopDC);
HBITMAP hCaptureBitmap = CreateCompatibleBitmap(hDesktopDC,
nScreenWidth, nScreenHeight);
SelectObject(hCaptureDC, hCaptureBitmap);
BitBlt(hCaptureDC, 0, 0, nScreenWidth, nScreenHeight,
hDesktopDC, 0, 0, SRCCOPY | CAPTUREBLT);
LPCSTR fname = "c:\\Users\\hom3r\\Downloads\\image.bmp";
HPALETTE hpal = NULL;
saveBitmap(fname, hCaptureBitmap, hpal);
ReleaseDC(hDesktopWnd, hDesktopDC);
DeleteDC(hCaptureDC);
DeleteObject(hCaptureBitmap);
}

You have UNICODE defined in your project, meaning that you are using the wide-character version of the Windows API. LPC[W]STR is Long Pointer to C [Wide] String.
You can either remove the UNICODE define to use the 8-bit ASCII interface, or better, use wide characters throughout your application.

You have to convert file_name from LPCSTR to LPCWSTR using ATL (Active Template Library).
Hence, replace
HANDLE file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, 0,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
with
HANDLE file = CreateFile(A2W(filename), GENERIC_WRITE, FILE_SHARE_READ, 0,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
A2W (ANSI to wide) is defined in <atlbase.h>.

Try to use TCHAR or wchar_t type. See similar questions at StackOverflow and MSDN.net

Related

AcquireCredentialsHandleA() returns 0x8009030e (No credentials are available in the security package) for PFX file

I'm trying to setup server-side encryption using SSPI. I'm successfully (as far as I can tell) loading a certificate stored as a PFX file, but the call to m_pSSPI->AcquireCredentialsHandleA() returns 0x8009030e.
This method seems to successfully load the file and return a CERT_CONTEXT object.
HRESULT CTLSPackage::LoadCertContextFromFilePFX (PCWSTR pcwzFile, PCWSTR pcwzPassword, __deref_out PCCERT_CONTEXT* ppctxCert)
{
HRESULT hr;
HANDLE hFile, hSection = NULL;
BOOL (WINAPI* pfnPFXIsPFXBlob)(CRYPT_DATA_BLOB*);
HCERTSTORE (WINAPI* pfnPFXImportCertStore)(CRYPT_DATA_BLOB*, LPCWSTR, DWORD);
PCCERT_CONTEXT (WINAPI* pfnCertEnumCertificatesInStore)(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrevCertContext);
CRYPT_DATA_BLOB blob; blob.pbData = NULL;
HCERTSTORE pfxStore = NULL;
hFile = CreateFile(pcwzFile, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
CheckIfGetLastError(INVALID_HANDLE_VALUE == hFile);
blob.cbData = GetFileSize(hFile, NULL);
hSection = CreateFileMapping(hFile, 0, PAGE_READONLY, 0, 0, 0);
CheckIfGetLastError(NULL == hSection);
blob.pbData = reinterpret_cast<PBYTE>(MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0));
CheckIfGetLastError(NULL == blob.pbData);
Check(TGetFunction(m_hCrypt32, "PFXIsPFXBlob", &pfnPFXIsPFXBlob));
Check(TGetFunction(m_hCrypt32, "PFXImportCertStore", &pfnPFXImportCertStore));
Check(TGetFunction(m_hCrypt32, "CertEnumCertificatesInStore", &pfnCertEnumCertificatesInStore));
CheckIf(!pfnPFXIsPFXBlob(&blob), E_FAIL);
pfxStore = pfnPFXImportCertStore(&blob, pcwzPassword, CRYPT_MACHINE_KEYSET | CRYPT_EXPORTABLE);
CheckIf(NULL == pfxStore, SEC_E_NO_CREDENTIALS);
*ppctxCert = pfnCertEnumCertificatesInStore(pfxStore, NULL);
CheckIf(NULL == *ppctxCert, SEC_E_NO_CREDENTIALS);
Cleanup:
if(pfxStore)
{
BOOL (WINAPI* pfnCertCloseStore)(HCERTSTORE, DWORD);
if(SUCCEEDED(TGetFunction(m_hCrypt32, "CertCloseStore", &pfnCertCloseStore)))
pfnCertCloseStore(pfxStore, 0);
}
if(blob.pbData)
UnmapViewOfFile(blob.pbData);
SafeCloseHandle(hSection);
SafeCloseFileHandle(hFile);
return hr;
}
The result is immediately passed to another class method, which makes the failing AcquireCredentialsHandleA() call.
HRESULT CTLSPackage::AcquireCredentials (__in_opt PCCERT_CONTEXT pCertContext, PCredHandle phCreds)
{
SCHANNEL_CRED SchannelCred;
TimeStamp tsExpiry;
ZeroMemory(&SchannelCred, sizeof(SchannelCred));
SchannelCred.dwVersion = SCHANNEL_CRED_VERSION;
if(pCertContext)
{
SchannelCred.cCreds = 1;
SchannelCred.paCred = &pCertContext;
}
SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1 | SP_PROT_TLS1_1 | SP_PROT_TLS1_2;
if(!m_fServer)
SchannelCred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS | SCH_USE_STRONG_CRYPTO;
//
// Create an SSPI credential.
//
return m_pSSPI->AcquireCredentialsHandleA(
NULL, // Name of principal
m_fServer ? NEGOSSP_NAME_A : UNISP_NAME_A, // Name of package
m_fServer ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND,
NULL, // Pointer to logon ID
&SchannelCred, // Package specific data
NULL, // Pointer to GetKey() func
NULL, // Value to pass to GetKey()
phCreds, // (out) Cred Handle
&tsExpiry); // (out) Lifetime (optional)
}
My CTLSPackage::AcquireCredentials() code path is also used for setting up client-side encryption, and that works. For the server-side path, m_fServer is TRUE. The m_hCrypt32 member was loaded from Crypt32.dll.
I've cobbled together this code from samples, but I must be missing something for the server case. I only need to setup SSL/TLS-style encryption, so the "No credentials are available in the security package" error is weird because I have no need for credential authentication.
Does anyone know what might be missing? Thanks!
With a hint from RbMm, I then found this article:
https://www.codeproject.com/articles/125124/how-to-use-certificate-from-disk-with-microsoft-cr
The short answer is that CryptAcquireCertificatePrivateKey() needed to be used when loading a PFX from a file, and UNISP_NAME_A needed to be passed to AcquireCredentialsHandleA().
For reference, here is the revised code:
HRESULT CTLSPackage::LoadCertContextFromFilePFX (PCWSTR pcwzFile, PCWSTR pcwzPassword, __deref_out PCCERT_CONTEXT* ppctxCert)
{
HRESULT hr;
HANDLE hFile, hSection = NULL;
BOOL (WINAPI* pfnPFXIsPFXBlob)(CRYPT_DATA_BLOB*);
HCERTSTORE (WINAPI* pfnPFXImportCertStore)(CRYPT_DATA_BLOB*, LPCWSTR, DWORD);
PCCERT_CONTEXT (WINAPI* pfnCertFindCertificateInStore)(HCERTSTORE hCertStore, DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType, const void* pvFindPara, PCCERT_CONTEXT pPrevCertContext);
BOOL (WINAPI* pfnCryptAcquireCertificatePrivateKey)(PCCERT_CONTEXT pCert, DWORD dwFlags, void* pvReserved, HCRYPTPROV_OR_NCRYPT_KEY_HANDLE *phCryptProvOrNCryptKey, DWORD* pdwKeySpec, BOOL* pfCallerFreeProvOrNCryptKey);
HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hProv;
DWORD dwKeySpec;
BOOL fFreeProv = FALSE;
CRYPT_DATA_BLOB blob; blob.pbData = NULL;
HCERTSTORE hpfxStore = NULL;
hFile = CreateFile(pcwzFile, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
CheckIfGetLastError(INVALID_HANDLE_VALUE == hFile);
blob.cbData = GetFileSize(hFile, NULL);
hSection = CreateFileMapping(hFile, 0, PAGE_READONLY, 0, 0, 0);
CheckIfGetLastError(NULL == hSection);
blob.pbData = reinterpret_cast<PBYTE>(MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0));
CheckIfGetLastError(NULL == blob.pbData);
Check(TGetFunction(m_hCrypt32, "PFXIsPFXBlob", &pfnPFXIsPFXBlob));
Check(TGetFunction(m_hCrypt32, "PFXImportCertStore", &pfnPFXImportCertStore));
Check(TGetFunction(m_hCrypt32, "CertFindCertificateInStore", &pfnCertFindCertificateInStore));
Check(TGetFunction(m_hCrypt32, "CryptAcquireCertificatePrivateKey", &pfnCryptAcquireCertificatePrivateKey));
CheckIf(!pfnPFXIsPFXBlob(&blob), HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
hpfxStore = pfnPFXImportCertStore(&blob, pcwzPassword, 0);
if(NULL == hpfxStore && pcwzPassword && L'\0' == *pcwzPassword)
{
hpfxStore = pfnPFXImportCertStore(&blob, NULL, 0);
CheckIf(NULL == hpfxStore, SEC_E_NO_CREDENTIALS);
}
*ppctxCert = pfnCertFindCertificateInStore(hpfxStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL);
CheckIfGetLastError(NULL == *ppctxCert);
// Acquire the private key and make it available for the later AcquireCredentalsHandle() call.
if(!pfnCryptAcquireCertificatePrivateKey(*ppctxCert, 0, NULL, &hProv, &dwKeySpec, &fFreeProv))
{
DWORD dwError = GetLastError();
FreeCertificateContext(*ppctxCert);
*ppctxCert = NULL;
CheckWin32Error(dwError);
}
Cleanup:
if(fFreeProv)
FreeProvOrNCryptKey(hProv, dwKeySpec);
if(hpfxStore)
{
BOOL (WINAPI* pfnCertCloseStore)(HCERTSTORE, DWORD);
if(SUCCEEDED(TGetFunction(m_hCrypt32, "CertCloseStore", &pfnCertCloseStore)))
pfnCertCloseStore(hpfxStore, 0);
}
if(blob.pbData)
UnmapViewOfFile(blob.pbData);
SafeCloseHandle(hSection);
SafeCloseFileHandle(hFile);
return hr;
}
HRESULT CTLSPackage::AcquireCredentials (__in_opt PCCERT_CONTEXT pCertContext, PCredHandle phCreds)
{
SCHANNEL_CRED SchannelCred;
TimeStamp tsExpiry;
ZeroMemory(&SchannelCred, sizeof(SchannelCred));
SchannelCred.dwVersion = SCHANNEL_CRED_VERSION;
if(pCertContext)
{
SchannelCred.cCreds = 1;
SchannelCred.paCred = &pCertContext;
}
SchannelCred.grbitEnabledProtocols = SP_PROT_SSL3 | SP_PROT_TLS1 | SP_PROT_TLS1_1 | SP_PROT_TLS1_2;
SchannelCred.dwFlags = SCH_USE_STRONG_CRYPTO;
if(!m_fServer)
SchannelCred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
//
// Create an SSPI credential.
//
return m_pSSPI->AcquireCredentialsHandleA(
NULL, // Name of principal
UNISP_NAME_A, // Name of package
m_fServer ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND,
NULL, // Pointer to logon ID
&SchannelCred, // Package specific data
NULL, // Pointer to GetKey() func
NULL, // Value to pass to GetKey()
phCreds, // (out) Cred Handle
&tsExpiry); // (out) Lifetime (optional)
}

How to make and send a print screen to a FTP server without save the file? My working code save the files to HDD

Before to made this post I searched and trying 4 days all things,like https://www.codeproject.com/kb/gdi-plus/memimage.aspx, but I am new in programming.
This code (not mine), made a print screen, save to a file and then are sent to a ftp server. I want to do this without save the files to HDD, from memory to FTP.
// The print-screen and save to file (jpg) code:
wstring wtmp;
tmp = sDate + pictureName + ".jpeg";
wtmp = ToStringW(tmp);
screenName = wtmp.c_str();
ftpScreenName = wtmp.c_str();
fileToRemove = tmp.c_str();
using namespace Gdiplus;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
{
HDC scrdc, memdc;
HBITMAP membit;
scrdc = ::GetDC(0);
int Height = GetSystemMetrics(SM_CYSCREEN);
int Width = GetSystemMetrics(SM_CXSCREEN);
memdc = CreateCompatibleDC(scrdc);
membit = CreateCompatibleBitmap(scrdc, Width, Height);
HBITMAP hOldBitmap = (HBITMAP)SelectObject(memdc, membit);
BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);
Gdiplus::Bitmap bitmap(membit, NULL);
EncoderParameters encoderParameters;
ULONG quality;
CLSID clsid;
GetEncoderClsid(L"image/jpeg", &clsid);
encoderParameters.Count = 1;
encoderParameters.Parameter[0].Guid = EncoderQuality;
encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
encoderParameters.Parameter[0].NumberOfValues = 1;
// Save the image as a JPEG with quality level 80.
quality = 80;
encoderParameters.Parameter[0].Value = &quality;
int result;
result = bitmap.Save(screenName, &clsid); //saving the file to HDD
//send to ftp with given info
saveFTP(server, user, password, ftpScreenName, screenName);
}
GdiplusShutdown(gdiplusToken);
// And here the FTP client part:
bool saveFTP(LPCWSTR l_server, LPCWSTR l_user, LPCWSTR l_pass, LPCWSTR l_ftpfile, LPCWSTR l_screen)
{
HINTERNET internet = InternetOpen(L"tester", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_ASYNC);
HINTERNET inter = InternetConnect(internet, l_server, INTERNET_DEFAULT_FTP_PORT, l_user, l_pass, INTERNET_SERVICE_FTP, 0, 0);
bool result;
result = FtpPutFile(inter, l_screen, l_ftpfile, FTP_TRANSFER_TYPE_BINARY, 0);
InternetCloseHandle(inter);
InternetCloseHandle(internet);
return result;
}
Use FtpOpenFile() and InternetWriteFile() instead of FtpPutFile(). This is explicitly stated in the FtpPutFile() documentation:
FtpPutFile is a high-level routine that handles all the bookkeeping and overhead associated with reading a file locally and storing it on an FTP server. An application that needs to send file data only, or that requires close control over the file transfer, should use the FtpOpenFile and InternetWriteFile functions.
As well as in WinInet's FTP Sessions documentation
To upload or place files on an FTP server, the application can use either FtpPutFile or FtpOpenFile (along with InternetWriteFile). FtpPutFile can be used if the file already exists locally, while FtpOpenFile and InternetWriteFile can be used if data needs to be written to a file on the FTP server.
Gdiplus::Bitmap can save to either an HDD file or an IStream. You can use
either CreateStreamOnHGlobal() or SHCreateMemStream() to create a memory stream, then save the Bitmap to the stream, and finally upload the content of the stream using FtpOpenFile() and InternetWriteFile().
For example (error handling omitted for brevity, don't omit it in your real code!):
tmp = sDate + pictureName + ".jpeg";
wstring wtmp = ToStringW(tmp);
IStream *strm = SHCreateMemStream(NULL, 0);
using namespace Gdiplus;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
CLSID clsid;
GetEncoderClsid(L"image/jpeg", &clsid);
EncoderParameters encoderParameters;
encoderParameters.Count = 1;
encoderParameters.Parameter[0].Guid = EncoderQuality;
encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
encoderParameters.Parameter[0].NumberOfValues = 1;
// Save the image as a JPEG with quality level 80.
ULONG quality = 80;
encoderParameters.Parameter[0].Value = &quality;
HDC scrdc = ::GetDC(0);
int Height = GetSystemMetrics(SM_CYSCREEN);
int Width = GetSystemMetrics(SM_CXSCREEN);
HDC memdc = CreateCompatibleDC(scrdc);
HBITMAP membit = CreateCompatibleBitmap(scrdc, Width, Height);
HBITMAP hOldBitmap = (HBITMAP) SelectObject(memdc, membit);
BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);
{
Gdiplus::Bitmap bitmap(membit, NULL);
bitmap.Save(strm, &clsid); //saving the file to HDD
}
SelectObject(memdc, hOldBitmap);
DeleteObject(membit);
DeleteDC(memdc);
::ReleaseDC(0, scrdc);
GdiplusShutdown(gdiplusToken);
LARGE_INTEGER li;
li.QuadPart = 0;
strm->Seek(li, STREAM_SEEK_SET, NULL);
//send to ftp with given info
saveFTP(server, user, password, wtmp.c_str(), strm);
strm->Release();
bool saveFTP(LPCWSTR l_server, LPCWSTR l_user, LPCWSTR l_pass, LPCWSTR l_ftpfile, IStream *l_screen)
{
HINTERNET internet = InternetOpen(L"tester", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_ASYNC);
HINTERNET conn = InternetConnect(internet, l_server, INTERNET_DEFAULT_FTP_PORT, l_user, l_pass, INTERNET_SERVICE_FTP, 0, 0);
HINTERNET file = FtpOpenFile(conn, l_ftpfile, GENERIC_WRITE, FTP_TRANSFER_TYPE_BINARY, 0);
BYTE buffer[1024], *pbuf;
ULONG ulRead;
DWORD dwWritten;
HRESULT hr;
bool success = true;
do
{
hr = l_screen->Read(buffer, sizeof(buffer), &ulRead);
if (FAILED(hr))
{
success = false;
break;
}
pbuf = buffer;
while (ulRead != 0)
{
if (!InternetWriteFile(file, pbuf, ulRead, &dwWritten))
{
success = false;
break;
}
pbuf += dwWritten;
ulRead -= dwWritten;
}
}
while (hr == S_OK);
InternetCloseHandle(file);
InternetCloseHandle(conn);
InternetCloseHandle(internet);
return success;
}

Windows ListView LVM_GETITEM iImage is always zero

I am trying to do some stuff with the desktop listview. I can get the text of the item with LVM_GETITEM, but the iImage struct member is always zero, and so is the state. I'm running Win 7 64 and compiled for 64 with Dev C++(gcc). I also tried compiling it as 32bit and tested on XP with the same result...just text, image and state are assigned zero. I can also get the item count no problem with ListView_GetItemCount().
HWND progman = FindWindow("progman", NULL);
HWND shell = FindWindowEx(progman, NULL, "shelldll_defview", NULL);
HWND hwndListView = FindWindowEx(shell, NULL, "syslistview32", NULL);
int ct = ListView_GetItemCount(hwndListView);
const DWORD dwBufSize = 1024;
DWORD dwProcessID;
DWORD dwResult;
HANDLE hProcess;
BYTE *lpRemoteBuffer;
LVITEM lvItem = {0};
BYTE lpLocalBuffer[dwBufSize] = {0};
// Get the process id owning the window
::GetWindowThreadProcessId( hwndListView, &dwProcessID );
// Open the process wih all access (You may not have the rights to do this)
hProcess = ::OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessID );
// Allocate a buffer in the remote process
lpRemoteBuffer = (BYTE*)::VirtualAllocEx( hProcess, NULL, dwBufSize,
MEM_COMMIT, PAGE_READWRITE );
// Fill in the LVITEM struct, this is in your own process
// Set the pszText member to somewhere in the remote buffer,
// For the example I used the address imediately following the LVITEM stuct
lvItem.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM|LVIF_STATE;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.cchTextMax = MAX_PATH;
// Point to after LVITEM in the remote buffer
lvItem.pszText = (LPTSTR)(lpRemoteBuffer + sizeof( LVITEM ));
// Copy the local LVITEM to the remote buffer
::WriteProcessMemory( hProcess, (LPVOID)lpRemoteBuffer, &lvItem, sizeof(LVITEM), NULL );
// Send the message
::SendMessage( hwndListView, LVM_GETITEM, 0, (LPARAM)lpRemoteBuffer);
// Read the struct back from the remote process into local buffer
::ReadProcessMemory( hProcess, (LPVOID)lpRemoteBuffer, lpLocalBuffer, dwBufSize, NULL );
//Fix pszText to point to same offset in local buffer
lvItem.pszText = (LPTSTR)(lpLocalBuffer + sizeof( LVITEM ));
MessageBox(hwnd, lvItem.pszText, "", 0);
char txt[10];
ZeroMemory(txt, 10);
MessageBox(hwnd, itoa(lvItem.iImage, txt, 10), "", 0);
MessageBox(hwnd, itoa((int)lvItem.state, txt, 10), "", 0);
// Clean-up
::VirtualFreeEx( hProcess, (LPVOID)lpRemoteBuffer, 0, MEM_RELEASE );
::CloseHandle( hProcess );
You are allocating virtual memory for text. You must also allocate virtual memory for LVITEM. Then assign the text memory to lvItem.pszText, and then read both memory. It has to be compiled 64-bit for 64-bit systems. Add more error checks.
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ |
PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, FALSE, dwProcessID);
const DWORD dwBufSize = 1024;
void* pbuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);
void* pitem = VirtualAllocEx(hProcess, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);
LVITEM lvItem = { 0 };
lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.cchTextMax = MAX_PATH;
lvItem.pszText = (char*)pbuf;
WriteProcessMemory(hProcess, pitem, &lvItem, sizeof(LVITEM), NULL);
if (SendMessage(hwndListView, LVM_GETITEM, 0, (LPARAM)(LVITEM*)(pitem)))
{
char buf[dwBufSize];
if (ReadProcessMemory(hProcess, pbuf, buf, dwBufSize, 0))
{
OutputDebugString(buf);
OutputDebugString(", ");
if (ReadProcessMemory(hProcess, pitem, &lvItem, sizeof(LVITEM), 0))
{
_itoa_s(lvItem.iImage, buf, 10);
OutputDebugString(buf);
OutputDebugString("\n");
}
}
}
VirtualFreeEx(hProcess, pitem, 0, MEM_RELEASE);
VirtualFreeEx(hProcess, pbuf, 0, MEM_RELEASE);
CloseHandle(hProcess);

How to get services and characteristics from bluetooth LE device

I'm writing desktop app in Windows 8.1, and I need to get services from paired device using BluetoothGATTGetServices function. To make it I need to get handle to the device, that I've done and get handle using CreateFile function. But when I try to get service function return error: HRESULT_FROM_WIN32(ERROR_NOT_SUPORTED). Does anyone know how to fix it or tell what I'm doing wrong.
My device I'm trying to get services is iPhone 5s.
Here is code example:
HRESULT WinBluetoothDeviceProvider::GetBleHandle(OUT HANDLE* hBluetooth, WinBluetoothDevice* blDev)
{
GUID bthGuid;
CLSIDFromString(TEXT(BLE_INTERFACE_GUID), &bthGuid); // BLE_INTERFACE_GUID this is GUID of my Device Interface GUID
//#define BLE_INTERFACE_GUID "{00f40965-e89d-4487-9890-87c3abb211f4}"
HRESULT result = S_OK;
HDEVINFO hDevInfo;
SP_DEVINFO_DATA devInfoData;
HANDLE hBle;
hDevInfo = SetupDiGetClassDevs(&bthGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE)
return E_FAIL;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
SP_DEVICE_INTERFACE_DATA devInterfData = { 0 };
devInterfData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
DWORD DataT;
LPTSTR buffer = NULL;
DWORD buffersize = 0;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (DWORD i = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &bthGuid, i, &devInterfData); i++)
{
DWORD d = GetLastError();
DWORD size = 0;
if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterfData, NULL, 0, &size, 0))
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
{
result = S_OK;
break;
}
PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, size);
pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterfData, pInterfaceDetailData, size, &size, &devInfoData))
{
result = E_FAIL;
break;
}
hBle = CreateFile(pInterfaceDetailData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
USHORT serviceBuffActual;
PBTH_LE_GATT_SERVICE servicesBuff = new _BTH_LE_GATT_SERVICE;
HRESULT result = S_OK;
result = BluetoothGATTGetServices(hBle,
0, NULL, &serviceBuffActual, BLUETOOTH_GATT_FLAG_NONE);
// this function always retunr ERROR_NOT_SUPPORTED
LocalFree(pInterfaceDetailData);
}
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return result;
}
Try https://gist.github.com/programmarchy/c9d02e22d58bfab3f8bb#file-gistfile1-cpp-L110-L117, without FILE_ATTRIBUTE_NORMAL
hComm = CreateFile(
pInterfaceDetailData->DevicePath,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);

Using IOCTL_MOUNTMGR_QUERY_POINTS

I am not able to know how to use the IOCTL_MOUNTMGR_QUERY_POINTS .
I have searched the internet and found some sample code to try with.
but i am not sure whether its correct or not....
can you please let me know how to use the IOCTL_MOUNTMGR_QUERY_POINTS to get the drive letter
Thank you for your time
below is my source coode
HANDLE hUsbDevice = CreateFile( pDetData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
UCHAR Bytes[10000];
PMOUNTMGR_MOUNT_POINTS pMntPoints = (PMOUNTMGR_MOUNT_POINTS) Bytes;
MOUNTMGR_MOUNT_POINT mntPoint, *pmnt;
DWORD bytesReturned;
if (hUsbDevice == INVALID_HANDLE_VALUE) {
qDebug()<<"CreateFile failed with error: %d\n"<<GetLastError();
}
else {
qDebug ()<<"VALID DEVICE";
BOOL status = DeviceIoControl( hUsbDevice,
IOCTL_MOUNTMGR_QUERY_POINTS,
&mntPoint,
sizeof(MOUNTMGR_MOUNT_POINT),
pMntPoints,
10000,
&bytesReturned,
NULL);
wprintf(L"\tBOOL VALUE : %d\n", status);
qDebug ()<<pMntPoints->MountPoints;
}
OK! Here is a code example, but written without any error control to make it shorter:
#include <windows.h>
#include <C:\WinDDK\7600.16385.1\inc\ddk\mountmgr.h>
#include <tchar.h>
#include <stdio.h>
#pragma comment(lib, "Crypt32.lib")
int main()
{
TCHAR chDrive = 'N', szUniqueId[128];
TCHAR szDeviceName[7] = _T("\\\\.\\");
HANDLE hDevice, hMountMgr;
BYTE byBuffer[1024];
PMOUNTDEV_NAME pMountDevName;
DWORD cbBytesReturned, dwInBuffer, dwOutBuffer, ccb;
PMOUNTMGR_MOUNT_POINT pMountPoint;
BOOL bSuccess;
PBYTE pbyInBuffer, pbyOutBuffer;
LPTSTR pszLogicalDrives, pszDriveRoot;
// MOUNTMGR_DOS_DEVICE_NAME is defined as L"\\\\.\\MountPointManager"
hMountMgr = CreateFile (MOUNTMGR_DOS_DEVICE_NAME,
0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hMountMgr == INVALID_HANDLE_VALUE)
return 1;
cbBytesReturned = GetLogicalDriveStrings (0, NULL);
pszLogicalDrives = (LPTSTR) LocalAlloc (LMEM_ZEROINIT,
cbBytesReturned*sizeof(TCHAR));
cbBytesReturned = GetLogicalDriveStrings (cbBytesReturned,
pszLogicalDrives);
for (pszDriveRoot = pszLogicalDrives; *pszDriveRoot != TEXT('\0');
pszDriveRoot += lstrlen(pszDriveRoot) + 1) {
szDeviceName[4] = pszDriveRoot[0];
szDeviceName[5] = _T(':');
szDeviceName[6] = _T('\0');
//lstrcpy (&szDeviceName[4], TEXT("\\??\\USBSTOR\\DISK&VEN_SANDISK&PROD_CRUZER&REV_8.01\\1740030578903736&0"));
hDevice = CreateFile (szDeviceName, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
return 1;
bSuccess = DeviceIoControl (hDevice,
IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
NULL, 0,
(LPVOID)byBuffer, sizeof(byBuffer),
&cbBytesReturned,
(LPOVERLAPPED) NULL);
pMountDevName = (PMOUNTDEV_NAME) byBuffer;
_tprintf (TEXT("\n%.*ls\n"), pMountDevName->NameLength/sizeof(WCHAR),
pMountDevName->Name);
bSuccess = CloseHandle (hDevice);
dwInBuffer = pMountDevName->NameLength + sizeof(MOUNTMGR_MOUNT_POINT);
pbyInBuffer = (PBYTE) LocalAlloc (LMEM_ZEROINIT, dwInBuffer);
pMountPoint = (PMOUNTMGR_MOUNT_POINT) pbyInBuffer;
pMountPoint->DeviceNameLength = pMountDevName->NameLength;
pMountPoint->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
CopyMemory (pbyInBuffer + sizeof(MOUNTMGR_MOUNT_POINT),
pMountDevName->Name, pMountDevName->NameLength);
dwOutBuffer = 1024 + sizeof(MOUNTMGR_MOUNT_POINTS);
pbyOutBuffer = (PBYTE) LocalAlloc (LMEM_ZEROINIT, dwOutBuffer);
bSuccess = DeviceIoControl (hMountMgr,
IOCTL_MOUNTMGR_QUERY_POINTS,
pbyInBuffer, dwInBuffer,
(LPVOID)pbyOutBuffer, dwOutBuffer,
&cbBytesReturned,
(LPOVERLAPPED) NULL);
if (bSuccess) {
ULONG i;
PMOUNTMGR_MOUNT_POINTS pMountPoints = (PMOUNTMGR_MOUNT_POINTS) pbyOutBuffer;
for (i=0; i<pMountPoints->NumberOfMountPoints; i++) {
_tprintf (TEXT("#%i:\n"), i);
_tprintf (TEXT(" Device=%.*ls\n"),
pMountPoints->MountPoints[i].DeviceNameLength/sizeof(WCHAR),
pbyOutBuffer + pMountPoints->MountPoints[i].DeviceNameOffset);
_tprintf (TEXT(" SymbolicLink=%.*ls\n"),
pMountPoints->MountPoints[i].SymbolicLinkNameLength/sizeof(WCHAR),
pbyOutBuffer + pMountPoints->MountPoints[i].SymbolicLinkNameOffset);
ccb = sizeof(szUniqueId)/sizeof(szUniqueId[0]);
if (CryptBinaryToString (pbyOutBuffer + pMountPoints->MountPoints[i].UniqueIdOffset,
pMountPoints->MountPoints[i].UniqueIdLength,
CRYPT_STRING_BASE64,
szUniqueId, &ccb))
_tprintf (TEXT(" UniqueId=%s\n"), szUniqueId);
else
_tprintf (TEXT(" UniqueId=%.*ls\n"),
pMountPoints->MountPoints[i].UniqueIdLength/sizeof(WCHAR),
pbyOutBuffer + pMountPoints->MountPoints[i].UniqueIdOffset);
}
}
pbyInBuffer = (PBYTE) LocalFree (pbyInBuffer);
pbyOutBuffer = (PBYTE) LocalFree (pbyOutBuffer);
}
pszLogicalDrives = (LPTSTR) LocalFree (pszLogicalDrives);
bSuccess = CloseHandle (hMountMgr);
return 0;
}
if produce on my computer the output like
\Device\HarddiskVolume3
#0:
Device=\Device\HarddiskVolume3
SymbolicLink=\DosDevices\C:
UniqueId=O5TWlQAAwBRIAAAA
#1:
Device=\Device\HarddiskVolume3
SymbolicLink=\??\Volume{12703dc4-bf56-11db-8c6c-806e6f6e6963}
UniqueId=O5TWlQAAwBRIAAAA
...
\Device\CdRom2
#0:
Device=\Device\CdRom2
SymbolicLink=\DosDevices\L:
UniqueId=\??\USBSTOR#CdRom&Ven_HL-DT-ST&Prod_DVDRAM_GE20LU11&Rev_CL01#0010101640008B615&0#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}
#1:
Device=\Device\CdRom2
SymbolicLink=\??\Volume{2c5f6a93-2b50-11df-aa6a-005056c00008}
UniqueId=\??\USBSTOR#CdRom&Ven_HL-DT-ST&Prod_DVDRAM_GE20LU11&Rev_CL01#0010101640008B615&0#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}
\Device\HarddiskVolume8
#0:
Device=\Device\HarddiskVolume8
SymbolicLink=\DosDevices\N:
UniqueId=_??_USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer&Rev_8.01#1740030578903736&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
#1:
Device=\Device\HarddiskVolume8
SymbolicLink=\??\Volume{ae08a3c8-71cf-11de-bc1d-005056c00008}
UniqueId=_??_USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer&Rev_8.01#1740030578903736&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}