Christopher Schene
asked on
C++ BOOL WINAPI ReadFile fails on windows 10 when reading from USB cable
Hi,
I am using the ReadFile WINAPI function to read from a USB port using the USBSER.SYS driver.
The USBSER.SYS driver allows me to read and write to the USB port as it it were a file on disk. So I open the serial port with a "CreateFile" call as I would create a physical file on disk.
I am, of course, reading and writing to a device and not a real file.
I write to the file with the WriteFile call and read from the file with a ReadFile call.
My problem is that the ReadFile call works on xp, win7, win 8, win 8.1 but not Windows 10.
Any ideas? Do you see or can you take a guess at any reason why my ReadABuffer method might not work on windows 10? WriteFile works just fine, by the way on Windows 10. I am, by the way, verifying using a USB reader and debugging tool that the traffic I am supposed to be reading is actually being sent from the device and is visible in the USB trace.
This is old MFC code that was originally developed in Visual Studio 6 (prior to .NET 2001!) and has been upgraded to VS2012. I was written in 2001 (15 years ago!).
This was probably written when some of you were in Kindergarten! :-) This is a hard question and I wish I could award more points.
I am using the ReadFile WINAPI function to read from a USB port using the USBSER.SYS driver.
The USBSER.SYS driver allows me to read and write to the USB port as it it were a file on disk. So I open the serial port with a "CreateFile" call as I would create a physical file on disk.
I am, of course, reading and writing to a device and not a real file.
I write to the file with the WriteFile call and read from the file with a ReadFile call.
My problem is that the ReadFile call works on xp, win7, win 8, win 8.1 but not Windows 10.
Any ideas? Do you see or can you take a guess at any reason why my ReadABuffer method might not work on windows 10? WriteFile works just fine, by the way on Windows 10. I am, by the way, verifying using a USB reader and debugging tool that the traffic I am supposed to be reading is actually being sent from the device and is visible in the USB trace.
This is old MFC code that was originally developed in Visual Studio 6 (prior to .NET 2001!) and has been upgraded to VS2012. I was written in 2001 (15 years ago!).
This was probably written when some of you were in Kindergarten! :-) This is a hard question and I wish I could award more points.
BOOL IODev::ReadABuffer(HANDLE f1HCA,
char *lpBuf,
DWORD bytesToRead,
DWORD *bytesRead,
bool immediate)
{
DWORD dwRead;
lpBuf[0] = '\0';
OVERLAPPED overLap;
DWORD Internal;
DWORD InternalHigh;
int i;
DWORD count = 0;
OVERLAPPED osReader = {0};
int attempts;
bool handleOpen = false;
//Sleep(500);
if(!useAsyncIO){
ReadFile(f1HCA,lpBuf,bytesToRead,bytesRead,NULL);
}else{
strcpy(lpBuf,"XXXXX");
if(immediate){
attempts = 1;
}else{
attempts = 15;
}
// Read stuff until there is no more stuff.
// Note: 15 gives 1.2 seconds total sleep time, i.e., we
// give up after 1.2 seconds if we have not heard from the ABK.
// Test show that 450 milliseconds is not quite long enough for a
// board with daughter card. Almost but not quite...
for(i = 0; i<attempts; i++){ //15 gives 1.05 seconds total sleep time
//while(true){
// Create the overlapped event. Must be closed before exiting
// to avoid a handle leak.
overLap.Internal = (DWORD)&Internal;
overLap.InternalHigh = (DWORD)&InternalHigh;
overLap.Offset = (DWORD) 0;
overLap.OffsetHigh = (DWORD) 0;
osReader.hEvent = CreateEvent(NULL, true, false, NULL);
if (osReader.hEvent == NULL){
return false;
}
handleOpen = true;
overLap.hEvent = osReader.hEvent;
char *bufPtr = &lpBuf[count];
if (ReadFile(f1HCA, bufPtr, bytesToRead, &dwRead, &overLap)) {
//if (ReadFile(f1HCA, &lpBuf[count], 1, &dwRead, &overLap)) {
// read completes immediately due to ReadIntervalTimeOut set to MAXDWORD
count += dwRead;
if(count){
//The board transmits NULL-terminated strings...
if(count >= bytesToRead || lpBuf[count-1] == '\0'){
break;
}
}
}else{
}
if(bytesToRead == 1 && lpBuf[0] != 'X'){
dwRead++;
count = dwRead;
break;
}
//Progressive sleeps to provide just enough time hopefully...
if(handleOpen){
//make sure there is a close for every open
CloseHandle(osReader.hEvent);
handleOpen = false;
}
Sleep(10*i);
} //end for
if(handleOpen){
//make sure there is a close for every open
CloseHandle(osReader.hEvent);
handleOpen = false;
}
*bytesRead = count;
} //end asynchronous IO
return true;
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Still investigating. I am getting in touch with the device manufacturer to see if they have created a version of their .idf file for windows 10.
ASKER
NO, the question is not neglected. This process is just complicated.
ASKER
I assure you Sara and moderators and admins: I have not abandoned this question. It is just a very complex problem.
Sara: We are thinking this may have something to do with a USB "Get String Descriptor" that we see more of in Windows 10 than we do win XP, Win7, Win 8, win 8.1
does thing ring a bell?
I know the driver changed (usnser.sys) so I am wondering if the protocol changed a bit and it is confusing the device.
Sara: We are thinking this may have something to do with a USB "Get String Descriptor" that we see more of in Windows 10 than we do win XP, Win7, Win 8, win 8.1
does thing ring a bell?
I know the driver changed (usnser.sys) so I am wondering if the protocol changed a bit and it is confusing the device.
ASKER
Oh, one other item: I used this command to clear the last error so I am not looking at a left over error
SetLastError(0);
And then I used the code below to convert the last error to a string.
I still see the same error all the time as the last error "can't create a file when that file already exists" every time.
//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
std::string GetLastErrorAsString()
{
//Get the error message, if any.
DWORD errorMessageID = ::GetLastError();
if(errorMessageID == 0)
return std::string(); //No error message has been recorded
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(FORMAT_MESS AGE_ALLOCA TE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSE RTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
std::string message(messageBuffer, size);
//Free the buffer.
LocalFree(messageBuffer);
return message;
}
SetLastError(0);
And then I used the code below to convert the last error to a string.
I still see the same error all the time as the last error "can't create a file when that file already exists" every time.
//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
std::string GetLastErrorAsString()
{
//Get the error message, if any.
DWORD errorMessageID = ::GetLastError();
if(errorMessageID == 0)
return std::string(); //No error message has been recorded
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(FORMAT_MESS
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
std::string message(messageBuffer, size);
//Free the buffer.
LocalFree(messageBuffer);
return message;
}
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
It turns out that the error I was seeing was actually a red herring. I had some debugging stubs that were appending to a file and that is where the ""can't create a file when that file already exists" error was from.
I am going to try a different approach: we wrote a small console application that is based on VS2005 and that works with the USB interface on win10. As an experiment, I am going to replace the path I am having issues with in the app with the code form the console app and see what happens. Since the app I am debugging has been upgraded to VS2012 if the code from the console app works it is probably a bug in the application. If it does not work, my theory is that the problem is the VS2012 winapi libraries included with VS2012.
Chris
I am going to try a different approach: we wrote a small console application that is based on VS2005 and that works with the USB interface on win10. As an experiment, I am going to replace the path I am having issues with in the app with the code form the console app and see what happens. Since the app I am debugging has been upgraded to VS2012 if the code from the console app works it is probably a bug in the application. If it does not work, my theory is that the problem is the VS2012 winapi libraries included with VS2012.
Chris
ASKER
Hi Sara,
I determined that there is an incompatibility between the winio library I am compiling my application with in vs2012. If I compile the code in vs2005 it works fine.
I determined that there is an incompatibility between the winio library I am compiling my application with in vs2012. If I compile the code in vs2005 it works fine.
ASKER
I can write to the USB port successfully so I am fairly sure the driver is loaded. However, I am not using the usbser.inf. Rather, this is an embedded device and the software is issued by the embedded device manufacturer and I am using their .inf file.
I don't think there is an error---I am just timing out.
I'll dig deeper.
Thanks Sara.