WinHttpReadData

 

Description

 

The WinHttpReadData function reads data from a handle opened by the WinHttpOpenRequest function.

 

C/C++ Syntax

 

BOOL WinHttpReadData(

HINTERNET hRequest,

LPVOID lpBuffer,

DWORD dwNumberOfBytesToRead,

LPDWORD lpdwNumberOfBytesRead

);

 

PowerBASIC Syntax

 

FUNCTION WinHttpReadData ( _

BYVAL hRequest AS DWORD, _

BYVAL lpBuffer AS DWORD, _

BYVAL dwNumberOfBytesToRead AS DWORD, _

lpdwNumberOfBytesRead AS DWORD _

) AS LONG

 

Parameters

 

hRequest

 

[in] Valid HINTERNET handle returned from a previous call to WinHttpOpenRequest. WinHttpReceiveResponse or WinHttpQueryDataAvailable must have been called for this handle and must have completed before WinHttpReadData is called. Although calling WinHttpReadData immediately after completion of WinHttpReceiveResponse avoids the expense of a buffer copy, doing so requires that the application use a fixed-length buffer for reading.

 

lpBuffer

 

[out] Pointer to a buffer that receives the data read. Make sure that this buffer remains valid until WinHttpReadData has completed.

 

dwNumberOfBytesRead

 

[in] Unsigned long integer value that contains the number of bytes to read.

 

lpdwNumberOfBytesRead

 

[out] Pointer to an unsigned long integer variable that receives the number of bytes read. WinHttpReadData sets this value to zero before doing any work or error checking. When using WinHTTP asynchronously, always set this parameter to NULL and retrieve the information in the callback function; not doing so can cause a memory fault.

 

Return Value

 

Returns a valid session handle if successful, or NULL otherwise. To retrieve extended error information, call GetLastError. Among the error codes returned are:

 

Error Codes

Description

ERROR_WINHTTP_CONNECTION_ERROR

The connection with the server has been reset or terminated, or an incompatible SSL protocol was encountered. For example, WinHTTP 5.1 does not support SSL2 unless the client specifically enables it.

ERROR_WINHTTP_INCORRECT_HANDLE_STATE

The requested operation cannot be carried out because the handle supplied is not in the correct state.

ERROR_WINHTTP_INCORRECT_HANDLE_TYPE

The type of handle supplied is incorrect for this operation.

ERROR_WINHTTP_INTERNAL_ERROR

An internal error has occurred.

ERROR_WINHTTP_OPERATION_CANCELLED

The operation was canceled, usually because the handle on which the request was operating was closed before the operation completed.

ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW

Returned when an incoming response exceeds an internal WinHTTP size limit.

ERROR_WINHTTP_TIMEOUT

The request has timed out.

ERROR_NOT_ENOUGH_MEMORY

Not enough memory was available to complete the requested operation. (Windows error code)

 

Remarks

 

Even when WinHTTP is used in asynchronous mode (that is, when WINHTTP_FLAG_ASYNC has been set in WinHttpOpen), this function can operate either synchronously or asynchronously. If this function returns FALSE, this function failed and you can call GetLastError to get extended error information. If this function returns TRUE, use the WINHTTP_CALLBACK_STATUS_READ_COMPLETE completion to determine whether this function was successful and the value of the parameters. The WINHTTP_CALLBACK_STATUS_REQUEST_ERROR completion indicates that the operation completed asynchronously, but failed.

 

Warning When WinHTTP is used in asynchronous mode, always set the lpdwNumberOfBytesRead parameter to NULL and retrieve the bytes read in the callback function; otherwise, a memory fault can occur.

 

When the read buffer is very small, WinHttpReadData might complete synchronously. If the WINHTTP_CALLBACK_STATUS_READ_COMPLETE completion triggers another call to WinHttpReadData, the situation can result in a stack overflow. In general, it is best to use a read buffer that is comparable in size, or larger than the internal read buffer used by WinHTTP, which is 8 KB.

 

If you are using WinHttpReadData synchronously, and the return value is TRUE and the number of bytes read is zero, the transfer has been completed and there are no more bytes to read on the handle. This is analogous to reaching end-of-file in a local file. If you are using the function asynchronously, the WINHTTP_CALLBACK_STATUS_READ_COMPLETE callback is called with the dwStatusInformationLength parameter set to zero when the end of a response is found.

 

Use the return value of WinHttpReadData rather than that of WinHttpQueryDataAvailable to determine whether the end of the response has been reached, because an improperly terminated response can cause WinHttpQueryDataAvailable to continue to indicate that more data is available even when the response has been completely read.

 

The buffer pointed to by lpBuffer is not always filled by calls to the WinHttpReadData function; sufficient data might not have arrived from the server.

 

For HINTERNET handles created by the WinHttpOpenRequest function and sent by WinHttpSendRequest, a call to WinHttpReceiveResponse must be made on the handle before WinHttpReadData can be used.

 

Single byte characters retrieved with WinHttpReadData are not converted to multi-byte characters.

 

When the read buffer is very small, WinHttpReadData may complete synchronously, and if the WINHTTP_CALLBACK_STATUS_READ_COMPLETE completion then triggers another call to WinHttpReadData, a stack overflow can result. It is best to use a read buffer that is 8 Kilobytes or larger in size.

 

If sufficient data has not arrived from the server, WinHttpReadData does not entirely fill the buffer pointed to by lpBuffer. The buffer must be large enough at least to hold the HTTP headers on the first read, and when reading HTML encoded directory entries, it must be large enough to hold at least one complete entry.

 

If a status callback function has been installed by using WinHttpSetStatusCallback, then those of the following notifications that have been set in the dwNotificationFlags parameter of WinHttpSetStatusCallback indicate progress in checking for available data:

 

WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
WINHTTP_CALLBACK_STATUS_READ_COMPLETE

 

Example Code [PowerBASIC]

 

The following example shows how to use secure transaction semantics to download a resource from an Secure Hypertext Transfer Protocol (HTTPS) server. The sample code initializes the WinHTTP application programming interface (API), selects a target HTTPS server, then opens and sends a request for this secure resource. WinHttpQueryDataAvailable is used with the request handle to determine how much data is available for download, then WinHttpReadData is used to read that data. This process repeats until the entire document has been retrieved and displayed.

 

#COMPILE EXE

#DIM ALL

#INCLUDE "WIN32API.INC"

#INCLUDE "WINHTTP.INC"

 

FUNCTION PBMAIN () AS LONG

 

 LOCAL dwSize AS DWORD

 LOCAL dwDownloaded AS DWORD

 LOCAL bResults AS LONG

 LOCAL hSession AS DWORD

 LOCAL hConnect AS DWORD

 LOCAL hRequest AS DWORD

 LOCAL strUserAgent AS STRING

 LOCAL strServerName AS STRING

 LOCAL strVerb AS STRING

 LOCAL strOutBuffer AS STRING

 

 dwSize = 4  ' size of a DWORD

 

 ' Use WinHttpOpen to obtain a session handle.

 strUserAgent = UCODE$("A WinHTTP Example Program/1.0" & $NUL)

 hSession = WinHttpOpen(STRPTR(strUserAgent), _

                        %WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, _

                        %WINHTTP_NO_PROXY_NAME, _

                        %WINHTTP_NO_PROXY_BYPASS, _

                        0)

 

 ' Specify an HTTP server.

 IF hSession THEN

    strServerName = UCODE$("www.microsoft.com" & $NUL)

    hConnect = WinHttpConnect(hSession, _

                              STRPTR(strServerName), _

                              %INTERNET_DEFAULT_HTTP_PORT, _

                              0)

 END IF

 

 

 ' Create an HTTP Request handle.

 IF hConnect THEN

    strVerb = UCODE$("GET" & $NUL)

    hRequest = WinHttpOpenRequest(hConnect, _

                                  STRPTR(strVerb), _

                                  %NULL,  _

                                  %NULL, _

                                  %WINHTTP_NO_REFERER, _

                                  BYVAL %WINHTTP_DEFAULT_ACCEPT_TYPES, _

                                  0)

 END IF

 

 ' Send a Request.

 ' Note: The Microsoft C example uses WINHTTP_FLAG_SECURE for the last

 ' parameter, but I have changed it to 0 because, otherwise, it returns

 ' error 12175 (ERROR_WINHTTP_SECURE_FAILURE)

 IF hRequest THEN

    bResults = WinHttpSendRequest(hRequest, _

                                  %WINHTTP_NO_ADDITIONAL_HEADERS, _

                                  0, _

                                  %WINHTTP_NO_REQUEST_DATA, _

                                  0, _

                                  0, _

                                  0)

 END IF

 

 ' End the request.

 IF bResults THEN

    bResults = WinHttpReceiveResponse(hRequest, %NULL)

 END IF

 

 ' Keep checking for data until there is nothing left.

 IF bResults THEN

    DO

       ' Check for available data.

       dwSize = 0

       IF ISFALSE WinHttpQueryDataAvailable(hRequest, dwSize) THEN

          PRINT "Error " GetLastError " in WinHttpQueryDataAvailable."

          EXIT DO

       ELSE

          ' Allocate space for the buffer.

          strOutBuffer = STRING$(dwSize + 1, $NUL)

          ' Read the data.

          IF ISFALSE WinHttpReadData(hRequest, STRPTR(strOutBuffer), _

                                     dwSize, dwDownloaded) THEN

             PRINT "Error " GetLastError " in WinHttpReadData."

          ELSE

             STDOUT strOutBuffer

          END IF

       END IF

    LOOP WHILE dwSize > 0

 END IF

 

 ' Report any errors.

 IF ISFALSE bResults THEN

    PRINT "Error " GetLastError " has occurred."

 END IF

 

 ' Close open handles.

 IF hRequest THEN WinHttpCloseHandle(hRequest)

 IF hConnect THEN WinHttpCloseHandle(hConnect)

 IF hSession THEN WinHttpCloseHandle(hSession)

 

 WAITKEY$

 

END FUNCTION

 

Example Code [C++]

 

DWORD dwSize = 0;

DWORD dwDownloaded = 0;

LPSTR pszOutBuffer;

BOOL  bResults = FALSE;

HINTERNET  hSession = NULL,

         hConnect = NULL,

         hRequest = NULL;

 

// Use WinHttpOpen to obtain a session handle.

hSession = WinHttpOpen( L"WinHTTP Example/1.0",

                      WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,

                      WINHTTP_NO_PROXY_NAME,

                      WINHTTP_NO_PROXY_BYPASS, 0);

 

// Specify an HTTP server.

if (hSession)

  hConnect = WinHttpConnect( hSession, L"www.microsoft.com",

                             INTERNET_DEFAULT_HTTPS_PORT, 0);

 

// Create an HTTP request handle.

if (hConnect)

  hRequest = WinHttpOpenRequest( hConnect, L"GET", NULL,

                                 NULL, WINHTTP_NO_REFERER,

                                 WINHTTP_DEFAULT_ACCEPT_TYPES,

                                 WINHTTP_FLAG_SECURE);

 

// Send a request.

if (hRequest)

  bResults = WinHttpSendRequest( hRequest,

                                 WINHTTP_NO_ADDITIONAL_HEADERS,

                                 0, WINHTTP_NO_REQUEST_DATA, 0,

                                 0, 0);

 

// End the request.

if (bResults)

  bResults = WinHttpReceiveResponse( hRequest, NULL);

 

// Keep checking for data until there is nothing left.

if (bResults)

  do

  {

 

      // Check for available data.

      dwSize = 0;

      if (!WinHttpQueryDataAvailable( hRequest, &dwSize))

          printf( "Error %u in WinHttpQueryDataAvailable.\n",

                  GetLastError());

 

      // Allocate space for the buffer.

      pszOutBuffer = new char[dwSize+1];

      if (!pszOutBuffer)

      {

          printf("Out of memory\n");

          dwSize=0;

      }

      else

      {

          // Read the Data.

          ZeroMemory(pszOutBuffer, dwSize+1);

 

          if (!WinHttpReadData( hRequest, (LPVOID)pszOutBuffer,

                                dwSize, &dwDownloaded))

              printf( "Error %u in WinHttpReadData.\n",

                      GetLastError());

          else

              printf("%s", pszOutBuffer);

 

          // Free the memory allocated to the buffer.

          delete [] pszOutBuffer;

      }

 

  } while (dwSize>0);

 

 

// Report any errors.

if (!bResults)

  printf("Error %d has occurred.\n",GetLastError());

 

// Close any open handles.

if (hRequest) WinHttpCloseHandle(hRequest);

if (hConnect) WinHttpCloseHandle(hConnect);

if (hSession) WinHttpCloseHandle(hSession);

 

Valid XHTML 1.0 Transitional