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.

888 lines
25 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1998
  6. //
  7. // File: turlcache.cpp
  8. //
  9. // Contents: Test to display and delete Cryptnet Url cache entries
  10. //
  11. // See Usage() for a list of test options.
  12. //
  13. //
  14. // Functions: main
  15. //
  16. // History: 02-Feb-02 philh created
  17. //--------------------------------------------------------------------------
  18. #include <windows.h>
  19. #include <assert.h>
  20. #include "wincrypt.h"
  21. #include "crypthlp.h"
  22. #include "cryptnet.h"
  23. #include "certtest.h"
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <memory.h>
  28. #include <time.h>
  29. BOOL fExactMatch = FALSE;
  30. BOOL fOneMatch = FALSE; // at least one match
  31. BOOL fNoMatch = FALSE; // no matches
  32. typedef struct _TEST_DELETE_ARG {
  33. LPCWSTR pwszUrlSubString; // NULL implies delete all
  34. DWORD cUrlCacheEntry;
  35. LPWSTR *rgpwszUrl;
  36. LPWSTR *rgpwszMetaDataFileName;
  37. LPWSTR *rgpwszContentFileName;
  38. } TEST_DELETE_ARG, *PTEST_DELETE_ARG;
  39. typedef struct _TEST_DISPLAY_ARG {
  40. LPCWSTR pwszUrlSubString; // NULL implies display all
  41. DWORD dwDisplayFlags;
  42. BOOL fContent;
  43. BOOL fRawBytes;
  44. DWORD cUrl;
  45. } TEST_DISPLAY_ARG, *PTEST_DISPLAY_ARG;
  46. typedef struct _TEST_SET_SYNC_TIME_ARG {
  47. LPCWSTR pwszUrlSubString;
  48. BOOL fVerbose;
  49. FILETIME LastSyncTime;
  50. DWORD cUrl;
  51. } TEST_SET_SYNC_TIME_ARG, *PTEST_SET_SYNC_TIME_ARG;
  52. static void Usage(void)
  53. {
  54. printf("Usage: turlcache [options] [<Url SubString>]\n");
  55. printf("\n");
  56. printf("Options are:\n");
  57. printf(" -d - Delete Url Cache Entry\n");
  58. printf(" -dALL - Delete All Url Cache Entries\n");
  59. printf(" -c - Display Url Cache Content\n");
  60. printf(" -r - Display Url Cache Raw Bytes\n");
  61. printf(" -e - Exact match\n");
  62. printf(" -1 - At least one match without an error\n");
  63. printf(" -0 - No matches without an error\n");
  64. printf(" -h - This message\n");
  65. printf(" -b - Brief\n");
  66. printf(" -v - Verbose\n");
  67. printf(" -S<number> - SyncTime delta seconds\n");
  68. printf("\n");
  69. }
  70. BOOL
  71. TestIsUrlMatch(
  72. LPCWSTR pwszCacheUrl,
  73. LPCWSTR pwszUrlSubString // already in lower case
  74. )
  75. {
  76. BOOL fResult = FALSE;
  77. LPWSTR pwszLowerCaseCacheUrl = NULL;
  78. if (NULL == pwszUrlSubString)
  79. return TRUE;
  80. if (fExactMatch) {
  81. if (0 == wcscmp(pwszCacheUrl, pwszUrlSubString))
  82. return TRUE;
  83. else
  84. return FALSE;
  85. }
  86. // Do case insensitive substring in string matching
  87. pwszLowerCaseCacheUrl = (LPWSTR) TestAlloc(
  88. (wcslen(pwszCacheUrl) + 1) * sizeof(WCHAR));
  89. if (pwszLowerCaseCacheUrl) {
  90. wcscpy(pwszLowerCaseCacheUrl, pwszCacheUrl);
  91. _wcslwr(pwszLowerCaseCacheUrl);
  92. if (wcsstr(pwszLowerCaseCacheUrl, pwszUrlSubString))
  93. fResult = TRUE;
  94. TestFree(pwszLowerCaseCacheUrl);
  95. }
  96. return fResult;
  97. }
  98. BOOL
  99. WINAPI
  100. TestDeleteUrlCacheEntryCallback(
  101. IN const CRYPTNET_URL_CACHE_ENTRY *pUrlCacheEntry,
  102. IN DWORD dwFlags,
  103. IN LPVOID pvReserved,
  104. IN LPVOID pvArg
  105. )
  106. {
  107. BOOL fResult;
  108. PTEST_DELETE_ARG pArg = (PTEST_DELETE_ARG) pvArg;
  109. DWORD cbUrl;
  110. LPWSTR pwszUrl = NULL;
  111. LPWSTR *ppwszUrl = NULL;
  112. DWORD cbMetaDataFileName;
  113. LPWSTR pwszMetaDataFileName = NULL;
  114. LPWSTR *ppwszMetaDataFileName = NULL;
  115. DWORD cbContentFileName;
  116. LPWSTR pwszContentFileName = NULL;
  117. LPWSTR *ppwszContentFileName = NULL;
  118. DWORD cUrlCacheEntry;
  119. if (!TestIsUrlMatch(pUrlCacheEntry->pwszUrl, pArg->pwszUrlSubString))
  120. return TRUE;
  121. cbUrl = (wcslen(pUrlCacheEntry->pwszUrl) + 1) * sizeof(WCHAR);
  122. cbMetaDataFileName =
  123. (wcslen(pUrlCacheEntry->pwszMetaDataFileName) + 1) * sizeof(WCHAR);
  124. cbContentFileName =
  125. (wcslen(pUrlCacheEntry->pwszContentFileName) + 1) * sizeof(WCHAR);
  126. pwszUrl = (LPWSTR) TestAlloc(cbUrl);
  127. pwszMetaDataFileName = (LPWSTR) TestAlloc(cbMetaDataFileName);
  128. pwszContentFileName = (LPWSTR) TestAlloc(cbContentFileName);
  129. if (NULL == pwszUrl ||
  130. NULL == pwszMetaDataFileName ||
  131. NULL == pwszContentFileName)
  132. goto ErrorReturn;
  133. cUrlCacheEntry = pArg->cUrlCacheEntry;
  134. ppwszUrl = (LPWSTR *) TestRealloc(
  135. pArg->rgpwszUrl, sizeof(LPWSTR) * (cUrlCacheEntry + 1));
  136. if (NULL == ppwszUrl)
  137. goto ErrorReturn;
  138. pArg->rgpwszUrl = ppwszUrl;
  139. ppwszMetaDataFileName = (LPWSTR *) TestRealloc(
  140. pArg->rgpwszMetaDataFileName, sizeof(LPWSTR) * (cUrlCacheEntry + 1));
  141. if (NULL == ppwszMetaDataFileName)
  142. goto ErrorReturn;
  143. pArg->rgpwszMetaDataFileName = ppwszMetaDataFileName;
  144. ppwszContentFileName = (LPWSTR *) TestRealloc(
  145. pArg->rgpwszContentFileName, sizeof(LPWSTR) * (cUrlCacheEntry + 1));
  146. if (NULL == ppwszContentFileName)
  147. goto ErrorReturn;
  148. pArg->rgpwszContentFileName = ppwszContentFileName;
  149. memcpy(pwszUrl, pUrlCacheEntry->pwszUrl, cbUrl);
  150. ppwszUrl[cUrlCacheEntry] = pwszUrl;
  151. memcpy(pwszMetaDataFileName, pUrlCacheEntry->pwszMetaDataFileName,
  152. cbMetaDataFileName);
  153. ppwszMetaDataFileName[cUrlCacheEntry] = pwszMetaDataFileName;
  154. memcpy(pwszContentFileName, pUrlCacheEntry->pwszContentFileName,
  155. cbContentFileName);
  156. ppwszContentFileName[cUrlCacheEntry] = pwszContentFileName;
  157. pArg->cUrlCacheEntry = cUrlCacheEntry + 1;
  158. fResult = TRUE;
  159. CommonReturn:
  160. return fResult;
  161. ErrorReturn:
  162. TestFree(pwszUrl);
  163. TestFree(pwszMetaDataFileName);
  164. TestFree(pwszContentFileName);
  165. fResult = FALSE;
  166. goto CommonReturn;
  167. }
  168. BOOL TestDeleteUrlCacheEntry(
  169. IN LPCWSTR pwszUrlSubString, // NULL implies delete all
  170. IN BOOL fVerbose
  171. )
  172. {
  173. BOOL fResult;
  174. TEST_DELETE_ARG TestArg;
  175. DWORD i;
  176. DWORD cDeleted = 0;
  177. memset(&TestArg, 0, sizeof(TestArg));
  178. TestArg.pwszUrlSubString = pwszUrlSubString;
  179. fResult = I_CryptNetEnumUrlCacheEntry(
  180. 0, // dwFlags
  181. NULL, // pvReserved
  182. &TestArg,
  183. TestDeleteUrlCacheEntryCallback
  184. );
  185. if (!fResult)
  186. PrintLastError("I_CryptNetEnumUrlCacheEntry(Delete)");
  187. for (i = 0; i < TestArg.cUrlCacheEntry; i++) {
  188. BOOL fDelete = TRUE;
  189. if (!DeleteFileW(TestArg.rgpwszContentFileName[i])) {
  190. fDelete = FALSE;
  191. printf("Failed Content DeleteFile(%S) for Url: %S\n",
  192. TestArg.rgpwszContentFileName[i],
  193. TestArg.rgpwszUrl[i]
  194. );
  195. PrintLastError("DeleteFilew(Content)");
  196. }
  197. if (!DeleteFileW(TestArg.rgpwszMetaDataFileName[i])) {
  198. fDelete = FALSE;
  199. printf("Failed MetaData DeleteFile(%S) for Url: %S\n",
  200. TestArg.rgpwszMetaDataFileName[i],
  201. TestArg.rgpwszUrl[i]
  202. );
  203. PrintLastError("DeleteFilew(MetaData)");
  204. }
  205. if (fDelete) {
  206. if (fVerbose)
  207. printf("Successful Delete for Url: %S\n",
  208. TestArg.rgpwszUrl[i]);
  209. cDeleted++;
  210. }
  211. TestFree(TestArg.rgpwszUrl[i]);
  212. TestFree(TestArg.rgpwszContentFileName[i]);
  213. TestFree(TestArg.rgpwszMetaDataFileName[i]);
  214. }
  215. TestFree(TestArg.rgpwszUrl);
  216. TestFree(TestArg.rgpwszContentFileName);
  217. TestFree(TestArg.rgpwszMetaDataFileName);
  218. printf("\nDeleted %d Url Cache Entries\n", cDeleted);
  219. if (fOneMatch && 0 == cDeleted) {
  220. printf("Delete failed => no matched entries\n");
  221. fResult = FALSE;
  222. }
  223. if (fNoMatch && 0 != cDeleted) {
  224. printf("Delete failed => expected no matched entries\n");
  225. fResult = FALSE;
  226. }
  227. return fResult;
  228. }
  229. //+-------------------------------------------------------------------------
  230. // Allocate and read an encoded DER blob from a file
  231. //--------------------------------------------------------------------------
  232. BOOL ReadDERFromFile(
  233. LPCWSTR pwszFileName,
  234. PBYTE *ppbDER,
  235. PDWORD pcbDER
  236. )
  237. {
  238. BOOL fRet;
  239. HANDLE hFile = INVALID_HANDLE_VALUE;
  240. PBYTE pbDER = NULL;
  241. DWORD cbDER;
  242. DWORD cbRead;
  243. if( INVALID_HANDLE_VALUE == (hFile = CreateFileW( pwszFileName, GENERIC_READ,
  244. FILE_SHARE_READ | FILE_SHARE_WRITE,
  245. NULL, OPEN_EXISTING, 0, NULL))) {
  246. printf( "can't open %S\n", pwszFileName);
  247. goto ErrorReturn;
  248. }
  249. cbDER = GetFileSize( hFile, NULL);
  250. if (cbDER == 0) {
  251. printf( "empty file %S\n", pwszFileName);
  252. goto ErrorReturn;
  253. }
  254. if (NULL == (pbDER = (PBYTE)TestAlloc(cbDER))) {
  255. printf( "can't alloc %d bytes\n", cbDER);
  256. goto ErrorReturn;
  257. }
  258. if (!ReadFile( hFile, pbDER, cbDER, &cbRead, NULL) ||
  259. (cbRead != cbDER)) {
  260. printf( "can't read %S\n", pwszFileName);
  261. goto ErrorReturn;
  262. }
  263. *ppbDER = pbDER;
  264. *pcbDER = cbDER;
  265. fRet = TRUE;
  266. CommonReturn:
  267. if (INVALID_HANDLE_VALUE != hFile)
  268. CloseHandle(hFile);
  269. return fRet;
  270. ErrorReturn:
  271. if (pbDER)
  272. TestFree(pbDER);
  273. *ppbDER = NULL;
  274. *pcbDER = 0;
  275. fRet = FALSE;
  276. goto CommonReturn;
  277. }
  278. //+-------------------------------------------------------------------------
  279. // Write an encoded DER blob to a file
  280. //--------------------------------------------------------------------------
  281. BOOL WriteDERToFile(
  282. LPCWSTR pwszFileName,
  283. PBYTE pbDER,
  284. DWORD cbDER
  285. )
  286. {
  287. BOOL fResult;
  288. // Write the Encoded Blob to the file
  289. HANDLE hFile;
  290. hFile = CreateFileW(pwszFileName,
  291. GENERIC_WRITE,
  292. 0, // fdwShareMode
  293. NULL, // lpsa
  294. CREATE_ALWAYS,
  295. FILE_ATTRIBUTE_SYSTEM,
  296. 0); // TemplateFile
  297. if (INVALID_HANDLE_VALUE == hFile) {
  298. fResult = FALSE;
  299. PrintLastError("WriteDERToFile::CreateFile");
  300. } else {
  301. DWORD dwBytesWritten;
  302. if (!(fResult = WriteFile(
  303. hFile,
  304. pbDER,
  305. cbDER,
  306. &dwBytesWritten,
  307. NULL // lpOverlapped
  308. )))
  309. PrintLastError("WriteDERToFile::WriteFile");
  310. CloseHandle(hFile);
  311. }
  312. return fResult;
  313. }
  314. HCERTSTORE TestCreateStoreFromUrlCacheContent(
  315. IN DWORD cBlob,
  316. IN DWORD *pcbBlob,
  317. IN PBYTE pbContent
  318. )
  319. {
  320. BOOL fResult = TRUE;
  321. HCERTSTORE hStore = NULL;
  322. DWORD cCount;
  323. int iQueryResult;
  324. DWORD dwQueryErr = 0;
  325. PBYTE pb;
  326. if ( ( hStore = CertOpenStore(
  327. CERT_STORE_PROV_MEMORY,
  328. 0,
  329. NULL,
  330. 0,
  331. NULL
  332. ) ) == NULL )
  333. {
  334. PrintLastError("CertOpenStore(Memory)");
  335. return NULL;
  336. }
  337. // 0 => no CryptQueryObject()
  338. // 1 => 1 successful CryptQueryObject()
  339. // -1 => all CryptQueryObject()'s failed
  340. iQueryResult = 0;
  341. for ( cCount = 0, pb = pbContent;
  342. ( fResult == TRUE ) && ( cCount < cBlob );
  343. pb += pcbBlob[cCount], cCount++ )
  344. {
  345. CERT_BLOB Blob;
  346. HCERTSTORE hChildStore = NULL;
  347. // Skip empty blobs. I have seen empty LDAP attributes containing
  348. // a single byte set to 0.
  349. if (0 == pcbBlob[cCount] ||
  350. (1 == pcbBlob[cCount] && 0 == pb[0]))
  351. {
  352. continue;
  353. }
  354. Blob.pbData = pb;
  355. Blob.cbData = pcbBlob[cCount];
  356. if (CryptQueryObject(
  357. CERT_QUERY_OBJECT_BLOB,
  358. (LPVOID) &Blob,
  359. CERT_QUERY_CONTENT_FLAG_CERT |
  360. CERT_QUERY_CONTENT_FLAG_CTL |
  361. CERT_QUERY_CONTENT_FLAG_CRL |
  362. CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE |
  363. CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT |
  364. CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL |
  365. CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL |
  366. CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
  367. CERT_QUERY_CONTENT_FLAG_CERT_PAIR,
  368. CERT_QUERY_FORMAT_FLAG_ALL,
  369. 0,
  370. NULL,
  371. NULL,
  372. NULL,
  373. &hChildStore,
  374. NULL,
  375. NULL
  376. ))
  377. {
  378. fResult = I_CertUpdateStore( hStore, hChildStore, 0, NULL );
  379. CertCloseStore( hChildStore, 0 );
  380. iQueryResult = 1;
  381. }
  382. else if (iQueryResult == 0)
  383. {
  384. iQueryResult = -1;
  385. dwQueryErr = GetLastError();
  386. }
  387. }
  388. if ( fResult == TRUE && iQueryResult < 0)
  389. {
  390. fResult = FALSE;
  391. SetLastError(dwQueryErr);
  392. }
  393. if (!fResult)
  394. {
  395. PrintLastError("TestCreateStoreFromUrlCacheContent");
  396. CertCloseStore( hStore, 0 );
  397. hStore = NULL;
  398. }
  399. return hStore;
  400. }
  401. LPCSTR FileTimeTextWithoutMilliseconds(FILETIME *pft)
  402. {
  403. static char buf[80];
  404. FILETIME ftLocal;
  405. struct tm ctm;
  406. SYSTEMTIME st;
  407. FileTimeToLocalFileTime(pft, &ftLocal);
  408. if (FileTimeToSystemTime(&ftLocal, &st))
  409. {
  410. ctm.tm_sec = st.wSecond;
  411. ctm.tm_min = st.wMinute;
  412. ctm.tm_hour = st.wHour;
  413. ctm.tm_mday = st.wDay;
  414. ctm.tm_mon = st.wMonth-1;
  415. ctm.tm_year = st.wYear-1900;
  416. ctm.tm_wday = st.wDayOfWeek;
  417. ctm.tm_yday = 0;
  418. ctm.tm_isdst = 0;
  419. strcpy(buf, asctime(&ctm));
  420. buf[strlen(buf)-1] = 0;
  421. }
  422. else
  423. sprintf(buf, "<FILETIME %08lX:%08lX>", pft->dwHighDateTime,
  424. pft->dwLowDateTime);
  425. return buf;
  426. }
  427. BOOL
  428. WINAPI
  429. TestDisplayUrlCacheEntryCallback(
  430. IN const CRYPTNET_URL_CACHE_ENTRY *pUrlCacheEntry,
  431. IN DWORD dwFlags,
  432. IN LPVOID pvReserved,
  433. IN LPVOID pvArg
  434. )
  435. {
  436. PTEST_DISPLAY_ARG pArg = (PTEST_DISPLAY_ARG) pvArg;
  437. DWORD cbBlob;
  438. DWORD i;
  439. PBYTE pbContent = NULL;
  440. DWORD cbContent;
  441. BOOL fDetails;
  442. if (pArg->fRawBytes || pArg->fContent ||
  443. (pArg->dwDisplayFlags & DISPLAY_VERBOSE_FLAG))
  444. fDetails = TRUE;
  445. else
  446. fDetails = FALSE;
  447. if (!TestIsUrlMatch(pUrlCacheEntry->pwszUrl, pArg->pwszUrlSubString))
  448. return TRUE;
  449. cbBlob = 0;
  450. for (i = 0; i < pUrlCacheEntry->cBlob; i++)
  451. cbBlob += pUrlCacheEntry->pcbBlob[i];
  452. if (fDetails) {
  453. printf("\n");
  454. printf(
  455. "=========================================================================\n");
  456. }
  457. printf("%s %9d %S\n",
  458. FileTimeTextWithoutMilliseconds((FILETIME *) &pUrlCacheEntry->LastSyncTime),
  459. cbBlob,
  460. pUrlCacheEntry->pwszUrl
  461. );
  462. if (fDetails) {
  463. printf(
  464. "=========================================================================\n");
  465. if (pArg->dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
  466. printf("MetaDataFileName: %S\n",
  467. pUrlCacheEntry->pwszMetaDataFileName);
  468. printf("ContentFileName : %S\n",
  469. pUrlCacheEntry->pwszContentFileName);
  470. }
  471. if (!ReadDERFromFile(
  472. pUrlCacheEntry->pwszContentFileName,
  473. &pbContent,
  474. &cbContent
  475. ))
  476. goto ErrorReturn;
  477. if (cbBlob != cbContent) {
  478. printf("Invalid content length: %d, expected: %d\n",
  479. cbContent, cbBlob);
  480. if (cbBlob > cbContent)
  481. goto ErrorReturn;
  482. }
  483. if (pArg->fRawBytes) {
  484. PBYTE pb = pbContent;
  485. for (i = 0; i < pUrlCacheEntry->cBlob; i++) {
  486. printf("---- Blob[%d] ----\n", i);
  487. PrintBytes(" ", pb, pUrlCacheEntry->pcbBlob[i]);
  488. pb += pUrlCacheEntry->pcbBlob[i];
  489. }
  490. }
  491. if (pArg->fContent) {
  492. HCERTSTORE hStore;
  493. hStore = TestCreateStoreFromUrlCacheContent(
  494. pUrlCacheEntry->cBlob,
  495. pUrlCacheEntry->pcbBlob,
  496. pbContent
  497. );
  498. if (hStore) {
  499. DisplayStore(hStore, pArg->dwDisplayFlags);
  500. CertCloseStore(hStore, 0);
  501. }
  502. }
  503. }
  504. CommonReturn:
  505. TestFree(pbContent);
  506. pArg->cUrl++;
  507. return TRUE;
  508. ErrorReturn:
  509. goto CommonReturn;
  510. }
  511. BOOL TestDisplayUrlCacheEntry(
  512. IN LPCWSTR pwszUrlSubString, // NULL implies display all
  513. IN DWORD dwDisplayFlags,
  514. IN BOOL fContent,
  515. IN BOOL fRawBytes
  516. )
  517. {
  518. BOOL fResult;
  519. TEST_DISPLAY_ARG TestArg;
  520. memset(&TestArg, 0, sizeof(TestArg));
  521. TestArg.pwszUrlSubString = pwszUrlSubString;
  522. TestArg.dwDisplayFlags = dwDisplayFlags;
  523. TestArg.fContent = fContent;
  524. TestArg.fRawBytes = fRawBytes;
  525. fResult = I_CryptNetEnumUrlCacheEntry(
  526. 0, // dwFlags
  527. NULL, // pvReserved
  528. &TestArg,
  529. TestDisplayUrlCacheEntryCallback
  530. );
  531. if (!fResult)
  532. PrintLastError("I_CryptNetEnumUrlCacheEntry(Display)");
  533. printf("\nDisplayed %d Url Cache Entries\n", TestArg.cUrl);
  534. if (fOneMatch && 0 == TestArg.cUrl) {
  535. printf("Display failed => no matched entries\n");
  536. fResult = FALSE;
  537. }
  538. if (fNoMatch && 0 != TestArg.cUrl) {
  539. printf("Display failed => expected no matched entries\n");
  540. fResult = FALSE;
  541. }
  542. return fResult;
  543. }
  544. #if 0
  545. from \nt\ds\security\cryptoapi\pki\rpor\rporprov.h
  546. typedef struct _SCHEME_CACHE_META_DATA_HEADER {
  547. DWORD cbSize;
  548. DWORD dwMagic;
  549. DWORD cBlob;
  550. DWORD cbUrl;
  551. FILETIME LastSyncTime;
  552. } SCHEME_CACHE_META_DATA_HEADER, *PSCHEME_CACHE_META_DATA_HEADER;
  553. #endif
  554. #define TEST_LAST_SYNC_TIME_META_DATA_OFFSET (sizeof(DWORD) * 4)
  555. #define TEST_MIN_META_DATA_SIZE \
  556. (TEST_LAST_SYNC_TIME_META_DATA_OFFSET + sizeof(FILETIME))
  557. BOOL
  558. WINAPI
  559. TestSetSyncTimeCallback(
  560. IN const CRYPTNET_URL_CACHE_ENTRY *pUrlCacheEntry,
  561. IN DWORD dwFlags,
  562. IN LPVOID pvReserved,
  563. IN LPVOID pvArg
  564. )
  565. {
  566. BOOL fResult;
  567. BYTE *pbMetaData = NULL;
  568. DWORD cbMetaData;
  569. PTEST_SET_SYNC_TIME_ARG pArg = (PTEST_SET_SYNC_TIME_ARG) pvArg;
  570. if (!TestIsUrlMatch(pUrlCacheEntry->pwszUrl, pArg->pwszUrlSubString))
  571. return TRUE;
  572. printf("SetSyncTime for: %S\n", pUrlCacheEntry->pwszUrl);
  573. if (pArg->fVerbose)
  574. printf("MetaDataFileName: %S\n", pUrlCacheEntry->pwszMetaDataFileName);
  575. if (!ReadDERFromFile(
  576. pUrlCacheEntry->pwszMetaDataFileName,
  577. &pbMetaData,
  578. &cbMetaData
  579. ))
  580. goto ErrorReturn;
  581. if (TEST_MIN_META_DATA_SIZE > cbMetaData) {
  582. printf("Invalid meta data file length: %d, expected at least: %d\n",
  583. cbMetaData, TEST_MIN_META_DATA_SIZE);
  584. goto ErrorReturn;
  585. }
  586. memcpy(pbMetaData + TEST_LAST_SYNC_TIME_META_DATA_OFFSET,
  587. &pArg->LastSyncTime, sizeof(FILETIME));
  588. if (!WriteDERToFile(
  589. pUrlCacheEntry->pwszMetaDataFileName,
  590. pbMetaData,
  591. cbMetaData
  592. ))
  593. goto ErrorReturn;
  594. pArg->cUrl++;
  595. CommonReturn:
  596. TestFree(pbMetaData);
  597. return TRUE;
  598. ErrorReturn:
  599. goto CommonReturn;
  600. }
  601. BOOL TestSetSyncTime(
  602. IN LPCWSTR pwszUrlSubString, // NULL implies delete all
  603. IN BOOL fVerbose,
  604. IN LONG lDeltaSeconds
  605. )
  606. {
  607. BOOL fResult;
  608. TEST_SET_SYNC_TIME_ARG TestArg;
  609. FILETIME CurrentTime;
  610. memset(&TestArg, 0, sizeof(TestArg));
  611. TestArg.pwszUrlSubString = pwszUrlSubString;
  612. TestArg.fVerbose = fVerbose;
  613. GetSystemTimeAsFileTime(&CurrentTime);
  614. if (lDeltaSeconds >= 0)
  615. I_CryptIncrementFileTimeBySeconds(
  616. &CurrentTime,
  617. (DWORD) lDeltaSeconds,
  618. &TestArg.LastSyncTime
  619. );
  620. else
  621. I_CryptDecrementFileTimeBySeconds(
  622. &CurrentTime,
  623. (DWORD) -lDeltaSeconds,
  624. &TestArg.LastSyncTime
  625. );
  626. fResult = I_CryptNetEnumUrlCacheEntry(
  627. 0, // dwFlags
  628. NULL, // pvReserved
  629. &TestArg,
  630. TestSetSyncTimeCallback
  631. );
  632. if (!fResult)
  633. PrintLastError("I_CryptNetEnumUrlCacheEntry(SetSyncTime)");
  634. printf("\nSetSyncTime for %d Url Cache Entries\n", TestArg.cUrl);
  635. if (fOneMatch && 0 == TestArg.cUrl) {
  636. printf("SetSyncTime failed => no matched entries\n");
  637. fResult = FALSE;
  638. }
  639. if (fNoMatch && 0 != TestArg.cUrl) {
  640. printf("SetSyncTime failed => expected no matched entries\n");
  641. fResult = FALSE;
  642. }
  643. return fResult;
  644. }
  645. int _cdecl main(int argc, char * argv[])
  646. {
  647. int status;
  648. LPWSTR pwszUrlSubString = NULL;
  649. BOOL fVerbose = FALSE;
  650. DWORD dwDisplayFlags = 0;
  651. BOOL fContent = FALSE;
  652. BOOL fRawBytes = FALSE;
  653. BOOL fDelete = FALSE;
  654. BOOL fDeleteAll = FALSE;
  655. BOOL fSyncTime = FALSE;
  656. LONG lSyncTimeDeltaSeconds = 0;
  657. while (--argc>0) {
  658. if (**++argv == '-')
  659. {
  660. {
  661. switch(argv[0][1])
  662. {
  663. case 'd':
  664. fDelete = TRUE;
  665. if (argv[0][2]) {
  666. if (0 != _stricmp(argv[0]+2, "ALL")) {
  667. printf("Need to specify -dALL\n");
  668. goto BadUsage;
  669. }
  670. fDeleteAll = TRUE;
  671. }
  672. break;
  673. case 'b':
  674. dwDisplayFlags |= DISPLAY_BRIEF_FLAG;
  675. break;
  676. case 'v':
  677. fVerbose = TRUE;
  678. dwDisplayFlags |= DISPLAY_VERBOSE_FLAG;
  679. break;
  680. case 'c':
  681. fContent = TRUE;
  682. break;
  683. case 'r':
  684. fRawBytes = TRUE;
  685. break;
  686. case 'e':
  687. fExactMatch = TRUE;
  688. break;
  689. case '1':
  690. fOneMatch = TRUE;
  691. break;
  692. case '0':
  693. fNoMatch = TRUE;
  694. break;
  695. case 'S':
  696. fSyncTime = TRUE;
  697. lSyncTimeDeltaSeconds = strtol(argv[0]+2, NULL, 0);
  698. break;
  699. case 'h':
  700. default:
  701. goto BadUsage;
  702. }
  703. }
  704. } else {
  705. if (pwszUrlSubString) {
  706. printf("Multiple Url Subtrings:: %S %s\n",
  707. pwszUrlSubString, argv[0]);
  708. goto BadUsage;
  709. }
  710. pwszUrlSubString = AllocAndSzToWsz(argv[0]);
  711. }
  712. }
  713. printf("command line: %s\n", GetCommandLine());
  714. if (!fExactMatch && pwszUrlSubString)
  715. _wcslwr(pwszUrlSubString);
  716. if (fDelete) {
  717. if (!fDeleteAll && NULL == pwszUrlSubString) {
  718. printf("Missing Url Substring for Delete\n");
  719. goto BadUsage;
  720. }
  721. if (!TestDeleteUrlCacheEntry(
  722. fDeleteAll ? NULL : pwszUrlSubString, // NULL implies delete all
  723. fVerbose
  724. ))
  725. goto ErrorReturn;
  726. } else if (fSyncTime) {
  727. if (NULL == pwszUrlSubString) {
  728. printf("Missing Url Substring for SetSyncTime\n");
  729. goto BadUsage;
  730. }
  731. if (!TestSetSyncTime(
  732. pwszUrlSubString,
  733. fVerbose,
  734. lSyncTimeDeltaSeconds
  735. ))
  736. goto ErrorReturn;
  737. } else {
  738. if (!TestDisplayUrlCacheEntry(
  739. pwszUrlSubString, // NULL implies display all
  740. dwDisplayFlags,
  741. fContent,
  742. fRawBytes
  743. ))
  744. goto ErrorReturn;
  745. }
  746. printf("Passed\n");
  747. status = 0;
  748. CommonReturn:
  749. TestFree(pwszUrlSubString);
  750. return status;
  751. ErrorReturn:
  752. status = -1;
  753. printf("Failed\n");
  754. goto CommonReturn;
  755. BadUsage:
  756. Usage();
  757. goto ErrorReturn;
  758. }