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.

593 lines
14 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: misc.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <stdafx.h>
  11. // sddl.h requires this value to be at least
  12. // 0x0500. Bump it up if necessary. NOTE: This
  13. // 'bump' comes after all other H files that may
  14. // be sensitive to this value.
  15. #if(_WIN32_WINNT < 0x500)
  16. #undef _WIN32_WINNT
  17. #define _WIN32_WINNT 0x0500
  18. #endif
  19. #include "tmpllist.h"
  20. #include <sddl.h>
  21. #include <shlobj.h>
  22. #include <dsclient.h>
  23. #include <dsgetdc.h>
  24. #include <lm.h>
  25. #include <lmapibuf.h>
  26. #include <objsel.h>
  27. #define __dwFILE__ __dwFILE_CAPESNPN_MISC_CPP__
  28. CLIPFORMAT g_cfDsObjectPicker = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
  29. // returns (if cstr.IsEmpty()) ? NULL : cstr)
  30. LPCWSTR GetNullMachineName(CString* pcstr)
  31. {
  32. LPCWSTR szMachine = (pcstr->IsEmpty()) ? NULL : (LPCWSTR)*pcstr;
  33. return szMachine;
  34. }
  35. /////////////////////////////////////////
  36. // fxns to load/save cstrings to a streams
  37. STDMETHODIMP CStringLoad(CString& cstr, IStream *pStm)
  38. {
  39. ASSERT(pStm);
  40. HRESULT hr;
  41. DWORD cbSize=0;
  42. ULONG nBytesRead;
  43. // get cbSize (bytes)
  44. hr = pStm->Read(&cbSize, sizeof(cbSize), &nBytesRead);
  45. ASSERT(SUCCEEDED(hr) && (nBytesRead == sizeof(cbSize)) );
  46. if (FAILED(hr))
  47. return E_FAIL;
  48. // get string
  49. hr = pStm->Read(cstr.GetBuffer(cbSize), cbSize, &nBytesRead);
  50. ASSERT(SUCCEEDED(hr) && (nBytesRead == cbSize));
  51. cstr.ReleaseBuffer();
  52. return SUCCEEDED(hr) ? S_OK : E_FAIL;
  53. }
  54. STDMETHODIMP CStringSave(CString& cstr, IStream *pStm, BOOL fClearDirty)
  55. {
  56. // Write the string
  57. DWORD cbSize = (cstr.GetLength()+1)*sizeof(WCHAR);
  58. ULONG nBytesWritten;
  59. HRESULT hr;
  60. // write size in bytes
  61. hr = pStm->Write(&cbSize, sizeof(cbSize), &nBytesWritten);
  62. ASSERT(SUCCEEDED(hr) && (nBytesWritten == sizeof(cbSize)) );
  63. if (FAILED(hr))
  64. return STG_E_CANTSAVE;
  65. // write string
  66. hr = pStm->Write((LPCWSTR)cstr, cbSize, &nBytesWritten);
  67. ASSERT(SUCCEEDED(hr) && (nBytesWritten == cbSize));
  68. // Verify that the write operation succeeded
  69. return SUCCEEDED(hr) ? S_OK : STG_E_CANTSAVE;
  70. }
  71. LPSTR AllocAndCopyStr(LPCSTR psz)
  72. {
  73. LPSTR pszReturn;
  74. pszReturn = (LPSTR) new(BYTE[strlen(psz)+1]);
  75. if(pszReturn)
  76. {
  77. strcpy(pszReturn, psz);
  78. }
  79. return pszReturn;
  80. }
  81. LPWSTR AllocAndCopyStr(LPCWSTR pwsz)
  82. {
  83. LPWSTR pwszReturn;
  84. pwszReturn = (LPWSTR) new(WCHAR[wcslen(pwsz)+1]);
  85. if(pwszReturn)
  86. {
  87. wcscpy(pwszReturn, pwsz);
  88. }
  89. return pwszReturn;
  90. }
  91. LPWSTR BuildErrorMessage(DWORD dwErr)
  92. {
  93. LPWSTR lpMsgBuf = NULL;
  94. FormatMessageW(
  95. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  96. NULL,
  97. dwErr,
  98. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  99. (LPWSTR) &lpMsgBuf,
  100. 0,
  101. NULL );
  102. return lpMsgBuf;
  103. }
  104. //////////////////////////////////////////////////////////////////
  105. // given an error code and a console pointer, will pop error dlg
  106. void DisplayGenericCertSrvError(LPCONSOLE2 pConsole, DWORD dwErr)
  107. {
  108. ASSERT(pConsole);
  109. LPWSTR lpMsgBuf = BuildErrorMessage(dwErr);
  110. if(lpMsgBuf)
  111. {
  112. // ...
  113. // Display the string.
  114. pConsole->MessageBoxW(lpMsgBuf, L"Certificate Services Error", MB_OK | MB_ICONINFORMATION, NULL);
  115. // Free the buffer.
  116. LocalFree( lpMsgBuf );
  117. }
  118. }
  119. // returns localized, stringized time
  120. BOOL FileTimeToLocalTimeString(FILETIME* pftGMT, LPWSTR* ppszTmp)
  121. {
  122. FILETIME ftLocal;
  123. if (FileTimeToLocalFileTime(pftGMT, &ftLocal))
  124. {
  125. SYSTEMTIME sysLocal;
  126. if (FileTimeToSystemTime(
  127. &ftLocal,
  128. &sysLocal))
  129. {
  130. WCHAR rgTmpDate[128], rgTmpTime[128];
  131. DWORD dwLen;
  132. dwLen = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &sysLocal,
  133. NULL, rgTmpDate, ARRAYLEN(rgTmpDate));
  134. dwLen += GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &sysLocal,
  135. NULL, rgTmpTime, ARRAYLEN(rgTmpTime));
  136. dwLen += sizeof(L" ");
  137. *ppszTmp = new WCHAR[dwLen];
  138. if(*ppszTmp == NULL)
  139. {
  140. return FALSE;
  141. }
  142. wcscpy(*ppszTmp, rgTmpDate);
  143. wcscat(*ppszTmp, L" ");
  144. wcscat(*ppszTmp, rgTmpTime);
  145. }
  146. }
  147. return TRUE;
  148. }
  149. void MyErrorBox(HWND hwndParent, UINT nIDText, UINT nIDCaption, DWORD dwErrorCode)
  150. {
  151. CString cstrTitle, cstrFormatText, cstrFullText;
  152. cstrTitle.LoadString(nIDCaption);
  153. cstrFormatText.LoadString(nIDText);
  154. WCHAR const *pwszError = NULL;
  155. if (dwErrorCode != ERROR_SUCCESS)
  156. {
  157. pwszError = myGetErrorMessageText(dwErrorCode, TRUE);
  158. cstrFullText.Format(cstrFormatText, pwszError);
  159. // Free the buffer
  160. if (NULL != pwszError)
  161. {
  162. LocalFree(const_cast<WCHAR *>(pwszError));
  163. }
  164. }
  165. ::MessageBoxW(hwndParent, cstrFullText, cstrTitle, MB_OK | MB_ICONERROR);
  166. }
  167. BOOL MyGetOIDInfo(LPWSTR string, DWORD stringSize, LPSTR pszObjId)
  168. {
  169. PCCRYPT_OID_INFO pOIDInfo;
  170. pOIDInfo = CryptFindOIDInfo(
  171. CRYPT_OID_INFO_OID_KEY,
  172. pszObjId,
  173. 0);
  174. if (pOIDInfo != NULL)
  175. {
  176. if (wcslen(pOIDInfo->pwszName)+1 <= stringSize)
  177. {
  178. wcscpy(string, pOIDInfo->pwszName);
  179. }
  180. else
  181. {
  182. return FALSE;
  183. }
  184. }
  185. else
  186. {
  187. return (MultiByteToWideChar(CP_ACP, 0, pszObjId, -1, string, stringSize) != 0);
  188. }
  189. return TRUE;
  190. }
  191. BOOL MyGetEnhancedKeyUsages(HCERTTYPE hCertType, CString **aszUsages, DWORD *cUsages, BOOL *pfCritical, BOOL fGetOIDSNotNames)
  192. {
  193. PCERT_EXTENSIONS pCertExtensions;
  194. CERT_ENHKEY_USAGE *pehku;
  195. DWORD cb = 0;
  196. WCHAR OIDName[256];
  197. unsigned int i;
  198. LPWSTR pwszOID;
  199. HRESULT hr;
  200. CSASSERT(cUsages);
  201. if(aszUsages)
  202. *aszUsages = NULL;
  203. hr = CAGetCertTypeExtensionsEx(hCertType, CT_EXTENSION_EKU, NULL, &pCertExtensions);
  204. if(hr != S_OK)
  205. {
  206. return FALSE;
  207. }
  208. if(1 != pCertExtensions->cExtension)
  209. {
  210. CAFreeCertTypeExtensions(hCertType, pCertExtensions);
  211. return FALSE;
  212. }
  213. i = 0;
  214. if (pfCritical != NULL)
  215. {
  216. *pfCritical = pCertExtensions->rgExtension[i].fCritical;
  217. }
  218. CryptDecodeObject(
  219. X509_ASN_ENCODING,
  220. X509_ENHANCED_KEY_USAGE,
  221. pCertExtensions->rgExtension[i].Value.pbData,
  222. pCertExtensions->rgExtension[i].Value.cbData,
  223. 0,
  224. NULL,
  225. &cb);
  226. if (NULL == (pehku = (CERT_ENHKEY_USAGE *) new(BYTE[cb])))
  227. {
  228. CAFreeCertTypeExtensions(hCertType, pCertExtensions);
  229. return FALSE;
  230. }
  231. CryptDecodeObject(
  232. X509_ASN_ENCODING,
  233. X509_ENHANCED_KEY_USAGE,
  234. pCertExtensions->rgExtension[i].Value.pbData,
  235. pCertExtensions->rgExtension[i].Value.cbData,
  236. 0,
  237. pehku,
  238. &cb);
  239. if(!aszUsages)
  240. {
  241. // only retrieving the usage count
  242. *cUsages = pehku->cUsageIdentifier;
  243. }
  244. else
  245. {
  246. // retrieving usage strings, count better match
  247. CSASSERT(*cUsages == pehku->cUsageIdentifier);
  248. for (i=0; i<pehku->cUsageIdentifier; i++)
  249. {
  250. if (fGetOIDSNotNames)
  251. {
  252. pwszOID = MyMkWStr(pehku->rgpszUsageIdentifier[i]);
  253. aszUsages[i]= new CString(pwszOID);
  254. delete(pwszOID);
  255. if(aszUsages[i] == NULL)
  256. {
  257. return FALSE;
  258. }
  259. }
  260. else
  261. {
  262. MyGetOIDInfo(OIDName, sizeof(OIDName)/sizeof(WCHAR), pehku->rgpszUsageIdentifier[i]);
  263. aszUsages[i]= new CString(OIDName);
  264. if(aszUsages[i] == NULL)
  265. {
  266. return FALSE;
  267. }
  268. }
  269. }
  270. }
  271. delete[](pehku);
  272. CAFreeCertTypeExtensions(hCertType, pCertExtensions);
  273. return TRUE;
  274. }
  275. BOOL GetIntendedUsagesString(HCERTTYPE hCertType, CString *pUsageString)
  276. {
  277. CString **aszUsages = NULL;
  278. DWORD cNumUsages = 0;
  279. unsigned int i;
  280. if(!MyGetEnhancedKeyUsages(hCertType, NULL, &cNumUsages, NULL, FALSE))
  281. return FALSE;
  282. if(0==cNumUsages)
  283. {
  284. *pUsageString = "";
  285. return TRUE;
  286. }
  287. aszUsages = new CString*[cNumUsages];
  288. if(!aszUsages)
  289. return FALSE;
  290. if(!MyGetEnhancedKeyUsages(hCertType, aszUsages, &cNumUsages, NULL, FALSE))
  291. {
  292. delete[] aszUsages;
  293. return FALSE;
  294. }
  295. *pUsageString = "";
  296. for (i=0; i<cNumUsages; i++)
  297. {
  298. if (i != 0)
  299. {
  300. *pUsageString += ", ";
  301. }
  302. *pUsageString += *(aszUsages[i]);
  303. delete(aszUsages[i]);
  304. }
  305. delete[] aszUsages;
  306. return TRUE;
  307. }
  308. BOOL MyGetKeyUsages(HCERTTYPE hCertType, CRYPT_BIT_BLOB **ppBitBlob, BOOL *pfPublicKeyUsageCritical)
  309. {
  310. PCERT_EXTENSIONS pCertExtensions;
  311. DWORD cb = 0;
  312. unsigned int i;
  313. HRESULT hr;
  314. hr = CAGetCertTypeExtensionsEx(hCertType, CT_EXTENSION_KEY_USAGE, NULL, &pCertExtensions);
  315. if(hr != S_OK)
  316. {
  317. return FALSE;
  318. }
  319. if(1 != pCertExtensions->cExtension)
  320. {
  321. CAFreeCertTypeExtensions(hCertType, pCertExtensions);
  322. return FALSE;
  323. }
  324. i = 0;
  325. if (pfPublicKeyUsageCritical != NULL)
  326. {
  327. *pfPublicKeyUsageCritical = pCertExtensions->rgExtension[i].fCritical;
  328. }
  329. CryptDecodeObject(
  330. X509_ASN_ENCODING,
  331. X509_KEY_USAGE,
  332. pCertExtensions->rgExtension[i].Value.pbData,
  333. pCertExtensions->rgExtension[i].Value.cbData,
  334. 0,
  335. NULL,
  336. &cb);
  337. if (NULL == (*ppBitBlob = (CRYPT_BIT_BLOB *) new(BYTE[cb])))
  338. {
  339. CAFreeCertTypeExtensions(hCertType, pCertExtensions);
  340. return FALSE;
  341. }
  342. CryptDecodeObject(
  343. X509_ASN_ENCODING,
  344. X509_KEY_USAGE,
  345. pCertExtensions->rgExtension[i].Value.pbData,
  346. pCertExtensions->rgExtension[i].Value.cbData,
  347. 0,
  348. *ppBitBlob,
  349. &cb);
  350. CAFreeCertTypeExtensions(hCertType, pCertExtensions);
  351. return TRUE;
  352. }
  353. BOOL MyGetBasicConstraintInfo(HCERTTYPE hCertType, BOOL *pfCA, BOOL *pfPathLenConstraint, DWORD *pdwPathLenConstraint)
  354. {
  355. PCERT_EXTENSIONS pCertExtensions;
  356. DWORD cb = sizeof(CERT_BASIC_CONSTRAINTS2_INFO);
  357. unsigned int i;
  358. CERT_BASIC_CONSTRAINTS2_INFO basicConstraintsInfo;
  359. HRESULT hr;
  360. hr = CAGetCertTypeExtensionsEx(hCertType, CT_EXTENSION_BASIC_CONTRAINTS, NULL, &pCertExtensions);
  361. if(hr != S_OK)
  362. {
  363. return FALSE;
  364. }
  365. if(1 != pCertExtensions->cExtension)
  366. {
  367. CAFreeCertTypeExtensions(hCertType, pCertExtensions);
  368. return FALSE;
  369. }
  370. i = 0;
  371. CryptDecodeObject(
  372. X509_ASN_ENCODING,
  373. X509_BASIC_CONSTRAINTS2,
  374. pCertExtensions->rgExtension[i].Value.pbData,
  375. pCertExtensions->rgExtension[i].Value.cbData,
  376. 0,
  377. &basicConstraintsInfo,
  378. &cb);
  379. *pfCA = basicConstraintsInfo.fCA;
  380. *pfPathLenConstraint = basicConstraintsInfo.fPathLenConstraint;
  381. *pdwPathLenConstraint = basicConstraintsInfo.dwPathLenConstraint;
  382. CAFreeCertTypeExtensions(hCertType, pCertExtensions);
  383. return TRUE;
  384. }
  385. LPSTR MyMkMBStr(LPCWSTR pwsz)
  386. {
  387. int cb;
  388. LPSTR psz;
  389. if (pwsz == NULL)
  390. {
  391. return NULL;
  392. }
  393. cb = WideCharToMultiByte(
  394. 0,
  395. 0,
  396. pwsz,
  397. -1,
  398. NULL,
  399. 0,
  400. NULL,
  401. NULL);
  402. if (NULL == (psz = (LPSTR) new BYTE[cb]))
  403. {
  404. return NULL;
  405. }
  406. cb = WideCharToMultiByte(
  407. 0,
  408. 0,
  409. pwsz,
  410. -1,
  411. psz,
  412. cb,
  413. NULL,
  414. NULL);
  415. if (cb==0)
  416. {
  417. delete [] psz;
  418. return NULL;
  419. }
  420. return(psz);
  421. }
  422. LPWSTR MyMkWStr(LPCSTR psz)
  423. {
  424. int cWChars;
  425. LPWSTR pwsz;
  426. if (psz == NULL)
  427. {
  428. return NULL;
  429. }
  430. cWChars = MultiByteToWideChar(
  431. 0,
  432. 0,
  433. psz,
  434. -1,
  435. NULL,
  436. 0);
  437. if (NULL == (pwsz = (LPWSTR) new BYTE[cWChars * sizeof(WCHAR)] ))
  438. {
  439. return NULL;
  440. }
  441. cWChars = MultiByteToWideChar(
  442. 0,
  443. 0,
  444. psz,
  445. -1,
  446. pwsz,
  447. cWChars);
  448. if (cWChars == 0)
  449. {
  450. delete [] pwsz;
  451. return NULL;
  452. }
  453. return(pwsz);
  454. }
  455. HRESULT
  456. UpdateCATemplateList(
  457. HWND hwndParent,
  458. HCAINFO hCAInfo,
  459. const CTemplateList& list)
  460. {
  461. HRESULT hr = myUpdateCATemplateListToCA(hCAInfo, list);
  462. if(S_OK != hr)
  463. {
  464. // if failed to update through the CA for any reason, try
  465. // writing directly to DS
  466. CString cstrMsg, cstrTitle, cstrFormat;
  467. cstrFormat.LoadString(IDS_ERROR_CANNOT_SAVE_TEMPLATES);
  468. cstrTitle.LoadString(IDS_TITLE_CANNOT_SAVE_TEMPLATES);
  469. CAutoLPWSTR pwszError;
  470. pwszError.Attach((LPWSTR)myGetErrorMessageText(hr, TRUE));
  471. cstrMsg.Format(cstrFormat, (LPCWSTR)pwszError);
  472. if (IDYES != MessageBox(
  473. hwndParent,
  474. (LPCWSTR)cstrMsg,
  475. (LPCWSTR)cstrTitle,
  476. MB_YESNO))
  477. return ERROR_CANCELLED;
  478. hr = myUpdateCATemplateListToDS(hCAInfo);
  479. }
  480. return hr;
  481. }