Shared memory - matrix mapping - c++

I'm currently working on a Bomberman game project where there should be a Server, which has a bidimensional matrix, and 1 or more Clients.
The way that I think it should be done is by using shared memory between process, where the clients and "enemies" access to get the information about the Table Map(Matrix) and work with that.
The problem is that I don't know how to map a pointer to my Map object(Matrix) so the other processes can grab that information.
I've got this function from MSDN but I only explain to a string:
//Server.cpp
//object creation (Matrix)
Mapa M(height, width);
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size(high-order DWORD)
BUF_SIZE, // maximum object size (low-order DWORD)
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
**HANDLE hMapFile = &M; // will this work?**
pBuf = (LPTSTR) MapViewOfFile(hMapFile, // <- How can I pass the object here?
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
Please how can I map a pointer to an object or even to an object so the other processes can access?
Regards,
RC

To use a mapping file your server code should look something like the following. Note that I do not check for any errors to keep the posted code simple (always check for errors!).
/* server */
HANDLE hFile;
HANDLE hMapFile;
hFile = CreateFile("test.dat",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
hMapFile = CreateFileMapping(hFile,
NULL,
PAGE_READWRITE,
0,
1024 * 1024,
"test.mapping"); // "mapping file name" of "test.dat"
/* keep server process running and do not close hFile or hMapFile */
And your client should look something like this:
/* client */
HANDLE hMapFile;
char *pFile; // note: you can use any type of pointer here!
hMapFile = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,
FALSE,
"test.mapping"); // same name as within CreateFileMapping(..)
if (hMapFile != NULL)
{
pFile = MapViewOfFile(hMapFile,
FILE_MAP_ALL_ACCESS,
0,
0,
1024 * 1024);
/* read pFile */
printf(pFile);
/* write pFile */
wsprintf(pFile, "Hallo?"); // <-- writes to test.dat!!
}
As noted before this design will have some drawbacks if used for a server/client architecture. I recommend using a TCP/IP server/client which is no more difficult to implement than named pipes. A good place to start would be Running the Winsock Client and Server Code Sample but there are numerous other examples on the web...
If using TCP/IP your application will look something like this:
/* server */
// create listener socket
// while running
// accept new client(s)
// receive data from clients (if any data was received)
// react on data: (client sent 0x01 -> send matrix, ...)
/* client */
// create socket and connect to server
// send 0x01 command to obtain matrix
// receive response from server (= get matrix)
// do whatever your client does...
Note that the 0x01 is a simple command byte to tell the server what to do. You're completely free on how to tell the server what to do. You can as well implement a string based command interface (e.g. client sends "get_matrix" instead of 0x01)...

Related

windows ReadFile() doesn't return when reading data from a HID device

I'm trying to write a program that sends and receives data from a HID device. The device employs ASTM protocol for communication. I'm using hidsdi.h library for communicating with the device. So far I have been able to get a handle on the device. I'm now attempting to send a message to the device so that it sends a response in return.
My Code:
HANDLE hDevice = CreateFile(devicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
// error…
}
char DataBuffer[] = "X";
DWORD dwBytesToWrite = (DWORD)strlen(DataBuffer);
DWORD dwBytesWritten = 0;
BOOL bErrorFlag = FALSE;
uint8_t * pTmpBuf = (uint8_t *)calloc(inputReportLength, sizeof(uint8_t));
uint8_t * pAppBuffer = (uint8_t *)calloc(inputReportLength, sizeof(uint8_t));
DWORD nRead;
if (pTmpBuf == NULL)
{
//return error(“memory allocation failed”);
}
try{
if (pTmpBuf == NULL)
{
;// memory allocation error…
}
//
// copy data to be sent, reserving the 1st byte for report ID
//
memcpy(pTmpBuf + 1, DataBuffer, sizeof(DataBuffer));
bErrorFlag = WriteFile(hDevice, pTmpBuf, dwBytesToWrite, &dwBytesWritten, NULL);
free(pTmpBuf);
pTmpBuf = (uint8_t *)calloc(inputReportLength, sizeof(uint8_t));
if (!bErrorFlag)
{
bErrorFlag = ReadFile(hDevice, pTmpBuf, inputReportLength, &nRead, NULL);
DWORD dwError = GetLastError();
if (!bErrorFlag)
{
memcpy(pAppBuffer, pTmpBuf + 1, nRead - 1);
free(pTmpBuf);
}
}
CloseHandle(hDevice);
hDevice = INVALID_HANDLE_VALUE;
It seems that WriteFile functions successfully sends data to device however when the compiler tries to execute the ReadFile() function, the control is never returned and the execution just hangs. I haven't implemented any timeout function, I figured there would be a timeout by default but the compiler never gets to execute the next line after ReadFile.
I'm new to the ASTM communication protocol and there's loads of things I'm still trying to understand and wrap my hand around.
According to the documentation I have, the structure of the frame looks this:
<STX> FN text <ETB> C1 C2 <CR> <LF>
where each field has a certain ASCII value. Do I need to encode my message in that fashion when I'm sending data or sending char representation of the message is enough? like I have done in the code.
According to the doc, I need to do the following to get a response from the device:
1) Send “X” to the meter.
2) Meter responds with <EOT> HEADER <ENQ> within 2 seconds.
3) Send <NAK> to reject data transfer
4) Meter responds with <EOT> to indicate it is exiting the transfer phase.
5) Send <ENQ> to the meter to initiate sending remote commands.
6) Meter responds with <ACK> to indicate it is ready to receive remote commands.
7) Send remote commands.
Send <EOT> to the meter to indicate remote commands are complete.
I'd really appreciate someone helping me out.
The software guide for the device can be found here

Which ReadFile parameter in this code is incorrect? (Error code 87)

(Edit: I didn't exclude any code except the headers and the main() function's brackets. Nothing is written between lines of code listed here.)
.
I used the ReadFile function to read this COM3 port (which returned no INVALID_HANDLE_VALUE or ERROR_FILE_NOT_FOUND):
LPCTSTR portName = "COM3" ;
HANDLE hSerial;
hSerial = CreateFile(portName,
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // default security attributes
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
And the ReadFile function in question uses following parameters:
DWORD n = 512 ;
char szBuff[n] = {0};
DWORD dwBytesRead = 0;
if(!ReadFile(hSerial, szBuff, n, &dwBytesRead, NULL))
{
cout << "ReadFile error. Error code: " << GetLastError() << endl ;
cin.get() ;
return 0 ;
}
What changes should I introduce to cause the read to succeed?
(I searched through the function's documentation and other StackOverflow questions, tested lots of things, but couldn't find an answer.)
In ReadFile documentation you can read:
lpOverlapped [in, out, optional]
A pointer to an OVERLAPPED structure is required if the hFile parameter was opened with FILE_FLAG_OVERLAPPED, otherwise it can be NULL.
so since you specified FILE_FLAG_OVERLAPPED in CreateFile you should provide OVERLAPPED in ReadFile.
In CreateFile you can read on parameters for Communications Resources:
... and the handle can be opened for overlapped I/O.
so you can skip FILE_FLAG_OVERLAPPED in CreateFile
Marcin Jędrzejewski's answer is correct about the mismatch between the overlapped IO Flag and the ReadFile function, but I will leave this up just to be helpful.
You are missing a lot of initialisation which may be helpful to you when operating a COM port.
This code is used to open, configure, and read from a COM port on windows using C++.
FOR REFERENCE
READ_BUFFER_SIZE = 1024;
WRITE_BUFFER_SIZE = 1024;
COM_READ_BUFFER_SIZE = 1024;
COM_WRITE_BUFFER_SIZE = 1024;
READ_TIMEOUT = 50;
WRITE_TIMEOUT = 100;
port = "\\.\COM6"
portFormat = "9600,N,8,1" /* for information on this, google the MODE command for windows. */
HANDLE hComPort;
DCB dcbComConfig;
OPENING COM PORT
DWORD dwStoredFlags = EV_BREAK | EV_ERR | EV_RXCHAR;
COMMTIMEOUTS timeouts;
FillMemory(&dcbComConfig, sizeof(dcbComConfig), 0);
dcbComConfig.DCBlength = sizeof(dcbComConfig);
/* assign a COM format to the COM Port. */
if(!BuildCommDCB(portFormat, &dcbComConfig))
{
printf("Failed to build comm format data %s\n", portFormat);
}
/* Open the COM port with overlapped IO. */
hComPort = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, 0,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if (hComPort == INVALID_HANDLE_VALUE)
{
printf("Error opening port %s\n", port);
}
/* Set the COM Ports internal Read and Write buffer sizes. */
if(!SetupComm(hComPort, COM_READ_BUFFER_SIZE, COM_WRITE_BUFFER_SIZE))
{
printf("Could not set COM buffers\n");
}
/* assign the previously created COM Format to the COM Port. */
if(!SetCommState(hComPort, &dcbComConfig))
{
printf("Error setting com to format data.\n");
}
/* Mask what events you want to look for in the COM Port. */
if (!SetCommMask(hComPort, dwStoredFlags))
{
printf("Error setting communications mask\n");
}
/*-- Read Timeouts set like this so we can use the event based reading. --*/
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 100;
if (!SetCommTimeouts(hComPort, &timeouts))
{
printf("Error setting time-outs.\n");
}
READING COM PORT
DWORD dwRead = 0;
DWORD dwComEvent = EV_RXCHAR;
DWORD lpErrors = 0;
char readBuffer[READ_BUFFER_SIZE];
/* Create the Overlapped IO Read Event. */
OVERLAPPED osRead = {0};
osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
/* Used to monitor the COM Port State. */
COMSTAT ComStatus;
/* Loop at 20Hz to read the COM Port until a Kill event has been set. */
while(WaitForSingleObject(hKillEvent, 50) == WAIT_TIMEOUT)
{
/* Wait for a COM Event to occur ( Read Event in this Case ). */
if (WaitCommEvent(hComPort, &dwComEvent , NULL))
{
/* If the COM Port had an error Clear it. */
ClearCommError(hComPort, &lpErrors, &ComStatus);
/*-- Reset read operation's OVERLAPPED structure's hEvent --*/
ResetEvent(osRead.hEvent);
if (ReadFile(hComPort, readBuffer, ComStatus.cbInQue, &dwRead, &osRead))
{
/*-- bytes have been read; process it --*/
USE_DATA(readBuffer, dwRead);
}
else
{
/*-- An error occurred in the ReadFile call --*/
printf("ReadFile encountered an error.\n");
break;
}
}
else
{
/*-- Error in WaitCommEvent --*/
printf("WaitCommEvent encountered an error.\n");
break;
}
}
/* Close the Overlapped IO Read Event. */
CloseHandle(osRead.hEvent);
The top answer is correct. In this case, opening with FILE_FLAG_OVERLAPPED, ReadFile expects an OVERLAPPED structure as last argument.
Would like to add that you can also get 'parameter is incorrect' error if you do supply an OVERLAPPED struct, but forget to ZeroMemory it.
From the documentation:
Any unused members of this structure should always be initialized to zero before the structure is used in a function call. Otherwise, the function may fail and return ERROR_INVALID_PARAMETER.
So don't forget to:
OVERLAPPED ovl;
ZeroMemory(&ovl, sizeof(ovl));
...
ReadFile(hSerial, szBuff, n, &dwBytesRead, &ovl);

Fastest way to write raw data to hard drive (PhysicalDrive) on Windows 7

My company is developing a "fancy" USB Mass Storage Device running under Windows 7. The Mass Storage Client Driver that handles the reading and writing to the actual storage media on the client side is being written in C++. The problem we are having is very, very slow write speeds. About 30 times slower than expected. We are using calls to WriteFile() to write blocks of data to the storage media (specifically the physical drive 'PhysicalDrive2') as they are received from the Host device. I have read in many other forums that people have experience very slow write speeds using WriteFile() especially on Windows 7. So I am trying to figure out if I am using the best method and function calls for this particular task.
Below are two blocks of code. One for LockVolume() function that gets called one time by the program during initialization and actually just unmounts the volume. The other block of code is WriteSector() which is used to write the actual data to the physical drive when its received by the USB Client controller driver. I am hoping that someone can shed some light on what I might be doing wrong or provided suggestions on a better way to implement this.
short WriteSector
(LPCWSTR _dsk, // disk to access
char *&_buff, // buffer containing data to be stored
unsigned int _nsect, // sector number, starting with 0
ULONG Blocks
)
{
DWORD bytesWritten;
wchar_t errMsg[256];
//attempt to get a handle to the specified volume or physical drive
HANDLE hDisk = CreateFile(_dsk, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
//make sure we have a handle to the specified volume or physical drive
if(hDisk==INVALID_HANDLE_VALUE)
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
OutputDebugString(errMsg);
printf("Error attempting to get a handle to the device! (%s)\n", errMsg);
goto exit;
}
// set pointer to the sector on the disk that we want to write to
SetFilePointer(hDisk, (_nsect * SIZE_OF_BLOCK), 0, FILE_BEGIN);
//write the data
if (!WriteFile(hDisk, _buff, (Blocks * SIZE_OF_BLOCK), &bytesWritten, NULL))
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
printf("WriteFile failed! (%s)\n", errMsg);
goto exit;
}
exit:
CloseHandle(hDisk);
writeMutex.unlock();
return 0;
}
UINT Disk_LockVolume(LPCWSTR _dsk)
{
HANDLE hVol;
LPWSTR errMsg;
DWORD status;
bool success = false;
//now try to get a handle to the specified volume so we can write to it
hVol = CreateFile(_dsk, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
//check to see if we were able to obtain a handle to the volume
if( hVol == INVALID_HANDLE_VALUE )
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
printf("Disk_LockVolume() - CreateFile failed (%s)\n", errMsg);
goto exit;
}
// now lock volume
if (!DeviceIoControl(hVol, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &status, NULL))
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
printf("Disk_LockVolume() - Error attempting to lock device! (%s)\n", errMsg);
goto exit;
}
//dismount the device
if (!DeviceIoControl(hVol, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &status, NULL))
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
printf("Disk_LockVolume() - Error attempting to dismount volume. (%s)\n", errMsg);
goto exit;
}
exit:
CloseHandle(hVol);
return 1;
}
EDIT #1 (2/10/2015)
So I incorporated the suggestions made by Ben Voigt and found that calling CreateFile and CloseHandle only once (instead of every time we want to write data to the drive) significantly improved write speed. 80% increase. Even with that increase, the write speed was still much slower than expected. Around 6 times slower. So I then incorporated his other suggested change which included eliminating the original call to SetFilePointer() and replace it with and OVERLAPPED structure that now gets passed to WriteFile. After I made that change, I now get and error that states "stack around the variable 'MyOverLappedStructure' was corrupted". Below is the updated version of my SectorWrite function along with the new Disk_GetHandle() function which gets the initial handle to the Physical Drive. Also, I am still calling Disk_LockVolume(), one time, after I call Disk_GetHandle(). However, I have modified the Disk_LockVolume() function so that the handle to the volume (in this case) does not get closed at the end of the function. Ultimately that would be closed at the end of the program, prior to closing the handle on the Physical Drive. Any thoughts on this new error would be greatly appreciated. Oh, the FILE_FLAG_NO_BUFFERING had no impact on performance that I could see.
UINT WriteSector(HANDLE hWriteDisk, PBYTE Buf, ULONG Lba, ULONG Blocks)
{
DWORD bytesWritten;
LPTSTR errMsg = "";
//setup overlapped structure to tell WriteFile function where to write the data
OVERLAPPED overlapped_structure;
memset(&overlapped_structure, 0, (Blocks * SIZE_OF_BLOCK));
overlapped_structure.Offset = (Lba * SIZE_OF_BLOCK);
overlapped_structure.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
//write the data
if (!WriteFile(hWriteDisk, Buf, (Blocks * SIZE_OF_BLOCK), &bytesWritten, &overlapped_structure))
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
printf("WriteSector() - WriteFile failed (%s)\n", errMsg);
}
if (bytesWritten != (Blocks * SIZE_OF_BLOCK))
{
printf("WriteSector() - Bytes written did not equal the number of bytes to be written\n");
return 0;
}
else
{
return Blocks;
}
}
HANDLE Disk_GetHandle(UINT Lun)
{
HANDLE hVol;
LPTSTR errMsg = "";
bool success = false;
//now try to get a handle to the specified volume so we can write to it
hVol = CreateFile(MassStorageDisk[Lun].PhysicalDisk, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED|FILE_FLAG_NO_BUFFERING, 0);
//check to see if we were able to obtain a handle to the volume
if( hVol == INVALID_HANDLE_VALUE )
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
printf("Disk_WriteData() - CreateFile failed (%s)\n", errMsg);
}
return hVol;
}
EDIT #2 (2/10/2015)
So I eliminated the FILE_FLAG_OVERLAPPED from CreateFile() call per Ben's comment. I also modified part of the WriteSector() function to include a check to see if IO is pending after call to WriteFile(). If so, I call WaitForSingleObject() which waits indefinitely until the IO operation is complete. Lastly, I call CloseHandle() on the OVERLAPPED structure hEvent. Even with these changes I still get the error "stack around the variable 'osWrite' was corrupted", where osWrite is the OVERLAPPED structure. Below is a code snippet illustrating the changes.
OVERLAPPED osWrite;
memset(&osWrite, 0, (Blocks * SIZE_OF_BLOCK));
osWrite.Offset = (Lba * SIZE_OF_BLOCK);
osWrite.hEvent = 0;
//write the data
if (!WriteFile(hWriteDisk, Buf, (Blocks * SIZE_OF_BLOCK), &bytesWritten, &osWrite))
{
DWORD Errorcode = GetLastError();
if (Errorcode == ERROR_IO_PENDING)
{
WaitForSingleObject(osWrite.hEvent, INFINITE);
}
else
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
printf("WriteSector() - WriteFile failed (%s)\n", errMsg);
goto exit;
}
}
EDIT #3 (2/10/2015)
So the code is now working with Ben's inputs. The code above has been modified to reflect those changes. I need to mention that up until this afternoon, all of my testing was done where the storage media on the client side was a USB flash drive. I have since changed that so the client now writes to an attached SSD. With the USB flash drive setup, the speed at which I can write data to the client over the USB connection is virtually identical now to the speed at which the client SBC can transfer the same file directly from itself to the storage media (without the host connected). However, with the SSD now being used, this is not the case. The test file I am using which is 34MB takes 2.5 seconds when transferred directly from the client SBC to the SSD. It takes 2.5 MINUTES from host to client over the USB. Other than changing the volume letter and physical drive number, no other changes were made to the code
You should not call CreateFile and CloseHandle for each sector overwritten. CreateFile is a very expensive operation that has to do security checks (evaluate group membership, walk SIDs, etc).
Open the handle once, pass it to WriteFile many times, and close it once. This means changing your _dsk parameter from a volume path to a HANDLE.
You probably also want to lose the call to SetFilePointer, and use an OVERLAPPED structure instead, which lets you supply the position to write to as part of the write call. (The operation won't be overlapped unless you use FILE_FLAG_OVERLAPPED, but non-overlapped I/O respects the position information in the OVERLAPPED structure).

How to connect to the bluetooth low energy device

I am writing program for Win 8 tablet. I need to connect an external BLE device.
The device is already paired with Windows and I can see it in Device Manager. But I can not figure out how to connect it.
With SetupDiEnumDeviceInfo and SetupDiGetDeviceProperty I can get some information about the BLE-device, but to perform, e.g. BluetoothGATTGetServices
Handle device requires. I do not know where to take it. Perhaps i can use CreateFile, but it is not clear that the substitute as the first argument lpFileName.
Here's a piece of code with which I'm looking for my device.
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DeviceInfoData;
DWORD i;
// Create a HDEVINFO with all present devices.
hDevInfo = SetupDiGetClassDevs(
&BluetoothClassGUID, /* GUID_DEVCLASS_BLUETOOTH */
0, 0, DIGCF_PRESENT);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
// Insert error handling here.
return ;//1;
}
// Enumerate through all devices in Set.
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (i=0;SetupDiEnumDeviceInfo(hDevInfo,i,
&DeviceInfoData);i++)
{
DWORD DataT;
LPTSTR buffer = NULL;
DWORD buffersize = 0;
while (!SetupDiGetDeviceRegistryProperty(
hDevInfo,
&DeviceInfoData,
SPDRP_FRIENDLYNAME,
&DataT,
(PBYTE)buffer,
buffersize,
&buffersize))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER){
// Change the buffer size.
if (buffer) delete(buffer);
// Double the size to avoid problems on
// W2k MBCS systems per KB 888609.
buffer = new wchar_t[buffersize * 2];
}else{
// Insert error handling here.
break;
}
}
/* Here i just compare by name is this my device or not */
...
/* Here i just compare by name is this my device or not */
if (buffer) delete(buffer);
}
if ( GetLastError()!=NO_ERROR &&
GetLastError()!=ERROR_NO_MORE_ITEMS )
{
// Insert error handling here.
return; //1;
}
// Cleanup
SetupDiDestroyDeviceInfoList(hDevInfo);
return;// 0;
I moved a little further, but still i can't get the data from device.
To obtain "Device Interface Path" had to use the other functions:
SetupDiGetClassDevs, SetupDiEnumDeviceInterfaces and SetupDiGetDeviceInterfaceDetail.
Next, with CreateFile I get HANDLE BLE-device.
hComm = CreateFile(pInterfaceDetailData->DevicePath, GENERIC_WRITE | GENERIC_READ,NULL,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL);
Next using WinAPI BluetoothGATTGetServices and BluetoothGATTGetCharacteristics I get the appropriate structures.
But when trying to get the property value with BluetoothGATTGetCharacteristicsValue, I get ERROR_ACCESS_DENIED.
And then I do not know what to do. What could be wrong?
Andrey, I think the problem is that your device is not connected and BluetoothGATTGetCharacteristicsValue is not triggering a connection.
Try manually to connect your device using Windows tools. I've the following flow that helps me: Unpair device, Pair device -> It should appear as connected ( it worked in my case ;) )
Anyway, If this is not helping, try to run "As Administrator", this helps in some cases.
Good luck!!!
Note: Would be very interested to know how to retrievethe device path for the BTLE device in order to call BluetoothGATTGetServices?
gattServiceGUID is any long form BLE UUID supported by your device.
"{00001803-0000-1000-8000-00805F9B34FB"} can be used to open a handle to the Link Loss service if supported by the device you are trying to open
HDEVINFO hDevInfo = SetupDiGetClassDevs(&gattServiceGUID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo != INVALID_HANDLE_VALUE)
{
SP_DEVICE_INTERFACE_DATA interfaceData;
ZeroMemory(&interfaceData,sizeof(SP_DEVICE_INTERFACE_DATA));
interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
for (DWORD dwDeviceIndex = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &gattServiceGUID, dwDeviceIndex, &interfaceData); dwDeviceIndex++)
{
dwDeviceCount++;
SetupDiGetDeviceInterfaceDetail(hDevInfo, &interfaceData, NULL, 0, &dwBytesNeeded, NULL);
if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
pInterfaceDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA) new byte[dwBytesNeeded];
SP_DEVINFO_DATA spDeviceInfoData = { sizeof(SP_DEVINFO_DATA) };
ZeroMemory(pInterfaceDetail, sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA));
pInterfaceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
// grab the interface detail
if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &interfaceData, pInterfaceDetail, dwBytesNeeded, NULL, &spDeviceInfoData) == TRUE)
{
// request a handle to the GATT service path
m_hGattServiceHandle = CreateFile(pInterfaceDetail->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (m_hGattServiceHandle != INVALID_HANDLE_VALUE)
{
now you can drill down the characteristics and descriptors with the m_hGattServiceHandle
}
}
}
}
}

getting error code 998 Invalid access to memory location when trying to read from named pipe

I created a named pipe using WCF and C#, and a client to connect to it so that I know that it is working correctly. Now I'm trying to create a c++ client. So far I have been able to get the name of the pipe, connect to it, and write some data to it. When I try to read from it I'm getting error code 998 Invalid access to memory location. Here is the code I'm using:
HANDLE hPipe = CreateFile(pipeName.c_str(), GENERIC_WRITE | GENERIC_READ, 2, NULL, OPEN_EXISTING, NULL, NULL);
BOOL bWrite = WriteFile(hPipe, &message, size, &bytesWritten, NULL);
LPVOID buffer = 0;
DWORD bytesRead;
BOOL bRead = ReadFile(hPipe, buffer, 10, &bytesRead, NULL);
I'm not sure what I'm doing wrong.
No memory has been allocated for buffer, it is currently a null pointer, and the code is requesting that 10 bytes of data be read into an array that does not exist. From ReadFile():
lpBuffer [out]
A pointer to the buffer that receives the data read from a file or device.
To rectify:
char buffer[10];