You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2387 lines
68 KiB
2387 lines
68 KiB
/*++
|
|
|
|
Copyright (c) 1994-98 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
options.cxx
|
|
|
|
Abstract:
|
|
|
|
Contains the Internet*Option APIs
|
|
|
|
Contents:
|
|
InternetQueryOptionA
|
|
InternetSetOptionA
|
|
WinHttpQueryOption
|
|
WinHttpSetOption
|
|
(FValidCacheHandleType)
|
|
|
|
Author:
|
|
|
|
Richard L Firth (rfirth) 02-Mar-1995
|
|
|
|
Environment:
|
|
|
|
Win32 user-mode DLL
|
|
|
|
Revision History:
|
|
|
|
02-Mar-1995 rfirth
|
|
Created
|
|
|
|
07-Mar-1995 madana
|
|
|
|
07-Jul-1998 Forked by akabir
|
|
|
|
--*/
|
|
|
|
#include <wininetp.h>
|
|
#include <perfdiag.hxx>
|
|
#include "msident.h"
|
|
|
|
//
|
|
// private macros
|
|
//
|
|
|
|
//
|
|
// IS_PER_THREAD_OPTION - options applicable to the thread (HINTERNET is NULL).
|
|
// Subset of IS_VALID_OPTION()
|
|
//
|
|
|
|
#define IS_PER_THREAD_OPTION(option) (( \
|
|
((option) == WINHTTP_OPTION_EXTENDED_ERROR) \
|
|
) ? TRUE : FALSE)
|
|
|
|
//
|
|
// IS_PER_PROCESS_OPTION - options applicable to the process (HINTERNET is NULL).
|
|
// Subset of IS_VALID_OPTION()
|
|
//
|
|
|
|
#define IS_PER_PROCESS_OPTION(option) \
|
|
(( ((option) == WINHTTP_OPTION_GET_DEBUG_INFO) \
|
|
|| ((option) == WINHTTP_OPTION_SET_DEBUG_INFO) \
|
|
|| ((option) == WINHTTP_OPTION_GET_HANDLE_COUNT) \
|
|
|| ((option) == WINHTTP_OPTION_PROXY) \
|
|
|| ((option) == WINHTTP_OPTION_VERSION) \
|
|
|| ((option) == WINHTTP_OPTION_HTTP_VERSION) \
|
|
|| ((option) == WINHTTP_OPTION_WORKER_THREAD_COUNT) \
|
|
) ? TRUE : FALSE)
|
|
|
|
//
|
|
// IS_DEBUG_OPTION - the set of debug-specific options
|
|
//
|
|
|
|
#define IS_DEBUG_OPTION(option) \
|
|
(( ((option) >= INTERNET_FIRST_DEBUG_OPTION) \
|
|
&& ((option) <= INTERNET_LAST_DEBUG_OPTION) \
|
|
) ? TRUE : FALSE)
|
|
|
|
//
|
|
// IS_VALID_OPTION - the set of known option values, for a HINTERNET, thread, or
|
|
// process. In the retail version, debug options are invalid
|
|
//
|
|
|
|
#if INET_DEBUG
|
|
|
|
#define IS_VALID_OPTION(option) \
|
|
(((((option) >= WINHTTP_FIRST_OPTION) \
|
|
&& ((option) <= WINHTTP_LAST_OPTION_INTERNAL)) \
|
|
|| IS_DEBUG_OPTION(option) \
|
|
) ? TRUE : FALSE)
|
|
|
|
#else
|
|
|
|
#define IS_VALID_OPTION(option) \
|
|
(((((option) >= WINHTTP_FIRST_OPTION) \
|
|
&& ((option) <= WINHTTP_LAST_OPTION_INTERNAL)) \
|
|
) ? TRUE : FALSE)
|
|
|
|
#endif // INET_DEBUG
|
|
|
|
//
|
|
// private prototypes
|
|
//
|
|
PRIVATE
|
|
BOOL
|
|
FValidCacheHandleType(
|
|
HINTERNET_HANDLE_TYPE hType
|
|
);
|
|
|
|
PRIVATE
|
|
VOID
|
|
InitIPCOList(LPINTERNET_PER_CONN_OPTION_LISTW plistW, LPINTERNET_PER_CONN_OPTION_LISTA plistA)
|
|
{
|
|
plistA->dwSize = sizeof(INTERNET_PER_CONN_OPTION_LISTA);
|
|
plistA->dwOptionCount = plistW->dwOptionCount;
|
|
if (plistW->pszConnection && *plistW->pszConnection)
|
|
{
|
|
SHUnicodeToAnsi(plistW->pszConnection, plistA->pszConnection, RAS_MaxEntryName + 1);
|
|
}
|
|
else
|
|
{
|
|
plistA->pszConnection = NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// functions
|
|
//
|
|
|
|
|
|
INTERNETAPI
|
|
BOOL
|
|
WINAPI
|
|
InternetQueryOptionA(
|
|
IN HINTERNET hInternet OPTIONAL,
|
|
IN DWORD dwOption,
|
|
OUT LPVOID lpBuffer OPTIONAL,
|
|
IN OUT LPDWORD lpdwBufferLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns information about various handle-specific variables
|
|
|
|
Arguments:
|
|
|
|
hInternet - handle of object for which information will be
|
|
returned
|
|
|
|
dwOption - the handle-specific WINHTTP_OPTION to query
|
|
|
|
lpBuffer - pointer to a buffer which will receive results
|
|
|
|
lpdwBufferLength - IN: number of bytes available in lpBuffer
|
|
OUT: number of bytes returned in lpBuffer
|
|
|
|
Return Value:
|
|
|
|
BOOL
|
|
Success - TRUE
|
|
|
|
Failure - FALSE. Call GetLastError() for more info:
|
|
ERROR_INVALID_HANDLE
|
|
hInternet does not identify a valid Internet handle
|
|
object
|
|
|
|
ERROR_WINHTTP_INTERNAL_ERROR
|
|
Shouldn't see this?
|
|
|
|
ERROR_INVALID_PARAMETER
|
|
One of the parameters was bad
|
|
|
|
ERROR_INSUFFICIENT_BUFFER
|
|
lpBuffer is not large enough to hold the requested
|
|
information; *lpdwBufferLength contains the number of
|
|
bytes needed
|
|
|
|
ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
|
|
The handle is the wrong type for the requested option
|
|
|
|
ERROR_WINHTTP_INVALID_OPTION
|
|
The option is unrecognized
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER((DBG_API,
|
|
Bool,
|
|
"InternetQueryOptionA",
|
|
"%#x, %s (%d), %#x, %#x [%d]",
|
|
hInternet,
|
|
InternetMapOption(dwOption),
|
|
dwOption,
|
|
lpBuffer,
|
|
lpdwBufferLength,
|
|
lpdwBufferLength
|
|
? (!IsBadReadPtr(lpdwBufferLength, sizeof(DWORD))
|
|
? *lpdwBufferLength
|
|
: 0)
|
|
: 0
|
|
));
|
|
|
|
DWORD error;
|
|
BOOL success;
|
|
HINTERNET_HANDLE_TYPE handleType = (HINTERNET_HANDLE_TYPE)0;
|
|
LPINTERNET_THREAD_INFO lpThreadInfo;
|
|
DWORD requiredSize = 0;
|
|
LPVOID lpSource = NULL;
|
|
DWORD dwValue;
|
|
DWORD_PTR dwPtrValue;
|
|
HINTERNET hObjectMapped = NULL;
|
|
BOOL isString = FALSE;
|
|
BOOL freeString = FALSE;
|
|
// INTERNET_DIAGNOSTIC_SOCKET_INFO socketInfo;
|
|
|
|
if (!GlobalDataInitialized) {
|
|
error = GlobalDataInitialize();
|
|
if (error != ERROR_SUCCESS) {
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
lpThreadInfo = InternetGetThreadInfo();
|
|
if (lpThreadInfo == NULL) {
|
|
error = ERROR_WINHTTP_INTERNAL_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
//
|
|
// validate parameters
|
|
//
|
|
|
|
INET_ASSERT(lpdwBufferLength);
|
|
|
|
if (!ARGUMENT_PRESENT(lpBuffer)) {
|
|
*lpdwBufferLength = 0;
|
|
}
|
|
|
|
//
|
|
// validate the handle and get its type
|
|
//
|
|
|
|
HINTERNET hOriginal;
|
|
|
|
hOriginal = hInternet;
|
|
if (ARGUMENT_PRESENT(hInternet)) {
|
|
|
|
//
|
|
// map the handle
|
|
//
|
|
|
|
error = MapHandleToAddress(hInternet, (LPVOID *)&hObjectMapped, FALSE);
|
|
if (error == ERROR_SUCCESS) {
|
|
hInternet = hObjectMapped;
|
|
error = RGetHandleType(hInternet, &handleType);
|
|
}
|
|
} else if (IS_PER_THREAD_OPTION(dwOption)) {
|
|
|
|
//
|
|
// this option updates the per-thread information block, so this is a
|
|
// good point at which to get it
|
|
//
|
|
|
|
if (lpThreadInfo != NULL) {
|
|
error = ERROR_SUCCESS;
|
|
} else {
|
|
|
|
DEBUG_PRINT(INET,
|
|
ERROR,
|
|
("InternetGetThreadInfo() returns NULL\n"
|
|
));
|
|
|
|
//
|
|
// we never expect this - ERROR_WINHTTP_SPANISH_INQUISITION
|
|
//
|
|
|
|
INET_ASSERT(FALSE);
|
|
|
|
error = ERROR_WINHTTP_INTERNAL_ERROR;
|
|
}
|
|
} else if (IS_PER_PROCESS_OPTION(dwOption)) {
|
|
error = ERROR_SUCCESS;
|
|
} else {
|
|
|
|
//
|
|
// catch any invalid options for the NULL handle. If the option is valid
|
|
// then it is incorrect for this handle type, otherwise its an invalid
|
|
// option, period
|
|
//
|
|
|
|
error = IS_VALID_OPTION(dwOption)
|
|
? ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
|
|
: ERROR_WINHTTP_INVALID_OPTION
|
|
;
|
|
}
|
|
|
|
//
|
|
// if the option and handle combination is valid then query the option value
|
|
//
|
|
|
|
if (error != ERROR_SUCCESS) {
|
|
goto quit;
|
|
}
|
|
|
|
HTTP_REQUEST_HANDLE_OBJECT* pReq;
|
|
switch(handleType)
|
|
{
|
|
case TypeHttpRequestHandle:
|
|
pReq = (HTTP_REQUEST_HANDLE_OBJECT*) hInternet;
|
|
break;
|
|
default:
|
|
pReq = NULL;
|
|
break;
|
|
}
|
|
|
|
// New fast path for request handle options.
|
|
|
|
if (dwOption > WINHTTP_OPTION_MASK)
|
|
{
|
|
dwOption &= WINHTTP_OPTION_MASK;
|
|
if (dwOption > MAX_INTERNET_STRING_OPTION)
|
|
error = ERROR_INVALID_PARAMETER;
|
|
else if (!pReq)
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
else
|
|
{
|
|
lpSource = pReq->GetProp (dwOption);
|
|
isString = TRUE;
|
|
error = ERROR_SUCCESS;
|
|
freeString = (lpSource != NULL);
|
|
goto copy;
|
|
}
|
|
goto quit;
|
|
}
|
|
|
|
// ensure SSL is loaded if this is an SSL related option
|
|
switch (dwOption)
|
|
{
|
|
case WINHTTP_OPTION_CLIENT_CERT_CONTEXT:
|
|
case WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT:
|
|
case WINHTTP_OPTION_SERVER_CERT_CONTEXT:
|
|
// Make sure SSL is loaded now
|
|
error = LoadSecurity();
|
|
if (ERROR_SUCCESS != error)
|
|
{
|
|
goto quit;
|
|
}
|
|
};
|
|
|
|
switch (dwOption) {
|
|
case WINHTTP_OPTION_CALLBACK:
|
|
requiredSize = sizeof(WINHTTP_STATUS_CALLBACK);
|
|
if (hInternet != NULL) {
|
|
error = RGetStatusCallback(hInternet,
|
|
(LPWINHTTP_STATUS_CALLBACK)&dwValue
|
|
);
|
|
lpSource = (LPVOID)&dwValue;
|
|
} else {
|
|
error = ERROR_INVALID_HANDLE;
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_RESOLVE_TIMEOUT:
|
|
case WINHTTP_OPTION_CONNECT_TIMEOUT:
|
|
case WINHTTP_OPTION_CONNECT_RETRIES:
|
|
case WINHTTP_OPTION_SEND_TIMEOUT:
|
|
case WINHTTP_OPTION_RECEIVE_TIMEOUT:
|
|
case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
|
|
requiredSize = sizeof(DWORD);
|
|
|
|
//
|
|
// remember hInternet in the INTERNET_THREAD_INFO then call
|
|
// GetTimeoutValue(). If hInternet refers to a valid Internet
|
|
// object handle, then the relevant timeout value will be
|
|
// returned from that, else we will return the global value
|
|
// corresponding to the requested option
|
|
//
|
|
|
|
InternetSetObjectHandle(hOriginal, hInternet);
|
|
dwValue = GetTimeoutValue(dwOption);
|
|
lpSource = (LPVOID)&dwValue;
|
|
break;
|
|
|
|
case WINHTTP_OPTION_REDIRECT_POLICY:
|
|
case WINHTTP_OPTION_AUTOLOGON_POLICY:
|
|
case WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS:
|
|
case WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE:
|
|
case WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE:
|
|
case WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE:
|
|
|
|
// For WinHttp, these options are per-handle, not per-process.
|
|
if (hInternet == NULL)
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
break;
|
|
}
|
|
|
|
switch (handleType)
|
|
{
|
|
case TypeInternetHandle:
|
|
|
|
//only error possible is in allocing memory for OPTIONAL_PARAMS struct
|
|
if (! ((INTERNET_HANDLE_OBJECT*)hObjectMapped)->GetDwordOption(dwOption, &dwValue) )
|
|
{
|
|
error = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
requiredSize = sizeof(DWORD);
|
|
lpSource = (LPVOID)&dwValue;
|
|
}
|
|
break;
|
|
|
|
case TypeHttpRequestHandle:
|
|
|
|
// no errors possible here
|
|
dwValue = ((HTTP_REQUEST_HANDLE_OBJECT*)hObjectMapped)->GetDwordOption(dwOption);
|
|
requiredSize = sizeof(DWORD);
|
|
lpSource = (LPVOID)&dwValue;
|
|
break;
|
|
|
|
default:
|
|
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_HANDLE_TYPE:
|
|
|
|
requiredSize = sizeof(dwValue);
|
|
switch (handleType)
|
|
{
|
|
case TypeInternetHandle:
|
|
dwValue = WINHTTP_HANDLE_TYPE_SESSION;
|
|
break;
|
|
|
|
case TypeHttpConnectHandle:
|
|
dwValue = WINHTTP_HANDLE_TYPE_CONNECT;
|
|
break;
|
|
|
|
case TypeHttpRequestHandle:
|
|
dwValue = WINHTTP_HANDLE_TYPE_REQUEST;
|
|
break;
|
|
|
|
default:
|
|
error = ERROR_WINHTTP_INTERNAL_ERROR;
|
|
break;
|
|
}
|
|
lpSource = (LPVOID)&dwValue;
|
|
break;
|
|
|
|
case WINHTTP_OPTION_CONTEXT_VALUE:
|
|
requiredSize = sizeof(DWORD_PTR);
|
|
error = RGetContext(hInternet, &dwPtrValue);
|
|
lpSource = (LPVOID)&dwPtrValue;
|
|
break;
|
|
|
|
case WINHTTP_OPTION_READ_BUFFER_SIZE:
|
|
case WINHTTP_OPTION_WRITE_BUFFER_SIZE:
|
|
|
|
if (pReq)
|
|
{
|
|
requiredSize = sizeof(DWORD);
|
|
error = ERROR_SUCCESS;
|
|
dwValue = pReq->GetBufferSize(dwOption);
|
|
lpSource = (LPVOID)&dwValue;
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_PARENT_HANDLE:
|
|
hInternet = ((HANDLE_OBJECT *)hInternet)->GetParent();
|
|
if (hInternet != NULL) {
|
|
hInternet = ((HANDLE_OBJECT *)hInternet)->GetPseudoHandle();
|
|
}
|
|
requiredSize = sizeof(hInternet);
|
|
lpSource = (LPVOID)&hInternet;
|
|
break;
|
|
|
|
case WINHTTP_OPTION_EXTENDED_ERROR:
|
|
requiredSize = sizeof(lpThreadInfo->dwMappedErrorCode);
|
|
lpSource = (LPVOID)&lpThreadInfo->dwMappedErrorCode;
|
|
break;
|
|
|
|
case WINHTTP_OPTION_SECURITY_FLAGS:
|
|
|
|
if (handleType != TypeHttpRequestHandle)
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
else
|
|
{
|
|
HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
|
|
|
|
requiredSize = sizeof(dwValue);
|
|
dwValue = 0;
|
|
lpSource = (LPVOID)&dwValue;
|
|
|
|
lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
|
|
|
|
dwValue = lphHttpRqst->GetSecureFlags();
|
|
|
|
DEBUG_PRINT(INET,
|
|
INFO,
|
|
("SECURITY_FLAGS: %X\n",
|
|
dwValue
|
|
));
|
|
|
|
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case WINHTTP_OPTION_URL:
|
|
|
|
//
|
|
// return the URL associated with the request handle. This may be
|
|
// different from the original URL due to redirections
|
|
//
|
|
|
|
if (pReq)
|
|
{
|
|
|
|
//
|
|
// only these handle types (retrieved object handles) can have
|
|
// associated URLs
|
|
//
|
|
|
|
lpSource = pReq->GetURL();
|
|
isString = TRUE;
|
|
|
|
INET_ASSERT(error == ERROR_SUCCESS);
|
|
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
|
|
case WINHTTP_OPTION_SECURITY_CONNECTION_INFO:
|
|
//
|
|
// Caller is expected to pass in an INTERNET_SECURITY_CONNECTION_INFO structure.
|
|
|
|
if (handleType != TypeHttpRequestHandle) {
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
} else if (*lpdwBufferLength < (DWORD)sizeof(INTERNET_SECURITY_CONNECTION_INFO)) {
|
|
requiredSize = sizeof(INTERNET_SECURITY_CONNECTION_INFO);
|
|
*lpdwBufferLength = requiredSize;
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
} else {
|
|
HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
|
|
LPINTERNET_SECURITY_CONNECTION_INFO lpSecConnInfo;
|
|
INTERNET_SECURITY_INFO ciInfo;
|
|
|
|
lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *)hInternet;
|
|
lpSecConnInfo = (LPINTERNET_SECURITY_CONNECTION_INFO)lpBuffer;
|
|
requiredSize = sizeof(INTERNET_SECURITY_CONNECTION_INFO);
|
|
|
|
if ((error = lphHttpRqst->GetSecurityInfo(&ciInfo)) == ERROR_SUCCESS) {
|
|
// Set up that data members in the structure passed in.
|
|
lpSecConnInfo->fSecure = TRUE;
|
|
|
|
lpSecConnInfo->dwProtocol = ciInfo.dwProtocol;
|
|
lpSecConnInfo->aiCipher = ciInfo.aiCipher;
|
|
lpSecConnInfo->dwCipherStrength = ciInfo.dwCipherStrength;
|
|
lpSecConnInfo->aiHash = ciInfo.aiHash;
|
|
lpSecConnInfo->dwHashStrength = ciInfo.dwHashStrength;
|
|
lpSecConnInfo->aiExch = ciInfo.aiExch;
|
|
lpSecConnInfo->dwExchStrength = ciInfo.dwExchStrength;
|
|
|
|
if (ciInfo.pCertificate)
|
|
{
|
|
WRAP_REVERT_USER_VOID((*g_pfnCertFreeCertificateContext),
|
|
GetRootHandle(lphHttpRqst)->GetSslSessionCache()->IsImpersonationEnabled(),
|
|
(ciInfo.pCertificate));
|
|
}
|
|
|
|
} else if (error == ERROR_WINHTTP_INTERNAL_ERROR) {
|
|
// This implies we are not secure.
|
|
error = ERROR_SUCCESS;
|
|
lpSecConnInfo->fSecure = FALSE;
|
|
}
|
|
|
|
lpSecConnInfo->dwSize = requiredSize;
|
|
*lpdwBufferLength = requiredSize;
|
|
}
|
|
|
|
goto quit;
|
|
|
|
|
|
case WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT:
|
|
|
|
//
|
|
// Allocates memory that caller is expected to free.
|
|
//
|
|
|
|
if (handleType != TypeHttpRequestHandle) {
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
} else if (*lpdwBufferLength < (DWORD)sizeof(INTERNET_CERTIFICATE_INFO)) {
|
|
requiredSize = sizeof(INTERNET_CERTIFICATE_INFO);
|
|
*lpdwBufferLength = requiredSize;
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
} else {
|
|
HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
|
|
INTERNET_SECURITY_INFO cInfo;
|
|
lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
|
|
requiredSize = sizeof(INTERNET_CERTIFICATE_INFO);
|
|
|
|
if( !(lphHttpRqst->GetOpenFlags() & WINHTTP_FLAG_SECURE))
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_STATE;
|
|
goto quit;
|
|
}
|
|
|
|
if (ERROR_SUCCESS == lphHttpRqst->GetSecurityInfo(&cInfo))
|
|
{
|
|
error = ConvertSecurityInfoIntoCertInfoStruct(&cInfo, (LPINTERNET_CERTIFICATE_INFO)lpBuffer, lpdwBufferLength);
|
|
if(cInfo.pCertificate)
|
|
{
|
|
WRAP_REVERT_USER_VOID((*g_pfnCertFreeCertificateContext),
|
|
GetRootHandle(lphHttpRqst)->GetSslSessionCache()->IsImpersonationEnabled(),
|
|
(cInfo.pCertificate));
|
|
}
|
|
goto quit;
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INVALID_OPERATION;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_SERVER_CERT_CONTEXT:
|
|
if (handleType != TypeHttpRequestHandle)
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
else if (*lpdwBufferLength < (DWORD)sizeof(PCCERT_CONTEXT))
|
|
{
|
|
requiredSize = sizeof(PCCERT_CONTEXT);
|
|
*lpdwBufferLength = requiredSize;
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
else
|
|
{
|
|
HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
|
|
INTERNET_SECURITY_INFO cInfo;
|
|
lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
|
|
requiredSize = sizeof(PCERT_CONTEXT);
|
|
|
|
if( !(lphHttpRqst->GetOpenFlags() & WINHTTP_FLAG_SECURE))
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_STATE;
|
|
goto quit;
|
|
}
|
|
|
|
if (lpBuffer)
|
|
{
|
|
if (ERROR_SUCCESS == lphHttpRqst->GetSecurityInfo(&cInfo))
|
|
{
|
|
// GetSecurityInfo calls CertDuplicateCertificateContext, so
|
|
// the client app should call CertFreeCertificateContext when
|
|
// finished in order to maintain the proper ref count.
|
|
*((PCCERT_CONTEXT *) lpBuffer) = cInfo.pCertificate;
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INVALID_OPERATION;
|
|
}
|
|
}
|
|
}
|
|
goto quit;
|
|
|
|
case WINHTTP_OPTION_SECURITY_KEY_BITNESS:
|
|
|
|
if (handleType != TypeHttpRequestHandle)
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
else
|
|
{
|
|
HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
|
|
INTERNET_SECURITY_INFO secInfo;
|
|
|
|
requiredSize = sizeof(dwValue);
|
|
dwValue = 0;
|
|
lpSource = (LPVOID)&dwValue;
|
|
|
|
lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
|
|
if (ERROR_SUCCESS != lphHttpRqst->GetSecurityInfo(&secInfo)) {
|
|
error = ERROR_INVALID_OPERATION;
|
|
} else {
|
|
dwValue = secInfo.dwCipherStrength;
|
|
WRAP_REVERT_USER_VOID((*g_pfnCertFreeCertificateContext),
|
|
GetRootHandle(lphHttpRqst)->GetSslSessionCache()->IsImpersonationEnabled(),
|
|
(secInfo.pCertificate));
|
|
|
|
INET_ASSERT (error == ERROR_SUCCESS);
|
|
|
|
DEBUG_PRINT(INET,
|
|
INFO,
|
|
("SECURITY_KEY_BITNESS: %X\n",
|
|
dwValue
|
|
));
|
|
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case WINHTTP_OPTION_PROXY:
|
|
if (!ARGUMENT_PRESENT(hInternet)) {
|
|
|
|
error = g_pGlobalProxyInfo->GetProxyStringInfo(lpBuffer, lpdwBufferLength);
|
|
requiredSize = *lpdwBufferLength;
|
|
goto quit;
|
|
|
|
} else if ((handleType == TypeInternetHandle) || (handleType == TypeHttpRequestHandle)) {
|
|
|
|
//
|
|
// GetProxyInfo() will return the data, or calculate the buffer
|
|
// length required
|
|
//
|
|
|
|
error = ((INTERNET_HANDLE_BASE *)hInternet)->GetProxyStringInfo(
|
|
lpBuffer,
|
|
lpdwBufferLength
|
|
);
|
|
requiredSize = *lpdwBufferLength;
|
|
goto quit;
|
|
} else {
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_VERSION:
|
|
requiredSize = sizeof(InternetVersionInfo);
|
|
lpSource = (LPVOID)&InternetVersionInfo;
|
|
break;
|
|
|
|
case WINHTTP_OPTION_USER_AGENT:
|
|
if (handleType == TypeInternetHandle) {
|
|
lpSource = ((INTERNET_HANDLE_OBJECT *)hInternet)->GetUserAgent();
|
|
isString = TRUE;
|
|
} else {
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_PASSPORT_COBRANDING_TEXT:
|
|
if (handleType == TypeHttpRequestHandle) {
|
|
AUTHCTX* pAuthCtx = ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->GetAuthCtx();
|
|
if (pAuthCtx && (pAuthCtx->GetSchemeType() == WINHTTP_AUTH_SCHEME_PASSPORT))
|
|
{
|
|
lpSource = ((PASSPORT_CTX*)pAuthCtx)->m_pszCbTxt;
|
|
isString = TRUE;
|
|
}
|
|
else
|
|
{
|
|
lpSource = NULL;
|
|
}
|
|
|
|
if (lpSource == NULL)
|
|
{
|
|
error = ERROR_WINHTTP_HEADER_NOT_FOUND;
|
|
}
|
|
} else {
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_PASSPORT_COBRANDING_URL:
|
|
if (handleType == TypeHttpRequestHandle) {
|
|
AUTHCTX* pAuthCtx = ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->GetAuthCtx();
|
|
if (pAuthCtx && (pAuthCtx->GetSchemeType() == WINHTTP_AUTH_SCHEME_PASSPORT))
|
|
{
|
|
lpSource = ((PASSPORT_CTX*)pAuthCtx)->m_pszCbUrl;
|
|
isString = TRUE;
|
|
}
|
|
else
|
|
{
|
|
lpSource = NULL;
|
|
}
|
|
|
|
if (lpSource == NULL)
|
|
{
|
|
error = ERROR_WINHTTP_HEADER_NOT_FOUND;
|
|
}
|
|
} else {
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_PASSPORT_RETURN_URL:
|
|
if (handleType == TypeHttpRequestHandle) {
|
|
if (((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->m_lpszRetUrl)
|
|
{
|
|
lpSource = ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->m_lpszRetUrl;
|
|
UrlUnescapeA((LPSTR)lpSource, NULL, NULL, URL_UNESCAPE_INPLACE);
|
|
isString = TRUE;
|
|
}
|
|
else
|
|
{
|
|
lpSource = NULL;
|
|
}
|
|
|
|
if (lpSource == NULL)
|
|
{
|
|
error = ERROR_WINHTTP_HEADER_NOT_FOUND;
|
|
}
|
|
} else {
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_REQUEST_PRIORITY:
|
|
if (handleType == TypeHttpRequestHandle) {
|
|
requiredSize = sizeof(dwValue);
|
|
dwValue = ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->GetPriority();
|
|
lpSource = (LPVOID)&dwValue;
|
|
} else {
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_HTTP_VERSION:
|
|
requiredSize = sizeof(HttpVersionInfo);
|
|
lpSource = (LPVOID)&HttpVersionInfo;
|
|
break;
|
|
|
|
//case WINHTTP_OPTION_DIAGNOSTIC_SOCKET_INFO:
|
|
|
|
// //
|
|
// // internal option
|
|
// //
|
|
|
|
// if (pReq) {
|
|
// requiredSize = sizeof(socketInfo);
|
|
// lpSource = (LPVOID)&socketInfo;
|
|
|
|
// socketInfo.Socket = pReq->GetSocket();
|
|
// socketInfo.SourcePort = pReq->GetSourcePort();
|
|
// socketInfo.DestPort = pReq->GetDestPort();
|
|
// socketInfo.Flags = (pReq->IsSocketFromGlobalKeepAlivePool()
|
|
// ? IDSI_FLAG_KEEP_ALIVE : 0)
|
|
// | (pReq->IsSecure()
|
|
// ? IDSI_FLAG_SECURE : 0)
|
|
// | (pReq->IsRequestUsingProxy()
|
|
// ? IDSI_FLAG_PROXY : 0)
|
|
// | (pReq->IsTunnel()
|
|
// ? IDSI_FLAG_TUNNEL : 0)
|
|
// | (pReq->IsSocketAuthenticated()
|
|
// ? IDSI_FLAG_AUTHENTICATED : 0);
|
|
// } else {
|
|
// error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
// }
|
|
// break;
|
|
|
|
case WINHTTP_OPTION_MAX_CONNS_PER_SERVER:
|
|
case WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER:
|
|
if (hInternet)
|
|
{
|
|
if (handleType == TypeInternetHandle)
|
|
{
|
|
requiredSize = sizeof(dwValue);
|
|
dwValue = 0;
|
|
lpSource = (LPVOID)&dwValue;
|
|
dwValue = ((INTERNET_HANDLE_OBJECT *)hInternet)->GetMaxConnectionsPerServer(dwOption);
|
|
}
|
|
else
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
else
|
|
error = ERROR_INVALID_OPERATION;
|
|
break;
|
|
|
|
case WINHTTP_OPTION_WORKER_THREAD_COUNT:
|
|
|
|
requiredSize = sizeof(DWORD);
|
|
dwValue = g_cNumIOCPThreads;
|
|
lpSource = (LPVOID)&dwValue;
|
|
break;
|
|
|
|
#if INET_DEBUG
|
|
|
|
case WINHTTP_OPTION_GET_DEBUG_INFO:
|
|
error = InternetGetDebugInfo((LPINTERNET_DEBUG_INFO)lpBuffer,
|
|
lpdwBufferLength
|
|
);
|
|
|
|
//
|
|
// everything updated, so quit without going through common buffer
|
|
// processing
|
|
//
|
|
|
|
goto quit;
|
|
break;
|
|
|
|
case WINHTTP_OPTION_GET_HANDLE_COUNT:
|
|
requiredSize = sizeof(DWORD);
|
|
dwValue = InternetHandleCount();
|
|
lpSource = (LPVOID)&dwValue;
|
|
break;
|
|
|
|
#endif // INET_DEBUG
|
|
|
|
default:
|
|
requiredSize = 0;
|
|
error = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// if we have a buffer and enough space, then copy the data
|
|
//
|
|
|
|
copy:
|
|
if (error == ERROR_SUCCESS) {
|
|
|
|
//
|
|
// if we are returning a string, calculate the amount of space
|
|
// required to hold it
|
|
//
|
|
|
|
if (isString) {
|
|
if (lpSource != NULL) {
|
|
requiredSize = lstrlen((LPCSTR)lpSource) + 1;
|
|
} else {
|
|
|
|
//
|
|
// option string is NULL: return an empty string
|
|
//
|
|
|
|
lpSource = "";
|
|
requiredSize = 1;
|
|
freeString = FALSE;
|
|
}
|
|
}
|
|
|
|
INET_ASSERT(lpSource != NULL);
|
|
|
|
if ((*lpdwBufferLength >= requiredSize)
|
|
&& ARGUMENT_PRESENT(lpBuffer)) {
|
|
memcpy(lpBuffer, lpSource, requiredSize);
|
|
if (isString) {
|
|
|
|
//
|
|
// string copied successfully. Returned length is string
|
|
// length, not buffer length, i.e. drop 1 for '\0'
|
|
//
|
|
|
|
--requiredSize;
|
|
}
|
|
} else {
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
if (freeString)
|
|
{
|
|
SecureZeroMemory(lpSource, requiredSize);
|
|
FREE_MEMORY(lpSource);
|
|
}
|
|
}
|
|
|
|
quit:
|
|
|
|
//
|
|
// return the amount the app needs to supply, or the amount of data in the
|
|
// buffer, depending on success/failure status
|
|
//
|
|
|
|
*lpdwBufferLength = requiredSize;
|
|
|
|
if (hObjectMapped != NULL) {
|
|
DereferenceObject((LPVOID)hObjectMapped);
|
|
}
|
|
|
|
done:
|
|
|
|
if (error == ERROR_SUCCESS) {
|
|
success = TRUE;
|
|
|
|
IF_DEBUG(API) {
|
|
|
|
if (isString) {
|
|
|
|
DEBUG_PRINT_API(API,
|
|
INFO,
|
|
("returning %q (%d chars)\n",
|
|
lpBuffer,
|
|
requiredSize
|
|
));
|
|
|
|
} else {
|
|
|
|
DEBUG_DUMP_API(API,
|
|
"option data:\n",
|
|
lpBuffer,
|
|
requiredSize
|
|
);
|
|
|
|
}
|
|
}
|
|
} else {
|
|
|
|
DEBUG_ERROR(API, error);
|
|
|
|
IF_DEBUG(API) {
|
|
|
|
if (error == ERROR_INSUFFICIENT_BUFFER) {
|
|
|
|
DEBUG_PRINT_API(API,
|
|
INFO,
|
|
("*lpdwBufferLength (%#x)= %d\n",
|
|
lpdwBufferLength,
|
|
*lpdwBufferLength
|
|
));
|
|
|
|
}
|
|
}
|
|
|
|
SetLastError(error);
|
|
success = FALSE;
|
|
}
|
|
|
|
DEBUG_LEAVE(success);
|
|
|
|
return success;
|
|
}
|
|
|
|
|
|
INTERNETAPI
|
|
BOOL
|
|
WINAPI
|
|
WinHttpQueryOption(
|
|
IN HINTERNET hInternet OPTIONAL,
|
|
IN DWORD dwOption,
|
|
OUT LPVOID lpBuffer OPTIONAL,
|
|
IN OUT LPDWORD lpdwBufferLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
description-of-function.
|
|
|
|
Arguments:
|
|
|
|
hInternet -
|
|
|
|
dwOption -
|
|
|
|
lpBuffer -
|
|
|
|
lpdwBufferLength -
|
|
|
|
Return Value:
|
|
|
|
BOOL
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER_API((DBG_API,
|
|
Bool,
|
|
"WinHttpQueryOption",
|
|
"%#x, %s (%d), %#x, %#x [%d]",
|
|
hInternet,
|
|
InternetMapOption(dwOption),
|
|
dwOption,
|
|
lpBuffer,
|
|
lpdwBufferLength,
|
|
lpdwBufferLength
|
|
? (!IsBadReadPtr(lpdwBufferLength, sizeof(DWORD))
|
|
? *lpdwBufferLength
|
|
: 0)
|
|
: 0
|
|
));
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
BOOL fResult = FALSE;
|
|
MEMORYPACKET mpBuffer;
|
|
|
|
if (!lpdwBufferLength
|
|
|| IsBadWritePtr(lpdwBufferLength, sizeof(*lpdwBufferLength))
|
|
|| (lpBuffer && *lpdwBufferLength && IsBadWritePtr(lpBuffer, *lpdwBufferLength)) )
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
|
|
switch (dwOption)
|
|
{
|
|
case WINHTTP_OPTION_USERNAME:
|
|
case WINHTTP_OPTION_PASSWORD:
|
|
case WINHTTP_OPTION_URL:
|
|
case WINHTTP_OPTION_USER_AGENT:
|
|
case WINHTTP_OPTION_PROXY_USERNAME:
|
|
case WINHTTP_OPTION_PROXY_PASSWORD:
|
|
case WINHTTP_OPTION_PASSPORT_COBRANDING_TEXT:
|
|
case WINHTTP_OPTION_PASSPORT_COBRANDING_URL:
|
|
case WINHTTP_OPTION_PASSPORT_RETURN_URL:
|
|
if (lpBuffer)
|
|
{
|
|
mpBuffer.dwAlloc = mpBuffer.dwSize = *lpdwBufferLength;
|
|
ALLOC_BYTES(mpBuffer.psStr, mpBuffer.dwAlloc*sizeof(CHAR));
|
|
if (!mpBuffer.psStr)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
}
|
|
fResult = InternetQueryOptionA(hInternet,
|
|
dwOption,
|
|
(LPVOID)mpBuffer.psStr,
|
|
&mpBuffer.dwSize
|
|
);
|
|
if (fResult)
|
|
{
|
|
*lpdwBufferLength = sizeof(WCHAR) *
|
|
MultiByteToWideChar(CP_ACP, 0, mpBuffer.psStr, mpBuffer.dwSize + 1, NULL, 0);
|
|
|
|
if (*lpdwBufferLength <= mpBuffer.dwAlloc && lpBuffer)
|
|
{
|
|
MultiByteToWideChar(CP_ACP, 0, mpBuffer.psStr, mpBuffer.dwSize+1,
|
|
(LPWSTR)lpBuffer, *lpdwBufferLength);
|
|
(*lpdwBufferLength)-=sizeof(WCHAR);
|
|
}
|
|
else
|
|
{
|
|
fResult = FALSE;
|
|
dwErr = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (GetLastError()==ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
*lpdwBufferLength = mpBuffer.dwSize*sizeof(WCHAR);
|
|
}
|
|
}
|
|
|
|
switch(dwOption)
|
|
{
|
|
case WINHTTP_OPTION_USERNAME:
|
|
case WINHTTP_OPTION_PASSWORD:
|
|
case WINHTTP_OPTION_PROXY_USERNAME:
|
|
case WINHTTP_OPTION_PROXY_PASSWORD:
|
|
ZERO_MEMORY_ALLOC(mpBuffer);
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_PROXY:
|
|
{
|
|
WINHTTP_PROXY_INFOW * pInfo = (WINHTTP_PROXY_INFOW *) lpBuffer;
|
|
|
|
union
|
|
{
|
|
WINHTTP_PROXY_INFOA InfoA;
|
|
char Buffer[1024];
|
|
};
|
|
|
|
char * pBuffer = NULL;
|
|
DWORD dwBufferLen = sizeof(Buffer);
|
|
bool fFreeBuffer = false;
|
|
|
|
if (IsBadWritePtr(pInfo, sizeof(WINHTTP_PROXY_INFOW)) ||
|
|
(*lpdwBufferLength < sizeof(WINHTTP_PROXY_INFOW)))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
fResult = InternetQueryOptionA(hInternet, WINHTTP_OPTION_PROXY,
|
|
(void *) &Buffer,
|
|
&dwBufferLen);
|
|
|
|
if (!fResult && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
|
|
{
|
|
pBuffer = New char[dwBufferLen];
|
|
|
|
if (pBuffer)
|
|
{
|
|
fFreeBuffer = true;
|
|
|
|
fResult = InternetQueryOptionA(hInternet, WINHTTP_OPTION_PROXY,
|
|
(void *) pBuffer,
|
|
&dwBufferLen);
|
|
}
|
|
else
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
if (fResult)
|
|
{
|
|
pInfo->dwAccessType = InfoA.dwAccessType;
|
|
|
|
dwErr = AsciiToWideChar_UsingGlobalAlloc(InfoA.lpszProxy,
|
|
&(pInfo->lpszProxy));
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
dwErr = AsciiToWideChar_UsingGlobalAlloc(InfoA.lpszProxyBypass,
|
|
&(pInfo->lpszProxyBypass));
|
|
|
|
if ((dwErr != ERROR_SUCCESS) && (pInfo->lpszProxy != NULL))
|
|
{
|
|
GlobalFree(pInfo->lpszProxy);
|
|
pInfo->lpszProxy = NULL;
|
|
}
|
|
}
|
|
|
|
fResult = (dwErr == ERROR_SUCCESS);
|
|
}
|
|
|
|
if (fFreeBuffer)
|
|
{
|
|
delete [] pBuffer;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_ENABLETRACING:
|
|
{
|
|
if(hInternet)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
BOOL *pInfo = (BOOL *)lpBuffer;
|
|
if (IsBadWritePtr(pInfo, sizeof(BOOL)) ||
|
|
(*lpdwBufferLength < sizeof(BOOL)))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
*pInfo = CTracer::IsTracingEnabled();
|
|
fResult = TRUE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
fResult = InternetQueryOptionA(hInternet,
|
|
dwOption,
|
|
lpBuffer,
|
|
lpdwBufferLength
|
|
);
|
|
}
|
|
|
|
cleanup:
|
|
if (dwErr!=ERROR_SUCCESS)
|
|
{
|
|
SetLastError(dwErr);
|
|
DEBUG_ERROR(INET, dwErr);
|
|
}
|
|
DEBUG_LEAVE_API(fResult);
|
|
return fResult;
|
|
}
|
|
|
|
|
|
INTERNETAPI
|
|
BOOL
|
|
WINAPI
|
|
InternetSetOptionA(
|
|
IN HINTERNET hInternet OPTIONAL,
|
|
IN DWORD dwOption,
|
|
IN LPVOID lpBuffer,
|
|
IN DWORD dwBufferLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets a handle-specific variable, or a per-thread variable
|
|
|
|
Arguments:
|
|
|
|
hInternet - handle of object for which information will be set,
|
|
or NULL if the option defines a per-thread variable
|
|
|
|
dwOption - the handle-specific WINHTTP_OPTION to set
|
|
|
|
lpBuffer - pointer to a buffer containing value to set
|
|
|
|
dwBufferLength - size of lpBuffer
|
|
|
|
Return Value:
|
|
|
|
BOOL
|
|
Success - TRUE
|
|
|
|
Failure - FALSE. Call GetLastError() for more info:
|
|
ERROR_INVALID_HANDLE
|
|
hInternet does not identify a valid Internet handle
|
|
object
|
|
|
|
ERROR_WINHTTP_INTERNAL_ERROR
|
|
Shouldn't see this?
|
|
|
|
ERROR_INVALID_PARAMETER
|
|
One of the parameters was bad
|
|
|
|
ERROR_WINHTTP_INVALID_OPTION
|
|
The requested option cannot be set
|
|
|
|
ERROR_WINHTTP_OPTION_NOT_SETTABLE
|
|
Can't set this option, only query it
|
|
|
|
ERROR_INSUFFICIENT_BUFFER
|
|
The dwBufferLength parameter is incorrect for the
|
|
expected type of the option
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER((DBG_API,
|
|
Bool,
|
|
"InternetSetOptionA",
|
|
"%#x, %s (%d), %#x [%#x], %d",
|
|
hInternet,
|
|
InternetMapOption(dwOption),
|
|
dwOption,
|
|
lpBuffer,
|
|
lpBuffer
|
|
? (!IsBadReadPtr(lpBuffer, sizeof(DWORD))
|
|
? *(LPDWORD)lpBuffer
|
|
: 0)
|
|
: 0,
|
|
dwBufferLength
|
|
));
|
|
|
|
DWORD error;
|
|
BOOL success = TRUE;
|
|
HINTERNET_HANDLE_TYPE handleType = (HINTERNET_HANDLE_TYPE)0;
|
|
LPINTERNET_THREAD_INFO lpThreadInfo;
|
|
DWORD requiredSize;
|
|
HINTERNET hObjectMapped = NULL;
|
|
|
|
INET_ASSERT(dwBufferLength != 0);
|
|
|
|
if (!GlobalDataInitialized) {
|
|
error = GlobalDataInitialize();
|
|
if (error != ERROR_SUCCESS) {
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
//
|
|
// validate the handle and get its type
|
|
//
|
|
|
|
if (ARGUMENT_PRESENT(hInternet)) {
|
|
|
|
//
|
|
// map the handle
|
|
//
|
|
|
|
error = MapHandleToAddress(hInternet, (LPVOID *)&hObjectMapped, FALSE);
|
|
if (error == ERROR_SUCCESS) {
|
|
hInternet = hObjectMapped;
|
|
error = RGetHandleType(hInternet, &handleType);
|
|
}
|
|
} else if (IS_PER_THREAD_OPTION(dwOption)) {
|
|
|
|
//
|
|
// this option updates the per-thread information block, so this is a
|
|
// good point at which to get it
|
|
//
|
|
|
|
lpThreadInfo = InternetGetThreadInfo();
|
|
if (lpThreadInfo != NULL) {
|
|
error = ERROR_SUCCESS;
|
|
} else {
|
|
|
|
DEBUG_PRINT(INET,
|
|
ERROR,
|
|
("InternetGetThreadInfo() returns NULL\n"
|
|
));
|
|
|
|
//
|
|
// we never expect this - ERROR_WINHTTP_SPANISH_INQUISITION
|
|
//
|
|
|
|
INET_ASSERT(FALSE);
|
|
|
|
error = ERROR_WINHTTP_INTERNAL_ERROR;
|
|
}
|
|
} else if (IS_PER_PROCESS_OPTION(dwOption)) {
|
|
error = ERROR_SUCCESS;
|
|
} else {
|
|
|
|
//
|
|
// catch any invalid options for the NULL handle. If the option is valid
|
|
// then it is incorrect for this handle type, otherwise its an invalid
|
|
// option, period
|
|
//
|
|
|
|
error = IS_VALID_OPTION(dwOption)
|
|
? ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
|
|
: ERROR_WINHTTP_INVALID_OPTION
|
|
;
|
|
}
|
|
|
|
if (error != ERROR_SUCCESS) {
|
|
goto quit;
|
|
}
|
|
|
|
HTTP_REQUEST_HANDLE_OBJECT *pReq;
|
|
|
|
switch (handleType)
|
|
{
|
|
case TypeHttpRequestHandle:
|
|
pReq = (HTTP_REQUEST_HANDLE_OBJECT*) hInternet;
|
|
break;
|
|
default:
|
|
pReq = NULL;
|
|
break;
|
|
}
|
|
|
|
// New fast path for request handle options.
|
|
|
|
if (dwOption > WINHTTP_OPTION_MASK)
|
|
{
|
|
dwOption &= WINHTTP_OPTION_MASK;
|
|
if (dwOption > MAX_INTERNET_STRING_OPTION)
|
|
error = ERROR_INVALID_PARAMETER;
|
|
else if (!pReq)
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
else if (pReq->SetProp (dwOption, (LPSTR) lpBuffer))
|
|
error = ERROR_SUCCESS;
|
|
else
|
|
error = ERROR_WINHTTP_INTERNAL_ERROR;
|
|
|
|
goto quit;
|
|
}
|
|
|
|
|
|
//
|
|
// if the option and handle combination is valid then set the option value
|
|
//
|
|
|
|
switch (dwOption) {
|
|
case WINHTTP_OPTION_CALLBACK:
|
|
case WINHTTP_OPTION_HANDLE_TYPE:
|
|
|
|
// these options cannot be set by this function
|
|
error = ERROR_WINHTTP_OPTION_NOT_SETTABLE;
|
|
break;
|
|
|
|
case WINHTTP_OPTION_RESOLVE_TIMEOUT:
|
|
case WINHTTP_OPTION_CONNECT_TIMEOUT:
|
|
case WINHTTP_OPTION_CONNECT_RETRIES:
|
|
case WINHTTP_OPTION_SEND_TIMEOUT:
|
|
case WINHTTP_OPTION_RECEIVE_TIMEOUT:
|
|
case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
|
|
case WINHTTP_OPTION_REDIRECT_POLICY:
|
|
case WINHTTP_OPTION_AUTOLOGON_POLICY:
|
|
case WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS:
|
|
case WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE:
|
|
case WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE:
|
|
case WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE:
|
|
requiredSize = sizeof(DWORD);
|
|
if (dwBufferLength != requiredSize)
|
|
{
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
break;
|
|
}
|
|
|
|
// For WinHttp, these options are per-handle, not per-process.
|
|
if (hInternet == NULL)
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Do per-option parameter validation where applicable
|
|
//
|
|
error = ERROR_SUCCESS;
|
|
switch(dwOption)
|
|
{
|
|
case WINHTTP_OPTION_REDIRECT_POLICY:
|
|
if( WINHTTP_OPTION_REDIRECT_POLICY_LAST < (*(LPDWORD)lpBuffer))
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
}
|
|
break;
|
|
case WINHTTP_OPTION_AUTOLOGON_POLICY:
|
|
if( WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH < (*(LPDWORD)lpBuffer))
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
}
|
|
break;
|
|
};
|
|
if(error != ERROR_SUCCESS)
|
|
break;
|
|
|
|
// we have a non-NULL context handle: the app wants to set specific
|
|
// protocol timeouts
|
|
switch (handleType)
|
|
{
|
|
case TypeInternetHandle:
|
|
|
|
//only error possible is in allocing memory for OPTIONAL_PARAMS struct
|
|
if (! ((INTERNET_HANDLE_OBJECT*)hObjectMapped)->SetDwordOption(dwOption, *(LPDWORD)lpBuffer) )
|
|
{
|
|
error = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
break;
|
|
|
|
case TypeHttpRequestHandle:
|
|
|
|
// no errors possible here
|
|
((HTTP_REQUEST_HANDLE_OBJECT*)hObjectMapped)->SetDwordOption(dwOption, *(LPDWORD)lpBuffer);
|
|
break;
|
|
|
|
default:
|
|
|
|
// any other handle type (?) cannot have timeouts set for it
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_CONTEXT_VALUE:
|
|
|
|
//
|
|
// BUGBUG - can't change context if async operation is pending
|
|
//
|
|
|
|
if (dwBufferLength == sizeof(LPVOID)) {
|
|
error = RSetContext(hInternet, *((DWORD_PTR *) lpBuffer));
|
|
} else {
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_READ_BUFFER_SIZE:
|
|
case WINHTTP_OPTION_WRITE_BUFFER_SIZE:
|
|
if (pReq)
|
|
{
|
|
if (dwBufferLength == sizeof(DWORD))
|
|
{
|
|
DWORD bufferSize;
|
|
|
|
bufferSize = *(LPDWORD)lpBuffer;
|
|
if (bufferSize > 0)
|
|
{
|
|
pReq->SetBufferSize(dwOption, bufferSize);
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
else // the read/write buffer size cannot be set to 0
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_CLIENT_CERT_CONTEXT:
|
|
|
|
if (handleType != TypeHttpRequestHandle)
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
else if (dwBufferLength < sizeof(CERT_CONTEXT))
|
|
{
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
else
|
|
{
|
|
HTTP_REQUEST_HANDLE_OBJECT *pRequest =
|
|
(HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
|
|
CERT_CONTEXT_ARRAY* pArray = NULL;
|
|
|
|
if( !(pRequest->GetOpenFlags() & WINHTTP_FLAG_SECURE))
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_STATE;
|
|
break;
|
|
}
|
|
|
|
pArray = pRequest->GetCertContextArray();
|
|
if (!pArray)
|
|
{
|
|
pArray = New CERT_CONTEXT_ARRAY(GetRootHandle(pRequest)->
|
|
GetSslSessionCache()->
|
|
IsImpersonationEnabled());
|
|
pRequest->SetCertContextArray(pArray);
|
|
}
|
|
|
|
if (!pArray)
|
|
error = ERROR_NOT_ENOUGH_MEMORY;
|
|
else
|
|
{
|
|
pArray->Reset();
|
|
pArray->AddCertContext((PCCERT_CONTEXT) lpBuffer);
|
|
pArray->SelectCertContext(0);
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_SECURITY_FLAGS:
|
|
|
|
if (handleType != TypeHttpRequestHandle)
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
else if (dwBufferLength < sizeof(DWORD))
|
|
{
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
else
|
|
{
|
|
HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
|
|
|
|
lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
|
|
|
|
lphHttpRqst->SetSecureFlags(*(LPDWORD)lpBuffer);
|
|
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
|
|
break;
|
|
|
|
case WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH:
|
|
if (handleType != TypeInternetHandle)
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
else
|
|
{
|
|
DWORD dwFlags = *(LPDWORD)lpBuffer;
|
|
|
|
if (dwFlags == WINHTTP_DISABLE_PASSPORT_AUTH)
|
|
{
|
|
((INTERNET_HANDLE_OBJECT *)hInternet)->DisableTweener();
|
|
}
|
|
else
|
|
{
|
|
if (dwFlags & WINHTTP_ENABLE_PASSPORT_AUTH)
|
|
{
|
|
((INTERNET_HANDLE_OBJECT *)hInternet)->EnableTweener();
|
|
}
|
|
|
|
if (dwFlags & WINHTTP_DISABLE_PASSPORT_KEYRING)
|
|
{
|
|
((INTERNET_HANDLE_OBJECT *)hInternet)->DisableKeyring();
|
|
}
|
|
|
|
if (dwFlags & WINHTTP_ENABLE_PASSPORT_KEYRING)
|
|
{
|
|
((INTERNET_HANDLE_OBJECT *)hInternet)->EnableKeyring();
|
|
}
|
|
}
|
|
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
|
|
break;
|
|
|
|
case WINHTTP_OPTION_SECURE_PROTOCOLS:
|
|
|
|
if (handleType != TypeInternetHandle)
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
else if (dwBufferLength < sizeof(DWORD))
|
|
{
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
else if (*(LPDWORD)lpBuffer & ~(WINHTTP_FLAG_SECURE_PROTOCOL_ALL))
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
((INTERNET_HANDLE_OBJECT *)hInternet)->SetSecureProtocols(
|
|
*(LPDWORD)lpBuffer);
|
|
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
|
|
break;
|
|
|
|
case WINHTTP_OPTION_PROXY:
|
|
if ((handleType == TypeInternetHandle) || (handleType == TypeHttpRequestHandle))
|
|
{
|
|
WINHTTP_PROXY_INFOA * lpInfo = (WINHTTP_PROXY_INFOA *) lpBuffer;
|
|
|
|
//
|
|
// validate parameters
|
|
//
|
|
|
|
if (dwBufferLength != sizeof(*lpInfo))
|
|
{
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
else if (!((lpInfo->dwAccessType == WINHTTP_ACCESS_TYPE_DEFAULT_PROXY)
|
|
|| (lpInfo->dwAccessType == WINHTTP_ACCESS_TYPE_NO_PROXY)
|
|
|| (lpInfo->dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY))
|
|
|| ((lpInfo->dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY)
|
|
&& ((lpInfo->lpszProxy == NULL) || (*lpInfo->lpszProxy == '\0'))))
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
error = ((INTERNET_HANDLE_BASE *)hInternet)->SetProxyInfo(
|
|
lpInfo->dwAccessType,
|
|
lpInfo->lpszProxy,
|
|
lpInfo->lpszProxyBypass
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_USER_AGENT:
|
|
if (*(LPSTR)lpBuffer == '\0') {
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
} else {
|
|
if ((handleType == TypeInternetHandle) || (handleType == TypeHttpRequestHandle))
|
|
{
|
|
((INTERNET_HANDLE_BASE *)hInternet)->SetUserAgent((LPSTR)lpBuffer);
|
|
} else {
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_PASSPORT_SIGN_OUT:
|
|
if (*(LPSTR)lpBuffer == '\0') {
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
} else {
|
|
if (handleType == TypeInternetHandle)
|
|
{
|
|
INTERNET_HANDLE_OBJECT* pInternet = ((INTERNET_HANDLE_OBJECT*)hInternet);
|
|
PP_CONTEXT hPP = pInternet->GetPPContext();
|
|
|
|
pInternet->ClearPassportCookies((LPSTR)lpBuffer);
|
|
|
|
if (hPP != NULL)
|
|
{
|
|
::PP_Logout(hPP, 0);
|
|
}
|
|
} else {
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_REQUEST_PRIORITY:
|
|
if (handleType == TypeHttpRequestHandle) {
|
|
if (dwBufferLength == sizeof(LONG)) {
|
|
((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->
|
|
SetPriority(*(LPLONG)lpBuffer);
|
|
} else {
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
} else {
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_HTTP_VERSION:
|
|
if (dwBufferLength == sizeof(HTTP_VERSION_INFO))
|
|
{
|
|
HTTP_VERSION_INFO* pVersionInfo = (LPHTTP_VERSION_INFO)lpBuffer;
|
|
if (pVersionInfo->dwMajorVersion != 1
|
|
|| (pVersionInfo->dwMinorVersion != 0
|
|
&& pVersionInfo->dwMajorVersion != 1))
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
HttpVersionInfo = *(LPHTTP_VERSION_INFO)lpBuffer;
|
|
}
|
|
} else {
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_DISABLE_FEATURE:
|
|
|
|
if (handleType == TypeHttpRequestHandle)
|
|
{
|
|
HTTP_REQUEST_HANDLE_OBJECT *pRequest =
|
|
(HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
|
|
|
|
DWORD dwDisable = *((LPDWORD) lpBuffer);
|
|
|
|
if (dwDisable & WINHTTP_DISABLE_KEEP_ALIVE)
|
|
{
|
|
DWORD dwFlags = pRequest->GetOpenFlags();
|
|
dwFlags &= ~INTERNET_FLAG_KEEP_CONNECTION;
|
|
pRequest->SetOpenFlags (dwFlags);
|
|
}
|
|
if (dwDisable & WINHTTP_DISABLE_REDIRECTS)
|
|
{
|
|
pRequest->SetDwordOption( WINHTTP_OPTION_REDIRECT_POLICY, WINHTTP_OPTION_REDIRECT_POLICY_NEVER);
|
|
}
|
|
if (dwDisable & WINHTTP_DISABLE_COOKIES)
|
|
{
|
|
DWORD dwFlags = pRequest->GetOpenFlags();
|
|
dwFlags |= INTERNET_FLAG_NO_COOKIES;
|
|
pRequest->SetOpenFlags (dwFlags);
|
|
}
|
|
if (dwDisable & WINHTTP_DISABLE_AUTHENTICATION)
|
|
{
|
|
DWORD dwFlags = pRequest->GetOpenFlags();
|
|
dwFlags |= INTERNET_FLAG_NO_AUTH;
|
|
pRequest->SetOpenFlags (dwFlags);
|
|
}
|
|
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
else if (dwBufferLength < sizeof(DWORD))
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
|
|
case WINHTTP_OPTION_ENABLE_FEATURE:
|
|
|
|
if (dwBufferLength < sizeof(DWORD))
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else if (handleType == TypeHttpRequestHandle)
|
|
{
|
|
HTTP_REQUEST_HANDLE_OBJECT *pRequest =
|
|
(HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
|
|
DWORD dwEnable = *((LPDWORD) lpBuffer);
|
|
|
|
// This one feature is only allowed to be set on the
|
|
// session handle
|
|
if (dwEnable & WINHTTP_ENABLE_SSL_REVERT_IMPERSONATION)
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
pRequest->SetEnableFlags(*((LPDWORD) lpBuffer));
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
else if (handleType == TypeInternetHandle)
|
|
{
|
|
INTERNET_HANDLE_OBJECT *pInternet =
|
|
(INTERNET_HANDLE_OBJECT *) hInternet;
|
|
DWORD dwEnable = *((LPDWORD) lpBuffer);
|
|
|
|
// Consider the call invalid if anything else is being
|
|
// set on the session handle.
|
|
if (dwEnable & ~WINHTTP_ENABLE_SSL_REVERT_IMPERSONATION)
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
// Error code could indicate that a request handle
|
|
// has already been created, resulting in this call failing.
|
|
error = pInternet->SetSslImpersonationLevel(
|
|
(*((LPDWORD) lpBuffer) & WINHTTP_ENABLE_SSL_REVERT_IMPERSONATION) ? FALSE : TRUE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
|
|
case WINHTTP_OPTION_CODEPAGE:
|
|
if ((hInternet == NULL) || (handleType == TypeHttpRequestHandle))
|
|
{
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
else
|
|
{
|
|
if (dwBufferLength == sizeof(DWORD))
|
|
{
|
|
((INTERNET_HANDLE_BASE *)hInternet)->SetCodePage(*(LPDWORD)lpBuffer);
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_MAX_CONNS_PER_SERVER:
|
|
case WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER:
|
|
if (handleType == TypeInternetHandle)
|
|
{
|
|
if (dwBufferLength == sizeof(DWORD))
|
|
{
|
|
((INTERNET_HANDLE_OBJECT *)hInternet)->SetMaxConnectionsPerServer(dwOption, *(DWORD *)lpBuffer);
|
|
}
|
|
else
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
else
|
|
error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
break;
|
|
|
|
case WINHTTP_OPTION_WORKER_THREAD_COUNT:
|
|
|
|
if (dwBufferLength < sizeof(DWORD))
|
|
{
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
else
|
|
{
|
|
if (!g_cNumIOCPThreads)
|
|
{
|
|
g_cNumIOCPThreads = *(LPDWORD)lpBuffer;
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_WINHTTP_OPTION_NOT_SETTABLE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
#if INET_DEBUG
|
|
case WINHTTP_OPTION_SET_DEBUG_INFO:
|
|
error = InternetSetDebugInfo((LPINTERNET_DEBUG_INFO)lpBuffer,
|
|
dwBufferLength
|
|
);
|
|
break;
|
|
|
|
#endif // INET_DEBUG
|
|
|
|
default:
|
|
|
|
//
|
|
// this option is not recognized
|
|
//
|
|
|
|
error = ERROR_WINHTTP_INVALID_OPTION;
|
|
}
|
|
|
|
quit:
|
|
|
|
if (hObjectMapped != NULL) {
|
|
DereferenceObject((LPVOID)hObjectMapped);
|
|
}
|
|
|
|
done:
|
|
|
|
if (error != ERROR_SUCCESS) {
|
|
|
|
DEBUG_ERROR(API, error);
|
|
|
|
SetLastError(error);
|
|
success = FALSE;
|
|
}
|
|
|
|
DEBUG_LEAVE(success);
|
|
|
|
return success;
|
|
}
|
|
|
|
#define CHECK_MODIFY_TIMEOUT(nTimeout) \
|
|
{ \
|
|
if (nTimeout <= 0) \
|
|
{ \
|
|
if (nTimeout == 0) \
|
|
{ \
|
|
nTimeout = (int)INFINITE; \
|
|
} \
|
|
else if (nTimeout < -1) \
|
|
{ \
|
|
dwError = ERROR_INVALID_PARAMETER; \
|
|
goto quit; \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
INTERNETAPI
|
|
BOOL
|
|
WINAPI
|
|
WinHttpSetTimeouts(
|
|
IN HINTERNET hInternet, // Session/Request handle.
|
|
IN int nResolveTimeout,
|
|
IN int nConnectTimeout,
|
|
IN int nSendTimeout,
|
|
IN int nReceiveTimeout
|
|
)
|
|
{
|
|
DEBUG_ENTER_API((DBG_API,
|
|
Bool,
|
|
"WinHttpSetTimeouts",
|
|
"%#x, %d, %d, %d, %d",
|
|
hInternet,
|
|
nResolveTimeout,
|
|
nConnectTimeout,
|
|
nSendTimeout,
|
|
nReceiveTimeout
|
|
));
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
BOOL bRetval = FALSE;
|
|
HINTERNET_HANDLE_TYPE handleType;
|
|
HINTERNET hObjectMapped = NULL;
|
|
|
|
if (!hInternet)
|
|
{
|
|
dwError = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
goto quit;
|
|
}
|
|
|
|
CHECK_MODIFY_TIMEOUT(nResolveTimeout);
|
|
CHECK_MODIFY_TIMEOUT(nConnectTimeout);
|
|
CHECK_MODIFY_TIMEOUT(nSendTimeout);
|
|
CHECK_MODIFY_TIMEOUT(nReceiveTimeout);
|
|
|
|
dwError = MapHandleToAddress(hInternet, (LPVOID *)&hObjectMapped, FALSE);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
{
|
|
goto quit;
|
|
}
|
|
|
|
dwError = RGetHandleType(hObjectMapped, &handleType);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
{
|
|
goto quit;
|
|
}
|
|
|
|
switch(handleType)
|
|
{
|
|
case TypeInternetHandle:
|
|
|
|
//only error possible is in allocing memory for OPTIONAL_PARAMS struct
|
|
bRetval = ((INTERNET_HANDLE_OBJECT*)hObjectMapped)->SetTimeouts(
|
|
nResolveTimeout, nConnectTimeout, nSendTimeout, nReceiveTimeout);
|
|
if (!bRetval)
|
|
{
|
|
dwError = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto quit;
|
|
}
|
|
break;
|
|
|
|
case TypeHttpRequestHandle:
|
|
|
|
// no errors possible here
|
|
bRetval = ((HTTP_REQUEST_HANDLE_OBJECT*)hObjectMapped)->SetTimeouts(
|
|
nResolveTimeout, nConnectTimeout, nSendTimeout, nReceiveTimeout);
|
|
INET_ASSERT(bRetval);
|
|
break;
|
|
|
|
default:
|
|
|
|
// any other handle type cannot have timeouts set for it
|
|
dwError = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
break;
|
|
}
|
|
|
|
quit:
|
|
|
|
if (hObjectMapped)
|
|
{
|
|
DereferenceObject((LPVOID)hObjectMapped);
|
|
}
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
{
|
|
::SetLastError(dwError);
|
|
INET_ASSERT(!bRetval);
|
|
}
|
|
|
|
DEBUG_LEAVE_API(bRetval);
|
|
return bRetval;
|
|
}
|
|
|
|
|
|
INTERNETAPI
|
|
BOOL
|
|
WINAPI
|
|
WinHttpSetOption(
|
|
IN HINTERNET hInternet OPTIONAL,
|
|
IN DWORD dwOption,
|
|
IN LPVOID lpBuffer,
|
|
IN DWORD dwBufferLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
description-of-function.
|
|
|
|
Arguments:
|
|
|
|
hInternet -
|
|
|
|
dwOption -
|
|
|
|
lpBuffer -
|
|
|
|
dwBufferLength -
|
|
|
|
Return Value:
|
|
|
|
BOOL
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER2_API((DBG_API,
|
|
Bool,
|
|
"WinHttpSetOption",
|
|
"%#x, %s (%d), %#x [%#x], %d",
|
|
hInternet,
|
|
InternetMapOption(dwOption),
|
|
dwOption,
|
|
lpBuffer,
|
|
lpBuffer
|
|
? (!IsBadReadPtr(lpBuffer, sizeof(DWORD))
|
|
? *(LPDWORD)lpBuffer
|
|
: 0)
|
|
: 0,
|
|
dwBufferLength
|
|
));
|
|
|
|
TRACE_ENTER2_API((DBG_API,
|
|
Bool,
|
|
"WinHttpSetOption",
|
|
hInternet,
|
|
"%#x, %s (%d), %#x [%#x], %d",
|
|
hInternet,
|
|
InternetMapOption(dwOption),
|
|
dwOption,
|
|
lpBuffer,
|
|
lpBuffer
|
|
? (!IsBadReadPtr(lpBuffer, sizeof(DWORD))
|
|
? *(LPDWORD)lpBuffer
|
|
: 0)
|
|
: 0,
|
|
dwBufferLength
|
|
));
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
MEMORYPACKET mpBuffer;
|
|
BOOL fResult = FALSE;
|
|
|
|
//
|
|
// validate parameters
|
|
//
|
|
|
|
if ((dwBufferLength == 0) || IsBadReadPtr(lpBuffer, dwBufferLength))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
|
|
switch (dwOption)
|
|
{
|
|
case WINHTTP_OPTION_USERNAME:
|
|
case WINHTTP_OPTION_PASSWORD:
|
|
case WINHTTP_OPTION_URL:
|
|
case WINHTTP_OPTION_USER_AGENT:
|
|
case WINHTTP_OPTION_PROXY_USERNAME:
|
|
case WINHTTP_OPTION_PROXY_PASSWORD:
|
|
case WINHTTP_OPTION_PASSPORT_SIGN_OUT:
|
|
ALLOC_MB((LPWSTR)lpBuffer, dwBufferLength, mpBuffer);
|
|
if (!mpBuffer.psStr)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
UNICODE_TO_ANSI((LPWSTR)lpBuffer, mpBuffer);
|
|
fResult = InternetSetOptionA(hInternet,
|
|
dwOption,
|
|
mpBuffer.psStr,
|
|
mpBuffer.dwSize
|
|
);
|
|
|
|
switch(dwOption)
|
|
{
|
|
case WINHTTP_OPTION_USERNAME:
|
|
case WINHTTP_OPTION_PASSWORD:
|
|
case WINHTTP_OPTION_PROXY_USERNAME:
|
|
case WINHTTP_OPTION_PROXY_PASSWORD:
|
|
ZERO_MEMORY_ALLOC(mpBuffer);
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_PROXY:
|
|
{
|
|
WINHTTP_PROXY_INFOW * pInfo = (WINHTTP_PROXY_INFOW *) lpBuffer;
|
|
WINHTTP_PROXY_INFOA InfoA;
|
|
|
|
if (IsBadReadPtr(pInfo, sizeof(WINHTTP_PROXY_INFOW)) || (dwBufferLength < sizeof(WINHTTP_PROXY_INFOW)))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
InfoA.dwAccessType = pInfo->dwAccessType;
|
|
|
|
dwErr = WideCharToAscii(pInfo->lpszProxy, &InfoA.lpszProxy);
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
dwErr = WideCharToAscii(pInfo->lpszProxyBypass, &InfoA.lpszProxyBypass);
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
fResult = InternetSetOptionA(hInternet, WINHTTP_OPTION_PROXY, &InfoA, sizeof(InfoA));
|
|
|
|
if (InfoA.lpszProxyBypass)
|
|
{
|
|
delete [] InfoA.lpszProxyBypass;
|
|
}
|
|
}
|
|
|
|
if (InfoA.lpszProxy)
|
|
{
|
|
delete [] InfoA.lpszProxy;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WINHTTP_OPTION_ENABLETRACING:
|
|
{
|
|
if(hInternet)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
BOOL *pInfo = (BOOL *)lpBuffer;
|
|
if (IsBadReadPtr(pInfo, sizeof(BOOL)) ||
|
|
(dwBufferLength < sizeof(BOOL)))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
if( *pInfo)
|
|
{
|
|
fResult = CTracer::GlobalTraceInit( TRUE);
|
|
if( fResult != FALSE)
|
|
CTracer::EnableTracing();
|
|
}
|
|
else
|
|
{
|
|
CTracer::DisableTracing();
|
|
fResult = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
fResult = InternetSetOptionA(hInternet,
|
|
dwOption,
|
|
lpBuffer,
|
|
dwBufferLength
|
|
);
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if (dwErr!=ERROR_SUCCESS)
|
|
{
|
|
SetLastError(dwErr);
|
|
DEBUG_ERROR(INET, dwErr);
|
|
}
|
|
DEBUG_LEAVE_API(fResult);
|
|
return fResult;
|
|
}
|
|
|
|
|
|
|
|
PRIVATE
|
|
BOOL
|
|
FValidCacheHandleType(
|
|
HINTERNET_HANDLE_TYPE hType
|
|
)
|
|
{
|
|
return ((hType != TypeInternetHandle) &&
|
|
(hType != TypeHttpConnectHandle));
|
|
}
|
|
|
|
#ifdef ENABLE_DEBUG
|
|
|
|
#define CASE_OF(constant) case constant: return # constant
|
|
|
|
LPSTR
|
|
InternetMapOption(
|
|
IN DWORD Option
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert WINHTTP_OPTION_ value to symbolic name
|
|
|
|
Arguments:
|
|
|
|
Option - to map
|
|
|
|
Return Value:
|
|
|
|
LPSTR - pointer to symbolic name, or "?" if unknown
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (Option) {
|
|
CASE_OF(WINHTTP_OPTION_CALLBACK);
|
|
CASE_OF(WINHTTP_OPTION_RESOLVE_TIMEOUT);
|
|
CASE_OF(WINHTTP_OPTION_CONNECT_TIMEOUT);
|
|
CASE_OF(WINHTTP_OPTION_CONNECT_RETRIES);
|
|
CASE_OF(WINHTTP_OPTION_SEND_TIMEOUT);
|
|
CASE_OF(WINHTTP_OPTION_RECEIVE_TIMEOUT);
|
|
CASE_OF(WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT);
|
|
CASE_OF(WINHTTP_OPTION_HANDLE_TYPE);
|
|
CASE_OF(WINHTTP_OPTION_READ_BUFFER_SIZE);
|
|
CASE_OF(WINHTTP_OPTION_WRITE_BUFFER_SIZE);
|
|
CASE_OF(WINHTTP_OPTION_PARENT_HANDLE);
|
|
CASE_OF(WINHTTP_OPTION_EXTENDED_ERROR);
|
|
CASE_OF(WINHTTP_OPTION_USERNAME);
|
|
CASE_OF(WINHTTP_OPTION_PASSWORD);
|
|
CASE_OF(WINHTTP_OPTION_SECURITY_FLAGS);
|
|
CASE_OF(WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT);
|
|
CASE_OF(WINHTTP_OPTION_URL);
|
|
CASE_OF(WINHTTP_OPTION_SECURITY_KEY_BITNESS);
|
|
CASE_OF(WINHTTP_OPTION_PROXY);
|
|
CASE_OF(WINHTTP_OPTION_VERSION);
|
|
CASE_OF(WINHTTP_OPTION_USER_AGENT);
|
|
CASE_OF(WINHTTP_OPTION_PROXY_USERNAME);
|
|
CASE_OF(WINHTTP_OPTION_PROXY_PASSWORD);
|
|
CASE_OF(WINHTTP_OPTION_CONTEXT_VALUE);
|
|
CASE_OF(WINHTTP_OPTION_CLIENT_CERT_CONTEXT);
|
|
CASE_OF(WINHTTP_OPTION_REQUEST_PRIORITY);
|
|
CASE_OF(WINHTTP_OPTION_HTTP_VERSION);
|
|
CASE_OF(WINHTTP_OPTION_SECURITY_CONNECTION_INFO);
|
|
// CASE_OF(WINHTTP_OPTION_DIAGNOSTIC_SOCKET_INFO);
|
|
CASE_OF(WINHTTP_OPTION_SERVER_CERT_CONTEXT);
|
|
}
|
|
return "?";
|
|
}
|
|
|
|
#endif // ENABLE_DEBUG
|
|
|