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.

1327 lines
28 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: ds.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <pch.cpp>
  11. #pragma hdrstop
  12. #include <wininet.h>
  13. #include <winineti.h> // for MAX_CACHE_ENTRY_INFO_SIZE
  14. #include "cryptnet.h"
  15. #define __dwFILE__ __dwFILE_CERTUTIL_CACHE_CPP__
  16. typedef struct _QUERY_INFO
  17. {
  18. WCHAR const *pwszInfo;
  19. DWORD dwInfo;
  20. } QUERY_INFO;
  21. QUERY_INFO g_rgQueryInfo[] = {
  22. #if 0
  23. L"HTTP_QUERY_MIME_VERSION-Req",
  24. HTTP_QUERY_MIME_VERSION | HTTP_QUERY_FLAG_REQUEST_HEADERS,
  25. L"HTTP_QUERY_CONTENT_TYPE-Req",
  26. HTTP_QUERY_CONTENT_TYPE | HTTP_QUERY_FLAG_REQUEST_HEADERS,
  27. L"HTTP_QUERY_CONTENT_TRANSFER_ENCODING-Req",
  28. HTTP_QUERY_CONTENT_TRANSFER_ENCODING | HTTP_QUERY_FLAG_REQUEST_HEADERS,
  29. L"HTTP_QUERY_CONTENT_LENGTH-Req",
  30. HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_REQUEST_HEADERS,
  31. #endif
  32. L"HTTP_QUERY_MIME_VERSION", HTTP_QUERY_MIME_VERSION,
  33. L"HTTP_QUERY_CONTENT_TYPE", HTTP_QUERY_CONTENT_TYPE,
  34. L"HTTP_QUERY_CONTENT_TRANSFER_ENCODING",
  35. HTTP_QUERY_CONTENT_TRANSFER_ENCODING,
  36. L"HTTP_QUERY_CONTENT_LENGTH",
  37. HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
  38. L"HTTP_QUERY_VERSION", HTTP_QUERY_VERSION,
  39. L"HTTP_QUERY_STATUS_CODE", HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
  40. L"HTTP_QUERY_STATUS_TEXT", HTTP_QUERY_STATUS_TEXT,
  41. L"HTTP_QUERY_RAW_HEADERS", HTTP_QUERY_RAW_HEADERS,
  42. L"HTTP_QUERY_RAW_HEADERS_CRLF", HTTP_QUERY_RAW_HEADERS_CRLF,
  43. L"HTTP_QUERY_CONTENT_ENCODING", HTTP_QUERY_CONTENT_ENCODING,
  44. L"HTTP_QUERY_LOCATION", HTTP_QUERY_LOCATION,
  45. L"HTTP_QUERY_ORIG_URI", HTTP_QUERY_ORIG_URI,
  46. L"HTTP_QUERY_REQUEST_METHOD", HTTP_QUERY_REQUEST_METHOD,
  47. L"HTTP_QUERY_DATE", HTTP_QUERY_DATE | HTTP_QUERY_FLAG_SYSTEMTIME,
  48. L"HTTP_QUERY_EXPIRES", HTTP_QUERY_EXPIRES | HTTP_QUERY_FLAG_SYSTEMTIME,
  49. L"HTTP_QUERY_LAST_MODIFIED",
  50. HTTP_QUERY_LAST_MODIFIED | HTTP_QUERY_FLAG_SYSTEMTIME,
  51. };
  52. HRESULT
  53. DisplayQueryInfo(
  54. IN HINTERNET hInternetFile)
  55. {
  56. HRESULT hr;
  57. DWORD i;
  58. for (i = 0; i < ARRAYSIZE(g_rgQueryInfo); i++)
  59. {
  60. QUERY_INFO *pQuery = &g_rgQueryInfo[i];
  61. DWORD dwIndex;
  62. BOOL fFirst;
  63. fFirst = TRUE;
  64. dwIndex = 0;
  65. while (TRUE)
  66. {
  67. BYTE rgbBuf[MAX_CACHE_ENTRY_INFO_SIZE];
  68. DWORD cbBuf;
  69. DWORD dwThisIndex = dwIndex;
  70. BOOL fResult;
  71. DWORD dwValue;
  72. SYSTEMTIME st;
  73. if (HTTP_QUERY_FLAG_NUMBER & pQuery->dwInfo)
  74. {
  75. cbBuf = sizeof(dwValue);
  76. fResult = HttpQueryInfo(
  77. hInternetFile,
  78. pQuery->dwInfo,
  79. &dwValue,
  80. &cbBuf,
  81. &dwIndex);
  82. }
  83. else
  84. if (HTTP_QUERY_FLAG_SYSTEMTIME & pQuery->dwInfo)
  85. {
  86. cbBuf = sizeof(st);
  87. fResult = HttpQueryInfo(
  88. hInternetFile,
  89. pQuery->dwInfo,
  90. &st,
  91. &cbBuf,
  92. &dwIndex);
  93. }
  94. else
  95. {
  96. ZeroMemory(rgbBuf, sizeof(rgbBuf));
  97. cbBuf = sizeof(rgbBuf);
  98. fResult = HttpQueryInfo(
  99. hInternetFile,
  100. pQuery->dwInfo,
  101. rgbBuf,
  102. &cbBuf,
  103. &dwIndex);
  104. }
  105. if (!fResult)
  106. {
  107. hr = myHLastError();
  108. _PrintErrorStr3(
  109. hr,
  110. "HttpQueryInfo",
  111. pQuery->pwszInfo,
  112. HRESULT_FROM_WIN32(ERROR_HTTP_HEADER_NOT_FOUND),
  113. HRESULT_FROM_WIN32(ERROR_HTTP_INVALID_QUERY_REQUEST));
  114. break;
  115. }
  116. if (HTTP_QUERY_FLAG_NUMBER & pQuery->dwInfo)
  117. {
  118. wprintf(
  119. L"%ws[%d] = %x (%d)\n",
  120. pQuery->pwszInfo,
  121. dwThisIndex,
  122. dwValue,
  123. dwValue);
  124. }
  125. else
  126. if (HTTP_QUERY_FLAG_SYSTEMTIME & pQuery->dwInfo)
  127. {
  128. FILETIME ft;
  129. if (!SystemTimeToFileTime(&st, &ft))
  130. {
  131. hr = myHLastError();
  132. _JumpErrorStr(
  133. hr,
  134. error,
  135. "SystemTimeToFileTime",
  136. pQuery->pwszInfo);
  137. }
  138. else
  139. {
  140. wprintf(L"%ws[%d] =", pQuery->pwszInfo, dwThisIndex);
  141. hr = cuDumpFileTime(0, NULL, &ft);
  142. wprintf(wszNewLine);
  143. _PrintIfError(hr, "cuDumpFileTime");
  144. }
  145. }
  146. else
  147. {
  148. wprintf(
  149. L"%ws[%d] = \"%.*ws\"\n",
  150. pQuery->pwszInfo,
  151. dwThisIndex,
  152. cbBuf / sizeof(WCHAR),
  153. rgbBuf);
  154. if (1 < g_fVerbose)
  155. {
  156. DumpHex(0, (BYTE const *) rgbBuf, cbBuf);
  157. }
  158. }
  159. fFirst = FALSE;
  160. if (dwThisIndex == dwIndex)
  161. {
  162. #if 0
  163. wprintf(
  164. L"HttpQueryInfo(%ws) dwIndex not advanced\n",
  165. pQuery->pwszInfo);
  166. #endif
  167. break;
  168. }
  169. }
  170. }
  171. hr = S_OK;
  172. error:
  173. return(hr);
  174. }
  175. HRESULT
  176. DisplayCacheEntryInfo(
  177. IN WCHAR const *pwszURL)
  178. {
  179. HRESULT hr;
  180. DWORD cbCachEntryInfo;
  181. BYTE rgbCachEntryInfo[MAX_CACHE_ENTRY_INFO_SIZE];
  182. INTERNET_CACHE_ENTRY_INFO *pCacheEntryInfo =
  183. (INTERNET_CACHE_ENTRY_INFO *) &rgbCachEntryInfo[0];
  184. cbCachEntryInfo = sizeof(rgbCachEntryInfo);
  185. if (!GetUrlCacheEntryInfo(pwszURL, pCacheEntryInfo, &cbCachEntryInfo))
  186. {
  187. hr = myHLastError();
  188. wprintf(L"%ws\n", pwszURL);
  189. _JumpError(hr, error, "GetUrlCacheEntryInfo");
  190. }
  191. wprintf(
  192. L"%ws %d %ws\n",
  193. myLoadResourceString(IDS_WININET_CACHE_ENTRY_COLON),
  194. cbCachEntryInfo,
  195. myLoadResourceString(IDS_BYTES));
  196. if (0 != cbCachEntryInfo)
  197. {
  198. wprintf(
  199. L" %ws \"%ws\"\n",
  200. myLoadResourceString(IDS_FORMAT_SOURCE_URL),
  201. pCacheEntryInfo->lpszSourceUrlName);
  202. wprintf(
  203. L" %ws \"%ws\"\n",
  204. myLoadResourceString(IDS_FORMAT_LOCAL_FILENAME),
  205. pCacheEntryInfo->lpszLocalFileName);
  206. wprintf(g_wszPad2);
  207. wprintf(myLoadResourceString(IDS_FORMAT_USE_COUNT), pCacheEntryInfo->dwUseCount);
  208. wprintf(wszNewLine);
  209. wprintf(g_wszPad2);
  210. wprintf(myLoadResourceString(IDS_FORMAT_HIT_RATE), pCacheEntryInfo->dwHitRate);
  211. wprintf(wszNewLine);
  212. wprintf(g_wszPad2);
  213. wprintf(myLoadResourceString(IDS_FORMAT_FILE_SIZE), pCacheEntryInfo->dwSizeLow);
  214. wprintf(wszNewLine);
  215. wprintf(g_wszPad2);
  216. wprintf(myLoadResourceString(IDS_FORMAT_LAST_MOD_TIME_COLON));
  217. cuDumpFileTime(0, NULL, &pCacheEntryInfo->LastModifiedTime);
  218. wprintf(g_wszPad2);
  219. wprintf(myLoadResourceString(IDS_FORMAT_EXPIRE_TIME_COLON));
  220. cuDumpFileTime(0, NULL, &pCacheEntryInfo->ExpireTime);
  221. wprintf(g_wszPad2);
  222. wprintf(myLoadResourceString(IDS_FORMAT_LAST_ACCESS_TIME_COLON));
  223. cuDumpFileTime(0, NULL, &pCacheEntryInfo->LastAccessTime);
  224. wprintf(g_wszPad2);
  225. wprintf(myLoadResourceString(IDS_FORMAT_LAST_SYNC_TIME_COLON));
  226. cuDumpFileTime(0, NULL, &pCacheEntryInfo->LastSyncTime);
  227. }
  228. hr = S_OK;
  229. error:
  230. return(hr);
  231. }
  232. typedef struct _DATABLOCK {
  233. struct _DATABLOCK *pNext;
  234. DWORD cbData;
  235. BYTE abData[1];
  236. } DATABLOCK;
  237. HRESULT
  238. AddDataBlock(
  239. IN BYTE *pb,
  240. IN DWORD cb,
  241. IN OUT DATABLOCK **ppData)
  242. {
  243. HRESULT hr;
  244. DATABLOCK *pData = NULL;
  245. pData = (DATABLOCK *) LocalAlloc(LMEM_FIXED, sizeof(*pData) + cb);
  246. if (NULL == pData)
  247. {
  248. hr = E_OUTOFMEMORY;
  249. _JumpError(hr, error, "LocalAlloc");
  250. }
  251. pData->pNext = *ppData;
  252. pData->cbData = cb;
  253. CopyMemory(pData->abData, pb, cb);
  254. *ppData = pData;
  255. hr = S_OK;
  256. error:
  257. return(hr);
  258. }
  259. HRESULT
  260. ReadURL(
  261. OPTIONAL IN HINTERNET hInternetFile,
  262. IN WCHAR const *pwszURL)
  263. {
  264. HRESULT hr;
  265. HCERTSTORE hStore = NULL;
  266. BYTE *pb = NULL;
  267. BYTE *pb2;
  268. DWORD cb;
  269. DWORD cbRead;
  270. DATABLOCK *pData = NULL;
  271. DATABLOCK *pData2;
  272. if (NULL == hInternetFile)
  273. {
  274. if (!CryptRetrieveObjectByUrl(
  275. pwszURL,
  276. CONTEXT_OID_CAPI2_ANY,
  277. CRYPT_RETRIEVE_MULTIPLE_OBJECTS |
  278. (g_fForce?
  279. CRYPT_WIRE_ONLY_RETRIEVAL :
  280. CRYPT_CACHE_ONLY_RETRIEVAL),
  281. 0,
  282. (VOID **) &hStore,
  283. NULL,
  284. NULL,
  285. NULL,
  286. NULL))
  287. {
  288. hr = myHLastError();
  289. _JumpErrorStr2(hr, error, "CryptRetrieveObjectByUrl", pwszURL, hr);
  290. }
  291. hr = cuDumpAndVerifyStore(
  292. hStore,
  293. DVNS_DUMP,
  294. NULL, // pwszCertName
  295. MAXDWORD, // iCertSave
  296. MAXDWORD, // iCRLSave
  297. MAXDWORD, // iCTLSave
  298. NULL, // pwszfnOut
  299. NULL); // pwszPassword
  300. _JumpIfError(hr, error, "cuDumpAndVerifyStore");
  301. }
  302. else
  303. {
  304. cb = 0;
  305. if (!InternetQueryDataAvailable(
  306. hInternetFile,
  307. &cb,
  308. 0, // dwFlags
  309. 0)) // dwContext
  310. {
  311. hr = myHLastError();
  312. _PrintError(hr, "InternetQueryDataAvailable");
  313. }
  314. cb = 0;
  315. while (TRUE)
  316. {
  317. BYTE ab[4096];
  318. if (!InternetReadFile(hInternetFile, ab, sizeof(ab), &cbRead))
  319. {
  320. hr = myHLastError();
  321. _JumpError(hr, error, "InternetReadFile");
  322. }
  323. if (0 == cbRead)
  324. {
  325. break;
  326. }
  327. hr = AddDataBlock(ab, cbRead, &pData);
  328. _JumpIfError(hr, error, "AddDataBlock");
  329. cb += cbRead;
  330. }
  331. pb = (BYTE *) LocalAlloc(LMEM_FIXED, cb);
  332. if (NULL == pb)
  333. {
  334. hr = E_OUTOFMEMORY;
  335. _JumpError(hr, error, "LocalAlloc");
  336. }
  337. pb2 = &pb[cb];
  338. for (pData2 = pData; NULL != pData2; pData2 = pData2->pNext)
  339. {
  340. pb2 -= pData2->cbData;
  341. CSASSERT(pb2 >= pb);
  342. CopyMemory(pb2, pData2->abData, pData2->cbData);
  343. }
  344. CSASSERT(pb2 == pb);
  345. hr = cuDumpAsnBinary(pb, cb, MAXDWORD);
  346. if (S_OK != hr)
  347. {
  348. _PrintError(hr, "cuDumpAsnBinary");
  349. DumpHex(0, pb, cb);
  350. }
  351. }
  352. hr = S_OK;
  353. error:
  354. if (NULL != hStore)
  355. {
  356. CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
  357. }
  358. while (NULL != pData)
  359. {
  360. pData2 = pData;
  361. pData = pData->pNext;
  362. LocalFree(pData2);
  363. }
  364. if (NULL != pb)
  365. {
  366. LocalFree(pb);
  367. }
  368. return(hr);
  369. }
  370. HRESULT
  371. DeleteCacheGroups()
  372. {
  373. HRESULT hr;
  374. HRESULT hr2;
  375. HANDLE hFind = NULL;
  376. GROUPID GroupId;
  377. DWORD cDelete = 0;
  378. hFind = FindFirstUrlCacheGroup(
  379. 0, // dwFlags
  380. CACHEGROUP_SEARCH_ALL, // dwFilter
  381. NULL, // lpSearchCondition
  382. 0, // dwSearchCondition
  383. &GroupId,
  384. NULL); // lpReserved
  385. if (NULL == hFind)
  386. {
  387. hr = myHLastError();
  388. _JumpError(hr, error, "FindFirstUrlCacheGroup");
  389. }
  390. while (TRUE)
  391. {
  392. //wprintf(L"GROUPID: %I64u (0x%I64x)\n", GroupId, GroupId);
  393. if (!DeleteUrlCacheGroup(
  394. GroupId,
  395. CACHEGROUP_FLAG_FLUSHURL_ONDELETE, // dwFlags
  396. NULL)) // lpReserved
  397. {
  398. hr = myHLastError();
  399. _PrintError(hr, "DeleteUrlCacheGroup");
  400. }
  401. else
  402. {
  403. cDelete++;
  404. }
  405. if (!FindNextUrlCacheGroup(hFind, &GroupId, NULL))
  406. {
  407. hr = myHLastError();
  408. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  409. {
  410. break;
  411. }
  412. _JumpError(hr, error, "FindNextUrlCacheGroup");
  413. }
  414. }
  415. //wprintf(L"Deleted %u groups\n", cDelete);
  416. hr = S_OK;
  417. error:
  418. if (NULL != hFind)
  419. {
  420. if (!FindCloseUrlCache(hFind))
  421. {
  422. hr2 = myHLastError();
  423. _PrintError(hr2, "FindCloseUrlCache");
  424. if (S_OK == hr)
  425. {
  426. hr = hr2;
  427. }
  428. }
  429. }
  430. return(hr);
  431. }
  432. HANDLE
  433. myFindFirstUrlCacheEntry(
  434. OPTIONAL IN WCHAR const *pwszPattern,
  435. OUT INTERNET_CACHE_ENTRY_INFO **ppcei,
  436. OUT DWORD *pcb)
  437. {
  438. HRESULT hr;
  439. HANDLE hFind = NULL;
  440. INTERNET_CACHE_ENTRY_INFO *pcei = NULL;
  441. DWORD cb;
  442. BOOL fRetried;
  443. *ppcei = NULL;
  444. cb = MAX_CACHE_ENTRY_INFO_SIZE;
  445. fRetried = FALSE;
  446. while (TRUE)
  447. {
  448. pcei = (INTERNET_CACHE_ENTRY_INFO *) LocalAlloc(LMEM_FIXED, cb);
  449. if (NULL == pcei)
  450. {
  451. hr = E_OUTOFMEMORY;
  452. _JumpError(hr, error, "LocalAlloc");
  453. }
  454. hFind = FindFirstUrlCacheEntry(pwszPattern, pcei, &cb);
  455. if (NULL != hFind)
  456. {
  457. break;
  458. }
  459. hr = myHLastError();
  460. if (!fRetried || HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr)
  461. {
  462. _JumpError(hr, error, "FindFirstUrlCacheEntry");
  463. }
  464. LocalFree(pcei);
  465. pcei = NULL;
  466. fRetried = TRUE;
  467. }
  468. *pcb = cb;
  469. *ppcei = pcei;
  470. pcei = NULL;
  471. hr = S_OK;
  472. error:
  473. if (NULL != pcei)
  474. {
  475. LocalFree(pcei);
  476. }
  477. if (NULL == hFind)
  478. {
  479. CSASSERT(FAILED(hr));
  480. SetLastError(hr);
  481. }
  482. else
  483. {
  484. CSASSERT(S_OK == hr);
  485. }
  486. return(hFind);
  487. }
  488. BOOL
  489. myFindNextUrlCacheEntry(
  490. HANDLE hFind,
  491. OUT INTERNET_CACHE_ENTRY_INFO **ppcei,
  492. OUT DWORD *pcb)
  493. {
  494. HRESULT hr;
  495. BOOL fRet;
  496. INTERNET_CACHE_ENTRY_INFO *pcei = NULL;
  497. DWORD cb;
  498. BOOL fRetried;
  499. *ppcei = NULL;
  500. cb = MAX_CACHE_ENTRY_INFO_SIZE;
  501. fRet = FALSE;
  502. fRetried = FALSE;
  503. while (TRUE)
  504. {
  505. pcei = (INTERNET_CACHE_ENTRY_INFO *) LocalAlloc(LMEM_FIXED, cb);
  506. if (NULL == pcei)
  507. {
  508. hr = E_OUTOFMEMORY;
  509. _JumpError(hr, error, "LocalAlloc");
  510. }
  511. fRet = FindNextUrlCacheEntry(hFind, pcei, &cb);
  512. if (fRet)
  513. {
  514. break;
  515. }
  516. hr = myHLastError();
  517. if (!fRetried || HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr)
  518. {
  519. _JumpError2(
  520. hr,
  521. error,
  522. "FindNextUrlCacheEntry",
  523. HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS));
  524. }
  525. LocalFree(pcei);
  526. pcei = NULL;
  527. fRetried = TRUE;
  528. }
  529. *pcb = cb;
  530. *ppcei = pcei;
  531. pcei = NULL;
  532. hr = S_OK;
  533. error:
  534. if (!fRet)
  535. {
  536. CSASSERT(FAILED(hr));
  537. SetLastError(hr);
  538. }
  539. else
  540. {
  541. CSASSERT(S_OK == hr);
  542. }
  543. return(fRet);
  544. }
  545. BOOL
  546. CachedURLIsCRL(
  547. IN WCHAR const *pwszURL)
  548. {
  549. HRESULT hr;
  550. HCERTSTORE hStore = NULL;
  551. BOOL fIsCRL = FALSE;
  552. CRL_CONTEXT const *pCRL = NULL;
  553. if (!CryptRetrieveObjectByUrl(
  554. pwszURL,
  555. CONTEXT_OID_CRL,
  556. CRYPT_CACHE_ONLY_RETRIEVAL |
  557. CRYPT_RETRIEVE_MULTIPLE_OBJECTS,
  558. 0,
  559. (VOID **) &hStore,
  560. NULL,
  561. NULL,
  562. NULL,
  563. NULL))
  564. {
  565. hr = myHLastError();
  566. _JumpErrorStr2(hr, error, "CryptRetrieveObjectByUrl", pwszURL, hr);
  567. }
  568. pCRL = CertEnumCRLsInStore(hStore, NULL);
  569. if (NULL == pCRL)
  570. {
  571. hr = myHLastError();
  572. _JumpError(hr, error, "CertEnumCRLsInStore");
  573. }
  574. fIsCRL = TRUE;
  575. hr = S_OK;
  576. error:
  577. if (NULL != pCRL)
  578. {
  579. CertFreeCRLContext(pCRL);
  580. }
  581. if (NULL != hStore)
  582. {
  583. CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
  584. }
  585. return(fIsCRL);
  586. }
  587. HRESULT
  588. EnumWinINetCache(
  589. IN BOOL fDelete,
  590. IN BOOL fCRLsOnly)
  591. {
  592. HRESULT hr;
  593. HRESULT hr2;
  594. HANDLE hFind = NULL;
  595. DWORD cDelete = 0;
  596. DWORD cEntries = 0;
  597. INTERNET_CACHE_ENTRY_INFO *pcei = NULL;
  598. DWORD cb;
  599. hFind = myFindFirstUrlCacheEntry(
  600. NULL, // lpszUrlSearchPattern
  601. &pcei,
  602. &cb);
  603. if (NULL == hFind)
  604. {
  605. hr = myHLastError();
  606. _JumpError(hr, error, "myFindFirstUrlCacheEntry");
  607. }
  608. while (TRUE)
  609. {
  610. if (!fCRLsOnly || CachedURLIsCRL(pcei->lpszSourceUrlName))
  611. {
  612. if (g_fVerbose)
  613. {
  614. hr = DisplayCacheEntryInfo(pcei->lpszSourceUrlName);
  615. _PrintIfError(hr, "DisplayCacheEntryInfo");
  616. if (1 < g_fVerbose)
  617. {
  618. BOOL fVerbose = g_fVerbose;
  619. g_fVerbose -= 2;
  620. hr = ReadURL(NULL, pcei->lpszSourceUrlName);
  621. _PrintIfError(hr, "ReadURL");
  622. g_fVerbose = fVerbose;
  623. }
  624. }
  625. else
  626. {
  627. wprintf(L"%ws\n", pcei->lpszSourceUrlName);
  628. }
  629. wprintf(wszNewLine);
  630. cEntries++;
  631. if (fDelete)
  632. {
  633. if (!DeleteUrlCacheEntry(pcei->lpszSourceUrlName))
  634. {
  635. hr = myHLastError();
  636. _PrintError(hr, "DeleteUrlCacheEntry");
  637. }
  638. else
  639. {
  640. cDelete++;
  641. }
  642. }
  643. }
  644. LocalFree(pcei);
  645. pcei = NULL;
  646. if (!myFindNextUrlCacheEntry(hFind, &pcei, &cb))
  647. {
  648. hr = myHLastError();
  649. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
  650. {
  651. break;
  652. }
  653. _JumpError(hr, error, "myFindNextUrlCacheEntry");
  654. }
  655. }
  656. if (fDelete)
  657. {
  658. wprintf(myLoadResourceString(IDS_FORMAT_DELETED_WININETCACHE), cDelete);
  659. }
  660. else
  661. {
  662. wprintf(myLoadResourceString(IDS_FORMAT_WININETCACHE), cEntries);
  663. }
  664. wprintf(wszNewLine);
  665. wprintf(wszNewLine);
  666. hr = S_OK;
  667. error:
  668. if (NULL != hFind)
  669. {
  670. if (!FindCloseUrlCache(hFind))
  671. {
  672. hr2 = myHLastError();
  673. _PrintError(hr2, "FindCloseUrlCache");
  674. if (S_OK == hr)
  675. {
  676. hr = hr2;
  677. }
  678. }
  679. }
  680. if (NULL != pcei)
  681. {
  682. LocalFree(pcei);
  683. }
  684. return(hr);
  685. }
  686. HRESULT
  687. DisplayWinINetURL(
  688. IN WCHAR const *pwszURL)
  689. {
  690. HRESULT hr;
  691. HRESULT hr2;
  692. HINTERNET hInternetSession = NULL;
  693. HINTERNET hInternetFile = NULL;
  694. wprintf(
  695. L"**** %ws ****\n",
  696. myLoadResourceString(g_fForce? IDS_ONLINE : IDS_OFFLINE));
  697. hInternetSession = InternetOpen(
  698. L"CertUtil URL Agent", // lpszAgent
  699. INTERNET_OPEN_TYPE_PRECONFIG, // dwAccessType
  700. NULL, // lpszProxy
  701. NULL, // lpszProxyBypass
  702. g_fForce? 0 : INTERNET_FLAG_FROM_CACHE);
  703. if (NULL == hInternetSession)
  704. {
  705. hr = myHLastError();
  706. _JumpError(hr, error, "InternetOpen");
  707. }
  708. hInternetFile = InternetOpenUrl(
  709. hInternetSession,
  710. pwszURL,
  711. L"Accept: */*\r\n", // lpszHeaders
  712. MAXDWORD, // dwHeadersLength
  713. INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
  714. (g_fForce? INTERNET_FLAG_RELOAD : 0),
  715. 0); // dwContext
  716. if (NULL == hInternetFile)
  717. {
  718. hr = myHLastError();
  719. _PrintErrorStr2(
  720. hr,
  721. "InternetOpenUrl",
  722. pwszURL,
  723. HRESULT_FROM_WIN32(ERROR_INTERNET_UNRECOGNIZED_SCHEME));
  724. }
  725. if (g_fForce)
  726. {
  727. if (g_fVerbose)
  728. {
  729. hr = DisplayCacheEntryInfo(pwszURL);
  730. _PrintIfError(hr, "DisplayCacheEntryInfo");
  731. }
  732. }
  733. else
  734. {
  735. if (g_fVerbose && NULL != hInternetFile)
  736. {
  737. hr = DisplayQueryInfo(hInternetFile);
  738. _PrintIfError(hr, "DisplayQueryInfo");
  739. }
  740. }
  741. hr = ReadURL(hInternetFile, pwszURL);
  742. _PrintIfError(hr, "ReadURL");
  743. if (!g_fForce && g_fVerbose)
  744. {
  745. hr = DisplayCacheEntryInfo(pwszURL);
  746. _PrintIfError(hr, "DisplayCacheEntryInfo");
  747. }
  748. hr = S_OK;
  749. error:
  750. if (NULL != hInternetFile)
  751. {
  752. if (!InternetCloseHandle(hInternetFile))
  753. {
  754. hr2 = myHLastError();
  755. _PrintError(hr2, "InternetCloseHandle");
  756. if (S_OK == hr)
  757. {
  758. hr = hr2;
  759. }
  760. }
  761. }
  762. if (NULL != hInternetSession)
  763. {
  764. if (!InternetCloseHandle(hInternetSession))
  765. {
  766. hr2 = myHLastError();
  767. _PrintError(hr2, "InternetCloseHandle(Session)");
  768. if (S_OK == hr)
  769. {
  770. hr = hr2;
  771. }
  772. }
  773. }
  774. return(hr);
  775. }
  776. HRESULT
  777. DeleteWinINetCachedURL(
  778. IN WCHAR const *pwszURL)
  779. {
  780. HRESULT hr;
  781. if (!DeleteUrlCacheEntry(pwszURL))
  782. {
  783. hr = myHLastError();
  784. _JumpError(hr, error, "DeleteUrlCacheEntry");
  785. }
  786. hr = S_OK;
  787. error:
  788. return(hr);
  789. }
  790. typedef BOOL (WINAPI FNCRYPTNETENUMURLCACHEENTRY)(
  791. IN DWORD dwFlags,
  792. IN LPVOID pvReserved,
  793. IN LPVOID pvArg,
  794. IN PFN_CRYPTNET_ENUM_URL_CACHE_ENTRY_CALLBACK pfnEnumCallback);
  795. FNCRYPTNETENUMURLCACHEENTRY *g_pfnCryptNetEnumUrlCacheEntry = NULL;
  796. HRESULT
  797. LoadWinINetCacheFunction()
  798. {
  799. HRESULT hr;
  800. HMODULE hModule;
  801. hModule = GetModuleHandle(TEXT("cryptnet.dll"));
  802. if (NULL == hModule)
  803. {
  804. hr = myHLastError();
  805. _JumpErrorStr(hr, error, "GetModuleHandle", L"cryptnet.dll");
  806. }
  807. // load system function
  808. g_pfnCryptNetEnumUrlCacheEntry = (FNCRYPTNETENUMURLCACHEENTRY *)
  809. GetProcAddress(hModule, "I_CryptNetEnumUrlCacheEntry");
  810. if (NULL == g_pfnCryptNetEnumUrlCacheEntry)
  811. {
  812. hr = myHLastError();
  813. _JumpErrorStr(hr, error, "GetProcAddress", L"I_CryptNetEnumUrlCacheEntry");
  814. }
  815. hr = S_OK;
  816. error:
  817. return(hr);
  818. }
  819. typedef struct _ENUM_ARG
  820. {
  821. WCHAR const *pwszUrlSubString; // NULL implies display/delete all
  822. BOOL fDelete;
  823. BOOL fCRLsOnly;
  824. DWORD cUrl;
  825. DWORD cUrlDeleted;
  826. } ENUM_ARG;
  827. BOOL
  828. IsURLMatch(
  829. WCHAR const *pwszCacheUrl,
  830. WCHAR const *pwszUrlSubString)
  831. {
  832. BOOL fMatch = FALSE;
  833. if (NULL == pwszUrlSubString)
  834. {
  835. fMatch = TRUE;
  836. }
  837. else
  838. {
  839. // Do case sensitive substring matching
  840. if (0 == lstrcmpi(pwszCacheUrl, pwszUrlSubString) ||
  841. wcsstr(pwszCacheUrl, pwszUrlSubString))
  842. {
  843. fMatch = TRUE;
  844. }
  845. }
  846. return(fMatch);
  847. }
  848. BOOL
  849. WINAPI
  850. WinHttpCacheEntryWorker(
  851. IN CRYPTNET_URL_CACHE_ENTRY const *pUrlCacheEntry,
  852. IN DWORD dwFlags,
  853. IN VOID *pvReserved,
  854. IN VOID *pvArg)
  855. {
  856. HRESULT hr;
  857. ENUM_ARG *pArg = (ENUM_ARG *) pvArg;
  858. DWORD cbBlob;
  859. DWORD i;
  860. BYTE *pbContent = NULL;
  861. DWORD cbContent;
  862. BYTE *pb;
  863. if (!IsURLMatch(pUrlCacheEntry->pwszUrl, pArg->pwszUrlSubString))
  864. {
  865. goto error; // skip non-matching URLs
  866. }
  867. cbBlob = 0;
  868. for (i = 0; i < pUrlCacheEntry->cBlob; i++)
  869. {
  870. cbBlob += pUrlCacheEntry->pcbBlob[i];
  871. }
  872. if (g_fVerbose || pArg->fCRLsOnly)
  873. {
  874. hr = DecodeFileW(
  875. pUrlCacheEntry->pwszContentFileName,
  876. &pbContent,
  877. &cbContent,
  878. CRYPT_STRING_ANY);
  879. _PrintIfError(hr, "DecodeFileW");
  880. if (NULL != pbContent && cbBlob != cbContent)
  881. {
  882. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  883. _PrintError(hr, "cuDumpFileTime");
  884. if (cbBlob > cbContent)
  885. {
  886. LocalFree(pbContent); // invalid content
  887. pbContent = NULL;
  888. }
  889. }
  890. if (NULL != pbContent && pArg->fCRLsOnly)
  891. {
  892. BOOL fCRL = FALSE;
  893. pb = pbContent;
  894. for (i = 0; i < pUrlCacheEntry->cBlob; i++)
  895. {
  896. CRL_CONTEXT const *pCRL;
  897. pCRL = CertCreateCRLContext(
  898. X509_ASN_ENCODING,
  899. pb,
  900. pUrlCacheEntry->pcbBlob[i]);
  901. if (NULL != pCRL)
  902. {
  903. CertFreeCRLContext(pCRL);
  904. fCRL = TRUE;
  905. break;
  906. }
  907. pb += pUrlCacheEntry->pcbBlob[i];
  908. }
  909. if (!fCRL)
  910. {
  911. goto error; // skip non-CRLS
  912. }
  913. }
  914. }
  915. if (!g_fVerbose)
  916. {
  917. wprintf(L"%ws\n", pUrlCacheEntry->pwszUrl);
  918. }
  919. else
  920. {
  921. wprintf(
  922. L"%ws %d %ws\n",
  923. myLoadResourceString(IDS_WINHTTP_CACHE_ENTRY_COLON),
  924. pUrlCacheEntry->cbSize,
  925. myLoadResourceString(IDS_BYTES));
  926. wprintf(
  927. L" %ws \"%ws\"\n",
  928. myLoadResourceString(IDS_FORMAT_SOURCE_URL),
  929. pUrlCacheEntry->pwszUrl);
  930. wprintf(wszNewLine);
  931. wprintf(
  932. L" %ws \"%ws\"\n",
  933. myLoadResourceString(IDS_FORMAT_LOCAL_FILENAME),
  934. pUrlCacheEntry->pwszContentFileName);
  935. wprintf(wszNewLine);
  936. wprintf(
  937. L" %ws \"%ws\"\n",
  938. myLoadResourceString(IDS_FORMAT_META_FILENAME),
  939. pUrlCacheEntry->pwszMetaDataFileName);
  940. wprintf(wszNewLine);
  941. wprintf(g_wszPad2);
  942. wprintf(myLoadResourceString(IDS_FORMAT_FILE_SIZE), cbBlob);
  943. wprintf(wszNewLine);
  944. wprintf(g_wszPad2);
  945. wprintf(myLoadResourceString(IDS_FORMAT_LAST_SYNC_TIME_COLON));
  946. cuDumpFileTime(0, NULL, &pUrlCacheEntry->LastSyncTime);
  947. if (NULL != pbContent && 1 < g_fVerbose)
  948. {
  949. BOOL fVerbose = g_fVerbose;
  950. g_fVerbose -= 2;
  951. pb = pbContent;
  952. for (i = 0; i < pUrlCacheEntry->cBlob; i++)
  953. {
  954. hr = cuDumpAsnBinary(pb, pUrlCacheEntry->pcbBlob[i], i);
  955. if (S_OK != hr || 1 < g_fVerbose)
  956. {
  957. _PrintIfError(hr, "cuDumpAsnBinary");
  958. DumpHex(0, pb, pUrlCacheEntry->pcbBlob[i]);
  959. }
  960. pb += pUrlCacheEntry->pcbBlob[i];
  961. }
  962. g_fVerbose = fVerbose;
  963. }
  964. }
  965. if (pArg->fDelete)
  966. {
  967. hr = S_OK;
  968. if (!DeleteFile(pUrlCacheEntry->pwszContentFileName))
  969. {
  970. hr = myHLastError();
  971. _PrintErrorStr(hr, "DeleteFile", pUrlCacheEntry->pwszContentFileName);
  972. }
  973. if (!DeleteFile(pUrlCacheEntry->pwszMetaDataFileName))
  974. {
  975. hr = myHLastError();
  976. _PrintErrorStr(hr, "DeleteFile", pUrlCacheEntry->pwszMetaDataFileName);
  977. }
  978. if (S_OK == hr)
  979. {
  980. pArg->cUrlDeleted++;
  981. }
  982. }
  983. wprintf(wszNewLine);
  984. pArg->cUrl++;
  985. error:
  986. if (NULL != pbContent)
  987. {
  988. LocalFree(pbContent);
  989. }
  990. return(TRUE);
  991. }
  992. HRESULT
  993. EnumWinHttpCache(
  994. OPTIONAL IN WCHAR const *pwszURL,
  995. IN BOOL fDelete,
  996. IN BOOL fCRLsOnly)
  997. {
  998. HRESULT hr;
  999. if (NULL != g_pfnCryptNetEnumUrlCacheEntry)
  1000. {
  1001. ENUM_ARG EnumArg;
  1002. memset(&EnumArg, 0, sizeof(EnumArg));
  1003. EnumArg.pwszUrlSubString = pwszURL;
  1004. EnumArg.fDelete = fDelete;
  1005. EnumArg.fCRLsOnly = fCRLsOnly;
  1006. if (!(*g_pfnCryptNetEnumUrlCacheEntry)(
  1007. 0, // dwFlags
  1008. NULL, // pvReserved
  1009. &EnumArg,
  1010. WinHttpCacheEntryWorker))
  1011. {
  1012. hr = myHLastError();
  1013. _JumpError(hr, error, "I_CryptNetEnumUrlCacheEntry");
  1014. }
  1015. if (fDelete)
  1016. {
  1017. wprintf(myLoadResourceString(IDS_FORMAT_DELETED_WINHTTPCACHE), EnumArg.cUrlDeleted);
  1018. }
  1019. else
  1020. {
  1021. wprintf(myLoadResourceString(IDS_FORMAT_WINHTTPCACHE), EnumArg.cUrl);
  1022. }
  1023. wprintf(wszNewLine);
  1024. wprintf(wszNewLine);
  1025. }
  1026. hr = S_OK;
  1027. error:
  1028. return(hr);
  1029. }
  1030. HRESULT
  1031. DisplayWinHttpURL(
  1032. IN WCHAR const *pwszURL)
  1033. {
  1034. HRESULT hr;
  1035. hr = EnumWinHttpCache(pwszURL, FALSE, FALSE);
  1036. _JumpIfError(hr, error, "EnumWinHttpCache");
  1037. error:
  1038. return(hr);
  1039. }
  1040. HRESULT
  1041. DeleteWinHttpCachedURL(
  1042. IN WCHAR const *pwszURL)
  1043. {
  1044. HRESULT hr;
  1045. hr = EnumWinHttpCache(pwszURL, TRUE, FALSE);
  1046. _JumpIfError(hr, error, "EnumWinHttpCache");
  1047. error:
  1048. return(hr);
  1049. }
  1050. HRESULT
  1051. CacheSelectHResult(
  1052. IN HRESULT hr1,
  1053. IN HRESULT hr2)
  1054. {
  1055. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr1 ||
  1056. (S_OK != hr2 && HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr2))
  1057. {
  1058. hr1 = hr2;
  1059. }
  1060. return(hr1);
  1061. }
  1062. HRESULT
  1063. EnumURLCache(
  1064. IN BOOL fDelete,
  1065. IN BOOL fCRLsOnly)
  1066. {
  1067. HRESULT hr;
  1068. HRESULT hr2;
  1069. hr = EnumWinINetCache(fDelete, fCRLsOnly);
  1070. _PrintIfError(hr, "EnumWinINetCache");
  1071. hr2 = EnumWinHttpCache(NULL, fDelete, fCRLsOnly);
  1072. _PrintIfError(hr2, "EnumWinHttpCache");
  1073. hr = CacheSelectHResult(hr, hr2);
  1074. _JumpIfError(hr, error, "EnumURLCache");
  1075. error:
  1076. return(hr);
  1077. }
  1078. HRESULT
  1079. DisplayURL(
  1080. IN WCHAR const *pwszURL)
  1081. {
  1082. HRESULT hr;
  1083. HRESULT hr2;
  1084. hr = DisplayWinINetURL(pwszURL);
  1085. _PrintIfError(hr, "DisplayWinINetURL");
  1086. hr2 = DisplayWinHttpURL(pwszURL);
  1087. _PrintIfError(hr2, "DisplayWinHttpURL");
  1088. hr = CacheSelectHResult(hr, hr2);
  1089. _JumpIfError(hr, error, "DisplayURL");
  1090. error:
  1091. return(hr);
  1092. }
  1093. HRESULT
  1094. DeleteCachedURL(
  1095. IN WCHAR const *pwszURL)
  1096. {
  1097. HRESULT hr;
  1098. HRESULT hr2;
  1099. hr = DeleteWinINetCachedURL(pwszURL);
  1100. _PrintIfError(hr, "DeleteWinINetCachedURL");
  1101. hr2 = DeleteWinHttpCachedURL(pwszURL);
  1102. _PrintIfError(hr2, "DeleteWinHttpCachedURL");
  1103. hr = CacheSelectHResult(hr, hr2);
  1104. _JumpIfError(hr, error, "DeleteCachedURL");
  1105. error:
  1106. return(hr);
  1107. }
  1108. HRESULT
  1109. verbURLCache(
  1110. IN WCHAR const *pwszOption,
  1111. IN WCHAR const *pwszURL,
  1112. IN WCHAR const *pwszDelete,
  1113. IN WCHAR const *pwszArg3,
  1114. IN WCHAR const *pwszArg4)
  1115. {
  1116. HRESULT hr;
  1117. hr = LoadWinINetCacheFunction();
  1118. _PrintIfError(hr, "LoadWinINetCacheFunction");
  1119. if (NULL != pwszDelete)
  1120. {
  1121. if (0 != LSTRCMPIS(pwszDelete, L"Delete"))
  1122. {
  1123. hr = E_INVALIDARG;
  1124. _JumpError(hr, error, "bad delete arg");
  1125. }
  1126. if (0 == lstrcmp(L"*", pwszURL))
  1127. {
  1128. hr = EnumURLCache(TRUE, FALSE); // fDelete, fCRLsOnly (delete all)
  1129. _JumpIfError(hr, error, "EnumURLCache(Delete all)");
  1130. hr = DeleteCacheGroups();
  1131. _JumpIfError(hr, error, "DeleteCacheGroups");
  1132. }
  1133. else if (0 == LSTRCMPIS(pwszURL, L"crl"))
  1134. {
  1135. hr = EnumURLCache(TRUE, TRUE); // fDelete, fCRLsOnly (delete CRLs)
  1136. _JumpIfError(hr, error, "EnumURLCache(Delete CRLs)");
  1137. }
  1138. else
  1139. {
  1140. hr = DeleteCachedURL(pwszURL); // delete single URL
  1141. _JumpIfError(hr, error, "DeleteCachedURL");
  1142. }
  1143. }
  1144. else if (NULL == pwszURL || 0 == lstrcmp(L"*", pwszURL))
  1145. {
  1146. hr = EnumURLCache(FALSE, FALSE); // fDelete, fCRLsOnly (display all)
  1147. _JumpIfError(hr, error, "EnumURLCache");
  1148. }
  1149. else if (0 == LSTRCMPIS(pwszURL, L"crl"))
  1150. {
  1151. hr = EnumURLCache(FALSE, TRUE); // fDelete, fCRLsOnly (display CRLs)
  1152. _JumpIfError(hr, error, "EnumURLCache(CRLs)");
  1153. }
  1154. else
  1155. {
  1156. hr = DisplayURL(pwszURL);
  1157. _JumpIfError(hr, error, "DisplayURL");
  1158. }
  1159. hr = S_OK;
  1160. error:
  1161. return(hr);
  1162. }