/*----------------------------------------------------------------------------- Copyright (c) 1996 Microsoft Corporation Module Name: ckcnv.cxx Abstract: Upgrades cookies to present urlcache format by enumerating cookie files in the cache cookies directory and creates cookie cache index entries in the format of the current wininet.dll. Author: Adriaan Canter (adriaanc) 09-Jan-1997 Created Adriaan Canter (adriaanc) 01-Feb-1997 Modified for per-user caches. The class CCookieLoader definition can now be pasted into the urlcache build without re-definition and work correctly, as long as the HKLM and HKCU cache keys are not modified. BUGBUG - do this. -----------------------------------------------------------------------------*/ #include #include #include #include #include "cachedef.h" #define INET_ASSERT(condition) Assert(condition) /*----------------------------------------------------------------------------- GetHKLMHistoryDirectory ----------------------------------------------------------------------------*/ DWORD GetHKLMHistoryDirectory(CHAR *szHistoryDirectory) { HKEY hKey = (HKEY) INVALID_HANDLE_VALUE; DWORD dwError, dwKeyType, cbKeyLen = MAX_PATH; // Skip the level of indirection for url history. if (dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Url History", NULL, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS) goto exit; if (dwError = RegQueryValueEx(hKey, CACHE_DIRECTORY_VALUE, NULL, &dwKeyType, (LPBYTE) szHistoryDirectory, &cbKeyLen) != ERROR_SUCCESS) goto exit; exit: if (hKey != INVALID_HANDLE_VALUE) CloseHandle(hKey); return dwError; } /*----------------------------------------------------------------------------- GetHKCUHistoryDirectory ----------------------------------------------------------------------------*/ DWORD GetHKCUHistoryDirectory(CHAR *szHistoryDirectory) { HKEY hKey = (HKEY) INVALID_HANDLE_VALUE; DWORD dwError, dwKeyType, cbKeyLen = MAX_PATH; CHAR szHistoryDirRegKey[MAX_PATH]; strcpy(szHistoryDirRegKey, OLD_CACHE_KEY); strcat(szHistoryDirRegKey, "\\"); strcat(szHistoryDirRegKey, HISTORY_PATH_KEY); if (dwError = RegOpenKeyEx(HKEY_CURRENT_USER, szHistoryDirRegKey, NULL, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS) goto exit; if (dwError = RegQueryValueEx(hKey, CACHE_PATH_VALUE, NULL, &dwKeyType, (LPBYTE) szHistoryDirectory, &cbKeyLen) != ERROR_SUCCESS) goto exit; exit: if (hKey != INVALID_HANDLE_VALUE) CloseHandle(hKey); return dwError; } /*----------------------------------------------------------------------------- GetHKLMCookiesDirectory ----------------------------------------------------------------------------*/ DWORD GetHKLMCookiesDirectory(CHAR *szCookiesDirectory) { HKEY hKey = (HKEY) INVALID_HANDLE_VALUE; DWORD dwError, dwKeyType, cbKeyLen = MAX_PATH; CHAR szCookiesDirRegKey[MAX_PATH]; strcpy(szCookiesDirRegKey, OLD_CACHE_KEY); strcat(szCookiesDirRegKey, "\\"); strcat(szCookiesDirRegKey, CACHE_SPECIAL_PATHS_KEY); strcat(szCookiesDirRegKey, "\\"); strcat(szCookiesDirRegKey, COOKIE_PATH_KEY); if (dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szCookiesDirRegKey, NULL, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS) goto exit; if (dwError = RegQueryValueEx(hKey, CACHE_DIRECTORY_VALUE, NULL, &dwKeyType, (LPBYTE) szCookiesDirectory, &cbKeyLen) != ERROR_SUCCESS) goto exit; exit: if (hKey != INVALID_HANDLE_VALUE) CloseHandle(hKey); return dwError; } /*----------------------------------------------------------------------------- GetHKCUCookiesDirectory ----------------------------------------------------------------------------*/ DWORD GetHKCUCookiesDirectory(CHAR *szCookiesDirectory) { HKEY hKey = (HKEY) INVALID_HANDLE_VALUE; DWORD dwError, dwKeyType, cbKeyLen = MAX_PATH; CHAR szCookiesDirRegKey[MAX_PATH]; strcpy(szCookiesDirRegKey, OLD_CACHE_KEY); strcat(szCookiesDirRegKey, "\\"); strcat(szCookiesDirRegKey, COOKIE_PATH_KEY); if (dwError = RegOpenKeyEx(HKEY_CURRENT_USER, szCookiesDirRegKey, NULL, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS) goto exit; if (dwError = RegQueryValueEx(hKey, CACHE_PATH_VALUE, NULL, &dwKeyType, (LPBYTE) szCookiesDirectory, &cbKeyLen) != ERROR_SUCCESS) goto exit; exit: if (hKey != INVALID_HANDLE_VALUE) CloseHandle(hKey); return dwError; } /*----------------------------------------------------------------------------- GetHKLMContentDirectory ----------------------------------------------------------------------------*/ DWORD GetHKLMContentDirectory(CHAR *szContentDirectory) { HKEY hKey = (HKEY) INVALID_HANDLE_VALUE; DWORD dwError, dwKeyType, cbKeyLen = MAX_PATH; CHAR szContentDirRegKey[MAX_PATH]; strcpy(szContentDirRegKey, CACHE_PATHS_FULL_KEY); if (dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szContentDirRegKey, NULL, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS) goto exit; if (dwError = RegQueryValueEx(hKey, CACHE_DIRECTORY_VALUE, NULL, &dwKeyType, (LPBYTE) szContentDirectory, &cbKeyLen) != ERROR_SUCCESS) goto exit; exit: if (hKey != INVALID_HANDLE_VALUE) CloseHandle(hKey); return dwError; } /*----------------------------------------------------------------------------- GetHKCUContentDirectory ----------------------------------------------------------------------------*/ DWORD GetHKCUContentDirectory(CHAR *szContentDirectory) { HKEY hKey = (HKEY) INVALID_HANDLE_VALUE; DWORD dwError, dwKeyType, cbKeyLen = MAX_PATH; CHAR szContentDirRegKey[MAX_PATH]; strcpy(szContentDirRegKey, OLD_CACHE_KEY); strcat(szContentDirRegKey, "\\"); strcat(szContentDirRegKey, CONTENT_PATH_KEY); if (dwError = RegOpenKeyEx(HKEY_CURRENT_USER, szContentDirRegKey, NULL, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS) goto exit; if (dwError = RegQueryValueEx(hKey, CACHE_PATH_VALUE, NULL, &dwKeyType, (LPBYTE) szContentDirectory, &cbKeyLen) != ERROR_SUCCESS) goto exit; exit: if (hKey != INVALID_HANDLE_VALUE) CloseHandle(hKey); return dwError; } /*----------------------------------------------------------------------------- class CCookieLoader Class used to perform cookie conversion ----------------------------------------------------------------------------*/ class CCookieLoader { public: CHAR* ParseNextCookie(CHAR*, CHAR**, FILETIME*, FILETIME*); DWORD LoadCookies(BOOL); }; // Debug assert code. #if DBG #define Assert(Predicate) \ { \ if (!(Predicate)) \ AssertFailed( #Predicate, __FILE__, __LINE__, NULL ); \ } VOID AssertFailed( LPSTR FailedAssertion, LPSTR FileName, DWORD LineNumber, LPSTR Message ) { printf("Assert @ %s \n", FailedAssertion ); printf("Assert Filename, %s \n", FileName ); printf("Line Num. = %ld.\n", LineNumber ); printf("Message is %s\n", Message ); DebugBreak(); } #else #define Assert(_x_) #endif // DBG /*----------------------------------------------------------------------------- CCookieLoader::ParseNextCookie Upgrades cookies from Cache Version 3.2 to Cache Version 4.0 ----------------------------------------------------------------------------*/ CHAR* CCookieLoader::ParseNextCookie(CHAR* ptr, CHAR** ppszHash, FILETIME* pftExpire, FILETIME* pftLast) { CHAR *pszName, *pszValue, *pszFlags, *pszExpireTimeLow, *pszExpireTimeHigh, *pszLastTimeHigh, *pszLastTimeLow, *pszDelimiter, *pszNextCookie; __try { // Get the first token (cookie name). pszName = strtok(ptr, "\n"); if (!pszName) // Cookie name. { // Normal termination of the parse. pszNextCookie = 0; goto exit; } // Parse the rest of the cookie pszValue = strtok(NULL, "\n"); // Cookie value. *ppszHash = strtok(NULL, "\n"); // Combo of domain and path. pszFlags = strtok(NULL, "\n"); // Cookie flags. pszExpireTimeLow = strtok(NULL, "\n"); // Expire time. pszExpireTimeHigh = strtok(NULL, "\n"); pszLastTimeLow = strtok(NULL, "\n"); // Last Modified time. pszLastTimeHigh = strtok(NULL, "\n"); pszDelimiter = strtok(NULL, "\n"); // Delimiter should be "*" // Abnormal termination of parse. if (!pszDelimiter || pszDelimiter[0] != '*') { INET_ASSERT(FALSE); pszNextCookie = 0; goto exit; } // Set the times. pftExpire->dwLowDateTime = atoi(pszExpireTimeLow); pftExpire->dwHighDateTime = atoi(pszExpireTimeHigh); pftLast->dwLowDateTime = atoi(pszLastTimeLow); pftLast->dwHighDateTime = atoi(pszLastTimeHigh); pszNextCookie = pszDelimiter+2; } __except(EXCEPTION_EXECUTE_HANDLER) { INET_ASSERT(FALSE); pszNextCookie = 0; goto exit; } exit: return pszNextCookie; } /*----------------------------------------------------------------------------- CCookieLoader::LoadCookies ----------------------------------------------------------------------------*/ DWORD CCookieLoader::LoadCookies(BOOL fConvertToPerUser) { HANDLE hFind = INVALID_HANDLE_VALUE; HANDLE hFile = INVALID_HANDLE_VALUE; FILETIME ftExpire, ftLast; CHAR szCookieFileName [MAX_PATH], szCookieFileNamePattern [MAX_PATH], szHKLMCookiesPath [MAX_PATH], szHKCUCookiesPath [MAX_PATH], szCookieName [MAX_PATH], szHKLMCookieFileName [MAX_PATH], szHKCUCookieFileName [MAX_PATH]; CHAR *pszHash, *ptr, *pszCookiesPath, *pszCurrentCookie, *szBuffer; WIN32_FIND_DATA FindData; BOOL bReturn; DWORD cbRead = 0, dwError = ERROR_SUCCESS; // Data for a single cookie should fit in 2 pages. BYTE bCacheEntryInfoBuffer[2 * PAGE_SIZE]; INTERNET_CACHE_ENTRY_INFO *pCacheEntryInfo; DWORD cbCacheEntryInfoBuffer; // Strictly enforced syntax: requires this to be initialized // before the try block is entered. szBuffer = 0; __try { // Check to see if we are upgrading cookies // from local machine to per user. if (fConvertToPerUser) { DWORD cb = MAX_PATH; CHAR szUserName[MAX_PATH]; // We are converting cookies from HKLM to HKCU. // This is done by enumerating the user's cookies // files and copying them to the per-user diretory. // Once this is accomplished, cookie converting will // proceed normally. // Get the cookies directory as specified by HKLM. if (dwError = GetHKLMCookiesDirectory(szHKLMCookiesPath) != ERROR_SUCCESS) { INET_ASSERT(FALSE); goto exit; } strcpy(szCookieFileNamePattern, szHKLMCookiesPath); // Get the cookies directory as specified by HKCU. if (dwError = GetHKCUCookiesDirectory(szHKCUCookiesPath) != ERROR_SUCCESS) { INET_ASSERT(FALSE); goto exit; } // Get the current user name. GetUserName(szUserName, &cb); // szCookieFileNamePattern will look like c:\winnt\cookies\joeuser@*.txt strcat(szCookieFileNamePattern, "\\"); strcat(szCookieFileNamePattern, szUserName); strcat(szCookieFileNamePattern, "@*.txt"); // Enumerate the users cache files hFind = FindFirstFile(szCookieFileNamePattern, &FindData); if (hFind == INVALID_HANDLE_VALUE) { // OK, No cookie files to upgrade. dwError = ERROR_SUCCESS; goto exit; } // One or more cookie files exist. do { // Construct absolute path from HKLM to cookies file. strcpy(szHKLMCookieFileName, szHKLMCookiesPath); strcat(szHKLMCookieFileName, "\\"); strcat(szHKLMCookieFileName, FindData.cFileName); // Construct absolute path from HKCU to cookies file. strcpy(szHKCUCookieFileName, szHKCUCookiesPath); strcat(szHKCUCookieFileName, "\\"); strcat(szHKCUCookieFileName, FindData.cFileName); // Copy the file to the per-user directory. CopyFile(szHKLMCookieFileName, szHKCUCookieFileName, TRUE); } while (FindNextFile(hFind, &FindData)); // Close the Find handle. if (hFind != INVALID_HANDLE_VALUE) { FindClose(hFind); hFind = INVALID_HANDLE_VALUE; } } // Per-user upgrade. else { // No per-user upgrade. szCookieFileNamePattern will look like // c:\winnt\cookies\*@*.txt or c:\winnt\profiles\joeuser\cookies\*@*.txt. GetHKLMCookiesDirectory(szHKLMCookiesPath); strcpy(szCookieFileNamePattern, szHKLMCookiesPath); strcat(szCookieFileNamePattern, "\\*@*.txt"); } // We now have the appropriate cookie filename pattern, also need a copy // of the cookies directory associated with the current user. pszCookiesPath = (fConvertToPerUser ? szHKCUCookiesPath : szHKLMCookiesPath); // Enumerate the cache files. hFind = FindFirstFile(szCookieFileNamePattern, &FindData); if (hFind == INVALID_HANDLE_VALUE) { // OK, No cookies files to upgrade. // BUGBUG - should we verify this? dwError = ERROR_SUCCESS; goto exit; } // One or more cookie files exist. do { // Construct absolute path to cookie file. strcpy(szCookieFileName, pszCookiesPath); strcat(szCookieFileName, "\\"); strcat(szCookieFileName, FindData.cFileName); // Open the cookie file. hFile = CreateFile( szCookieFileName, // Absolute path to cookies file. GENERIC_READ, // Read only. FILE_SHARE_READ, // Share. 0, // Security Attribute (ignored in W95). OPEN_EXISTING, // Fail if doesn't exist. FILE_ATTRIBUTE_NORMAL, // No special attributes. 0 // Attribute template. ); // File handle must be valid. if (hFile != INVALID_HANDLE_VALUE) { // Allocate memory for cookie file contents. // BUGBUG - put an upper limit on this? -> // 300 cookies * 4k/cookie = 1200k plus sundry. szBuffer = new CHAR[FindData.nFileSizeLow + 1]; if (!szBuffer) { dwError = ERROR_NOT_ENOUGH_MEMORY; goto exit; } // Read the file into memory. bReturn = ReadFile(hFile, szBuffer, FindData.nFileSizeLow, &cbRead, NULL); // ReadFile must be successful. INET_ASSERT(bReturn); if (bReturn) { // Null terminate buffer. szBuffer[cbRead] = '\0'; // Parse each cookie out of the buffer. pszCurrentCookie = szBuffer; while (pszCurrentCookie = ParseNextCookie(pszCurrentCookie, &pszHash, &ftExpire, &ftLast)) { // Construct the cookie name from the following strings: // FindData.cFileName is like "user@foobar.txt" // pszHash is like "foobar.com/" // szCookieName should then be "Cookie:user@foobar.com/" strcpy(szCookieName, COOKIE_PREFIX); strcat(szCookieName, FindData.cFileName); ptr = strstr(szCookieName, "@"); strcpy(ptr+1, pszHash); // Check to see if an earlier version of this cookie // has already been added to the cache index file. BOOL fAddToCache = TRUE; pCacheEntryInfo = (INTERNET_CACHE_ENTRY_INFO*) bCacheEntryInfoBuffer; cbCacheEntryInfoBuffer = sizeof(bCacheEntryInfoBuffer); dwError = GetUrlCacheEntryInfo(szCookieName, pCacheEntryInfo, &cbCacheEntryInfoBuffer); if (dwError == ERROR_SUCCESS && CompareFileTime(&pCacheEntryInfo->LastModifiedTime, &ftLast) > 0) fAddToCache = FALSE; if (fAddToCache) { // Either this cookie was not found in the index file or // it was found and the last modified time on it is // less than the currently parsed cookie. Proceed // to add this cookie to the index file. BOOL bCommit; bCommit = CommitUrlCacheEntry( szCookieName, // cookie:user@foobar.com. szCookieFileName, // c:\winnt\cookies\user@foobar.txt. ftExpire, // Expire time. ftLast, // Last modified time. 0, // CacheEntryType. 0, // HeaderInfo. 0, // HeaderSize. 0, // FileExtension. 0); // Reserved. INET_ASSERT(bCommit); } } // Successful next cookie field. } // Successful read. // Done with this cookie file. Delete the buffer. delete [] szBuffer; // And close the file CloseHandle(hFile); hFile = INVALID_HANDLE_VALUE; } // File handle is valid. } while (FindNextFile(hFind, &FindData)); // No more cookie files or an error occured. if ((dwError = GetLastError()) != ERROR_NO_MORE_FILES) goto exit; // Normal termination. dwError = ERROR_SUCCESS; exit: // Close the file handle. if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); // Close the Find handle. if (hFind != INVALID_HANDLE_VALUE) FindClose(hFind); return dwError; } // try __except(EXCEPTION_EXECUTE_HANDLER) { // Cleanup. delete [] szBuffer; if (hFind != INVALID_HANDLE_VALUE) FindClose(hFind); if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); INET_ASSERT(FALSE); dwError = ERROR_EXCEPTION_IN_SERVICE; return dwError; } } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { DWORD dwError; CHAR szFilename[MAX_PATH]; CHAR szHistoryIndexFile[MAX_PATH]; CHAR szCookiesIndexFile[MAX_PATH]; CHAR szContentIndexFile[MAX_PATH]; CCookieLoader cc; __try { // Convert cookies. Note, for ckcnv, we never // upgrade to per-user. dwError = cc.LoadCookies(FALSE); // Nuke all index.dat files so that re-installations will init properly. // Take care of HKLM entries only. // Content if (GetHKLMContentDirectory(szContentIndexFile) == ERROR_SUCCESS) { strcat(szContentIndexFile, "\\"); strcat(szContentIndexFile, MEMMAP_FILE_NAME); DeleteFile(szContentIndexFile); } // Cookies if (GetHKLMCookiesDirectory(szCookiesIndexFile) == ERROR_SUCCESS) { strcat(szCookiesIndexFile, "\\"); strcat(szCookiesIndexFile, MEMMAP_FILE_NAME); DeleteFile(szCookiesIndexFile); } // History if (GetHKLMHistoryDirectory(szHistoryIndexFile) == ERROR_SUCCESS) { strcat(szHistoryIndexFile, "\\"); strcat(szHistoryIndexFile, MEMMAP_FILE_NAME); DeleteFile(szHistoryIndexFile); } // See if we're supposed to delete this // executable after the user reboots. if (!_strnicmp(lpCmdLine, "/D", sizeof("/D"))) { // Got this filename? if (GetModuleFileName(NULL, szFilename, MAX_PATH)) { OSVERSIONINFO osVersionInfo; osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (GetVersionEx(&osVersionInfo)) { // Two different methods of deleting this file // depending on the platform ID. if (osVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) { // Platform is Windows NT. MoveFileEx(szFilename, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); } else { // Platform is Windows 95. CHAR szString[MAX_PATH]; strcpy(szString, "NUL="); strcat(szString, szFilename); WritePrivateProfileSection("Rename", szString, "wininit.ini"); } } } } } __except(EXCEPTION_EXECUTE_HANDLER) { INET_ASSERT(FALSE); dwError = ERROR_EXTENDED_ERROR; } return (dwError == ERROR_SUCCESS ? 0 : 1); }