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

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

ReadFile fails with 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  Thanks for reply. I got the solution. The problem was my pen drive had 2048 bytes per sector and so ReadFile() failed as number of bytes to read was not sector aligned.

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++.


port = "\\.\COM6"
portFormat = "9600,N,8,1" /* for information on this, google the MODE command for windows. */

HANDLE hComPort;
DCB dcbComConfig;

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, 

    printf("Error opening port %s\n", port);

/* Set the COM Ports internal Read and Write buffer sizes. */
    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");
DWORD dwRead = 0;
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 --*/

        if (ReadFile(hComPort, readBuffer, ComStatus.cbInQue, &dwRead, &osRead))
            /*-- bytes have been read; process it --*/
            USE_DATA(readBuffer, dwRead);
            /*-- An error occurred in the ReadFile call --*/
            printf("ReadFile encountered an error.\n");
        /*-- Error in WaitCommEvent --*/
        printf("WaitCommEvent encountered an error.\n");

/* Close the Overlapped IO Read Event. */

why readfile error code 87 ??, to begin of drive and call ReadFile() to read 512 bytes. ReadFile() fails with error code 87. (The parameter is incorrect). Code: -------------------- (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

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:

ZeroMemory(&ovl, sizeof(ovl));
ReadFile(hSerial, szBuff, n, &dwBytesRead, &ovl);

[Solved] WriteFile Failure with error code 87 in 4096 Bytes per sector , What is the value of the diskletter variable you are passing as the first parameter to CreateFile? 3. Please, always use the Code tags while posting  Can you try disabling that and/or excluding the Reflect EXEs under C:\Program Files\Macrium and its subfolders from BitDefender intervention?

CSerialException for error 87 - wrong parameter - MSDN, Hi Thanks all, I was passing the handle to writeFile which was created by CREATEFILE with FILE_FLAG_NO_BUFFERING attribute, MSDN has  ReadFile () fails with error code 87. (The parameter is incorrect) on ReFS Storage Space Mirror. Archived Forums. >. Windows 10 Insider Preview General. Windows 10 Insider Preview General https://social.technet.microsoft.com/Forums/en-US/2ea742ca-8685-4b0b-a030-5ee9de9b6e20/solved-oscdimg-tool-does-not-work-on-windows-10-readfile-fails-with-error-code-87-the Question 3 4/8/2015 4:47:56 PM 4/10/2015 12:59:31 PM Use this forum to discuss all issues except setup, installation, and deployment of

OSCDIMG Tool Does Not Work on Windows 10? ReadFile() fails , CSerialPort::Read, Failed in call to ReadFile, Error:87 Warning: throwing is definitely something I'm doing wrong in my C++ code in the GUI. Tech support scams are an industry-wide issue where scammers trick you into paying for unnecessary technical support services. Additionally, some scammers may try to identify themselves as a Microsoft MVP.

ERROR_INVALID_PARAMETER, ReadFile() fails with error code 87. (The parameter is incorrect) on ReFS Storage Space Mirror RRS feed · Archived Forums. > Windows 10  The problem is not the creation time of the file on "Z:\" but of the one on the source side. Anyway, FFS should not fail for a broken creation time, so I'll see to make the copy routine more tolerant.

  • You assign a value to hSerial, then 1) You never checked for NULL and 2) your code disappears and reappears again in a ReadFile function, losing any track of what happened to hSerial.
  • @Paul I checked hSerial immediately after creation - not NULL. And the ReadFile occurs immediately after creating hSerial. Still 87.
  • LPCTSTR portName = "COM3" ; You may want to change this, as LPCTSTR is a pointer to a wide string if a Unicode build is being done. LPCTSTR portName = _T("COM3");
  • I suppose it is compiled with mingw and no UNICODE, for example: DWORD n = 512 ; char szBuff[n] = {0}; is a variable length array use, CreateFileW would not accept char array.
  • @MarcinJędrzejewski Yes, but "officially", initializing an LPCTSTR to a non-wide string literal is not really 100% correct. If the app is going to use LPCTSTR, then it should be using the Microsoft-ism if using _T() macro or TEXT macro.