Link to home
Start Free TrialLog in
Avatar of Christopher Schene
Christopher ScheneFlag for United States of America

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.

 


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;
    }

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of sarabande
sarabande
Flag of Luxembourg image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Christopher Schene

ASKER

"that might require a slightly different handling in order to get the new driver loaded (and used) for the device. you may check the Windows 10 section of the above MSDN link."

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.
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.
NO, the question is not neglected. This process is just complicated.
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.
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_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                                 NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);

    std::string message(messageBuffer, size);

    //Free the buffer.
    LocalFree(messageBuffer);

    return message;
}
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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
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.