Leaked source code of windows server 2003
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

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