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.

523 lines
18 KiB

  1. /*-----------------------------------------------------------------------------
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name: ckcnv.cxx
  4. Abstract:
  5. Upgrades cookies to present urlcache format by enumerating cookie files in the
  6. cache cookies directory and creates cookie cache index entries in the format of
  7. the current wininet.dll.
  8. Author:
  9. Adriaan Canter (adriaanc) 09-Jan-1997
  10. Created
  11. Adriaan Canter (adriaanc) 01-Feb-1997
  12. Modified for per-user caches. The class CCookieLoader definition
  13. can now be pasted into the urlcache build without re-definition
  14. and work correctly, as long as the HKLM and HKCU cache keys are
  15. not modified. BUGBUG - do this.
  16. -----------------------------------------------------------------------------*/
  17. #include <windows.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <wininet.h>
  21. #include "cachedef.h"
  22. #define INET_ASSERT(condition) Assert(condition)
  23. /*-----------------------------------------------------------------------------
  24. class CCookieLoader
  25. Class used to perform cookie conversion
  26. ----------------------------------------------------------------------------*/
  27. class CCookieLoader
  28. {
  29. private:
  30. DWORD GetHKLMCookiesDirectory(CHAR*);
  31. DWORD GetHKCUCookiesDirectory(CHAR*);
  32. CHAR* ParseNextCookie(CHAR*, CHAR**, FILETIME*, FILETIME*);
  33. public:
  34. DWORD LoadCookies(BOOL);
  35. };
  36. // Debug assert code.
  37. #if DBG
  38. #define Assert(Predicate) \
  39. { \
  40. if (!(Predicate)) \
  41. AssertFailed( #Predicate, __FILE__, __LINE__, NULL ); \
  42. }
  43. VOID
  44. AssertFailed(
  45. LPSTR FailedAssertion,
  46. LPSTR FileName,
  47. DWORD LineNumber,
  48. LPSTR Message
  49. )
  50. {
  51. printf("Assert @ %s \n", FailedAssertion );
  52. printf("Assert Filename, %s \n", FileName );
  53. printf("Line Num. = %ld.\n", LineNumber );
  54. printf("Message is %s\n", Message );
  55. DebugBreak();
  56. }
  57. #else
  58. #define Assert(_x_)
  59. #endif // DBG
  60. /*-----------------------------------------------------------------------------
  61. CCookieLoader::GetHKLMCookiesDirectory
  62. ----------------------------------------------------------------------------*/
  63. DWORD CCookieLoader::GetHKLMCookiesDirectory(CHAR *szCookiesDirectory)
  64. {
  65. HKEY hKey;
  66. DWORD dwError, dwKeyType, cbKeyLen = MAX_PATH;
  67. CHAR szCookiesDirRegKey[MAX_PATH];
  68. strcpy(szCookiesDirRegKey, CACHE_KEY);
  69. strcat(szCookiesDirRegKey, "\\");
  70. strcat(szCookiesDirRegKey, CACHE_SPECIAL_PATHS_KEY);
  71. strcat(szCookiesDirRegKey, "\\");
  72. strcat(szCookiesDirRegKey, COOKIE_PATH_KEY);
  73. if (dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  74. szCookiesDirRegKey, NULL, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS)
  75. goto exit;
  76. if (dwError = RegQueryValueEx(hKey, CACHE_DIRECTORY_VALUE, NULL, &dwKeyType,
  77. (LPBYTE) szCookiesDirectory, &cbKeyLen) != ERROR_SUCCESS)
  78. goto exit;
  79. exit:
  80. if (hKey != INVALID_HANDLE_VALUE)
  81. CloseHandle(hKey);
  82. return dwError;
  83. }
  84. /*-----------------------------------------------------------------------------
  85. CCookieLoader::GetHKCUCookiesDirectory
  86. ----------------------------------------------------------------------------*/
  87. DWORD CCookieLoader::GetHKCUCookiesDirectory(CHAR *szCookiesDirectory)
  88. {
  89. HKEY hKey;
  90. DWORD dwError, dwKeyType, cbKeyLen = MAX_PATH;
  91. CHAR szCookiesDirRegKey[MAX_PATH];
  92. strcpy(szCookiesDirRegKey, CACHE_KEY);
  93. strcat(szCookiesDirRegKey, "\\");
  94. strcat(szCookiesDirRegKey, COOKIE_PATH_KEY);
  95. if (dwError = RegOpenKeyEx(HKEY_CURRENT_USER,
  96. szCookiesDirRegKey, NULL, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS)
  97. goto exit;
  98. if (dwError = RegQueryValueEx(hKey, CACHE_DIRECTORY_VALUE, NULL, &dwKeyType,
  99. (LPBYTE) szCookiesDirectory, &cbKeyLen) != ERROR_SUCCESS)
  100. goto exit;
  101. exit:
  102. if (hKey != INVALID_HANDLE_VALUE)
  103. CloseHandle(hKey);
  104. return dwError;
  105. }
  106. /*-----------------------------------------------------------------------------
  107. CCookieLoader::ParseNextCookie
  108. Upgrades cookies from Cache Version 3.2 to Cache Version 4.0
  109. ----------------------------------------------------------------------------*/
  110. CHAR* CCookieLoader::ParseNextCookie(CHAR* ptr, CHAR** ppszHash,
  111. FILETIME* pftExpire, FILETIME* pftLast)
  112. {
  113. CHAR *pszName, *pszValue, *pszFlags,
  114. *pszExpireTimeLow, *pszExpireTimeHigh,
  115. *pszLastTimeHigh, *pszLastTimeLow,
  116. *pszDelimiter, *pszNextCookie;
  117. __try
  118. {
  119. // Get the first token (cookie name).
  120. pszName = StrTokEx(&ptr, "\n");
  121. if (!pszName) // Cookie name.
  122. {
  123. // Normal termination of the parse.
  124. pszNextCookie = 0;
  125. goto exit;
  126. }
  127. // Parse the rest of the cookie
  128. pszValue = StrTokEx(&ptr, "\n"); // Cookie value.
  129. *ppszHash = StrTokEx(&ptr, "\n"); // Combo of domain and path.
  130. pszFlags = StrTokEx(&ptr, "\n"); // Cookie flags.
  131. pszExpireTimeLow = StrTokEx(&ptr, "\n"); // Expire time.
  132. pszExpireTimeHigh = StrTokEx(&ptr, "\n");
  133. pszLastTimeLow = StrTokEx(&ptr, "\n"); // Last Modified time.
  134. pszLastTimeHigh = StrTokEx(&ptr, "\n");
  135. pszDelimiter = StrTokEx(&ptr, "\n"); // Delimiter should be "*"
  136. // Abnormal termination of parse.
  137. if (!pszDelimiter || pszDelimiter[0] != '*')
  138. {
  139. INET_ASSERT(FALSE);
  140. pszNextCookie = 0;
  141. goto exit;
  142. }
  143. // Set the times.
  144. pftExpire->dwLowDateTime = atoi(pszExpireTimeLow);
  145. pftExpire->dwHighDateTime = atoi(pszExpireTimeHigh);
  146. pftLast->dwLowDateTime = atoi(pszLastTimeLow);
  147. pftLast->dwHighDateTime = atoi(pszLastTimeHigh);
  148. pszNextCookie = pszDelimiter+2;
  149. }
  150. __except(EXCEPTION_EXECUTE_HANDLER)
  151. {
  152. INET_ASSERT(FALSE);
  153. pszNextCookie = 0;
  154. goto exit;
  155. }
  156. exit:
  157. return pszNextCookie;
  158. }
  159. /*-----------------------------------------------------------------------------
  160. CCookieLoader::LoadCookies
  161. ----------------------------------------------------------------------------*/
  162. DWORD CCookieLoader::LoadCookies(BOOL fConvertToPerUser)
  163. {
  164. HANDLE hFind = INVALID_HANDLE_VALUE;
  165. HANDLE hFile = INVALID_HANDLE_VALUE;
  166. FILETIME ftExpire, ftLast;
  167. CHAR szCookieFileName [MAX_PATH],
  168. szCookieFileNamePattern [MAX_PATH],
  169. szHKLMCookiesPath [MAX_PATH],
  170. szHKCUCookiesPath [MAX_PATH],
  171. szCookieName [MAX_PATH],
  172. szHKLMCookieFileName [MAX_PATH],
  173. szHKCUCookieFileName [MAX_PATH];
  174. CHAR *pszHash, *ptr, *pszCookiesPath,
  175. *pszCurrentCookie, *szBuffer;
  176. WIN32_FIND_DATA FindData;
  177. BOOL bReturn;
  178. DWORD cbRead = 0, dwError = ERROR_SUCCESS;
  179. // Data for a single cookie should fit in 2 pages.
  180. BYTE bCacheEntryInfoBuffer[2 * PAGE_SIZE];
  181. INTERNET_CACHE_ENTRY_INFO *pCacheEntryInfo;
  182. DWORD cbCacheEntryInfoBuffer;
  183. __try
  184. {
  185. szBuffer = 0;
  186. // Check to see if we are upgrading cookies
  187. // from local machine to per user.
  188. if (fConvertToPerUser)
  189. {
  190. DWORD cb = MAX_PATH;
  191. CHAR szUserName[MAX_PATH];
  192. // We are converting cookies from HKLM to HKCU.
  193. // This is done by enumerating the user's cookies
  194. // files and copying them to the per-user diretory.
  195. // Once this is accomplished, cookie converting will
  196. // proceed normally.
  197. // Get the cookies directory as specified by HKLM.
  198. if (dwError = GetHKLMCookiesDirectory(szHKLMCookiesPath) != ERROR_SUCCESS)
  199. {
  200. INET_ASSERT(FALSE);
  201. goto exit;
  202. }
  203. strcpy(szCookieFileNamePattern, szHKLMCookiesPath);
  204. // Get the cookies directory as specified by HKCU.
  205. if (dwError = GetHKCUCookiesDirectory(szHKCUCookiesPath) != ERROR_SUCCESS)
  206. {
  207. INET_ASSERT(FALSE);
  208. goto exit;
  209. }
  210. // Get the current user name.
  211. GetUserName(szUserName, &cb);
  212. // szCookieFileNamePattern will look like c:\winnt\cookies\joeuser@*.txt
  213. strcat(szCookieFileNamePattern, "\\");
  214. strcat(szCookieFileNamePattern, szUserName);
  215. strcat(szCookieFileNamePattern, "@*.txt");
  216. // Enumerate the users cache files
  217. hFind = FindFirstFile(szCookieFileNamePattern, &FindData);
  218. if (hFind == INVALID_HANDLE_VALUE)
  219. {
  220. // OK, No cookie files to upgrade.
  221. dwError = ERROR_SUCCESS;
  222. goto exit;
  223. }
  224. // One or more cookie files exist.
  225. do
  226. {
  227. // Construct absolute path from HKLM to cookies file.
  228. strcpy(szHKLMCookieFileName, szHKLMCookiesPath);
  229. strcat(szHKLMCookieFileName, "\\");
  230. strcat(szHKLMCookieFileName, FindData.cFileName);
  231. // Construct absolute path from HKCU to cookies file.
  232. strcpy(szHKCUCookieFileName, szHKCUCookiesPath);
  233. strcat(szHKCUCookieFileName, "\\");
  234. strcat(szHKCUCookieFileName, FindData.cFileName);
  235. // Copy the file to the per-user directory.
  236. CopyFile(szHKLMCookieFileName, szHKCUCookieFileName, TRUE);
  237. } while (FindNextFile(hFind, &FindData));
  238. // Close the Find handle.
  239. if (hFind != INVALID_HANDLE_VALUE)
  240. {
  241. FindClose(hFind);
  242. hFind = INVALID_HANDLE_VALUE;
  243. }
  244. } // Per-user upgrade.
  245. else
  246. {
  247. // No per-user upgrade. szCookieFileNamePattern will look like
  248. // c:\winnt\cookies\*@*.txt or c:\winnt\profiles\joeuser\cookies\*@*.txt.
  249. GetHKLMCookiesDirectory(szHKLMCookiesPath);
  250. strcpy(szCookieFileNamePattern, szHKLMCookiesPath);
  251. strcat(szCookieFileNamePattern, "\\*@*.txt");
  252. }
  253. // We now have the appropriate cookie filename pattern, also need a copy
  254. // of the cookies directory associated with the current user.
  255. pszCookiesPath = (fConvertToPerUser ? szHKCUCookiesPath : szHKLMCookiesPath);
  256. // Enumerate the cache files.
  257. hFind = FindFirstFile(szCookieFileNamePattern, &FindData);
  258. if (hFind == INVALID_HANDLE_VALUE)
  259. {
  260. // OK, No cookies files to upgrade.
  261. // BUGBUG - should we verify this?
  262. dwError = ERROR_SUCCESS;
  263. goto exit;
  264. }
  265. // One or more cookie files exist.
  266. do
  267. {
  268. // Construct absolute path to cookie file.
  269. strcpy(szCookieFileName, pszCookiesPath);
  270. strcat(szCookieFileName, "\\");
  271. strcat(szCookieFileName, FindData.cFileName);
  272. // Open the cookie file.
  273. hFile = CreateFile(
  274. szCookieFileName, // Absolute path to cookies file.
  275. GENERIC_READ, // Read only.
  276. FILE_SHARE_READ, // Share.
  277. 0, // Security Attribute (ignored in W95).
  278. OPEN_EXISTING, // Fail if doesn't exist.
  279. FILE_ATTRIBUTE_NORMAL, // No special attributes.
  280. 0 // Attribute template.
  281. );
  282. // File handle must be valid.
  283. if (hFile != INVALID_HANDLE_VALUE)
  284. {
  285. // Allocate memory for cookie file contents.
  286. // BUGBUG - put an upper limit on this? ->
  287. // 300 cookies * 4k/cookie = 1200k plus sundry.
  288. szBuffer = new CHAR[FindData.nFileSizeLow + 1];
  289. if (!szBuffer)
  290. {
  291. dwError = ERROR_NOT_ENOUGH_MEMORY;
  292. goto exit;
  293. }
  294. // Read the file into memory.
  295. bReturn = ReadFile(hFile, szBuffer, FindData.nFileSizeLow, &cbRead, NULL);
  296. // ReadFile must be successful.
  297. INET_ASSERT(bReturn);
  298. if (bReturn)
  299. {
  300. // Null terminate buffer.
  301. szBuffer[cbRead] = '\0';
  302. // Parse each cookie out of the buffer.
  303. pszCurrentCookie = szBuffer;
  304. while (pszCurrentCookie = ParseNextCookie(pszCurrentCookie,
  305. &pszHash, &ftExpire, &ftLast))
  306. {
  307. // Construct the cookie name from the following strings:
  308. // FindData.cFileName is like "[email protected]"
  309. // pszHash is like "foobar.com/"
  310. // szCookieName should then be "Cookie:[email protected]/"
  311. strcpy(szCookieName, COOKIE_PREFIX);
  312. strcat(szCookieName, FindData.cFileName);
  313. ptr = strstr(szCookieName, "@");
  314. strcpy(ptr+1, pszHash);
  315. // Check to see if an earlier version of this cookie
  316. // has already been added to the cache index file.
  317. BOOL fAddToCache = TRUE;
  318. pCacheEntryInfo = (INTERNET_CACHE_ENTRY_INFO*) bCacheEntryInfoBuffer;
  319. cbCacheEntryInfoBuffer = sizeof(bCacheEntryInfoBuffer);
  320. dwError = GetUrlCacheEntryInfo(szCookieName, pCacheEntryInfo,
  321. &cbCacheEntryInfoBuffer);
  322. if (dwError == ERROR_SUCCESS
  323. && CompareFileTime(&pCacheEntryInfo->LastModifiedTime, &ftLast) > 0)
  324. fAddToCache = FALSE;
  325. if (fAddToCache)
  326. {
  327. // Either this cookie was not found in the index file or
  328. // it was found and the last modified time on it is
  329. // less than the currently parsed cookie. Proceed
  330. // to add this cookie to the index file.
  331. BOOL bCommit;
  332. bCommit = CommitUrlCacheEntry(
  333. szCookieName, // cookie:[email protected].
  334. szCookieFileName, // c:\winnt\cookies\[email protected].
  335. ftExpire, // Expire time.
  336. ftLast, // Last modified time.
  337. 0, // CacheEntryType.
  338. 0, // HeaderInfo.
  339. 0, // HeaderSize.
  340. 0, // FileExtension.
  341. 0); // Reserved.
  342. INET_ASSERT(bCommit);
  343. }
  344. } // Successful next cookie field.
  345. } // Successful read.
  346. // Done with this cookie file. Delete the buffer.
  347. delete [] szBuffer;
  348. // And close the file
  349. CloseHandle(hFile);
  350. hFile = INVALID_HANDLE_VALUE;
  351. } // File handle is valid.
  352. } while (FindNextFile(hFind, &FindData));
  353. // No more cookie files or an error occured.
  354. if ((dwError = GetLastError()) != ERROR_NO_MORE_FILES)
  355. goto exit;
  356. // Normal termination.
  357. dwError = ERROR_SUCCESS;
  358. exit:
  359. // Close the file handle.
  360. if (hFile != INVALID_HANDLE_VALUE)
  361. CloseHandle(hFile);
  362. // Close the Find handle.
  363. if (hFind != INVALID_HANDLE_VALUE)
  364. FindClose(hFind);
  365. return dwError;
  366. } // try
  367. __except(EXCEPTION_EXECUTE_HANDLER)
  368. {
  369. // Cleanup.
  370. delete [] szBuffer;
  371. if (hFind != INVALID_HANDLE_VALUE)
  372. FindClose(hFind);
  373. if (hFile != INVALID_HANDLE_VALUE)
  374. CloseHandle(hFile);
  375. INET_ASSERT(FALSE);
  376. dwError = ERROR_EXCEPTION_IN_SERVICE;
  377. return dwError;
  378. }
  379. }
  380. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  381. {
  382. DWORD dwError;
  383. CHAR szFilename[MAX_PATH];
  384. CCookieLoader cc;
  385. __try
  386. {
  387. // Convert cookies.
  388. dwError = cc.LoadCookies(FALSE);
  389. // See if we're supposed to delete this
  390. // executable after the user reboots.
  391. if (!_strnicmp(lpCmdLine, "/D", sizeof("/D")))
  392. {
  393. // Got this filename?
  394. if (GetModuleFileName(NULL, szFilename, MAX_PATH))
  395. {
  396. OSVERSIONINFO osVersionInfo;
  397. osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  398. if (GetVersionEx(&osVersionInfo))
  399. {
  400. // Two different methods of deleting this file
  401. // depending on the platform ID.
  402. if (osVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  403. {
  404. // Platform is Windows NT.
  405. MoveFileEx(szFilename, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  406. }
  407. else
  408. {
  409. // Platform is Windows 95
  410. WriteProfileSection("NUL", szFilename);
  411. }
  412. }
  413. }
  414. }
  415. }
  416. __except(EXCEPTION_EXECUTE_HANDLER)
  417. {
  418. INET_ASSERT(FALSE);
  419. dwError = ERROR_EXTENDED_ERROR;
  420. }
  421. return (dwError == ERROR_SUCCESS ? 0 : 1);
  422. }