/*++ 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 // because wininet doesnt know about IStream #define NO_SHLWAPI_STREAM #include #include // -- 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; }