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.
3215 lines
99 KiB
3215 lines
99 KiB
/*++
|
|
|
|
Copyright (c) 1994-98 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
options.cxx
|
|
|
|
Abstract:
|
|
|
|
Contains the Internet*Option APIs
|
|
|
|
Contents:
|
|
InternetQueryOptionA
|
|
InternetSetOptionA
|
|
InternetSetOptionExA
|
|
InternetQueryOptionW
|
|
InternetSetOptionW
|
|
InternetSetOptionExW
|
|
(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 "inetapiu.h"
|
|
#include "autodial.h"
|
|
#include "msident.h"
|
|
#include "secinit.h"
|
|
|
|
|
|
extern HANDLE g_hDialEvent;
|
|
|
|
//
|
|
// 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) == INTERNET_OPTION_SERVER_ERROR_CALLBACK) \
|
|
// || ((option) == INTERNET_OPTION_ASYNC_ID) \
|
|
// || ((option) == INTERNET_OPTION_EXTENDED_ERROR) \
|
|
// ) ? TRUE : FALSE)
|
|
|
|
#define IS_PER_THREAD_OPTION(option) \
|
|
(( ((option) == INTERNET_OPTION_ASYNC_ID) \
|
|
|| ((option) == INTERNET_OPTION_EXTENDED_ERROR) \
|
|
|| ((option) == INTERNET_OPTION_PER_CONNECTION_OPTION) \
|
|
) ? 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) == INTERNET_OPTION_GET_DEBUG_INFO) \
|
|
|| ((option) == INTERNET_OPTION_SET_DEBUG_INFO) \
|
|
|| ((option) == INTERNET_OPTION_GET_HANDLE_COUNT) \
|
|
|| ((option) == INTERNET_OPTION_CONNECT_TIMEOUT) \
|
|
|| ((option) == INTERNET_OPTION_CONNECT_RETRIES) \
|
|
|| ((option) == INTERNET_OPTION_CONNECT_BACKOFF) \
|
|
|| ((option) == INTERNET_OPTION_SEND_TIMEOUT) \
|
|
|| ((option) == INTERNET_OPTION_RECEIVE_TIMEOUT) \
|
|
|| ((option) == INTERNET_OPTION_DATA_SEND_TIMEOUT) \
|
|
|| ((option) == INTERNET_OPTION_DATA_RECEIVE_TIMEOUT) \
|
|
|| ((option) == INTERNET_OPTION_FROM_CACHE_TIMEOUT) \
|
|
|| ((option) == INTERNET_OPTION_REFRESH) \
|
|
|| ((option) == INTERNET_OPTION_PROXY) \
|
|
|| ((option) == INTERNET_OPTION_SETTINGS_CHANGED) \
|
|
|| ((option) == INTERNET_OPTION_PROXY_SETTINGS_CHANGED) \
|
|
|| ((option) == INTERNET_OPTION_VERSION) \
|
|
|| ((option) == INTERNET_OPTION_END_BROWSER_SESSION) \
|
|
|| ((option) == INTERNET_OPTION_RESET_URLCACHE_SESSION) \
|
|
|| ((option) == INTERNET_OPTION_OFFLINE_TIMEOUT) \
|
|
|| ((option) == INTERNET_OPTION_LINE_STATE) \
|
|
|| ((option) == INTERNET_OPTION_IDLE_STATE) \
|
|
|| ((option) == INTERNET_OPTION_OFFLINE_SEMANTICS) \
|
|
|| ((option) == INTERNET_OPTION_HTTP_VERSION) \
|
|
|| ((option) == INTERNET_OPTION_BYPASS_EDITED_ENTRY) \
|
|
|| ((option) == INTERNET_OPTION_MAX_CONNS_PER_SERVER) \
|
|
|| ((option) == INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER) \
|
|
|| ((option) == INTERNET_OPTION_DIGEST_AUTH_UNLOAD) \
|
|
|| ((option) == INTERNET_OPTION_IDENTITY) \
|
|
|| ((option) == INTERNET_OPTION_REMOVE_IDENTITY) \
|
|
|| ((option) == INTERNET_OPTION_ALTER_IDENTITY) \
|
|
|| ((option) == INTERNET_OPTION_SUPPRESS_BEHAVIOR) \
|
|
|| ((option) == INTERNET_OPTION_PER_CONNECTION_OPTION) \
|
|
|| ((option) == INTERNET_OPTION_AUTODIAL_CONNECTION) \
|
|
|| ((option) == INTERNET_OPTION_AUTODIAL_MODE) \
|
|
|| ((option) == INTERNET_OPTION_USERNAME) \
|
|
|| ((option) == INTERNET_OPTION_PASSWORD) \
|
|
|| ((option) == INTERNET_OPTION_HIBERNATE_INACTIVE_WORKER_THREADS) \
|
|
|| ((option) == INTERNET_OPTION_ACTIVATE_WORKER_THREADS) \
|
|
|| ((option) == INTERNET_OPTION_RESTORE_WORKER_THREAD_DEFAULTS) \
|
|
) ? 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) >= INTERNET_FIRST_OPTION) \
|
|
&& ((option) <= INTERNET_LAST_OPTION_INTERNAL)) \
|
|
|| IS_DEBUG_OPTION(option) \
|
|
) ? TRUE : FALSE)
|
|
|
|
#else
|
|
|
|
#define IS_VALID_OPTION(option) \
|
|
(((((option) >= INTERNET_FIRST_OPTION) \
|
|
&& ((option) <= INTERNET_LAST_OPTION_INTERNAL)) \
|
|
) ? TRUE : FALSE)
|
|
|
|
#endif // INET_DEBUG
|
|
|
|
//
|
|
// IS_CONNECT_HANDLE_TYPE - TRUE if handle type contains INTERNET_CONNECT_HANDLE_OBJECT
|
|
//
|
|
|
|
#define IS_CONNECT_HANDLE_TYPE(handleType) \
|
|
((handleType == TypeHttpRequestHandle) \
|
|
|| (handleType == TypeHttpConnectHandle) \
|
|
|| (handleType == TypeFtpConnectHandle) \
|
|
|| (handleType == TypeFtpFileHandle) \
|
|
|| (handleType == TypeFtpFindHandle) \
|
|
|| (handleType == TypeFtpFileHandleHtml) \
|
|
|| (handleType == TypeFtpFindHandleHtml) \
|
|
|| (handleType == TypeGopherConnectHandle) \
|
|
|| (handleType == TypeGopherFileHandle) \
|
|
|| (handleType == TypeGopherFindHandle) \
|
|
|| (handleType == TypeGopherFileHandleHtml) \
|
|
|| (handleType == TypeGopherFindHandleHtml))
|
|
|
|
//
|
|
// 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) 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 INTERNET_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_INTERNET_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_INTERNET_INCORRECT_HANDLE_TYPE
|
|
The handle is the wrong type for the requested option
|
|
|
|
ERROR_INTERNET_INVALID_OPTION
|
|
The option is unrecognized
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER_API((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;
|
|
LPINTERNET_THREAD_INFO lpThreadInfo;
|
|
DWORD requiredSize = 0;
|
|
LPVOID lpSource;
|
|
DWORD dwValue;
|
|
DWORD_PTR dwPtrValue;
|
|
HANDLE hValue;
|
|
HINTERNET hObjectMapped = NULL;
|
|
INTERNET_CONNECT_HANDLE_OBJECT * lphRequest;
|
|
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_INTERNET_INTERNAL_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
//
|
|
// validate parameters
|
|
//
|
|
|
|
if (!ARGUMENT_PRESENT(lpdwBufferLength)) {
|
|
error = ERROR_INVALID_PARAMETER;
|
|
goto done;
|
|
}
|
|
|
|
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 *)&hInternet, FALSE);
|
|
if (error == ERROR_SUCCESS) {
|
|
hObjectMapped = hInternet;
|
|
lphRequest = (INTERNET_CONNECT_HANDLE_OBJECT *)hInternet;
|
|
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_INTERNET_SPANISH_INQUISITION
|
|
//
|
|
|
|
INET_ASSERT(FALSE);
|
|
|
|
error = ERROR_INTERNET_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_INTERNET_INCORRECT_HANDLE_TYPE
|
|
: ERROR_INTERNET_INVALID_OPTION
|
|
;
|
|
}
|
|
|
|
//
|
|
// if the option and handle combination is valid then query the option value
|
|
//
|
|
|
|
if (error != ERROR_SUCCESS) {
|
|
goto quit;
|
|
}
|
|
switch (dwOption) {
|
|
case INTERNET_OPTION_CALLBACK:
|
|
requiredSize = sizeof(INTERNET_STATUS_CALLBACK);
|
|
if (hInternet != NULL) {
|
|
error = RGetStatusCallback(hInternet,
|
|
(LPINTERNET_STATUS_CALLBACK)&dwValue
|
|
);
|
|
lpSource = (LPVOID)&dwValue;
|
|
} else {
|
|
error = ERROR_INVALID_HANDLE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_CONNECT_TIMEOUT:
|
|
case INTERNET_OPTION_CONNECT_RETRIES:
|
|
case INTERNET_OPTION_CONNECT_BACKOFF:
|
|
case INTERNET_OPTION_SEND_TIMEOUT:
|
|
case INTERNET_OPTION_RECEIVE_TIMEOUT:
|
|
case INTERNET_OPTION_DATA_SEND_TIMEOUT:
|
|
case INTERNET_OPTION_DATA_RECEIVE_TIMEOUT:
|
|
case INTERNET_OPTION_FROM_CACHE_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 INTERNET_OPTION_HANDLE_TYPE:
|
|
requiredSize = sizeof(dwValue);
|
|
switch (handleType) {
|
|
case TypeInternetHandle:
|
|
dwValue = INTERNET_HANDLE_TYPE_INTERNET;
|
|
break;
|
|
|
|
case TypeFtpConnectHandle:
|
|
dwValue = INTERNET_HANDLE_TYPE_CONNECT_FTP;
|
|
break;
|
|
|
|
case TypeFtpFindHandle:
|
|
dwValue = INTERNET_HANDLE_TYPE_FTP_FIND;
|
|
break;
|
|
|
|
case TypeFtpFindHandleHtml:
|
|
dwValue = INTERNET_HANDLE_TYPE_FTP_FIND_HTML;
|
|
break;
|
|
|
|
case TypeFtpFileHandle:
|
|
dwValue = INTERNET_HANDLE_TYPE_FTP_FILE;
|
|
break;
|
|
|
|
case TypeFtpFileHandleHtml:
|
|
dwValue = INTERNET_HANDLE_TYPE_FTP_FILE_HTML;
|
|
break;
|
|
|
|
case TypeGopherConnectHandle:
|
|
dwValue = INTERNET_HANDLE_TYPE_CONNECT_GOPHER;
|
|
break;
|
|
|
|
case TypeGopherFindHandle:
|
|
dwValue = INTERNET_HANDLE_TYPE_GOPHER_FIND;
|
|
break;
|
|
|
|
case TypeGopherFindHandleHtml:
|
|
dwValue = INTERNET_HANDLE_TYPE_GOPHER_FIND_HTML;
|
|
break;
|
|
|
|
case TypeGopherFileHandle:
|
|
dwValue = INTERNET_HANDLE_TYPE_GOPHER_FILE;
|
|
break;
|
|
|
|
case TypeGopherFileHandleHtml:
|
|
dwValue = INTERNET_HANDLE_TYPE_GOPHER_FILE_HTML;
|
|
break;
|
|
|
|
case TypeHttpConnectHandle:
|
|
dwValue = INTERNET_HANDLE_TYPE_CONNECT_HTTP;
|
|
break;
|
|
|
|
case TypeHttpRequestHandle:
|
|
dwValue = INTERNET_HANDLE_TYPE_HTTP_REQUEST;
|
|
break;
|
|
|
|
case TypeFileRequestHandle:
|
|
dwValue = INTERNET_HANDLE_TYPE_FILE_REQUEST;
|
|
break;
|
|
|
|
default:
|
|
error = ERROR_INTERNET_INTERNAL_ERROR;
|
|
break;
|
|
}
|
|
lpSource = (LPVOID)&dwValue;
|
|
break;
|
|
|
|
case INTERNET_OPTION_CONTEXT_VALUE:
|
|
case INTERNET_OPTION_CONTEXT_VALUE_OLD: // see InternetSetOption
|
|
requiredSize = sizeof(DWORD_PTR);
|
|
error = RGetContext(hInternet, &dwPtrValue);
|
|
lpSource = (LPVOID)&dwPtrValue;
|
|
break;
|
|
|
|
//case INTERNET_OPTION_NAME_RES_THREAD:
|
|
// requiredSize = sizeof(BOOL);
|
|
// lpSource = (LPVOID)&MultiThreadedNameResolution;
|
|
// break;
|
|
|
|
case INTERNET_OPTION_READ_BUFFER_SIZE:
|
|
case INTERNET_OPTION_WRITE_BUFFER_SIZE:
|
|
if (IS_CONNECT_HANDLE_TYPE(handleType)) {
|
|
requiredSize = sizeof(DWORD);
|
|
error = RGetBufferSize(hInternet, dwOption, &dwValue);
|
|
lpSource = (LPVOID)&dwValue;
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
//case INTERNET_OPTION_GATEWAY_NAME:
|
|
// error = ERROR_CALL_NOT_IMPLEMENTED;
|
|
// break;
|
|
|
|
case INTERNET_OPTION_ASYNC_ID:
|
|
error = ERROR_CALL_NOT_IMPLEMENTED;
|
|
break;
|
|
|
|
case INTERNET_OPTION_ASYNC_PRIORITY:
|
|
error = ERROR_CALL_NOT_IMPLEMENTED;
|
|
break;
|
|
|
|
//case INTERNET_OPTION_ASYNC_REQUEST_COUNT:
|
|
// requiredSize = sizeof(dwValue);
|
|
// error = RGetAsyncRequestCount(hInternet, &dwValue);
|
|
// lpSource = (LPVOID)&dwValue;
|
|
// break;
|
|
|
|
case INTERNET_OPTION_PARENT_HANDLE:
|
|
hInternet = ((HANDLE_OBJECT *)hInternet)->GetParent();
|
|
if (hInternet != NULL) {
|
|
hInternet = ((HANDLE_OBJECT *)hInternet)->GetPseudoHandle();
|
|
}
|
|
requiredSize = sizeof(hInternet);
|
|
lpSource = (LPVOID)&hInternet;
|
|
break;
|
|
|
|
case INTERNET_OPTION_KEEP_CONNECTION:
|
|
if (handleType == TypeHttpConnectHandle) {
|
|
requiredSize = sizeof(BOOL);
|
|
|
|
//
|
|
// we return TRUE or FALSE based on whether the connect
|
|
// object believes the server supports Keep-Alive
|
|
//
|
|
|
|
//dwValue = RGetKeepAliveState(hInternet);
|
|
lpSource = (LPVOID)&dwValue;
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_REQUEST_FLAGS:
|
|
requiredSize = sizeof(dwValue);
|
|
if (FValidCacheHandleType(handleType)) {
|
|
dwValue = 0;
|
|
if (lphRequest->IsFromCache()) {
|
|
dwValue |= INTERNET_REQFLAG_FROM_CACHE;
|
|
if (lphRequest->IsNetFailed()) {
|
|
dwValue |= INTERNET_REQFLAG_NET_TIMEOUT;
|
|
}
|
|
}
|
|
if (lphRequest->IsViaProxy()) {
|
|
dwValue |= INTERNET_REQFLAG_VIA_PROXY;
|
|
}
|
|
if (lphRequest->IsNoHeaders()) {
|
|
dwValue |= INTERNET_REQFLAG_NO_HEADERS;
|
|
}
|
|
if (lphRequest->IsCacheWriteDisabled()) {
|
|
dwValue |= INTERNET_REQFLAG_CACHE_WRITE_DISABLED;
|
|
}
|
|
lpSource = (LPVOID)&dwValue;
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_EXTENDED_ERROR:
|
|
requiredSize = sizeof(lpThreadInfo->dwMappedErrorCode);
|
|
lpSource = (LPVOID)&lpThreadInfo->dwMappedErrorCode;
|
|
break;
|
|
|
|
case INTERNET_OPTION_OFFLINE_MODE:
|
|
error = ERROR_CALL_NOT_IMPLEMENTED;
|
|
break;
|
|
|
|
case INTERNET_OPTION_CACHE_STREAM_HANDLE:
|
|
requiredSize = sizeof(HANDLE);
|
|
if (FValidCacheHandleType(handleType)) {
|
|
error = lphRequest->GetCacheStream((LPBYTE)&hValue,
|
|
sizeof(hValue)
|
|
);
|
|
lpSource = (LPVOID)&hValue;
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
BOOL fUser, fProxy;
|
|
|
|
case INTERNET_OPTION_USERNAME:
|
|
fUser = IS_USER;
|
|
fProxy = IS_SERVER;
|
|
goto callGetUserOrPass;
|
|
|
|
case INTERNET_OPTION_PASSWORD:
|
|
fUser = IS_PASS;
|
|
fProxy = IS_SERVER;
|
|
goto callGetUserOrPass;
|
|
|
|
case INTERNET_OPTION_PROXY_USERNAME:
|
|
fUser = IS_USER;
|
|
fProxy = IS_PROXY;
|
|
goto callGetUserOrPass;
|
|
|
|
case INTERNET_OPTION_PROXY_PASSWORD:
|
|
fUser = IS_PASS;
|
|
fProxy = IS_PROXY;
|
|
goto callGetUserOrPass;
|
|
|
|
callGetUserOrPass:
|
|
|
|
if (hInternet && (handleType != TypeInternetHandle)
|
|
&& (handleType != TypeFileRequestHandle)) {
|
|
lpSource = lphRequest->GetUserOrPass(fUser, fProxy);
|
|
isString = TRUE;
|
|
freeString = (lpSource != NULL && fUser == IS_PASS); // password string must be freed
|
|
error = ERROR_SUCCESS;
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
|
|
case INTERNET_OPTION_ASYNC:
|
|
error = ERROR_CALL_NOT_IMPLEMENTED;
|
|
break;
|
|
|
|
case INTERNET_OPTION_IDENTITY:
|
|
lpSource = (LPVOID)&GlobalIdentityGuid;
|
|
requiredSize = sizeof(GlobalIdentityGuid);
|
|
break;
|
|
|
|
case INTERNET_OPTION_SECURITY_FLAGS:
|
|
|
|
if (handleType != TypeHttpRequestHandle)
|
|
{
|
|
error = ERROR_INTERNET_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 INTERNET_OPTION_DATAFILE_NAME:
|
|
if ((handleType == TypeHttpRequestHandle)
|
|
|| (handleType == TypeFtpFindHandle)
|
|
|| (handleType == TypeFtpFindHandleHtml)
|
|
|| (handleType == TypeFtpFileHandle)
|
|
|| (handleType == TypeFtpFileHandleHtml)
|
|
|| (handleType == TypeGopherFindHandle)
|
|
|| (handleType == TypeGopherFindHandleHtml)
|
|
|| (handleType == TypeGopherFileHandle)
|
|
|| (handleType == TypeGopherFileHandleHtml)
|
|
|| (handleType == TypeFileRequestHandle )) {
|
|
|
|
//
|
|
// DATAFILE_NAME is slightly different from the other string
|
|
// options: if the name is not present then we return an error
|
|
// to the effect that we couldn't find it. The others just
|
|
// return an empty string
|
|
//
|
|
|
|
if ( handleType != TypeFileRequestHandle ) {
|
|
lpSource = lphRequest->GetDataFileName();
|
|
}
|
|
else {
|
|
lpSource =
|
|
((INTERNET_FILE_HANDLE_OBJECT *)lphRequest)->GetDataFileName();
|
|
}
|
|
|
|
if (lpSource != NULL) {
|
|
isString = TRUE;
|
|
|
|
INET_ASSERT(error == ERROR_SUCCESS);
|
|
|
|
} else {
|
|
error = ERROR_INTERNET_ITEM_NOT_FOUND;
|
|
}
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_URL:
|
|
|
|
//
|
|
// return the URL associated with the request handle. This may be
|
|
// different from the original URL due to redirections
|
|
//
|
|
|
|
if ((handleType == TypeHttpRequestHandle)
|
|
|| (handleType == TypeFtpFindHandle)
|
|
|| (handleType == TypeFtpFindHandleHtml)
|
|
|| (handleType == TypeFtpFileHandle)
|
|
|| (handleType == TypeFtpFileHandleHtml)
|
|
|| (handleType == TypeGopherFindHandle)
|
|
|| (handleType == TypeGopherFindHandleHtml)
|
|
|| (handleType == TypeGopherFileHandle)
|
|
|| (handleType == TypeGopherFileHandleHtml)) {
|
|
|
|
//
|
|
// only these handle types (retrieved object handles) can have
|
|
// associated URLs
|
|
//
|
|
|
|
lpSource = lphRequest->GetURL();
|
|
isString = TRUE;
|
|
|
|
INET_ASSERT(error == ERROR_SUCCESS);
|
|
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
case INTERNET_OPTION_SECURITY_CERTIFICATE:
|
|
|
|
if (handleType != TypeHttpRequestHandle) {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
} else {
|
|
HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
|
|
INTERNET_SECURITY_INFO siInfo;
|
|
INTERNET_CERTIFICATE_INFO ciInfo;
|
|
DWORD dwciInfoSize = sizeof(INTERNET_CERTIFICATE_INFO);
|
|
|
|
lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
|
|
|
|
if (ERROR_SUCCESS == lphHttpRqst->GetSecurityInfo(&siInfo))
|
|
{
|
|
error = ConvertSecurityInfoIntoCertInfoStruct(&siInfo, &ciInfo, &dwciInfoSize);
|
|
if(siInfo.pCertificate)
|
|
{
|
|
CertFreeCertificateContext(siInfo.pCertificate);
|
|
}
|
|
|
|
if ( error == ERROR_SUCCESS )
|
|
{
|
|
LPTSTR szResult = NULL;
|
|
DWORD cchNeedLen = 0;
|
|
|
|
|
|
szResult = FormatCertInfo(
|
|
&ciInfo
|
|
);
|
|
|
|
if (NULL == szResult)
|
|
{
|
|
error = ERROR_INTERNET_INVALID_OPERATION;
|
|
goto secOptEnd;
|
|
}
|
|
|
|
cchNeedLen = lstrlen(szResult) + 1;
|
|
if (*lpdwBufferLength < cchNeedLen)
|
|
{
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
goto secOptEnd;
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT(lpBuffer))
|
|
{
|
|
memcpy(
|
|
lpBuffer,
|
|
szResult,
|
|
(cchNeedLen) * sizeof(TCHAR));
|
|
cchNeedLen--;
|
|
}
|
|
|
|
secOptEnd:
|
|
if (NULL != szResult) {
|
|
FREE_MEMORY(szResult);
|
|
}
|
|
if (NULL != ciInfo.lpszSubjectInfo) {
|
|
LocalFree(ciInfo.lpszSubjectInfo);
|
|
}
|
|
if (NULL != ciInfo.lpszIssuerInfo) {
|
|
LocalFree(ciInfo.lpszIssuerInfo);
|
|
}
|
|
if (NULL != ciInfo.lpszSignatureAlgName) {
|
|
LocalFree(ciInfo.lpszSignatureAlgName);
|
|
}
|
|
if (NULL != ciInfo.lpszEncryptionAlgName) {
|
|
LocalFree(ciInfo.lpszEncryptionAlgName);
|
|
}
|
|
if (NULL != ciInfo.lpszProtocolName) {
|
|
LocalFree(ciInfo.lpszProtocolName);
|
|
}
|
|
|
|
*lpdwBufferLength = cchNeedLen;
|
|
requiredSize = *lpdwBufferLength;
|
|
}
|
|
|
|
goto quit;
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INTERNET_INVALID_OPERATION;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_SECURITY_CONNECTION_INFO:
|
|
//
|
|
// Caller is expected to pass in an INTERNET_SECURITY_CONNECTION_INFO structure.
|
|
|
|
if (handleType != TypeHttpRequestHandle) {
|
|
error = ERROR_INTERNET_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)
|
|
{
|
|
CertFreeCertificateContext(ciInfo.pCertificate);
|
|
}
|
|
|
|
} else if (error == ERROR_INTERNET_INTERNAL_ERROR) {
|
|
// This implies we are not secure.
|
|
error = ERROR_SUCCESS;
|
|
lpSecConnInfo->fSecure = FALSE;
|
|
}
|
|
|
|
lpSecConnInfo->dwSize = requiredSize;
|
|
*lpdwBufferLength = requiredSize;
|
|
}
|
|
|
|
goto quit;
|
|
|
|
|
|
case INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT:
|
|
|
|
//
|
|
// Allocates memory that caller is expected to free.
|
|
//
|
|
|
|
if (handleType != TypeHttpRequestHandle) {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
} else {
|
|
LPTSTR szResult = NULL;
|
|
DWORD cchNeedLen = 0;
|
|
HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
|
|
INTERNET_SECURITY_INFO cInfo;
|
|
lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
|
|
requiredSize = sizeof(INTERNET_CERTIFICATE_INFO);
|
|
|
|
if (ERROR_SUCCESS == lphHttpRqst->GetSecurityInfo(&cInfo))
|
|
{
|
|
error = ConvertSecurityInfoIntoCertInfoStruct(&cInfo, (LPINTERNET_CERTIFICATE_INFO)lpBuffer, lpdwBufferLength);
|
|
if(cInfo.pCertificate)
|
|
{
|
|
CertFreeCertificateContext(cInfo.pCertificate);
|
|
}
|
|
goto quit;
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INTERNET_INVALID_OPERATION;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_SECURITY_KEY_BITNESS:
|
|
|
|
if (handleType != TypeHttpRequestHandle)
|
|
{
|
|
error = ERROR_INTERNET_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_INTERNET_INVALID_OPERATION;
|
|
} else {
|
|
dwValue = secInfo.dwCipherStrength;
|
|
CertFreeCertificateContext(secInfo.pCertificate);
|
|
|
|
INET_ASSERT (error == ERROR_SUCCESS);
|
|
|
|
DEBUG_PRINT(INET,
|
|
INFO,
|
|
("SECURITY_KEY_BITNESS: %X\n",
|
|
dwValue
|
|
));
|
|
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case INTERNET_OPTION_PROXY:
|
|
if (!ARGUMENT_PRESENT(hInternet)) {
|
|
|
|
if (!GlobalProxyInfo.IsModifiedInProcess())
|
|
{
|
|
FixProxySettingsForCurrentConnection(
|
|
FALSE
|
|
);
|
|
}
|
|
|
|
error = GlobalProxyInfo.GetProxyStringInfo(lpBuffer, lpdwBufferLength);
|
|
requiredSize = *lpdwBufferLength;
|
|
goto quit;
|
|
} else if (handleType == TypeInternetHandle) {
|
|
|
|
//
|
|
// GetProxyInfo() will return the data, or calculate the buffer
|
|
// length required
|
|
//
|
|
|
|
error = ((INTERNET_HANDLE_OBJECT *)hInternet)->GetProxyStringInfo(
|
|
lpBuffer,
|
|
lpdwBufferLength
|
|
);
|
|
requiredSize = *lpdwBufferLength;
|
|
goto quit;
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_VERSION:
|
|
requiredSize = sizeof(InternetVersionInfo);
|
|
lpSource = (LPVOID)&InternetVersionInfo;
|
|
break;
|
|
|
|
case INTERNET_OPTION_USER_AGENT:
|
|
if (handleType == TypeInternetHandle) {
|
|
lpSource = ((INTERNET_HANDLE_OBJECT *)hInternet)->GetUserAgent();
|
|
isString = TRUE;
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_LINE_STATE:
|
|
|
|
if(InternetSettingsChanged())
|
|
{
|
|
ChangeGlobalSettings(); // refreshes GlobalDllState
|
|
}
|
|
|
|
requiredSize = sizeof(DWORD);
|
|
lpSource = (LPVOID)&dwValue;
|
|
dwValue = GlobalDllState
|
|
& (INTERNET_LINE_STATE_MASK | INTERNET_STATE_OFFLINE_USER);
|
|
break;
|
|
|
|
case INTERNET_OPTION_IDLE_STATE:
|
|
requiredSize = sizeof(DWORD);
|
|
lpSource = (LPVOID)&dwValue;
|
|
dwValue = GlobalDllState & INTERNET_STATE_IDLE;
|
|
break;
|
|
|
|
case INTERNET_OPTION_OFFLINE_SEMANTICS:
|
|
requiredSize = sizeof(DWORD);
|
|
dwValue = FALSE;
|
|
lpSource = (LPVOID)&dwValue;
|
|
break;
|
|
|
|
case INTERNET_OPTION_SECONDARY_CACHE_KEY:
|
|
if (handleType == TypeHttpRequestHandle) {
|
|
lphRequest = (INTERNET_CONNECT_HANDLE_OBJECT *)hInternet;
|
|
lpSource = lphRequest->GetSecondaryCacheKey();
|
|
isString = TRUE;
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_CALLBACK_FILTER:
|
|
error = ERROR_NOT_SUPPORTED;
|
|
break;
|
|
|
|
case INTERNET_OPTION_CONNECT_TIME:
|
|
error = ERROR_NOT_SUPPORTED;
|
|
break;
|
|
|
|
case INTERNET_OPTION_SEND_THROUGHPUT:
|
|
error = ERROR_NOT_SUPPORTED;
|
|
break;
|
|
|
|
case INTERNET_OPTION_RECEIVE_THROUGHPUT:
|
|
error = ERROR_NOT_SUPPORTED;
|
|
break;
|
|
|
|
case INTERNET_OPTION_REQUEST_PRIORITY:
|
|
if (handleType == TypeHttpRequestHandle) {
|
|
requiredSize = sizeof(dwValue);
|
|
dwValue = ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->GetPriority();
|
|
lpSource = (LPVOID)&dwValue;
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_HTTP_VERSION:
|
|
requiredSize = sizeof(HttpVersionInfo);
|
|
lpSource = (LPVOID)&HttpVersionInfo;
|
|
break;
|
|
|
|
case INTERNET_OPTION_NET_SPEED:
|
|
break;
|
|
|
|
case INTERNET_OPTION_BYPASS_EDITED_ENTRY:
|
|
requiredSize = sizeof(BOOL);
|
|
dwValue = GlobalBypassEditedEntry;
|
|
lpSource = (LPVOID)&dwValue;
|
|
break;
|
|
|
|
case INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO:
|
|
|
|
//
|
|
// internal option
|
|
//
|
|
|
|
if (handleType == TypeHttpRequestHandle) {
|
|
requiredSize = sizeof(socketInfo);
|
|
lpSource = (LPVOID)&socketInfo;
|
|
|
|
HTTP_REQUEST_HANDLE_OBJECT * pReq;
|
|
|
|
pReq = (HTTP_REQUEST_HANDLE_OBJECT *)hInternet;
|
|
socketInfo.Socket = pReq->GetSocket();
|
|
socketInfo.SourcePort = pReq->GetSourcePort();
|
|
socketInfo.DestPort = pReq->GetDestPort();
|
|
socketInfo.Flags = (pReq->FromKeepAlivePool()
|
|
? IDSI_FLAG_KEEP_ALIVE : 0)
|
|
| (pReq->IsSecure()
|
|
? IDSI_FLAG_SECURE : 0)
|
|
| (pReq->IsRequestUsingProxy()
|
|
? IDSI_FLAG_PROXY : 0)
|
|
| (pReq->IsTunnel()
|
|
? IDSI_FLAG_TUNNEL : 0);
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_CACHE_TIMESTAMPS:
|
|
if (handleType == TypeHttpRequestHandle) {
|
|
if (*lpdwBufferLength == sizeof(INTERNET_CACHE_TIMESTAMPS)) {
|
|
INTERNET_CACHE_TIMESTAMPS* ts =
|
|
(INTERNET_CACHE_TIMESTAMPS*)lpBuffer;
|
|
BOOL bU1;
|
|
BOOL bU2;
|
|
BOOL bU3;
|
|
FILETIME ftPostCheck;
|
|
|
|
((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->
|
|
GetTimeStampsForCache(
|
|
&(ts->ftExpires),
|
|
&(ts->ftLastModified),
|
|
&ftPostCheck,
|
|
&bU1, &bU2, &bU3 );
|
|
} else {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
goto quit;
|
|
break;
|
|
|
|
case INTERNET_OPTION_DISABLE_AUTODIAL:
|
|
error = ERROR_NOT_SUPPORTED;
|
|
break;
|
|
|
|
case INTERNET_OPTION_AUTODIAL_MODE:
|
|
requiredSize = sizeof(DWORD);
|
|
dwValue = GetAutodialMode();
|
|
lpSource = (LPVOID)&dwValue;
|
|
break;
|
|
|
|
case INTERNET_OPTION_AUTODIAL_CONNECTION:
|
|
error = GetAutodialConnection((LPSTR)lpBuffer, *lpdwBufferLength);
|
|
isString = TRUE;
|
|
lpSource = lpBuffer;
|
|
requiredSize = *lpdwBufferLength;
|
|
break;
|
|
|
|
// IE5 #23845: Wininet: Various auth related feature requests for FP
|
|
// This will return TRUE if post data will be sent on a request.
|
|
case INTERNET_OPTION_DETECT_POST_SEND:
|
|
if (handleType == TypeHttpRequestHandle)
|
|
{
|
|
requiredSize = sizeof(DWORD);
|
|
lpSource = (LPVOID)&dwValue;
|
|
HTTP_REQUEST_HANDLE_OBJECT *pRequest;
|
|
pRequest = (HTTP_REQUEST_HANDLE_OBJECT*) hInternet;
|
|
|
|
if (pRequest->GetAuthState() == AUTHSTATE_NEGOTIATE
|
|
&& !((PLUG_CTX*)(pRequest->GetAuthCtx()))->_fNTLMProxyAuth
|
|
&& !(pRequest->GetAuthCtx()->GetSchemeType() == AUTHCTX::SCHEME_DPA))
|
|
{
|
|
dwValue = 0;
|
|
}
|
|
else
|
|
{
|
|
dwValue = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_MAX_CONNS_PER_SERVER:
|
|
if( !hInternet ) {
|
|
requiredSize = sizeof(dwValue);
|
|
dwValue = 0;
|
|
lpSource = (LPVOID)&dwValue;
|
|
dwValue = GlobalMaxConnectionsPerServer;
|
|
}
|
|
else
|
|
error = ERROR_INTERNET_INVALID_OPERATION;
|
|
|
|
break;
|
|
|
|
case INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER:
|
|
if( !hInternet ) {
|
|
requiredSize = sizeof(dwValue);
|
|
dwValue = 0;
|
|
lpSource = (LPVOID)&dwValue;
|
|
dwValue = GlobalMaxConnectionsPer1_0Server;
|
|
}
|
|
else
|
|
error = ERROR_INTERNET_INVALID_OPERATION;
|
|
|
|
break;
|
|
|
|
case INTERNET_OPTION_PER_CONNECTION_OPTION:
|
|
{
|
|
if (handleType != TypeInternetHandle) {
|
|
hInternet = NULL;
|
|
}
|
|
|
|
error = QueryPerConnOptions(hInternet,
|
|
lpThreadInfo->IsAutoProxyProxyThread,
|
|
(LPINTERNET_PER_CONN_OPTION_LIST)lpBuffer);
|
|
|
|
requiredSize = *lpdwBufferLength;
|
|
goto quit;
|
|
}
|
|
|
|
case INTERNET_OPTION_COOKIES_3RD_PARTY:
|
|
if (handleType == TypeHttpRequestHandle)
|
|
{
|
|
requiredSize = sizeof(DWORD);
|
|
lpSource = (LPVOID)&dwValue;
|
|
dwValue = (DWORD) ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->Is3rdPartyCookies();
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
#if INET_DEBUG
|
|
|
|
case INTERNET_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 INTERNET_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
|
|
//
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// Scrub and free password string from GetUserOrPass().
|
|
switch (dwOption)
|
|
{
|
|
case INTERNET_OPTION_PASSWORD:
|
|
case INTERNET_OPTION_PROXY_PASSWORD:
|
|
if (freeString)
|
|
{
|
|
INET_ASSERT(isString);
|
|
SecureZeroMemory(lpSource, requiredSize);
|
|
FREE_MEMORY(lpSource);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
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_API(success);
|
|
|
|
return success;
|
|
}
|
|
|
|
|
|
INTERNETAPI_(BOOL) InternetQueryOptionW(
|
|
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,
|
|
"InternetQueryOptionW",
|
|
"%#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;
|
|
|
|
switch (dwOption)
|
|
{
|
|
case INTERNET_OPTION_USERNAME:
|
|
case INTERNET_OPTION_PASSWORD:
|
|
case INTERNET_OPTION_DATAFILE_NAME:
|
|
case INTERNET_OPTION_URL:
|
|
case INTERNET_OPTION_USER_AGENT:
|
|
case INTERNET_OPTION_PROXY_USERNAME:
|
|
case INTERNET_OPTION_PROXY_PASSWORD:
|
|
case INTERNET_OPTION_SECONDARY_CACHE_KEY:
|
|
case INTERNET_OPTION_AUTODIAL_CONNECTION:
|
|
if (lpBuffer)
|
|
{
|
|
mpBuffer.dwAlloc = mpBuffer.dwSize = *lpdwBufferLength;
|
|
mpBuffer.psStr = (LPSTR)ALLOC_BYTES(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 = MultiByteToWideChar(CP_ACP, 0, mpBuffer.psStr, mpBuffer.dwSize + 1,
|
|
NULL, 0);
|
|
if (*lpdwBufferLength*sizeof(WCHAR)<=mpBuffer.dwAlloc && lpBuffer)
|
|
{
|
|
MultiByteToWideChar(CP_ACP, 0, mpBuffer.psStr, mpBuffer.dwSize+1,
|
|
(LPWSTR)lpBuffer, *lpdwBufferLength);
|
|
(*lpdwBufferLength)--;
|
|
}
|
|
else
|
|
{
|
|
*lpdwBufferLength *= sizeof(WCHAR);
|
|
fResult = FALSE;
|
|
dwErr = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (GetLastError()==ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
*lpdwBufferLength = mpBuffer.dwSize*sizeof(WCHAR);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_PER_CONNECTION_OPTION:
|
|
{
|
|
if (!lpBuffer)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
INTERNET_PER_CONN_OPTION_LISTA listA;
|
|
LPINTERNET_PER_CONN_OPTION_LISTW plistW = (LPINTERNET_PER_CONN_OPTION_LISTW)lpBuffer;
|
|
CHAR szEntryA[RAS_MaxEntryName + 1];
|
|
listA.pszConnection = szEntryA;
|
|
|
|
InitIPCOList(plistW, &listA);
|
|
listA.pOptions = (LPINTERNET_PER_CONN_OPTIONA)_alloca(sizeof(INTERNET_PER_CONN_OPTIONA)*listA.dwOptionCount);
|
|
|
|
for (DWORD i=0; i<listA.dwOptionCount; i++)
|
|
{
|
|
listA.pOptions[i].dwOption = plistW->pOptions[i].dwOption;
|
|
listA.pOptions[i].Value.pszValue = NULL;
|
|
plistW->pOptions[i].Value.pszValue = NULL;
|
|
}
|
|
|
|
fResult = InternetQueryOptionA(hInternet,
|
|
dwOption,
|
|
(PVOID)&listA,
|
|
lpdwBufferLength);
|
|
|
|
// Now, convert from ansi to unicode
|
|
|
|
if (fResult)
|
|
{
|
|
for (DWORD i=0; i<listA.dwOptionCount; i++)
|
|
{
|
|
switch (listA.pOptions[i].dwOption)
|
|
{
|
|
case INTERNET_PER_CONN_FLAGS:
|
|
case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS:
|
|
case INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS:
|
|
plistW->pOptions[i].Value.dwValue = listA.pOptions[i].Value.dwValue;
|
|
break;
|
|
|
|
case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME:
|
|
plistW->pOptions[i].Value.ftValue = listA.pOptions[i].Value.ftValue;
|
|
break;
|
|
|
|
case INTERNET_PER_CONN_PROXY_SERVER:
|
|
case INTERNET_PER_CONN_PROXY_BYPASS:
|
|
case INTERNET_PER_CONN_AUTOCONFIG_URL:
|
|
case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL:
|
|
case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL:
|
|
if (listA.pOptions[i].Value.pszValue && *listA.pOptions[i].Value.pszValue)
|
|
{
|
|
DWORD cc = MultiByteToWideChar(CP_ACP,
|
|
0,
|
|
listA.pOptions[i].Value.pszValue,
|
|
-1,
|
|
NULL,
|
|
0);
|
|
plistW->pOptions[i].Value.pszValue = (PWSTR)GlobalAlloc(GPTR, cc*sizeof(WCHAR));
|
|
if (!plistW->pOptions[i].Value.pszValue)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto iopco_cleanup;
|
|
}
|
|
MultiByteToWideChar(CP_ACP,
|
|
0,
|
|
listA.pOptions[i].Value.pszValue,
|
|
-1,
|
|
plistW->pOptions[i].Value.pszValue,
|
|
cc);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
INET_ASSERT(FALSE);
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto iopco_cleanup;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
plistW->dwOptionError = listA.dwOptionError;
|
|
}
|
|
|
|
iopco_cleanup:
|
|
// Free all the allocated buffers
|
|
for (i=0; i<listA.dwOptionCount; i++)
|
|
{
|
|
switch (listA.pOptions[i].dwOption)
|
|
{
|
|
case INTERNET_PER_CONN_PROXY_SERVER:
|
|
case INTERNET_PER_CONN_PROXY_BYPASS:
|
|
case INTERNET_PER_CONN_AUTOCONFIG_URL:
|
|
case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL:
|
|
case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL:
|
|
// These should have been converted from ansi to unicode
|
|
// and can be freed now
|
|
if (listA.pOptions[i].Value.pszValue)
|
|
{
|
|
GlobalFree(listA.pOptions[i].Value.pszValue);
|
|
}
|
|
// No point in passing back buffers in the event of an error
|
|
// condition
|
|
if (dwErr && plistW->pOptions[i].Value.pszValue)
|
|
{
|
|
GlobalFree(plistW->pOptions[i].Value.pszValue);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// No need to do anything
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
fResult = InternetQueryOptionA(hInternet,
|
|
dwOption,
|
|
lpBuffer,
|
|
lpdwBufferLength
|
|
);
|
|
}
|
|
|
|
if (dwErr!=ERROR_SUCCESS)
|
|
{
|
|
SetLastError(dwErr);
|
|
DEBUG_ERROR(INET, dwErr);
|
|
}
|
|
DEBUG_LEAVE_API(fResult);
|
|
return fResult;
|
|
}
|
|
|
|
|
|
INTERNETAPI_(BOOL) 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 INTERNET_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_INTERNET_INTERNAL_ERROR
|
|
Shouldn't see this?
|
|
|
|
ERROR_INVALID_PARAMETER
|
|
One of the parameters was bad
|
|
|
|
ERROR_INTERNET_INVALID_OPTION
|
|
The requested option cannot be set
|
|
|
|
ERROR_INTERNET_OPTION_NOT_SETTABLE
|
|
Can't set this option, only query it
|
|
|
|
ERROR_INTERNET_BAD_OPTION_LENGTH
|
|
The dwBufferLength parameter is incorrect for the
|
|
expected type of the option
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER_API((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;
|
|
LPINTERNET_THREAD_INFO lpThreadInfo = NULL;
|
|
DWORD requiredSize;
|
|
HINTERNET hObjectMapped = NULL;
|
|
INTERNET_CONNECT_HANDLE_OBJECT *lphRequest;
|
|
|
|
//
|
|
// Auth code can query on connect handle by walking up from request handle,
|
|
// unbeknownst to the client, who might try to set the option concurrently.
|
|
// Ideally access would be serialized only for the four combinations of
|
|
// {user,pass} and {server,proxy}, but unconditional keeps the code simple.
|
|
//
|
|
|
|
//AuthLock();
|
|
|
|
//
|
|
// validate parameters
|
|
//
|
|
|
|
if ((dwBufferLength == 0) || IsBadReadPtr(lpBuffer, dwBufferLength)) {
|
|
|
|
|
|
switch (dwOption) {
|
|
|
|
//
|
|
// these options don't require a buffer - don't fail request because
|
|
// no buffer supplied
|
|
//
|
|
|
|
case INTERNET_OPTION_SETTINGS_CHANGED:
|
|
case INTERNET_OPTION_PROXY_SETTINGS_CHANGED:
|
|
case INTERNET_OPTION_END_BROWSER_SESSION:
|
|
case INTERNET_OPTION_RESET_URLCACHE_SESSION:
|
|
case INTERNET_OPTION_REFRESH:
|
|
case INTERNET_OPTION_DIGEST_AUTH_UNLOAD:
|
|
case INTERNET_OPTION_IGNORE_OFFLINE:
|
|
case INTERNET_OPTION_EXEMPT_CONNECTION_LIMIT:
|
|
case INTERNET_OPTION_DISABLE_PASSPORT_AUTH:
|
|
case INTERNET_OPTION_ENABLE_PASSPORT_AUTH:
|
|
case INTERNET_OPTION_HIBERNATE_INACTIVE_WORKER_THREADS:
|
|
case INTERNET_OPTION_ACTIVATE_WORKER_THREADS:
|
|
case INTERNET_OPTION_RESTORE_WORKER_THREAD_DEFAULTS:
|
|
break;
|
|
|
|
default:
|
|
error = ERROR_INVALID_PARAMETER;
|
|
goto quit;
|
|
}
|
|
}
|
|
|
|
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 *)&hInternet, FALSE);
|
|
if (error == ERROR_SUCCESS) {
|
|
hObjectMapped = hInternet;
|
|
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_INTERNET_SPANISH_INQUISITION
|
|
//
|
|
|
|
INET_ASSERT(FALSE);
|
|
|
|
error = ERROR_INTERNET_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_INTERNET_INCORRECT_HANDLE_TYPE
|
|
: ERROR_INTERNET_INVALID_OPTION
|
|
;
|
|
}
|
|
|
|
if (error != ERROR_SUCCESS) {
|
|
goto quit;
|
|
}
|
|
|
|
//
|
|
// if the option and handle combination is valid then set the option value
|
|
//
|
|
|
|
switch (dwOption) {
|
|
case INTERNET_OPTION_CALLBACK:
|
|
case INTERNET_OPTION_HANDLE_TYPE:
|
|
//case INTERNET_OPTION_GATEWAY_NAME:
|
|
case INTERNET_OPTION_KEEP_CONNECTION:
|
|
case INTERNET_OPTION_ASYNC_ID:
|
|
case INTERNET_OPTION_ASYNC_REQUEST_COUNT:
|
|
case INTERNET_OPTION_ASYNC_QUEUE_DEPTH:
|
|
case INTERNET_OPTION_WORKER_THREAD_TIMEOUT:
|
|
case INTERNET_OPTION_IDLE_STATE:
|
|
case INTERNET_OPTION_CONNECT_TIME:
|
|
case INTERNET_OPTION_SEND_THROUGHPUT:
|
|
case INTERNET_OPTION_RECEIVE_THROUGHPUT:
|
|
case INTERNET_OPTION_NET_SPEED:
|
|
|
|
//
|
|
// these options cannot be set by this function
|
|
//
|
|
|
|
error = ERROR_INTERNET_OPTION_NOT_SETTABLE;
|
|
break;
|
|
|
|
case INTERNET_OPTION_HIBERNATE_INACTIVE_WORKER_THREADS:
|
|
|
|
if (!g_bDisableHibernation)
|
|
{
|
|
g_bHibernating = TRUE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_ACTIVATE_WORKER_THREADS:
|
|
|
|
if (g_bHibernating)
|
|
{
|
|
InterruptSelect();
|
|
GlobalProxyInfo.ActivateAutoproxyThread();
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_RESTORE_WORKER_THREAD_DEFAULTS:
|
|
|
|
if (g_bHibernating)
|
|
{
|
|
g_bHibernating = FALSE;
|
|
InterruptSelect();
|
|
GlobalProxyInfo.ActivateAutoproxyThread();
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_BYPASS_EDITED_ENTRY:
|
|
requiredSize = sizeof(BOOL);
|
|
if (dwBufferLength != requiredSize) {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
break;
|
|
}
|
|
// Only support global, not per handle yet
|
|
if (hInternet != NULL) {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
break;
|
|
}
|
|
|
|
// Made it this far, so buffer is right size and handle is NULL
|
|
GlobalBypassEditedEntry = *(LPBOOL)lpBuffer;
|
|
break;
|
|
|
|
|
|
case INTERNET_OPTION_CONNECT_TIMEOUT:
|
|
case INTERNET_OPTION_CONNECT_RETRIES:
|
|
case INTERNET_OPTION_CONNECT_BACKOFF:
|
|
case INTERNET_OPTION_SEND_TIMEOUT:
|
|
case INTERNET_OPTION_RECEIVE_TIMEOUT:
|
|
case INTERNET_OPTION_DATA_SEND_TIMEOUT:
|
|
case INTERNET_OPTION_DATA_RECEIVE_TIMEOUT:
|
|
case INTERNET_OPTION_FROM_CACHE_TIMEOUT:
|
|
requiredSize = sizeof(DWORD);
|
|
if (dwBufferLength != requiredSize) {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// if hInternet is NULL then the app is requesting that we set the
|
|
// global timeout values, not handle-specific ones
|
|
//
|
|
|
|
if (hInternet == NULL) {
|
|
switch (dwOption) {
|
|
case INTERNET_OPTION_CONNECT_TIMEOUT:
|
|
GlobalConnectTimeout = *(LPDWORD)lpBuffer;
|
|
break;
|
|
|
|
case INTERNET_OPTION_CONNECT_RETRIES:
|
|
GlobalConnectRetries = *(LPDWORD)lpBuffer;
|
|
break;
|
|
|
|
case INTERNET_OPTION_SEND_TIMEOUT:
|
|
GlobalSendTimeout = *(LPDWORD)lpBuffer;
|
|
break;
|
|
|
|
case INTERNET_OPTION_RECEIVE_TIMEOUT:
|
|
GlobalReceiveTimeout = *(LPDWORD)lpBuffer;
|
|
break;
|
|
|
|
case INTERNET_OPTION_DATA_SEND_TIMEOUT:
|
|
GlobalDataSendTimeout = *(LPDWORD)lpBuffer;
|
|
break;
|
|
|
|
case INTERNET_OPTION_DATA_RECEIVE_TIMEOUT:
|
|
GlobalDataReceiveTimeout = *(LPDWORD)lpBuffer;
|
|
break;
|
|
|
|
case INTERNET_OPTION_FROM_CACHE_TIMEOUT:
|
|
GlobalFromCacheTimeout = *(LPDWORD)lpBuffer;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// we have a non-NULL context handle: the app wants to set specific
|
|
// protocol timeouts
|
|
//
|
|
|
|
switch (handleType) {
|
|
case TypeInternetHandle:
|
|
case TypeFtpConnectHandle:
|
|
case TypeFtpFindHandle:
|
|
case TypeFtpFindHandleHtml:
|
|
case TypeFtpFileHandle:
|
|
case TypeFtpFileHandleHtml:
|
|
case TypeGopherConnectHandle:
|
|
case TypeGopherFindHandle:
|
|
case TypeGopherFindHandleHtml:
|
|
case TypeGopherFileHandle:
|
|
case TypeGopherFileHandleHtml:
|
|
case TypeHttpConnectHandle:
|
|
case TypeHttpRequestHandle:
|
|
|
|
//
|
|
// N.B. For some of these handle types, setting a timeout etc.
|
|
// value will have absolutely no affect (we have already gotten
|
|
// the information after connecting, sending etc.), but we'll
|
|
// allow the app to go ahead anyway (its benign)
|
|
//
|
|
|
|
error = RSetTimeout(hInternet,
|
|
dwOption,
|
|
*(LPDWORD)lpBuffer
|
|
);
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// any other handle type (?) cannot have timeouts set for it
|
|
//
|
|
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_CONTEXT_VALUE:
|
|
|
|
//
|
|
// BUGBUG - can't change context if async operation is pending
|
|
//
|
|
|
|
if (dwBufferLength == sizeof(lpThreadInfo->Context)) {
|
|
error = RSetContext(hInternet, *((DWORD*) lpBuffer));
|
|
} else {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_NAME_RES_THREAD:
|
|
//if (dwBufferLength == sizeof(MultiThreadedNameResolution)) {
|
|
// MultiThreadedNameResolution = (BOOL)(*(LPDWORD)lpBuffer != 0);
|
|
//} else {
|
|
// error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
//}
|
|
break;
|
|
|
|
case INTERNET_OPTION_READ_BUFFER_SIZE:
|
|
case INTERNET_OPTION_WRITE_BUFFER_SIZE:
|
|
if (IS_CONNECT_HANDLE_TYPE(handleType)) {
|
|
if (dwBufferLength == sizeof(DWORD)) {
|
|
|
|
DWORD bufferSize;
|
|
|
|
bufferSize = *(LPDWORD)lpBuffer;
|
|
if (bufferSize > 0) {
|
|
error = RSetBufferSize(hInternet, dwOption, bufferSize);
|
|
} else {
|
|
|
|
//
|
|
// the read/write buffer size cannot be set to 0
|
|
//
|
|
|
|
error = ERROR_INVALID_PARAMETER;
|
|
}
|
|
} else {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
BOOL fUser, fProxy;
|
|
|
|
case INTERNET_OPTION_ASYNC_PRIORITY:
|
|
error = ERROR_CALL_NOT_IMPLEMENTED;
|
|
break;
|
|
|
|
case INTERNET_OPTION_AUTH_FLAGS:
|
|
|
|
if (handleType != TypeHttpRequestHandle)
|
|
{
|
|
error = ERROR_INTERNET_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->SetAuthFlag(*(LPDWORD)lpBuffer);
|
|
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
|
|
break;
|
|
|
|
case INTERNET_OPTION_USERNAME:
|
|
fUser = IS_USER;
|
|
fProxy = IS_SERVER;
|
|
goto callSetUserOrPass;
|
|
|
|
|
|
case INTERNET_OPTION_PASSWORD:
|
|
fUser = IS_PASS;
|
|
fProxy = IS_SERVER;
|
|
goto callSetUserOrPass;
|
|
|
|
case INTERNET_OPTION_PROXY_USERNAME:
|
|
fUser = IS_USER;
|
|
fProxy = IS_PROXY;
|
|
goto callSetUserOrPass;
|
|
|
|
case INTERNET_OPTION_PROXY_PASSWORD:
|
|
fUser = IS_PASS;
|
|
fProxy = IS_PROXY;
|
|
goto callSetUserOrPass;
|
|
|
|
|
|
callSetUserOrPass:
|
|
|
|
if (hInternet == 0)
|
|
{
|
|
if (!fProxy)
|
|
{
|
|
AuthLock();
|
|
SetUserOrPass ((LPSTR)lpBuffer, fUser);
|
|
TimeStampCreds();
|
|
AuthUnlock();
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
}
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
else if (handleType != TypeInternetHandle) {
|
|
AuthLock();
|
|
lphRequest = (INTERNET_CONNECT_HANDLE_OBJECT *)hInternet;
|
|
lphRequest->SetUserOrPass ((LPSTR)lpBuffer, fUser, fProxy);
|
|
lphRequest->TimeStampCreds();
|
|
AuthUnlock();
|
|
error = ERROR_SUCCESS;
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
|
|
break;
|
|
|
|
case INTERNET_OPTION_DISABLE_PASSPORT_AUTH:
|
|
if (handleType != TypeInternetHandle)
|
|
{
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
else
|
|
{
|
|
((INTERNET_HANDLE_OBJECT *)hInternet)->DisableTweener();
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
|
|
break;
|
|
|
|
case INTERNET_OPTION_ENABLE_PASSPORT_AUTH:
|
|
if (handleType != TypeInternetHandle)
|
|
{
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
else
|
|
{
|
|
((INTERNET_HANDLE_OBJECT *)hInternet)->EnableTweener();
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
|
|
break;
|
|
|
|
case INTERNET_OPTION_EXEMPT_CONNECTION_LIMIT:
|
|
if (handleType != TypeInternetHandle)
|
|
{
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
else
|
|
{
|
|
((INTERNET_HANDLE_OBJECT *)hInternet)->ExemptConnLimit();
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
|
|
break;
|
|
|
|
case INTERNET_OPTION_CLIENT_CERT_CONTEXT:
|
|
|
|
if (handleType != TypeHttpRequestHandle)
|
|
{
|
|
error = ERROR_INTERNET_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 = pRequest->GetCertContextArray();
|
|
if (!pArray)
|
|
{
|
|
pArray = new CERT_CONTEXT_ARRAY;
|
|
pRequest->SetCertContextArray(pArray);
|
|
}
|
|
|
|
if (!pArray)
|
|
error = ERROR_NOT_ENOUGH_MEMORY;
|
|
else
|
|
{
|
|
error = LoadSecurity();
|
|
if (ERROR_SUCCESS == error)
|
|
{
|
|
pArray->Reset();
|
|
pArray->AddCertContext((PCCERT_CONTEXT) lpBuffer);
|
|
pArray->SelectCertContext(0);
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
pRequest->SetCertContextArray(NULL);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_SECURITY_SELECT_CLIENT_CERT:
|
|
|
|
// This option sets an index into an internal wininet structure.
|
|
// This is worthless to apps because there is no way to guarantee
|
|
// they enum the cert store the same as wininet, especially if the
|
|
// server returns a list of acceptable CA to filter by. This has
|
|
// been superseded by INTERNET_OPTION_CLIENT_CERT_CONTEXT above.
|
|
|
|
if (handleType != TypeHttpRequestHandle)
|
|
{
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
else if (dwBufferLength < sizeof(DWORD))
|
|
{
|
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
else
|
|
{
|
|
CERT_CONTEXT_ARRAY* pCertContextArray;
|
|
HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
|
|
|
|
lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
|
|
|
|
pCertContextArray =
|
|
lphHttpRqst->GetCertContextArray();
|
|
|
|
if ( ! pCertContextArray )
|
|
{
|
|
error = ERROR_INTERNET_CLIENT_AUTH_NOT_SETUP;
|
|
}
|
|
else
|
|
{
|
|
|
|
if ( (*((LPINT)lpBuffer) < (INT) pCertContextArray->GetArraySize() )
|
|
|| *((LPINT)lpBuffer) == -1 )
|
|
{
|
|
pCertContextArray->SelectCertContext( *((LPDWORD)lpBuffer) );
|
|
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_SECURITY_FLAGS:
|
|
|
|
if (handleType != TypeHttpRequestHandle)
|
|
{
|
|
error = ERROR_INTERNET_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 INTERNET_OPTION_REFRESH:
|
|
|
|
//
|
|
// BUGBUG - can only accept global or InternetOpen() handles currently
|
|
//
|
|
|
|
if (!ARGUMENT_PRESENT(hInternet)) {
|
|
if (!GlobalProxyInfo.IsModifiedInProcess()) {
|
|
FixProxySettingsForCurrentConnection(TRUE);
|
|
error = ERROR_SUCCESS;
|
|
} else {
|
|
INET_ASSERT(error == ERROR_SUCCESS);
|
|
}
|
|
} else if (handleType == TypeInternetHandle) {
|
|
error = ((INTERNET_HANDLE_OBJECT *)hInternet)->Refresh(0);
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_PROXY:
|
|
if ((handleType == TypeInternetHandle) || !ARGUMENT_PRESENT(hInternet)) {
|
|
|
|
LPINTERNET_PROXY_INFO lpInfo = (LPINTERNET_PROXY_INFO)lpBuffer;
|
|
|
|
//
|
|
// validate parameters
|
|
//
|
|
|
|
if (dwBufferLength != sizeof(*lpInfo)) {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
} else if (!((lpInfo->dwAccessType == INTERNET_OPEN_TYPE_DIRECT)
|
|
|| (lpInfo->dwAccessType == INTERNET_OPEN_TYPE_PROXY)
|
|
|| (lpInfo->dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG))
|
|
|| ((lpInfo->dwAccessType == INTERNET_OPEN_TYPE_PROXY)
|
|
&& ((lpInfo->lpszProxy == NULL) || (*lpInfo->lpszProxy == '\0')))) {
|
|
error = ERROR_INVALID_PARAMETER;
|
|
} else {
|
|
if (!ARGUMENT_PRESENT(hInternet)) {
|
|
|
|
INTERNET_PROXY_INFO_EX info;
|
|
memset(&info, 0, sizeof(info));
|
|
info.dwFlags = PROXY_TYPE_DIRECT;
|
|
|
|
|
|
switch (lpInfo->dwAccessType) {
|
|
case INTERNET_OPEN_TYPE_PRECONFIG:
|
|
FixProxySettingsForCurrentConnection(TRUE);
|
|
error = ERROR_SUCCESS;
|
|
goto quit;
|
|
case INTERNET_OPEN_TYPE_DIRECT:
|
|
info.dwFlags |= PROXY_TYPE_DIRECT;
|
|
break;
|
|
case INTERNET_OPEN_TYPE_PROXY:
|
|
info.dwFlags |= PROXY_TYPE_PROXY;
|
|
info.lpszProxy = lpInfo->lpszProxy;
|
|
info.lpszProxyBypass = lpInfo->lpszProxyBypass;
|
|
break;
|
|
}
|
|
GlobalProxyInfo.SetProxySettings(&info, TRUE );
|
|
|
|
} else {
|
|
error = ((INTERNET_HANDLE_OBJECT *)hInternet)->SetProxyInfo(
|
|
lpInfo->dwAccessType,
|
|
lpInfo->lpszProxy,
|
|
lpInfo->lpszProxyBypass
|
|
);
|
|
}
|
|
}
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_SETTINGS_CHANGED:
|
|
{
|
|
DWORD dwVer;
|
|
|
|
IncrementCurrentSettingsVersion(&dwVer);
|
|
// eat the update settings for this process,
|
|
// since calling ChangeGlobalSettings should suffice
|
|
InternetSettingsChanged();
|
|
ChangeGlobalSettings();
|
|
PurgeKeepAlives(PKA_NOW);
|
|
}
|
|
|
|
break;
|
|
|
|
case INTERNET_OPTION_PROXY_SETTINGS_CHANGED:
|
|
{
|
|
DWORD dwVer;
|
|
|
|
IncrementCurrentSettingsVersion(&dwVer);
|
|
// eat the update settings for this process,
|
|
// since calling ChangeGlobalSettings should suffice
|
|
InternetSettingsChanged();
|
|
ChangeGlobalSettings();
|
|
// PurgeKeepAlives(PKA_NOW);
|
|
}
|
|
|
|
break;
|
|
|
|
case INTERNET_OPTION_USER_AGENT:
|
|
if (*(LPSTR)lpBuffer == '\0') {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
} else {
|
|
if (handleType == TypeInternetHandle) {
|
|
((INTERNET_HANDLE_OBJECT *)hInternet)->SetUserAgent((LPSTR)lpBuffer);
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_END_BROWSER_SESSION:
|
|
|
|
//
|
|
// Flush the in-memory password cache and drop any keep-alive
|
|
// sockets which had authorization (IIS retains the credentials.
|
|
//
|
|
|
|
AuthFlush();
|
|
PurgeKeepAlives (PKA_AUTH_FAILED);
|
|
|
|
if(g_hDialEvent)
|
|
{
|
|
WaitForSingleObject(g_hDialEvent, INFINITE);
|
|
CloseHandle(g_hDialEvent);
|
|
}
|
|
|
|
//
|
|
// Empty the content cache if registry key is set.
|
|
//
|
|
|
|
UrlCacheFlush();
|
|
|
|
//
|
|
// Flush session cookies.
|
|
//
|
|
|
|
PurgeCookieJarOfStaleCookies();
|
|
|
|
//
|
|
// Purge Proxy Script Cache
|
|
//
|
|
|
|
UPDATE_GLOBAL_PROXY_VERSION();
|
|
|
|
//
|
|
// Flush all cached SSL Certificates.
|
|
//
|
|
|
|
//GlobalCertCache.ClearList();
|
|
|
|
//
|
|
// Need to close global keys
|
|
//
|
|
ResetAutodialModule();
|
|
CloseInternetSettingsKey();
|
|
|
|
//
|
|
// Make sure cert key is reset, too
|
|
//
|
|
CloseMyCertStore();
|
|
|
|
// Look out: intentional fall through.
|
|
|
|
case INTERNET_OPTION_RESET_URLCACHE_SESSION:
|
|
|
|
// Look out: intentional fall through.
|
|
|
|
//
|
|
// Restart the session used for cache syncmode.
|
|
//
|
|
|
|
GetCurrentGmtTime ((LPFILETIME)&dwdwSessionStartTime);
|
|
dwdwSessionStartTime -= dwdwSessionStartTimeDefaultDelta;
|
|
|
|
error = ERROR_SUCCESS;
|
|
break;
|
|
|
|
case INTERNET_OPTION_DIGEST_AUTH_UNLOAD:
|
|
if (DIGEST_CTX::g_pFuncTbl)
|
|
{
|
|
DIGEST_CTX::Logoff();
|
|
DIGEST_CTX::g_pFuncTbl = NULL;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_LINE_STATE:
|
|
if (dwBufferLength == sizeof(INTERNET_ONLINE_OFFLINE_INFO)) {
|
|
|
|
LPINTERNET_ONLINE_OFFLINE_INFO lpInfo;
|
|
DWORD state;
|
|
|
|
lpInfo = (LPINTERNET_ONLINE_OFFLINE_INFO)lpBuffer;
|
|
state = lpInfo->dwOfflineState;
|
|
|
|
//
|
|
// we allow app to pass in INTERNET_STATE_OFFLINE_USER and interpret
|
|
// it as same as INTERNET_STATE_OFFLINE
|
|
//
|
|
|
|
if (state == INTERNET_STATE_OFFLINE_USER) {
|
|
state = INTERNET_STATE_OFFLINE;
|
|
}
|
|
if (((state == INTERNET_STATE_ONLINE)
|
|
|| (state == INTERNET_STATE_OFFLINE))
|
|
&& ((lpInfo->dwFlags & ~ISO_FORCE_OFFLINE) == 0)) {
|
|
error = SetOfflineUserState(state,
|
|
(lpInfo->dwFlags & ISO_FORCE_OFFLINE)
|
|
? TRUE
|
|
: FALSE
|
|
);
|
|
|
|
// update registry value
|
|
InternetWriteRegistryDword("GlobalUserOffline",
|
|
((state == INTERNET_STATE_ONLINE) ? 0 : 1));
|
|
|
|
// notification
|
|
DWORD dwOp = CACHE_NOTIFY_SET_OFFLINE;
|
|
if( state == INTERNET_STATE_ONLINE )
|
|
{
|
|
dwOp = CACHE_NOTIFY_SET_ONLINE;
|
|
}
|
|
|
|
UrlCacheSendNotification(dwOp);
|
|
|
|
// invalidate global info so other instances pick it up
|
|
DWORD dwVer;
|
|
IncrementCurrentSettingsVersion(&dwVer);
|
|
|
|
} else {
|
|
error = ERROR_INVALID_PARAMETER;
|
|
}
|
|
} else {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_OFFLINE_SEMANTICS:
|
|
break;
|
|
|
|
case INTERNET_OPTION_SECONDARY_CACHE_KEY:
|
|
if( handleType == TypeHttpRequestHandle ) {
|
|
lphRequest = (INTERNET_CONNECT_HANDLE_OBJECT *)hInternet;
|
|
if (!lphRequest->SetSecondaryCacheKey((LPSTR) lpBuffer)) {
|
|
error = ERROR_NOT_ENOUGH_MEMORY;
|
|
} else {
|
|
INET_ASSERT (error == ERROR_SUCCESS);
|
|
}
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
|
|
break;
|
|
|
|
case INTERNET_OPTION_CALLBACK_FILTER:
|
|
error = ERROR_NOT_SUPPORTED;
|
|
break;
|
|
|
|
case INTERNET_OPTION_REQUEST_PRIORITY:
|
|
if (handleType == TypeHttpRequestHandle) {
|
|
if (dwBufferLength == sizeof(LONG)) {
|
|
((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->
|
|
SetPriority(*(LPLONG)lpBuffer);
|
|
} else {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_HTTP_VERSION:
|
|
if (dwBufferLength == sizeof(HTTP_VERSION_INFO)) {
|
|
HttpVersionInfo = *(LPHTTP_VERSION_INFO)lpBuffer;
|
|
} else {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_ERROR_MASK:
|
|
lphRequest = (INTERNET_CONNECT_HANDLE_OBJECT *)hInternet;
|
|
if (dwBufferLength == sizeof(DWORD)) {
|
|
if ( *((LPDWORD) lpBuffer) & ~(INTERNET_ERROR_MASK_INSERT_CDROM |
|
|
INTERNET_ERROR_MASK_COMBINED_SEC_CERT |
|
|
INTERNET_ERROR_MASK_LOGIN_FAILURE_DISPLAY_ENTITY_BODY)) {
|
|
|
|
error = ERROR_INVALID_PARAMETER;
|
|
} else {
|
|
lphRequest->SetErrorMask(*(LPDWORD) lpBuffer);
|
|
}
|
|
} else {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_CODEPAGE:
|
|
if (handleType == TypeHttpRequestHandle) {
|
|
if (dwBufferLength == sizeof(DWORD)) {
|
|
((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->
|
|
SetCodePage(*(LPDWORD)lpBuffer);
|
|
} else {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY:
|
|
if (!GlobalSendUTF8ServerToProxy)
|
|
{
|
|
error = ERROR_INTERNET_INVALID_OPTION;
|
|
}
|
|
else if (handleType != TypeHttpRequestHandle)
|
|
{
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
else if (dwBufferLength != sizeof(DWORD))
|
|
{
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->
|
|
SetSendUTF8ServerNameToProxy(*(LPDWORD)lpBuffer);
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_DISABLE_AUTODIAL:
|
|
if (dwBufferLength == sizeof(DWORD)) {
|
|
|
|
DWORD dwValue = *(LPDWORD)lpBuffer;
|
|
|
|
SetAutodialEnable(dwValue == 0);
|
|
} else {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_AUTODIAL_MODE:
|
|
if(dwBufferLength == sizeof(DWORD))
|
|
{
|
|
SetAutodialMode(*(LPDWORD)lpBuffer);
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_AUTODIAL_CONNECTION:
|
|
if(dwBufferLength > 0)
|
|
{
|
|
SetAutodialConnection((LPSTR)lpBuffer);
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
break;
|
|
|
|
// Override to disable NTLM preauth.
|
|
case INTERNET_OPTION_DISABLE_NTLM_PREAUTH:
|
|
if (handleType == TypeHttpRequestHandle) {
|
|
if (dwBufferLength == sizeof(DWORD)) {
|
|
((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->
|
|
SetDisableNTLMPreauth(*(LPDWORD)lpBuffer);
|
|
} else {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_MAX_CONNS_PER_SERVER:
|
|
if (dwBufferLength == sizeof(DWORD)) {
|
|
DWORD dwValue = *(LPDWORD)lpBuffer;
|
|
|
|
if( !hInternet )
|
|
{
|
|
GlobalMaxConnectionsPerServer = dwValue;
|
|
// begin a-thkesa:
|
|
// Using NULL should affect the whole process.
|
|
// As per the bug, its not affecting the visited sites.
|
|
// so browse through the server info and set the new limits to all server.
|
|
// WindSE BUG: 243039 & Windows 612742
|
|
CServerInfo * lpServerInfo;
|
|
LockSerializedList(&GlobalServerInfoList);
|
|
for (lpServerInfo = (CServerInfo *)HeadOfSerializedList(&GlobalServerInfoList);
|
|
lpServerInfo != (CServerInfo *)SlSelf(&GlobalServerInfoList);
|
|
lpServerInfo = lpServerInfo->Next())
|
|
{
|
|
lpServerInfo->SetNewLimit(dwValue);
|
|
}
|
|
UnlockSerializedList(&GlobalServerInfoList);
|
|
//end: a-thkesa.
|
|
}
|
|
else
|
|
error = ERROR_INTERNET_INVALID_OPERATION;
|
|
|
|
} else {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
break;
|
|
|
|
|
|
break;
|
|
case INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER:
|
|
if (dwBufferLength == sizeof(DWORD)) {
|
|
DWORD dwValue = *(LPDWORD)lpBuffer;
|
|
|
|
if( !hInternet )
|
|
{
|
|
GlobalMaxConnectionsPer1_0Server = dwValue;
|
|
// begin a-thkesa:
|
|
// Using NULL should affect the whole process.
|
|
// As per the bug, its not affecting the visited sites.
|
|
// so browse through the server info and set the new limits to all server.
|
|
// WindSE BUG: 243039 & Windows 612742
|
|
CServerInfo * lpServerInfo;
|
|
LockSerializedList(&GlobalServerInfoList);
|
|
for (lpServerInfo = (CServerInfo *)HeadOfSerializedList(&GlobalServerInfoList);
|
|
lpServerInfo != (CServerInfo *)SlSelf(&GlobalServerInfoList);
|
|
lpServerInfo = lpServerInfo->Next())
|
|
{
|
|
lpServerInfo->SetNewLimit(dwValue);
|
|
}
|
|
UnlockSerializedList(&GlobalServerInfoList);
|
|
//end: a-thkesa.
|
|
}
|
|
else
|
|
error = ERROR_INTERNET_INVALID_OPERATION;
|
|
|
|
} else {
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
|
|
break;
|
|
|
|
case INTERNET_OPTION_PER_CONNECTION_OPTION:
|
|
{
|
|
if (handleType != TypeInternetHandle) {
|
|
hInternet = NULL;
|
|
}
|
|
|
|
error = SetPerConnOptions(hInternet,
|
|
lpThreadInfo? lpThreadInfo->IsAutoProxyProxyThread : FALSE,
|
|
(LPINTERNET_PER_CONN_OPTION_LIST)lpBuffer);
|
|
break;
|
|
}
|
|
|
|
case INTERNET_OPTION_IGNORE_OFFLINE:
|
|
if (handleType == TypeHttpRequestHandle) {
|
|
((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->SetIgnoreOffline();
|
|
} else {
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_IDENTITY:
|
|
if (dwBufferLength==sizeof(IUserIdentity2 *))
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else if (dwBufferLength==sizeof(GUID))
|
|
{
|
|
error = SwitchIdentity((GUID*)lpBuffer);
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_REMOVE_IDENTITY:
|
|
if (dwBufferLength==sizeof(GUID))
|
|
{
|
|
error = RemoveIdentity((GUID*)lpBuffer);
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_ALTER_IDENTITY:
|
|
if (dwBufferLength==sizeof(DWORD))
|
|
{
|
|
error = AlterIdentity(*(LPDWORD)lpBuffer);
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_SUPPRESS_BEHAVIOR:
|
|
if (dwBufferLength==sizeof(DWORD))
|
|
{
|
|
error = ERROR_SUCCESS;
|
|
switch (*(LPDWORD)lpBuffer)
|
|
{
|
|
case INTERNET_SUPPRESS_RESET_ALL:
|
|
GlobalSuppressCookiesPolicy = FALSE;
|
|
break;
|
|
|
|
case INTERNET_SUPPRESS_COOKIE_POLICY:
|
|
GlobalSuppressCookiesPolicy = TRUE;
|
|
break;
|
|
|
|
case INTERNET_SUPPRESS_COOKIE_POLICY_RESET:
|
|
GlobalSuppressCookiesPolicy = FALSE;
|
|
break;
|
|
|
|
default:
|
|
error = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_COOKIES_3RD_PARTY:
|
|
if(handleType == TypeHttpRequestHandle)
|
|
{
|
|
if(sizeof(DWORD) == dwBufferLength)
|
|
{
|
|
BOOL f3rdParty = *(BOOL *)lpBuffer;
|
|
|
|
((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->Set3rdPartyCookies(f3rdParty);
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INTERNET_BAD_OPTION_LENGTH;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
|
}
|
|
break;
|
|
|
|
case INTERNET_OPTION_SOCKET_SEND_BUFFER_LENGTH:
|
|
|
|
if (handleType != TypeHttpRequestHandle)
|
|
{
|
|
error = ERROR_INTERNET_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->SetSocketSendBufferLength(*(LPDWORD)lpBuffer);
|
|
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
#if INET_DEBUG
|
|
case INTERNET_OPTION_SET_DEBUG_INFO:
|
|
error = InternetSetDebugInfo((LPINTERNET_DEBUG_INFO)lpBuffer,
|
|
dwBufferLength
|
|
);
|
|
break;
|
|
|
|
#endif // INET_DEBUG
|
|
|
|
default:
|
|
|
|
//
|
|
// this option is not recognized
|
|
//
|
|
|
|
error = ERROR_INTERNET_INVALID_OPTION;
|
|
}
|
|
|
|
quit:
|
|
|
|
//AuthUnlock();
|
|
|
|
if (hObjectMapped != NULL) {
|
|
DereferenceObject((LPVOID)hObjectMapped);
|
|
}
|
|
|
|
done:
|
|
|
|
if (error != ERROR_SUCCESS) {
|
|
|
|
DEBUG_ERROR(API, error);
|
|
|
|
SetLastError(error);
|
|
success = FALSE;
|
|
}
|
|
|
|
DEBUG_LEAVE_API(success);
|
|
|
|
return success;
|
|
}
|
|
|
|
|
|
INTERNETAPI_(BOOL) InternetSetOptionW(
|
|
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_ENTER_API((DBG_API,
|
|
Bool,
|
|
"InternetSetOptionW",
|
|
"%#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;
|
|
|
|
switch (dwOption)
|
|
{
|
|
case INTERNET_OPTION_USERNAME:
|
|
case INTERNET_OPTION_PASSWORD:
|
|
case INTERNET_OPTION_DATAFILE_NAME:
|
|
case INTERNET_OPTION_URL:
|
|
case INTERNET_OPTION_USER_AGENT:
|
|
case INTERNET_OPTION_PROXY_USERNAME:
|
|
case INTERNET_OPTION_PROXY_PASSWORD:
|
|
case INTERNET_OPTION_SECONDARY_CACHE_KEY:
|
|
case INTERNET_OPTION_AUTODIAL_CONNECTION:
|
|
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
|
|
);
|
|
break;
|
|
|
|
case INTERNET_OPTION_PER_CONNECTION_OPTION:
|
|
{
|
|
if (!lpBuffer)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
|
|
INTERNET_PER_CONN_OPTION_LISTA listA;
|
|
LPINTERNET_PER_CONN_OPTION_LISTW plistW = (LPINTERNET_PER_CONN_OPTION_LISTW)lpBuffer;
|
|
CHAR szEntryA[RAS_MaxEntryName + 1];
|
|
listA.pszConnection = szEntryA;
|
|
|
|
InitIPCOList(plistW, &listA);
|
|
listA.pOptions = (LPINTERNET_PER_CONN_OPTIONA)_alloca(sizeof(INTERNET_PER_CONN_OPTIONA)*listA.dwOptionCount);
|
|
|
|
for (DWORD i=0; i<listA.dwOptionCount; i++)
|
|
{
|
|
listA.pOptions[i].dwOption = plistW->pOptions[i].dwOption;
|
|
|
|
switch (listA.pOptions[i].dwOption)
|
|
{
|
|
case INTERNET_PER_CONN_FLAGS:
|
|
case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS:
|
|
case INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS:
|
|
listA.pOptions[i].Value.dwValue = plistW->pOptions[i].Value.dwValue;
|
|
break;
|
|
|
|
case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME:
|
|
listA.pOptions[i].Value.ftValue = plistW->pOptions[i].Value.ftValue;
|
|
break;
|
|
|
|
case INTERNET_PER_CONN_PROXY_SERVER:
|
|
case INTERNET_PER_CONN_PROXY_BYPASS:
|
|
case INTERNET_PER_CONN_AUTOCONFIG_URL:
|
|
case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL:
|
|
case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL:
|
|
if (plistW->pOptions[i].Value.pszValue && *plistW->pOptions[i].Value.pszValue)
|
|
{
|
|
// ** WARNING ** NO UTF8 ENCODING HERE
|
|
DWORD cb = WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
plistW->pOptions[i].Value.pszValue,
|
|
-1,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL);
|
|
listA.pOptions[i].Value.pszValue = (PSTR)_alloca(cb);
|
|
WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
plistW->pOptions[i].Value.pszValue,
|
|
-1,
|
|
listA.pOptions[i].Value.pszValue,
|
|
cb,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
listA.pOptions[i].Value.pszValue = NULL;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
break;
|
|
}
|
|
}
|
|
fResult = InternetSetOptionA(hInternet,
|
|
dwOption,
|
|
(PVOID)&listA,
|
|
dwBufferLength);
|
|
plistW->dwOptionError = listA.dwOptionError;
|
|
}
|
|
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;
|
|
}
|
|
|
|
|
|
INTERNETAPI_(BOOL) InternetSetOptionExA(
|
|
IN HINTERNET hInternet OPTIONAL,
|
|
IN DWORD dwOption,
|
|
IN LPVOID lpBuffer,
|
|
IN DWORD dwBufferLength,
|
|
IN DWORD dwFlags
|
|
)
|
|
|
|
/*++
|
|
|
|
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 INTERNET_OPTION to set
|
|
|
|
lpBuffer - pointer to a buffer containing value to set
|
|
|
|
dwBufferLength - size of lpBuffer
|
|
|
|
dwFlags - flags controlling operation. Possible values are:
|
|
|
|
ISO_GLOBAL - set this option globally. The
|
|
shared Wininet data segment will
|
|
be updated with this value
|
|
|
|
ISO_REGISTRY - this value will be written to the
|
|
registry for the corresponding
|
|
entry
|
|
|
|
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_INTERNET_INTERNAL_ERROR
|
|
Shouldn't see this?
|
|
|
|
ERROR_INVALID_PARAMETER
|
|
One of the parameters was bad
|
|
|
|
ERROR_INTERNET_INVALID_OPTION
|
|
The requested option cannot be set
|
|
|
|
ERROR_INTERNET_OPTION_NOT_SETTABLE
|
|
Can't set this option, only query it
|
|
|
|
ERROR_INTERNET_BAD_OPTION_LENGTH
|
|
The dwBufferLength parameter is incorrect for the
|
|
expected type of the option
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER_API((DBG_API,
|
|
Bool,
|
|
"InternetSetOptionExA",
|
|
"%#x, %s (%d), %#x [%#x], %d, %#x",
|
|
hInternet,
|
|
InternetMapOption(dwOption),
|
|
dwOption,
|
|
lpBuffer,
|
|
lpBuffer
|
|
? (!IsBadReadPtr(lpBuffer, sizeof(DWORD))
|
|
? *(LPDWORD)lpBuffer
|
|
: 0)
|
|
: 0,
|
|
dwBufferLength,
|
|
dwFlags
|
|
));
|
|
|
|
BOOL success;
|
|
|
|
//
|
|
// validate parameters
|
|
//
|
|
|
|
//
|
|
// currently, dwFlags MBZ
|
|
//
|
|
|
|
if (dwFlags == 0) {
|
|
success = InternetSetOptionA(hInternet,
|
|
dwOption,
|
|
lpBuffer,
|
|
dwBufferLength
|
|
);
|
|
} else {
|
|
DEBUG_ERROR(INET, ERROR_INVALID_PARAMETER);
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
success = FALSE;
|
|
}
|
|
|
|
DEBUG_LEAVE_API(success);
|
|
return success;
|
|
}
|
|
|
|
|
|
INTERNETAPI_(BOOL) InternetSetOptionExW(
|
|
IN HINTERNET hInternet OPTIONAL,
|
|
IN DWORD dwOption,
|
|
IN LPVOID lpBuffer,
|
|
IN DWORD dwBufferLength,
|
|
IN DWORD dwFlags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
description-of-function.
|
|
|
|
Arguments:
|
|
|
|
hInternet -
|
|
|
|
dwOption -
|
|
|
|
lpBuffer -
|
|
|
|
dwBufferLength -
|
|
|
|
dwFlags -
|
|
|
|
Return Value:
|
|
|
|
BOOL
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER_API((DBG_API,
|
|
Bool,
|
|
"InternetSetOptionExW",
|
|
"%#x, %s (%d), %#x [%#x], %d, %#x",
|
|
hInternet,
|
|
InternetMapOption(dwOption),
|
|
dwOption,
|
|
lpBuffer,
|
|
lpBuffer
|
|
? (!IsBadReadPtr(lpBuffer, sizeof(DWORD))
|
|
? *(LPDWORD)lpBuffer
|
|
: 0)
|
|
: 0,
|
|
dwBufferLength,
|
|
dwFlags
|
|
));
|
|
|
|
BOOL fResult = FALSE;
|
|
|
|
if (dwFlags)
|
|
{
|
|
DEBUG_ERROR(INET, ERROR_INVALID_PARAMETER);
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
}
|
|
else
|
|
{
|
|
fResult = InternetSetOptionW(hInternet,
|
|
dwOption,
|
|
lpBuffer,
|
|
dwBufferLength
|
|
);
|
|
}
|
|
|
|
DEBUG_LEAVE_API(fResult);
|
|
return fResult;
|
|
}
|
|
|
|
|
|
PRIVATE
|
|
BOOL
|
|
FValidCacheHandleType(
|
|
HINTERNET_HANDLE_TYPE hType
|
|
)
|
|
{
|
|
return ((hType != TypeInternetHandle) &&
|
|
(hType != TypeFtpConnectHandle) &&
|
|
(hType != TypeGopherConnectHandle) &&
|
|
(hType != TypeFileRequestHandle) &&
|
|
(hType != TypeHttpConnectHandle));
|
|
}
|
|
|