using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Vanara.Extensions;
using Vanara.InteropServices;
namespace Vanara.PInvoke;
/// Items from the WinHTTP.dll.
public static partial class WinHTTP
{
/// Represents an application-defined proxy change callback function.
///
/// Type: _In_ ULONGLONG
/// The flag passed to the WinHttpRegisterProxyChangeNotification function (for example, WINHTTP_PROXY_NOTIFY_CHANGE).
///
///
/// Type: _In_ PVOID
/// The context object pointer passed to the WinHttpRegisterProxyChangeNotification function.
///
/// None
// https://learn.microsoft.com/en-us/windows/win32/api/winhttp/nc-winhttp-winhttp_proxy_change_callback WINHTTP_PROXY_CHANGE_CALLBACK
// WinhttpProxyChangeCallback; void WinhttpProxyChangeCallback( ULONGLONG ullFlags, PVOID pvContext ) {...}
[PInvokeData("winhttp.h", MSDNShortId = "NC:winhttp.WINHTTP_PROXY_CHANGE_CALLBACK")]
[UnmanagedFunctionPointer(CallingConvention.Winapi, SetLastError = false)]
public delegate void WINHTTP_PROXY_CHANGE_CALLBACK(ulong ullFlags, IntPtr pvContext);
/// Frees the data retrieved from a previous call to WinHttpGetProxySettingsResultEx.
///
/// Type: _In_ WINHTTP_PROXY_SETTINGS_TYPE
/// A proxy settings type.
///
///
/// Type: _In_ PVOID
/// A pointer to a WINHTTP_PROXY_SETTINGS_EX structure that was retrieved from a previous call to WinHttpGetProxySettingsResultEx.
///
/// This function does not return a value.
// https://learn.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpfreeproxysettingsex WINHTTPAPI DWORD
// WinHttpFreeProxySettingsEx( WINHTTP_PROXY_SETTINGS_TYPE ProxySettingsType, PVOID pProxySettingsEx );
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpFreeProxySettingsEx")]
[DllImport(Lib_Winhttp, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error WinHttpFreeProxySettingsEx(WINHTTP_PROXY_SETTINGS_TYPE ProxySettingsType,
IntPtr pProxySettingsEx);
/// Retrieves extended proxy settings.
///
/// Type: _In_ HINTERNET
/// The WinHTTP resolver handle returned by the WinHttpCreateProxyResolver function.
///
///
/// Type: _In_ WINHTTP_PROXY_SETTINGS_TYPE
/// A proxy settings type.
///
///
/// Type: _In_opt_ PWINHTTP_PROXY_SETTINGS_PARAM
/// An optional pointer to a WINHTTP_PROXY_SETTINGS_PARAM.
///
///
/// Type: _In_opt_ DWORD_PTR
/// An optional pointer to a DWORD containing context data that will be passed to the completion callback function.
///
///
///
/// A DWORD containing a status code indicating the result of the operation. The following codes can be returned (the list is not exhaustive).
///
///
///
/// Code
/// Description
///
/// -
/// ERROR_IO_PENDING
/// The operation is continuing asynchronously.
///
///
///
// https://learn.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpgetproxysettingsex WINHTTPAPI DWORD
// WinHttpGetProxySettingsEx( HINTERNET hResolver, WINHTTP_PROXY_SETTINGS_TYPE ProxySettingsType, PWINHTTP_PROXY_SETTINGS_PARAM
// pProxySettingsParam, DWORD_PTR pContext );
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpGetProxySettingsEx")]
[DllImport(Lib_Winhttp, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error WinHttpGetProxySettingsEx(HINTERNET hResolver, WINHTTP_PROXY_SETTINGS_TYPE ProxySettingsType,
in WINHTTP_PROXY_SETTINGS_PARAM pProxySettingsParam, IntPtr pContext);
/// Retrieves extended proxy settings.
///
/// Type: _In_ HINTERNET
/// The WinHTTP resolver handle returned by the WinHttpCreateProxyResolver function.
///
///
/// Type: _In_ WINHTTP_PROXY_SETTINGS_TYPE
/// A proxy settings type.
///
///
/// Type: _In_opt_ PWINHTTP_PROXY_SETTINGS_PARAM
/// An optional pointer to a WINHTTP_PROXY_SETTINGS_PARAM.
///
///
/// Type: _In_opt_ DWORD_PTR
/// An optional pointer to a DWORD containing context data that will be passed to the completion callback function.
///
///
///
/// A DWORD containing a status code indicating the result of the operation. The following codes can be returned (the list is not exhaustive).
///
///
///
/// Code
/// Description
///
/// -
/// ERROR_IO_PENDING
/// The operation is continuing asynchronously.
///
///
///
// https://learn.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpgetproxysettingsex WINHTTPAPI DWORD
// WinHttpGetProxySettingsEx( HINTERNET hResolver, WINHTTP_PROXY_SETTINGS_TYPE ProxySettingsType, PWINHTTP_PROXY_SETTINGS_PARAM
// pProxySettingsParam, DWORD_PTR pContext );
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpGetProxySettingsEx")]
[DllImport(Lib_Winhttp, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error WinHttpGetProxySettingsEx(HINTERNET hResolver, WINHTTP_PROXY_SETTINGS_TYPE ProxySettingsType,
[In, Optional] IntPtr pProxySettingsParam, IntPtr pContext);
/// Retrieves the results of a call to WinHttpGetProxySettingsEx.
///
/// Type: _In_ HINTERNET
/// The WinHTTP resolver handle returned by the WinHttpCreateProxyResolver function.
///
///
/// Type: _In_ WINHTTP_PROXY_SETTINGS_TYPE
/// A proxy settings type.
///
///
/// Type: _In_opt_ PWINHTTP_PROXY_SETTINGS_PARAM
/// An optional WINHTTP_PROXY_SETTINGS_PARAM.
///
/// A WINHTTP_PROXY_SETTINGS_EX structure.
// https://learn.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpgetproxysettingsresultex WINHTTPAPI DWORD
// WinHttpGetProxySettingsResultEx( HINTERNET hResolver, PVOID pProxySettingsEx );
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpGetProxySettingsResultEx")]
public static Win32Error WinHttpGetProxySettingsEx(HINTERNET hResolver, WINHTTP_PROXY_SETTINGS_TYPE ProxySettingsType,
WINHTTP_PROXY_SETTINGS_PARAM? pProxySettingsParam, out WINHTTP_PROXY_SETTINGS_EX_MGD pProxySettingsEx)
{
pProxySettingsEx = default;
using var pParam = pProxySettingsParam.HasValue ? new SafeCoTaskMemStruct(pProxySettingsParam.Value) : SafeCoTaskMemStruct.Null;
var ret = WinHttpGetProxySettingsEx(hResolver, ProxySettingsType, pParam, default);
if (ret.Failed)
return ret;
IntPtr ptr = default;
ret = WinHttpGetProxySettingsResultEx(hResolver, ptr);
if (ret.Failed)
return ret;
pProxySettingsEx = ptr.ToStructure();
WinHttpFreeProxySettingsEx(ProxySettingsType, ptr);
return ret;
}
/// Retrieves the results of a call to WinHttpGetProxySettingsEx.
///
/// Type: _In_ HINTERNET
/// The resolver handle used to issue a previously completed call to WinHttpGetProxySettingsEx.
///
///
/// A pointer to a WINHTTP_PROXY_SETTINGS_EX structure. The memory occupied by the structure is allocated by
/// WinHttpGetProxySettingsResultEx, so you need to free that memory by passing this pointer to WinHttpFreeProxySettingsEx.
///
// https://learn.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpgetproxysettingsresultex
// WINHTTPAPI DWORD WinHttpGetProxySettingsResultEx( HINTERNET hResolver, PVOID pProxySettingsEx );
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpGetProxySettingsResultEx")]
[DllImport(Lib_Winhttp, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error WinHttpGetProxySettingsResultEx(HINTERNET hResolver, IntPtr pProxySettingsEx);
/// The WinHttpQueryOption function queries an Internet option on the specified handle.
///
/// An HINTERNET handle on which to query information. Note that this can be either a Session handle or a Request handle,
/// depending on what option is being queried; see the Option Flags topic to determine which handle is appropriate to use in querying a
/// particular option.
///
///
/// An unsigned long integer value that contains the Internet option to query. This can be one of the Option Flags values.
///
///
/// A pointer to a buffer that receives the option setting. Strings returned by the WinHttpQueryOption function are globally
/// allocated, so the calling application must globally free the string when it finishes using it. Setting this parameter to NULL
/// causes this function to return FALSE. Calling GetLastError then returns ERROR_INSUFFICIENT_BUFFER and lpdwBufferLength
/// contains the number of bytes required to hold the requested information.
///
///
/// A pointer to an unsigned long integer variable that contains the length of lpBuffer, in bytes. When the function returns, the
/// variable receives the length of the data placed into lpBuffer. If GetLastError returns ERROR_INSUFFICIENT_BUFFER, this
/// parameter receives the number of bytes required to hold the requested information.
///
///
///
/// Returns TRUE if successful, or FALSE otherwise. To get a specific error message, call GetLastError. Among the error
/// codes returned are the following:
///
///
///
/// Error Code
/// Description
///
/// -
/// 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_INVALID_OPTION
/// An invalid option value was specified.
///
/// -
/// ERROR_NOT_ENOUGH_MEMORY
/// Not enough memory was available to complete the requested operation. (Windows error code)
///
///
///
///
///
/// Even when WinHTTP is used in asynchronous mode (that is, when WINHTTP_FLAG_ASYNC has been set in WinHttpOpen), this function
/// operates synchronously. The return value indicates success or failure. To get extended error information, call GetLastError.
///
///
/// GetLastError returns the ERROR_INVALID_PARAMETER if an option flag that is invalid for the specified handle type is passed to the
/// dwOption parameter.
///
/// Note For Windows XP and Windows 2000, see the Run-Time Requirements section of the WinHttp start page.
/// Examples
/// This example demonstrates retrieving the connection time-out value:
///
/// DWORD data; DWORD dwSize = sizeof(DWORD); // Use WinHttpOpen to obtain an HINTERNET handle. HINTERNET hSession = WinHttpOpen(L"A WinHTTP Example Program/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (hSession) { // Use WinHttpQueryOption to retrieve internet options. if (WinHttpQueryOption( hSession, WINHTTP_OPTION_CONNECT_TIMEOUT, &data, &dwSize)) { printf("Connection timeout: %u ms\n\n",data); } else { printf( "Error %u in WinHttpQueryOption.\n", GetLastError()); } // When finished, release the HINTERNET handle. WinHttpCloseHandle(hSession); } else { printf("Error %u in WinHttpOpen.\n", GetLastError()); }
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpqueryoption BOOL WinHttpQueryOption( [in] HINTERNET
// hInternet, [in] DWORD dwOption, [out] LPVOID lpBuffer, [in, out] LPDWORD lpdwBufferLength );
[DllImport(Lib_Winhttp, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpQueryOption")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WinHttpQueryOption(HINTERNET hInternet, WINHTTP_OPTION dwOption, [Out, Optional] IntPtr lpBuffer, ref uint lpdwBufferLength);
/// The WinHttpQueryOption function queries an Internet option on the specified handle.
/// The type of the option.
///
/// An HINTERNET handle on which to query information. Note that this can be either a Session handle or a Request handle,
/// depending on what option is being queried; see the Option Flags topic to determine which handle is appropriate to use in querying a
/// particular option.
///
///
/// An unsigned long integer value that contains the Internet option to query. This can be one of the Option Flags values.
///
/// The option setting.
///
/// Even when WinHTTP is used in asynchronous mode (that is, when WINHTTP_FLAG_ASYNC has been set in WinHttpOpen), this function
/// operates synchronously. The return value indicates success or failure. To get extended error information, call GetLastError.
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpqueryoption BOOL WinHttpQueryOption( [in] HINTERNET
// hInternet, [in] DWORD dwOption, [out] LPVOID lpBuffer, [in, out] LPDWORD lpdwBufferLength );
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpQueryOption")]
public static T WinHttpQueryOption(HINTERNET hInternet, WINHTTP_OPTION dwOption)
{
Type rType = CorrespondingTypeAttribute.GetCorrespondingTypes(dwOption, CorrespondingAction.Get).FirstOrDefault() ?? typeof(T);
if (typeof(T) != typeof(object))
{
rType = typeof(T);
}
uint sz = 0;
WinHttpQueryOption(hInternet, dwOption, default, ref sz);
Win32Error.ThrowLastErrorUnless(Win32Error.ERROR_INSUFFICIENT_BUFFER);
using SafeHGlobalHandle buffer = new(sz);
Win32Error.ThrowLastErrorIfFalse(WinHttpQueryOption(hInternet, dwOption, buffer, ref sz));
return (T)buffer.DangerousGetHandle().Convert(sz, rType, CharSet.Unicode);
}
/// Also see WinHttpReadDataEx.
///
/// 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.
///
///
/// Pointer to a buffer that receives the data read. Make sure that this buffer remains valid until WinHttpReadData has completed.
///
/// Unsigned long integer value that contains the number of bytes to read.
///
/// 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.
///
///
///
/// Returns TRUE if successful, or FALSE otherwise. For extended error information, call GetLastError. The following table
/// identifies the error codes that are returned.
///
///
///
/// Error Code
/// 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)
///
///
///
///
///
/// Starting in Windows Vista and Windows Server 2008, WinHttp enables applications to perform chunked transfer encoding on data sent to
/// the server. When the Transfer-Encoding header is present on the WinHttp response, WinHttpReadData strips the chunking
/// information before giving the data to the application.
///
///
/// 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.
///
///
/// WinHttpReadData tries to fill the buffer pointed to by lpBuffer until there is no more data available from the
/// response. If sufficient data has not arrived from the server, the buffer is not filled.
///
///
/// 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
///
///
/// Note For Windows XP and Windows 2000, see the Run-Time Requirements section of the WinHttp start page.
/// Examples
///
/// 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.
///
///
/// 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()); break; } // No more available data. if (!dwSize) break; // Allocate space for the buffer. pszOutBuffer = new char[dwSize+1]; if (!pszOutBuffer) { printf("Out of memory\n"); break; } // 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; // This condition should never be reached since WinHttpQueryDataAvailable // reported that there are bits to read. if (!dwDownloaded) break; } while (dwSize > 0); } else { // Report any errors. printf( "Error %d has occurred.\n", GetLastError() ); } // Close any open handles. if (hRequest) WinHttpCloseHandle(hRequest); if (hConnect) WinHttpCloseHandle(hConnect); if (hSession) WinHttpCloseHandle(hSession);
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpreaddata BOOL WinHttpReadData( [in] HINTERNET hRequest,
// [out] LPVOID lpBuffer, [in] DWORD dwNumberOfBytesToRead, [out] LPDWORD lpdwNumberOfBytesRead );
[DllImport(Lib_Winhttp, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpReadData")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WinHttpReadData(HINTERNET hRequest, [Out] IntPtr lpBuffer, uint dwNumberOfBytesToRead, out uint lpdwNumberOfBytesRead);
/// Also see WinHttpReadDataEx.
///
/// 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.
///
///
/// Pointer to a buffer that receives the data read. Make sure that this buffer remains valid until WinHttpReadData has completed.
///
/// Unsigned long integer value that contains the number of bytes to read.
///
/// 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.
///
///
///
/// Returns TRUE if successful, or FALSE otherwise. For extended error information, call GetLastError. The following table
/// identifies the error codes that are returned.
///
///
///
/// Error Code
/// 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)
///
///
///
///
///
/// Starting in Windows Vista and Windows Server 2008, WinHttp enables applications to perform chunked transfer encoding on data sent to
/// the server. When the Transfer-Encoding header is present on the WinHttp response, WinHttpReadData strips the chunking
/// information before giving the data to the application.
///
///
/// 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.
///
///
/// WinHttpReadData tries to fill the buffer pointed to by lpBuffer until there is no more data available from the
/// response. If sufficient data has not arrived from the server, the buffer is not filled.
///
///
/// 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
///
///
/// Note For Windows XP and Windows 2000, see the Run-Time Requirements section of the WinHttp start page.
/// Examples
///
/// 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.
///
///
/// 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()); break; } // No more available data. if (!dwSize) break; // Allocate space for the buffer. pszOutBuffer = new char[dwSize+1]; if (!pszOutBuffer) { printf("Out of memory\n"); break; } // 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; // This condition should never be reached since WinHttpQueryDataAvailable // reported that there are bits to read. if (!dwDownloaded) break; } while (dwSize > 0); } else { // Report any errors. printf( "Error %d has occurred.\n", GetLastError() ); } // Close any open handles. if (hRequest) WinHttpCloseHandle(hRequest); if (hConnect) WinHttpCloseHandle(hConnect); if (hSession) WinHttpCloseHandle(hSession);
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpreaddata BOOL WinHttpReadData( [in] HINTERNET hRequest,
// [out] LPVOID lpBuffer, [in] DWORD dwNumberOfBytesToRead, [out] LPDWORD lpdwNumberOfBytesRead );
[DllImport(Lib_Winhttp, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpReadData")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WinHttpReadData(HINTERNET hRequest, [Out] byte[] lpBuffer, int dwNumberOfBytesToRead, out int lpdwNumberOfBytesRead);
/// Reads data from a handle opened by the WinHttpOpenRequest function.
///
/// Type: IN HINTERNET
/// An HINTERNET handle returned from a previous call to WinHttpOpenRequest.
///
/// WinHttpReceiveResponse or WinHttpQueryDataAvailable must have been called for this handle and must have completed before
/// WinHttpReadDataEx is called. Although calling WinHttpReadDataEx immediately after completion of
/// WinHttpReceiveResponse avoids the expense of a buffer copy, doing so requires that your application use a fixed-length buffer
/// for reading.
///
///
///
/// Type: _Out_writes_bytes_to_(dwNumberOfBytesToRead, *lpdwNumberOfBytesRead) __out_data_source(NETWORK) LPVOID
///
/// Pointer to a buffer that receives the data read. Make sure that this buffer remains valid until WinHttpReadDataEx has completed.
///
///
///
/// Type: IN DWORD
/// Unsigned long integer value that contains the number of bytes to read.
///
///
/// Type: OUT LPDWORD
///
/// Pointer to an unsigned long integer variable that receives the number of bytes read. WinHttpReadDataEx 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.
///
///
///
/// Type: IN ULONGLONG
///
/// If you pass WINHTTP_READ_DATA_EX_FLAG_FILL_BUFFER, then WinHttp won't complete the call to WinHttpReadDataEx until the
/// provided data buffer has been filled, or the response is complete. Passing this flag makes the behavior of this API equivalent to
/// that of WinHttpReadData.
///
///
///
/// Type: IN DWORD
/// Reserved. Pass 0.
///
///
/// Type: _In_reads_bytes_opt_(cbProperty) PVOID
/// Reserved. Pass NULL.
///
///
/// A status code indicating the result of the operation. Among the error codes returned are the following.
///
///
/// Error Code
/// 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)
///
///
///
///
/// By default, WinHttpReadDataEx returns after any amount of data has been written to the buffer that you provide (the function
/// won't always completely fill the buffer that you provide).
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpreaddataex WINHTTPAPI DWORD WinHttpReadDataEx( HINTERNET
// hRequest, LPVOID lpBuffer, DWORD dwNumberOfBytesToRead, LPDWORD lpdwNumberOfBytesRead, ULONGLONG ullFlags, DWORD cbProperty, PVOID
// pvProperty );
[DllImport(Lib_Winhttp, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpReadDataEx")]
public static extern Win32Error WinHttpReadDataEx(HINTERNET hRequest, [Out] IntPtr lpBuffer, uint dwNumberOfBytesToRead,
out uint lpdwNumberOfBytesRead, [Optional] WINHTTP_READ_DATA_EX_FLAG ullFlags, [Optional] uint cbProperty, [Optional] IntPtr pvProperty);
/// Reads data from a handle opened by the WinHttpOpenRequest function.
///
/// Type: IN HINTERNET
/// An HINTERNET handle returned from a previous call to WinHttpOpenRequest.
///
/// WinHttpReceiveResponse or WinHttpQueryDataAvailable must have been called for this handle and must have completed before
/// WinHttpReadDataEx is called. Although calling WinHttpReadDataEx immediately after completion of
/// WinHttpReceiveResponse avoids the expense of a buffer copy, doing so requires that your application use a fixed-length buffer
/// for reading.
///
///
///
/// Type: _Out_writes_bytes_to_(dwNumberOfBytesToRead, *lpdwNumberOfBytesRead) __out_data_source(NETWORK) LPVOID
///
/// Pointer to a buffer that receives the data read. Make sure that this buffer remains valid until WinHttpReadDataEx has completed.
///
///
///
/// Type: IN DWORD
/// Unsigned long integer value that contains the number of bytes to read.
///
///
/// Type: OUT LPDWORD
///
/// Pointer to an unsigned long integer variable that receives the number of bytes read. WinHttpReadDataEx 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.
///
///
///
/// Type: IN ULONGLONG
///
/// If you pass WINHTTP_READ_DATA_EX_FLAG_FILL_BUFFER, then WinHttp won't complete the call to WinHttpReadDataEx until the
/// provided data buffer has been filled, or the response is complete. Passing this flag makes the behavior of this API equivalent to
/// that of WinHttpReadData.
///
///
///
/// Type: IN DWORD
/// Reserved. Pass 0.
///
///
/// Type: _In_reads_bytes_opt_(cbProperty) PVOID
/// Reserved. Pass NULL.
///
///
/// A status code indicating the result of the operation. Among the error codes returned are the following.
///
///
/// Error Code
/// 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)
///
///
///
///
/// By default, WinHttpReadDataEx returns after any amount of data has been written to the buffer that you provide (the function
/// won't always completely fill the buffer that you provide).
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpreaddataex WINHTTPAPI DWORD WinHttpReadDataEx( HINTERNET
// hRequest, LPVOID lpBuffer, DWORD dwNumberOfBytesToRead, LPDWORD lpdwNumberOfBytesRead, ULONGLONG ullFlags, DWORD cbProperty, PVOID
// pvProperty );
[DllImport(Lib_Winhttp, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpReadDataEx")]
public static extern Win32Error WinHttpReadDataEx(HINTERNET hRequest, [Out] byte[] lpBuffer, int dwNumberOfBytesToRead,
out int lpdwNumberOfBytesRead, [Optional] WINHTTP_READ_DATA_EX_FLAG ullFlags, [Optional] uint cbProperty, [Optional] IntPtr pvProperty);
///
/// The WinHttpReceiveResponse function waits to receive the response to an HTTP request initiated by WinHttpSendRequest. When
/// WinHttpReceiveResponse completes successfully, the status code and response headers have been received and are available for
/// the application to inspect using WinHttpQueryHeaders. An application must call WinHttpReceiveResponse before it can use
/// WinHttpQueryDataAvailable and WinHttpReadData to access the response entity body (if any).
///
///
/// HINTERNET handle returned by WinHttpOpenRequest and sent by WinHttpSendRequest. Wait until WinHttpSendRequest has completed
/// for this handle before calling WinHttpReceiveResponse.
///
/// This parameter is reserved and must be NULL.
///
///
/// Returns TRUE if successful, or FALSE otherwise. For extended error information, call GetLastError. Among the error
/// codes returned are the following.
///
///
///
/// Error Code
/// Description
///
/// -
/// ERROR_WINHTTP_CANNOT_CONNECT
/// Returned if connection to the server failed.
///
/// -
/// ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW
/// Returned when an overflow condition is encountered in the course of parsing chunked encoding.
///
/// -
/// ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED
/// Returned when the server requests client authentication.
///
/// -
/// ERROR_WINHTTP_CONNECTION_ERROR
///
/// The connection with the server has been reset or terminated, or an incompatible SSL protocol was encountered. For example, WinHTTP
/// version 5.1 does not support SSL2 unless the client specifically enables it.
///
///
/// -
/// ERROR_WINHTTP_HEADER_COUNT_EXCEEDED
/// Returned when a larger number of headers were present in a response than WinHTTP could receive.
///
/// -
/// ERROR_WINHTTP_HEADER_SIZE_OVERFLOW
/// Returned by WinHttpReceiveResponse when the size of headers received exceeds the limit for the request handle.
///
/// -
/// 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_INVALID_SERVER_RESPONSE
/// The server response could not be parsed.
///
/// -
/// ERROR_WINHTTP_INVALID_URL
/// The URL is invalid.
///
/// -
/// ERROR_WINHTTP_LOGIN_FAILURE
///
/// The login attempt failed. When this error is encountered, the request handle should be closed with WinHttpCloseHandle. A new request
/// handle must be created before retrying the function that originally produced this error.
///
///
/// -
/// ERROR_WINHTTP_NAME_NOT_RESOLVED
/// The server name could not be resolved.
///
/// -
/// 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_REDIRECT_FAILED
/// The redirection failed because either the scheme changed or all attempts made to redirect failed (default is five attempts).
///
/// -
/// ERROR_WINHTTP_RESEND_REQUEST
/// The WinHTTP function failed. The desired function can be retried on the same request handle.
///
/// -
/// ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW
/// Returned when an incoming response exceeds an internal WinHTTP size limit.
///
/// -
/// ERROR_WINHTTP_SECURE_FAILURE
///
/// One or more errors were found in the Secure Sockets Layer (SSL) certificate sent by the server. To determine what type of error was
/// encountered, check for a WINHTTP_CALLBACK_STATUS_SECURE_FAILURE notification in a status callback function. For more information, see WINHTTP_STATUS_CALLBACK.
///
///
/// -
/// ERROR_WINHTTP_TIMEOUT
/// The request has timed out.
///
/// -
/// ERROR_WINHTTP_UNRECOGNIZED_SCHEME
/// The URL specified a scheme other than "http:" or "https:".
///
/// -
/// ERROR_NOT_ENOUGH_MEMORY
/// Not enough memory was available to complete the requested operation. (Windows error code)
///
///
///
///
///
/// 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, the application should expect either the
/// WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE completion callback, indicating success, or the
/// WINHTTP_CALLBACK_STATUS_REQUEST_ERROR completion callback, indicating that the operation completed asynchronously, but failed.
///
///
/// If a status callback function has been installed with WinHttpSetStatusCallback, then those of the following notifications that have
/// been set in the dwNotificationFlags parameter of WinHttpSetStatusCallback indicate progress in receiving the response:
///
///
/// -
/// WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
///
/// -
/// WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
///
/// -
/// WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
///
/// -
/// WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE
///
/// -
/// WINHTTP_CALLBACK_STATUS_REDIRECT
///
///
///
/// If the server closes the connection, the following notifications will also be reported, provided that they have been set in the
/// dwNotificationFlags parameter of WinHttpSetStatusCallback:
///
///
/// -
/// WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
///
/// -
/// WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
///
///
/// Note For Windows XP and Windows 2000, see the Run-Time Requirements section of the WinHttp start page.
/// Examples
///
/// This example shows code that writes data to an HTTP server. The server name supplied in the example, www.wingtiptoys.com, is
/// fictitious and must be replaced with the name of a server for which you have write access.
///
///
/// LPSTR pszData = "WinHttpWriteData Example"; DWORD dwBytesWritten = 0; BOOL bResults = FALSE; HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL; // Use WinHttpOpen to obtain a session handle. hSession = WinHttpOpen( L"A WinHTTP Example Program/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.wingtiptoys.com", INTERNET_DEFAULT_HTTP_PORT, 0); // Create an HTTP Request handle. if (hConnect) hRequest = WinHttpOpenRequest( hConnect, L"PUT", L"/writetst.txt", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); // Send a Request. if (hRequest) bResults = WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, (DWORD)strlen(pszData), 0); // Write data to the server. if (bResults) bResults = WinHttpWriteData( hRequest, pszData, (DWORD)strlen(pszData), &dwBytesWritten); // End the request. if (bResults) bResults = WinHttpReceiveResponse( hRequest, NULL); // 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);
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpreceiveresponse WINHTTPAPI BOOL WinHttpReceiveResponse(
// [in] HINTERNET hRequest, [in] LPVOID lpReserved );
[DllImport(Lib_Winhttp, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpReceiveResponse")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WinHttpReceiveResponse(HINTERNET hRequest, [In, Optional] IntPtr lpReserved);
/// Registers a callback function that WinHTTP calls when the effective proxy settings change.
///
/// Type: _In_ ULONGLONG
/// The flag to pass to the callback (for example, WINHTTP_PROXY_NOTIFY_CHANGE).
///
///
/// Type: _In_ WINHTTP_PROXY_CHANGE_CALLBACK
/// A pointer to the callback function that should be called when the effective proxy settings change.
///
///
/// Type: _In_ PVOID
/// A pointer to a context object to pass to the callback.
///
///
/// Type: _Out_ WINHTTP_PROXY_CHANGE_REGISTRATION_HANDLE*
///
/// A handle that identifies the registration of the callback function. To unregister, pass this value to
/// WinHttpUnregisterProxyChangeNotification. WINHTTP_PROXY_CHANGE_REGISTRATION_HANDLE is equivalent to PVOID.
///
///
///
///
/// A DWORD containing a status code indicating the result of the operation. The following codes can be returned (the list is not exhaustive).
///
///
///
/// Code
/// Description
///
/// -
/// ERROR_SUCCESS
/// The operation succeeded.
///
///
///
// https://learn.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpregisterproxychangenotification WINHTTPAPI DWORD
// WinHttpRegisterProxyChangeNotification( ULONGLONG ullFlags, WINHTTP_PROXY_CHANGE_CALLBACK pfnCallback, PVOID pvContext,
// WINHTTP_PROXY_CHANGE_REGISTRATION_HANDLE *hRegistration );
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpRegisterProxyChangeNotification")]
[DllImport(Lib_Winhttp, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error WinHttpRegisterProxyChangeNotification(ulong ullFlags,
WINHTTP_PROXY_CHANGE_CALLBACK pfnCallback, IntPtr pvContext,
ref WINHTTP_PROXY_CHANGE_REGISTRATION_HANDLE hRegistration);
/// The WinHttpResetAutoProxy function resets the auto-proxy.
/// A valid HINTERNET WinHTTP session handle returned by a previous call to the WinHttpOpen function.
///
/// A set of flags that affects the reset operation.
/// The following flags are supported as defined in the Winhttp.h header file.
///
///
/// Value
/// Meaning
///
/// -
/// WINHTTP_RESET_STATE 0x00000001
/// Forces a flush and retry of non-persistent proxy information on the current network.
///
/// -
/// WINHTTP_RESET_SWPAD_CURRENT_NETWORK 0x00000002
/// Flush the PAD information for the current network.
///
/// -
/// WINHTTP_RESET_SWPAD_ALL 0x00000004
/// Flush the PAD information for all networks.
///
/// -
/// WINHTTP_RESET_SCRIPT_CACHE 0x00000008
/// Flush the persistent HTTP cache of proxy scripts.
///
/// -
/// WINHTTP_RESET_ALL 0x0000FFFF
/// Forces a flush and retry of all proxy information on the current network.
///
/// -
/// WINHTTP_RESET_NOTIFY_NETWORK_CHANGED 0x00010000
/// Flush the current proxy information and notify that the network changed.
///
/// -
/// WINHTTP_RESET_OUT_OF_PROC 0x00020000
///
/// Act on the autoproxy service instead of the current process. Applications that use the WinHttpGetProxyForUrl function to purge
/// in-process caching should close the hInternet handle and open a new handle for future calls.
///
///
///
///
///
/// A code indicating the success or failure of the operation.
///
///
/// Return code
/// Description
///
/// -
/// ERROR_SUCCESS
/// The operation was successful.
///
/// -
/// ERROR_INVALID_HANDLE
/// The hSession parameter is not a valid handle.
///
/// -
/// ERROR_WINHTTP_INCORRECT_HANDLE TYPE
/// The hSession parameter is not the product of a call to WinHttpOpen.
///
///
///
///
/// To reset everything, set the dwFlags parameter to include WINHTTP_RESET_ALL and WINHTTP_RESET_OUT_OF_PROC.
///
/// Note If you make subsequent calls to the WinHttpResetAutoProxy function, there must be at least 30 seconds delay
/// between calls to reset the state of the auto-proxy. If there is less than 30 seconds, the WinHttpResetAutoProxy function call
/// may return ERROR_SUCCESS but the reset won't happen.
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpresetautoproxy WINHTTPAPI DWORD WinHttpResetAutoProxy(
// [in] HINTERNET hSession, [in] DWORD dwFlags );
[DllImport(Lib_Winhttp, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpResetAutoProxy")]
public static extern Win32Error WinHttpResetAutoProxy(HINTERNET hSession, WINHTTP_RESET dwFlags);
/// The WinHttpSendRequest function sends the specified request to the HTTP server.
/// An HINTERNET handle returned by WinHttpOpenRequest.
///
/// A pointer to a string that contains the additional headers to append to the request. This parameter can be
/// WINHTTP_NO_ADDITIONAL_HEADERS if there are no additional headers to append.
///
///
/// An unsigned long integer value that contains the length, in characters, of the additional headers. If this parameter is -1L
/// and pwszHeaders is not NULL, this function assumes that pwszHeaders is null-terminated, and the length is calculated.
///
///
///
/// A pointer to a buffer that contains any optional data to send immediately after the request headers. This parameter is generally used
/// for POST and PUT operations. The optional data can be the resource or data posted to the server. This parameter can be
/// WINHTTP_NO_REQUEST_DATA if there is no optional data to send.
///
/// If the dwOptionalLength parameter is 0, this parameter is ignored and set to NULL.
/// This buffer must remain available until the request handle is closed or the call to WinHttpReceiveResponse has completed.
///
///
///
/// An unsigned long integer value that contains the length, in bytes, of the optional data. This parameter can be zero if there is no
/// optional data to send.
///
///
/// This parameter must contain a valid length when the lpOptional parameter is not NULL. Otherwise, lpOptional is
/// ignored and set to NULL.
///
///
///
///
/// An unsigned long integer value that contains the length, in bytes, of the total data sent. This parameter specifies the
/// Content-Length header of the request. If the value of this parameter is greater than the length specified by dwOptionalLength,
/// then WinHttpWriteData can be used to send additional data.
///
///
/// dwTotalLength must not change between calls to WinHttpSendRequest for the same request. If dwTotalLength needs
/// to be changed, the caller should create a new request.
///
///
///
/// A pointer to a pointer-sized variable that contains an application-defined value that is passed, with the request handle, to any
/// callback functions.
///
///
///
/// Returns TRUE if successful, or FALSE otherwise. For extended error information, call GetLastError. Error codes are
/// listed in the following table.
///
///
///
/// Error Code
/// Description
///
/// -
/// ERROR_WINHTTP_CANNOT_CONNECT
/// Returned if connection to the server failed.
///
/// -
/// ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED
///
/// The secure HTTP server requires a client certificate. The application retrieves the list of certificate issuers by calling
/// WinHttpQueryOption with the WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST option. If the server requests the client certificate, but
/// does not require it, the application can alternately call WinHttpSetOption with the WINHTTP_OPTION_CLIENT_CERT_CONTEXT option.
/// In this case, the application specifies the WINHTTP_NO_CLIENT_CERT_CONTEXT macro in the lpBuffer parameter of
/// WinHttpSetOption. For more information, see the WINHTTP_OPTION_CLIENT_CERT_CONTEXT option. Windows Server 2003 with
/// SP1, Windows XP with SP2 and Windows 2000: This error is not supported.
///
///
/// -
/// ERROR_WINHTTP_CONNECTION_ERROR
///
/// The connection with the server has been reset or terminated, or an incompatible SSL protocol was encountered. For example, WinHTTP
/// version 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_INVALID_URL
/// The URL is invalid.
///
/// -
/// ERROR_WINHTTP_LOGIN_FAILURE
///
/// The login attempt failed. When this error is encountered, the request handle should be closed with WinHttpCloseHandle. A new request
/// handle must be created before retrying the function that originally produced this error.
///
///
/// -
/// ERROR_WINHTTP_NAME_NOT_RESOLVED
/// The server name cannot be resolved.
///
/// -
/// 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_SECURE_FAILURE
///
/// One or more errors were found in the Secure Sockets Layer (SSL) certificate sent by the server. To determine what type of error was
/// encountered, verify through a WINHTTP_CALLBACK_STATUS_SECURE_FAILURE notification in a status callback function. For more
/// information, see WINHTTP_STATUS_CALLBACK.
///
///
/// -
/// ERROR_WINHTTP_SHUTDOWN
/// The WinHTTP function support is shut down or unloaded.
///
/// -
/// ERROR_WINHTTP_TIMEOUT
/// The request timed out.
///
/// -
/// ERROR_WINHTTP_UNRECOGNIZED_SCHEME
/// The URL specified a scheme other than "http:" or "https:".
///
/// -
/// ERROR_NOT_ENOUGH_MEMORY
///
/// Not enough memory was available to complete the requested operation. (Windows error code) Windows Server 2003, Windows XP and
/// Windows 2000: The TCP reservation range set with the WINHTTP_OPTION_PORT_RESERVATION option is not large enough to send
/// this request.
///
///
/// -
/// ERROR_INVALID_PARAMETER
///
/// The content length specified in the dwTotalLength parameter does not match the length specified in the Content-Length header.
/// The lpOptional parameter must be NULL and the dwOptionalLength parameter must be zero when the Transfer-Encoding
/// header is present. The Content-Length header cannot be present when the Transfer-Encoding header is present.
///
///
/// -
/// ERROR_WINHTTP_RESEND_REQUEST
///
/// The application must call WinHttpSendRequest again due to a redirect or authentication challenge. Windows Server 2003 with SP1,
/// Windows XP with SP2 and Windows 2000: This error is not supported.
///
///
///
///
///
///
/// 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. In either case, if the request is sent successfully, the application is called
/// back with the completion status set to WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE. The
/// WINHTTP_CALLBACK_STATUS_REQUEST_ERROR completion indicates that the operation completed asynchronously, but failed. Upon
/// receiving the WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE status callback, the application can start to receive a response
/// from the server with WinHttpReceiveResponse. Before then, no other asynchronous functions can be called, otherwise,
/// ERROR_WINHTTP_INCORRECT_HANDLE_STATE is returned.
///
///
/// An application must not delete or alter the buffer pointed to by lpOptional until the request handle is closed or the call to
/// WinHttpReceiveResponse has completed, because an authentication challenge or redirect that required the optional data could be
/// encountered in the course of receiving the response. If the operation must be aborted with WinHttpCloseHandle, the application must
/// keep the buffer valid until it receives the callback WINHTTP_CALLBACK_STATUS_REQUEST_ERROR with an
/// ERROR_WINHTTP_OPERATION_CANCELLED error code.
///
///
/// If WinHTTP is used synchronously, that is, when WINHTP_FLAG_ASYNC was not set in WinHttpOpen, an application is not called
/// with a completion status even if a callback function is registered. While in this mode, the application can call
/// WinHttpReceiveResponse when WinHttpSendRequest returns.
///
///
/// The WinHttpSendRequest function sends the specified request to the HTTP server and allows the client to specify additional
/// headers to send along with the request.
///
///
/// This function also lets the client specify optional data to send to the HTTP server immediately following the request headers. This
/// feature is generally used for write operations such as PUT and POST.
///
///
/// An application can use the same HTTP request handle in multiple calls to WinHttpSendRequest to re-send the same request, but
/// the application must read all data returned from the previous call before calling this function again.
///
///
/// The name and value of request headers added with this function are validated. Headers must be well formed. For more information about
/// valid HTTP headers, see RFC 2616. If an invalid header is used, this function fails and GetLastError returns ERROR_INVALID_PARAMETER.
/// The invalid header is not added.
///
/// Windows 2000: When sending requests from multiple threads, there may be a significant decrease in network and CPU performance.
/// Windows XP and Windows 2000: See Run-Time Requirements.
/// WinHttpSetStatusCallback
///
/// If a status callback function has been installed with WinHttpSetStatusCallback, then those of the following notifications that have
/// been set in the dwNotificationFlags parameter of WinHttpSetStatusCallback indicate the progress in sending the request:
///
///
/// -
/// WINHTTP_CALLBACK_STATUS_DETECTING_PROXY (not implemented)
///
/// -
/// WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE (only in asynchronous mode)
///
/// -
/// WINHTTP_CALLBACK_STATUS_REDIRECT
///
/// -
/// WINHTTP_CALLBACK_STATUS_SECURE_FAILURE
///
/// -
/// WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE
///
///
/// Note On Windows 7 and Windows Server 2008 R2, all of the following notifications are deprecated.
///
/// -
/// WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
///
/// -
/// WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
///
/// -
/// WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
///
/// -
/// WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
///
/// -
/// WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
///
/// -
/// WINHTTP_CALLBACK_STATUS_REQUEST_SENT
///
/// -
/// WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
///
/// -
/// WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
///
///
///
/// If the server closes the connection, the following notifications are also sent, provided that they have been set in the
/// dwNotificationFlags parameter of WinHttpSetStatusCallback:
///
///
/// -
/// WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
///
/// -
/// WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
///
///
/// Support for Greater Than 4-GB Upload
///
/// Starting in Windows Vista and Windows Server 2008, WinHttp supports uploading files up to the size of a LARGE_INTEGER (2^64
/// bytes) using the Content-Length header. Payload lengths specified in the call to WinHttpSendRequest are limited to the size of
/// a DWORD (2^32 bytes). To upload data to a URL larger than a DWORD, the application must provide the length in the
/// Content-Length header of the request. In this case, the WinHttp client application calls WinHttpSendRequest with the
/// dwTotalLength parameter set to WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH.
///
///
/// If the Content-Length header specifies a length less than a 2^32, the application must also specify the content length in the call to
/// WinHttpSendRequest. If the dwTotalLength parameter does not match the length specified in the Content-Length header,
/// the call fails and returns ERROR_INVALID_PARAMETER.
///
///
/// The Content-Length header can be added in the call to WinHttpAddRequestHeaders, or it can be specified in the lpszHeader
/// parameter of WinHttpSendRequest as shown in the following code example.
///
///
/// BOOL fRet = WinHttpSendRequest( hReq, L"Content-Length: 68719476735\r\n", -1L, WINHTTP_NO_REQUEST_DATA, 0, WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, pMyContent);
///
/// Transfer-Encoding Header
///
/// Starting in Windows Vista and Windows Server 2008, WinHttp enables applications to perform chunked transfer encoding on data sent to
/// the server. When the Transfer-Encoding header is present on the WinHttp request, the dwTotalLength parameter in the call to
/// WinHttpSendRequest is set to WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH and the application sends the entity body in one or
/// more calls to WinHttpWriteData. The lpOptional parameter of WinHttpSendRequest must be NULL and the
/// dwOptionLength parameter must be zero, otherwise an ERROR_WINHTTP_INVALID_PARAMETER error is returned. To terminate the
/// chunked data transfer, the application generates a zero length chunk and sends it in the last call to WinHttpWriteData.
///
/// Examples
///
/// The following code example shows how to obtain an HINTERNET handle, open an HTTP session, create a request header, and send that
/// header to the server.
///
///
/// BOOL bResults = FALSE; HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL; // Use WinHttpOpen to obtain a session handle. hSession = WinHttpOpen( L"A WinHTTP Example Program/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.wingtiptoys.com", INTERNET_DEFAULT_HTTP_PORT, 0); // Create an HTTP Request handle. if (hConnect) hRequest = WinHttpOpenRequest( hConnect, L"PUT", L"/writetst.txt", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); // Send a Request. if (hRequest) bResults = WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); // Place additional code here. // Report errors. if (!bResults) printf("Error %d has occurred.\n",GetLastError()); // Close open handles. if (hRequest) WinHttpCloseHandle(hRequest); if (hConnect) WinHttpCloseHandle(hConnect); if (hSession) WinHttpCloseHandle(hSession);
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpsendrequest BOOL WinHttpSendRequest( [in] HINTERNET
// hRequest, [in, optional] LPCWSTR lpszHeaders, [in] DWORD dwHeadersLength, [in, optional] LPVOID lpOptional, [in] DWORD
// dwOptionalLength, [in] DWORD dwTotalLength, [in] DWORD_PTR dwContext );
[DllImport(Lib_Winhttp, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpSendRequest")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WinHttpSendRequest(HINTERNET hRequest, [Optional, MarshalAs(UnmanagedType.LPWStr)] string lpszHeaders,
[Optional] int dwHeadersLength, [In, Optional] IntPtr lpOptional, [Optional] uint dwOptionalLength, [Optional] uint dwTotalLength,
[In, Optional] IntPtr dwContext);
/// The WinHttpSetCredentials function passes the required authorization credentials to the server.
/// Valid HINTERNET handle returned by WinHttpOpenRequest.
///
///
/// An unsigned integer that specifies a flag that contains the authentication target. Can be one of the values in the following table.
///
///
///
/// Value
/// Meaning
///
/// -
/// WINHTTP_AUTH_TARGET_SERVER
/// Credentials are passed to a server.
///
/// -
/// WINHTTP_AUTH_TARGET_PROXY
/// Credentials are passed to a proxy.
///
///
///
///
///
/// An unsigned integer that specifies a flag that contains the authentication scheme. Must be one of the supported authentication
/// schemes returned from WinHttpQueryAuthSchemes. The following table identifies the possible values.
///
///
///
/// Value
/// Meaning
///
/// -
/// WINHTTP_AUTH_SCHEME_BASIC
/// Use basic authentication.
///
/// -
/// WINHTTP_AUTH_SCHEME_NTLM
/// Use NTLM authentication.
///
/// -
/// WINHTTP_AUTH_SCHEME_PASSPORT
/// Use passport authentication.
///
/// -
/// WINHTTP_AUTH_SCHEME_DIGEST
/// Use digest authentication.
///
/// -
/// WINHTTP_AUTH_SCHEME_NEGOTIATE
/// Selects between NTLM and Kerberos authentication.
///
///
///
/// Pointer to a string that contains a valid user name.
/// Pointer to a string that contains a valid password. The password can be blank.
/// This parameter is reserved and must be NULL.
///
///
/// Returns TRUE if successful, or FALSE otherwise. For extended error information, call GetLastError. The following table
/// identifies the error codes returned.
///
///
///
/// Error Code
/// Description
///
/// -
/// 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_NOT_ENOUGH_MEMORY
/// Not enough memory was available to complete the requested operation (Windows error code).
///
///
///
///
///
/// Even when WinHTTP is used in asynchronous mode (that is, when WINHTTP_FLAG_ASYNC has been set in WinHttpOpen), this function
/// operates synchronously. The return value indicates success or failure. To get extended error information, call GetLastError.
///
///
/// The credentials set by WinHttpSetCredentials are only used for a single request; WinHTTP does not cache these credentials for
/// use in subsequent requests. As a result, applications must be written so that they can respond to multiple challenges. If an
/// authenticated connection is re-used, subsequent requests cannot be challenged, but your code should be able to respond to a challenge
/// at any point.
///
/// For sample code that illustrates the use of WinHttpSetCredentials, see Authentication in WinHTTP.
///
/// When using Passport authentication and responding to a 407 status code, a WinHTTP application must use
/// WinHttpSetOption to provide proxy credentials rather than WinHttpSetCredentials. This is only true when using Passport
/// authentication; in all other circumstances, use WinHttpSetCredentials, because WinHttpSetOption is less secure.
///
/// For Windows XP and Windows 2000, see the Run-Time Requirements section of the WinHttp start page.
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpsetcredentials BOOL WinHttpSetCredentials( [in] HINTERNET
// hRequest, [in] DWORD AuthTargets, [in] DWORD AuthScheme, [in] LPCWSTR pwszUserName, [in] LPCWSTR pwszPassword, [in] LPVOID pAuthParams );
[DllImport(Lib_Winhttp, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpSetCredentials")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WinHttpSetCredentials(HINTERNET hRequest, WINHTTP_AUTH_TARGET AuthTargets, WINHTTP_AUTH_SCHEME AuthScheme,
[MarshalAs(UnmanagedType.LPWStr)] string pwszUserName, [Optional, MarshalAs(UnmanagedType.LPWStr)] string pwszPassword, IntPtr pAuthParams = default);
/// The WinHttpSetDefaultProxyConfiguration function sets the default WinHTTP proxy configuration in the registry.
/// A pointer to a variable of type WINHTTP_PROXY_INFO that specifies the default proxy configuration.
///
///
/// Returns TRUE if successful, or FALSE otherwise. For extended error information, call GetLastError. Among the error
/// codes returned are the following.
///
///
///
/// Error Code
/// Description
///
/// -
/// ERROR_WINHTTP_INTERNAL_ERROR
/// An internal error has occurred.
///
/// -
/// ERROR_NOT_ENOUGH_MEMORY
/// Not enough memory was available to complete the requested operation. (Windows error code)
///
///
///
///
///
/// The default proxy configuration set by WinHttpSetDefaultProxyConfiguration can be overridden for an existing WinHTTP session
/// by calling WinHttpSetOption and specifying the WINHTTP_OPTION_PROXY flag. The default proxy configuration can be overridden for a new
/// session by specifying the configuration with the WinHttpOpen function.
///
///
/// The dwAccessType member of the WINHTTP_PROXY_INFO structure pointed to by pProxyInfo should be set to
/// WINHTTP_ACCESS_TYPE_NAMED_PROXY if a proxy is specified. Otherwise, it should be set to WINHTTP_ACCESS_TYPE_DEFAULT_PROXY.
///
/// Any new sessions created after calling this function use the new default proxy configuration.
///
/// Even when WinHTTP is used in asynchronous mode (that is, when WINHTTP_FLAG_ASYNC has been set in WinHttpOpen), this function
/// operates synchronously. The return value indicates success or failure. To get extended error information, call GetLastError.
///
/// For Windows XP and Windows 2000, see the Run-Time Requirements section of the WinHTTP start page.
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpsetdefaultproxyconfiguration WINHTTPAPI BOOL
// WinHttpSetDefaultProxyConfiguration( [in] WINHTTP_PROXY_INFO *pProxyInfo );
[DllImport(Lib_Winhttp, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpSetDefaultProxyConfiguration")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WinHttpSetDefaultProxyConfiguration(in WINHTTP_PROXY_INFO pProxyInfo);
/// The WinHttpSetOption function sets an Internet option.
///
/// The HINTERNET handle on which to set data. Be aware that this can be either a Session handle or a Request handle, depending on what
/// option is being set. For more information about how to determine which handle is appropriate to use in setting a particular option,
/// see the Option Flags.
///
///
/// An unsigned long integer value that contains the Internet option to set. This can be one of the Option Flags values.
///
/// A pointer to a buffer that contains the option setting.
///
/// Unsigned long integer value that contains the length of the lpBuffer buffer. The length of the buffer is specified in
/// characters for the following options; for all other options, the length is specified in bytes.
///
///
///
/// Returns TRUE if successful, or FALSE otherwise. For extended error information, call GetLastError. Among the error
/// codes returned are the following:
///
///
///
/// Error Code
/// Description
///
/// -
/// 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_INVALID_OPTION
/// A request to WinHttpQueryOption or WinHttpSetOption specified an invalid option value.
///
/// -
/// ERROR_INVALID_PARAMETER
///
/// A parameter is not valid. This value will be returned if WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL is set to a value lower
/// than 15000.
///
///
/// -
/// ERROR_WINHTTP_OPTION_NOT_SETTABLE
/// The requested option cannot be set, only queried.
///
/// -
/// ERROR_INVALID_PARAMETER
///
/// A parameter is not valid. This value will be returned if WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL is set to a value lower
/// than 15000.
///
///
/// -
/// ERROR_NOT_ENOUGH_MEMORY
/// Not enough memory was available to complete the requested operation. (Windows error code)
///
///
///
///
///
/// Credentials passed to WinHttpSetOption could be unexpectedly sent in plaintext. It is strongly recommended that you use
/// WinHttpQueryAuthSchemes and WinHttpSetCredentials instead of WinHttpSetOption for setting credentials.
///
///
/// When using Passport authentication, however, a WinHTTP application responding to a 407 status code must use
/// WinHttpSetOption to provide proxy credentials rather than WinHttpSetCredentials. This is only true when using Passport
/// authentication; in all other circumstances, use WinHttpSetCredentials.
///
///
/// Even when WinHTTP is used in asynchronous mode (that is, when WINHTTP_FLAG_ASYNC has been set in WinHttpOpen), this function
/// operates synchronously. The return value indicates success or failure. To get extended error information, call GetLastError.
///
/// GetLastError returns the error ERROR_INVALID_PARAMETER if an option flag is specified that cannot be set.
/// For more information and code examples that show the use of WinHttpSetOption, see Authentication in WinHTTP.
/// For Windows XP and Windows 2000, see the Run-Time Requirements section of the WinHttp start page.
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpsetoption BOOL WinHttpSetOption( [in] HINTERNET
// hInternet, [in] DWORD dwOption, [in] LPVOID lpBuffer, [in] DWORD dwBufferLength );
[DllImport(Lib_Winhttp, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpSetOption")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WinHttpSetOption(HINTERNET hInternet, WINHTTP_OPTION dwOption, [In] IntPtr lpBuffer, uint dwBufferLength);
/// The WinHttpSetOption function sets an Internet option.
///
/// The HINTERNET handle on which to set data. Be aware that this can be either a Session handle or a Request handle, depending on what
/// option is being set. For more information about how to determine which handle is appropriate to use in setting a particular option,
/// see the Option Flags.
///
///
/// An unsigned long integer value that contains the Internet option to set. This can be one of the Option Flags values.
///
/// The option setting.
///
///
/// Returns TRUE if successful, or FALSE otherwise. For extended error information, call GetLastError. Among the error
/// codes returned are the following:
///
///
///
/// Error Code
/// Description
///
/// -
/// 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_INVALID_OPTION
/// A request to WinHttpQueryOption or WinHttpSetOption specified an invalid option value.
///
/// -
/// ERROR_INVALID_PARAMETER
///
/// A parameter is not valid. This value will be returned if WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL is set to a value lower
/// than 15000.
///
///
/// -
/// ERROR_WINHTTP_OPTION_NOT_SETTABLE
/// The requested option cannot be set, only queried.
///
/// -
/// ERROR_INVALID_PARAMETER
///
/// A parameter is not valid. This value will be returned if WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL is set to a value lower
/// than 15000.
///
///
/// -
/// ERROR_NOT_ENOUGH_MEMORY
/// Not enough memory was available to complete the requested operation. (Windows error code)
///
///
///
///
///
/// Credentials passed to WinHttpSetOption could be unexpectedly sent in plaintext. It is strongly recommended that you use
/// WinHttpQueryAuthSchemes and WinHttpSetCredentials instead of WinHttpSetOption for setting credentials.
///
///
/// When using Passport authentication, however, a WinHTTP application responding to a 407 status code must use
/// WinHttpSetOption to provide proxy credentials rather than WinHttpSetCredentials. This is only true when using Passport
/// authentication; in all other circumstances, use WinHttpSetCredentials.
///
///
/// Even when WinHTTP is used in asynchronous mode (that is, when WINHTTP_FLAG_ASYNC has been set in WinHttpOpen), this function
/// operates synchronously. The return value indicates success or failure. To get extended error information, call GetLastError.
///
/// GetLastError returns the error ERROR_INVALID_PARAMETER if an option flag is specified that cannot be set.
/// For more information and code examples that show the use of WinHttpSetOption, see Authentication in WinHTTP.
/// For Windows XP and Windows 2000, see the Run-Time Requirements section of the WinHttp start page.
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpsetoption BOOL WinHttpSetOption( [in] HINTERNET
// hInternet, [in] DWORD dwOption, [in] LPVOID lpBuffer, [in] DWORD dwBufferLength );
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpSetOption")]
public static bool WinHttpSetOption(HINTERNET hInternet, WINHTTP_OPTION dwOption, in T value) where T : struct
{
using SafeHGlobalHandle mem = SafeHGlobalHandle.CreateFromStructure(value);
return WinHttpSetOption(hInternet, dwOption, mem, mem.Size);
}
///
/// The WinHttpSetStatusCallback function sets up a callback function that WinHTTP can call as progress is made during an operation.
///
/// HINTERNET handle for which the callback is to be set.
///
/// Pointer to the callback function to call when progress is made. Set this to NULL to remove the existing callback function. For
/// more information about the callback function, see WINHTTP_STATUS_CALLBACK.
///
///
/// Unsigned long integer value that specifies flags to indicate which events activate the callback function.
/// The possible values are as follows.
///
///
/// Value
/// Meaning
///
/// -
/// WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS
///
/// Activates upon any completion notification. This flag specifies that all notifications required for read or write operations are
/// used. See WINHTTP_STATUS_CALLBACK for a list of completions.
///
///
/// -
/// WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
/// Activates upon any status change notification including completions. See WINHTTP_STATUS_CALLBACK for a list of notifications.
///
/// -
/// WINHTTP_CALLBACK_FLAG_RESOLVE_NAME
/// Activates upon beginning and completing name resolution.
///
/// -
/// WINHTTP_CALLBACK_FLAG_CONNECT_TO_SERVER
/// Activates upon beginning and completing connection to the server.
///
/// -
/// WINHTTP_CALLBACK_FLAG_DETECTING_PROXY
/// Activates when detecting the proxy server.
///
/// -
/// WINHTTP_CALLBACK_FLAG_DATA_AVAILABLE
/// Activates when completing a query for data.
///
/// -
/// WINHTTP_CALLBACK_FLAG_HEADERS_AVAILABLE
/// Activates when the response headers are available for retrieval.
///
/// -
/// WINHTTP_CALLBACK_FLAG_READ_COMPLETE
/// Activates upon completion of a data-read operation.
///
/// -
/// WINHTTP_CALLBACK_FLAG_REQUEST_ERROR
/// Activates when an asynchronous error occurs.
///
/// -
/// WINHTTP_CALLBACK_FLAG_SEND_REQUEST
/// Activates upon beginning and completing the sending of a request header with WinHttpSendRequest.
///
/// -
/// WINHTTP_CALLBACK_FLAG_SENDREQUEST_COMPLETE
/// Activates when a request header has been sent with WinHttpSendRequest.
///
/// -
/// WINHTTP_CALLBACK_FLAG_WRITE_COMPLETE
/// Activates upon completion of a data-post operation.
///
/// -
/// WINHTTP_CALLBACK_FLAG_RECEIVE_RESPONSE
/// Activates upon beginning and completing the receipt of a resource from the HTTP server.
///
/// -
/// WINHTTP_CALLBACK_FLAG_CLOSE_CONNECTION
/// Activates when beginning and completing the closing of an HTTP connection.
///
/// -
/// WINHTTP_CALLBACK_FLAG_HANDLES
/// Activates when an HINTERNET handle is created or closed.
///
/// -
/// WINHTTP_CALLBACK_FLAG_REDIRECT
/// Activates when the request is redirected.
///
/// -
/// WINHTTP_CALLBACK_FLAG_INTERMEDIATE_RESPONSE
/// Activates when receiving an intermediate (100 level) status code message from the server.
///
/// -
/// WINHTTP_CALLBACK_FLAG_SECURE_FAILURE
/// Activates upon a secure connection failure.
///
///
///
/// This parameter is reserved and must be NULL.
///
///
/// If successful, returns a pointer to the previously defined status callback function or NULL if there was no previously defined
/// status callback function. Returns WINHTTP_INVALID_STATUS_CALLBACK if the callback function could not be installed. For
/// extended error information, call GetLastError. Among the error codes returned are the following.
///
///
///
/// Error Code
/// Description
///
/// -
/// 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_NOT_ENOUGH_MEMORY
/// Not enough memory was available to complete the requested operation. (Windows error code)
///
///
///
///
///
/// If you set the callback on the session handle before creating the request handle, the request handle inherits the callback function
/// pointer from its parent session.
///
///
/// Even when WinHTTP is used in asynchronous mode (that is, when WINHTTP_FLAG_ASYNC has been set in WinHttpOpen), this function
/// operates synchronously. The return value indicates success or failure. To get extended error information, call GetLastError.
///
///
/// Both synchronous and asynchronous functions use the callback function to indicate the progress of the request, such as resolving a
/// name, connecting to a server, and so on. The callback function is required for an asynchronous operation.
///
///
/// A callback function can be set on any handle and is inherited by derived handles. A callback function can be changed using
/// WinHttpSetStatusCallback, provided there are no pending requests that need to use the previous callback value. However,
/// changing the callback function on a handle does not change the callbacks on derived handles, such as that returned by WinHttpConnect.
/// You must change the callback function at each level.
///
/// Many WinHTTP functions perform several operations on the network. Each operation can take time to complete and each can fail.
///
/// After initiating the WinHttpSetStatusCallback function, the callback function can be accessed from within WinHTTP for
/// monitoring time-intensive network operations.
///
///
/// At the end of asynchronous processing, the application may set the callback function to NULL. This prevents the client
/// application from receiving additional notifications.
///
/// The following code snippet shows the recommended method for setting the callback function to NULL.
/// WinHttpSetStatusCallback( hOpen, NULL, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, NULL );
///
/// Note, however, that WinHTTP does not synchronize WinHttpSetStatusCallback with worker threads. If a callback originating in
/// another thread is in progress when an application calls WinHttpSetStatusCallback, the application still receives a callback
/// notification even after WinHttpSetStatusCallback successfully sets the callback function to NULL and returns.
///
/// For Windows XP and Windows 2000, see the Run-Time Requirements section of the WinHttp start page.
/// Examples
///
/// The following example shows how to install a callback function for asynchronous WinHTTP functions. The example assumes that a
/// WINHTTP_STATUS_CALLBACK function named "AsyncCallback( )" has been previously implemented:
///
///
/// // Use WinHttpOpen to obtain an HINTERNET handle. HINTERNET hSession = WinHttpOpen(L"A WinHTTP Example Program/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (hSession) { // Install the status callback function. WINHTTP_STATUS_CALLBACK isCallback = WinHttpSetStatusCallback( hSession, (WINHTTP_STATUS_CALLBACK)AsyncCallback, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, NULL); // Place additional code here. // When finished, release the HINTERNET handle. WinHttpCloseHandle(hSession); } else { printf("Error %u in WinHttpOpen.\n", GetLastError()); }
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpsetstatuscallback WINHTTPAPI WINHTTP_STATUS_CALLBACK
// WinHttpSetStatusCallback( [in] HINTERNET hInternet, [in] WINHTTP_STATUS_CALLBACK lpfnInternetCallback, [in] DWORD dwNotificationFlags,
// [in] DWORD_PTR dwReserved );
[DllImport(Lib_Winhttp, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpSetStatusCallback")]
public static extern IntPtr WinHttpSetStatusCallback(HINTERNET hInternet, WINHTTP_STATUS_CALLBACK lpfnInternetCallback,
WINHTTP_CALLBACK_FLAG dwNotificationFlags, IntPtr dwReserved = default);
/// The WinHttpSetTimeouts function sets time-outs involved with HTTP transactions.
/// The HINTERNET handle returned by WinHttpOpen or WinHttpOpenRequest.
///
///
/// A value of type integer that specifies the time-out value, in milliseconds, to use for name resolution. If resolution takes longer
/// than this time-out value, the action is canceled. The initial value is zero, meaning no time-out (infinite).
///
///
/// Windows Vista and Windows XP: If DNS timeout is specified using NAME_RESOLUTION_TIMEOUT, there is an overhead of one thread
/// per request.
///
///
///
///
/// A value of type integer that specifies the time-out value, in milliseconds, to use for server connection requests. If a connection
/// request takes longer than this time-out value, the request is canceled. The initial value is 60,000 (60 seconds).
///
/// TCP/IP can time out while setting up the socket during the three leg SYN/ACK exchange, regardless of the value of this parameter.
///
///
/// A value of type integer that specifies the time-out value, in milliseconds, to use for sending requests. If sending a request takes
/// longer than this time-out value, the send is canceled. The initial value is 30,000 (30 seconds).
///
///
/// A value of type integer that specifies the time-out value, in milliseconds, to receive a response to a request. If a response takes
/// longer than this time-out value, the request is canceled. The initial value is 30,000 (30 seconds).
///
///
///
/// Returns TRUE if successful, or FALSE otherwise. For extended error information, call GetLastError. Among the error
/// codes returned are the following.
///
///
///
/// Error Code
/// Description
///
/// -
/// 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_NOT_ENOUGH_MEMORY
/// Not enough memory was available to complete the requested operation. (Windows error code)
///
/// -
/// ERROR_INVALID_PARAMETER
/// One or more of the timeout parameters has a negative value other than -1.
///
///
///
///
///
/// Even when WinHTTP is used in asynchronous mode (that is, when WINHTTP_FLAG_ASYNC has been set in WinHttpOpen), this function
/// operates synchronously. The return value indicates success or failure. To get extended error information, call GetLastError.
///
///
/// A value of 0 or -1 sets a time-out to wait infinitely. A value greater than 0 sets the time-out value in milliseconds. For example,
/// 30,000 would set the time-out to 30 seconds. All negative values other than -1 cause the function to fail with ERROR_INVALID_PARAMETER.
///
///
/// Important If a small timeout is set using WinHttpSetOption and WINHTTP_OPTION_RECEIVE_TIMEOUT, it can override the value set
/// with the dwReceiveTimeout parameter, causing a response to terminate earlier than expected. To avoid this, do not set a
/// timeout with the WINHTTP_OPTION_RECEIVE_TIMEOUT option that is smaller than the value set using dwReceiveTimeout.
///
/// Note For Windows XP and Windows 2000, see the Run-Time Requirements section of the WinHTTP start page.
/// Examples
/// This example shows how to set new time-out values using WinHttpSetTimeouts.
///
/// // Use WinHttpOpen to obtain an HINTERNET handle. HINTERNET hSession = WinHttpOpen(L"A WinHTTP Example Program/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (hSession) { // Use WinHttpSetTimeouts to set a new time-out values. if (!WinHttpSetTimeouts( hSession, 10000, 10000, 10000, 10000)) printf( "Error %u in WinHttpSetTimeouts.\n", GetLastError()); // PLACE ADDITIONAL CODE HERE. // When finished, release the HINTERNET handle. WinHttpCloseHandle(hSession); } else { printf("Error %u in WinHttpOpen.\n", GetLastError()); }
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpsettimeouts BOOL WinHttpSetTimeouts( [in] HINTERNET
// hInternet, [in] int nResolveTimeout, [in] int nConnectTimeout, [in] int nSendTimeout, [in] int nReceiveTimeout );
[DllImport(Lib_Winhttp, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpSetTimeouts")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WinHttpSetTimeouts(HINTERNET hInternet, int nResolveTimeout = 0, int nConnectTimeout = 60000, int nSendTimeout = 30000, int nReceiveTimeout = 30000);
/// The WinHttpTimeFromSystemTime function formats a date and time according to the HTTP version 1.0 specification.
/// A pointer to a SYSTEMTIME structure that contains the date and time to format.
///
/// A pointer to a string buffer that receives the formatted date and time. The buffer should equal to the size, in bytes, of WINHTTP_TIME_FORMAT_BUFSIZE.
///
///
///
/// Returns TRUE if successful, or FALSE otherwise. To get extended error information, call GetLastError. Error codes
/// include the following.
///
///
///
/// Error Code
/// Description
///
/// -
/// ERROR_WINHTTP_INTERNAL_ERROR
/// An internal error has occurred.
///
///
///
///
///
/// Even when WinHTTP is used in asynchronous mode (that is, when WINHTTP_FLAG_ASYNC has been set in WinHttpOpen), this function
/// operates synchronously. The return value indicates success or failure. To get extended error information, call GetLastError.
///
/// Note For Windows XP and Windows 2000, see the Run-Time Requirements section of the WinHTTP Start Page.
/// Examples
/// The following code example code shows how to convert a SYSTEMTIME structure to a string that contains the time in HTTP format.
///
/// SYSTEMTIME sTime; LPWSTR pwszTimeStr; // Get the current time. GetSystemTime(&sTime); // Allocate memory for the string. // Note: WINHTTP_TIME_FORMAT_BUFSIZE is a byte count. // Therefore, you must divide the array by // sizeof WCHAR to get the proper string length. pwszTimeStr = new WCHAR[WINHTTP_TIME_FORMAT_BUFSIZE/sizeof(WCHAR)]; // Convert the current time to HTTP format. if(!WinHttpTimeFromSystemTime( &sTime, pwszTimeStr)) { printf( "Error %u in WinHttpTimeFromSystemTime.\n", GetLastError()); } else { // Print the time. printf("Current time is (%S)\n", pwszTimeStr); } // Free the memory. delete [] pwszTimeStr;
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttptimefromsystemtime BOOL WinHttpTimeFromSystemTime( [in]
// const SYSTEMTIME *pst, [out] LPWSTR pwszTime );
[DllImport(Lib_Winhttp, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpTimeFromSystemTime")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WinHttpTimeFromSystemTime(in SYSTEMTIME pst, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszTime);
/// The WinHttpTimeToSystemTime function takes an HTTP time/date string and converts it to a SYSTEMTIME structure.
///
/// Pointer to a null-terminated date/time string to convert. This value must use the format defined in section 3.3 of the RFC2616.
///
/// Pointer to the SYSTEMTIME structure that receives the converted time.
///
///
/// Returns TRUE if successful, or FALSE otherwise. For extended error information, call GetLastError. Among the error
/// codes returned is:
///
///
///
/// Error Code
/// Description
///
/// -
/// ERROR_WINHTTP_INTERNAL_ERROR
/// An internal error has occurred.
///
///
///
///
///
/// Even when WinHTTP is used in asynchronous mode (that is, when WINHTTP_FLAG_ASYNC has been set in WinHttpOpen), this function
/// operates synchronously. The return value indicates success or failure. To get extended error information, call GetLastError.
///
/// Note For Windows XP and Windows 2000, see the Run-Time Requirements section of the WinHttp start page.
/// Examples
/// This example shows how to convert an HTTP formatted date to a SYSTEMTIME structure.
///
/// SYSTEMTIME sTime; LPCWSTR pwszTimeStr = L"Tue, 21 Nov 2000 01:06:53 GMT"; // Convert the HTTP string to a SYSTEMTIME structure. if (!WinHttpTimeToSystemTime( pwszTimeStr, &sTime)) { printf( "Error %u in WinHttpTimeToSystemTime.\n", GetLastError()); } else { // Print the date. printf( "The U.S. formatted date is (%u/%u/%u)\n", sTime.wMonth, sTime.wDay, sTime.wYear); }
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttptimetosystemtime BOOL WinHttpTimeToSystemTime( [in]
// LPCWSTR pwszTime, [out] SYSTEMTIME *pst );
[DllImport(Lib_Winhttp, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpTimeToSystemTime")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WinHttpTimeToSystemTime([MarshalAs(UnmanagedType.LPWStr)] string pwszTime, out SYSTEMTIME pst);
/// Unregisters a callback function that was registered by calling WinHttpRegisterProxyChangeNotification.
///
/// Type: _In_ WINHTTP_PROXY_CHANGE_REGISTRATION_HANDLE*
/// The handle that was returned from WinHttpRegisterProxyChangeNotification.
///
/// A DWORD containing a status code indicating the result of the operation.
// https://learn.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpunregisterproxychangenotification WINHTTPAPI DWORD
// WinHttpUnregisterProxyChangeNotification( WINHTTP_PROXY_CHANGE_REGISTRATION_HANDLE hRegistration );
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpUnregisterProxyChangeNotification")]
[DllImport(Lib_Winhttp, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error WinHttpUnregisterProxyChangeNotification(WINHTTP_PROXY_CHANGE_REGISTRATION_HANDLE hRegistration);
/// The WinHttpWebSocketClose function closes a WebSocket connection.
///
/// Type: HINTERNET
/// Handle to a WebSocket.
///
///
/// Type: USHORT
/// A close status code. See WINHTTP_WEB_SOCKET_CLOSE_STATUS for possible values.
///
///
/// Type: PVOID
/// A detailed reason for the close.
///
///
/// Type: DWORD
/// The length of pvReason, in bytes.
/// If pvReason is NULL, this must be 0. This value must be within the range of 0 to 123.
///
///
/// Type: DWORD
/// With the following exception, all error codes indicate that the underlying TCP connection has been aborted.
///
///
///
/// Description
///
/// -
/// ERROR_INVALID_OPERATION
/// A close or send is pending.
///
/// -
/// ERROR_INVALID_PARAMETER
/// A parameter is invalid.
///
/// -
/// ERROR_INVALID_SERVER_RESPONSE
/// Invalid data was received from the server.
///
///
///
///
///
/// WinHttpWebSocketClose completely closes a WebSocket connection. To close the send channel while still leaving the receive
/// channel open, use WinHttpWebSocketShutdown.
///
///
/// It is possible to receive a close frame during regular receive operations. In this case, WinHttpWebSocketClose will also send
/// a close frame.
///
/// The close timer can be set by the property WINHTTP_OPTION_WEB_SOCKET_CLOSE_TIMEOUT. The default is 10 seconds.
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpwebsocketclose WINHTTPAPI DWORD WinHttpWebSocketClose(
// [in] HINTERNET hWebSocket, [in] USHORT usStatus, [in, optional] PVOID pvReason, [in] DWORD dwReasonLength );
[DllImport(Lib_Winhttp, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpWebSocketClose")]
public static extern Win32Error WinHttpWebSocketClose(HINTERNET hWebSocket, WINHTTP_WEB_SOCKET_CLOSE_STATUS usStatus,
[In, Optional] IntPtr pvReason, [In, Optional] uint dwReasonLength);
/// The WinHttpWebSocketCompleteUpgrade function completes a WebSocket handshake started by WinHttpSendRequest.
///
/// Type: HINTERNET
/// HTTP request handle used to send a WebSocket handshake.
///
///
/// Type: DWORD_PTR
/// Context to be associated with the new handle.
///
///
/// Type: HINTERNET
/// A new WebSocket handle. If NULL, call GetLastError to determine the cause of failure.
///
///
///
/// WinHttpWebSocketCompleteUpgrade can be called on an open HTTP request to get a WebSocket handle for performing other WebSocket operations.
///
///
/// The request handle must be marked as a WebSocket upgrade by calling WinHttpSetOption with WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET
/// before sending the request.
///
///
/// The caller should check the HTTP status code returned by the server and call this function only if the status code was 101. Calling
/// it with any other status code will result in a failure.
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpwebsocketcompleteupgrade WINHTTPAPI HINTERNET
// WinHttpWebSocketCompleteUpgrade( [in] HINTERNET hRequest, [in, optional] DWORD_PTR pContext );
[DllImport(Lib_Winhttp, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpWebSocketCompleteUpgrade")]
public static extern SafeHINTERNET WinHttpWebSocketCompleteUpgrade(HINTERNET hRequest, [In, Optional] IntPtr pContext);
/// The WinHttpWebSocketQueryCloseStatus function retrieves the close status sent by a server.
///
/// Type: HINTERNET
/// Handle to a WebSocket
///
///
/// Type: USHORT*
/// A pointer to a close status code that will be filled upon return. See WINHTTP_WEB_SOCKET_CLOSE_STATUS for possible values.
///
///
/// Type: PVOID
/// A pointer to a buffer that will receive a close reason on return.
///
///
/// Type: DWORD
/// The length of the pvReason buffer, in bytes.
///
///
/// Type: DWORD*
///
/// The number of bytes consumed. If pvReason is NULL and dwReasonLength is 0, pdwReasonLengthConsumed will
/// contain the size of the buffer that needs to be allocated by the calling application.
///
///
///
/// Type: DWORD
/// NO_ERROR on success. Otherwise an error code.
///
///
///
/// Description
///
/// -
/// ERROR_INSUFFICIENT_BUFFER
/// There is not enough space in pvReason to write the whole close reason.
///
/// -
/// ERROR_INVALID_OPERATION
/// No close frame has been received yet.
///
/// -
/// ERROR_INVALID_PARAMETER
/// A parameter is invalid.
///
///
///
///
///
/// Call WinHttpWebSocketQueryCloseStatus only after WinHttpWebSocketClose succeeds or if WinHttpWebSocketReceive returns WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE.
///
///
/// pdwReasonLengthConsumed will never be greater than 123, so allocating buffer with at least 123 will guarantee that
/// ERROR_INSUFFICIENT_BUFFER will never be returned.
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpwebsocketqueryclosestatus WINHTTPAPI DWORD
// WinHttpWebSocketQueryCloseStatus( [in] HINTERNET hWebSocket, [out] USHORT *pusStatus, [out] PVOID pvReason, [in] DWORD dwReasonLength,
// [out] DWORD *pdwReasonLengthConsumed );
[DllImport(Lib_Winhttp, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpWebSocketQueryCloseStatus")]
public static extern Win32Error WinHttpWebSocketQueryCloseStatus(HINTERNET hWebSocket, out WINHTTP_WEB_SOCKET_CLOSE_STATUS pusStatus, [Out] IntPtr pvReason,
uint dwReasonLength, out uint pdwReasonLengthConsumed);
/// The WinHttpWebSocketReceive function receives data from a WebSocket connection.
///
/// Type: HINTERNET
/// Handle to a WebSocket.
///
///
/// Type: PVOID
/// Pointer to a buffer to receive the data.
///
///
/// Type: DWORD
/// Length of pvBuffer, in bytes.
///
///
/// Type: DWORD*
///
/// Pointer to a DWORD that receives the number of bytes read from the connection at the end of the operation. This is set only if
/// WinHttpWebSocketReceive returns NO_ERROR and the handle was opened in synchronous mode.
///
///
///
/// Type: WINHTTP_WEB_SOCKET_BUFFER_TYPE*
///
/// The type of a returned buffer. This is only set if WinHttpWebSocketReceive returns NO_ERROR and the handle was opened
/// in synchronous mode.
///
///
///
/// Type: DWORD
/// NO_ERROR on success. Otherwise an error code.
///
///
///
/// Description
///
/// -
/// ERROR_INVALID_OPERATION
/// A close or send is pending, or the receive channel has already been closed.
///
/// -
/// ERROR_INVALID_PARAMETER
/// A parameter is invalid.
///
/// -
/// ERROR_INVALID_SERVER_RESPONSE
/// Invalid data was received from the server.
///
/// -
/// ERROR_WINHTTP_OPERATION_CANCELLED
/// The operation was cancelled because WinHttpWebSocketClose was called to close the connection.
///
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpwebsocketreceive WINHTTPAPI DWORD
// WinHttpWebSocketReceive( [in] HINTERNET hWebSocket, [out] PVOID pvBuffer, [in] DWORD dwBufferLength, [out] DWORD *pdwBytesRead, [out]
// WINHTTP_WEB_SOCKET_BUFFER_TYPE *peBufferType );
[DllImport(Lib_Winhttp, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpWebSocketReceive")]
public static extern Win32Error WinHttpWebSocketReceive(HINTERNET hWebSocket, [Out] IntPtr pvBuffer, uint dwBufferLength,
out uint pdwBytesRead, out WINHTTP_WEB_SOCKET_BUFFER_TYPE peBufferType);
/// The WinHttpWebSocketSend function sends data over a WebSocket connection.
///
/// Type: HINTERNET
/// Handle to a websocket.
///
///
/// Type: WINHTTP_WEB_SOCKET_BUFFER_TYPE
/// Type of buffer.
///
///
/// Type: PVOID
/// Pointer to a buffer containing the data to send. Can be NULL only if dwBufferLength is 0.
///
///
/// Type: DWORD
/// Length of pvBuffer.
///
///
/// Type: DWORD
/// NO_ERROR on success. Otherwise an error code.
///
///
///
/// Description
///
/// -
/// ERROR_INVALID_OPERATION
/// A close or send is pending, or the send channel has already been closed.
///
/// -
/// ERROR_INVALID_PARAMETER
/// A parameter is invalid.
///
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpwebsocketsend WINHTTPAPI DWORD WinHttpWebSocketSend( [in]
// HINTERNET hWebSocket, [in] WINHTTP_WEB_SOCKET_BUFFER_TYPE eBufferType, [in] PVOID pvBuffer, [in] DWORD dwBufferLength );
[DllImport(Lib_Winhttp, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpWebSocketSend")]
public static extern Win32Error WinHttpWebSocketSend(HINTERNET hWebSocket, WINHTTP_WEB_SOCKET_BUFFER_TYPE eBufferType,
[In, Optional] IntPtr pvBuffer, [In, Optional] uint dwBufferLength);
///
/// The WinHttpWebSocketShutdown function sends a close frame to a WebSocket server to close the send channel, but leaves the
/// receive channel open.
///
///
/// Type: HINTERNET
/// Handle to a WebSocket.
///
///
/// Type: USHORT
/// A close status code. See WINHTTP_WEB_SOCKET_CLOSE_STATUS for possible values.
///
///
/// Type: PVOID
/// A detailed reason for the close.
///
///
/// Type: DWORD
/// The length of pvReason, in bytes.
/// If pvReason is NULL, this must be 0. This value must be within the range of 0 to 123.
///
///
/// Type: DWORD
/// With the following exception, all error codes indicate that the underlying TCP connection has been aborted.
///
///
///
/// Description
///
/// -
/// ERROR_IO_PENDING
/// The operation will complete asynchronously.
///
///
///
///
///
/// WinHttpWebSocketShutdown sends a close frame and prevents additional data from being sent over the WebSocket connection. It
/// does not close the receive channel. Use WinHttpWebSocketClose when you want to completely close the connection and prevent any
/// subsequent receive operations.
///
/// The application is responsible for receiving the close frame from the server (through regular receive operations).
///
/// After WinHttpWebSocketShutdown is called, the application can call WinHttpWebSocketClose if it does not want to receive a
/// close frame on its own and delegate it to the stack.
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpwebsocketshutdown WINHTTPAPI DWORD
// WinHttpWebSocketShutdown( [in] HINTERNET hWebSocket, [in] USHORT usStatus, [in, optional] PVOID pvReason, [in] DWORD dwReasonLength );
[DllImport(Lib_Winhttp, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpWebSocketShutdown")]
public static extern Win32Error WinHttpWebSocketShutdown(HINTERNET hWebSocket, WINHTTP_WEB_SOCKET_CLOSE_STATUS usStatus,
[In, Optional] IntPtr pvReason, [In, Optional] uint dwReasonLength);
/// The WinHttpWriteData function writes request data to an HTTP server.
///
/// Valid HINTERNET handle returned by WinHttpOpenRequest. Wait until WinHttpSendRequest has completed before calling this function.
///
///
/// Pointer to a buffer that contains the data to be sent to the server. Be sure that this buffer remains valid until after
/// WinHttpWriteData completes.
///
/// Unsigned long integer value that contains the number of bytes to be written to the file.
///
/// Pointer to an unsigned long integer variable that receives the number of bytes written to the buffer. The WinHttpWriteData
/// function sets this value to zero before doing any work or error checking. When using WinHTTP asynchronously, this parameter must be
/// set to NULL and retrieve the information in the callback function. Not doing so can cause a memory fault.
///
///
///
/// Returns TRUE if successful, or FALSE otherwise. For extended error information, call GetLastError. Among the error
/// codes returned are:
///
///
///
/// Error Code
/// 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
/// version 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_TIMEOUT
/// The request has timed out.
///
/// -
/// ERROR_NOT_ENOUGH_MEMORY
/// Not enough memory was available to complete the requested operation. (Windows error code)
///
///
///
///
///
/// 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, you can call GetLastError to get extended
/// error information. If this function returns TRUE, use the WINHTTP_CALLBACK_STATUS_WRITE_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 using WinHTTP asynchronously, always set the lpdwNumberOfBytesWritten parameter to NULL and
/// retrieve the bytes written in the callback function; otherwise, a memory fault can occur.
///
///
/// When the application is sending data, it can call WinHttpReceiveResponse to end the data transfer. If WinHttpCloseHandle is called,
/// then the data transfer is aborted.
///
///
/// If a status callback function has been installed with WinHttpSetStatusCallback, then those of the following notifications that have
/// been set in the dwNotificationFlags parameter of WinHttpSetStatusCallback indicate progress in sending data to the server:
///
///
/// -
/// WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
///
/// -
/// WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
///
/// -
/// WINHTTP_CALLBACK_STATUS_DATA_WRITTEN
///
/// -
/// WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
///
/// -
/// WINHTTP_CALLBACK_STATUS_REQUEST_SENT
///
/// -
/// WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE
///
///
///
/// Two issues can arise when attempting to POST (or PUT) data to proxies or servers that challenge using NTLM or Negotiate
/// authentication. First, these proxies or servers may send 401/407 challenges and close the connection before all the data can be
/// POST'ed, in which case not only does WinHttpWriteData fail, but also WinHTTP cannot handle the authentication challenges. NTLM
/// and Negotiate require that all authentication handshakes be exchanged on the same socket connection, so authentication fails if the
/// connection is broken prematurely.
///
///
/// Secondly, NTLM and Negotiate may require multiple handshakes to complete authentication, which requires data to be re-POST'ed for
/// each authentication legs. This can be very inefficient for large data uploads.
///
///
/// To work around these two issues, one solution is to send an idempotent warm-up request such as HEAD to the authenticating v-dir
/// first, handle the authentication challenges associated with this request, and only then POST data. As long as the same socket is
/// re-used to handle the POST'ing, no further authentication challenges should be encountered and all data can be uploaded at once.
/// Since an authenticated socket can only be reused for subsequent requests within the same session, the POST should go out in the same
/// socket as long as the socket is not pooled with concurrent requests competing for it.
///
/// Note For Windows XP and Windows 2000, see the Run-Time Requirements section of the WinHTTP start page.
/// Examples
///
/// This example shows code that writes data to an HTTP server. The server name supplied in the example, www.wingtiptoys.com, is
/// fictitious and must be replaced with the name of a server for which you have write access.
///
///
/// PCSTR pszData = "WinHttpWriteData Example"; DWORD dwBytesWritten = 0; BOOL bResults = FALSE; HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL; // Use WinHttpOpen to obtain a session handle. hSession = WinHttpOpen( L"A WinHTTP Example Program/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.wingtiptoys.com", INTERNET_DEFAULT_HTTP_PORT, 0); // Create an HTTP Request handle. if (hConnect) hRequest = WinHttpOpenRequest( hConnect, L"PUT", L"/writetst.txt", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); // Send a Request. if (hRequest) bResults = WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, (DWORD)strlen(pszData), 0); // Write data to the server. if (bResults) bResults = WinHttpWriteData( hRequest, pszData, (DWORD)strlen(pszData), &dwBytesWritten); // End the request. if (bResults) bResults = WinHttpReceiveResponse( hRequest, NULL); // 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);
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpwritedata BOOL WinHttpWriteData( [in] HINTERNET hRequest,
// [in] LPCVOID lpBuffer, [in] DWORD dwNumberOfBytesToWrite, [out] LPDWORD lpdwNumberOfBytesWritten );
[DllImport(Lib_Winhttp, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpWriteData")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WinHttpWriteData(HINTERNET hRequest, [In] IntPtr lpBuffer, uint dwNumberOfBytesToWrite, out uint lpdwNumberOfBytesWritten);
/// The WinHttpWriteData function writes request data to an HTTP server.
///
/// Valid HINTERNET handle returned by WinHttpOpenRequest. Wait until WinHttpSendRequest has completed before calling this function.
///
///
/// Pointer to a buffer that contains the data to be sent to the server. Be sure that this buffer remains valid until after
/// WinHttpWriteData completes.
///
/// Unsigned long integer value that contains the number of bytes to be written to the file.
///
/// Pointer to an unsigned long integer variable that receives the number of bytes written to the buffer. The WinHttpWriteData
/// function sets this value to zero before doing any work or error checking. When using WinHTTP asynchronously, this parameter must be
/// set to NULL and retrieve the information in the callback function. Not doing so can cause a memory fault.
///
///
///
/// Returns TRUE if successful, or FALSE otherwise. For extended error information, call GetLastError. Among the error
/// codes returned are:
///
///
///
/// Error Code
/// 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
/// version 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_TIMEOUT
/// The request has timed out.
///
/// -
/// ERROR_NOT_ENOUGH_MEMORY
/// Not enough memory was available to complete the requested operation. (Windows error code)
///
///
///
///
///
/// 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, you can call GetLastError to get extended
/// error information. If this function returns TRUE, use the WINHTTP_CALLBACK_STATUS_WRITE_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 using WinHTTP asynchronously, always set the lpdwNumberOfBytesWritten parameter to NULL and
/// retrieve the bytes written in the callback function; otherwise, a memory fault can occur.
///
///
/// When the application is sending data, it can call WinHttpReceiveResponse to end the data transfer. If WinHttpCloseHandle is called,
/// then the data transfer is aborted.
///
///
/// If a status callback function has been installed with WinHttpSetStatusCallback, then those of the following notifications that have
/// been set in the dwNotificationFlags parameter of WinHttpSetStatusCallback indicate progress in sending data to the server:
///
///
/// -
/// WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
///
/// -
/// WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
///
/// -
/// WINHTTP_CALLBACK_STATUS_DATA_WRITTEN
///
/// -
/// WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
///
/// -
/// WINHTTP_CALLBACK_STATUS_REQUEST_SENT
///
/// -
/// WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE
///
///
///
/// Two issues can arise when attempting to POST (or PUT) data to proxies or servers that challenge using NTLM or Negotiate
/// authentication. First, these proxies or servers may send 401/407 challenges and close the connection before all the data can be
/// POST'ed, in which case not only does WinHttpWriteData fail, but also WinHTTP cannot handle the authentication challenges. NTLM
/// and Negotiate require that all authentication handshakes be exchanged on the same socket connection, so authentication fails if the
/// connection is broken prematurely.
///
///
/// Secondly, NTLM and Negotiate may require multiple handshakes to complete authentication, which requires data to be re-POST'ed for
/// each authentication legs. This can be very inefficient for large data uploads.
///
///
/// To work around these two issues, one solution is to send an idempotent warm-up request such as HEAD to the authenticating v-dir
/// first, handle the authentication challenges associated with this request, and only then POST data. As long as the same socket is
/// re-used to handle the POST'ing, no further authentication challenges should be encountered and all data can be uploaded at once.
/// Since an authenticated socket can only be reused for subsequent requests within the same session, the POST should go out in the same
/// socket as long as the socket is not pooled with concurrent requests competing for it.
///
/// Note For Windows XP and Windows 2000, see the Run-Time Requirements section of the WinHTTP start page.
/// Examples
///
/// This example shows code that writes data to an HTTP server. The server name supplied in the example, www.wingtiptoys.com, is
/// fictitious and must be replaced with the name of a server for which you have write access.
///
///
/// PCSTR pszData = "WinHttpWriteData Example"; DWORD dwBytesWritten = 0; BOOL bResults = FALSE; HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL; // Use WinHttpOpen to obtain a session handle. hSession = WinHttpOpen( L"A WinHTTP Example Program/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.wingtiptoys.com", INTERNET_DEFAULT_HTTP_PORT, 0); // Create an HTTP Request handle. if (hConnect) hRequest = WinHttpOpenRequest( hConnect, L"PUT", L"/writetst.txt", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); // Send a Request. if (hRequest) bResults = WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, (DWORD)strlen(pszData), 0); // Write data to the server. if (bResults) bResults = WinHttpWriteData( hRequest, pszData, (DWORD)strlen(pszData), &dwBytesWritten); // End the request. if (bResults) bResults = WinHttpReceiveResponse( hRequest, NULL); // 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);
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpwritedata BOOL WinHttpWriteData( [in] HINTERNET hRequest,
// [in] LPCVOID lpBuffer, [in] DWORD dwNumberOfBytesToWrite, [out] LPDWORD lpdwNumberOfBytesWritten );
[DllImport(Lib_Winhttp, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winhttp.h", MSDNShortId = "NF:winhttp.WinHttpWriteData")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WinHttpWriteData(HINTERNET hRequest, [In] byte[] lpBuffer, int dwNumberOfBytesToWrite, out int lpdwNumberOfBytesWritten);
}