Source code of Windows XP (NT5)
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.

975 lines
29 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: frmtutil.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "global.hxx"
  11. #include <dbgdef.h>
  12. extern HINSTANCE HinstDll;
  13. ///////////////////////////////////////////////////////
  14. const WCHAR RgwchHex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
  15. '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
  16. const CHAR RgchHex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
  17. '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
  18. //////////////////////////////////////////////////////////////////////////////////////
  19. //
  20. //////////////////////////////////////////////////////////////////////////////////////
  21. BOOL FormatAlgorithmString(LPWSTR *ppString, CRYPT_ALGORITHM_IDENTIFIER const *pAlgorithm)
  22. {
  23. PCCRYPT_OID_INFO pOIDInfo;
  24. pOIDInfo = CryptFindOIDInfo(
  25. CRYPT_OID_INFO_OID_KEY,
  26. pAlgorithm->pszObjId,
  27. 0);
  28. if (pOIDInfo != NULL)
  29. {
  30. if (NULL == (*ppString = AllocAndCopyWStr((LPWSTR) pOIDInfo->pwszName)))
  31. {
  32. return FALSE;
  33. }
  34. }
  35. else
  36. {
  37. if (NULL == (*ppString = CertUIMkWStr(pAlgorithm->pszObjId)))
  38. {
  39. return FALSE;
  40. }
  41. }
  42. return TRUE;
  43. }
  44. //////////////////////////////////////////////////////////////////////////////////////
  45. //
  46. //////////////////////////////////////////////////////////////////////////////////////
  47. BOOL FormatDateString(LPWSTR *ppString, FILETIME ft, BOOL fIncludeTime, BOOL fLongFormat, HWND hwnd)
  48. {
  49. int cch;
  50. int cch2;
  51. LPWSTR psz;
  52. SYSTEMTIME st;
  53. FILETIME localTime;
  54. DWORD locale;
  55. BOOL bRTLLocale;
  56. DWORD dwFlags = fLongFormat ? DATE_LONGDATE : 0;
  57. // See if the user locale id is RTL (Arabic, Urdu, Farsi or Hebrew).
  58. locale = GetUserDefaultLCID();
  59. bRTLLocale = ( (PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_ARABIC) ||
  60. (PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_URDU) ||
  61. (PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_FARSI) ||
  62. (PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_HEBREW)
  63. );
  64. locale = MAKELCID( MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), SORT_DEFAULT) ;
  65. if (bRTLLocale && (hwnd != NULL))
  66. {
  67. //Get the date format that matches the edit control reading direction.
  68. if (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_RTLREADING) {
  69. dwFlags |= DATE_RTLREADING;
  70. } else {
  71. dwFlags |= DATE_LTRREADING;
  72. }
  73. }
  74. if (!FileTimeToLocalFileTime(&ft, &localTime))
  75. {
  76. return FALSE;
  77. }
  78. if (!FileTimeToSystemTime(&localTime, &st))
  79. {
  80. //
  81. // if the conversion to local time failed, then just use the original time
  82. //
  83. if (!FileTimeToSystemTime(&ft, &st))
  84. {
  85. return FALSE;
  86. }
  87. }
  88. cch = (GetTimeFormatU(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) +
  89. GetDateFormatU(locale, dwFlags, &st, NULL, NULL, 0) + 5);
  90. if (NULL == (psz = (LPWSTR) malloc((cch+5) * sizeof(WCHAR))))
  91. {
  92. return FALSE;
  93. }
  94. cch2 = GetDateFormatU(locale, dwFlags, &st, NULL, psz, cch);
  95. if (fIncludeTime)
  96. {
  97. psz[cch2-1] = ' ';
  98. GetTimeFormatU(LOCALE_USER_DEFAULT, 0, &st, NULL,
  99. &psz[cch2], cch-cch2);
  100. }
  101. *ppString = psz;
  102. return TRUE;
  103. }
  104. //////////////////////////////////////////////////////////////////////////////////////
  105. //
  106. //////////////////////////////////////////////////////////////////////////////////////
  107. BOOL FormatValidityString(LPWSTR *ppString, PCCERT_CONTEXT pCertContext, HWND hwnd)
  108. {
  109. WCHAR szText[256];
  110. LPWSTR pwszReturnText;
  111. LPWSTR pwszText;
  112. void *pTemp;
  113. *ppString = NULL;
  114. LoadStringU(HinstDll, IDS_VALIDFROM, szText, ARRAYSIZE(szText));
  115. if (NULL == (pwszReturnText = AllocAndCopyWStr(szText)))
  116. {
  117. return FALSE;
  118. }
  119. if (!FormatDateString(&pwszText, pCertContext->pCertInfo->NotBefore, FALSE, FALSE, hwnd))
  120. {
  121. free(pwszReturnText);
  122. return FALSE;
  123. }
  124. if (NULL == (pTemp = realloc(pwszReturnText, (wcslen(pwszReturnText)+wcslen(pwszText)+3) * sizeof(WCHAR))))
  125. {
  126. free(pwszText);
  127. free(pwszReturnText);
  128. return FALSE;
  129. }
  130. pwszReturnText = (LPWSTR) pTemp;
  131. wcscat(pwszReturnText, L" ");
  132. wcscat(pwszReturnText, pwszText);
  133. free(pwszText);
  134. pwszText = NULL;
  135. LoadStringU(HinstDll, IDS_VALIDTO, szText, ARRAYSIZE(szText));
  136. if (NULL == (pTemp = realloc(pwszReturnText, (wcslen(pwszReturnText)+wcslen(szText)+3) * sizeof(WCHAR))))
  137. {
  138. free(pwszReturnText);
  139. return FALSE;
  140. }
  141. pwszReturnText = (LPWSTR) pTemp;
  142. wcscat(pwszReturnText, L" ");
  143. wcscat(pwszReturnText, szText);
  144. if (!FormatDateString(&pwszText, pCertContext->pCertInfo->NotAfter, FALSE, FALSE, hwnd))
  145. {
  146. free(pwszReturnText);
  147. return FALSE;
  148. }
  149. if (NULL == (pTemp = realloc(pwszReturnText, (wcslen(pwszReturnText)+wcslen(pwszText)+3) * sizeof(WCHAR))))
  150. {
  151. free(pwszText);
  152. free(pwszReturnText);
  153. return FALSE;
  154. }
  155. pwszReturnText = (LPWSTR) pTemp;
  156. wcscat(pwszReturnText, L" ");
  157. wcscat(pwszReturnText, pwszText);
  158. free(pwszText);
  159. *ppString = pwszReturnText;
  160. return TRUE;
  161. }
  162. //////////////////////////////////////////////////////////////////////////////////////
  163. //
  164. //////////////////////////////////////////////////////////////////////////////////////
  165. BOOL FormatSerialNoString(LPWSTR *ppString, CRYPT_INTEGER_BLOB const *pblob)
  166. {
  167. DWORD i = 0;
  168. LPBYTE pb;
  169. //DSIE: Bug 54159.
  170. // To solve the problem, we need to put the Left-To-Right marker (0x200e),
  171. // if complex script is supported, at the beginning of the Unicode string,
  172. // so that it will always be displayed as US string (left-to-right).
  173. #if (0)
  174. if (NULL == (*ppString = (LPWSTR) malloc((pblob->cbData * 3) * sizeof(WCHAR))))
  175. {
  176. return FALSE;
  177. }
  178. // fill the buffer
  179. pb = &pblob->pbData[pblob->cbData-1];
  180. while (pb >= &pblob->pbData[0])
  181. {
  182. (*ppString)[i++] = RgwchHex[(*pb & 0xf0) >> 4];
  183. (*ppString)[i++] = RgwchHex[*pb & 0x0f];
  184. (*ppString)[i++] = L' ';
  185. pb--;
  186. }
  187. (*ppString)[--i] = 0;
  188. #else
  189. HMODULE hModule = NULL;
  190. DWORD dwLength = pblob->cbData * 3;
  191. // See if complex script is supported.
  192. if (hModule = GetModuleHandle("LPK.DLL"))
  193. {
  194. dwLength++;
  195. }
  196. if (NULL == (*ppString = (LPWSTR) malloc(dwLength * sizeof(WCHAR))))
  197. {
  198. return FALSE;
  199. }
  200. // The marker will be changed back to NULL if no data to format.
  201. if (hModule)
  202. {
  203. (*ppString)[i++] = (WCHAR) 0x200e;
  204. }
  205. // fill the buffer
  206. pb = &pblob->pbData[pblob->cbData-1];
  207. while (pb >= &pblob->pbData[0])
  208. {
  209. (*ppString)[i++] = RgwchHex[(*pb & 0xf0) >> 4];
  210. (*ppString)[i++] = RgwchHex[*pb & 0x0f];
  211. (*ppString)[i++] = L' ';
  212. pb--;
  213. }
  214. (*ppString)[--i] = 0;
  215. #endif
  216. return TRUE;
  217. }
  218. //////////////////////////////////////////////////////////////////////////////////////
  219. //
  220. //////////////////////////////////////////////////////////////////////////////////////
  221. #define NUM_HEXBYTES_PERLINE 8
  222. #define NUM_CHARS_PERLINE ((NUM_HEXBYTES_PERLINE*2) + (NUM_HEXBYTES_PERLINE-1) + 3 + NUM_HEXBYTES_PERLINE + 2)
  223. // (two hex digits per byte) + (space between each byte)+ (3 spaces) + (an ascci char per byte) + \n
  224. BOOL FormatMemBufToWindow(HWND hWnd, LPBYTE pbData, DWORD cbData)
  225. {
  226. DWORD i = 0;
  227. LPBYTE pb;
  228. LPSTR pszBuffer;
  229. DWORD cbBuffer;
  230. char szHexText[(NUM_HEXBYTES_PERLINE*2) + NUM_HEXBYTES_PERLINE];
  231. DWORD dwHexTextIndex = 0;
  232. char szASCIIText[NUM_HEXBYTES_PERLINE+1];
  233. DWORD dwASCIITextIndex = 0;
  234. BYTE *pbBuffer;
  235. cbBuffer = ((cbData+NUM_HEXBYTES_PERLINE-1) / NUM_HEXBYTES_PERLINE) * NUM_CHARS_PERLINE + 1;
  236. if (NULL == (pszBuffer = (LPSTR) malloc(cbBuffer)))
  237. {
  238. return FALSE;
  239. }
  240. pszBuffer[0] = 0;
  241. pbBuffer = (BYTE *) &pszBuffer[0];
  242. szHexText[(NUM_HEXBYTES_PERLINE*2) + NUM_HEXBYTES_PERLINE-1] = 0;
  243. szASCIIText[NUM_HEXBYTES_PERLINE] = 0;
  244. #if (1) //DSIE: bug 262252
  245. if (cbData && pbData)
  246. {
  247. pb = pbData;
  248. while (pb <= &(pbData[cbData-1]))
  249. {
  250. // if we have a full line, then add the ascii characters
  251. if (((pb - pbData) % NUM_HEXBYTES_PERLINE == 0) && (pb != pbData))
  252. {
  253. szHexText[(NUM_HEXBYTES_PERLINE*2) + NUM_HEXBYTES_PERLINE-1] = 0;
  254. //
  255. // for some reason strcat is dying when the string gets REALLY long, so just do
  256. // the string cat stuff manually with memcpy.
  257. //
  258. memcpy(pbBuffer, (BYTE *) szHexText, strlen(szHexText)); pbBuffer += strlen(szHexText);//strcat(pszBuffer, szHexText);
  259. memcpy(pbBuffer, (BYTE *) " ", strlen(" ")); pbBuffer += strlen(" ");//strcat(pszBuffer, " ");
  260. memcpy(pbBuffer, (BYTE *) szASCIIText, strlen(szASCIIText)); pbBuffer += strlen(szASCIIText);//strcat(pszBuffer, szASCIIText);
  261. memcpy(pbBuffer, (BYTE *) "\n", strlen("\n")); pbBuffer += strlen("\n");//strcat(pszBuffer, "\n");
  262. dwHexTextIndex = 0;
  263. dwASCIITextIndex = 0;
  264. }
  265. szHexText[dwHexTextIndex++] = RgchHex[(*pb & 0xf0) >> 4];
  266. szHexText[dwHexTextIndex++] = RgchHex[*pb & 0x0f];
  267. // this will overwrite the null character when it is the last iteration,
  268. // so just reset the null characert before doing the strcat
  269. szHexText[dwHexTextIndex++] = ' ';
  270. szASCIIText[dwASCIITextIndex++] = (*pb >= 0x20 && *pb <= 0x7f) ? (char)*pb : '.';
  271. pb++;
  272. }
  273. //
  274. // print out the last line
  275. //
  276. // fill in with spaces if needed
  277. for (i=dwHexTextIndex; i<((NUM_HEXBYTES_PERLINE*2) + NUM_HEXBYTES_PERLINE-1); i++)
  278. {
  279. szHexText[i] = ' ';
  280. }
  281. szHexText[(NUM_HEXBYTES_PERLINE*2) + NUM_HEXBYTES_PERLINE-1] = 0;
  282. // add the null character to the proper place in the ascii buffer
  283. szASCIIText[dwASCIITextIndex] = 0;
  284. //
  285. // for some reason strcat is dying when the string gets REALLY long, so just do
  286. // the string cat stuff manually with memcpy.
  287. //
  288. memcpy(pbBuffer, (BYTE *) szHexText, strlen(szHexText)); pbBuffer += strlen(szHexText);//strcat(pszBuffer, szHexText);
  289. memcpy(pbBuffer, (BYTE *) " ", strlen(" ")); pbBuffer += strlen(" ");//strcat(pszBuffer, " ");
  290. memcpy(pbBuffer, (BYTE *) szASCIIText, strlen(szASCIIText)); pbBuffer += strlen(szASCIIText);//strcat(pszBuffer, szASCIIText);
  291. *pbBuffer = 0;
  292. }
  293. #endif
  294. SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM) pszBuffer);
  295. free(pszBuffer);
  296. return TRUE;
  297. }
  298. //////////////////////////////////////////////////////////////////////////////////////
  299. //
  300. //////////////////////////////////////////////////////////////////////////////////////
  301. BOOL FormatMemBufToString(LPWSTR *ppString, LPBYTE pbData, DWORD cbData)
  302. {
  303. DWORD i = 0;
  304. LPBYTE pb;
  305. if (NULL == (*ppString = (LPWSTR) malloc((cbData * 3) * sizeof(WCHAR))))
  306. {
  307. return FALSE;
  308. }
  309. //
  310. // copy to the buffer
  311. //
  312. pb = pbData;
  313. while (pb <= &(pbData[cbData-1]))
  314. {
  315. (*ppString)[i++] = RgwchHex[(*pb & 0xf0) >> 4];
  316. (*ppString)[i++] = RgwchHex[*pb & 0x0f];
  317. (*ppString)[i++] = L' ';
  318. pb++;
  319. }
  320. (*ppString)[--i] = 0;
  321. return TRUE;
  322. }
  323. //////////////////////////////////////////////////////////////////////////////////////
  324. //
  325. //////////////////////////////////////////////////////////////////////////////////////
  326. #define STRING_ALLOCATION_SIZE 128
  327. BOOL FormatDNNameString(LPWSTR *ppString, LPBYTE pbData, DWORD cbData, BOOL fMultiline)
  328. {
  329. CERT_NAME_INFO *pNameInfo;
  330. DWORD cbNameInfo;
  331. WCHAR szText[256];
  332. LPWSTR pwszText;
  333. int i,j;
  334. DWORD numChars = 1; // 1 for the terminating 0
  335. DWORD numAllocations = 1;
  336. void *pTemp;
  337. //
  338. // decode the dnname into a CERT_NAME_INFO struct
  339. //
  340. if (!CryptDecodeObject(
  341. X509_ASN_ENCODING,
  342. X509_UNICODE_NAME,
  343. pbData,
  344. cbData,
  345. 0,
  346. NULL,
  347. &cbNameInfo))
  348. {
  349. return FALSE;
  350. }
  351. if (NULL == (pNameInfo = (CERT_NAME_INFO *) malloc(cbNameInfo)))
  352. {
  353. return FALSE;
  354. }
  355. if (!CryptDecodeObject(
  356. X509_ASN_ENCODING,
  357. X509_UNICODE_NAME,
  358. pbData,
  359. cbData,
  360. 0,
  361. pNameInfo,
  362. &cbNameInfo))
  363. {
  364. free (pNameInfo);
  365. return FALSE;
  366. }
  367. //
  368. // allocate an initial buffer for the DN name string, then if it grows larger
  369. // than the initial amount just grow as needed
  370. //
  371. *ppString = (LPWSTR) malloc(STRING_ALLOCATION_SIZE * sizeof(WCHAR));
  372. if (*ppString == NULL)
  373. {
  374. free (pNameInfo);
  375. return FALSE;
  376. }
  377. (*ppString)[0] = 0;
  378. //
  379. // loop for each rdn and add it to the string
  380. //
  381. for (i=pNameInfo->cRDN-1; i>=0; i--)
  382. {
  383. // if this is not the first iteration, then add a eol or a ", "
  384. if (i != (int)pNameInfo->cRDN-1)
  385. {
  386. if (numChars+2 >= (numAllocations * STRING_ALLOCATION_SIZE))
  387. {
  388. pTemp = realloc(*ppString, ++numAllocations * STRING_ALLOCATION_SIZE * sizeof(WCHAR));
  389. if (pTemp == NULL)
  390. {
  391. free (pNameInfo);
  392. free (*ppString);
  393. return FALSE;
  394. }
  395. *ppString = (LPWSTR) pTemp;
  396. }
  397. if (fMultiline)
  398. wcscat(*ppString, L"\n");
  399. else
  400. wcscat(*ppString, L", ");
  401. numChars += 2;
  402. }
  403. for (j=pNameInfo->rgRDN[i].cRDNAttr-1; j>=0; j--)
  404. {
  405. // if this is not the first iteration, then add a eol or a ", "
  406. if (j != (int)pNameInfo->rgRDN[i].cRDNAttr-1)
  407. {
  408. if (numChars+2 >= (numAllocations * STRING_ALLOCATION_SIZE))
  409. {
  410. pTemp = realloc(*ppString, ++numAllocations * STRING_ALLOCATION_SIZE * sizeof(WCHAR));
  411. if (pTemp == NULL)
  412. {
  413. free (pNameInfo);
  414. free (*ppString);
  415. return FALSE;
  416. }
  417. *ppString = (LPWSTR) pTemp;
  418. }
  419. if (fMultiline)
  420. wcscat(*ppString, L"\n");
  421. else
  422. wcscat(*ppString, L", ");
  423. numChars += 2;
  424. }
  425. //
  426. // add the field name to the string if it is Multiline display
  427. //
  428. if (fMultiline)
  429. {
  430. if (!MyGetOIDInfo(szText, ARRAYSIZE(szText), pNameInfo->rgRDN[i].rgRDNAttr[j].pszObjId))
  431. {
  432. free (pNameInfo);
  433. return FALSE;
  434. }
  435. if ((numChars + wcslen(szText) + 3) >= (numAllocations * STRING_ALLOCATION_SIZE))
  436. {
  437. // increment the number of allocation blocks until it is large enough
  438. while ((numChars + wcslen(szText) + 3) >= (++numAllocations * STRING_ALLOCATION_SIZE));
  439. pTemp = realloc(*ppString, numAllocations * STRING_ALLOCATION_SIZE * sizeof(WCHAR));
  440. if (pTemp == NULL)
  441. {
  442. free (pNameInfo);
  443. free (*ppString);
  444. return FALSE;
  445. }
  446. *ppString = (LPWSTR) pTemp;
  447. }
  448. numChars += wcslen(szText) + 3;
  449. wcscat(*ppString, szText);
  450. wcscat(*ppString, L" = "); // delimiter
  451. }
  452. //
  453. // add the value to the string
  454. //
  455. if (CERT_RDN_ENCODED_BLOB == pNameInfo->rgRDN[i].rgRDNAttr[j].dwValueType ||
  456. CERT_RDN_OCTET_STRING == pNameInfo->rgRDN[i].rgRDNAttr[j].dwValueType)
  457. {
  458. // translate the buffer to a text string and display it that way
  459. if (FormatMemBufToString(
  460. &pwszText,
  461. pNameInfo->rgRDN[i].rgRDNAttr[j].Value.pbData,
  462. pNameInfo->rgRDN[i].rgRDNAttr[j].Value.cbData))
  463. {
  464. if ((numChars + wcslen(pwszText)) >= (numAllocations * STRING_ALLOCATION_SIZE))
  465. {
  466. // increment the number of allocation blocks until it is large enough
  467. while ((numChars + wcslen(pwszText)) >= (++numAllocations * STRING_ALLOCATION_SIZE));
  468. pTemp = realloc(*ppString, numAllocations * STRING_ALLOCATION_SIZE * sizeof(WCHAR));
  469. if (pTemp == NULL)
  470. {
  471. free (pwszText);
  472. free (pNameInfo);
  473. free (*ppString);
  474. return FALSE;
  475. }
  476. *ppString = (LPWSTR) pTemp;
  477. }
  478. wcscat(*ppString, pwszText);
  479. numChars += wcslen(pwszText);
  480. free (pwszText);
  481. }
  482. }
  483. else
  484. {
  485. // buffer is already a string so just copy it
  486. if ((numChars + (pNameInfo->rgRDN[i].rgRDNAttr[j].Value.cbData/sizeof(WCHAR)))
  487. >= (numAllocations * STRING_ALLOCATION_SIZE))
  488. {
  489. // increment the number of allocation blocks until it is large enough
  490. while ((numChars + (pNameInfo->rgRDN[i].rgRDNAttr[j].Value.cbData/sizeof(WCHAR)))
  491. >= (++numAllocations * STRING_ALLOCATION_SIZE));
  492. pTemp = realloc(*ppString, numAllocations * STRING_ALLOCATION_SIZE * sizeof(WCHAR));
  493. if (pTemp == NULL)
  494. {
  495. free (pNameInfo);
  496. free (*ppString);
  497. return FALSE;
  498. }
  499. *ppString = (LPWSTR) pTemp;
  500. }
  501. wcscat(*ppString, (LPWSTR) pNameInfo->rgRDN[i].rgRDNAttr[j].Value.pbData);
  502. numChars += (pNameInfo->rgRDN[i].rgRDNAttr[j].Value.cbData/sizeof(WCHAR));
  503. }
  504. }
  505. }
  506. free (pNameInfo);
  507. return TRUE;
  508. }
  509. //////////////////////////////////////////////////////////////////////////////////////
  510. //
  511. //////////////////////////////////////////////////////////////////////////////////////
  512. BOOL FormatEnhancedKeyUsageString(LPWSTR *ppString, PCCERT_CONTEXT pCertContext, BOOL fPropertiesOnly, BOOL fMultiline)
  513. {
  514. CERT_ENHKEY_USAGE *pKeyUsage = NULL;
  515. DWORD cbKeyUsage = 0;
  516. DWORD numChars = 1;
  517. WCHAR szText[CRYPTUI_MAX_STRING_SIZE];
  518. DWORD i;
  519. //
  520. // Try to get the enhanced key usage property
  521. //
  522. if (!CertGetEnhancedKeyUsage ( pCertContext,
  523. fPropertiesOnly ? CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG : 0,
  524. NULL,
  525. &cbKeyUsage))
  526. {
  527. return FALSE;
  528. }
  529. if (NULL == (pKeyUsage = (CERT_ENHKEY_USAGE *) malloc(cbKeyUsage)))
  530. {
  531. return FALSE;
  532. }
  533. if (!CertGetEnhancedKeyUsage ( pCertContext,
  534. fPropertiesOnly ? CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG : 0,
  535. pKeyUsage,
  536. &cbKeyUsage))
  537. {
  538. free(pKeyUsage);
  539. return FALSE;
  540. }
  541. if (pKeyUsage->cUsageIdentifier == 0)
  542. {
  543. free (pKeyUsage);
  544. if (GetLastError() == CRYPT_E_NOT_FOUND)
  545. {
  546. LoadStringU(HinstDll, IDS_ALL_FIELDS, szText, ARRAYSIZE(szText));
  547. if (NULL == (*ppString = AllocAndCopyWStr(szText)))
  548. {
  549. return FALSE;
  550. }
  551. else
  552. {
  553. return TRUE;
  554. }
  555. }
  556. else
  557. {
  558. LoadStringU(HinstDll, IDS_NO_USAGES, szText, ARRAYSIZE(szText));
  559. if (NULL == (*ppString = AllocAndCopyWStr(szText)))
  560. {
  561. return FALSE;
  562. }
  563. else
  564. {
  565. return TRUE;
  566. }
  567. }
  568. }
  569. //
  570. // calculate size
  571. //
  572. // loop for each usage and add it to the display string
  573. for (i=0; i<pKeyUsage->cUsageIdentifier; i++)
  574. {
  575. if (MyGetOIDInfo(szText, ARRAYSIZE(szText), pKeyUsage->rgpszUsageIdentifier[i]))
  576. {
  577. // add delimeter if not first iteration
  578. if (i != 0)
  579. {
  580. numChars += 2;
  581. }
  582. numChars += wcslen(szText);
  583. }
  584. else
  585. {
  586. free (pKeyUsage);
  587. return FALSE;
  588. }
  589. }
  590. if (NULL == (*ppString = (LPWSTR) malloc((numChars+1) * sizeof(WCHAR))))
  591. {
  592. free (pKeyUsage);
  593. return FALSE;
  594. }
  595. //
  596. // copy to buffer
  597. //
  598. (*ppString)[0] = 0;
  599. // loop for each usage and add it to the display string
  600. for (i=0; i<pKeyUsage->cUsageIdentifier; i++)
  601. {
  602. if (MyGetOIDInfo(szText, ARRAYSIZE(szText), pKeyUsage->rgpszUsageIdentifier[i]))
  603. {
  604. // add delimeter if not first iteration
  605. if (i != 0)
  606. {
  607. if (fMultiline)
  608. wcscat(*ppString, L"\n");
  609. else
  610. wcscat(*ppString, L", ");
  611. numChars += 2;
  612. }
  613. // add the enhanced key usage string
  614. wcscat(*ppString, szText);
  615. numChars += wcslen(szText);
  616. }
  617. else
  618. {
  619. free (pKeyUsage);
  620. return FALSE;
  621. }
  622. }
  623. free (pKeyUsage);
  624. return TRUE;
  625. }
  626. //////////////////////////////////////////////////////////////////////////////////////
  627. //
  628. //////////////////////////////////////////////////////////////////////////////////////
  629. LPWSTR AllocAndReturnSignTime(CMSG_SIGNER_INFO const *pSignerInfo, FILETIME **ppSignTime, HWND hwnd)
  630. {
  631. DWORD i;
  632. BOOL fFound = FALSE;
  633. FILETIME *pFileTime = NULL;
  634. DWORD cbFileTime = 0;
  635. LPWSTR pszReturn = NULL;
  636. if (ppSignTime != NULL)
  637. {
  638. *ppSignTime = NULL;
  639. }
  640. //
  641. // loop for each authenticated attribute
  642. //
  643. i=0;
  644. while ((!fFound) && (i<pSignerInfo->AuthAttrs.cAttr))
  645. {
  646. if (!(strcmp(pSignerInfo->AuthAttrs.rgAttr[i].pszObjId, szOID_RSA_signingTime) == 0))
  647. {
  648. i++;
  649. continue;
  650. }
  651. assert(pSignerInfo->AuthAttrs.rgAttr[i].cValue == 1);
  652. fFound = TRUE;
  653. //decode the EncodedSigner info
  654. if(!CryptDecodeObject(PKCS_7_ASN_ENCODING|CRYPT_ASN_ENCODING,
  655. PKCS_UTC_TIME,
  656. pSignerInfo->AuthAttrs.rgAttr[i].rgValue[0].pbData,
  657. pSignerInfo->AuthAttrs.rgAttr[i].rgValue[0].cbData,
  658. 0,
  659. NULL,
  660. &cbFileTime))
  661. {
  662. return NULL;
  663. }
  664. if (NULL == (pFileTime = (FILETIME *) malloc(cbFileTime)))
  665. {
  666. return NULL;
  667. }
  668. if(!CryptDecodeObject(PKCS_7_ASN_ENCODING|CRYPT_ASN_ENCODING,
  669. PKCS_UTC_TIME,
  670. pSignerInfo->AuthAttrs.rgAttr[i].rgValue[0].pbData,
  671. pSignerInfo->AuthAttrs.rgAttr[i].rgValue[0].cbData,
  672. 0,
  673. pFileTime,
  674. &cbFileTime))
  675. {
  676. return NULL;
  677. }
  678. //
  679. // return the sign time if the caller wants it, otherwise format the string and return it
  680. //
  681. if (ppSignTime)
  682. {
  683. if (NULL != (*ppSignTime = (FILETIME *) malloc(sizeof(FILETIME))))
  684. {
  685. memcpy(*ppSignTime, pFileTime, sizeof(FILETIME));
  686. }
  687. }
  688. else if (!FormatDateString(&pszReturn, *pFileTime, TRUE, TRUE, hwnd))
  689. {
  690. free(pFileTime);
  691. return NULL;
  692. }
  693. }
  694. if (pFileTime != NULL)
  695. {
  696. free(pFileTime);
  697. }
  698. return(pszReturn);
  699. }
  700. //////////////////////////////////////////////////////////////////////////////////////
  701. //
  702. //////////////////////////////////////////////////////////////////////////////////////
  703. LPWSTR AllocAndReturnTimeStampersTimes(CMSG_SIGNER_INFO const *pSignerInfo, FILETIME **ppSignTime, HWND hwnd)
  704. {
  705. PCMSG_SIGNER_INFO pCounterSignerInfo;
  706. DWORD cbCounterSignerInfo;
  707. DWORD i;
  708. LPWSTR pszReturnText = NULL;
  709. LPWSTR pszTimeText = NULL;
  710. void *pTemp;
  711. if (ppSignTime != NULL)
  712. {
  713. *ppSignTime = NULL;
  714. }
  715. for (i=0; i<pSignerInfo->UnauthAttrs.cAttr; i++)
  716. {
  717. if (!(strcmp(pSignerInfo->UnauthAttrs.rgAttr[i].pszObjId, szOID_RSA_counterSign) == 0))
  718. {
  719. continue;
  720. }
  721. assert(pSignerInfo->UnauthAttrs.rgAttr[i].cValue == 1);
  722. //decode the EncodedSigner info
  723. if(!CryptDecodeObject(PKCS_7_ASN_ENCODING|CRYPT_ASN_ENCODING,
  724. PKCS7_SIGNER_INFO,
  725. pSignerInfo->UnauthAttrs.rgAttr[i].rgValue[0].pbData,
  726. pSignerInfo->UnauthAttrs.rgAttr[i].rgValue[0].cbData,
  727. 0,
  728. NULL,
  729. &cbCounterSignerInfo))
  730. {
  731. return NULL;
  732. }
  733. if (NULL == (pCounterSignerInfo = (PCMSG_SIGNER_INFO)malloc(cbCounterSignerInfo)))
  734. {
  735. return NULL;
  736. }
  737. if(!CryptDecodeObject(PKCS_7_ASN_ENCODING|CRYPT_ASN_ENCODING,
  738. PKCS7_SIGNER_INFO,
  739. pSignerInfo->UnauthAttrs.rgAttr[i].rgValue[0].pbData,
  740. pSignerInfo->UnauthAttrs.rgAttr[i].rgValue[0].cbData,
  741. 0,
  742. pCounterSignerInfo,
  743. &cbCounterSignerInfo))
  744. {
  745. free(pCounterSignerInfo);
  746. return NULL;
  747. }
  748. if (ppSignTime != NULL)
  749. {
  750. //
  751. // break after this which means we just get the first time stamp time,
  752. // but reallistically there should only be one anyway.
  753. //
  754. AllocAndReturnSignTime(pCounterSignerInfo, ppSignTime, hwnd);
  755. free(pCounterSignerInfo);
  756. break;
  757. }
  758. else
  759. {
  760. pszTimeText = AllocAndReturnSignTime(pCounterSignerInfo, NULL, hwnd);
  761. if (pszReturnText == NULL)
  762. {
  763. pszReturnText = pszTimeText;
  764. }
  765. else if (pszTimeText != NULL)
  766. {
  767. pTemp = realloc(pszReturnText,
  768. (wcslen(pszReturnText) + wcslen(pszTimeText) + wcslen(L", ") + 1) * sizeof(WCHAR));
  769. if (pTemp == NULL)
  770. {
  771. free(pszTimeText);
  772. free(pszReturnText);
  773. return NULL;
  774. }
  775. pszReturnText = (LPWSTR) pTemp;
  776. wcscat(pszReturnText, L", ");
  777. wcscat(pszReturnText, pszTimeText);
  778. free(pszTimeText);
  779. }
  780. }
  781. free(pCounterSignerInfo);
  782. }
  783. //
  784. // if there were no counter signers, then use the time in the original signer info
  785. //
  786. if ((pszReturnText == NULL) && (ppSignTime == NULL))
  787. {
  788. pszReturnText = AllocAndReturnSignTime(pSignerInfo, NULL, hwnd);
  789. }
  790. return(pszReturnText);
  791. }
  792. //////////////////////////////////////////////////////////////////////////////////////
  793. //
  794. //////////////////////////////////////////////////////////////////////////////////////
  795. LPWSTR FormatCTLSubjectUsage(CTL_USAGE *pSubjectUsage, BOOL fMultiline)
  796. {
  797. DWORD i;
  798. WCHAR szText[CRYPTUI_MAX_STRING_SIZE];
  799. LPWSTR pwszText = NULL;
  800. void *pTemp;
  801. for (i=0; i<pSubjectUsage->cUsageIdentifier; i++)
  802. {
  803. if (!MyGetOIDInfo(szText, ARRAYSIZE(szText), pSubjectUsage->rgpszUsageIdentifier[i]))
  804. {
  805. continue;
  806. }
  807. if (pwszText == NULL)
  808. {
  809. pwszText = AllocAndCopyWStr(szText);
  810. }
  811. else
  812. {
  813. pTemp = realloc(pwszText, (wcslen(szText) + wcslen(pwszText) + 3) * sizeof(WCHAR));
  814. if (pTemp != NULL)
  815. {
  816. pwszText = (LPWSTR) pTemp;
  817. if (fMultiline)
  818. {
  819. wcscat(pwszText, L"\n");
  820. }
  821. else
  822. {
  823. wcscat(pwszText, L", ");
  824. }
  825. wcscat(pwszText, szText);
  826. }
  827. else
  828. {
  829. free(pwszText);
  830. return NULL;
  831. }
  832. }
  833. }
  834. return pwszText;
  835. }