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.

531 lines
15 KiB

  1. /*++
  2. Copyright (c) 1994-2000 Microsoft Corporation
  3. Module Name:
  4. ids.cxx
  5. Abstract:
  6. Contains functions responsible for managing identities in wininet
  7. Contents:
  8. Author:
  9. July - September 1999. akabir
  10. Environment:
  11. Win32 user-mode DLL
  12. Revision History:
  13. --*/
  14. #include <cache.hxx>
  15. #include <hlink.h>
  16. #include <urlmon.h>
  17. #include <shlobj.h>
  18. #define HMONITOR_DECLARED 1
  19. #include <shlobjp.h>
  20. // -- whatever -----------------------------------------------------------------------------------------------
  21. #undef SHGetFolderPath
  22. HRESULT SHGetFolderPath(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPSTR pszPath);
  23. typedef HRESULT (*PFNSHGETDESKTOPFOLDER)(IShellFolder**);
  24. HRESULT _SHGetDesktopFolder(IShellFolder **psfDesktop)
  25. {
  26. HMODULE h = LoadLibrary("shell32.dll");
  27. HRESULT hr = E_POINTER;
  28. if (h)
  29. {
  30. PFNSHGETDESKTOPFOLDER pfn = (PFNSHGETDESKTOPFOLDER)GetProcAddress(h, "SHGetDesktopFolder");
  31. if (pfn)
  32. {
  33. hr = pfn(psfDesktop);
  34. }
  35. FreeLibrary(h);
  36. }
  37. return hr;
  38. }
  39. typedef VOID (*PFNILFREE)(LPITEMIDLIST);
  40. VOID _ILFree(LPITEMIDLIST pidl)
  41. {
  42. HMODULE h = LoadLibrary("shell32.dll");
  43. if (h)
  44. {
  45. PFNILFREE pfn = (PFNILFREE)GetProcAddress(h, "ILFree");
  46. if (pfn)
  47. {
  48. pfn(pidl);
  49. }
  50. FreeLibrary(h);
  51. }
  52. }
  53. const GUID DefaultGuid = { 0x00000000L, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  54. const GUID IID_IHistSFPrivate = { 0x62e1261L, 0xa60e, 0x11d0, 0x82, 0xc2, 0x0, 0xc0, 0x4f, 0xd5, 0xae, 0x38 };
  55. // -- Utility functions --------------------------------------------------------------------------------------
  56. // Create an ansi representation of a guid.
  57. VOID GuidToAnsiStr(GUID* pGuid, PSTR psz, DWORD dwSize)
  58. {
  59. WCHAR wszUid[MAX_PATH];
  60. StringFromGUID2(*pGuid, wszUid, ARRAY_ELEMENTS(wszUid));
  61. SHUnicodeToAnsi(wszUid, psz, dwSize);
  62. }
  63. REGISTRY_OBJ* CreateExtensiRegObjFor(HKEY hKey, GUID* pguid)
  64. {
  65. REGISTRY_OBJ *pro = NULL;
  66. CHAR sz[MAX_PATH];
  67. GuidToAnsiStr(pguid, sz, ARRAY_ELEMENTS(sz));
  68. CHAR szBranches[MAX_PATH];
  69. if (wnsprintf(szBranches, ARRAY_ELEMENTS(szBranches),
  70. "%s\\%s\\%s",
  71. IDENTITIES_KEY,
  72. sz,
  73. EXTENSIBLE_CACHE_PATH_KEY) >= 0)
  74. {
  75. pro = new REGISTRY_OBJ(hKey, szBranches, CREATE_KEY_IF_NOT_EXISTS);
  76. }
  77. return pro;
  78. }
  79. #ifdef WININET6
  80. DWORD IDRegDwordCore(LPCTSTR psz, PDWORD pdw, BOOL fSet)
  81. {
  82. INET_ASSERT(GlobalIdentity);
  83. CHAR sz[MAX_PATH];
  84. GuidToAnsiStr(&GlobalIdentityGuid, sz, ARRAY_ELEMENTS(sz));
  85. CHAR szBranches[MAX_PATH];
  86. DWORD dwError = ERROR_INVALID_PARAMETER;
  87. if (wnsprintf(szBranches, ARRAY_ELEMENTS(szBranches),
  88. "%s\\%s",
  89. IDENTITIES_KEY,
  90. sz) >= 0)
  91. {
  92. REGISTRY_OBJ ro(GlobalCacheHKey, szBranches);
  93. dwError = ro.GetStatus();
  94. if (dwError==ERROR_SUCCESS)
  95. {
  96. dwError = fSet ? ro.SetValue((LPTSTR)psz, pdw)
  97. : ro.GetValue((LPTSTR)psz, pdw);
  98. }
  99. }
  100. return dwError;
  101. }
  102. DWORD ReadIDRegDword(LPCTSTR psz, PDWORD pdw)
  103. {
  104. return IDRegDwordCore(psz, pdw, FALSE);
  105. }
  106. DWORD WriteIDRegDword(LPCTSTR psz, DWORD dw)
  107. {
  108. return IDRegDwordCore(psz, &dw, TRUE);
  109. }
  110. #endif
  111. VOID CreateCurrentHistory()
  112. {
  113. INTERNET_CACHE_CONFIG_INFO icci;
  114. icci.dwStructSize = sizeof(icci);
  115. if (GlobalUrlContainers->GetUrlCacheConfigInfo(&icci, NULL, CACHE_CONFIG_HISTORY_PATHS_FC)
  116. && SUCCEEDED(CoInitialize(NULL)))
  117. {
  118. // We want to ensure that the history is valid for this user.
  119. IShellFolder *psfDesktop;
  120. if (SUCCEEDED(_SHGetDesktopFolder(&psfDesktop)))
  121. {
  122. WCHAR wszPath[MAX_PATH];
  123. LPITEMIDLIST pidlHistory;
  124. IShellFolder *psfHistory;
  125. MultiByteToWideChar(CP_ACP, 0, icci.CachePath, -1, wszPath, ARRAY_ELEMENTS(wszPath));
  126. PathRemoveFileSpecW(wszPath); // get the trailing slash
  127. PathRemoveFileSpecW(wszPath); // get the trailing slash
  128. PathRemoveFileSpecW(wszPath); // trim the "content.ie5" junk
  129. if (SUCCEEDED(psfDesktop->ParseDisplayName(NULL, NULL, wszPath, NULL, &pidlHistory, NULL)))
  130. {
  131. if (SUCCEEDED(psfDesktop->BindToObject(pidlHistory, NULL, IID_IShellFolder, (VOID**)&psfHistory)))
  132. {
  133. IHistSFPrivate *phsf;
  134. if (SUCCEEDED(psfHistory->QueryInterface(IID_IHistSFPrivate, (void**)&phsf)))
  135. {
  136. FILETIME ftBogus = { 0 };
  137. // This forces the validation in shdocvw
  138. phsf->WriteHistory(L"", ftBogus, ftBogus, NULL);
  139. phsf->Release();
  140. }
  141. psfHistory->Release();
  142. }
  143. _ILFree(pidlHistory);
  144. }
  145. psfDesktop->Release();
  146. }
  147. CoUninitialize();
  148. }
  149. }
  150. CONST TCHAR c_szIdentityOrdinal[] = "Identity Ordinal";
  151. DWORD MapGuidToOrdinal(GUID* lpGUID)
  152. {
  153. DWORD dwOrdinal = 0;
  154. HKEY hSourceSubKey;
  155. if (!memcmp(lpGUID, &DefaultGuid, sizeof(DefaultGuid)))
  156. {
  157. return 0;
  158. }
  159. if (RegCreateKey(HKEY_CURRENT_USER, IDENTITIES_KEY, &hSourceSubKey) == ERROR_SUCCESS)
  160. {
  161. CHAR szUid[MAX_PATH];
  162. GuidToAnsiStr(lpGUID, szUid, ARRAY_ELEMENTS(szUid));
  163. DWORD dwSize, dwType;
  164. DWORD dwIdentityOrdinal = 1;
  165. dwSize = sizeof(dwIdentityOrdinal);
  166. RegQueryValueEx(hSourceSubKey, c_szIdentityOrdinal, NULL, &dwType, (LPBYTE)&dwIdentityOrdinal, &dwSize);
  167. HKEY hkUserKey;
  168. if (RegCreateKey(hSourceSubKey, szUid, &hkUserKey) == ERROR_SUCCESS)
  169. {
  170. if (RegQueryValueEx(hkUserKey, c_szIdentityOrdinal, NULL, &dwType, (LPBYTE)&dwOrdinal, &dwSize)!=ERROR_SUCCESS)
  171. {
  172. if (RegSetValueEx(hkUserKey, c_szIdentityOrdinal, NULL, REG_DWORD, (LPBYTE)&dwIdentityOrdinal, dwSize)==ERROR_SUCCESS)
  173. {
  174. dwOrdinal = dwIdentityOrdinal++;
  175. RegSetValueEx(hSourceSubKey, c_szIdentityOrdinal, 0, REG_DWORD, (LPBYTE)&dwIdentityOrdinal, dwSize);
  176. }
  177. }
  178. RegCloseKey(hkUserKey);
  179. }
  180. RegCloseKey(hSourceSubKey);
  181. }
  182. INET_ASSERT(dwOrdinal);
  183. return dwOrdinal;
  184. }
  185. DWORD AlterIdentity(DWORD dwFlags)
  186. {
  187. if (!GlobalIdentity)
  188. {
  189. return ERROR_INVALID_PARAMETER;
  190. }
  191. switch (dwFlags)
  192. {
  193. case INTERNET_IDENTITY_FLAG_PRIVATE_CACHE:
  194. case INTERNET_IDENTITY_FLAG_SHARED_CACHE:
  195. case INTERNET_IDENTITY_FLAG_CLEAR_DATA:
  196. case INTERNET_IDENTITY_FLAG_CLEAR_COOKIES:
  197. case INTERNET_IDENTITY_FLAG_CLEAR_HISTORY:
  198. case INTERNET_IDENTITY_FLAG_CLEAR_CONTENT:
  199. break;
  200. }
  201. return ERROR_CALL_NOT_IMPLEMENTED;
  202. }
  203. DWORD RemoveIdentity(GUID* pguidIdentity)
  204. {
  205. if (!pguidIdentity
  206. || !memcmp(pguidIdentity, &DefaultGuid, sizeof(DefaultGuid)))
  207. {
  208. return ERROR_INVALID_PARAMETER;
  209. }
  210. CHAR szUid[MAX_PATH];
  211. GuidToAnsiStr(pguidIdentity, szUid, ARRAY_ELEMENTS(szUid));
  212. DWORD dwIdentity = MapGuidToOrdinal(pguidIdentity);
  213. if (dwIdentity==GlobalIdentity)
  214. {
  215. DWORD dwErr = SwitchIdentity(NULL);
  216. if (dwErr!=ERROR_SUCCESS)
  217. return dwErr;
  218. }
  219. DWORD dwErr = ERROR_INVALID_PARAMETER;
  220. REGISTRY_OBJ roIds(HKEY_CURRENT_USER, IDENTITIES_KEY);
  221. if (roIds.GetStatus()==ERROR_SUCCESS)
  222. {
  223. // We want to delete the containers before we delete the reg keys.
  224. // First the extensible containers
  225. REGISTRY_OBJ* pro = CreateExtensiRegObjFor(HKEY_CURRENT_USER, pguidIdentity);
  226. if (pro && (pro->GetStatus()==ERROR_SUCCESS))
  227. {
  228. CHAR szVendorKey[MAX_PATH];
  229. while (pro->FindNextKey(szVendorKey, MAX_PATH) == ERROR_SUCCESS)
  230. {
  231. REGISTRY_OBJ roVendor(pro, szVendorKey);
  232. if (roVendor.GetStatus()==ERROR_SUCCESS)
  233. {
  234. TCHAR szPath[MAX_PATH];
  235. DWORD ccKeyLen = ARRAY_ELEMENTS(szPath);
  236. if (roVendor.GetValue(CACHE_PATH_VALUE, (LPBYTE) szPath, &ccKeyLen)==ERROR_SUCCESS)
  237. {
  238. TCHAR szScratch[MAX_PATH+1];
  239. ExpandEnvironmentStrings(szPath, szScratch, ARRAY_ELEMENTS(szScratch)-1); // don't count the NULL
  240. DeleteCachedFilesInDir(szScratch);
  241. RemoveDirectory(szScratch);
  242. }
  243. }
  244. }
  245. }
  246. if (pro)
  247. {
  248. delete pro;
  249. }
  250. TCHAR szPath[MAX_PATH];
  251. if ((S_OK==SHGetFolderPath(NULL, CSIDL_COOKIES | CSIDL_FLAG_CREATE, NULL, 0, szPath))
  252. && (*szPath!='\0'))
  253. {
  254. if (GenerateStringWithOrdinal(NULL, dwIdentity, szPath, ARRAY_ELEMENTS(szPath)))
  255. {
  256. DeleteCachedFilesInDir(szPath);
  257. RemoveDirectory(szPath);
  258. }
  259. }
  260. if ((S_OK==SHGetFolderPath(NULL, CSIDL_HISTORY | CSIDL_FLAG_CREATE, NULL, 0, szPath))
  261. && (*szPath!='\0'))
  262. {
  263. StrCatBuff(szPath, "\\History.IE5", ARRAY_ELEMENTS(szPath));
  264. if (GenerateStringWithOrdinal(NULL, dwIdentity, szPath, ARRAY_ELEMENTS(szPath)))
  265. {
  266. DeleteCachedFilesInDir(szPath);
  267. RemoveDirectory(szPath);
  268. }
  269. }
  270. // We'll leave the content; it'll be scavenged anyway.
  271. if (roIds.DeleteKey(szUid)==ERROR_SUCCESS)
  272. {
  273. dwErr = ERROR_SUCCESS;
  274. }
  275. }
  276. return dwErr;
  277. }
  278. DWORD SwitchIdentity(GUID* pguidIdentity)
  279. {
  280. DWORD dwIdentity = pguidIdentity ? MapGuidToOrdinal(pguidIdentity) : 0;
  281. if (dwIdentity==GlobalIdentity)
  282. return ERROR_SUCCESS;
  283. DWORD dwErr = ERROR_SUCCESS;
  284. LOCK_CACHE();
  285. INET_ASSERT(dwIdentity!=GlobalIdentity);
  286. CloseTheCookieJar();
  287. DWORD dwTemp = GlobalIdentity;
  288. GUID guidTemp;
  289. GlobalIdentity = dwIdentity;
  290. GlobalCacheInitialized = FALSE;
  291. memcpy(&guidTemp, &GlobalIdentityGuid, sizeof(GlobalIdentityGuid));
  292. if (dwIdentity==0)
  293. {
  294. memset(&GlobalIdentityGuid, 0, sizeof(GlobalIdentityGuid));
  295. }
  296. else
  297. {
  298. memcpy(&GlobalIdentityGuid, pguidIdentity, sizeof(*pguidIdentity));
  299. }
  300. CConMgr* NewGUC = new CConMgr();
  301. if (!NewGUC
  302. || (NewGUC->GetStatus()!=ERROR_SUCCESS)
  303. || (!InternetSetOption(NULL, INTERNET_OPTION_END_BROWSER_SESSION, NULL, 0)))
  304. {
  305. INET_ASSERT(FALSE);
  306. if (NewGUC)
  307. delete NewGUC;
  308. dwErr = ERROR_INTERNET_INTERNAL_ERROR;
  309. GlobalCacheInitialized = TRUE;
  310. GlobalIdentity = dwTemp;
  311. memcpy(&GlobalIdentityGuid, &guidTemp, sizeof(GlobalIdentityGuid));
  312. goto exit;
  313. }
  314. // We need to stop the scavenger
  315. GlobalPleaseQuitWhatYouAreDoing = TRUE;
  316. while (GlobalScavengerRunning!=-1)
  317. {
  318. Sleep(0);
  319. }
  320. delete GlobalUrlContainers;
  321. GlobalUrlContainers = NewGUC;
  322. GlobalCacheInitialized = TRUE;
  323. // It's safe now, you can scavenge
  324. GlobalPleaseQuitWhatYouAreDoing = FALSE;
  325. if (AnyFindsInProgress(0))
  326. {
  327. HandleMgr.InvalidateAll();
  328. }
  329. CreateCurrentHistory();
  330. // Note to ASK: check what this call does, if it affects identities
  331. if ((dwErr = GlobalUrlContainers->CreateDefaultGroups())!=ERROR_SUCCESS)
  332. goto exit;
  333. if (!OpenTheCookieJar())
  334. {
  335. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  336. goto exit;
  337. }
  338. #ifdef WININET6
  339. // Set warnings appropriately.
  340. GlobalWarnOnPost = FALSE;
  341. GlobalWarnAlways = FALSE;
  342. GlobalWarnOnZoneCrossing = TRUE;
  343. GlobalWarnOnBadCertSending = FALSE;
  344. GlobalWarnOnBadCertRecving = TRUE;
  345. GlobalWarnOnPostRedirect = TRUE;
  346. GlobalDataReadWarningUIFlags();
  347. #endif
  348. exit:
  349. UNLOCK_CACHE();
  350. INET_ASSERT((dwErr==ERROR_SUCCESS));
  351. return dwErr;
  352. }
  353. // CreateExtensiRegObj ----------------
  354. // Create an identity-appropriate registry object
  355. // for extensible cache containers.
  356. REGISTRY_OBJ* CreateExtensiRegObj(HKEY hKey)
  357. {
  358. REGISTRY_OBJ *pro = NULL;
  359. if (GlobalIdentity)
  360. {
  361. pro = CreateExtensiRegObjFor(hKey, &GlobalIdentityGuid);
  362. }
  363. else
  364. {
  365. REGISTRY_OBJ roCache(hKey, CACHE5_KEY);
  366. if (roCache.GetStatus()==ERROR_SUCCESS)
  367. {
  368. pro = new REGISTRY_OBJ(&roCache, EXTENSIBLE_CACHE_PATH_KEY, CREATE_KEY_IF_NOT_EXISTS);
  369. }
  370. }
  371. if (pro && pro->GetStatus()!=ERROR_SUCCESS)
  372. {
  373. delete pro;
  374. pro = NULL;
  375. }
  376. return pro;
  377. }
  378. // GenerateStringWithOrdinal ------------
  379. // We want to append the identity ordinal to a string
  380. // If psz is null, then pszBuffer better contain a 0-terminated string that we can
  381. // append the ordinal to.
  382. // Otherwise, we copy psz to pszBuffer and append to that.
  383. BOOL GenerateStringWithOrdinal(PCTSTR psz, DWORD dwOrdinal, PTSTR pszBuffer, DWORD dwMax)
  384. {
  385. DWORD cc = psz ? lstrlen(psz) : lstrlen(pszBuffer);
  386. if (cc>dwMax)
  387. return FALSE;
  388. if (psz)
  389. {
  390. memcpy(pszBuffer, psz, cc*sizeof(*pszBuffer));
  391. }
  392. if (dwOrdinal)
  393. {
  394. if (!AppendSlashIfNecessary(pszBuffer, &cc))
  395. return FALSE;
  396. if (wnsprintf(pszBuffer+cc, dwMax-cc,
  397. "%d",
  398. dwOrdinal) < 0)
  399. return FALSE;
  400. }
  401. else
  402. {
  403. pszBuffer[cc] = TEXT('\0');
  404. }
  405. return TRUE;
  406. }
  407. // IsPerUserEntry
  408. // Examine the headers of a cache entry to determine whether or
  409. // not it is user-specific
  410. BOOL IsPerUserEntry(LPURL_FILEMAP_ENTRY pfe)
  411. {
  412. INET_ASSERT(pfe);
  413. BOOL fRet = FALSE;
  414. PTSTR lpszHeaderInfo = (PTSTR)pfe + pfe->HeaderInfoOffset;
  415. DWORD dwHeaderSize = pfe->HeaderInfoSize;
  416. if (!lpszHeaderInfo || !dwHeaderSize)
  417. {
  418. return FALSE;
  419. }
  420. LPSTR lpTemp = lpszHeaderInfo+dwHeaderSize-1;
  421. LPSTR lpTemp2;
  422. // start searching backwards
  423. while (lpTemp >= lpszHeaderInfo)
  424. {
  425. if (*lpTemp ==':')
  426. {
  427. // compare with "~U:"
  428. fRet = (!strnicmp(lpTemp-2, vszUserNameHeader, sizeof(vszUserNameHeader)-1))
  429. // guarantee that this is the beginning of a header
  430. && (((lpTemp-2)==lpszHeaderInfo)
  431. || isspace(*(lpTemp-3)));
  432. break;
  433. }
  434. --lpTemp;
  435. }
  436. return fRet;
  437. }