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.

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