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.

1293 lines
25 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: celib.cpp
  8. //
  9. // Contents: helper functions
  10. //
  11. //--------------------------------------------------------------------------
  12. #include "pch.cpp"
  13. #pragma hdrstop
  14. #include "celib.h"
  15. #include <assert.h>
  16. //+--------------------------------------------------------------------------
  17. // ceDecodeObject -- call CryptDecodeObject, and allocate memory for output
  18. //
  19. //+--------------------------------------------------------------------------
  20. BOOL
  21. ceDecodeObject(
  22. IN DWORD dwEncodingType,
  23. IN LPCSTR lpszStructType,
  24. IN BYTE const *pbEncoded,
  25. IN DWORD cbEncoded,
  26. IN BOOL fCoTaskMemAlloc,
  27. OUT VOID **ppvStructInfo,
  28. OUT DWORD *pcbStructInfo)
  29. {
  30. BOOL b;
  31. assert(!fCoTaskMemAlloc);
  32. *ppvStructInfo = NULL;
  33. *pcbStructInfo = 0;
  34. while (TRUE)
  35. {
  36. b = CryptDecodeObject(
  37. dwEncodingType,
  38. lpszStructType,
  39. pbEncoded,
  40. cbEncoded,
  41. 0, // dwFlags
  42. *ppvStructInfo,
  43. pcbStructInfo);
  44. if (b && 0 == *pcbStructInfo)
  45. {
  46. SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_DATA));
  47. b = FALSE;
  48. }
  49. if (!b)
  50. {
  51. if (NULL != *ppvStructInfo)
  52. {
  53. HRESULT hr = GetLastError();
  54. LocalFree(*ppvStructInfo);
  55. *ppvStructInfo = NULL;
  56. SetLastError(hr);
  57. }
  58. break;
  59. }
  60. if (NULL != *ppvStructInfo)
  61. {
  62. break;
  63. }
  64. *ppvStructInfo = (BYTE *) LocalAlloc(LMEM_FIXED, *pcbStructInfo);
  65. if (NULL == *ppvStructInfo)
  66. {
  67. b = FALSE;
  68. break;
  69. }
  70. }
  71. return(b);
  72. }
  73. BOOL
  74. ceEncodeObject(
  75. IN DWORD dwEncodingType,
  76. IN LPCSTR lpszStructType,
  77. IN VOID const *pvStructInfo,
  78. IN DWORD dwFlags,
  79. IN BOOL fCoTaskMemAlloc,
  80. OUT BYTE **ppbEncoded,
  81. OUT DWORD *pcbEncoded)
  82. {
  83. BOOL b;
  84. assert(0 == dwFlags);
  85. assert(!fCoTaskMemAlloc);
  86. *ppbEncoded = NULL;
  87. *pcbEncoded = 0;
  88. while (TRUE)
  89. {
  90. b = CryptEncodeObject(
  91. dwEncodingType,
  92. lpszStructType,
  93. const_cast<VOID *>(pvStructInfo),
  94. *ppbEncoded,
  95. pcbEncoded);
  96. if (b && 0 == *pcbEncoded)
  97. {
  98. SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_DATA));
  99. b = FALSE;
  100. }
  101. if (!b)
  102. {
  103. if (NULL != *ppbEncoded)
  104. {
  105. HRESULT hr = GetLastError();
  106. LocalFree(*ppbEncoded);
  107. *ppbEncoded = NULL;
  108. SetLastError(hr);
  109. }
  110. break;
  111. }
  112. if (NULL != *ppbEncoded)
  113. {
  114. break;
  115. }
  116. *ppbEncoded = (BYTE *) LocalAlloc(LMEM_FIXED, *pcbEncoded);
  117. if (NULL == *ppbEncoded)
  118. {
  119. b = FALSE;
  120. break;
  121. }
  122. }
  123. return(b);
  124. }
  125. // The returned pszObjId is a constant that must not be freed. CryptFindOIDInfo
  126. // has a static internal database that is valid until crypt32.dll is unloaded.
  127. WCHAR const *
  128. ceGetOIDNameA(
  129. IN char const *pszObjId)
  130. {
  131. CRYPT_OID_INFO const *pInfo = NULL;
  132. WCHAR const *pwszName = L"";
  133. // First try looking up the ObjectId as an Extension or Attribute, because
  134. // we get a better Display Name, especially for Subject RDNs: CN, L, etc.
  135. // If that fails, look it up withoput restricting the group.
  136. pInfo = CryptFindOIDInfo(
  137. CRYPT_OID_INFO_OID_KEY,
  138. (VOID *) pszObjId,
  139. CRYPT_EXT_OR_ATTR_OID_GROUP_ID);
  140. if (NULL == pInfo || NULL == pInfo->pwszName || L'\0' == pInfo->pwszName[0])
  141. {
  142. pInfo = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, (VOID *) pszObjId, 0);
  143. }
  144. if (NULL != pInfo && NULL != pInfo->pwszName && L'\0' != pInfo->pwszName[0])
  145. {
  146. pwszName = pInfo->pwszName;
  147. }
  148. return(pwszName);
  149. }
  150. WCHAR const *
  151. ceGetOIDName(
  152. IN WCHAR const *pwszObjId)
  153. {
  154. char *pszObjId = NULL;
  155. WCHAR const *pwszName = L"";
  156. if (!ceConvertWszToSz(&pszObjId, pwszObjId, -1))
  157. {
  158. _JumpError(E_OUTOFMEMORY, error, "ceConvertWszToSz");
  159. }
  160. pwszName = ceGetOIDNameA(pszObjId);
  161. error:
  162. if (NULL != pszObjId)
  163. {
  164. LocalFree(pszObjId);
  165. }
  166. return(pwszName);
  167. }
  168. WCHAR *
  169. ceDuplicateString(
  170. IN WCHAR const *pwsz)
  171. {
  172. WCHAR *pwszOut;
  173. pwszOut = (WCHAR *) LocalAlloc(
  174. LMEM_FIXED,
  175. (wcslen(pwsz) + 1) * sizeof(pwsz[0]));
  176. if (NULL != pwszOut)
  177. {
  178. wcscpy(pwszOut, pwsz);
  179. }
  180. return(pwszOut);
  181. }
  182. BOOL
  183. ceConvertWszToSz(
  184. OUT CHAR **ppsz,
  185. IN WCHAR const *pwc,
  186. IN LONG cwc)
  187. {
  188. BOOL fOk = FALSE;
  189. LONG cch = 0;
  190. *ppsz = NULL;
  191. while (TRUE)
  192. {
  193. cch = WideCharToMultiByte(
  194. GetACP(),
  195. 0, // dwFlags
  196. pwc,
  197. cwc, // cchWideChar, -1 => null terminated
  198. *ppsz,
  199. cch,
  200. NULL,
  201. NULL);
  202. if (0 >= cch)
  203. {
  204. DWORD err;
  205. err = GetLastError();
  206. ceERRORPRINTLINE("WideCharToMultiByte", err);
  207. if (NULL != *ppsz)
  208. {
  209. LocalFree(*ppsz);
  210. *ppsz = NULL;
  211. }
  212. break;
  213. }
  214. if (NULL != *ppsz)
  215. {
  216. fOk = TRUE;
  217. break;
  218. }
  219. *ppsz = (CHAR *) LocalAlloc(LMEM_FIXED, cch + 1);
  220. if (NULL == *ppsz)
  221. {
  222. break;
  223. }
  224. }
  225. return(fOk);
  226. }
  227. BOOL
  228. ceConvertWszToBstr(
  229. OUT BSTR *pbstr,
  230. IN WCHAR const *pwc,
  231. IN LONG cb)
  232. {
  233. BOOL fOk = FALSE;
  234. BSTR bstr;
  235. ceFreeBstr(pbstr);
  236. do
  237. {
  238. bstr = NULL;
  239. if (NULL != pwc)
  240. {
  241. if (-1 == cb)
  242. {
  243. cb = wcslen(pwc) * sizeof(WCHAR);
  244. }
  245. bstr = SysAllocStringByteLen((char const *) pwc, cb);
  246. if (NULL == bstr)
  247. {
  248. break;
  249. }
  250. }
  251. *pbstr = bstr;
  252. fOk = TRUE;
  253. } while (FALSE);
  254. return(fOk);
  255. }
  256. BOOL
  257. ceConvertSzToWsz(
  258. OUT WCHAR **ppwsz,
  259. IN char const *pch,
  260. IN LONG cch)
  261. {
  262. BOOL fOk = FALSE;
  263. LONG cwc = 0;
  264. *ppwsz = NULL;
  265. while (TRUE)
  266. {
  267. cwc = MultiByteToWideChar(GetACP(), 0, pch, cch, *ppwsz, cwc);
  268. if (0 >= cwc)
  269. {
  270. DWORD err;
  271. err = GetLastError();
  272. ceERRORPRINTLINE("MultiByteToWideChar", err);
  273. if (NULL != *ppwsz)
  274. {
  275. LocalFree(*ppwsz);
  276. *ppwsz = NULL;
  277. }
  278. break;
  279. }
  280. if (NULL != *ppwsz)
  281. {
  282. fOk = TRUE;
  283. break;
  284. }
  285. *ppwsz = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
  286. if (NULL == *ppwsz)
  287. {
  288. break;
  289. }
  290. }
  291. return(fOk);
  292. }
  293. BOOL
  294. ceConvertSzToBstr(
  295. OUT BSTR *pbstr,
  296. IN CHAR const *pch,
  297. IN LONG cch)
  298. {
  299. BOOL fOk = FALSE;
  300. BSTR bstr = NULL;
  301. LONG cwc = 0;
  302. ceFreeBstr(pbstr);
  303. if (-1 == cch)
  304. {
  305. cch = strlen(pch);
  306. }
  307. while (TRUE)
  308. {
  309. cwc = MultiByteToWideChar(GetACP(), 0, pch, cch, bstr, cwc);
  310. if (0 >= cwc)
  311. {
  312. //hr = ceHLastError();
  313. //printf("MultiByteToWideChar returned %d (%x)\n", hr, hr);
  314. break;
  315. }
  316. if (NULL != bstr)
  317. {
  318. bstr[cwc] = L'\0';
  319. *pbstr = bstr;
  320. fOk = TRUE;
  321. break;
  322. }
  323. bstr = SysAllocStringLen(NULL, cwc);
  324. if (NULL == bstr)
  325. {
  326. break;
  327. }
  328. }
  329. return(fOk);
  330. }
  331. VOID
  332. ceFreeBstr(
  333. IN OUT BSTR *pstr)
  334. {
  335. if (NULL != *pstr)
  336. {
  337. SysFreeString(*pstr);
  338. *pstr = NULL;
  339. }
  340. }
  341. HRESULT
  342. ceHError(
  343. IN HRESULT hr)
  344. {
  345. assert(S_FALSE != hr);
  346. if (S_OK != hr && S_FALSE != hr && !FAILED(hr))
  347. {
  348. hr = HRESULT_FROM_WIN32(hr);
  349. if ((HRESULT) 0 == HRESULT_CODE(hr))
  350. {
  351. // A call failed without properly setting an error condition!
  352. hr = E_UNEXPECTED;
  353. }
  354. assert(FAILED(hr));
  355. }
  356. return(hr);
  357. }
  358. HRESULT
  359. ceHLastError(VOID)
  360. {
  361. return(ceHError(GetLastError()));
  362. }
  363. VOID
  364. ceErrorPrintLine(
  365. IN char const *pszFile,
  366. IN DWORD line,
  367. IN char const *pszMessage,
  368. IN WCHAR const *pwszData,
  369. IN HRESULT hr)
  370. {
  371. CHAR ach[4096];
  372. DWORD cch;
  373. cch = _snprintf(
  374. ach,
  375. sizeof(ach),
  376. "CeLib: Error: %hs(%u): %hs%hs%ws%hs 0x%x (%d)\n",
  377. pszFile,
  378. line,
  379. pszMessage,
  380. NULL == pwszData? "" : szLPAREN,
  381. NULL == pwszData? L"" : pwszData,
  382. NULL == pwszData? "" : szRPAREN,
  383. hr,
  384. hr);
  385. if (0 < cch)
  386. {
  387. strcpy(&ach[sizeof(ach) - 5], "...\n");
  388. }
  389. OutputDebugStringA(ach);
  390. wprintf(L"%hs", ach);
  391. }
  392. HRESULT
  393. ceDateToFileTime(
  394. IN DATE const *pDate,
  395. OUT FILETIME *pft)
  396. {
  397. SYSTEMTIME st;
  398. HRESULT hr = S_OK;
  399. if (*pDate == 0.0)
  400. {
  401. GetSystemTime(&st);
  402. }
  403. else
  404. {
  405. if (!VariantTimeToSystemTime(*pDate, &st))
  406. {
  407. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  408. _JumpError(hr, error, "VariantTimeToSystemTime");
  409. }
  410. }
  411. if (!SystemTimeToFileTime(&st, pft))
  412. {
  413. hr = ceHLastError();
  414. _JumpError(hr, error, "SystemTimeToFileTime");
  415. }
  416. error:
  417. return(hr);
  418. }
  419. HRESULT
  420. ceFileTimeToDate(
  421. IN FILETIME const *pft,
  422. OUT DATE *pDate)
  423. {
  424. SYSTEMTIME st;
  425. HRESULT hr = S_OK;
  426. if (!FileTimeToSystemTime(pft, &st))
  427. {
  428. hr = ceHLastError();
  429. _JumpError(hr, error, "FileTimeToSystemTime");
  430. }
  431. if (!SystemTimeToVariantTime(&st, pDate))
  432. {
  433. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  434. _JumpError(hr, error, "SystemTimeToVariantTime");
  435. }
  436. error:
  437. return(hr);
  438. }
  439. VOID
  440. ceMakeExprDateTime(
  441. IN OUT FILETIME *pft,
  442. IN LONG lDelta,
  443. IN enum ENUM_PERIOD enumPeriod)
  444. {
  445. LLFILETIME llft;
  446. LONGLONG llDelta;
  447. BOOL fSysTimeDelta;
  448. llft.ft = *pft;
  449. llDelta = lDelta;
  450. fSysTimeDelta = FALSE;
  451. switch (enumPeriod)
  452. {
  453. case ENUM_PERIOD_WEEKS: llDelta *= CVT_WEEKS; break;
  454. case ENUM_PERIOD_DAYS: llDelta *= CVT_DAYS; break;
  455. case ENUM_PERIOD_HOURS: llDelta *= CVT_HOURS; break;
  456. case ENUM_PERIOD_MINUTES: llDelta *= CVT_MINUTES; break;
  457. case ENUM_PERIOD_SECONDS: break;
  458. default:
  459. fSysTimeDelta = TRUE;
  460. break;
  461. }
  462. if (fSysTimeDelta)
  463. {
  464. SYSTEMTIME SystemTime;
  465. FileTimeToSystemTime(&llft.ft, &SystemTime);
  466. switch (enumPeriod)
  467. {
  468. case ENUM_PERIOD_MONTHS:
  469. if (0 > lDelta)
  470. {
  471. DWORD dwDelta = (DWORD) -lDelta;
  472. SystemTime.wYear -= (WORD) (dwDelta / 12) + 1;
  473. SystemTime.wMonth += 12 - (WORD) (dwDelta % 12);
  474. }
  475. else
  476. {
  477. SystemTime.wMonth += (WORD) lDelta;
  478. }
  479. if (12 < SystemTime.wMonth)
  480. {
  481. SystemTime.wYear += (SystemTime.wMonth - 1) / 12;
  482. SystemTime.wMonth = ((SystemTime.wMonth - 1) % 12) + 1;
  483. }
  484. break;
  485. case ENUM_PERIOD_YEARS:
  486. SystemTime.wYear += (WORD) lDelta;
  487. break;
  488. default:
  489. SystemTime.wYear += 1;
  490. break;
  491. }
  492. DoConvert:
  493. if (!SystemTimeToFileTime(&SystemTime, &llft.ft))
  494. {
  495. if (GetLastError() != ERROR_INVALID_PARAMETER)
  496. {
  497. assert(!"Unable to do time conversion");
  498. return;
  499. }
  500. // In some cases we'll convert to an invalid month-end
  501. // only one month changes length from year to year
  502. if (SystemTime.wMonth == 2)
  503. {
  504. // > 29? try leap year
  505. if (SystemTime.wDay > 29)
  506. {
  507. SystemTime.wDay = 29;
  508. goto DoConvert;
  509. }
  510. // == 29? try non-leap year
  511. else if (SystemTime.wDay == 29)
  512. {
  513. SystemTime.wDay = 28;
  514. goto DoConvert;
  515. }
  516. }
  517. // sept (9), apr(4), jun(6), nov(11) all have 30 days
  518. else if ((SystemTime.wMonth == 9) ||
  519. (SystemTime.wMonth == 4) ||
  520. (SystemTime.wMonth == 6) ||
  521. (SystemTime.wMonth == 11))
  522. {
  523. if (SystemTime.wDay > 30)
  524. {
  525. SystemTime.wDay = 30;
  526. goto DoConvert;
  527. }
  528. }
  529. // should never get here
  530. assert(!"Month/year processing: inaccessible code");
  531. return;
  532. }
  533. }
  534. else
  535. {
  536. llft.ll += llDelta * CVT_BASE;
  537. }
  538. *pft = llft.ft;
  539. }
  540. HRESULT
  541. ceMakeExprDate(
  542. IN OUT DATE *pDate,
  543. IN LONG lDelta,
  544. IN enum ENUM_PERIOD enumPeriod)
  545. {
  546. HRESULT hr;
  547. FILETIME ft;
  548. hr = ceDateToFileTime(pDate, &ft);
  549. _JumpIfError(hr, error, "ceDateToFileTime");
  550. ceMakeExprDateTime(&ft, lDelta, enumPeriod);
  551. hr = ceFileTimeToDate(&ft, pDate);
  552. _JumpIfError(hr, error, "ceFileTimeToDate");
  553. error:
  554. return(hr);
  555. }
  556. typedef struct _UNITSTABLE
  557. {
  558. WCHAR const *pwszString;
  559. enum ENUM_PERIOD enumPeriod;
  560. } UNITSTABLE;
  561. UNITSTABLE g_aut[] =
  562. {
  563. { wszPERIODSECONDS, ENUM_PERIOD_SECONDS },
  564. { wszPERIODMINUTES, ENUM_PERIOD_MINUTES },
  565. { wszPERIODHOURS, ENUM_PERIOD_HOURS },
  566. { wszPERIODDAYS, ENUM_PERIOD_DAYS },
  567. { wszPERIODWEEKS, ENUM_PERIOD_WEEKS },
  568. { wszPERIODMONTHS, ENUM_PERIOD_MONTHS },
  569. { wszPERIODYEARS, ENUM_PERIOD_YEARS },
  570. };
  571. #define CUNITSTABLEMAX (sizeof(g_aut)/sizeof(g_aut[0]))
  572. HRESULT
  573. ceTranslatePeriodUnits(
  574. IN WCHAR const *pwszPeriod,
  575. IN LONG lCount,
  576. OUT enum ENUM_PERIOD *penumPeriod,
  577. OUT LONG *plCount)
  578. {
  579. HRESULT hr;
  580. UNITSTABLE const *put;
  581. for (put = g_aut; put < &g_aut[CUNITSTABLEMAX]; put++)
  582. {
  583. if (0 == lstrcmpi(pwszPeriod, put->pwszString))
  584. {
  585. *penumPeriod = put->enumPeriod;
  586. if (0 > lCount)
  587. {
  588. lCount = MAXLONG;
  589. }
  590. *plCount = lCount;
  591. hr = S_OK;
  592. goto error;
  593. }
  594. }
  595. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  596. error:
  597. return(hr);
  598. }
  599. //+-------------------------------------------------------------------------
  600. // ceVerifyObjIdA - verify the passed pszObjId is valid as per X.208
  601. //
  602. // Encode and Decode the Object Id and make sure it suvives the round trip.
  603. // The first number must be 0, 1 or 2.
  604. // Enforce all characters are digits and dots.
  605. // Enforce that no dot starts or ends the Object Id, and disallow double dots.
  606. // Enforce there is at least one dot separator.
  607. // If the first number is 0 or 1, the second number must be between 0 & 39.
  608. // If the first number is 2, the second number can be any value.
  609. //--------------------------------------------------------------------------
  610. HRESULT
  611. ceVerifyObjIdA(
  612. IN CHAR const *pszObjId)
  613. {
  614. HRESULT hr;
  615. BYTE *pbEncoded = NULL;
  616. DWORD cbEncoded;
  617. CRYPT_ATTRIBUTE ainfo;
  618. CRYPT_ATTRIBUTE *painfo = NULL;
  619. DWORD cbainfo;
  620. char const *psz;
  621. int i;
  622. ainfo.pszObjId = const_cast<char *>(pszObjId);
  623. ainfo.cValue = 0;
  624. ainfo.rgValue = NULL;
  625. if (!ceEncodeObject(
  626. X509_ASN_ENCODING,
  627. PKCS_ATTRIBUTE,
  628. &ainfo,
  629. 0,
  630. FALSE,
  631. &pbEncoded,
  632. &cbEncoded))
  633. {
  634. hr = ceHLastError();
  635. _JumpError(hr, error, "ceEncodeObject");
  636. }
  637. if (!ceDecodeObject(
  638. X509_ASN_ENCODING,
  639. PKCS_ATTRIBUTE,
  640. pbEncoded,
  641. cbEncoded,
  642. FALSE,
  643. (VOID **) &painfo,
  644. &cbainfo))
  645. {
  646. hr = ceHLastError();
  647. _JumpError(hr, error, "ceDecodeObject");
  648. }
  649. hr = E_INVALIDARG;
  650. if (0 != strcmp(ainfo.pszObjId, painfo->pszObjId))
  651. {
  652. _JumpError(hr, error, "bad ObjId: decode mismatch");
  653. }
  654. for (psz = painfo->pszObjId; '\0' != *psz; psz++)
  655. {
  656. // must be a digit or a dot separator
  657. if (!isdigit(*psz))
  658. {
  659. if ('.' != *psz)
  660. {
  661. _JumpError(hr, error, "bad ObjId: bad char");
  662. }
  663. // can't have dot at start, double dots or dot at end
  664. if (psz == painfo->pszObjId || '.' == psz[1] || '\0' == psz[1])
  665. {
  666. _JumpError(hr, error, "bad ObjId: dot location");
  667. }
  668. }
  669. }
  670. psz = strchr(painfo->pszObjId, '.');
  671. if (NULL == psz)
  672. {
  673. _JumpError(hr, error, "bad ObjId: must have at least one dot");
  674. }
  675. i = atoi(painfo->pszObjId);
  676. switch (i)
  677. {
  678. case 0:
  679. case 1:
  680. i = atoi(++psz);
  681. if (0 > i || 39 < i)
  682. {
  683. _JumpError(hr, error, "bad ObjId: 0. or 1. must be followed by 0..39");
  684. }
  685. break;
  686. case 2:
  687. break;
  688. default:
  689. _JumpError(hr, error, "bad ObjId: must start with 0, 1 or 2");
  690. }
  691. hr = S_OK;
  692. error:
  693. if (NULL != pbEncoded)
  694. {
  695. LocalFree(pbEncoded);
  696. }
  697. if (NULL != painfo)
  698. {
  699. LocalFree(painfo);
  700. }
  701. return(hr);
  702. }
  703. HRESULT
  704. ceVerifyObjId(
  705. IN WCHAR const *pwszObjId)
  706. {
  707. HRESULT hr;
  708. CHAR *pszObjId = NULL;
  709. if (!ceConvertWszToSz(&pszObjId, pwszObjId, -1))
  710. {
  711. hr = E_OUTOFMEMORY;
  712. _JumpError(hr, error, "ceConvertWszToSz");
  713. }
  714. hr = ceVerifyObjIdA(pszObjId);
  715. _JumpIfErrorStr(hr, error, "ceVerifyObjIdA", pwszObjId);
  716. error:
  717. if (NULL != pszObjId)
  718. {
  719. LocalFree(pszObjId);
  720. }
  721. return(hr);
  722. }
  723. HRESULT
  724. ceVerifyAltNameString(
  725. IN LONG NameChoice,
  726. IN WCHAR const *pwszName)
  727. {
  728. HRESULT hr = S_OK;
  729. CERT_ALT_NAME_INFO AltName;
  730. CERT_ALT_NAME_ENTRY Entry;
  731. char *pszObjectId = NULL;
  732. DWORD cbEncoded;
  733. ZeroMemory(&AltName, sizeof(AltName));
  734. AltName.cAltEntry = 1;
  735. AltName.rgAltEntry = &Entry;
  736. ZeroMemory(&Entry, sizeof(Entry));
  737. Entry.dwAltNameChoice = NameChoice;
  738. switch (NameChoice)
  739. {
  740. case CERT_ALT_NAME_RFC822_NAME:
  741. Entry.pwszRfc822Name = const_cast<WCHAR *>(pwszName);
  742. break;
  743. case CERT_ALT_NAME_DNS_NAME:
  744. Entry.pwszDNSName = const_cast<WCHAR *>(pwszName);
  745. break;
  746. case CERT_ALT_NAME_URL:
  747. Entry.pwszURL = const_cast<WCHAR *>(pwszName);
  748. break;
  749. case CERT_ALT_NAME_REGISTERED_ID:
  750. if (!ceConvertWszToSz(&pszObjectId, pwszName, -1))
  751. {
  752. hr = E_OUTOFMEMORY;
  753. ceERRORPRINTLINE("ceConvertWszToSz", hr);
  754. goto error;
  755. }
  756. Entry.pszRegisteredID = pszObjectId;
  757. break;
  758. //case CERT_ALT_NAME_DIRECTORY_NAME:
  759. //case CERT_ALT_NAME_OTHER_NAME:
  760. //case CERT_ALT_NAME_X400_ADDRESS:
  761. //case CERT_ALT_NAME_EDI_PARTY_NAME:
  762. //case CERT_ALT_NAME_IP_ADDRESS:
  763. default:
  764. hr = E_INVALIDARG;
  765. ceERRORPRINTLINE("NameChoice", hr);
  766. goto error;
  767. }
  768. // Encode CERT_ALT_NAME_INFO:
  769. if (!CryptEncodeObject(
  770. X509_ASN_ENCODING,
  771. X509_ALTERNATE_NAME,
  772. &AltName,
  773. NULL,
  774. &cbEncoded))
  775. {
  776. hr = ceHLastError();
  777. ceERRORPRINTLINE("ceEncodeObject", hr);
  778. goto error;
  779. }
  780. error:
  781. if (NULL != pszObjectId)
  782. {
  783. LocalFree(pszObjectId);
  784. }
  785. return(hr);
  786. }
  787. HRESULT
  788. ceDispatchSetErrorInfo(
  789. IN HRESULT hrError,
  790. IN WCHAR const *pwszDescription,
  791. OPTIONAL IN WCHAR const *pwszProgId,
  792. OPTIONAL IN IID const *piid)
  793. {
  794. HRESULT hr;
  795. ICreateErrorInfo *pCreateErrorInfo = NULL;
  796. IErrorInfo *pErrorInfo = NULL;
  797. WCHAR *pwszError = NULL;
  798. WCHAR *pwszText = NULL;
  799. if (NULL == pwszDescription)
  800. {
  801. hr = E_POINTER;
  802. ceERRORPRINTLINE("NULL pointer", hr);
  803. goto error;
  804. }
  805. assert(FAILED(hrError));
  806. pwszError = ceGetErrorMessageText(hrError, TRUE);
  807. if (NULL == pwszError)
  808. {
  809. ceERRORPRINTLINE("ceGetErrorMessageText", E_OUTOFMEMORY);
  810. }
  811. else
  812. {
  813. pwszText = (WCHAR *) LocalAlloc(
  814. LMEM_FIXED,
  815. (wcslen(pwszDescription) + 1 + wcslen(pwszError) + 1) *
  816. sizeof(WCHAR));
  817. if (NULL == pwszText)
  818. {
  819. ceERRORPRINTLINE("LocalAlloc", E_OUTOFMEMORY);
  820. }
  821. else
  822. {
  823. wcscpy(pwszText, pwszDescription);
  824. wcscat(pwszText, L" ");
  825. wcscpy(pwszText, pwszError);
  826. }
  827. }
  828. hr = CreateErrorInfo(&pCreateErrorInfo);
  829. if (S_OK != hr)
  830. {
  831. ceERRORPRINTLINE("CreateErrorInfo", hr);
  832. goto error;
  833. }
  834. if (NULL != piid)
  835. {
  836. hr = pCreateErrorInfo->SetGUID(*piid);
  837. if (S_OK != hr)
  838. {
  839. ceERRORPRINTLINE("SetGUID", hr);
  840. }
  841. }
  842. hr = pCreateErrorInfo->SetDescription(
  843. NULL != pwszText?
  844. pwszText : const_cast<WCHAR *>(pwszDescription));
  845. if (S_OK != hr)
  846. {
  847. ceERRORPRINTLINE("SetDescription", hr);
  848. }
  849. // Set ProgId:
  850. if (NULL != pwszProgId)
  851. {
  852. hr = pCreateErrorInfo->SetSource(const_cast<WCHAR *>(pwszProgId));
  853. if (S_OK != hr)
  854. {
  855. ceERRORPRINTLINE("SetSource", hr);
  856. }
  857. }
  858. hr = pCreateErrorInfo->QueryInterface(
  859. IID_IErrorInfo,
  860. (VOID **) &pErrorInfo);
  861. if (S_OK != hr)
  862. {
  863. ceERRORPRINTLINE("QueryInterface", hr);
  864. goto error;
  865. }
  866. SetErrorInfo(0, pErrorInfo);
  867. error:
  868. if (NULL != pErrorInfo)
  869. {
  870. pErrorInfo->Release();
  871. }
  872. if (NULL != pCreateErrorInfo)
  873. {
  874. pCreateErrorInfo->Release();
  875. }
  876. if (NULL != pwszText)
  877. {
  878. LocalFree(pwszText);
  879. }
  880. if (NULL != pwszError)
  881. {
  882. LocalFree(pwszError);
  883. }
  884. return(hrError); // return input error!
  885. }
  886. int
  887. ceWtoI(
  888. IN WCHAR const *string,
  889. OUT BOOL *pfValid)
  890. {
  891. HRESULT hr;
  892. WCHAR szBuf[16];
  893. WCHAR *szTmp = szBuf;
  894. int cTmp = ARRAYSIZE(szBuf);
  895. int i = 0;
  896. WCHAR const *pwsz;
  897. BOOL fSawDigit = FALSE;
  898. if (pfValid == NULL)
  899. {
  900. hr = E_POINTER;
  901. _JumpError(hr, error, "NULLPARAM");
  902. }
  903. *pfValid = FALSE;
  904. assert(NULL != pfValid);
  905. cTmp = FoldString(
  906. MAP_FOLDDIGITS,
  907. string,
  908. -1,
  909. szTmp,
  910. cTmp);
  911. if (cTmp == 0)
  912. {
  913. hr = ceHLastError();
  914. if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
  915. {
  916. hr = S_OK;
  917. cTmp = FoldString(
  918. MAP_FOLDDIGITS,
  919. string,
  920. -1,
  921. NULL,
  922. 0);
  923. szTmp = (WCHAR*)LocalAlloc(LMEM_FIXED, cTmp*sizeof(WCHAR));
  924. if (NULL == szTmp)
  925. {
  926. hr = E_OUTOFMEMORY;
  927. _JumpError(hr, error, "LocalAlloc");
  928. }
  929. cTmp = FoldString(
  930. MAP_FOLDDIGITS,
  931. string,
  932. -1,
  933. szTmp,
  934. cTmp);
  935. if (cTmp == 0)
  936. hr = ceHLastError();
  937. }
  938. _JumpIfError(hr, error, "FoldString");
  939. }
  940. pwsz = szTmp;
  941. while (iswspace(*pwsz))
  942. {
  943. pwsz++;
  944. }
  945. while (iswdigit(*pwsz))
  946. {
  947. fSawDigit = TRUE;
  948. pwsz++;
  949. }
  950. while (iswspace(*pwsz))
  951. {
  952. pwsz++;
  953. }
  954. if (L'\0' == *pwsz)
  955. {
  956. *pfValid = fSawDigit;
  957. }
  958. i = _wtoi(szTmp);
  959. error:
  960. if (szTmp && (szTmp != szBuf))
  961. LocalFree(szTmp);
  962. return i;
  963. }
  964. HRESULT
  965. ceGetMachineDnsName(
  966. OUT WCHAR **ppwszDnsName)
  967. {
  968. HRESULT hr;
  969. WCHAR *pwszDnsName = NULL;
  970. DWORD cwc;
  971. COMPUTER_NAME_FORMAT NameType = ComputerNameDnsFullyQualified;
  972. *ppwszDnsName = NULL;
  973. while (TRUE)
  974. {
  975. cwc = 0;
  976. if (!GetComputerNameEx(NameType, NULL, &cwc))
  977. {
  978. hr = ceHLastError();
  979. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr &&
  980. ComputerNameDnsFullyQualified == NameType)
  981. {
  982. _PrintError(hr, "GetComputerNameEx(DnsFullyQualified) -- switching to NetBIOS");
  983. NameType = ComputerNameNetBIOS;
  984. continue;
  985. }
  986. if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr)
  987. {
  988. _JumpError(hr, error, "GetComputerNameEx");
  989. }
  990. break;
  991. }
  992. }
  993. pwszDnsName = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  994. if (NULL == pwszDnsName)
  995. {
  996. hr = E_OUTOFMEMORY;
  997. _JumpError(hr, error, "LocalAlloc");
  998. }
  999. if (!GetComputerNameEx(NameType, pwszDnsName, &cwc))
  1000. {
  1001. hr = ceHLastError();
  1002. _JumpError(hr, error, "GetComputerNameEx");
  1003. }
  1004. *ppwszDnsName = pwszDnsName;
  1005. pwszDnsName = NULL;
  1006. hr = S_OK;
  1007. error:
  1008. if (NULL != pwszDnsName)
  1009. {
  1010. LocalFree(pwszDnsName);
  1011. }
  1012. return(hr);
  1013. }
  1014. HRESULT
  1015. ceGetComputerNames(
  1016. OUT WCHAR **ppwszDnsName,
  1017. OUT WCHAR **ppwszOldName)
  1018. {
  1019. HRESULT hr;
  1020. DWORD cwc;
  1021. WCHAR *pwszOldName = NULL;
  1022. *ppwszOldName = NULL;
  1023. *ppwszDnsName = NULL;
  1024. cwc = MAX_COMPUTERNAME_LENGTH + 1;
  1025. pwszOldName = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  1026. if (NULL == pwszOldName)
  1027. {
  1028. hr = E_OUTOFMEMORY;
  1029. _JumpError(hr, error, "LocalAlloc");
  1030. }
  1031. if (!GetComputerName(pwszOldName, &cwc))
  1032. {
  1033. hr = ceHLastError();
  1034. _JumpError(hr, error, "GetComputerName");
  1035. }
  1036. hr = ceGetMachineDnsName(ppwszDnsName);
  1037. _JumpIfError(hr, error, "ceGetMachineDnsName");
  1038. *ppwszOldName = pwszOldName;
  1039. pwszOldName = NULL;
  1040. error:
  1041. if (NULL != pwszOldName)
  1042. {
  1043. LocalFree(pwszOldName);
  1044. }
  1045. return(hr);
  1046. }
  1047. HRESULT
  1048. _IsConfigLocal(
  1049. IN WCHAR const *pwszConfig,
  1050. IN WCHAR const *pwszDnsName,
  1051. IN WCHAR const *pwszOldName,
  1052. OPTIONAL OUT WCHAR **ppwszMachine,
  1053. OUT BOOL *pfLocal)
  1054. {
  1055. HRESULT hr;
  1056. WCHAR *pwszMachine = NULL;
  1057. WCHAR const *pwsz;
  1058. DWORD cwc;
  1059. *pfLocal = FALSE;
  1060. if (NULL != ppwszMachine)
  1061. {
  1062. *ppwszMachine = NULL;
  1063. }
  1064. while (L'\\' == *pwszConfig)
  1065. {
  1066. pwszConfig++;
  1067. }
  1068. pwsz = wcschr(pwszConfig, L'\\');
  1069. if (NULL != pwsz)
  1070. {
  1071. cwc = SAFE_SUBTRACT_POINTERS(pwsz, pwszConfig);
  1072. }
  1073. else
  1074. {
  1075. cwc = wcslen(pwszConfig);
  1076. }
  1077. pwszMachine = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
  1078. if (NULL == pwszMachine)
  1079. {
  1080. hr = E_OUTOFMEMORY;
  1081. _JumpError(hr, error, "LocalAlloc");
  1082. }
  1083. CopyMemory(pwszMachine, pwszConfig, cwc * sizeof(WCHAR));
  1084. pwszMachine[cwc] = L'\0';
  1085. if (0 == lstrcmpi(pwszMachine, pwszDnsName) ||
  1086. 0 == lstrcmpi(pwszMachine, pwszOldName))
  1087. {
  1088. *pfLocal = TRUE;
  1089. }
  1090. if (NULL != ppwszMachine)
  1091. {
  1092. *ppwszMachine = pwszMachine;
  1093. pwszMachine = NULL;
  1094. }
  1095. hr = S_OK;
  1096. error:
  1097. if (NULL != pwszMachine)
  1098. {
  1099. LocalFree(pwszMachine);
  1100. }
  1101. return(hr);
  1102. }
  1103. HRESULT
  1104. ceIsConfigLocal(
  1105. IN WCHAR const *pwszConfig,
  1106. OPTIONAL OUT WCHAR **ppwszMachine,
  1107. OUT BOOL *pfLocal)
  1108. {
  1109. HRESULT hr;
  1110. WCHAR *pwszDnsName = NULL;
  1111. WCHAR *pwszOldName = NULL;
  1112. *pfLocal = FALSE;
  1113. if (NULL != ppwszMachine)
  1114. {
  1115. *ppwszMachine = NULL;
  1116. }
  1117. hr = ceGetComputerNames(&pwszDnsName, &pwszOldName);
  1118. _JumpIfError(hr, error, "ceGetComputerNames");
  1119. hr = _IsConfigLocal(
  1120. pwszConfig,
  1121. pwszDnsName,
  1122. pwszOldName,
  1123. ppwszMachine,
  1124. pfLocal);
  1125. _JumpIfError(hr, error, "_IsConfigLocal");
  1126. error:
  1127. if (NULL != pwszDnsName)
  1128. {
  1129. LocalFree(pwszDnsName);
  1130. }
  1131. if (NULL != pwszOldName)
  1132. {
  1133. LocalFree(pwszOldName);
  1134. }
  1135. return(hr);
  1136. }