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.

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