|
|
/*++
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
|