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.

3825 lines
81 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: view.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <pch.cpp>
  11. #pragma hdrstop
  12. #include <esent.h>
  13. #include <certdb.h>
  14. #include "csprop.h"
  15. #define __dwFILE__ __dwFILE_CERTUTIL_VIEW_CPP__
  16. #define wszQUEUE L"Queue"
  17. #define wszLOG L"Log"
  18. #define wszLOGFAIL L"LogFail"
  19. #define wszREVOKED L"Revoked"
  20. #define wszCOLONQUEUE L":" wszQUEUE
  21. #define wszCOLONLOG L":" wszLOG
  22. #define wszCOLONLOGFAIL L":" wszLOGFAIL
  23. #define wszCOLONREVOKED L":" wszREVOKED
  24. ICertDB *g_pdb = NULL;
  25. WCHAR const g_wszAttrib[] = L"attrib";
  26. WCHAR const g_wszExt[] = L"ext";
  27. WCHAR const g_wszCRL[] = L"CRL";
  28. WCHAR const *g_apwszAllowedPrefixes[] =
  29. {
  30. g_wszAttrib,
  31. g_wszExt,
  32. NULL
  33. };
  34. BOOL
  35. cuDBIsShutDownInProgress()
  36. {
  37. return(NULL == g_pdb);
  38. }
  39. HRESULT
  40. ParseToken(
  41. OUT WCHAR *awcBuf,
  42. IN DWORD cwcBuf,
  43. IN BOOL fMatchPrefix,
  44. OPTIONAL IN WCHAR const *pwszPrefix,
  45. OPTIONAL IN WCHAR const * const *apwszAllowedPrefixes,
  46. OPTIONAL OUT BOOL *pfAllColumns,
  47. OUT WCHAR const **ppwszColumn,
  48. IN OUT WCHAR const **ppwszNext);
  49. WCHAR const *
  50. cuwszPropType(
  51. IN LONG PropType)
  52. {
  53. DWORD msgid;
  54. switch (PropType)
  55. {
  56. case PROPTYPE_DATE:
  57. msgid = IDS_PROPTYPE_DATE; // "Date"
  58. break;
  59. case PROPTYPE_LONG:
  60. msgid = IDS_PROPTYPE_LONG; // "Long"
  61. break;
  62. case PROPTYPE_STRING:
  63. msgid = IDS_PROPTYPE_STRING; // "String"
  64. break;
  65. case PROPTYPE_BINARY:
  66. msgid = IDS_PROPTYPE_BINARY; // "Binary"
  67. break;
  68. default:
  69. msgid = IDS_QUESTIONMARKS; // "???"
  70. break;
  71. }
  72. return(myLoadResourceString(msgid));
  73. }
  74. typedef struct _COLINFO
  75. {
  76. BSTR strCol;
  77. BSTR strColDisplay;
  78. LONG type;
  79. LONG maxlen;
  80. LONG indexed;
  81. } COLINFO;
  82. VOID
  83. cuPrintSchemaEntry(
  84. OPTIONAL IN WCHAR const *pwszName,
  85. IN WCHAR const *pwszDisplayName,
  86. IN LONG Type,
  87. IN LONG cbMax)
  88. {
  89. // wprintf(L" %-28ws %-28ws %-6ws", ...);
  90. // OR
  91. // wprintf(L"%-30ws %-6ws", ...);
  92. if (NULL != pwszName)
  93. {
  94. wprintf(L" ");
  95. myConsolePrintString(28, pwszName);
  96. wprintf(L" ");
  97. }
  98. myConsolePrintString(NULL != pwszName? 28 : 30, pwszDisplayName);
  99. wprintf(L" ");
  100. myConsolePrintString(6, cuwszPropType(PROPTYPE_MASK & Type));
  101. if (0 != cbMax)
  102. {
  103. wprintf(L" %u", cbMax);
  104. }
  105. if (PROPFLAGS_INDEXED & Type)
  106. {
  107. wprintf(myLoadResourceString(IDS_INDEXED)); // " -- Indexed"
  108. }
  109. wprintf(wszNewLine);
  110. }
  111. HRESULT
  112. DisplaySchema(
  113. IN DISPATCHINTERFACE *pdiView,
  114. IN LONG cColOut,
  115. OPTIONAL IN OUT COLINFO *aColInfo,
  116. IN BOOL fResult)
  117. {
  118. HRESULT hr;
  119. LONG i;
  120. BOOL fMustReleaseColumn = FALSE;
  121. DISPATCHINTERFACE diViewColumn;
  122. BSTR strCol = NULL;
  123. BSTR strColDisplay = NULL;
  124. LONG type;
  125. LONG maxlen;
  126. LONG indexed;
  127. if (!g_fCryptSilent)
  128. {
  129. wprintf(myLoadResourceString(IDS_SCHEMA_COLON)); // "Schema:"
  130. wprintf(wszNewLine);
  131. wprintf(myLoadResourceString(IDS_SCHEMA_COLUMNHEADERS)); // "Name..Type..."
  132. wprintf(wszNewLine);
  133. wprintf(myLoadResourceString(IDS_SCHEMA_COLUMNUNDERLINE)); // "____...____"
  134. wprintf(wszNewLine);
  135. }
  136. hr = View_EnumCertViewColumn(
  137. pdiView,
  138. fResult? CVRC_COLUMN_RESULT : CVRC_COLUMN_SCHEMA,
  139. &diViewColumn);
  140. _JumpIfError(hr, error, "View_EnumCertViewColumn");
  141. fMustReleaseColumn = TRUE;
  142. for (i = 0; ; i++)
  143. {
  144. LONG ielt;
  145. hr = ViewColumn_Next(&diViewColumn, &ielt);
  146. if (S_FALSE == hr || (S_OK == hr && -1 == ielt))
  147. {
  148. CSASSERT(-1 == ielt);
  149. CSASSERT(i == cColOut);
  150. hr = S_OK;
  151. break;
  152. }
  153. _JumpIfError(hr, error, "ViewColumn_Next");
  154. CSASSERT(-1 != ielt);
  155. CSASSERT(i < cColOut);
  156. hr = ViewColumn_GetName(&diViewColumn, &strCol);
  157. _JumpIfError(hr, error, "ViewColumn_GetName");
  158. hr = ViewColumn_GetDisplayName(&diViewColumn, &strColDisplay);
  159. _JumpIfError(hr, error, "ViewColumn_GetDisplayName");
  160. hr = ViewColumn_GetType(&diViewColumn, &type);
  161. _JumpIfError(hr, error, "ViewColumn_GetType");
  162. hr = ViewColumn_GetMaxLength(&diViewColumn, &maxlen);
  163. _JumpIfError(hr, error, "ViewColumn_GetType");
  164. hr = ViewColumn_IsIndexed(&diViewColumn, &indexed);
  165. _JumpIfError(hr, error, "ViewColumn_IsIndexed");
  166. if (!g_fCryptSilent)
  167. {
  168. cuPrintSchemaEntry(
  169. strCol,
  170. strColDisplay,
  171. type | (indexed? PROPFLAGS_INDEXED : 0),
  172. maxlen);
  173. }
  174. if (NULL != aColInfo)
  175. {
  176. aColInfo[i].strCol = strCol;
  177. strCol = NULL;
  178. aColInfo[i].strColDisplay = strColDisplay;
  179. strColDisplay = NULL;
  180. aColInfo[i].type = type;
  181. aColInfo[i].maxlen = maxlen;
  182. aColInfo[i].indexed = indexed;
  183. }
  184. }
  185. error:
  186. if (NULL != strCol)
  187. {
  188. SysFreeString(strCol);
  189. }
  190. if (NULL != strColDisplay)
  191. {
  192. SysFreeString(strColDisplay);
  193. }
  194. if (fMustReleaseColumn)
  195. {
  196. ViewColumn_Release(&diViewColumn);
  197. }
  198. return(hr);
  199. }
  200. LONG *g_askip = NULL;
  201. LONG g_cskip = 0;
  202. LONG g_iskip = 0;
  203. BOOL g_fskip = FALSE;
  204. LONG
  205. GetSkip(
  206. IN BOOL fAdvance)
  207. {
  208. LONG cskip = 0;
  209. if (g_fskip)
  210. {
  211. if (g_iskip >= g_cskip)
  212. {
  213. g_iskip = 0;
  214. }
  215. cskip = g_askip[g_iskip];
  216. if (fAdvance)
  217. {
  218. g_iskip++;
  219. }
  220. }
  221. return(cskip);
  222. }
  223. HRESULT
  224. ParseSkipCounts(
  225. IN WCHAR const *pwszField)
  226. {
  227. HRESULT hr;
  228. LONG i;
  229. WCHAR const *pwszNext;
  230. WCHAR const *pwszColumn;
  231. WCHAR awc[MAX_PATH];
  232. pwszNext = pwszField;
  233. for (i = 0; ; i++)
  234. {
  235. hr = ParseToken(
  236. awc,
  237. ARRAYSIZE(awc),
  238. FALSE,
  239. NULL,
  240. NULL,
  241. NULL,
  242. &pwszColumn,
  243. &pwszNext);
  244. if (S_FALSE == hr)
  245. {
  246. break;
  247. }
  248. _JumpIfError(hr, error, "ParseToken");
  249. }
  250. if (0 != i)
  251. {
  252. g_askip = (LONG *) LocalAlloc(LMEM_FIXED, i * sizeof(LONG));
  253. if (NULL == g_askip)
  254. {
  255. hr = E_OUTOFMEMORY;
  256. _JumpError(hr, error, "no memory for skip counts array");
  257. }
  258. g_cskip = i;
  259. g_iskip = 0;
  260. pwszNext = pwszField;
  261. for (i = 0; ; i++)
  262. {
  263. hr = ParseToken(
  264. awc,
  265. ARRAYSIZE(awc),
  266. FALSE,
  267. NULL,
  268. NULL,
  269. NULL,
  270. &pwszColumn,
  271. &pwszNext);
  272. if (S_FALSE == hr)
  273. {
  274. break;
  275. }
  276. _JumpIfError(hr, error, "ParseToken");
  277. hr = myGetSignedLong(pwszColumn, &g_askip[i]);
  278. _JumpIfError(hr, error, "myGetLong");
  279. //wprintf(L"ParseToken: %u: skip = '%ws' %d\n", i, pwszColumn, g_askip[i]);
  280. }
  281. CSASSERT(i == g_cskip);
  282. g_fskip = TRUE;
  283. }
  284. hr = S_OK;
  285. error:
  286. return(hr);
  287. }
  288. HRESULT
  289. ParseRestriction(
  290. IN WCHAR const *pwszField,
  291. OUT LONG *pColIndex,
  292. OUT LONG *pSeekOperator,
  293. OUT LONG *pSortOrder,
  294. OUT WCHAR **ppwszColName,
  295. OUT WCHAR **ppwszColValue)
  296. {
  297. HRESULT hr;
  298. DWORD i;
  299. LONG SortOrder;
  300. LONG SeekOperator;
  301. LONG SeekOperator2;
  302. WCHAR *pwszColName = NULL;
  303. WCHAR *pwszColValue = NULL;
  304. *pColIndex = 0;
  305. *ppwszColName = NULL;
  306. *ppwszColValue = NULL;
  307. SeekOperator = CVR_SEEK_GE;
  308. SeekOperator2 = CVR_SEEK_GE; // might be used inadvertantly
  309. SortOrder = CVR_SORT_NONE;
  310. if (L'+' == *pwszField)
  311. {
  312. SortOrder = CVR_SORT_ASCEND;
  313. pwszField++;
  314. }
  315. else if (myIsMinusSign(*pwszField))
  316. {
  317. SortOrder = CVR_SORT_DESCEND;
  318. pwszField++;
  319. }
  320. while (L' ' == *pwszField)
  321. {
  322. pwszField++;
  323. }
  324. // Copy the column name into wszBuf, and advance the pointer
  325. i = wcscspn(pwszField, L"<>=");
  326. pwszColName = (WCHAR *) LocalAlloc(LMEM_FIXED, (i + 1) * sizeof(WCHAR));
  327. if (NULL == pwszColName)
  328. {
  329. hr = E_OUTOFMEMORY;
  330. _JumpError(hr, error, "LocalAlloc");
  331. }
  332. CopyMemory(pwszColName, pwszField, i * sizeof(WCHAR));
  333. pwszField += i;
  334. while (0 < i && L' ' == pwszColName[i - 1])
  335. {
  336. i--;
  337. }
  338. pwszColName[i] = L'\0';
  339. switch (*pwszField)
  340. {
  341. case L'\0':
  342. SeekOperator = CVR_SEEK_NONE;
  343. break;
  344. case L'<':
  345. SeekOperator = CVR_SEEK_LT; // "<"
  346. SeekOperator2 = CVR_SEEK_LE; // "<="
  347. break;
  348. case L'>':
  349. SeekOperator = CVR_SEEK_GT; // ">"
  350. SeekOperator2 = CVR_SEEK_GE; // ">="
  351. break;
  352. case L'=':
  353. SeekOperator = CVR_SEEK_EQ; // "="
  354. SeekOperator2 = CVR_SEEK_EQ; // "=="
  355. break;
  356. default:
  357. hr = E_INVALIDARG;
  358. _JumpError(hr, error, "bad seek operator");
  359. }
  360. if (L'\0' != *pwszField)
  361. {
  362. if (L'=' == *++pwszField)
  363. {
  364. SeekOperator = SeekOperator2;
  365. pwszField++;
  366. }
  367. }
  368. while (L' ' == *pwszField)
  369. {
  370. pwszField++;
  371. }
  372. i = wcslen(pwszField);
  373. if (0 != i)
  374. {
  375. pwszColValue = (WCHAR *) LocalAlloc(
  376. LMEM_FIXED,
  377. (i + 1) * sizeof(WCHAR));
  378. if (NULL == pwszColValue)
  379. {
  380. hr = E_OUTOFMEMORY;
  381. _JumpError(hr, error, "LocalAlloc");
  382. }
  383. wcscpy(pwszColValue, pwszField);
  384. while (0 < i && L' ' == pwszColValue[i - 1])
  385. {
  386. i--;
  387. }
  388. pwszColValue[i] = L'\0';
  389. cuConvertEscapeSequences(pwszColValue);
  390. }
  391. if (NULL == pwszColValue)
  392. {
  393. if (0 == LSTRCMPIS(pwszColName, wszCOLONQUEUE))
  394. {
  395. *pColIndex = CV_COLUMN_QUEUE_DEFAULT;
  396. }
  397. else if (0 == LSTRCMPIS(pwszColName, wszCOLONLOG))
  398. {
  399. *pColIndex = CV_COLUMN_LOG_DEFAULT;
  400. }
  401. else if (0 == LSTRCMPIS(pwszColName, wszCOLONLOGFAIL))
  402. {
  403. *pColIndex = CV_COLUMN_LOG_FAILED_DEFAULT;
  404. }
  405. else if (0 == LSTRCMPIS(pwszColName, wszCOLONREVOKED))
  406. {
  407. *pColIndex = CV_COLUMN_LOG_REVOKED_DEFAULT;
  408. }
  409. else
  410. {
  411. hr = E_INVALIDARG;
  412. _JumpError(hr, error, "bad special column name");
  413. }
  414. }
  415. else
  416. {
  417. *ppwszColName = pwszColName;
  418. *ppwszColValue = pwszColValue;
  419. pwszColName = NULL;
  420. pwszColValue = NULL;
  421. }
  422. *pSortOrder = SortOrder;
  423. *pSeekOperator = SeekOperator;
  424. hr = S_OK;
  425. error:
  426. if (NULL != pwszColName)
  427. {
  428. LocalFree(pwszColName);
  429. }
  430. if (NULL != pwszColValue)
  431. {
  432. LocalFree(pwszColValue);
  433. }
  434. return(hr);
  435. }
  436. HRESULT
  437. ParseSpecialColumnValue(
  438. IN WCHAR const *pwszColValue,
  439. IN LONG ColType,
  440. IN OUT LONG *pSeekOperator,
  441. IN OUT LONG *pSortOrder,
  442. OUT BOOL *pfOneRow,
  443. OUT LONG *plSkip)
  444. {
  445. HRESULT hr;
  446. BOOL fFirst;
  447. *pfOneRow = FALSE;
  448. *plSkip = 0;
  449. switch (*pwszColValue)
  450. {
  451. case '^':
  452. fFirst = TRUE;
  453. break;
  454. case '$':
  455. fFirst = FALSE;
  456. break;
  457. default:
  458. hr = S_OK;
  459. goto error;
  460. }
  461. while (L' ' == *++pwszColValue)
  462. ;
  463. if (L'\0' != *pwszColValue)
  464. {
  465. BOOL fInvalid;
  466. switch (*pwszColValue)
  467. {
  468. case '+':
  469. fInvalid = !fFirst;
  470. break;
  471. case '-':
  472. fInvalid = fFirst;
  473. break;
  474. default:
  475. hr = E_INVALIDARG;
  476. _JumpErrorStr(hr, error, "expected signed skip count", pwszColValue);
  477. }
  478. if (fInvalid)
  479. {
  480. hr = E_INVALIDARG;
  481. _JumpError(hr, error, "skip to before start");
  482. }
  483. while (L' ' == *++pwszColValue)
  484. ;
  485. hr = myGetLong(pwszColValue, plSkip);
  486. _JumpIfError(hr, error, "bad numeric operand");
  487. }
  488. if (CVR_SEEK_EQ != *pSeekOperator || CVR_SORT_NONE != *pSortOrder)
  489. {
  490. hr = E_INVALIDARG;
  491. _JumpError(hr, error, "bad special restriction");
  492. }
  493. if (fFirst)
  494. {
  495. *pSortOrder = CVR_SORT_ASCEND;
  496. }
  497. else
  498. {
  499. *pSortOrder = CVR_SORT_DESCEND;
  500. }
  501. *pSeekOperator = CVR_SEEK_GE;
  502. *pfOneRow = TRUE;
  503. hr = S_OK;
  504. error:
  505. return(hr);
  506. }
  507. HRESULT
  508. SetViewRestriction(
  509. IN DISPATCHINTERFACE *pdiView,
  510. IN WCHAR const *pwszField,
  511. OUT BOOL *pfOneRow,
  512. OUT LONG *plSkip)
  513. {
  514. HRESULT hr;
  515. VARIANT var;
  516. LONG ColIndex;
  517. LONG ColType;
  518. BSTR strColName = NULL;
  519. LONG SeekOperator;
  520. LONG SortOrder;
  521. WCHAR *pwszColName = NULL;
  522. WCHAR *pwszColValue = NULL;
  523. BOOL fMustReleaseColumn = FALSE;
  524. DISPATCHINTERFACE diViewColumn;
  525. VariantInit(&var);
  526. *pfOneRow = FALSE;
  527. *plSkip = 0;
  528. hr = ParseRestriction(
  529. pwszField,
  530. &ColIndex,
  531. &SeekOperator,
  532. &SortOrder,
  533. &pwszColName,
  534. &pwszColValue);
  535. _JumpIfErrorStr(hr, error, "ParseRestriction", pwszField);
  536. // no value to parse if a special column...
  537. if (NULL == pwszColName)
  538. {
  539. CSASSERT(0 > ColIndex);
  540. }
  541. else
  542. {
  543. LONG ielt;
  544. hr = View_GetColumnIndex(
  545. pdiView,
  546. CVRC_COLUMN_SCHEMA,
  547. pwszColName,
  548. &ColIndex);
  549. _JumpIfErrorStr(hr, error, "View_GetColumnIndex", pwszColName);
  550. hr = View_EnumCertViewColumn(
  551. pdiView,
  552. CVRC_COLUMN_SCHEMA,
  553. &diViewColumn);
  554. _JumpIfError(hr, error, "View_EnumCertViewColumn");
  555. fMustReleaseColumn = TRUE;
  556. hr = ViewColumn_Skip(&diViewColumn, ColIndex);
  557. _JumpIfError(hr, error, "ViewColumn_Skip");
  558. hr = ViewColumn_Next(&diViewColumn, &ielt);
  559. if (S_OK == hr && -1 == ielt)
  560. {
  561. hr = S_FALSE;
  562. }
  563. _JumpIfError(hr, error, "ViewColumn_Next");
  564. hr = ViewColumn_GetName(&diViewColumn, &strColName);
  565. _JumpIfError(hr, error, "GetName");
  566. hr = ViewColumn_GetType(&diViewColumn, &ColType);
  567. _JumpIfError(hr, error, "GetType");
  568. hr = ParseSpecialColumnValue(
  569. pwszColValue,
  570. ColType,
  571. &SeekOperator,
  572. &SortOrder,
  573. pfOneRow,
  574. plSkip);
  575. _JumpIfError(hr, error, "ParseSpecialColumnValue");
  576. switch (ColType)
  577. {
  578. case PROPTYPE_LONG:
  579. var.lVal = 0;
  580. if (!*pfOneRow)
  581. {
  582. hr = myGetSignedLong(pwszColValue, &var.lVal);
  583. _JumpIfError(hr, error, "bad numeric operand");
  584. }
  585. var.vt = VT_I4;
  586. break;
  587. case PROPTYPE_DATE:
  588. var.date = 0;
  589. if (!*pfOneRow)
  590. {
  591. hr = myWszLocalTimeToGMTDate(pwszColValue, &var.date);
  592. _JumpIfError(hr, error, "invalid date format");
  593. }
  594. var.vt = VT_DATE;
  595. cuDumpDate(&var.date);
  596. break;
  597. case PROPTYPE_STRING:
  598. {
  599. WCHAR const *pwsz = L"";
  600. var.bstrVal = NULL;
  601. if (!*pfOneRow)
  602. {
  603. pwsz = pwszColValue;
  604. }
  605. if (!ConvertWszToBstr(&var.bstrVal, pwsz, MAXDWORD))
  606. {
  607. hr = E_OUTOFMEMORY;
  608. _JumpError(hr, error, "ConvertWszToBstr");
  609. }
  610. var.vt = VT_BSTR;
  611. break;
  612. }
  613. case PROPTYPE_BINARY:
  614. default:
  615. hr = E_INVALIDARG;
  616. _JumpError(hr, error, "not supported");
  617. }
  618. }
  619. //wprintf(L"ColIndex=%x(%d) vt=%d\n", ColIndex, ColIndex, var.vt);
  620. hr = View_SetRestriction(
  621. pdiView,
  622. ColIndex, // Restriction ColumnIndex
  623. SeekOperator,
  624. SortOrder,
  625. &var); // pvarValue
  626. _JumpIfError(hr, error, "View_SetRestriction");
  627. error:
  628. if (NULL != pwszColName)
  629. {
  630. LocalFree(pwszColName);
  631. }
  632. if (NULL != pwszColValue)
  633. {
  634. LocalFree(pwszColValue);
  635. }
  636. if (fMustReleaseColumn)
  637. {
  638. ViewColumn_Release(&diViewColumn);
  639. }
  640. if (NULL != strColName)
  641. {
  642. SysFreeString(strColName);
  643. }
  644. VariantClear(&var);
  645. return(hr);
  646. }
  647. HRESULT
  648. cuParseStrings(
  649. IN WCHAR const *pwszStrings,
  650. IN BOOL fMatchPrefix,
  651. OPTIONAL IN WCHAR const *pwszPrefix,
  652. OPTIONAL IN WCHAR const * const *apwszAllowedPrefixes,
  653. OUT WCHAR ***papwszStrings,
  654. OPTIONAL OUT BOOL *pfAllFields)
  655. {
  656. HRESULT hr;
  657. WCHAR const *pwszNext;
  658. WCHAR awc[MAX_PATH];
  659. DWORD i;
  660. WCHAR const *pwszCurrent;
  661. WCHAR **ppwsz;
  662. if (NULL != pfAllFields)
  663. {
  664. *pfAllFields = FALSE;
  665. }
  666. *papwszStrings = NULL;
  667. pwszNext = pwszStrings;
  668. for (i = 0; ; i++)
  669. {
  670. hr = ParseToken(
  671. awc,
  672. ARRAYSIZE(awc),
  673. fMatchPrefix,
  674. pwszPrefix,
  675. apwszAllowedPrefixes,
  676. pfAllFields,
  677. &pwszCurrent,
  678. &pwszNext);
  679. if (S_FALSE == hr)
  680. {
  681. break;
  682. }
  683. _JumpIfError(hr, error, "ParseToken");
  684. }
  685. if (0 != i)
  686. {
  687. *papwszStrings = (WCHAR **) LocalAlloc(
  688. LMEM_FIXED | LMEM_ZEROINIT,
  689. (i + 1) * sizeof(WCHAR *));
  690. if (NULL == *papwszStrings)
  691. {
  692. hr = E_OUTOFMEMORY;
  693. _JumpError(hr, error, "no memory for string array");
  694. }
  695. ppwsz = *papwszStrings;
  696. pwszNext = pwszStrings;
  697. for ( ; 0 < i; i--)
  698. {
  699. hr = ParseToken(
  700. awc,
  701. ARRAYSIZE(awc),
  702. fMatchPrefix,
  703. pwszPrefix,
  704. apwszAllowedPrefixes,
  705. pfAllFields,
  706. &pwszCurrent,
  707. &pwszNext);
  708. CSASSERT(S_FALSE != hr);
  709. _JumpIfError(hr, error, "ParseToken");
  710. hr = myDupString(pwszCurrent, ppwsz);
  711. _JumpIfError(hr, error, "myDupString");
  712. ppwsz++;
  713. }
  714. *ppwsz = NULL;
  715. }
  716. hr = S_OK;
  717. error:
  718. if (S_OK != hr)
  719. {
  720. cuFreeStringArray(*papwszStrings);
  721. *papwszStrings = NULL;
  722. }
  723. return(hr);
  724. }
  725. HRESULT
  726. ParseViewRestrictions(
  727. IN WCHAR const *pwszRestrictions,
  728. OUT WCHAR ***papwszRestrictions)
  729. {
  730. HRESULT hr;
  731. hr = cuParseStrings(
  732. pwszRestrictions,
  733. FALSE,
  734. NULL,
  735. NULL,
  736. papwszRestrictions,
  737. NULL);
  738. _JumpIfError(hr, error, "cuParseStrings");
  739. error:
  740. return(hr);
  741. }
  742. HRESULT
  743. ParseToken(
  744. OUT WCHAR *awcBuf,
  745. IN DWORD cwcBuf,
  746. IN BOOL fMatchPrefix,
  747. OPTIONAL IN WCHAR const *pwszPrefix,
  748. OPTIONAL IN WCHAR const * const *apwszAllowedPrefixes,
  749. OPTIONAL OUT BOOL *pfAllColumns,
  750. OUT WCHAR const **ppwszColumn,
  751. IN OUT WCHAR const **ppwszNext)
  752. {
  753. HRESULT hr;
  754. WCHAR const *pwsz;
  755. WCHAR *pwszT;
  756. WCHAR *pwszColumn;
  757. DWORD cwc;
  758. DWORD cwcPrefix = 0;
  759. if (NULL != pwszPrefix)
  760. {
  761. cwcPrefix = wcslen(pwszPrefix);
  762. }
  763. while (TRUE)
  764. {
  765. // Grab the next comma-separated token, and trim white space.
  766. awcBuf[0] = L'\0';
  767. pwsz = *ppwszNext;
  768. while (L' ' == *pwsz)
  769. {
  770. pwsz++;
  771. }
  772. cwc = wcscspn(pwsz, L",");
  773. if (cwc >= cwcBuf)
  774. {
  775. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  776. _JumpError(hr, error, "Buffer overflow");
  777. }
  778. CopyMemory(awcBuf, pwsz, cwc * sizeof(WCHAR));
  779. awcBuf[cwc] = L'\0';
  780. pwsz += cwc;
  781. while (L',' == *pwsz)
  782. {
  783. pwsz++;
  784. }
  785. *ppwszNext = pwsz;
  786. while (0 < cwc && L' ' == awcBuf[cwc - 1])
  787. {
  788. awcBuf[--cwc] = L'\0';
  789. }
  790. if (0 == cwc)
  791. {
  792. if (L'\0' == *pwsz)
  793. {
  794. *ppwszColumn = NULL;
  795. hr = S_FALSE;
  796. _JumpError2(hr, error, "end of list", hr);
  797. }
  798. continue;
  799. }
  800. pwszColumn = awcBuf; // assume no prefix
  801. if (fMatchPrefix)
  802. {
  803. // Look for a colon separator that delimits a matching prefix.
  804. // The separator must precede any relational operators:
  805. cwc = wcscspn(awcBuf, L"<>=:");
  806. pwszT = &awcBuf[cwc];
  807. if (L':' != *pwszT)
  808. {
  809. if (NULL != pwszPrefix)
  810. {
  811. continue; // prefix missing, but expected
  812. }
  813. }
  814. else
  815. {
  816. pwszColumn = pwszT;
  817. *pwszColumn++ = L'\0';
  818. while (L' ' == *pwszColumn)
  819. {
  820. pwszColumn++;
  821. }
  822. while (pwszT > awcBuf && L' ' == *(pwszT - 1))
  823. {
  824. *--pwszT = L'\0';
  825. }
  826. if (NULL != apwszAllowedPrefixes)
  827. {
  828. WCHAR const * const *ppwsz;
  829. for (ppwsz = apwszAllowedPrefixes; NULL != *ppwsz; ppwsz++)
  830. {
  831. if (0 == mylstrcmpiS(awcBuf, *ppwsz))
  832. {
  833. break;
  834. }
  835. }
  836. if (NULL == *ppwsz)
  837. {
  838. hr = E_INVALIDARG;
  839. _JumpErrorStr(hr, error, "bad prefix", awcBuf);
  840. }
  841. }
  842. if (NULL == pwszPrefix)
  843. {
  844. continue; // prefix not expected
  845. }
  846. if (pwszT - awcBuf != (LONG) cwcPrefix)
  847. {
  848. continue; // prefix length doesn't match
  849. }
  850. if (0 != mylstrcmpiS(awcBuf, pwszPrefix))
  851. {
  852. continue; // prefix doesn't match
  853. }
  854. }
  855. if (NULL != pfAllColumns && 0 == LSTRCMPIS(pwszColumn, L"all"))
  856. {
  857. *pfAllColumns = TRUE;
  858. continue;
  859. }
  860. }
  861. *ppwszColumn = pwszColumn;
  862. hr = S_OK;
  863. break;
  864. }
  865. error:
  866. if (S_OK != hr && 0 < cwcBuf)
  867. {
  868. awcBuf[0] = L'\0';
  869. }
  870. return(hr);
  871. }
  872. HRESULT
  873. ParseViewColumns(
  874. IN WCHAR const *pwszColumns,
  875. IN WCHAR const *pwszPrefix,
  876. OPTIONAL IN WCHAR const * const *apwszAllowedPrefixes,
  877. OUT WCHAR ***papwszColumns,
  878. OUT BOOL *pfAllColumns)
  879. {
  880. HRESULT hr;
  881. hr = cuParseStrings(
  882. pwszColumns,
  883. TRUE,
  884. pwszPrefix,
  885. apwszAllowedPrefixes,
  886. papwszColumns,
  887. pfAllColumns);
  888. _JumpIfError(hr, error, "cuParseStrings");
  889. error:
  890. return(hr);
  891. }
  892. VOID
  893. PrintRowIndex(
  894. IN LONG iRow,
  895. IN OUT BOOL *pfPrinted)
  896. {
  897. if (!*pfPrinted)
  898. {
  899. wprintf(wszNewLine);
  900. wprintf(myLoadResourceString(IDS_FORMAT_ROWID), iRow); // "Row %u:"
  901. wprintf(wszNewLine);
  902. *pfPrinted = TRUE;
  903. }
  904. }
  905. VOID
  906. cuFreeStringArray(
  907. IN OUT WCHAR **apwsz)
  908. {
  909. WCHAR **ppwsz;
  910. if (NULL != apwsz)
  911. {
  912. for (ppwsz = apwsz; NULL != *ppwsz; ppwsz++)
  913. {
  914. myZeroDataString(*ppwsz); // possible password data
  915. LocalFree(*ppwsz);
  916. }
  917. LocalFree(apwsz);
  918. }
  919. }
  920. VOID
  921. cuFreeStringArrayA(
  922. IN OUT char **apsz)
  923. {
  924. char **ppsz;
  925. if (NULL != apsz)
  926. {
  927. for (ppsz = apsz; NULL != *ppsz; ppsz++)
  928. {
  929. LocalFree(*ppsz);
  930. }
  931. LocalFree(apsz);
  932. }
  933. }
  934. VOID
  935. DumpLongValue(
  936. IN LONG longValue,
  937. IN WCHAR const *pwszColumnName)
  938. {
  939. long aidMsg[20];
  940. DWORD cidMsg;
  941. DWORD i;
  942. WCHAR const *pwszError = NULL;
  943. WCHAR const *pwszMsg = NULL;
  944. WCHAR awchr[cwcHRESULTSTRING];
  945. BOOL fDisplayNumeric = TRUE;
  946. BOOL fDisplayFlags = FALSE;
  947. cidMsg = 0;
  948. if (0 == LSTRCMPIS(
  949. pwszColumnName,
  950. wszPROPREQUESTDOT wszPROPREQUESTDISPOSITION))
  951. {
  952. switch (longValue)
  953. {
  954. case DB_DISP_ACTIVE: aidMsg[0] = IDS_DISP_ACTIVE; break;
  955. case DB_DISP_PENDING: aidMsg[0] = IDS_DISP_PENDING; break;
  956. case DB_DISP_FOREIGN: aidMsg[0] = IDS_DISP_FOREIGN_CERT; break;
  957. case DB_DISP_KRA_CERT: aidMsg[0] = IDS_DISP_KRA_CERT; break;
  958. case DB_DISP_CA_CERT: aidMsg[0] = IDS_DISP_CA_CERT; break;
  959. case DB_DISP_CA_CERT_CHAIN:
  960. aidMsg[0] = IDS_DISP_CA_CERT_CHAIN; break;
  961. case DB_DISP_ISSUED: aidMsg[0] = IDS_DISP_ISSUED; break;
  962. case DB_DISP_REVOKED: aidMsg[0] = IDS_DISP_REVOKED; break;
  963. case DB_DISP_ERROR: aidMsg[0] = IDS_DISP_ERROR; break;
  964. case DB_DISP_DENIED: aidMsg[0] = IDS_DISP_DENIED; break;
  965. default: aidMsg[0] = IDS_QUESTIONMARKS; break;
  966. }
  967. cidMsg = 1;
  968. }
  969. else
  970. if (0 == LSTRCMPIS(pwszColumnName, wszPROPREQUESTDOT wszPROPREQUESTFLAGS))
  971. {
  972. if (CR_FLG_RENEWAL & longValue)
  973. {
  974. aidMsg[cidMsg++] = IDS_REQFLAGS_RENEWAL;
  975. }
  976. if (CR_FLG_FORCETELETEX & longValue)
  977. {
  978. aidMsg[cidMsg++] = IDS_REQFLAGS_FORCETELETEX;
  979. }
  980. if (CR_FLG_FORCEUTF8 & longValue)
  981. {
  982. aidMsg[cidMsg++] = IDS_REQFLAGS_FORCEUTF8;
  983. }
  984. if (CR_FLG_CAXCHGCERT & longValue)
  985. {
  986. aidMsg[cidMsg++] = IDS_REQFLAGS_CAXCHGCERT;
  987. }
  988. if (CR_FLG_ENROLLONBEHALFOF & longValue)
  989. {
  990. aidMsg[cidMsg++] = IDS_REQFLAGS_ENROLLONBEHALFOF;
  991. }
  992. if (CR_FLG_SUBJECTUNMODIFIED & longValue)
  993. {
  994. aidMsg[cidMsg++] = IDS_REQFLAGS_SUBJECTUNMODIFIED;
  995. }
  996. if (CR_FLG_VALIDENCRYPTEDKEYHASH & longValue)
  997. {
  998. aidMsg[cidMsg++] = IDS_REQFLAGS_VALIDENCRYPTEDKEYHASH;
  999. }
  1000. if (CR_FLG_PUBLISHERROR & longValue)
  1001. {
  1002. aidMsg[cidMsg++] = IDS_REQFLAGS_PUBLISHERROR;
  1003. }
  1004. if (CR_FLG_CACROSSCERT & longValue)
  1005. {
  1006. aidMsg[cidMsg++] = IDS_REQFLAGS_CACROSSCERT;
  1007. }
  1008. }
  1009. else
  1010. if (0 == LSTRCMPIS(pwszColumnName, wszPROPREQUESTDOT wszPROPREQUESTTYPE))
  1011. {
  1012. switch (CR_IN_FORMATMASK & longValue)
  1013. {
  1014. case CR_IN_FORMATANY: aidMsg[0] = IDS_REQTYPE_ANY; break;
  1015. case CR_IN_PKCS10: aidMsg[0] = IDS_REQTYPE_PKCS10; break;
  1016. case CR_IN_KEYGEN: aidMsg[0] = IDS_REQTYPE_KEYGEN; break;
  1017. case CR_IN_PKCS7: aidMsg[0] = IDS_REQTYPE_PKCS7; break;
  1018. case CR_IN_CMC: aidMsg[0] = IDS_REQTYPE_CMC; break;
  1019. default: aidMsg[0] = IDS_REQTYPE_UNKNOWN; break;
  1020. }
  1021. cidMsg = 1;
  1022. if (CR_IN_CRLS & longValue)
  1023. {
  1024. aidMsg[cidMsg++] = IDS_REQTYPE_CRLS;
  1025. }
  1026. if (CR_IN_FULLRESPONSE & longValue)
  1027. {
  1028. aidMsg[cidMsg++] = IDS_REQTYPE_FULLRESPONSE;
  1029. }
  1030. }
  1031. else
  1032. if (0 == LSTRCMPIS(
  1033. pwszColumnName,
  1034. wszPROPREQUESTDOT wszPROPREQUESTSTATUSCODE) ||
  1035. 0 == LSTRCMPIS(pwszColumnName, wszPROPCRLPUBLISHSTATUSCODE))
  1036. {
  1037. pwszError = myGetErrorMessageText(longValue, FALSE);
  1038. wprintf(L" %ws -- %ws", myHResultToString(awchr, longValue), pwszError);
  1039. fDisplayNumeric = FALSE;
  1040. }
  1041. else
  1042. if (0 == LSTRCMPIS(
  1043. pwszColumnName,
  1044. wszPROPREQUESTDOT wszPROPREQUESTREVOKEDREASON))
  1045. {
  1046. aidMsg[0] = cuidCRLReason(longValue);
  1047. cidMsg = 1;
  1048. }
  1049. else
  1050. {
  1051. fDisplayFlags = TRUE;
  1052. }
  1053. if (fDisplayNumeric)
  1054. {
  1055. wprintf(L" 0x%x", longValue);
  1056. if (0 > longValue || 9 < longValue)
  1057. {
  1058. wprintf(L" (%d)", longValue);
  1059. }
  1060. }
  1061. if (0 != cidMsg)
  1062. {
  1063. WCHAR const *pwszComma = myLoadResourceString(IDS_SEPARATOR); // ", "
  1064. wprintf(L" -- ");
  1065. for (i = 0; i < cidMsg; i++)
  1066. {
  1067. wprintf(
  1068. L"%ws%ws",
  1069. 0 == i? L"" : pwszComma,
  1070. myLoadResourceString(aidMsg[i]));
  1071. }
  1072. }
  1073. if (0 == LSTRCMPIS(pwszColumnName, wszPROPEXTFLAGS))
  1074. {
  1075. wprintf(L" -- %ws", cuwszFromExtFlags(longValue));
  1076. }
  1077. else if (0 == LSTRCMPIS(pwszColumnName, wszPROPCERTIFICATEISSUERNAMEID) ||
  1078. 0 == LSTRCMPIS(pwszColumnName, wszPROPCRLNAMEID))
  1079. {
  1080. cuPrintPossibleObjectIdName(TEXT(szOID_CERTSRV_CA_VERSION));
  1081. wprintf(
  1082. L" %u.%u",
  1083. CANAMEIDTOICERT(longValue),
  1084. CANAMEIDTOIKEY(longValue));
  1085. }
  1086. wprintf(wszNewLine);
  1087. if (fDisplayFlags)
  1088. {
  1089. cuRegPrintDwordValue(FALSE, pwszColumnName, pwszColumnName, longValue);
  1090. }
  1091. if (NULL != pwszError)
  1092. {
  1093. LocalFree(const_cast<WCHAR *>(pwszError));
  1094. }
  1095. }
  1096. HRESULT
  1097. GetBinaryColumnFormat(
  1098. IN WCHAR const *pwszColumnName,
  1099. OUT LONG *pFormat)
  1100. {
  1101. LONG Format = CV_OUT_BINARY;
  1102. if (0 == LSTRCMPIS(
  1103. pwszColumnName,
  1104. wszPROPREQUESTDOT wszPROPREQUESTRAWREQUEST))
  1105. {
  1106. Format = CV_OUT_BASE64REQUESTHEADER;
  1107. }
  1108. else
  1109. if (0 == LSTRCMPIS(pwszColumnName, wszPROPRAWCERTIFICATE) ||
  1110. 0 == LSTRCMPIS(
  1111. pwszColumnName,
  1112. wszPROPREQUESTDOT wszPROPREQUESTRAWOLDCERTIFICATE) ||
  1113. 0 == LSTRCMPIS(pwszColumnName, wszPROPCERTIFICATERAWSMIMECAPABILITIES))
  1114. {
  1115. Format = CV_OUT_BASE64HEADER;
  1116. }
  1117. else
  1118. if (0 == LSTRCMPIS(pwszColumnName, wszPROPCRLRAWCRL))
  1119. {
  1120. Format = CV_OUT_BASE64X509CRLHEADER;
  1121. }
  1122. else
  1123. if (0 == LSTRCMPIS(pwszColumnName, wszPROPCERTIFICATERAWPUBLICKEY))
  1124. {
  1125. Format = CV_OUT_HEXADDR;
  1126. }
  1127. else
  1128. {
  1129. Format = CV_OUT_HEXASCIIADDR;
  1130. }
  1131. *pFormat = Format;
  1132. return(S_OK);
  1133. }
  1134. VOID
  1135. DumpBinaryValue(
  1136. IN WCHAR const *pwszColName,
  1137. OPTIONAL IN WCHAR const *pwszObjId,
  1138. IN LONG Format,
  1139. IN BYTE const *pb,
  1140. IN DWORD cb,
  1141. OPTIONAL IN WCHAR const *pwszStringValue)
  1142. {
  1143. wprintf(wszNewLine);
  1144. if (NULL == pwszObjId ||
  1145. 0 != LSTRCMPIS(pwszColName, wszPROPEXTRAWVALUE) ||
  1146. !cuDumpFormattedExtension(pwszObjId, pb, cb) ||
  1147. g_fVerbose)
  1148. {
  1149. if (NULL != pwszStringValue)
  1150. {
  1151. cuPrintCRLFString(NULL, pwszStringValue);
  1152. wprintf(wszNewLine);
  1153. }
  1154. else
  1155. {
  1156. DumpHex(
  1157. DH_NOADDRESS |
  1158. (CV_OUT_HEX == Format? DH_NOASCIIHEX : 0),
  1159. pb,
  1160. cb);
  1161. }
  1162. }
  1163. if (g_fVerbose &&
  1164. (CV_OUT_BASE64HEADER == Format ||
  1165. CV_OUT_BASE64REQUESTHEADER == Format ||
  1166. CV_OUT_BASE64X509CRLHEADER == Format))
  1167. {
  1168. BOOL fVerboseOld = g_fVerbose;
  1169. if (g_fVerbose)
  1170. {
  1171. g_fVerbose--;
  1172. }
  1173. cuDumpAsnBinary(pb, cb, MAXDWORD);
  1174. g_fVerbose = fVerboseOld;
  1175. wprintf(wszNewLine);
  1176. }
  1177. }
  1178. BOOL
  1179. ShouldDisplay(
  1180. IN WCHAR const *pwszName,
  1181. IN BOOL fDisplay,
  1182. IN WCHAR const * const *apwsz)
  1183. {
  1184. if (!fDisplay)
  1185. {
  1186. WCHAR const * const *ppwsz;
  1187. for (ppwsz = apwsz; NULL != *ppwsz; ppwsz++)
  1188. {
  1189. if (0 == mylstrcmpiL(pwszName, *ppwsz))
  1190. {
  1191. fDisplay = TRUE;
  1192. break;
  1193. }
  1194. }
  1195. }
  1196. return(fDisplay);
  1197. }
  1198. typedef struct _DBSTATS
  1199. {
  1200. DWORD cTotal;
  1201. DWORD cbTotal;
  1202. DWORD cbMax;
  1203. } DBSTATS;
  1204. VOID
  1205. UpdateStats(
  1206. IN OUT DBSTATS *pstats,
  1207. IN DWORD cbProp)
  1208. {
  1209. if (0 != cbProp)
  1210. {
  1211. pstats->cTotal++;
  1212. pstats->cbTotal += cbProp;
  1213. if (pstats->cbMax < cbProp)
  1214. {
  1215. pstats->cbMax = cbProp;
  1216. }
  1217. //wprintf(L"c=%u cb=%x(%x)\n", pstats->cTotal, pstats->cbTotal, cbProp);
  1218. }
  1219. }
  1220. VOID
  1221. CombineStats(
  1222. IN OUT DBSTATS *pstats,
  1223. IN DBSTATS const *pstats2)
  1224. {
  1225. pstats->cTotal += pstats2->cTotal;
  1226. pstats->cbTotal += pstats2->cbTotal;
  1227. if (pstats->cbMax < pstats2->cbMax)
  1228. {
  1229. pstats->cbMax = pstats2->cbMax;
  1230. }
  1231. }
  1232. VOID
  1233. DumpStats(
  1234. IN DBSTATS const *pstats,
  1235. IN DWORD idStats)
  1236. {
  1237. wprintf(
  1238. myLoadResourceString(IDS_VIEW_STATS), // "%u %ws, Total Size = %u, Max Size = %u, Ave Size = %u",
  1239. pstats->cTotal,
  1240. myLoadResourceString(idStats),
  1241. pstats->cbTotal,
  1242. pstats->cbMax,
  1243. 0 != pstats->cTotal? pstats->cbTotal / pstats->cTotal : 0);
  1244. wprintf(wszNewLine);
  1245. }
  1246. VOID
  1247. DumpViewStats(
  1248. IN DWORD cRowTotal,
  1249. IN DBSTATS const *pstatsRowProperties,
  1250. IN DBSTATS const *pstatsAttributes,
  1251. IN DBSTATS const *pstatsExtensions)
  1252. {
  1253. if (!g_fCryptSilent)
  1254. {
  1255. DBSTATS statsSum;
  1256. wprintf(wszNewLine);
  1257. wprintf(
  1258. myLoadResourceString(IDS_VIEW_ROWS), // "%u Rows"
  1259. cRowTotal);
  1260. wprintf(wszNewLine);
  1261. DumpStats(pstatsRowProperties, IDS_VIEW_ROWPROPERTIES); // "Row Properties"
  1262. DumpStats(pstatsAttributes, IDS_VIEW_ATTRIBUTES); // "Request Attributes"
  1263. DumpStats(pstatsExtensions, IDS_VIEW_EXTENSIONS); // "Certificate Extensions"
  1264. statsSum = *pstatsRowProperties;
  1265. CombineStats(&statsSum, pstatsAttributes);
  1266. CombineStats(&statsSum, pstatsExtensions);
  1267. DumpStats(&statsSum, IDS_VIEW_TOTALFIELDS); // "Total Fields"
  1268. }
  1269. }
  1270. #define VDQ_NONE 0
  1271. #define VDQ_SCHEMA 1
  1272. #define VDQ_QUEUE 2
  1273. #define VDQ_LOG 3
  1274. #define VDQ_LOGFAIL 4
  1275. #define VDQ_REVOKED 5
  1276. HRESULT
  1277. verbViewDump(
  1278. IN WCHAR const *pwszOption,
  1279. IN WCHAR const *pwszTable,
  1280. IN WCHAR const *pwszSkipCounts,
  1281. IN WCHAR const *pwszField3,
  1282. IN WCHAR const *pwszField4)
  1283. {
  1284. HRESULT hr;
  1285. BOOL fSchema = g_wszSchema == pwszOption;
  1286. DWORD vdq = VDQ_NONE;
  1287. LONG cvColDefault = 0;
  1288. DISPATCHINTERFACE diView;
  1289. DISPATCHINTERFACE diViewColumn;
  1290. DISPATCHINTERFACE diViewRow;
  1291. DISPATCHINTERFACE diViewAttribute;
  1292. DISPATCHINTERFACE diViewExtension;
  1293. BOOL fMustRelease = FALSE;
  1294. BOOL fMustReleaseColumn = FALSE;
  1295. BOOL fMustReleaseAttribute = FALSE;
  1296. BOOL fMustReleaseExtension = FALSE;
  1297. BOOL fMustReleaseRow = FALSE;
  1298. LONG i;
  1299. LONG cColFull;
  1300. LONG cColOut;
  1301. COLINFO *aColInfo = NULL;
  1302. LONG iRow;
  1303. LONG RowIndex;
  1304. LONG iCol;
  1305. LONG ColIndex;
  1306. LONG iAttribute;
  1307. LONG AttributeIndex;
  1308. LONG iExtension;
  1309. LONG ExtensionIndex;
  1310. BSTR strName = NULL;
  1311. BSTR strObjId = NULL;
  1312. BSTR strValue = NULL;
  1313. BSTR strValueBinary = NULL;
  1314. WCHAR const *pwszExtensionFormat;
  1315. WCHAR **apwszRestrictions = NULL;
  1316. WCHAR **apwszColumns = NULL;
  1317. WCHAR **apwszAttributes = NULL;
  1318. WCHAR **apwszExtensions = NULL;
  1319. WCHAR **ppwsz;
  1320. BOOL fOneRow = FALSE;
  1321. LONG lSkip = 0;
  1322. BOOL fAllColumns;
  1323. BOOL fAllAttributes = FALSE;
  1324. BOOL fAllExtensions = FALSE;
  1325. BOOL fSkip;
  1326. DWORD cbProp;
  1327. DWORD cRowTotal = 0;
  1328. DBSTATS statsRowProperties;
  1329. DBSTATS statsAttributes;
  1330. DBSTATS statsExtensions;
  1331. DWORD cvrcTable = CVRC_TABLE_REQCERT;
  1332. WCHAR const *pwszDefaultRestriction = NULL;
  1333. if (NULL != pwszTable)
  1334. {
  1335. if (0 == mylstrcmpiS(pwszTable, g_wszSchema))
  1336. {
  1337. fSchema = TRUE;
  1338. }
  1339. else
  1340. if (0 == LSTRCMPIS(pwszTable, wszQUEUE))
  1341. {
  1342. vdq = VDQ_QUEUE;
  1343. pwszDefaultRestriction = wszCOLONQUEUE;
  1344. cvColDefault = CV_COLUMN_QUEUE_DEFAULT;
  1345. }
  1346. else
  1347. if (0 == LSTRCMPIS(pwszTable, wszLOG))
  1348. {
  1349. vdq = VDQ_LOG;
  1350. pwszDefaultRestriction = wszCOLONLOG;
  1351. cvColDefault = CV_COLUMN_LOG_DEFAULT;
  1352. }
  1353. else
  1354. if (0 == LSTRCMPIS(pwszTable, wszLOGFAIL))
  1355. {
  1356. vdq = VDQ_LOGFAIL;
  1357. pwszDefaultRestriction = wszCOLONLOGFAIL;
  1358. cvColDefault = CV_COLUMN_LOG_DEFAULT;
  1359. }
  1360. else
  1361. if (0 == LSTRCMPIS(pwszTable, wszREVOKED))
  1362. {
  1363. vdq = VDQ_REVOKED;
  1364. pwszDefaultRestriction = wszCOLONREVOKED;
  1365. cvColDefault = CV_COLUMN_LOG_REVOKED_DEFAULT;
  1366. }
  1367. else
  1368. if (0 == LSTRCMPIS(pwszTable, g_wszExt))
  1369. {
  1370. cvrcTable = CVRC_TABLE_EXTENSIONS;
  1371. //cvColDefault = CV_COLUMN_EXTENSION_DEFAULT;
  1372. }
  1373. else
  1374. if (0 == LSTRCMPIS(pwszTable, g_wszAttrib))
  1375. {
  1376. cvrcTable = CVRC_TABLE_ATTRIBUTES;
  1377. //cvColDefault = CV_COLUMN_ATTRIBUTE_DEFAULT;
  1378. }
  1379. else
  1380. if (0 == LSTRCMPIS(pwszTable, g_wszCRL))
  1381. {
  1382. cvrcTable = CVRC_TABLE_CRL;
  1383. //cvColDefault = CV_COLUMN_CRL_DEFAULT;
  1384. }
  1385. else if (NULL == pwszSkipCounts && iswdigit(*pwszTable))
  1386. {
  1387. pwszSkipCounts = pwszTable;
  1388. }
  1389. else
  1390. {
  1391. hr = E_INVALIDARG;
  1392. _JumpError(hr, error, "bad view/table name");
  1393. }
  1394. }
  1395. if (NULL != pwszSkipCounts)
  1396. {
  1397. hr = ParseSkipCounts(pwszSkipCounts);
  1398. _JumpIfError(hr, error, "ParseSkipCounts");
  1399. }
  1400. hr = View_Init(g_DispatchFlags, &diView);
  1401. _JumpIfError(hr, error, "View_Init");
  1402. fMustRelease = TRUE;
  1403. hr = View_OpenConnection(&diView, g_pwszConfig);
  1404. _JumpIfError(hr, error, "View_OpenConnection");
  1405. if (CVRC_TABLE_REQCERT != cvrcTable)
  1406. {
  1407. hr = View2_SetTable(&diView, cvrcTable);
  1408. _JumpIfError(hr, error, "View2_SetTable");
  1409. }
  1410. if (NULL != g_pwszRestrict)
  1411. {
  1412. hr = ParseViewRestrictions(g_pwszRestrict, &apwszRestrictions);
  1413. _JumpIfError(hr, error, "ParseViewRestrictions");
  1414. if (NULL == apwszRestrictions)
  1415. {
  1416. hr = E_POINTER; // would have AV'd anyway
  1417. _JumpError(hr, error, "apwszRestrictions==NULL");
  1418. }
  1419. for (ppwsz = apwszRestrictions; NULL != *ppwsz; ppwsz++)
  1420. {
  1421. BOOL f;
  1422. LONG l;
  1423. hr = SetViewRestriction(&diView, *ppwsz, &f, &l);
  1424. _JumpIfErrorStr(hr, error, "SetViewRestriction", *ppwsz);
  1425. if (f)
  1426. {
  1427. fOneRow = TRUE;
  1428. lSkip = l;
  1429. }
  1430. }
  1431. }
  1432. else
  1433. if (NULL != pwszDefaultRestriction)
  1434. {
  1435. hr = SetViewRestriction(&diView, pwszDefaultRestriction, &fOneRow, &lSkip);
  1436. _JumpIfError(hr, error, "SetViewRestriction");
  1437. }
  1438. // If not a special default view, and no output columns were specified
  1439. // for the requests+certs table, include all attributes and extensions.
  1440. if (NULL == pwszDefaultRestriction &&
  1441. NULL == g_pwszOut &&
  1442. CVRC_TABLE_REQCERT == cvrcTable)
  1443. {
  1444. fAllAttributes = TRUE;
  1445. fAllExtensions = TRUE;
  1446. }
  1447. hr = View_GetColumnCount(&diView, CVRC_COLUMN_SCHEMA, &cColFull);
  1448. _JumpIfError(hr, error, "View_GetColumnCount");
  1449. if (NULL != g_pwszOut)
  1450. {
  1451. hr = ParseViewColumns(
  1452. g_pwszOut,
  1453. NULL,
  1454. NULL,
  1455. &apwszColumns,
  1456. &fAllColumns);
  1457. _JumpIfError(hr, error, "ParseViewColumns");
  1458. hr = ParseViewColumns(
  1459. g_pwszOut,
  1460. g_wszAttrib,
  1461. g_apwszAllowedPrefixes,
  1462. &apwszAttributes,
  1463. &fAllAttributes);
  1464. _JumpIfError(hr, error, "ParseViewColumns");
  1465. hr = ParseViewColumns(
  1466. g_pwszOut,
  1467. g_wszExt,
  1468. NULL,
  1469. &apwszExtensions,
  1470. &fAllExtensions);
  1471. _JumpIfError(hr, error, "ParseViewColumns");
  1472. if (NULL == apwszColumns)
  1473. {
  1474. if (!g_fReverse)
  1475. {
  1476. hr = View_SetResultColumnCount(&diView, 0);
  1477. _JumpIfError(hr, error, "View_SetResultColumnCount");
  1478. }
  1479. }
  1480. else
  1481. {
  1482. for (ppwsz = apwszColumns; NULL != *ppwsz; ppwsz++)
  1483. ;
  1484. hr = View_SetResultColumnCount(
  1485. &diView,
  1486. SAFE_SUBTRACT_POINTERS(ppwsz, apwszColumns));
  1487. _JumpIfError(hr, error, "View_SetResultColumnCount");
  1488. for (ppwsz = apwszColumns; NULL != *ppwsz; ppwsz++)
  1489. {
  1490. hr = View_GetColumnIndex(
  1491. &diView,
  1492. CVRC_COLUMN_SCHEMA,
  1493. *ppwsz,
  1494. &ColIndex);
  1495. _JumpIfErrorStr(hr, error, "View_GetColumnIndex", *ppwsz);
  1496. hr = View_SetResultColumn(&diView, ColIndex);
  1497. _JumpIfError(hr, error, "View_SetResultColumn");
  1498. }
  1499. }
  1500. }
  1501. else if (NULL == pwszDefaultRestriction)
  1502. {
  1503. if (g_fReverse)
  1504. {
  1505. hr = View_SetResultColumnCount(&diView, cColFull + 1);
  1506. _JumpIfError(hr, error, "View_SetResultColumnCount");
  1507. hr = View_SetResultColumn(&diView, 0);
  1508. _JumpIfError(hr, error, "View_SetResultColumn(0)");
  1509. for (i = cColFull; i > 0; i--)
  1510. {
  1511. hr = View_SetResultColumn(&diView, i - 1);
  1512. _JumpIfError(hr, error, "View_SetResultColumn");
  1513. }
  1514. }
  1515. else
  1516. {
  1517. hr = View_SetResultColumnCount(&diView, cColFull);
  1518. _JumpIfError(hr, error, "View_SetResultColumnCount");
  1519. for (i = 0; i < cColFull; i++)
  1520. {
  1521. hr = View_SetResultColumn(&diView, i);
  1522. _JumpIfError(hr, error, "View_SetResultColumn");
  1523. }
  1524. }
  1525. }
  1526. else
  1527. {
  1528. // Use the default set of columns for the specified special view.
  1529. CSASSERT(0 > cvColDefault);
  1530. hr = View_SetResultColumnCount(&diView, cvColDefault);
  1531. _JumpIfError(hr, error, "View_SetResultColumnCount");
  1532. }
  1533. hr = View_OpenView(&diView, &diViewRow);
  1534. _JumpIfError(hr, error, "View_OpenView");
  1535. fMustReleaseRow = TRUE;
  1536. hr = View_GetColumnCount(&diView, CVRC_COLUMN_RESULT, &cColOut);
  1537. _JumpIfError(hr, error, "View_GetColumnCount");
  1538. aColInfo = (COLINFO *) LocalAlloc(
  1539. LMEM_FIXED | LMEM_ZEROINIT,
  1540. cColOut * sizeof(aColInfo[0]));
  1541. if (NULL == aColInfo)
  1542. {
  1543. hr = E_OUTOFMEMORY;
  1544. _JumpError(hr, error, "no memory for column info array");
  1545. }
  1546. if (fSchema)
  1547. {
  1548. hr = DisplaySchema(&diView, cColFull, NULL, FALSE);
  1549. _JumpIfError(hr, error, "DisplaySchema");
  1550. goto error;
  1551. }
  1552. if (0 != cColOut)
  1553. {
  1554. hr = DisplaySchema(&diView, cColOut, aColInfo, TRUE);
  1555. _JumpIfError(hr, error, "DisplaySchema");
  1556. }
  1557. ZeroMemory(&statsRowProperties, sizeof(statsRowProperties));
  1558. ZeroMemory(&statsAttributes, sizeof(statsAttributes));
  1559. ZeroMemory(&statsExtensions, sizeof(statsExtensions));
  1560. hr = ViewRow_Skip(&diViewRow, lSkip);
  1561. _JumpIfError(hr, error, "ViewRow_Skip");
  1562. for (iRow = 1; ; iRow++)
  1563. {
  1564. BOOL fRowPrinted;
  1565. BOOL fHeaderPrinted;
  1566. BOOL fExtraNewLine;
  1567. LONG cskip;
  1568. if (NULL != strObjId)
  1569. {
  1570. SysFreeString(strObjId);
  1571. strObjId = NULL;
  1572. }
  1573. cskip = GetSkip(TRUE);
  1574. switch (cskip)
  1575. {
  1576. case 0:
  1577. break;
  1578. case 101:
  1579. hr = ViewRow_Reset(&diViewRow);
  1580. _JumpIfError(hr, error, "ViewRow_Reset");
  1581. iRow = 1;
  1582. break;
  1583. case 102:
  1584. {
  1585. DISPATCHINTERFACE diViewRowClone;
  1586. hr = ViewRow_Clone(&diViewRow, &diViewRowClone);
  1587. _JumpIfError(hr, error, "ViewRow_Clone");
  1588. ViewRow_Release(&diViewRow);
  1589. diViewRow = diViewRowClone; // structure assignment
  1590. goto done;
  1591. }
  1592. case 103:
  1593. goto done;
  1594. default:
  1595. hr = ViewRow_Skip(&diViewRow, cskip);
  1596. _JumpIfError(hr, error, "ViewRow_Skip");
  1597. iRow += cskip;
  1598. }
  1599. hr = ViewRow_Next(&diViewRow, &RowIndex);
  1600. if (S_FALSE == hr || (S_OK == hr && -1 == RowIndex))
  1601. {
  1602. LONG MaxIndex;
  1603. hr = ViewRow_GetMaxIndex(&diViewRow, &MaxIndex);
  1604. _JumpIfError(hr, error, "ViewRow_GetMaxIndex");
  1605. if (!g_fCryptSilent)
  1606. {
  1607. wprintf(
  1608. L"\n%ws: %u\n",
  1609. myLoadResourceString(IDS_MAXINDEX), // "Maximum Row Index"
  1610. MaxIndex);
  1611. }
  1612. if (101 == GetSkip(FALSE))
  1613. {
  1614. continue;
  1615. }
  1616. break;
  1617. }
  1618. _JumpIfError(hr, error, "ViewRow_Next");
  1619. CSASSERT(RowIndex == iRow + lSkip);
  1620. cRowTotal++;
  1621. fRowPrinted = FALSE;
  1622. fExtraNewLine = FALSE;
  1623. if (fMustReleaseColumn)
  1624. {
  1625. ViewColumn_Release(&diViewColumn);
  1626. fMustReleaseColumn = FALSE;
  1627. }
  1628. hr = ViewRow_EnumCertViewColumn(&diViewRow, &diViewColumn);
  1629. _JumpIfError(hr, error, "ViewRow_EnumCertViewColumn");
  1630. fMustReleaseColumn = TRUE;
  1631. for (iCol = 0; ; iCol++)
  1632. {
  1633. LONG Format;
  1634. LONG longValue;
  1635. DATE dateValue;
  1636. VOID *pretval;
  1637. if (NULL != strValue)
  1638. {
  1639. SysFreeString(strValue);
  1640. strValue = NULL;
  1641. }
  1642. if (NULL != strValueBinary)
  1643. {
  1644. SysFreeString(strValueBinary);
  1645. strValueBinary = NULL;
  1646. }
  1647. hr = ViewColumn_Next(&diViewColumn, &ColIndex);
  1648. if (S_FALSE == hr || (S_OK == hr && -1 == ColIndex))
  1649. {
  1650. break;
  1651. }
  1652. _JumpIfError(hr, error, "ViewColumn_Next");
  1653. CSASSERT(ColIndex == iCol);
  1654. hr = ViewColumn_GetType(&diViewColumn, &i);
  1655. _JumpIfError(hr, error, "GetType");
  1656. CSASSERT(i == aColInfo[iCol].type);
  1657. PrintRowIndex(iRow, &fRowPrinted);
  1658. fExtraNewLine = TRUE;
  1659. wprintf(L" %ws:", aColInfo[iCol].strColDisplay);
  1660. Format = CV_OUT_BINARY;
  1661. switch (aColInfo[iCol].type)
  1662. {
  1663. case PROPTYPE_LONG:
  1664. pretval = &longValue;
  1665. break;
  1666. case PROPTYPE_DATE:
  1667. pretval = &dateValue;
  1668. break;
  1669. case PROPTYPE_STRING:
  1670. pretval = &strValue;
  1671. break;
  1672. case PROPTYPE_BINARY:
  1673. pretval = &strValue;
  1674. hr = GetBinaryColumnFormat(aColInfo[iCol].strCol, &Format);
  1675. _JumpIfError(hr, error, "GetBinaryColumnFormat");
  1676. break;
  1677. default:
  1678. hr = E_FAIL;
  1679. _JumpError(hr, error, "bad proptype");
  1680. }
  1681. hr = ViewColumn_GetValue(
  1682. &diViewColumn,
  1683. Format,
  1684. aColInfo[iCol].type,
  1685. pretval);
  1686. if (S_OK != hr)
  1687. {
  1688. wprintf(L" ");
  1689. wprintf(myLoadResourceString(IDS_PROP_EMPTY)); // "EMPTY"
  1690. wprintf(wszNewLine);
  1691. _PrintIfErrorStr2(
  1692. hr,
  1693. "ViewColumn_GetValue",
  1694. aColInfo[iCol].strColDisplay,
  1695. CERTSRV_E_PROPERTY_EMPTY);
  1696. }
  1697. else
  1698. {
  1699. cbProp = 0;
  1700. switch (aColInfo[iCol].type)
  1701. {
  1702. case PROPTYPE_LONG:
  1703. DumpLongValue(longValue, aColInfo[iCol].strCol);
  1704. cbProp = sizeof(LONG);
  1705. break;
  1706. case PROPTYPE_DATE:
  1707. cuDumpDate(&dateValue);
  1708. cbProp = sizeof(DATE);
  1709. break;
  1710. case PROPTYPE_BINARY:
  1711. if (CV_OUT_BINARY != Format)
  1712. {
  1713. hr = ViewColumn_GetValue(
  1714. &diViewColumn,
  1715. CV_OUT_BINARY,
  1716. PROPTYPE_BINARY,
  1717. &strValueBinary);
  1718. _JumpIfError(hr, error, "ViewColumn_GetValue");
  1719. }
  1720. else
  1721. {
  1722. strValueBinary = strValue;
  1723. strValue = NULL;
  1724. }
  1725. cbProp = SysStringByteLen(strValueBinary);
  1726. DumpBinaryValue(
  1727. aColInfo[iCol].strCol,
  1728. strObjId,
  1729. Format,
  1730. (BYTE *) strValueBinary,
  1731. cbProp,
  1732. strValue);
  1733. break;
  1734. case PROPTYPE_STRING:
  1735. wprintf(L" \"");
  1736. cuPrintCRLFString(NULL, strValue);
  1737. wprintf(L"\"");
  1738. cuPrintPossibleObjectIdName(strValue);
  1739. wprintf(wszNewLine);
  1740. if (g_fVerbose)
  1741. {
  1742. DumpHex(
  1743. 0,
  1744. (BYTE *) strValue,
  1745. SysStringByteLen(strValue));
  1746. wprintf(wszNewLine);
  1747. }
  1748. cbProp = wcslen(strValue) * sizeof(WCHAR);
  1749. if (0 == LSTRCMPIS(
  1750. aColInfo[iCol].strCol,
  1751. wszPROPEXTNAME))
  1752. {
  1753. if (NULL != strObjId)
  1754. {
  1755. SysFreeString(strObjId);
  1756. }
  1757. strObjId = SysAllocString(strValue);
  1758. }
  1759. break;
  1760. }
  1761. UpdateStats(&statsRowProperties, cbProp);
  1762. }
  1763. }
  1764. fSkip = TRUE;
  1765. if (fAllAttributes || NULL != apwszAttributes)
  1766. {
  1767. // Enumerate Request Attributes
  1768. hr = ViewRow_EnumCertViewAttribute(&diViewRow, 0, &diViewAttribute);
  1769. if (CERTSRV_E_PROPERTY_EMPTY == hr)
  1770. {
  1771. _PrintError2(hr, "ViewRow_EnumCertViewAttribute", hr);
  1772. }
  1773. else
  1774. {
  1775. _JumpIfError(hr, error, "ViewRow_EnumCertViewAttribute");
  1776. fSkip = FALSE;
  1777. fMustReleaseAttribute = TRUE;
  1778. }
  1779. }
  1780. if (!fSkip)
  1781. {
  1782. fHeaderPrinted = FALSE;
  1783. for (iAttribute = 0; ; iAttribute++)
  1784. {
  1785. hr = ViewAttribute_Next(&diViewAttribute, &AttributeIndex);
  1786. if (S_FALSE == hr || (S_OK == hr && -1 == AttributeIndex))
  1787. {
  1788. break;
  1789. }
  1790. _JumpIfError(hr, error, "ViewAttribute_Next");
  1791. CSASSERT(AttributeIndex == iAttribute);
  1792. hr = ViewAttribute_GetName(&diViewAttribute, &strName);
  1793. _JumpIfError(hr, error, "GetName");
  1794. if (ShouldDisplay(strName, fAllAttributes, apwszAttributes))
  1795. {
  1796. if (!fHeaderPrinted)
  1797. {
  1798. PrintRowIndex(iRow, &fRowPrinted);
  1799. if (fExtraNewLine)
  1800. {
  1801. wprintf(wszNewLine);
  1802. }
  1803. wprintf(
  1804. L" %ws\n",
  1805. myLoadResourceString(IDS_REQUEST_ATTRIBUTES)); // "Request Attributes:"
  1806. fHeaderPrinted = TRUE;
  1807. fExtraNewLine = TRUE;
  1808. }
  1809. if (NULL != strValue)
  1810. {
  1811. SysFreeString(strValue);
  1812. strValue = NULL;
  1813. }
  1814. hr = ViewAttribute_GetValue(&diViewAttribute, &strValue);
  1815. _JumpIfError(hr, error, "GetValue");
  1816. wprintf(L" %ws: \"%ws\"\n", strName, strValue);
  1817. UpdateStats(
  1818. &statsAttributes,
  1819. (wcslen(strName) + wcslen(strValue)) *
  1820. sizeof(WCHAR) +
  1821. sizeof(LONG)); // for RequestId
  1822. }
  1823. }
  1824. ViewAttribute_Release(&diViewAttribute);
  1825. fMustReleaseAttribute = FALSE;
  1826. }
  1827. fSkip = TRUE;
  1828. if (fAllExtensions || NULL != apwszExtensions)
  1829. {
  1830. // Enumerate Certificate Extensions
  1831. hr = ViewRow_EnumCertViewExtension(&diViewRow, 0, &diViewExtension);
  1832. if (CERTSRV_E_PROPERTY_EMPTY == hr)
  1833. {
  1834. _PrintError2(hr, "ViewRow_EnumCertViewExtension", hr);
  1835. }
  1836. else
  1837. {
  1838. _JumpIfError(hr, error, "ViewRow_EnumCertViewExtension");
  1839. fSkip = FALSE;
  1840. fMustReleaseExtension = TRUE;
  1841. }
  1842. }
  1843. if (!fSkip)
  1844. {
  1845. fHeaderPrinted = FALSE;
  1846. pwszExtensionFormat = myLoadResourceString(IDS_FORMAT_EXTENSION); // "%ws: Flags = %x%ws, Length = %x"
  1847. for (iExtension = 0; ; iExtension++)
  1848. {
  1849. LONG ExtFlags;
  1850. hr = ViewExtension_Next(&diViewExtension, &ExtensionIndex);
  1851. if (S_FALSE == hr || (S_OK == hr && -1 == ExtensionIndex))
  1852. {
  1853. break;
  1854. }
  1855. _JumpIfError(hr, error, "ViewExtension_Next");
  1856. CSASSERT(ExtensionIndex == iExtension);
  1857. hr = ViewExtension_GetName(&diViewExtension, &strName);
  1858. _JumpIfError(hr, error, "GetName");
  1859. if (ShouldDisplay(strName, fAllExtensions, apwszExtensions))
  1860. {
  1861. DWORD cbValue;
  1862. if (!fHeaderPrinted)
  1863. {
  1864. PrintRowIndex(iRow, &fRowPrinted);
  1865. if (fExtraNewLine)
  1866. {
  1867. wprintf(wszNewLine);
  1868. }
  1869. wprintf(
  1870. L" %ws\n",
  1871. myLoadResourceString(IDS_CERTIFICATE_EXTENSIONS)); // "Certificate Extensions:"
  1872. fHeaderPrinted = TRUE;
  1873. }
  1874. hr = ViewExtension_GetFlags(&diViewExtension, &ExtFlags);
  1875. _JumpIfError(hr, error, "GetFlags");
  1876. if (NULL != strValue)
  1877. {
  1878. SysFreeString(strValue);
  1879. strValue = NULL;
  1880. }
  1881. hr = ViewExtension_GetValue(
  1882. &diViewExtension,
  1883. PROPTYPE_BINARY,
  1884. CV_OUT_BINARY,
  1885. &strValue);
  1886. if (CERTSRV_E_PROPERTY_EMPTY != hr)
  1887. {
  1888. _JumpIfError(hr, error, "GetValue");
  1889. }
  1890. cbValue = NULL == strValue? 0 : SysStringByteLen(strValue);
  1891. wprintf(g_wszPad4);
  1892. wprintf(
  1893. pwszExtensionFormat,
  1894. strName,
  1895. ExtFlags,
  1896. cuwszFromExtFlags(ExtFlags),
  1897. cbValue);
  1898. wprintf(wszNewLine);
  1899. if (0 == cbValue)
  1900. {
  1901. wprintf(g_wszPad4);
  1902. wprintf(myLoadResourceString(IDS_PROP_EMPTY)); // "EMPTY"
  1903. wprintf(wszNewLine);
  1904. }
  1905. else
  1906. {
  1907. if (!cuDumpFormattedExtension(
  1908. strName,
  1909. (BYTE const *) strValue,
  1910. SysStringByteLen(strValue)) ||
  1911. g_fVerbose)
  1912. {
  1913. wprintf(wszNewLine);
  1914. DumpHex(
  1915. DH_NOTABPREFIX | 4,
  1916. (BYTE const *) strValue,
  1917. SysStringByteLen(strValue));
  1918. }
  1919. }
  1920. wprintf(wszNewLine);
  1921. UpdateStats(
  1922. &statsExtensions,
  1923. wcslen(strName) * sizeof(WCHAR) +
  1924. cbValue + // for ext
  1925. sizeof(LONG) + // for RequestId
  1926. sizeof(ExtFlags)); // for ExtensionFlags
  1927. }
  1928. }
  1929. ViewExtension_Release(&diViewExtension);
  1930. fMustReleaseExtension = FALSE;
  1931. }
  1932. if (fOneRow)
  1933. {
  1934. break;
  1935. }
  1936. }
  1937. done:
  1938. DumpViewStats(
  1939. cRowTotal,
  1940. &statsRowProperties,
  1941. &statsAttributes,
  1942. &statsExtensions);
  1943. hr = S_OK;
  1944. error:
  1945. if (NULL != aColInfo)
  1946. {
  1947. for (i = 0; i < cColOut; i++)
  1948. {
  1949. if (NULL != aColInfo[i].strCol)
  1950. {
  1951. SysFreeString(aColInfo[i].strCol);
  1952. }
  1953. if (NULL != aColInfo[i].strColDisplay)
  1954. {
  1955. SysFreeString(aColInfo[i].strColDisplay);
  1956. }
  1957. }
  1958. LocalFree(aColInfo);
  1959. }
  1960. cuFreeStringArray(apwszRestrictions);
  1961. cuFreeStringArray(apwszColumns);
  1962. cuFreeStringArray(apwszAttributes);
  1963. cuFreeStringArray(apwszExtensions);
  1964. if (NULL != strObjId)
  1965. {
  1966. SysFreeString(strObjId);
  1967. }
  1968. if (NULL != strName)
  1969. {
  1970. SysFreeString(strName);
  1971. }
  1972. if (NULL != strValue)
  1973. {
  1974. SysFreeString(strValue);
  1975. }
  1976. if (NULL != strValueBinary)
  1977. {
  1978. SysFreeString(strValueBinary);
  1979. }
  1980. if (fMustReleaseAttribute)
  1981. {
  1982. ViewAttribute_Release(&diViewAttribute);
  1983. }
  1984. if (fMustReleaseExtension)
  1985. {
  1986. ViewExtension_Release(&diViewExtension);
  1987. }
  1988. if (fMustReleaseColumn)
  1989. {
  1990. ViewColumn_Release(&diViewColumn);
  1991. }
  1992. if (fMustReleaseRow)
  1993. {
  1994. ViewRow_Release(&diViewRow);
  1995. }
  1996. if (fMustRelease)
  1997. {
  1998. View_Release(&diView);
  1999. }
  2000. return(hr);
  2001. }
  2002. HRESULT
  2003. DBShutDown(
  2004. IN ICertDB *pdb)
  2005. {
  2006. HRESULT hr;
  2007. CSASSERT(NULL != pdb);
  2008. hr = pdb->ShutDown(0);
  2009. pdb->Release();
  2010. return(hr);
  2011. }
  2012. // Control-C handler to shut down DB
  2013. BOOL
  2014. cuDBAbortShutDown(
  2015. IN DWORD dwCtrlType)
  2016. {
  2017. HRESULT hr;
  2018. ICertDB *pdb;
  2019. EnterCriticalSection(&g_DBCriticalSection);
  2020. pdb = g_pdb;
  2021. g_pdb = NULL;
  2022. if (NULL != pdb)
  2023. {
  2024. DBShutDown(pdb);
  2025. SetConsoleCtrlHandler(cuDBAbortShutDown, FALSE);
  2026. }
  2027. LeaveCriticalSection(&g_DBCriticalSection);
  2028. return(TRUE);
  2029. }
  2030. HRESULT
  2031. DBOpen(
  2032. IN WCHAR const *pwszAuthority,
  2033. IN BOOL fReadOnly,
  2034. OUT ICertDB **ppdb)
  2035. {
  2036. HRESULT hr = S_OK;
  2037. DWORD cb;
  2038. DWORD i;
  2039. HKEY hkey = NULL;
  2040. WCHAR awszDatabase[MAX_PATH];
  2041. WCHAR awszLogDir[MAX_PATH];
  2042. WCHAR awszSystemDir[MAX_PATH];
  2043. WCHAR awszTempDir[MAX_PATH];
  2044. DWORD DBFlags;
  2045. WCHAR *pawszDirBuf[4] =
  2046. {
  2047. awszDatabase,
  2048. awszLogDir,
  2049. awszSystemDir,
  2050. awszTempDir
  2051. };
  2052. WCHAR *pawszRegNames[4] =
  2053. {
  2054. wszREGDBDIRECTORY,
  2055. wszREGDBLOGDIRECTORY,
  2056. wszREGDBSYSDIRECTORY,
  2057. wszREGDBTEMPDIRECTORY
  2058. };
  2059. // get info from registry
  2060. hr = RegOpenKey(HKEY_LOCAL_MACHINE, wszREGKEYCONFIGPATH, &hkey);
  2061. _JumpIfError(hr, error, "RegOpenKey(CAName)");
  2062. for (i = 0; i < 4; i++)
  2063. {
  2064. cb = sizeof(WCHAR) * MAX_PATH;
  2065. hr = RegQueryValueEx(
  2066. hkey,
  2067. pawszRegNames[i],
  2068. NULL,
  2069. NULL,
  2070. (BYTE *) pawszDirBuf[i],
  2071. &cb);
  2072. _JumpIfError(hr, error, "RegQueryValueEx(DB*Dir)");
  2073. }
  2074. if (wcslen(awszDatabase) +
  2075. 1 +
  2076. wcslen(pwszAuthority) +
  2077. wcslen(wszDBFILENAMEEXT) >= ARRAYSIZE(awszDatabase))
  2078. {
  2079. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  2080. _JumpErrorStr(hr, error, "awszDatabase", pwszAuthority);
  2081. }
  2082. wcscat(awszDatabase, L"\\");
  2083. wcscat(awszDatabase, pwszAuthority);
  2084. wcscat(awszDatabase, wszDBFILENAMEEXT);
  2085. cb = sizeof(DBFlags);
  2086. hr = RegQueryValueEx(
  2087. hkey,
  2088. wszREGDBFLAGS,
  2089. NULL,
  2090. NULL,
  2091. (BYTE *) &DBFlags,
  2092. &cb);
  2093. if (S_OK != hr)
  2094. {
  2095. _PrintErrorStr(hr, "RegQueryValueEx", wszREGDBFLAGS);
  2096. DBFlags = DBFLAGS_DEFAULT;
  2097. }
  2098. DBFlags &= ~DBFLAGS_READONLY;
  2099. wprintf(
  2100. myLoadResourceString(IDS_FORMAT_OPENING_DB), // "Opening Database %ws"
  2101. awszDatabase);
  2102. wprintf(wszNewLine);
  2103. hr = CoCreateInstance(
  2104. CLSID_CCertDB,
  2105. NULL, // pUnkOuter
  2106. CLSCTX_INPROC_SERVER,
  2107. IID_ICertDB,
  2108. (VOID **) ppdb);
  2109. _JumpIfError(hr, error, "CoCreateInstance(ICertDB)");
  2110. if (fReadOnly)
  2111. {
  2112. DBFlags |= DBFLAGS_READONLY;
  2113. }
  2114. else if (g_fForce)
  2115. {
  2116. DBFlags |= DBFLAGS_CREATEIFNEEDED;
  2117. }
  2118. hr = (*ppdb)->Open(
  2119. DBFlags,
  2120. 2, // cSession
  2121. L"certutil.exe", // pwszEventSource
  2122. awszDatabase, // pwszDBFile
  2123. awszLogDir, // pwszLogDir
  2124. awszSystemDir, // pwszSystemDir
  2125. awszTempDir); // pwszTempDir
  2126. _JumpIfError(hr, error, "ICertDB::Open");
  2127. error:
  2128. if (S_OK != hr)
  2129. {
  2130. if (NULL != *ppdb)
  2131. {
  2132. (*ppdb)->Release();
  2133. *ppdb = NULL;
  2134. }
  2135. }
  2136. if (NULL != hkey)
  2137. {
  2138. RegCloseKey(hkey);
  2139. }
  2140. return(hr);
  2141. }
  2142. HRESULT
  2143. cuDBOpen(
  2144. IN WCHAR const *pwszAuthority,
  2145. IN BOOL fReadOnly,
  2146. OUT ICertDB **ppdb)
  2147. {
  2148. HRESULT hr;
  2149. WCHAR *pwszSanitizedCA = NULL;
  2150. hr = mySanitizeName(pwszAuthority, &pwszSanitizedCA);
  2151. _JumpIfError(hr, error, "mySanitizeName");
  2152. SetConsoleCtrlHandler(NULL, TRUE); // ignore CTL-C during cuDBOpen
  2153. hr = DBOpen(pwszSanitizedCA, fReadOnly, ppdb);
  2154. if (S_OK != hr)
  2155. {
  2156. cuPrintError(IDS_DB_OPEN_FAILURE, hr);
  2157. if (myJetHResult(JET_errFileAccessDenied) == hr)
  2158. {
  2159. wprintf(myLoadResourceString(IDS_DB_ACCESS_STOP_SERVER));
  2160. wprintf(wszNewLine);
  2161. }
  2162. else
  2163. {
  2164. wprintf(myLoadResourceString(IDS_DB_ACCESS_INSTALL_SERVER)); // "Ensure the server is correctly installed and retry."
  2165. wprintf(wszNewLine);
  2166. }
  2167. _JumpError(hr, error, "DBOpen");
  2168. }
  2169. g_pdb = *ppdb;
  2170. SetConsoleCtrlHandler(cuDBAbortShutDown, TRUE);
  2171. SetConsoleCtrlHandler(NULL, FALSE); // allow CTL-C
  2172. error:
  2173. if (NULL != pwszSanitizedCA)
  2174. {
  2175. LocalFree(pwszSanitizedCA);
  2176. }
  2177. return(hr);
  2178. }
  2179. CERTDBCOLUMN g_adcRequests[50];
  2180. DWORD g_cdcRequests;
  2181. CERTDBCOLUMN g_adcCertificates[50];
  2182. DWORD g_cdcCertificates;
  2183. HRESULT
  2184. DBLoadSchema(
  2185. IN ICertDB *pdb)
  2186. {
  2187. HRESULT hr;
  2188. IEnumCERTDBCOLUMN *penum = NULL;
  2189. CERTDBCOLUMN acol[2];
  2190. DWORD ccol;
  2191. DWORD i;
  2192. CERTDBCOLUMN *pdc;
  2193. CERTDBCOLUMN const *pdcEnd;
  2194. CERTDBCOLUMN *pdcReq = g_adcRequests;
  2195. CERTDBCOLUMN *pdcCert = g_adcCertificates;
  2196. DWORD *pcdc;
  2197. hr = pdb->EnumCertDBColumn(CVRC_TABLE_REQCERT, &penum);
  2198. _JumpIfError(hr, error, "EnumCertDBColumn");
  2199. while (TRUE)
  2200. {
  2201. hr = penum->Next(ARRAYSIZE(acol), acol, &ccol);
  2202. if (S_FALSE != hr)
  2203. {
  2204. _JumpIfError(hr, error, "Next");
  2205. }
  2206. for (i = 0; i < ccol; i++)
  2207. {
  2208. if (0 == _wcsnicmp(
  2209. wszPROPREQUESTDOT,
  2210. acol[i].pwszName,
  2211. WSZARRAYSIZE(wszPROPREQUESTDOT)))
  2212. {
  2213. pdc = pdcReq++;
  2214. pcdc = &g_cdcRequests;
  2215. pdcEnd = &g_adcRequests[ARRAYSIZE(g_adcRequests) - 1];
  2216. }
  2217. else
  2218. {
  2219. pdc = pdcCert++;
  2220. pcdc = &g_cdcCertificates;
  2221. pdcEnd = &g_adcCertificates[ARRAYSIZE(g_adcCertificates) - 1];
  2222. }
  2223. if (pdc >= pdcEnd)
  2224. {
  2225. //wprintf(L"Property Name Table overflow\n");
  2226. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  2227. _JumpError(hr, error, "Property Name Table overflow");
  2228. }
  2229. *pdc = acol[i];
  2230. (*pcdc)++;
  2231. }
  2232. if (S_FALSE == hr)
  2233. {
  2234. break;
  2235. }
  2236. }
  2237. hr = S_OK;
  2238. error:
  2239. if (NULL != penum)
  2240. {
  2241. penum->Release();
  2242. }
  2243. return(hr);
  2244. }
  2245. HRESULT
  2246. DBLookupColumnInfo1(
  2247. IN CERTDBCOLUMN const *pdc,
  2248. IN DWORD ColIndex,
  2249. OUT CERTDBCOLUMN const **ppdc)
  2250. {
  2251. HRESULT hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  2252. *ppdc = NULL;
  2253. for ( ; NULL != pdc->pwszName; pdc++)
  2254. {
  2255. if (pdc->Index == ColIndex)
  2256. {
  2257. *ppdc = pdc;
  2258. hr = S_OK;
  2259. break;
  2260. }
  2261. }
  2262. //error:
  2263. return(hr);
  2264. }
  2265. HRESULT
  2266. DBLookupColumnInfo(
  2267. IN DWORD ColIndex,
  2268. OUT CERTDBCOLUMN const **ppdc,
  2269. OUT DWORD *pdwTable)
  2270. {
  2271. HRESULT hr;
  2272. hr = DBLookupColumnInfo1(
  2273. g_adcRequests,
  2274. ColIndex,
  2275. ppdc);
  2276. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  2277. {
  2278. _JumpIfError(hr, error, "DBLookupColumnInfo1");
  2279. *pdwTable = PROPTABLE_REQUEST;
  2280. }
  2281. else
  2282. {
  2283. hr = DBLookupColumnInfo1(
  2284. g_adcCertificates,
  2285. ColIndex,
  2286. ppdc);
  2287. *pdwTable = PROPTABLE_CERTIFICATE;
  2288. }
  2289. _JumpIfError(hr, error, "DBLookupColumnInfo1");
  2290. error:
  2291. return(hr);
  2292. }
  2293. HRESULT
  2294. DBDumpColumn(
  2295. IN CERTDBCOLUMN const *pdc)
  2296. {
  2297. HRESULT hr;
  2298. cuPrintSchemaEntry(
  2299. pdc->pwszName,
  2300. pdc->pwszDisplayName,
  2301. pdc->Type,
  2302. pdc->cbMax);
  2303. hr = S_OK;
  2304. //error:
  2305. return(hr);
  2306. }
  2307. HRESULT
  2308. DBDumpSchema1(
  2309. IN CERTDBCOLUMN const *pdc)
  2310. {
  2311. HRESULT hr;
  2312. CERTDBCOLUMN const *pdcEnd;
  2313. for ( ; NULL != pdc->pwszName; pdc++)
  2314. {
  2315. hr = DBDumpColumn(pdc);
  2316. _JumpIfError(hr, error, "DBDumpColumn");
  2317. }
  2318. hr = S_OK;
  2319. error:
  2320. return(hr);
  2321. }
  2322. HRESULT
  2323. DBDumpSchema(
  2324. IN ICertDB *pdb,
  2325. OPTIONAL IN DWORD const *pcol,
  2326. IN DWORD ccol)
  2327. {
  2328. HRESULT hr;
  2329. DWORD acol[100];
  2330. DWORD i;
  2331. if (1 == ccol && NULL != pcol && 0 > (LONG) *pcol)
  2332. {
  2333. hr = pdb->GetDefaultColumnSet(*pcol, ARRAYSIZE(acol), acol, &ccol);
  2334. _JumpIfError(hr, error, "GetDefaultColumnSet");
  2335. if (ARRAYSIZE(acol) == ccol)
  2336. {
  2337. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  2338. _JumpError(hr, error, "GetDefaultColumnSet");
  2339. }
  2340. pcol = acol;
  2341. }
  2342. wprintf(myLoadResourceString(IDS_SCHEMA_COLON)); // "Schema:"
  2343. wprintf(wszNewLine);
  2344. wprintf(myLoadResourceString(IDS_SCHEMA_COLUMNHEADERS)); // "Name..Type..."
  2345. wprintf(wszNewLine);
  2346. wprintf(myLoadResourceString(IDS_SCHEMA_COLUMNUNDERLINE)); // "____...____"
  2347. wprintf(wszNewLine);
  2348. if (NULL != pcol)
  2349. {
  2350. for (i = 0; i < ccol; i++)
  2351. {
  2352. CERTDBCOLUMN const *pdc;
  2353. DWORD dwTable;
  2354. hr = DBLookupColumnInfo(pcol[i], &pdc, &dwTable);
  2355. _JumpIfError(hr, error, "DBLookupColumnInfo");
  2356. hr = DBDumpColumn(pdc);
  2357. _JumpIfError(hr, error, "DBDumpColumn");
  2358. }
  2359. }
  2360. else
  2361. {
  2362. hr = DBDumpSchema1(g_adcRequests);
  2363. _JumpIfError(hr, error, "DBDumpSchema1");
  2364. hr = DBDumpSchema1(g_adcCertificates);
  2365. _JumpIfError(hr, error, "DBDumpSchema1");
  2366. }
  2367. hr = S_OK;
  2368. error:
  2369. return(hr);
  2370. }
  2371. VOID
  2372. DBFreeSchema1(
  2373. IN CERTDBCOLUMN const *pdc,
  2374. IN DWORD cdc)
  2375. {
  2376. CERTDBCOLUMN const *pdcEnd;
  2377. for (pdcEnd = &pdc[cdc]; pdc < pdcEnd; pdc++)
  2378. {
  2379. if (NULL != pdc->pwszName)
  2380. {
  2381. CoTaskMemFree(pdc->pwszName);
  2382. }
  2383. if (NULL != pdc->pwszDisplayName)
  2384. {
  2385. CoTaskMemFree(pdc->pwszDisplayName);
  2386. }
  2387. }
  2388. }
  2389. VOID
  2390. DBFreeSchema()
  2391. {
  2392. DBFreeSchema1(g_adcRequests, g_cdcRequests);
  2393. DBFreeSchema1(g_adcCertificates, g_cdcCertificates);
  2394. }
  2395. HRESULT
  2396. DBGetColumnInfo1(
  2397. IN CERTDBCOLUMN const *pdc,
  2398. IN WCHAR const *pwszColName,
  2399. OUT WCHAR const **ppwszColNameActual,
  2400. OUT DWORD *pColIndex,
  2401. OUT LONG *pColType)
  2402. {
  2403. HRESULT hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  2404. *ppwszColNameActual = NULL;
  2405. for ( ; NULL != pdc->pwszName; pdc++)
  2406. {
  2407. if (0 == mylstrcmpiL(pwszColName, pdc->pwszName))
  2408. {
  2409. *ppwszColNameActual = pdc->pwszName;
  2410. }
  2411. else
  2412. if (NULL != pdc->pwszDisplayName &&
  2413. 0 == mylstrcmpiL(pwszColName, pdc->pwszDisplayName))
  2414. {
  2415. *ppwszColNameActual = pdc->pwszDisplayName;
  2416. }
  2417. else
  2418. {
  2419. continue;
  2420. }
  2421. *pColIndex = pdc->Index;
  2422. *pColType = pdc->Type;
  2423. hr = S_OK;
  2424. break;
  2425. }
  2426. //error:
  2427. return(hr);
  2428. }
  2429. HRESULT
  2430. DBGetColumnInfo(
  2431. IN ICertDB *pdb,
  2432. IN WCHAR const *pwszColName,
  2433. OUT WCHAR const **ppwszColNameActual,
  2434. OUT DWORD *pColIndex,
  2435. OUT LONG *pColType)
  2436. {
  2437. HRESULT hr;
  2438. WCHAR *pwsz;
  2439. WCHAR *pwszRequestColName = NULL;
  2440. hr = DBGetColumnInfo1(
  2441. g_adcRequests,
  2442. pwszColName,
  2443. ppwszColNameActual,
  2444. pColIndex,
  2445. pColType);
  2446. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  2447. {
  2448. _JumpIfError(hr, error, "DBGetColumnInfo1");
  2449. }
  2450. else
  2451. {
  2452. DBGPRINT((DBG_SS_CERTUTILI, "DBGetColumnInfo1(req, %ws) = %x\n", pwszColName, hr));
  2453. hr = DBGetColumnInfo1(
  2454. g_adcCertificates,
  2455. pwszColName,
  2456. ppwszColNameActual,
  2457. pColIndex,
  2458. pColType);
  2459. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  2460. {
  2461. _JumpIfError(hr, error, "DBGetColumnInfo1");
  2462. }
  2463. else
  2464. {
  2465. DBGPRINT((DBG_SS_CERTUTILI, "DBGetColumnInfo1(cert, %ws) = %x\n", pwszColName, hr));
  2466. pwsz = wcschr(pwszColName, L'.');
  2467. if (NULL == pwsz)
  2468. {
  2469. pwszRequestColName = (WCHAR *) LocalAlloc(
  2470. LMEM_FIXED,
  2471. (WSZARRAYSIZE(wszPROPREQUESTDOT) + wcslen(pwszColName) + 1) *
  2472. sizeof(WCHAR));
  2473. if (NULL == pwszRequestColName)
  2474. {
  2475. hr = E_OUTOFMEMORY;
  2476. _JumpError(hr, error, "LocalAlloc");
  2477. }
  2478. wcscpy(pwszRequestColName, wszPROPREQUESTDOT);
  2479. wcscat(pwszRequestColName, pwszColName);
  2480. hr = DBGetColumnInfo1(
  2481. g_adcRequests,
  2482. pwszRequestColName,
  2483. ppwszColNameActual,
  2484. pColIndex,
  2485. pColType);
  2486. DBGPRINT((DBG_SS_CERTUTILI, "DBGetColumnInfo1(req, %ws) = %x\n", pwszRequestColName, hr));
  2487. }
  2488. }
  2489. _JumpIfError(hr, error, "DBGetColumnInfo1");
  2490. }
  2491. error:
  2492. if (NULL != pwszRequestColName)
  2493. {
  2494. LocalFree(pwszRequestColName);
  2495. }
  2496. return(hr);
  2497. }
  2498. HRESULT
  2499. cuDBPrintProperty(
  2500. OPTIONAL IN ICertDBRow *prow,
  2501. IN DWORD Type,
  2502. IN WCHAR const *pwszColName,
  2503. IN WCHAR const *pwszDisplayName,
  2504. OPTIONAL IN BYTE const *pbValue,
  2505. IN DWORD cbValue,
  2506. OUT DWORD *pcbValue)
  2507. {
  2508. HRESULT hr;
  2509. DWORD cb = 0;
  2510. BYTE *pb = NULL;
  2511. LONG Format;
  2512. WCHAR *pwszOut = NULL;
  2513. EnterCriticalSection(&g_DBCriticalSection);
  2514. *pcbValue = 0;
  2515. if (cuDBIsShutDownInProgress())
  2516. {
  2517. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  2518. _JumpError(hr, error, "cuDBIsShutDownInProgress");
  2519. }
  2520. wprintf(L" %ws:", pwszDisplayName);
  2521. if (NULL == pbValue)
  2522. {
  2523. cb = 0;
  2524. hr = prow->GetProperty(pwszColName, Type, NULL, &cb, pb);
  2525. if (S_OK == hr)
  2526. {
  2527. pb = (BYTE *) LocalAlloc(LMEM_FIXED, cb);
  2528. if (NULL == pb)
  2529. {
  2530. hr = E_OUTOFMEMORY;
  2531. _JumpError(hr, error, "LocalAlloc");
  2532. }
  2533. hr = prow->GetProperty(pwszColName, Type, NULL, &cb, pb);
  2534. }
  2535. if (S_OK != hr)
  2536. {
  2537. wprintf(L" ");
  2538. if (CERTSRV_E_PROPERTY_EMPTY != hr)
  2539. {
  2540. cuPrintError(IDS_FORMAT_ERROR, hr); // "error = %ws"
  2541. _JumpError(hr, error, "GetProperty");
  2542. }
  2543. wprintf(myLoadResourceString(IDS_PROP_EMPTY)); // "EMPTY"
  2544. wprintf(wszNewLine);
  2545. cb = 0;
  2546. }
  2547. else
  2548. {
  2549. pbValue = pb;
  2550. cbValue = cb;
  2551. }
  2552. }
  2553. if (NULL != pbValue)
  2554. {
  2555. switch (PROPTYPE_MASK & Type)
  2556. {
  2557. case PROPTYPE_LONG:
  2558. DumpLongValue(*(DWORD *) pbValue, pwszColName);
  2559. break;
  2560. case PROPTYPE_DATE:
  2561. hr = cuDumpFileTime(0, NULL, (FILETIME const *) pbValue);
  2562. _JumpIfError(hr, error, "cuDumpFileTime");
  2563. break;
  2564. case PROPTYPE_BINARY:
  2565. hr = GetBinaryColumnFormat(pwszColName, &Format);
  2566. _JumpIfError(hr, error, "GetBinaryColumnFormat");
  2567. if (CV_OUT_BINARY != Format)
  2568. {
  2569. CSASSERT(CV_OUT_BASE64HEADER == CRYPT_STRING_BASE64HEADER);
  2570. CSASSERT(CV_OUT_BASE64 == CRYPT_STRING_BASE64);
  2571. CSASSERT(
  2572. CV_OUT_BASE64REQUESTHEADER == CRYPT_STRING_BASE64REQUESTHEADER);
  2573. CSASSERT(CV_OUT_HEX == CRYPT_STRING_HEX);
  2574. CSASSERT(CV_OUT_HEXASCII == CRYPT_STRING_HEXASCII);
  2575. CSASSERT(CV_OUT_HEXADDR == CRYPT_STRING_HEXADDR);
  2576. CSASSERT(CV_OUT_HEXASCIIADDR == CRYPT_STRING_HEXASCIIADDR);
  2577. hr = myCryptBinaryToString(
  2578. pbValue,
  2579. cbValue,
  2580. Format,
  2581. &pwszOut);
  2582. _JumpIfError(hr, error, "myCryptBinaryToString");
  2583. }
  2584. DumpBinaryValue(
  2585. pwszColName,
  2586. NULL, // pwszObjId
  2587. Format,
  2588. pbValue,
  2589. cbValue,
  2590. pwszOut);
  2591. break;
  2592. case PROPTYPE_STRING:
  2593. wprintf(L" \"");
  2594. cuPrintCRLFString(NULL, (WCHAR const *) pbValue);
  2595. wprintf(L"\"");
  2596. cuPrintPossibleObjectIdName((WCHAR const *) pbValue);
  2597. wprintf(wszNewLine);
  2598. break;
  2599. }
  2600. }
  2601. *pcbValue = cb;
  2602. hr = S_OK;
  2603. error:
  2604. LeaveCriticalSection(&g_DBCriticalSection);
  2605. if (NULL != pb)
  2606. {
  2607. LocalFree(pb);
  2608. }
  2609. if (NULL != pwszOut)
  2610. {
  2611. LocalFree(pwszOut);
  2612. }
  2613. return(hr);
  2614. }
  2615. HRESULT
  2616. DBPrintRow(
  2617. IN ICertDB *pdb,
  2618. IN DWORD iRow,
  2619. IN DWORD RowId,
  2620. OPTIONAL IN CERTDBRESULTROW const *pResultRow,
  2621. OPTIONAL IN DWORD const *acol,
  2622. IN DWORD ccol,
  2623. IN BOOL fAllColumns,
  2624. IN OUT DBSTATS *pstatsRowProperties,
  2625. OPTIONAL IN WCHAR const * const *apwszAttributes,
  2626. IN BOOL fAllAttributes,
  2627. IN OUT DBSTATS *pstatsAttributes,
  2628. OPTIONAL IN WCHAR const * const *apwszExtensions,
  2629. IN BOOL fAllExtensions,
  2630. IN OUT DBSTATS *pstatsExtensions)
  2631. {
  2632. HRESULT hr;
  2633. ICertDBRow *prow = NULL;
  2634. DWORD ReqId;
  2635. CERTDBCOLUMN const *pdc;
  2636. LONG cskip;
  2637. IEnumCERTDBNAME *penum = NULL;
  2638. ULONG celtFetched;
  2639. CERTDBNAME cdbn;
  2640. BYTE abValue[64+1024];
  2641. DWORD dwTable;
  2642. DWORD i;
  2643. DWORD cb;
  2644. BOOL fRowPrinted = FALSE;
  2645. BOOL fExtraNewLine = FALSE;
  2646. BOOL fHeaderPrinted;
  2647. cdbn.pwszName = NULL;
  2648. hr = pdb->OpenRow(
  2649. PROPOPEN_READONLY | PROPTABLE_REQCERT,
  2650. RowId,
  2651. NULL,
  2652. &prow);
  2653. _JumpIfError2(hr, error, "OpenRow", CERTSRV_E_PROPERTY_EMPTY);
  2654. prow->GetRowId(&ReqId);
  2655. if (NULL != pResultRow)
  2656. {
  2657. #if 0
  2658. wprintf(
  2659. L"Row %u: ReqId=%u, ccol=%u, type=%x, index=%x, cb=%u, value=%u\n",
  2660. iRow,
  2661. pResultRow->rowid,
  2662. pResultRow->ccol,
  2663. pResultRow->acol[0].Type,
  2664. pResultRow->acol[0].Index,
  2665. pResultRow->acol[0].cbValue,
  2666. *(DWORD *) pResultRow->acol[0].pbValue);
  2667. #endif
  2668. for (i = 0; i < pResultRow->ccol; i++)
  2669. {
  2670. CERTDBRESULTCOLUMN *pcol = &pResultRow->acol[i];
  2671. hr = DBLookupColumnInfo(pcol->Index, &pdc, &dwTable);
  2672. _JumpIfError(hr, error, "DBLookupColumnInfo");
  2673. CSASSERT(pcol->Type == pdc->Type);
  2674. PrintRowIndex(iRow, &fRowPrinted);
  2675. fExtraNewLine = TRUE;
  2676. hr = cuDBPrintProperty(
  2677. prow,
  2678. dwTable | pcol->Type,
  2679. pdc->pwszName,
  2680. pdc->pwszDisplayName,
  2681. pcol->pbValue,
  2682. pcol->cbValue,
  2683. &cb);
  2684. _JumpIfError(hr, error, "cuDBPrintProperty");
  2685. UpdateStats(pstatsRowProperties, cb);
  2686. }
  2687. }
  2688. else if (NULL != acol)
  2689. {
  2690. for (i = 0; i < ccol; i++)
  2691. {
  2692. PrintRowIndex(iRow, &fRowPrinted);
  2693. fExtraNewLine = TRUE;
  2694. hr = DBLookupColumnInfo(acol[i], &pdc, &dwTable);
  2695. _JumpIfError(hr, error, "DBLookupColumnInfo");
  2696. hr = cuDBPrintProperty(
  2697. prow,
  2698. dwTable | pdc->Type,
  2699. pdc->pwszName,
  2700. pdc->pwszDisplayName,
  2701. NULL, // pbValue
  2702. 0, // cbValue
  2703. &cb);
  2704. _JumpIfError(hr, error, "cuDBPrintProperty");
  2705. UpdateStats(pstatsRowProperties, cb);
  2706. }
  2707. }
  2708. else if (fAllColumns)
  2709. {
  2710. PrintRowIndex(iRow, &fRowPrinted);
  2711. fExtraNewLine = TRUE;
  2712. for (pdc = g_adcRequests; NULL != pdc->pwszName; pdc++)
  2713. {
  2714. hr = cuDBPrintProperty(
  2715. prow,
  2716. PROPTABLE_REQUEST | pdc->Type,
  2717. pdc->pwszName,
  2718. pdc->pwszDisplayName,
  2719. NULL, // pbValue
  2720. 0, // cbValue
  2721. &cb);
  2722. _JumpIfError(hr, error, "cuDBPrintProperty");
  2723. UpdateStats(pstatsRowProperties, cb);
  2724. }
  2725. wprintf(wszNewLine);
  2726. wprintf(L" ");
  2727. wprintf(myLoadResourceString(IDS_CERT_PROPERTIES)); // "Certificate Properties:"
  2728. wprintf(wszNewLine);
  2729. for (pdc = g_adcCertificates; NULL != pdc->pwszName; pdc++)
  2730. {
  2731. hr = cuDBPrintProperty(
  2732. prow,
  2733. PROPTABLE_CERTIFICATE | pdc->Type,
  2734. pdc->pwszName,
  2735. pdc->pwszDisplayName,
  2736. NULL, // pbValue
  2737. 0, // cbValue
  2738. &cb);
  2739. _JumpIfError(hr, error, "cuDBPrintProperty");
  2740. UpdateStats(pstatsRowProperties, cb);
  2741. }
  2742. wprintf(wszNewLine);
  2743. }
  2744. if (fAllAttributes || NULL != apwszAttributes)
  2745. {
  2746. fHeaderPrinted = FALSE;
  2747. hr = prow->EnumCertDBName(CIE_TABLE_ATTRIBUTES, &penum);
  2748. _JumpIfError(hr, error, "EnumCertDBName");
  2749. while (TRUE)
  2750. {
  2751. hr = penum->Next(1, &cdbn, &celtFetched);
  2752. if (S_FALSE == hr)
  2753. {
  2754. break;
  2755. }
  2756. _JumpIfError(hr, error, "Next");
  2757. CSASSERT(1 == celtFetched);
  2758. CSASSERT(NULL != cdbn.pwszName);
  2759. if (ShouldDisplay(cdbn.pwszName, fAllAttributes, apwszAttributes))
  2760. {
  2761. if (!fHeaderPrinted)
  2762. {
  2763. PrintRowIndex(iRow, &fRowPrinted);
  2764. if (fExtraNewLine)
  2765. {
  2766. wprintf(wszNewLine);
  2767. }
  2768. wprintf(
  2769. L" %ws\n",
  2770. myLoadResourceString(IDS_REQUEST_ATTRIBUTES)); // "Request Attributes:"
  2771. fHeaderPrinted = TRUE;
  2772. fExtraNewLine = TRUE;
  2773. }
  2774. hr = cuDBPrintProperty(
  2775. prow,
  2776. PROPTABLE_ATTRIBUTE | PROPTYPE_STRING,
  2777. cdbn.pwszName,
  2778. cdbn.pwszName,
  2779. NULL, // pbValue
  2780. 0, // cbValue
  2781. &cb); // returned cbValue
  2782. _JumpIfError(hr, error, "cuDBPrintProperty");
  2783. UpdateStats(
  2784. pstatsAttributes,
  2785. wcslen(cdbn.pwszName) * sizeof(WCHAR) +
  2786. cb +
  2787. sizeof(LONG)); // for RequestId
  2788. }
  2789. CoTaskMemFree(cdbn.pwszName);
  2790. cdbn.pwszName = NULL;
  2791. }
  2792. penum->Release();
  2793. penum = NULL;
  2794. }
  2795. if (fAllExtensions || NULL != apwszExtensions)
  2796. {
  2797. fHeaderPrinted = FALSE;
  2798. hr = prow->EnumCertDBName(CIE_TABLE_EXTENSIONS, &penum);
  2799. _JumpIfError(hr, error, "EnumCertDBName");
  2800. while (TRUE)
  2801. {
  2802. DWORD ExtFlags;
  2803. hr = penum->Next(1, &cdbn, &celtFetched);
  2804. if (S_FALSE == hr)
  2805. {
  2806. break;
  2807. }
  2808. _JumpIfError(hr, error, "Next");
  2809. CSASSERT(1 == celtFetched);
  2810. CSASSERT(NULL != cdbn.pwszName);
  2811. if (ShouldDisplay(cdbn.pwszName, fAllExtensions, apwszExtensions))
  2812. {
  2813. if (!fHeaderPrinted)
  2814. {
  2815. PrintRowIndex(iRow, &fRowPrinted);
  2816. if (fExtraNewLine)
  2817. {
  2818. wprintf(wszNewLine);
  2819. }
  2820. wprintf(
  2821. L" %ws\n",
  2822. myLoadResourceString(IDS_CERTIFICATE_EXTENSIONS)); // "Certificate Extensions:"
  2823. fHeaderPrinted = TRUE;
  2824. }
  2825. cb = sizeof(abValue);
  2826. hr = prow->GetExtension(cdbn.pwszName, &ExtFlags, &cb, abValue);
  2827. _JumpIfError(hr, error, "GetExtension");
  2828. wprintf(g_wszPad4);
  2829. wprintf(
  2830. myLoadResourceString(IDS_FORMAT_EXTENSION), // "%ws: Flags = %x%ws, Length = %x"
  2831. cdbn.pwszName,
  2832. ExtFlags,
  2833. cuwszFromExtFlags(ExtFlags),
  2834. cb);
  2835. wprintf(wszNewLine);
  2836. if (!cuDumpFormattedExtension(cdbn.pwszName, abValue, cb) ||
  2837. g_fVerbose)
  2838. {
  2839. wprintf(wszNewLine);
  2840. DumpHex(DH_NOTABPREFIX | 4, abValue, cb);
  2841. }
  2842. wprintf(wszNewLine);
  2843. UpdateStats(
  2844. pstatsExtensions,
  2845. wcslen(cdbn.pwszName) * sizeof(WCHAR) +
  2846. cb + // for ext
  2847. sizeof(LONG) + // for RequestId
  2848. sizeof(ExtFlags)); // for ExtensionFlags
  2849. }
  2850. CoTaskMemFree(cdbn.pwszName);
  2851. cdbn.pwszName = NULL;
  2852. }
  2853. }
  2854. hr = S_OK;
  2855. error:
  2856. if (NULL != cdbn.pwszName)
  2857. {
  2858. CoTaskMemFree(cdbn.pwszName);
  2859. }
  2860. if (NULL != penum)
  2861. {
  2862. penum->Release();
  2863. }
  2864. if (NULL != prow)
  2865. {
  2866. prow->Release();
  2867. }
  2868. return(hr);
  2869. }
  2870. WCHAR const *
  2871. wszSeekOperator(
  2872. IN LONG SeekOperator)
  2873. {
  2874. WCHAR const *pwsz;
  2875. static WCHAR s_wszBuf[10 + cwcDWORDSPRINTF];
  2876. switch (CVR_SEEK_MASK & SeekOperator)
  2877. {
  2878. case CVR_SEEK_NONE: pwsz = L"None"; break;
  2879. case CVR_SEEK_EQ: pwsz = L"=="; break;
  2880. case CVR_SEEK_LT: pwsz = L"<"; break;
  2881. case CVR_SEEK_LE: pwsz = L"<="; break;
  2882. case CVR_SEEK_GE: pwsz = L">="; break;
  2883. case CVR_SEEK_GT: pwsz = L">"; break;
  2884. default:
  2885. wsprintf(s_wszBuf, L"???=%x", SeekOperator);
  2886. pwsz = s_wszBuf;
  2887. break;
  2888. }
  2889. if (s_wszBuf != pwsz && (CVR_SEEK_NODELTA & SeekOperator))
  2890. {
  2891. wcscpy(s_wszBuf, pwsz);
  2892. wcscat(s_wszBuf, L",NoDelta");
  2893. pwsz = s_wszBuf;
  2894. }
  2895. return(pwsz);
  2896. }
  2897. WCHAR const *
  2898. wszSortOperator(
  2899. IN LONG SortOrder)
  2900. {
  2901. WCHAR const *pwsz;
  2902. static WCHAR s_wszBuf[10 + cwcDWORDSPRINTF];
  2903. switch (SortOrder)
  2904. {
  2905. case CVR_SORT_NONE: pwsz = L"None"; break;
  2906. case CVR_SORT_ASCEND: pwsz = L"Ascend"; break;
  2907. case CVR_SORT_DESCEND: pwsz = L"Descend"; break;
  2908. default:
  2909. wsprintf(s_wszBuf, L"???=%x", SortOrder);
  2910. pwsz = s_wszBuf;
  2911. break;
  2912. }
  2913. return(pwsz);
  2914. }
  2915. HRESULT
  2916. DBParseRestriction(
  2917. IN ICertDB *pdb,
  2918. IN WCHAR const *pwszRestriction,
  2919. OUT CERTVIEWRESTRICTION *pcvr,
  2920. OUT BOOL *pfOneRow,
  2921. OUT LONG *plSkip)
  2922. {
  2923. HRESULT hr;
  2924. LONG ColType;
  2925. WCHAR *pwszColName = NULL;
  2926. WCHAR *pwszColValue = NULL;
  2927. WCHAR const *pwszColNameActual;
  2928. LONG lVal;
  2929. DATE date;
  2930. BYTE const *pb;
  2931. *pfOneRow = FALSE;
  2932. *plSkip = 0;
  2933. hr = ParseRestriction(
  2934. pwszRestriction,
  2935. (LONG *) &pcvr->ColumnIndex,
  2936. &pcvr->SeekOperator,
  2937. &pcvr->SortOrder,
  2938. &pwszColName,
  2939. &pwszColValue);
  2940. _JumpIfErrorStr(hr, error, "ParseRestriction", pwszRestriction);
  2941. // no value to parse if a special column...
  2942. if (NULL == pwszColName)
  2943. {
  2944. CSASSERT(0 > (LONG) pcvr->ColumnIndex);
  2945. pcvr->cbValue = 0;
  2946. pb = NULL; // no source data
  2947. pwszColNameActual = L"";
  2948. }
  2949. else
  2950. {
  2951. hr = DBGetColumnInfo(
  2952. pdb,
  2953. pwszColName,
  2954. &pwszColNameActual,
  2955. &pcvr->ColumnIndex,
  2956. &ColType);
  2957. _JumpIfErrorStr(hr, error, "DBGetColumnInfo", pwszColName);
  2958. hr = ParseSpecialColumnValue(
  2959. pwszColValue,
  2960. PROPTYPE_MASK & ColType,
  2961. &pcvr->SeekOperator,
  2962. &pcvr->SortOrder,
  2963. pfOneRow,
  2964. plSkip);
  2965. _JumpIfError(hr, error, "ParseSpecialColumnValue");
  2966. switch (PROPTYPE_MASK & ColType)
  2967. {
  2968. case PROPTYPE_LONG:
  2969. lVal = 0;
  2970. if (!*pfOneRow)
  2971. {
  2972. hr = myGetSignedLong(pwszColValue, &lVal);
  2973. _JumpIfError(hr, error, "bad numeric operand");
  2974. }
  2975. pb = (BYTE const *) &lVal;
  2976. pcvr->cbValue = sizeof(lVal);
  2977. break;
  2978. case PROPTYPE_DATE:
  2979. date = 0;
  2980. if (!*pfOneRow)
  2981. {
  2982. hr = myWszLocalTimeToGMTDate(pwszColValue, &date);
  2983. _JumpIfError(hr, error, "invalid date format");
  2984. }
  2985. pb = (BYTE const *) &date;
  2986. pcvr->cbValue = sizeof(date);
  2987. cuDumpDate(&date);
  2988. break;
  2989. case PROPTYPE_STRING:
  2990. {
  2991. WCHAR const *pwsz = L"";
  2992. if (!*pfOneRow)
  2993. {
  2994. pwsz = pwszColValue;
  2995. }
  2996. pb = (BYTE const *) pwsz;
  2997. pcvr->cbValue = (wcslen(pwsz) + 1) * sizeof(WCHAR);
  2998. break;
  2999. }
  3000. case PROPTYPE_BINARY:
  3001. default:
  3002. hr = E_INVALIDARG;
  3003. _JumpError(hr, error, "not supported");
  3004. }
  3005. }
  3006. pcvr->pbValue = (BYTE *) LocalAlloc(LMEM_FIXED, pcvr->cbValue);
  3007. if (NULL == pcvr->pbValue)
  3008. {
  3009. hr = E_OUTOFMEMORY;
  3010. _JumpError(hr, error, "LocalAlloc");
  3011. }
  3012. if (NULL != pb)
  3013. {
  3014. CopyMemory(pcvr->pbValue, pb, pcvr->cbValue);
  3015. }
  3016. #ifdef DBG_CERTSRV_DEBUG_PRINT
  3017. WCHAR wszSkip[cwcDWORDSPRINTF];
  3018. wszSkip[0] = L'\0';
  3019. if (0 != *plSkip)
  3020. {
  3021. wsprintf(wszSkip, L"%d", *plSkip);
  3022. }
  3023. #endif // DBG_CERTSRV_DEBUG_PRINT
  3024. DBGPRINT((
  3025. DBG_SS_CERTUTILI,
  3026. "Restriction: Col=%ws Index=%x Seek='%ws'%ws Sort=%ws cb=%x, pb=%x\n",
  3027. pwszColNameActual,
  3028. pcvr->ColumnIndex,
  3029. wszSeekOperator(pcvr->SeekOperator),
  3030. wszSkip,
  3031. wszSortOperator(pcvr->SortOrder),
  3032. pcvr->cbValue,
  3033. pcvr->pbValue));
  3034. DBGDUMPHEX((DBG_SS_CERTUTILI, 0, pcvr->pbValue, pcvr->cbValue));
  3035. error:
  3036. if (NULL != pwszColName)
  3037. {
  3038. LocalFree(pwszColName);
  3039. }
  3040. if (NULL != pwszColValue)
  3041. {
  3042. LocalFree(pwszColValue);
  3043. }
  3044. return(hr);
  3045. }
  3046. HRESULT
  3047. verbDBDump(
  3048. IN WCHAR const *pwszOption,
  3049. IN WCHAR const *pwszRequestId,
  3050. IN WCHAR const *pwszArg2,
  3051. IN WCHAR const *pwszArg3,
  3052. IN WCHAR const *pwszArg4)
  3053. {
  3054. HRESULT hr;
  3055. WCHAR const *pwsz;
  3056. ICertDB *pdb = NULL;
  3057. ICertDBRow *prow = NULL;
  3058. IEnumCERTDBRESULTROW *penum = NULL;
  3059. DWORD i;
  3060. DWORD imin = 1;
  3061. DWORD RequestId;
  3062. LONG cskip;
  3063. WCHAR **apwszRestrictions = NULL;
  3064. WCHAR **apwszColumns = NULL;
  3065. WCHAR **apwszAttributes = NULL;
  3066. WCHAR **apwszExtensions = NULL;
  3067. WCHAR **ppwsz;
  3068. BOOL fOneRow = FALSE;
  3069. LONG lSkip = 0;
  3070. BOOL fAllColumns;
  3071. BOOL fAllAttributes;
  3072. BOOL fAllExtensions;
  3073. CERTVIEWRESTRICTION *acvr = NULL;
  3074. DWORD ccvr;
  3075. DWORD *acol = NULL;
  3076. DWORD ccol;
  3077. CERTDBRESULTROW arow[35];
  3078. DWORD crow;
  3079. BOOL fReleaseRows = FALSE;
  3080. DWORD iRow;
  3081. DBSTATS statsRowProperties;
  3082. DBSTATS statsAttributes;
  3083. DBSTATS statsExtensions;
  3084. ZeroMemory(&statsRowProperties, sizeof(statsRowProperties));
  3085. ZeroMemory(&statsAttributes, sizeof(statsAttributes));
  3086. ZeroMemory(&statsExtensions, sizeof(statsExtensions));
  3087. if (NULL != pwszRequestId)
  3088. {
  3089. if (L'+' == *pwszRequestId)
  3090. {
  3091. hr = ParseSkipCounts(&pwszRequestId[1]);
  3092. _JumpIfError(hr, error, "ParseSkipCounts");
  3093. }
  3094. else
  3095. {
  3096. hr = myGetLong(pwszRequestId, (LONG *) &RequestId);
  3097. _JumpIfError(hr, error, "RequestId must be a number");
  3098. imin = RequestId;
  3099. fOneRow = TRUE;
  3100. }
  3101. }
  3102. pwsz = wcschr(g_pwszConfig, L'\\');
  3103. if (NULL != pwsz)
  3104. {
  3105. pwsz++;
  3106. }
  3107. else
  3108. {
  3109. pwsz = g_pwszConfig;
  3110. }
  3111. hr = cuDBOpen(pwsz, TRUE, &pdb);
  3112. _JumpIfError(hr, error, "cuDBOpen");
  3113. hr = DBLoadSchema(pdb);
  3114. _JumpIfError(hr, error, "DBLoadSchema");
  3115. if (1 < g_fVerbose)
  3116. {
  3117. hr = DBDumpSchema(pdb, NULL, 0);
  3118. _JumpIfError(hr, error, "DBDumpSchema");
  3119. }
  3120. ccvr = 0;
  3121. if (NULL != g_pwszRestrict)
  3122. {
  3123. hr = ParseViewRestrictions(g_pwszRestrict, &apwszRestrictions);
  3124. _JumpIfError(hr, error, "ParseViewRestrictions");
  3125. for (ppwsz = apwszRestrictions; NULL != *ppwsz; ppwsz++)
  3126. ;
  3127. ccvr = (DWORD) (ppwsz - apwszRestrictions);
  3128. acvr = (CERTVIEWRESTRICTION *) LocalAlloc(
  3129. LMEM_FIXED | LMEM_ZEROINIT,
  3130. ccvr * sizeof(acvr[0]));
  3131. if (NULL == acvr)
  3132. {
  3133. hr = E_OUTOFMEMORY;
  3134. _JumpError(hr, error, "LocalAlloc");
  3135. }
  3136. for (i = 0; i < ccvr; i++)
  3137. {
  3138. BOOL f;
  3139. LONG l;
  3140. hr = DBParseRestriction(pdb, apwszRestrictions[i], &acvr[i], &f, &l);
  3141. _JumpIfErrorStr(
  3142. hr,
  3143. error,
  3144. "DBParseRestriction",
  3145. apwszRestrictions[i]);
  3146. if (f)
  3147. {
  3148. fOneRow = TRUE;
  3149. lSkip = l;
  3150. }
  3151. }
  3152. }
  3153. ccol = 0;
  3154. fAllColumns = TRUE;
  3155. fAllAttributes = TRUE;
  3156. fAllExtensions = TRUE;
  3157. if (NULL != g_pwszOut)
  3158. {
  3159. fAllAttributes = FALSE;
  3160. fAllExtensions = FALSE;
  3161. hr = ParseViewColumns(
  3162. g_pwszOut,
  3163. NULL,
  3164. NULL,
  3165. &apwszColumns,
  3166. &fAllColumns);
  3167. _JumpIfError(hr, error, "ParseViewColumns");
  3168. if (NULL != apwszColumns)
  3169. {
  3170. for (ppwsz = apwszColumns; NULL != *ppwsz; ppwsz++)
  3171. ;
  3172. ccol = (DWORD) (ppwsz - apwszColumns);
  3173. }
  3174. hr = ParseViewColumns(
  3175. g_pwszOut,
  3176. g_wszAttrib,
  3177. g_apwszAllowedPrefixes,
  3178. &apwszAttributes,
  3179. &fAllAttributes);
  3180. _JumpIfError(hr, error, "ParseViewColumns");
  3181. hr = ParseViewColumns(
  3182. g_pwszOut,
  3183. g_wszExt,
  3184. NULL,
  3185. &apwszExtensions,
  3186. &fAllExtensions);
  3187. _JumpIfError(hr, error, "ParseViewColumns");
  3188. }
  3189. if (fAllColumns)
  3190. {
  3191. ccol = g_cdcRequests + g_cdcCertificates;
  3192. }
  3193. if (0 != ccol)
  3194. {
  3195. acol = (DWORD *) LocalAlloc(LMEM_FIXED, ccol * sizeof(acol[0]));
  3196. if (NULL == acol)
  3197. {
  3198. hr = E_OUTOFMEMORY;
  3199. _JumpError(hr, error, "LocalAlloc");
  3200. }
  3201. if (fAllColumns)
  3202. {
  3203. for (i = 0; i < ccol; i++)
  3204. {
  3205. CERTDBCOLUMN const *pdc;
  3206. pdc = (i < g_cdcRequests)?
  3207. &g_adcRequests[i] :
  3208. &g_adcCertificates[i - g_cdcRequests];
  3209. acol[i] = pdc->Index;
  3210. }
  3211. }
  3212. else
  3213. {
  3214. CSASSERT(NULL != apwszColumns);
  3215. for (i = 0; i < ccol; i++)
  3216. {
  3217. WCHAR const *pwszColNameActual;
  3218. LONG ColType;
  3219. hr = DBGetColumnInfo(
  3220. pdb,
  3221. apwszColumns[i],
  3222. &pwszColNameActual,
  3223. &acol[i],
  3224. &ColType);
  3225. _JumpIfErrorStr(hr, error, "DBGetColumnInfo", apwszColumns[i]);
  3226. }
  3227. }
  3228. }
  3229. if (!g_fCryptSilent)
  3230. {
  3231. hr = DBDumpSchema(pdb, acol, ccol);
  3232. _JumpIfError(hr, error, "DBDumpSchema");
  3233. }
  3234. if (NULL != g_pwszRestrict)
  3235. {
  3236. BOOL fNoMore;
  3237. LONG lIndex;
  3238. hr = pdb->OpenView(ccvr, acvr, ccol, acol, 0x0, &penum);
  3239. _JumpIfError(hr, error, "OpenView");
  3240. hr = penum->Skip(lSkip, &lIndex);
  3241. _JumpIfError(hr, error, "Skip");
  3242. iRow = 1;
  3243. fNoMore = FALSE;
  3244. while (!fNoMore)
  3245. {
  3246. hr = penum->Next(
  3247. NULL,
  3248. (ULONG)(fOneRow? 1 : ARRAYSIZE(arow)),
  3249. arow,
  3250. &crow);
  3251. if (S_FALSE == hr)
  3252. {
  3253. hr = S_OK;
  3254. fNoMore = TRUE;
  3255. }
  3256. _JumpIfError(hr, error, "Next");
  3257. fReleaseRows = TRUE;
  3258. //wprintf(L"celtFetched = %u\n", crow);
  3259. for (i = 0; i < crow; i++, iRow++)
  3260. {
  3261. hr = DBPrintRow(
  3262. pdb,
  3263. iRow,
  3264. arow[i].rowid,
  3265. &arow[i],
  3266. NULL, // acol
  3267. 0, // ccol
  3268. FALSE, // fAllColumns
  3269. &statsRowProperties,
  3270. apwszAttributes,
  3271. fAllAttributes,
  3272. &statsAttributes,
  3273. apwszExtensions,
  3274. fAllExtensions,
  3275. &statsExtensions);
  3276. _JumpIfError(hr, error, "DBPrintRow");
  3277. }
  3278. if (fNoMore)
  3279. {
  3280. CSASSERT(ARRAYSIZE(arow) > crow);
  3281. CSASSERT(i == crow);
  3282. CSASSERT(arow[i].rowid == ~arow[i].ccol);
  3283. wprintf(
  3284. L"\n%ws: %u\n",
  3285. myLoadResourceString(IDS_MAXINDEX), // "Maximum Row Index"
  3286. arow[i].rowid);
  3287. }
  3288. hr = penum->ReleaseResultRow(crow, arow);
  3289. _JumpIfError(hr, error, "ReleaseResultRow");
  3290. fReleaseRows = FALSE;
  3291. if (fOneRow)
  3292. {
  3293. break;
  3294. }
  3295. }
  3296. }
  3297. else
  3298. {
  3299. DWORD imax;
  3300. iRow = 1;
  3301. imax = fOneRow? imin + 1 : MAXDWORD;
  3302. for (i = imin; i < imax; i++, iRow++)
  3303. {
  3304. hr = DBPrintRow(
  3305. pdb,
  3306. iRow,
  3307. i, // RowId
  3308. NULL, // pResultRow
  3309. acol,
  3310. ccol,
  3311. fAllColumns,
  3312. &statsRowProperties,
  3313. apwszAttributes,
  3314. fAllAttributes,
  3315. &statsAttributes,
  3316. apwszExtensions,
  3317. fAllExtensions,
  3318. &statsExtensions);
  3319. if (CERTSRV_E_PROPERTY_EMPTY == hr) // RowId doesn't exist
  3320. {
  3321. hr = S_OK;
  3322. break;
  3323. }
  3324. _JumpIfError(hr, error, "DBPrintRow");
  3325. }
  3326. }
  3327. DumpViewStats(
  3328. iRow - 1,
  3329. &statsRowProperties,
  3330. &statsAttributes,
  3331. &statsExtensions);
  3332. error:
  3333. cuFreeStringArray(apwszRestrictions);
  3334. cuFreeStringArray(apwszColumns);
  3335. cuFreeStringArray(apwszAttributes);
  3336. cuFreeStringArray(apwszExtensions);
  3337. if (NULL != acvr)
  3338. {
  3339. for (i = 0; i < ccvr; i++)
  3340. {
  3341. if (NULL != acvr[i].pbValue)
  3342. {
  3343. LocalFree(acvr[i].pbValue);
  3344. }
  3345. }
  3346. LocalFree(acvr);
  3347. }
  3348. if (NULL != acol)
  3349. {
  3350. LocalFree(acol);
  3351. }
  3352. DBFreeSchema();
  3353. if (fReleaseRows)
  3354. {
  3355. hr = penum->ReleaseResultRow(crow, arow);
  3356. _JumpIfError(hr, error, "ReleaseResultRow");
  3357. }
  3358. // Take critical section to make sure we wait for CTL-C DB shutdown.
  3359. EnterCriticalSection(&g_DBCriticalSection);
  3360. if (cuDBIsShutDownInProgress())
  3361. {
  3362. if (myJetHResult(JET_errTermInProgress) == hr)
  3363. {
  3364. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  3365. }
  3366. }
  3367. else
  3368. {
  3369. if (NULL != penum)
  3370. {
  3371. penum->Release();
  3372. }
  3373. if (NULL != prow)
  3374. {
  3375. prow->Release();
  3376. }
  3377. }
  3378. LeaveCriticalSection(&g_DBCriticalSection);
  3379. cuDBAbortShutDown(0);
  3380. return(hr);
  3381. }