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.
978 lines
26 KiB
978 lines
26 KiB
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
inetapiw.cxx
|
|
|
|
Abstract:
|
|
|
|
Contains the wide-character Internet APIs
|
|
|
|
Contents:
|
|
WinHttpCrackUrl
|
|
WinHttpCreateUrl
|
|
WinHttpOpen
|
|
WinHttpConnect
|
|
WinHttpSetStatusCallback
|
|
|
|
Author:
|
|
|
|
Richard L Firth (rfirth) 02-Mar-1995
|
|
|
|
Environment:
|
|
|
|
Win32(s) user-mode DLL
|
|
|
|
Revision History:
|
|
|
|
02-Mar-1995 rfirth
|
|
Created
|
|
|
|
--*/
|
|
|
|
#include <wininetp.h>
|
|
|
|
// because wininet doesnt know about IStream
|
|
#define NO_SHLWAPI_STREAM
|
|
#include <shlwapi.h>
|
|
#include <shlwapip.h>
|
|
|
|
|
|
// -- FixStrings ------
|
|
|
|
// Used in WinHttpCrackUrlW only.
|
|
// Either
|
|
// (a) If we have an ansi string, AND a unicode buffer, convert from ansi to unicode
|
|
// (b) If we have an ansi string, but NO unicode buffer, determine where the ansi string
|
|
// occurs in the unicode URL, and point the component there.
|
|
|
|
VOID
|
|
FixStrings(
|
|
LPSTR& pszA,
|
|
DWORD cbA,
|
|
LPWSTR& pszW,
|
|
DWORD& ccW,
|
|
LPSTR pszUrlA,
|
|
LPCWSTR pszUrlW)
|
|
{
|
|
if (!pszA)
|
|
return;
|
|
|
|
if (pszW)
|
|
{
|
|
ccW = MultiByteToWideChar(CP_ACP, 0, pszA, cbA+1, pszW, ccW) - 1;
|
|
}
|
|
else
|
|
{
|
|
pszW = (LPWSTR)(pszUrlW + MultiByteToWideChar(CP_ACP, 0,
|
|
pszUrlA, (int) (pszA-pszUrlA), NULL, 0));
|
|
ccW = MultiByteToWideChar(CP_ACP, 0, pszA, cbA, NULL, 0);
|
|
}
|
|
}
|
|
|
|
//
|
|
// functions
|
|
//
|
|
|
|
|
|
INTERNETAPI
|
|
BOOL
|
|
WINAPI
|
|
WinHttpCrackUrl(
|
|
IN LPCWSTR pszUrlW,
|
|
IN DWORD dwUrlLengthW,
|
|
IN DWORD dwFlags,
|
|
IN OUT LPURL_COMPONENTSW pUCW
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Cracks an URL into its constituent parts. Optionally escapes the url-path.
|
|
We assume that the user has supplied large enough buffers for the various
|
|
URL parts
|
|
|
|
Arguments:
|
|
|
|
pszUrl - pointer to URL to crack
|
|
|
|
dwUrlLength - 0 if pszUrl is ASCIIZ string, else length of pszUrl
|
|
|
|
dwFlags - flags controlling operation
|
|
|
|
lpUrlComponents - pointer to URL_COMPONENTS
|
|
|
|
Return Value:
|
|
|
|
BOOL
|
|
Success - TRUE
|
|
|
|
Failure - FALSE. Call GetLastError() for more info
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER_API((DBG_API,
|
|
Bool,
|
|
"WinHttpCrackUrl",
|
|
"%wq, %#x, %#x, %#x",
|
|
pszUrlW,
|
|
dwUrlLengthW,
|
|
dwFlags,
|
|
pUCW
|
|
));
|
|
|
|
INET_ASSERT(pszUrlW);
|
|
INET_ASSERT(pUCW);
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
BOOL fResult = FALSE;
|
|
BOOL fContinue;
|
|
DWORD c;
|
|
MEMORYPACKET mpUrlA, mpHostName, mpUserName, mpScheme, mpPassword, mpUrlPath, mpExtraInfo;
|
|
URL_COMPONENTSA UCA;
|
|
|
|
if (!pszUrlW
|
|
|| (dwUrlLengthW
|
|
? IsBadStringPtrW(pszUrlW,-1)
|
|
: IsBadReadPtr(pszUrlW,dwUrlLengthW))
|
|
|| !pUCW
|
|
|| IsBadWritePtr(pUCW, sizeof(*pUCW))
|
|
|| (pUCW->dwStructSize != sizeof(*pUCW))
|
|
|| (dwFlags & ~(ICU_ESCAPE | ICU_DECODE)))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
|
|
UCA.dwStructSize = sizeof(URL_COMPONENTSA);
|
|
ALLOC_MB(pszUrlW, dwUrlLengthW, mpUrlA);
|
|
if (!mpUrlA.psStr) {
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
UNICODE_TO_ANSI(pszUrlW, mpUrlA);
|
|
|
|
for (c=0; c<=5; c++) {
|
|
LPWSTR pszWorker;
|
|
DWORD ccLen;
|
|
MEMORYPACKET* pmpWorker;
|
|
|
|
switch(c)
|
|
{
|
|
case 0:
|
|
pszWorker = pUCW->lpszScheme;
|
|
ccLen = pUCW->dwSchemeLength;
|
|
pmpWorker = &mpScheme;
|
|
break;
|
|
|
|
case 1:
|
|
pszWorker = pUCW->lpszHostName;
|
|
ccLen = pUCW->dwHostNameLength;
|
|
pmpWorker = &mpHostName;
|
|
break;
|
|
|
|
case 2:
|
|
pszWorker = pUCW->lpszUserName;
|
|
ccLen = pUCW->dwUserNameLength;
|
|
pmpWorker = &mpUserName;
|
|
break;
|
|
|
|
case 3:
|
|
pszWorker = pUCW->lpszPassword;
|
|
ccLen = pUCW->dwPasswordLength;
|
|
pmpWorker = &mpPassword;
|
|
break;
|
|
|
|
case 4:
|
|
pszWorker = pUCW->lpszUrlPath;
|
|
ccLen = pUCW->dwUrlPathLength;
|
|
pmpWorker = &mpUrlPath;
|
|
break;
|
|
|
|
case 5:
|
|
pszWorker = pUCW->lpszExtraInfo;
|
|
ccLen = pUCW->dwExtraInfoLength;
|
|
pmpWorker = &mpExtraInfo;
|
|
break;
|
|
}
|
|
|
|
if (pszWorker)
|
|
{
|
|
if (pszWorker
|
|
&& ccLen
|
|
&& (ProbeWriteBuffer(pszWorker,ccLen) != ERROR_SUCCESS) )
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
ALLOC_MB(pszWorker,ccLen,(*pmpWorker));
|
|
if (!pmpWorker->psStr)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pmpWorker->dwAlloc = ccLen;
|
|
}
|
|
};
|
|
|
|
REASSIGN_ALLOC(mpScheme,UCA.lpszScheme,UCA.dwSchemeLength);
|
|
REASSIGN_ALLOC(mpHostName, UCA.lpszHostName,UCA.dwHostNameLength);
|
|
REASSIGN_ALLOC(mpUserName, UCA.lpszUserName,UCA.dwUserNameLength);
|
|
REASSIGN_ALLOC(mpPassword,UCA.lpszPassword,UCA.dwPasswordLength);
|
|
REASSIGN_ALLOC(mpUrlPath,UCA.lpszUrlPath,UCA.dwUrlPathLength);
|
|
REASSIGN_ALLOC(mpExtraInfo,UCA.lpszExtraInfo,UCA.dwExtraInfoLength);
|
|
|
|
fResult = WinHttpCrackUrlA(mpUrlA.psStr, mpUrlA.dwSize, dwFlags, &UCA);
|
|
if (fResult) {
|
|
FixStrings(UCA.lpszScheme, UCA.dwSchemeLength, pUCW->lpszScheme,
|
|
pUCW->dwSchemeLength, mpUrlA.psStr, pszUrlW);
|
|
FixStrings(UCA.lpszHostName, UCA.dwHostNameLength, pUCW->lpszHostName,
|
|
pUCW->dwHostNameLength, mpUrlA.psStr, pszUrlW);
|
|
FixStrings(UCA.lpszUserName, UCA.dwUserNameLength, pUCW->lpszUserName,
|
|
pUCW->dwUserNameLength, mpUrlA.psStr, pszUrlW);
|
|
FixStrings(UCA.lpszPassword, UCA.dwPasswordLength, pUCW->lpszPassword,
|
|
pUCW->dwPasswordLength, mpUrlA.psStr, pszUrlW);
|
|
FixStrings(UCA.lpszUrlPath, UCA.dwUrlPathLength, pUCW->lpszUrlPath,
|
|
pUCW->dwUrlPathLength, mpUrlA.psStr, pszUrlW);
|
|
FixStrings(UCA.lpszExtraInfo, UCA.dwExtraInfoLength, pUCW->lpszExtraInfo,
|
|
pUCW->dwExtraInfoLength, mpUrlA.psStr, pszUrlW);
|
|
pUCW->nScheme = UCA.nScheme;
|
|
pUCW->nPort = UCA.nPort;
|
|
pUCW->dwStructSize = sizeof(URL_COMPONENTSW);
|
|
}
|
|
|
|
cleanup:
|
|
if (dwErr!=ERROR_SUCCESS) {
|
|
SetLastError(dwErr);
|
|
DEBUG_ERROR(API, dwErr);
|
|
}
|
|
DEBUG_LEAVE_API(fResult);
|
|
return fResult;
|
|
}
|
|
|
|
|
|
INTERNETAPI
|
|
BOOL
|
|
WINAPI
|
|
WinHttpCreateUrl(
|
|
IN LPURL_COMPONENTSW pUCW,
|
|
IN DWORD dwFlags,
|
|
OUT LPWSTR pszUrlW,
|
|
IN OUT LPDWORD pdwUrlLengthW
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates an URL from its constituent parts
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
BOOL
|
|
Success - URL written to pszUrl
|
|
|
|
Failure - call GetLastError() for more info
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER_API((DBG_API,
|
|
Bool,
|
|
"WinHttpCreateUrl",
|
|
"%#x, %#x, %#x, %#x",
|
|
pUCW,
|
|
dwFlags,
|
|
pszUrlW,
|
|
pdwUrlLengthW
|
|
));
|
|
|
|
INET_ASSERT(pszUrlW);
|
|
INET_ASSERT(pUCW);
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
BOOL fResult = FALSE;
|
|
MEMORYPACKET mpUrlA, mpHostName, mpUserName, mpScheme, mpPassword, mpUrlPath, mpExtraInfo;
|
|
URL_COMPONENTSA UCA;
|
|
|
|
if (!pdwUrlLengthW
|
|
|| (pUCW==NULL)
|
|
|| IsBadWritePtr(pUCW, sizeof(*pUCW))
|
|
|| (pUCW->dwStructSize != sizeof(*pUCW))
|
|
|| (pszUrlW && IsBadWritePtr(pszUrlW, *pdwUrlLengthW*sizeof(WCHAR)))
|
|
|| (dwFlags & ~(ICU_ESCAPE)))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
if (pszUrlW)
|
|
{
|
|
ALLOC_MB(pszUrlW, *pdwUrlLengthW, mpUrlA);
|
|
if (!mpUrlA.psStr)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
mpUrlA.dwSize = mpUrlA.dwAlloc;
|
|
UCA.dwStructSize = sizeof(URL_COMPONENTSA);
|
|
|
|
UCA.nScheme = pUCW->nScheme;
|
|
UCA.nPort = pUCW->nPort;
|
|
if (pUCW->lpszScheme)
|
|
{
|
|
if (pUCW->dwSchemeLength
|
|
? IsBadReadPtr(pUCW->lpszScheme, pUCW->dwSchemeLength)
|
|
: IsBadStringPtrW(pUCW->lpszScheme, -1))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
ALLOC_MB(pUCW->lpszScheme, pUCW->dwSchemeLength, mpScheme);
|
|
if (!mpScheme.psStr)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
UNICODE_TO_ANSI(pUCW->lpszScheme, mpScheme);
|
|
}
|
|
REASSIGN_SIZE(mpScheme, UCA.lpszScheme, UCA.dwSchemeLength);
|
|
if (pUCW->lpszHostName)
|
|
{
|
|
if (pUCW->dwHostNameLength
|
|
? IsBadReadPtr(pUCW->lpszHostName, pUCW->dwHostNameLength)
|
|
: IsBadStringPtrW(pUCW->lpszHostName, -1))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
ALLOC_MB(pUCW->lpszHostName, pUCW->dwHostNameLength, mpHostName);
|
|
if (!mpHostName.psStr)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
UNICODE_TO_ANSI(pUCW->lpszHostName, mpHostName);
|
|
}
|
|
REASSIGN_SIZE(mpHostName, UCA.lpszHostName, UCA.dwHostNameLength);
|
|
if (pUCW->lpszUserName)
|
|
{
|
|
if (pUCW->dwUserNameLength
|
|
? IsBadReadPtr(pUCW->lpszUserName, pUCW->dwUserNameLength)
|
|
: IsBadStringPtrW(pUCW->lpszUserName, -1))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
ALLOC_MB(pUCW->lpszUserName, pUCW->dwUserNameLength, mpUserName);
|
|
if (!mpUserName.psStr)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
UNICODE_TO_ANSI(pUCW->lpszUserName, mpUserName);
|
|
}
|
|
REASSIGN_SIZE(mpUserName, UCA.lpszUserName, UCA.dwUserNameLength);
|
|
if (pUCW->lpszPassword)
|
|
{
|
|
if (pUCW->dwPasswordLength
|
|
? IsBadReadPtr(pUCW->lpszPassword, pUCW->dwPasswordLength)
|
|
: IsBadStringPtrW(pUCW->lpszPassword, -1))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
ALLOC_MB(pUCW->lpszPassword, pUCW->dwPasswordLength, mpPassword);
|
|
if (!mpPassword.psStr)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
UNICODE_TO_ANSI(pUCW->lpszPassword, mpPassword);
|
|
}
|
|
REASSIGN_SIZE(mpPassword, UCA.lpszPassword, UCA.dwPasswordLength);
|
|
if (pUCW->lpszUrlPath)
|
|
{
|
|
if (pUCW->dwUrlPathLength
|
|
? IsBadReadPtr(pUCW->lpszUrlPath, pUCW->dwUrlPathLength)
|
|
: IsBadStringPtrW(pUCW->lpszUrlPath, -1))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
ALLOC_MB(pUCW->lpszUrlPath, pUCW->dwUrlPathLength, mpUrlPath);
|
|
if (!mpUrlPath.psStr)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
UNICODE_TO_ANSI(pUCW->lpszUrlPath, mpUrlPath);
|
|
}
|
|
REASSIGN_SIZE(mpUrlPath, UCA.lpszUrlPath, UCA.dwUrlPathLength);
|
|
if (pUCW->lpszExtraInfo)
|
|
{
|
|
if (pUCW->dwExtraInfoLength
|
|
? IsBadReadPtr(pUCW->lpszExtraInfo, pUCW->dwExtraInfoLength)
|
|
: IsBadStringPtrW(pUCW->lpszExtraInfo, -1))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
ALLOC_MB(pUCW->lpszExtraInfo, pUCW->dwExtraInfoLength, mpExtraInfo);
|
|
if (!mpExtraInfo.psStr)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
UNICODE_TO_ANSI(pUCW->lpszExtraInfo, mpExtraInfo);
|
|
}
|
|
REASSIGN_SIZE(mpExtraInfo, UCA.lpszExtraInfo, UCA.dwExtraInfoLength);
|
|
fResult = WinHttpCreateUrlA(&UCA, dwFlags, mpUrlA.psStr, &mpUrlA.dwSize);
|
|
if (fResult)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
fResult = FALSE;
|
|
|
|
if (pszUrlW && *pdwUrlLengthW)
|
|
{
|
|
//On success, reduce length of terminating NULL widechar.
|
|
dwRet = MultiByteToWideChar(CP_ACP, 0, mpUrlA.psStr, mpUrlA.dwSize+1, pszUrlW, *pdwUrlLengthW);
|
|
|
|
if (dwRet)
|
|
{
|
|
*pdwUrlLengthW = dwRet-1;
|
|
fResult = TRUE;
|
|
}
|
|
}
|
|
|
|
//If no url or no length or failure in prev. call, use MBtoWC to calculate required length of buffer.
|
|
//If a value is returned, then set ERROR_INSUFFICIENT_BUFFER as last error
|
|
if (!fResult)
|
|
{
|
|
dwRet = MultiByteToWideChar(CP_ACP, 0, mpUrlA.psStr, mpUrlA.dwSize+1, pszUrlW, 0);
|
|
|
|
if (dwRet)
|
|
{
|
|
dwErr = ERROR_INSUFFICIENT_BUFFER;
|
|
*pdwUrlLengthW = dwRet;
|
|
|
|
}
|
|
else
|
|
{
|
|
dwErr = GetLastError();
|
|
//Morph the error since we don't know what to initialize pdwUrlLengthW to
|
|
if (dwErr == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pdwUrlLengthW = mpUrlA.dwSize;
|
|
}
|
|
|
|
cleanup:
|
|
if (dwErr!=ERROR_SUCCESS)
|
|
{
|
|
SetLastError(dwErr);
|
|
DEBUG_ERROR(API, dwErr);
|
|
}
|
|
|
|
DEBUG_LEAVE_API(fResult);
|
|
return fResult;
|
|
}
|
|
|
|
|
|
// implemented in inetapia.cxx
|
|
DWORD ICUHrToWin32Error(HRESULT);
|
|
|
|
|
|
INTERNETAPI
|
|
HINTERNET
|
|
WINAPI
|
|
WinHttpOpen(
|
|
IN LPCWSTR pszAgentW,
|
|
IN DWORD dwAccessType,
|
|
IN LPCWSTR pszProxyW OPTIONAL,
|
|
IN LPCWSTR pszProxyBypassW OPTIONAL,
|
|
IN DWORD dwFlags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
description-of-function.
|
|
|
|
Arguments:
|
|
|
|
pszAgent -
|
|
|
|
dwAccessType -
|
|
|
|
pszProxy -
|
|
|
|
pszProxyBypass -
|
|
|
|
dwFlags -
|
|
|
|
Return Value:
|
|
|
|
HINTERNET
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER_API((DBG_API,
|
|
Handle,
|
|
"WinHttpOpen",
|
|
"%wq, %s (%d), %wq, %wq, %#x",
|
|
pszAgentW,
|
|
InternetMapOpenType(dwAccessType),
|
|
dwAccessType,
|
|
pszProxyW,
|
|
pszProxyBypassW,
|
|
dwFlags
|
|
));
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
HINTERNET hInternet = NULL;
|
|
MEMORYPACKET mpAgentA, mpProxyA, mpProxyBypassA;
|
|
|
|
if (dwFlags &~ (WINHTTP_OPEN_FLAGS_MASK))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
|
|
if (pszAgentW)
|
|
{
|
|
if (IsBadStringPtrW(pszAgentW, -1))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
ALLOC_MB(pszAgentW,0,mpAgentA);
|
|
if (!mpAgentA.psStr)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
UNICODE_TO_ANSI(pszAgentW,mpAgentA);
|
|
}
|
|
|
|
if (dwAccessType & WINHTTP_ACCESS_TYPE_NAMED_PROXY)
|
|
{
|
|
if (pszProxyW)
|
|
{
|
|
if (IsBadStringPtrW(pszProxyW, -1)
|
|
|| (*pszProxyW == L'\0'))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
ALLOC_MB(pszProxyW,0,mpProxyA);
|
|
if (!mpProxyA.psStr)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
UNICODE_TO_ANSI(pszProxyW,mpProxyA);
|
|
}
|
|
if (pszProxyBypassW)
|
|
{
|
|
if (IsBadStringPtrW(pszProxyBypassW, -1))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
ALLOC_MB(pszProxyBypassW,0,mpProxyBypassA);
|
|
if (!mpProxyBypassA.psStr)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
UNICODE_TO_ANSI(pszProxyBypassW,mpProxyBypassA);
|
|
}
|
|
}
|
|
|
|
hInternet = InternetOpenA(mpAgentA.psStr, dwAccessType, mpProxyA.psStr,
|
|
mpProxyBypassA.psStr, dwFlags);
|
|
|
|
|
|
cleanup:
|
|
if (dwErr!=ERROR_SUCCESS) {
|
|
SetLastError(dwErr);
|
|
DEBUG_ERROR(API, dwErr);
|
|
}
|
|
|
|
DEBUG_LEAVE_API(hInternet);
|
|
return hInternet;
|
|
}
|
|
|
|
|
|
INTERNETAPI
|
|
HINTERNET
|
|
WINAPI
|
|
WinHttpConnect(
|
|
IN HINTERNET hInternetSession,
|
|
IN LPCWSTR pszServerNameW,
|
|
IN INTERNET_PORT nServerPort,
|
|
IN DWORD dwReserved
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
description-of-function.
|
|
|
|
Arguments:
|
|
|
|
hInternetSession -
|
|
pszServerName -
|
|
nServerPort -
|
|
pszUserName -
|
|
pszPassword -
|
|
dwService -
|
|
dwReserved -
|
|
|
|
Return Value:
|
|
|
|
HINTERNET
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER_API((DBG_API,
|
|
Handle,
|
|
"WinHttpConnect",
|
|
"%#x, %wq, %d, %#x",
|
|
hInternetSession,
|
|
pszServerNameW,
|
|
nServerPort,
|
|
dwReserved
|
|
));
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
MEMORYPACKET mpServerNameA;
|
|
HINTERNET hInternet = NULL;
|
|
|
|
if (dwReserved)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
|
|
if (pszServerNameW)
|
|
{
|
|
if (IsBadStringPtrW(pszServerNameW,-1))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
dwErr = ConvertUnicodeToMultiByte(pszServerNameW, 0/*CODEPAGE not used here*/, &mpServerNameA,
|
|
WINHTTP_FLAG_VALID_HOSTNAME);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
hInternet = InternetConnectA
|
|
(hInternetSession, mpServerNameA.psStr, nServerPort, dwReserved, NULL);
|
|
|
|
cleanup:
|
|
if (dwErr!=ERROR_SUCCESS) {
|
|
SetLastError(dwErr);
|
|
DEBUG_ERROR(API, dwErr);
|
|
}
|
|
|
|
DEBUG_LEAVE_API(hInternet);
|
|
return hInternet;
|
|
}
|
|
|
|
|
|
INTERNETAPI
|
|
WINHTTP_STATUS_CALLBACK
|
|
WINAPI
|
|
WinHttpSetStatusCallback(
|
|
IN HINTERNET hInternet,
|
|
IN WINHTTP_STATUS_CALLBACK lpfnInternetCallback,
|
|
IN DWORD dwNotificationFlags,
|
|
IN DWORD_PTR dwReserved
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets the status callback function for the DLL or the handle object
|
|
|
|
Arguments:
|
|
|
|
hInternet - handle of the object for which we wish to set the
|
|
status callback
|
|
|
|
lpfnInternetCallback - pointer to caller-supplied status function
|
|
|
|
Return Value:
|
|
|
|
FARPROC
|
|
Success - previous status callback function address
|
|
|
|
Failure - INTERNET_INVALID_STATUS_CALLBACK. Call GetLastErrorInfo() for
|
|
more information:
|
|
|
|
ERROR_INVALID_PARAMETER
|
|
The callback function is invalid
|
|
|
|
ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
|
|
Cannot set the callback on the supplied handle (probably
|
|
a NULL handle - per-process callbacks no longer
|
|
supported)
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER_API((DBG_API,
|
|
Pointer,
|
|
"WinHttpSetStatusCallback",
|
|
"%#x, %#x, %#x",
|
|
hInternet,
|
|
lpfnInternetCallback,
|
|
dwNotificationFlags
|
|
));
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
BOOL fIsUnicode = TRUE; //vestigial UNICODE indicator
|
|
|
|
WINHTTP_STATUS_CALLBACK previousCallback = WINHTTP_INVALID_STATUS_CALLBACK;
|
|
HINTERNET hObjectMapped = NULL;
|
|
|
|
if (!GlobalDataInitialized)
|
|
{
|
|
dwErr = GlobalDataInitialize();
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
if (((lpfnInternetCallback != NULL) && IsBadCodePtr((FARPROC)lpfnInternetCallback))
|
|
|| (dwNotificationFlags == 0) || (dwReserved != 0))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!hInternet)
|
|
{
|
|
dwErr = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
|
|
goto cleanup;
|
|
}
|
|
|
|
// map the handle
|
|
dwErr = MapHandleToAddress(hInternet, (LPVOID *)&hObjectMapped, FALSE);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
// swap the new and previous handle object status callbacks, ONLY
|
|
// if there are no pending requests on this handle
|
|
previousCallback = lpfnInternetCallback;
|
|
dwErr = RExchangeStatusCallback(hObjectMapped, &previousCallback, fIsUnicode, dwNotificationFlags);
|
|
|
|
cleanup:
|
|
|
|
if (hObjectMapped != NULL)
|
|
{
|
|
DereferenceObject((LPVOID)hObjectMapped);
|
|
}
|
|
|
|
if (dwErr!=ERROR_SUCCESS)
|
|
{
|
|
SetLastError(dwErr);
|
|
DEBUG_ERROR(API, dwErr);
|
|
}
|
|
|
|
DEBUG_LEAVE_API(previousCallback);
|
|
return previousCallback;
|
|
}
|
|
|
|
|
|
// WinHttpPlatformCheck() API routines //////////////////////////////////////
|
|
|
|
static void ConvertVersionString(LPCSTR pszVersion, WORD rwVer[], CHAR ch)
|
|
{
|
|
LPCSTR pszEnd;
|
|
LPCSTR pszTemp;
|
|
int i;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
rwVer[i] = 0;
|
|
|
|
pszEnd = pszVersion + lstrlen(pszVersion);
|
|
pszTemp = pszVersion;
|
|
|
|
for (i = 0; i < 4 && pszTemp < pszEnd; i++)
|
|
{
|
|
while (pszTemp < pszEnd && *pszTemp != ch)
|
|
{
|
|
rwVer[i] = rwVer[i] * 10 + (*pszTemp - '0');
|
|
pszTemp++;
|
|
}
|
|
|
|
pszTemp++;
|
|
}
|
|
}
|
|
|
|
|
|
const char c_gszRegActiveSetup[] = "Software\\Microsoft\\Active Setup\\Installed Components\\";
|
|
const char c_gszInternetExplorerCLSID[] = "{89820200-ECBD-11cf-8B85-00AA005B4383}";
|
|
|
|
static void GetInstalledComponentVersion(LPCSTR szCLSID, DWORD *pdwMSVer, DWORD *pdwLSVer)
|
|
{
|
|
HKEY hKey;
|
|
char szKey[MAX_PATH];
|
|
WORD rgwVersion[4];
|
|
DWORD dwSize;
|
|
|
|
*pdwMSVer = 0;
|
|
*pdwLSVer = 0;
|
|
|
|
// Build the registry path.
|
|
lstrcpy(szKey, c_gszRegActiveSetup);
|
|
lstrcat(szKey, szCLSID);
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
dwSize = sizeof(szKey);
|
|
|
|
if ((RegQueryValueEx(hKey, "Version", NULL, NULL, (BYTE *)szKey, &dwSize) == ERROR_SUCCESS) &&
|
|
(dwSize > 0))
|
|
{
|
|
ConvertVersionString(szKey, rgwVersion, ',');
|
|
|
|
*pdwMSVer = (DWORD)rgwVersion[0] << 16; // Make hi word of MS version
|
|
*pdwMSVer += (DWORD)rgwVersion[1]; // Make lo word of MS version
|
|
*pdwLSVer = (DWORD)rgwVersion[2] << 16; // Make hi word of LS version
|
|
*pdwLSVer += (DWORD)rgwVersion[3]; // Make lo word of LS version
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
static BOOL Is_IE_501_OrLaterInstalled()
|
|
{
|
|
DWORD dwMSVer;
|
|
DWORD dwLSVer;
|
|
|
|
//
|
|
// Find the IE version number. IE 5.01 has version number 5.00.2919.6300.
|
|
// This will be returned from GetInstalledComponentVersion as two DWORDs,
|
|
// like so:
|
|
// 5.00 -> 0x00050000
|
|
// 2919.6300 -> 0x0B67189C
|
|
//
|
|
|
|
GetInstalledComponentVersion(c_gszInternetExplorerCLSID, &dwMSVer, &dwLSVer);
|
|
|
|
if (dwMSVer > 0x00050000)
|
|
return TRUE;
|
|
else if ((dwMSVer == 0x00050000) && (dwLSVer >= 0x0B67189C))
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
#if 0
|
|
|
|
#define REGSTR_CCS_CONTROL_WINDOWS TEXT("SYSTEM\\CurrentControlSet\\Control\\WINDOWS")
|
|
#define CSDVERSION TEXT("CSDVersion")
|
|
#define SP6_VERSION 0x0600
|
|
|
|
static BOOL Is_SP6_OrLater()
|
|
{
|
|
BOOL fSP6OrLater = FALSE;
|
|
HKEY hKey;
|
|
DWORD dwCSDVersion;
|
|
DWORD dwSize;
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_CCS_CONTROL_WINDOWS, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
dwSize = sizeof(dwCSDVersion);
|
|
|
|
if (RegQueryValueEx(hKey, CSDVERSION, NULL, NULL, (BYTE *)&dwCSDVersion, &dwSize) == ERROR_SUCCESS)
|
|
{
|
|
fSP6OrLater = (LOWORD(dwCSDVersion) >= SP6_VERSION);
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return fSP6OrLater;
|
|
}
|
|
#endif
|
|
|
|
|
|
INTERNETAPI
|
|
BOOL
|
|
WINAPI
|
|
WinHttpCheckPlatform(void)
|
|
{
|
|
static BOOL _fCheckedPlatform = FALSE;
|
|
static BOOL _fPlatformOk;
|
|
|
|
|
|
if (!_fCheckedPlatform)
|
|
{
|
|
OSVERSIONINFO osvi;
|
|
BOOL fPlatformOk = FALSE;
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
|
|
if (GetVersionEx(&osvi))
|
|
{
|
|
// Allow only Win2K or NT-based platforms.
|
|
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
|
|
{
|
|
if (osvi.dwMajorVersion >= 5)
|
|
{
|
|
// Ok on Win2K or later.
|
|
fPlatformOk = TRUE;
|
|
}
|
|
else if (osvi.dwMajorVersion == 4)
|
|
{
|
|
// On NT4, we require IE 5.01 (or later).
|
|
fPlatformOk = Is_IE_501_OrLaterInstalled();
|
|
}
|
|
}
|
|
}
|
|
|
|
_fPlatformOk = fPlatformOk;
|
|
|
|
InterlockedExchange((long *)&_fCheckedPlatform, TRUE);
|
|
}
|
|
|
|
return _fPlatformOk;
|
|
}
|
|
|
|
|