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