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.

2099 lines
61 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997 - 2001.
  5. //
  6. // File: CertMgr.cpp
  7. //
  8. // Contents: Implementation of DLL Exports
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include <initguid.h>
  13. #include <gpedit.h>
  14. #include "CertMgr_i.c"
  15. #include "about.h" // CCertMgrAbout
  16. #include "compdata.h" // CCertMgrSnapin, CCertMgrExtension
  17. #pragma warning(push, 3)
  18. #include <compuuid.h> // UUIDs for Computer Management
  19. #include "uuids.h"
  20. #include <efsstruc.h>
  21. #include <sceattch.h> // For Security Configuratino Editor snapin
  22. #include <ntverp.h> // VER_PRODUCTVERSION_STR, VERS_COMPANYNAME_STR
  23. #include <typeinfo.h>
  24. #pragma warning(pop)
  25. #ifdef _DEBUG
  26. #ifndef ALPHA
  27. #define new DEBUG_NEW
  28. #endif
  29. #undef THIS_FILE
  30. static char THIS_FILE[] = __FILE__;
  31. #endif
  32. bool g_bSchemaIsW2K = false;
  33. USE_HANDLE_MACROS ("CERTMGR (CertMgr.cpp)")
  34. LPCWSTR CM_HELP_TOPIC = L"sag_CMtopNode.htm";
  35. LPCWSTR CM_HELP_FILE = L"certmgr.chm";
  36. LPCWSTR CM_LINKED_HELP_FILE = L"CMconcepts.chm";
  37. LPCWSTR PKP_LINKED_HELP_FILE = L"SecSetConcepts.chm";
  38. LPCWSTR PKP_HELP_FILE = L"secsettings.chm";
  39. LPCWSTR PKP_HELP_TOPIC = L"sag_secsettopnode.htm";
  40. LPCWSTR SAFER_WINDOWS_HELP_FILE = L"SAFER.chm";
  41. LPCWSTR SAFER_WINDOWS_LINKED_HELP_FILE = L"SAFERconcepts.chm";
  42. LPCWSTR SAFER_HELP_TOPIC = L"SAFER_topnode.htm";
  43. LPCWSTR CM_CONTEXT_HELP = L"\\help\\certmgr.hlp";
  44. LPCWSTR WINDOWS_HELP = L"windows.hlp";
  45. //
  46. // This is used by the nodetype utility routines in stdutils.cpp
  47. //
  48. const struct NODETYPE_GUID_ARRAYSTRUCT g_NodetypeGuids[CERTMGR_NUMTYPES] =
  49. {
  50. { // CERTMGR_SNAPIN
  51. structuuidNodetypeSnapin,
  52. lstruuidNodetypeSnapin },
  53. { // CERTMGR_CERTIFICATE
  54. structuuidNodetypeCertificate,
  55. lstruuidNodetypeCertificate },
  56. { // CERTMGR_LOG_STORE
  57. structuuidNodetypeLogStore,
  58. lstruuidNodetypeLogStore },
  59. { // CERTMGR_PHYS_STORE
  60. structuuidNodetypePhysStore,
  61. lstruuidNodetypePhysStore },
  62. { // CERTMGR_USAGE
  63. structuuidNodetypeUsage,
  64. lstruuidNodetypeUsage },
  65. { // CERTMGR_CRL_CONTAINER
  66. structuuidNodetypeCRLContainer,
  67. lstruuidNodetypeCRLContainer },
  68. { // CERTMGR_CTL_CONTAINER
  69. structuuidNodetypeCTLContainer,
  70. lstruuidNodetypeCTLContainer },
  71. { // CERTMGR_CERT_CONTAINER
  72. structuuidNodetypeCertContainer,
  73. lstruuidNodetypeCertContainer },
  74. { // CERTMGR_CRL
  75. structuuidNodetypeCRL,
  76. lstruuidNodetypeCRL },
  77. { // CERTMGR_CTL
  78. structuuidNodetypeCTL,
  79. lstruuidNodetypeCTL },
  80. { // CERTMGR_AUTO_CERT_REQUEST
  81. structuuidNodetypeAutoCertRequest,
  82. lstruuidNodetypeAutoCertRequest },
  83. { // CERTMGR_CERT_POLICIES_USER,
  84. structuuidNodetypeCertPoliciesUser,
  85. lstruiidNodetypeCertPoliciesUser },
  86. { // CERTMGR_CERT_POLICIES_COMPUTER,
  87. structuuidNodetypeCertPoliciesComputer,
  88. lstruiidNodetypeCertPoliciesComputer },
  89. { // CERTMGR_LOG_STORE_GPE
  90. structuuidNodetypeLogStore,
  91. lstruuidNodetypeLogStore },
  92. { // CERTMGR_LOG_STORE_RSOP
  93. structuuidNodetypeLogStore,
  94. lstruuidNodetypeLogStore },
  95. { // CERTMGR_PKP_AUTOENROLLMENT_COMPUTER_SETTINGS
  96. structuuidNodetypePKPAutoenrollmentSettings,
  97. lstruiidNodetypePKPAutoenrollmentSettings },
  98. { // CERTMGR_PKP_AUTOENROLLMENT_USER_SETTINGS
  99. 0,
  100. 0 },
  101. { // CERTMGR_SAFER_COMPUTER_ROOT
  102. structuuidNodetypeSaferComputerRoot,
  103. lstruiidNodetypeSaferComputerRoot },
  104. { // CERTMGR_SAFER_COMPUTER_LEVELS
  105. structuuidNodetypeSaferComputerLevels,
  106. lstruiidNodetypeSaferComputerLevels },
  107. { // CERTMGR_SAFER_COMPUTER_ENTRIES
  108. structuuidNodetypeSaferComputerEntries,
  109. lstruiidNodetypeSaferComputerEntries },
  110. { // CERTMGR_SAFER_USER_ROOT
  111. structuuidNodetypeSaferUserRoot,
  112. lstruiidNodetypeSaferUserRoot },
  113. { // CERTMGR_SAFER_USER_ENTRIES
  114. structuuidNodetypeSaferUserEntries,
  115. lstruiidNodetypeSaferUserEntries },
  116. { // CERTMGR_SAFER_USER_LEVELS
  117. structuuidNodetypeSaferUserLevels,
  118. lstruiidNodetypeSaferUserLevels },
  119. { // CERTMGR_SAFER_COMPUTER_LEVEL
  120. structuuidNodetypeSaferComputerLevel,
  121. lstruiidNodetypeSaferComputerLevel },
  122. { // CERTMGR_SAFER_USER_LEVEL
  123. structuuidNodetypeSaferUserLevel,
  124. lstruiidNodetypeSaferUserLevel },
  125. { // CERTMGR_SAFER_COMPUTER_ENTRY
  126. structuuidNodetypeSaferComputerEntry,
  127. lstruiidNodetypeSaferComputerEntry },
  128. { // CERTMGR_SAFER_USER_ENTRY
  129. structuuidNodetypeSaferUserEntry,
  130. lstruiidNodetypeSaferUserEntry },
  131. { // CERTMGR_SAFER_COMPUTER_TRUSTED_PUBLISHERS
  132. structuuidNodetypeSaferTrustedPublishers,
  133. lstruiidNodetypeSaferTrustedPublisher },
  134. { // CERTMGR_SAFER_USER_TRUSTED_PUBLISHERS
  135. 0,
  136. 0 },
  137. { // CERTMGR_SAFER_COMPUTER_DEFINED_FILE_TYPES
  138. structuuidNodetypeSaferDefinedFileTypes,
  139. lstruiidNodetypeSaferDefinedFileTypes },
  140. { // CERTMGR_SAFER_USER_DEFINED_FILE_TYPES
  141. 0,
  142. 0 },
  143. { // CERTMGR_SAFER_USER_ENFORCEMENT
  144. structuuidNodetypeSaferEnforcement,
  145. lstruiidNodetypeSaferEnforcement },
  146. { // CERTMGR_SAFER_COMPUTER_ENFORCEMENT
  147. 0,
  148. 0 }
  149. };
  150. const struct NODETYPE_GUID_ARRAYSTRUCT* g_aNodetypeGuids = g_NodetypeGuids;
  151. const int g_cNumNodetypeGuids = CERTMGR_NUMTYPES;
  152. HINSTANCE g_hInstance = 0;
  153. CString g_szFileName;
  154. CComModule _Module;
  155. BEGIN_OBJECT_MAP (ObjectMap)
  156. OBJECT_ENTRY (CLSID_CertificateManager, CCertMgrSnapin)
  157. OBJECT_ENTRY (CLSID_CertificateManagerPKPOLExt, CCertMgrPKPolExtension)
  158. OBJECT_ENTRY (CLSID_CertificateManagerAbout, CCertMgrAbout)
  159. OBJECT_ENTRY (CLSID_PublicKeyPoliciesAbout, CPublicKeyPoliciesAbout)
  160. OBJECT_ENTRY (CLSID_SaferWindowsExtension, CSaferWindowsExtension)
  161. OBJECT_ENTRY (CLSID_SaferWindowsAbout, CSaferWindowsAbout)
  162. END_OBJECT_MAP ()
  163. class CCertMgrApp : public CWinApp
  164. {
  165. public:
  166. CCertMgrApp ();
  167. virtual BOOL InitInstance ();
  168. virtual int ExitInstance ();
  169. private:
  170. };
  171. CCertMgrApp theApp;
  172. CCertMgrApp::CCertMgrApp ()
  173. {
  174. LPWSTR pszCommandLine = _wcsupr (::GetCommandLine ());
  175. LPWSTR pszParam = L"/CERTMGR:FILENAME=";
  176. size_t len = wcslen (pszParam);
  177. LPWSTR pszArg = wcsstr (pszCommandLine, pszParam);
  178. if ( !pszArg )
  179. pszParam = L"-CERTMGR:FILENAME=";
  180. if ( pszArg )
  181. {
  182. LPWSTR pszDelimiters = 0;
  183. // jump past the name of the arg to get the value
  184. pszArg += len;
  185. // Is the file name delimited by double quotes? This could indicate
  186. // the presence of spaces in the name. If so, skip the quote
  187. // and look for the closing quote. Otherwise, look for the next
  188. // space, tab or NULL terminator.
  189. if ( L'\"' == pszArg[0] )
  190. {
  191. pszDelimiters = L"\"";
  192. pszArg++;
  193. }
  194. else
  195. pszDelimiters = L" \t\0";
  196. len = wcscspn (pszArg, pszDelimiters);
  197. * (pszArg + len) = 0;
  198. g_szFileName = pszArg;
  199. }
  200. }
  201. BOOL CCertMgrApp::InitInstance ()
  202. {
  203. #ifdef _MERGE_PROXYSTUB
  204. hProxyDll = m_hInstance;
  205. #endif
  206. g_hInstance = m_hInstance;
  207. AfxSetResourceHandle (m_hInstance);
  208. _Module.Init (ObjectMap, m_hInstance);
  209. #if DBG == 1
  210. CheckDebugOutputLevel ();
  211. #endif
  212. SHFusionInitializeFromModuleID (m_hInstance, 2);
  213. return CWinApp::InitInstance ();
  214. }
  215. int CCertMgrApp::ExitInstance ()
  216. {
  217. SHFusionUninitialize();
  218. SetRegistryScope (0, false);
  219. _Module.Term ();
  220. return CWinApp::ExitInstance ();
  221. }
  222. /////////////////////////////////////////////////////////////////////////////
  223. // Used to determine whether the DLL can be unloaded by OLE
  224. STDAPI DllCanUnloadNow (void)
  225. {
  226. AFX_MANAGE_STATE (AfxGetStaticModuleState ());
  227. return (AfxDllCanUnloadNow ()==S_OK && _Module.GetLockCount ()==0) ? S_OK : S_FALSE;
  228. }
  229. /////////////////////////////////////////////////////////////////////////////
  230. // Returns a class factory to create an object of the requested type
  231. STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  232. {
  233. return _Module.GetClassObject (rclsid, riid, ppv);
  234. }
  235. /////////////////////////////////////////////////////////////////////////////
  236. // DllRegisterServer - Adds entries to the system registry
  237. //const WCHAR g_szNameString[] = TEXT ("NameString");
  238. //const WCHAR g_szNodeType[] = TEXT ("NodeType");
  239. STDAPI DllRegisterServer (void)
  240. {
  241. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  242. // NTRAID# 88502 intlext: mui: me common: crypto: certificate 's
  243. // intended purpose string unlocalized
  244. // Unregister szOID_EFS_RECOVERY
  245. CRYPT_OID_INFO oid;
  246. ::ZeroMemory (&oid, sizeof (CRYPT_OID_INFO));
  247. oid.cbSize = sizeof (CRYPT_OID_INFO);
  248. oid.pszOID = szOID_EFS_RECOVERY;
  249. oid.dwGroupId = CRYPT_ENHKEY_USAGE_OID_GROUP_ID;
  250. CryptUnregisterOIDInfo (&oid);
  251. // registers object, typelib and all interfaces in typelib
  252. HRESULT hr = _Module.RegisterServer (TRUE);
  253. ASSERT (SUCCEEDED (hr));
  254. if ( E_ACCESSDENIED == hr )
  255. {
  256. CString caption;
  257. CString text;
  258. CThemeContextActivator activator;
  259. VERIFY (caption.LoadString (IDS_REGISTER_CERTMGR));
  260. VERIFY (text.LoadString (IDS_INSUFFICIENT_RIGHTS_TO_REGISTER_CERTMGR));
  261. MessageBox (NULL, text, caption, MB_OK);
  262. return hr;
  263. }
  264. try
  265. {
  266. CString strGUID;
  267. CString snapinName;
  268. CString verProviderStr, verVersionStr;
  269. AMC::CRegKey rkSnapins;
  270. BOOL fFound = rkSnapins.OpenKeyEx (HKEY_LOCAL_MACHINE, SNAPINS_KEY);
  271. ASSERT (fFound);
  272. if ( fFound )
  273. {
  274. {
  275. AMC::CRegKey rkCertMgrSnapin;
  276. hr = GuidToCString (&strGUID, CLSID_CertificateManager);
  277. if ( FAILED (hr) )
  278. {
  279. ASSERT (FALSE);
  280. return SELFREG_E_CLASS;
  281. }
  282. rkCertMgrSnapin.CreateKeyEx (rkSnapins, strGUID);
  283. ASSERT (rkCertMgrSnapin.GetLastError () == ERROR_SUCCESS);
  284. rkCertMgrSnapin.SetString (g_szNodeType, g_aNodetypeGuids[CERTMGR_SNAPIN].bstr);
  285. VERIFY (snapinName.LoadString (IDS_CERTIFICATE_MANAGER_REGISTRY));
  286. rkCertMgrSnapin.SetString (g_szNameString, (LPCWSTR) snapinName);
  287. hr = GuidToCString (&strGUID, CLSID_CertificateManagerAbout);
  288. if ( FAILED (hr) )
  289. {
  290. ASSERT (FALSE);
  291. return SELFREG_E_CLASS;
  292. }
  293. rkCertMgrSnapin.SetString (L"About", strGUID);
  294. size_t len = strlen (VER_COMPANYNAME_STR);
  295. len = mbstowcs (verProviderStr.GetBufferSetLength ((int) len),
  296. VER_COMPANYNAME_STR, len);
  297. rkCertMgrSnapin.SetString (L"Provider", verProviderStr);
  298. len = strlen (VER_PRODUCTVERSION_STR);
  299. len = mbstowcs (verVersionStr.GetBufferSetLength ((int)len),
  300. VER_PRODUCTVERSION_STR, len);
  301. rkCertMgrSnapin.SetString (L"Version", verVersionStr);
  302. AMC::CRegKey rkCertMgrStandalone;
  303. rkCertMgrStandalone.CreateKeyEx (rkCertMgrSnapin, g_szStandAlone);
  304. ASSERT (rkCertMgrStandalone.GetLastError () == ERROR_SUCCESS);
  305. AMC::CRegKey rkMyNodeTypes;
  306. rkMyNodeTypes.CreateKeyEx (rkCertMgrSnapin, g_szNodeTypes);
  307. ASSERT (rkMyNodeTypes.GetLastError () == ERROR_SUCCESS);
  308. AMC::CRegKey rkMyNodeType;
  309. for (int i = CERTMGR_SNAPIN; i < CERTMGR_NUMTYPES; i++)
  310. {
  311. switch (i)
  312. {
  313. case CERTMGR_LOG_STORE_GPE:
  314. case CERTMGR_LOG_STORE_RSOP:
  315. case CERTMGR_AUTO_CERT_REQUEST:
  316. case CERTMGR_CERT_POLICIES_USER:
  317. case CERTMGR_CERT_POLICIES_COMPUTER:
  318. case CERTMGR_PKP_AUTOENROLLMENT_USER_SETTINGS: // not necessary - just another kind of the same node
  319. break;
  320. // TODO: What to do with these?
  321. case CERTMGR_SAFER_COMPUTER_ROOT:
  322. case CERTMGR_SAFER_USER_ROOT:
  323. case CERTMGR_SAFER_COMPUTER_LEVELS:
  324. case CERTMGR_SAFER_USER_LEVELS:
  325. case CERTMGR_SAFER_COMPUTER_ENTRIES:
  326. case CERTMGR_SAFER_USER_ENTRIES:
  327. case CERTMGR_SAFER_COMPUTER_LEVEL:
  328. case CERTMGR_SAFER_USER_LEVEL:
  329. case CERTMGR_SAFER_COMPUTER_ENTRY:
  330. case CERTMGR_SAFER_USER_ENTRY:
  331. case CERTMGR_SAFER_COMPUTER_TRUSTED_PUBLISHERS:
  332. case CERTMGR_SAFER_USER_TRUSTED_PUBLISHERS:
  333. case CERTMGR_SAFER_COMPUTER_DEFINED_FILE_TYPES:
  334. case CERTMGR_SAFER_USER_DEFINED_FILE_TYPES:
  335. case CERTMGR_SAFER_USER_ENFORCEMENT:
  336. case CERTMGR_SAFER_COMPUTER_ENFORCEMENT:
  337. break;
  338. case CERTMGR_PKP_AUTOENROLLMENT_COMPUTER_SETTINGS:
  339. default:
  340. if ( wcslen (g_aNodetypeGuids[i].bstr) )
  341. {
  342. rkMyNodeType.CreateKeyEx (rkMyNodeTypes, g_aNodetypeGuids[i].bstr);
  343. ASSERT (rkMyNodeType.GetLastError () == ERROR_SUCCESS);
  344. rkMyNodeType.CloseKey ();
  345. }
  346. break;
  347. }
  348. }
  349. //
  350. // BryanWal 5/18/00
  351. // 94793: MUI: MMC: Certificates snap-in stores its display
  352. // information in the registry
  353. //
  354. // MMC now supports NameStringIndirect
  355. //
  356. TCHAR achModuleFileName[MAX_PATH+20];
  357. if (0 < ::GetModuleFileName(
  358. AfxGetInstanceHandle(),
  359. achModuleFileName,
  360. sizeof(achModuleFileName)/sizeof(TCHAR) ))
  361. {
  362. CString strNameIndirect;
  363. strNameIndirect.Format(L"@%s,-%d",
  364. achModuleFileName,
  365. IDS_CERTIFICATE_MANAGER_REGISTRY );
  366. rkCertMgrSnapin.SetString(L"NameStringIndirect",
  367. strNameIndirect );
  368. }
  369. rkCertMgrSnapin.CloseKey ();
  370. }
  371. AMC::CRegKey rkNodeTypes;
  372. fFound = rkNodeTypes.OpenKeyEx (HKEY_LOCAL_MACHINE, NODE_TYPES_KEY);
  373. ASSERT (fFound);
  374. if ( fFound )
  375. {
  376. AMC::CRegKey rkNodeType;
  377. for (int i = CERTMGR_SNAPIN; i < CERTMGR_NUMTYPES; i++)
  378. {
  379. switch (i)
  380. {
  381. // these types are not used in the primary snapin
  382. case CERTMGR_LOG_STORE_GPE:
  383. case CERTMGR_LOG_STORE_RSOP:
  384. case CERTMGR_AUTO_CERT_REQUEST:
  385. case CERTMGR_CERT_POLICIES_USER:
  386. case CERTMGR_CERT_POLICIES_COMPUTER:
  387. case CERTMGR_PKP_AUTOENROLLMENT_COMPUTER_SETTINGS:
  388. case CERTMGR_PKP_AUTOENROLLMENT_USER_SETTINGS:
  389. case CERTMGR_SAFER_COMPUTER_ROOT:
  390. case CERTMGR_SAFER_USER_ROOT:
  391. case CERTMGR_SAFER_COMPUTER_LEVELS:
  392. case CERTMGR_SAFER_USER_LEVELS:
  393. case CERTMGR_SAFER_COMPUTER_ENTRIES:
  394. case CERTMGR_SAFER_USER_ENTRIES:
  395. case CERTMGR_SAFER_COMPUTER_LEVEL:
  396. case CERTMGR_SAFER_USER_LEVEL:
  397. case CERTMGR_SAFER_COMPUTER_ENTRY:
  398. case CERTMGR_SAFER_USER_ENTRY:
  399. case CERTMGR_SAFER_COMPUTER_TRUSTED_PUBLISHERS:
  400. case CERTMGR_SAFER_USER_TRUSTED_PUBLISHERS:
  401. case CERTMGR_SAFER_COMPUTER_DEFINED_FILE_TYPES:
  402. case CERTMGR_SAFER_USER_DEFINED_FILE_TYPES:
  403. case CERTMGR_SAFER_USER_ENFORCEMENT:
  404. case CERTMGR_SAFER_COMPUTER_ENFORCEMENT:
  405. break;
  406. default:
  407. if ( wcslen (g_aNodetypeGuids[i].bstr) )
  408. {
  409. rkNodeType.CreateKeyEx (rkNodeTypes, g_aNodetypeGuids[i].bstr);
  410. ASSERT (rkNodeType.GetLastError () == ERROR_SUCCESS);
  411. rkNodeType.CloseKey ();
  412. }
  413. break;
  414. }
  415. }
  416. if ( IsWindowsNT () )
  417. {
  418. {
  419. // Public Key PoliciesSnap-in under Security Configuration Editor (SCE)
  420. // Certificate Manager extends "Computer Settings" and
  421. // "User Settings" node
  422. CString strCertMgrExtPKPolGUID;
  423. hr = GuidToCString (&strCertMgrExtPKPolGUID,
  424. CLSID_CertificateManagerPKPOLExt);
  425. if ( FAILED (hr) )
  426. {
  427. ASSERT (FALSE);
  428. return SELFREG_E_CLASS;
  429. }
  430. VERIFY (snapinName.LoadString (IDS_CERT_MGR_SCE_EXTENSION_REGISTRY));
  431. {
  432. AMC::CRegKey rkCertMgrExtension;
  433. rkCertMgrExtension.CreateKeyEx (rkSnapins, strCertMgrExtPKPolGUID);
  434. ASSERT (rkCertMgrExtension.GetLastError () == ERROR_SUCCESS);
  435. rkCertMgrExtension.SetString (g_szNameString, (LPCWSTR) snapinName);
  436. hr = GuidToCString (&strGUID, CLSID_PublicKeyPoliciesAbout);
  437. if ( FAILED (hr) )
  438. {
  439. ASSERT (FALSE);
  440. return SELFREG_E_CLASS;
  441. }
  442. rkCertMgrExtension.SetString (L"About", strGUID);
  443. rkCertMgrExtension.SetString (L"Provider", verProviderStr);
  444. rkCertMgrExtension.SetString (L"Version", verVersionStr);
  445. // Register the node types of the extension
  446. AMC::CRegKey rkMyNodeTypes;
  447. rkMyNodeTypes.CreateKeyEx (rkCertMgrExtension, g_szNodeTypes);
  448. ASSERT (rkMyNodeTypes.GetLastError () == ERROR_SUCCESS);
  449. AMC::CRegKey rkMyNodeType;
  450. for (int i = CERTMGR_SNAPIN; i < CERTMGR_NUMTYPES; i++)
  451. {
  452. switch (i)
  453. {
  454. // None of these are used in the Public Key Policy extension
  455. case CERTMGR_USAGE:
  456. case CERTMGR_PHYS_STORE:
  457. case CERTMGR_LOG_STORE:
  458. case CERTMGR_CRL_CONTAINER:
  459. case CERTMGR_CTL_CONTAINER:
  460. case CERTMGR_CERT_CONTAINER:
  461. case CERTMGR_CRL:
  462. case CERTMGR_SAFER_COMPUTER_ROOT:
  463. case CERTMGR_SAFER_USER_ROOT:
  464. case CERTMGR_SAFER_COMPUTER_LEVELS:
  465. case CERTMGR_SAFER_USER_LEVELS:
  466. case CERTMGR_SAFER_COMPUTER_ENTRIES:
  467. case CERTMGR_SAFER_USER_ENTRIES:
  468. case CERTMGR_SAFER_COMPUTER_LEVEL:
  469. case CERTMGR_SAFER_USER_LEVEL:
  470. case CERTMGR_SAFER_COMPUTER_ENTRY:
  471. case CERTMGR_SAFER_USER_ENTRY:
  472. case CERTMGR_SAFER_COMPUTER_TRUSTED_PUBLISHERS:
  473. case CERTMGR_SAFER_USER_TRUSTED_PUBLISHERS:
  474. case CERTMGR_SAFER_COMPUTER_DEFINED_FILE_TYPES:
  475. case CERTMGR_SAFER_USER_DEFINED_FILE_TYPES:
  476. case CERTMGR_SAFER_USER_ENFORCEMENT:
  477. case CERTMGR_SAFER_COMPUTER_ENFORCEMENT:
  478. // not necessary - just another kind of the same node
  479. case CERTMGR_PKP_AUTOENROLLMENT_USER_SETTINGS:
  480. break;
  481. default:
  482. if ( wcslen (g_aNodetypeGuids[i].bstr) )
  483. {
  484. rkMyNodeType.CreateKeyEx (rkMyNodeTypes, g_aNodetypeGuids[i].bstr);
  485. ASSERT (rkMyNodeType.GetLastError () == ERROR_SUCCESS);
  486. rkMyNodeType.CloseKey ();
  487. }
  488. break;
  489. }
  490. }
  491. //
  492. // BryanWal 5/18/00
  493. // 94793: MUI: MMC: Certificates snap-in stores its display
  494. // information in the registry
  495. //
  496. // MMC now supports NameStringIndirect
  497. //
  498. TCHAR achModuleFileName[MAX_PATH+20];
  499. if (0 < ::GetModuleFileName(
  500. AfxGetInstanceHandle(),
  501. achModuleFileName,
  502. sizeof(achModuleFileName)/sizeof(TCHAR) ))
  503. {
  504. CString strNameIndirect;
  505. strNameIndirect.Format(L"@%s,-%d",
  506. achModuleFileName,
  507. IDS_CERT_MGR_SCE_EXTENSION_REGISTRY );
  508. rkCertMgrExtension.SetString( L"NameStringIndirect",
  509. strNameIndirect );
  510. }
  511. rkCertMgrExtension.CloseKey ();
  512. }
  513. hr = GuidToCString (&strGUID, cNodetypeSceTemplate);
  514. if ( FAILED (hr) )
  515. {
  516. ASSERT (FALSE);
  517. return SELFREG_E_CLASS;
  518. }
  519. rkNodeType.CreateKeyEx (rkNodeTypes, strGUID);
  520. ASSERT (rkNodeType.GetLastError () == ERROR_SUCCESS);
  521. if ( rkNodeType.GetLastError () == ERROR_SUCCESS )
  522. {
  523. AMC::CRegKey rkExtensions;
  524. ASSERT (rkExtensions.GetLastError () == ERROR_SUCCESS);
  525. rkExtensions.CreateKeyEx (rkNodeType, g_szExtensions);
  526. AMC::CRegKey rkNameSpace;
  527. rkNameSpace.CreateKeyEx (rkExtensions, g_szNameSpace);
  528. ASSERT (rkNameSpace.GetLastError () == ERROR_SUCCESS);
  529. rkNameSpace.SetString (strCertMgrExtPKPolGUID, (LPCWSTR) snapinName);
  530. rkNodeType.CloseKey ();
  531. }
  532. else
  533. return SELFREG_E_CLASS;
  534. }
  535. {
  536. // SAFER Windows Snap-in under Security Configuration Editor (SCE)
  537. // Certificate Manager extends "Computer Settings" and
  538. // "User Settings" node
  539. CString strSaferWindowsExtensionGUID;
  540. hr = GuidToCString (&strSaferWindowsExtensionGUID,
  541. CLSID_SaferWindowsExtension);
  542. if ( FAILED (hr) )
  543. {
  544. ASSERT (FALSE);
  545. return SELFREG_E_CLASS;
  546. }
  547. VERIFY (snapinName.LoadString (IDS_SAFER_WINDOWS_EXTENSION_REGISTRY));
  548. {
  549. AMC::CRegKey rkCertMgrExtension;
  550. rkCertMgrExtension.CreateKeyEx (rkSnapins, strSaferWindowsExtensionGUID);
  551. ASSERT (rkCertMgrExtension.GetLastError () == ERROR_SUCCESS);
  552. rkCertMgrExtension.SetString (g_szNameString, (LPCWSTR) snapinName);
  553. hr = GuidToCString (&strGUID, CLSID_SaferWindowsAbout);
  554. if ( FAILED (hr) )
  555. {
  556. ASSERT (FALSE);
  557. return SELFREG_E_CLASS;
  558. }
  559. rkCertMgrExtension.SetString (L"About", strGUID);
  560. rkCertMgrExtension.SetString (L"Provider", verProviderStr);
  561. rkCertMgrExtension.SetString (L"Version", verVersionStr);
  562. // Register the node types of the extension
  563. AMC::CRegKey rkMyNodeTypes;
  564. rkMyNodeTypes.CreateKeyEx (rkCertMgrExtension, g_szNodeTypes);
  565. ASSERT (rkMyNodeTypes.GetLastError () == ERROR_SUCCESS);
  566. AMC::CRegKey rkMyNodeType;
  567. for (int i = CERTMGR_SNAPIN; i < CERTMGR_NUMTYPES; i++)
  568. {
  569. switch (i)
  570. {
  571. case CERTMGR_CERTIFICATE:
  572. case CERTMGR_LOG_STORE:
  573. case CERTMGR_PHYS_STORE:
  574. case CERTMGR_USAGE:
  575. case CERTMGR_CRL_CONTAINER:
  576. case CERTMGR_CTL_CONTAINER:
  577. case CERTMGR_CERT_CONTAINER:
  578. case CERTMGR_CRL:
  579. case CERTMGR_CTL:
  580. case CERTMGR_AUTO_CERT_REQUEST:
  581. case CERTMGR_CERT_POLICIES_USER:
  582. case CERTMGR_CERT_POLICIES_COMPUTER:
  583. case CERTMGR_LOG_STORE_GPE:
  584. case CERTMGR_LOG_STORE_RSOP:
  585. case CERTMGR_PKP_AUTOENROLLMENT_USER_SETTINGS:
  586. case CERTMGR_PKP_AUTOENROLLMENT_COMPUTER_SETTINGS:
  587. // None of these are used in the Software Restriction Policies extension
  588. break;
  589. case CERTMGR_SAFER_COMPUTER_ROOT:
  590. case CERTMGR_SAFER_USER_ROOT:
  591. case CERTMGR_SAFER_COMPUTER_LEVELS:
  592. case CERTMGR_SAFER_USER_LEVELS:
  593. case CERTMGR_SAFER_COMPUTER_ENTRIES:
  594. case CERTMGR_SAFER_USER_ENTRIES:
  595. case CERTMGR_SAFER_COMPUTER_LEVEL:
  596. case CERTMGR_SAFER_USER_LEVEL:
  597. case CERTMGR_SAFER_COMPUTER_ENTRY:
  598. case CERTMGR_SAFER_USER_ENTRY:
  599. case CERTMGR_SAFER_COMPUTER_TRUSTED_PUBLISHERS:
  600. case CERTMGR_SAFER_USER_TRUSTED_PUBLISHERS:
  601. case CERTMGR_SAFER_COMPUTER_DEFINED_FILE_TYPES:
  602. case CERTMGR_SAFER_USER_DEFINED_FILE_TYPES:
  603. case CERTMGR_SAFER_USER_ENFORCEMENT:
  604. case CERTMGR_SAFER_COMPUTER_ENFORCEMENT:
  605. default:
  606. if ( g_aNodetypeGuids[i].bstr && wcslen (g_aNodetypeGuids[i].bstr) )
  607. {
  608. rkMyNodeType.CreateKeyEx (rkMyNodeTypes, g_aNodetypeGuids[i].bstr);
  609. ASSERT (rkMyNodeType.GetLastError () == ERROR_SUCCESS);
  610. rkMyNodeType.CloseKey ();
  611. }
  612. break;
  613. }
  614. }
  615. TCHAR achModuleFileName[MAX_PATH+20];
  616. if (0 < ::GetModuleFileName(
  617. AfxGetInstanceHandle(),
  618. achModuleFileName,
  619. sizeof(achModuleFileName)/sizeof(TCHAR) ))
  620. {
  621. CString strNameIndirect;
  622. strNameIndirect.Format( L"@%s,-%d",
  623. achModuleFileName,
  624. IDS_SAFER_WINDOWS_EXTENSION_REGISTRY );
  625. rkCertMgrExtension.SetString( L"NameStringIndirect",
  626. strNameIndirect );
  627. }
  628. rkCertMgrExtension.CloseKey ();
  629. }
  630. hr = GuidToCString (&strGUID, cNodetypeSceTemplate);
  631. if ( FAILED (hr) )
  632. {
  633. ASSERT (FALSE);
  634. return SELFREG_E_CLASS;
  635. }
  636. rkNodeType.CreateKeyEx (rkNodeTypes, strGUID);
  637. ASSERT (rkNodeType.GetLastError () == ERROR_SUCCESS);
  638. if ( rkNodeType.GetLastError () == ERROR_SUCCESS )
  639. {
  640. AMC::CRegKey rkExtensions;
  641. ASSERT (rkExtensions.GetLastError () == ERROR_SUCCESS);
  642. rkExtensions.CreateKeyEx (rkNodeType, g_szExtensions);
  643. AMC::CRegKey rkNameSpace;
  644. rkNameSpace.CreateKeyEx (rkExtensions, g_szNameSpace);
  645. ASSERT (rkNameSpace.GetLastError () == ERROR_SUCCESS);
  646. rkNameSpace.SetString (strSaferWindowsExtensionGUID,
  647. (LPCWSTR) snapinName);
  648. rkNodeType.CloseKey ();
  649. }
  650. else
  651. return SELFREG_E_CLASS;
  652. }
  653. // Deregister as extension to My Computer System Tools node
  654. // CODEWORK It would be good if we deregistered the server too
  655. // JonN 12/14/98
  656. try
  657. {
  658. fFound = rkNodeType.OpenKeyEx (rkNodeTypes, TEXT(struuidNodetypeSystemTools));
  659. // if this fails just carry on
  660. if ( fFound )
  661. {
  662. AMC::CRegKey rkExtensions;
  663. ASSERT (rkExtensions.GetLastError () == ERROR_SUCCESS);
  664. fFound = rkExtensions.OpenKeyEx (rkNodeType, g_szExtensions);
  665. // if this fails just carry on
  666. if ( fFound )
  667. {
  668. AMC::CRegKey rkNameSpace;
  669. ASSERT (rkNameSpace.GetLastError () == ERROR_SUCCESS);
  670. fFound = rkNameSpace.OpenKeyEx (rkExtensions, g_szNameSpace);
  671. // if this fails just carry on
  672. if ( fFound )
  673. {
  674. rkNameSpace.DeleteValue( L"{9C7910D2-4C01-11D1-856B-00C04FB94F17}" );
  675. }
  676. }
  677. }
  678. } catch (COleException* /*e*/)
  679. {
  680. // don't do anything
  681. }
  682. } // endif IsWindowsNT ()
  683. rkNodeTypes.CloseKey ();
  684. }
  685. else
  686. return SELFREG_E_CLASS;
  687. }
  688. else
  689. return SELFREG_E_CLASS;
  690. }
  691. catch (COleException* e)
  692. {
  693. ASSERT (FALSE);
  694. e->Delete ();
  695. return SELFREG_E_CLASS;
  696. }
  697. ASSERT (SUCCEEDED (hr));
  698. return hr;
  699. }
  700. /////////////////////////////////////////////////////////////////////////////
  701. // DllUnregisterServer - Removes entries from the system registry
  702. STDAPI DllUnregisterServer (void)
  703. {
  704. _Module.UnregisterServer ();
  705. return S_OK;
  706. }
  707. STDAPI DllInstall(BOOL /*bInstall*/, LPCWSTR pszCmdLine)
  708. {
  709. LPCWSTR wszCurrentCmd = pszCmdLine;
  710. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  711. // parse the cmd line
  712. while(wszCurrentCmd && *wszCurrentCmd)
  713. {
  714. while(*wszCurrentCmd == L' ')
  715. wszCurrentCmd++;
  716. if(*wszCurrentCmd == 0)
  717. break;
  718. switch(*wszCurrentCmd++)
  719. {
  720. case L'?':
  721. return S_OK;
  722. }
  723. }
  724. return S_OK;
  725. }
  726. ///////////////////////////////////////////////////////////////////////////
  727. // ConvertNameBlobToString ()
  728. //
  729. // nameBlob (IN) - Contains a CERT_NAME_BLOB to be decoded
  730. // pszName (OUT) - The decoded contents of the name blob
  731. //
  732. ///////////////////////////////////////////////////////////////////////////
  733. HRESULT ConvertNameBlobToString (CERT_NAME_BLOB nameBlob, CString & pszName)
  734. {
  735. HRESULT hr = S_OK;
  736. DWORD dwSize = 0;
  737. // Call CertNameToStr to get returned the string length.
  738. dwSize = CertNameToStr (
  739. MY_ENCODING_TYPE, // Encoding type
  740. &nameBlob, // CERT_NAME_BLOB
  741. CERT_SIMPLE_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, // Type
  742. NULL, // Place to return string
  743. dwSize); // Size of string (chars),
  744. // including zero terminator.
  745. ASSERT (dwSize > 1);
  746. if ( dwSize > 1 ) // This function always returns a null char
  747. // (0), so the minimum count returned will
  748. // be 1, even if nothing got converted.
  749. {
  750. // Call CertNameToStr to get the string.
  751. dwSize = CertNameToStr (
  752. MY_ENCODING_TYPE, // Encoding type
  753. &nameBlob, // CERT_NAME_BLOB
  754. CERT_SIMPLE_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, // Type
  755. pszName.GetBufferSetLength (dwSize), // Place to return string
  756. dwSize); // Size of string (chars)
  757. ASSERT (dwSize > 1);
  758. pszName.ReleaseBuffer ();
  759. if ( dwSize <= 1 )
  760. {
  761. hr = E_UNEXPECTED;
  762. }
  763. }
  764. return hr;
  765. }
  766. ///////////////////////////////////////////////////////////////////////////////
  767. // FormatDate ()
  768. //
  769. // utcDateTime (IN) - A FILETIME in UTC format.
  770. // pszDateTime (OUT) - A string containing the local date and time
  771. // formatted by locale and user preference
  772. //
  773. ///////////////////////////////////////////////////////////////////////////////
  774. HRESULT FormatDate (FILETIME utcDateTime, CString & pszDateTime, DWORD dwDateFlags, bool bGetTime)
  775. {
  776. // Time is returned as UTC, will be displayed as local.
  777. // Use FileTimeToLocalFileTime () to make it local,
  778. // then call FileTimeToSystemTime () to convert to system time, then
  779. // format with GetDateFormat () and GetTimeFormat () to display
  780. // according to user and locale preferences
  781. HRESULT hr = S_OK;
  782. FILETIME localDateTime;
  783. BOOL bResult = FileTimeToLocalFileTime (&utcDateTime, // pointer to UTC file time to convert
  784. &localDateTime); // pointer to converted file time
  785. ASSERT (bResult);
  786. if ( bResult )
  787. {
  788. SYSTEMTIME sysTime;
  789. bResult = FileTimeToSystemTime (
  790. &localDateTime, // pointer to file time to convert
  791. &sysTime); // pointer to structure to receive system time
  792. if ( bResult )
  793. {
  794. CString date;
  795. CString time;
  796. // Get date
  797. // Get length to allocate buffer of sufficient size
  798. int iLen = GetDateFormat (
  799. LOCALE_USER_DEFAULT, // locale for which date is to be formatted
  800. dwDateFlags, // flags specifying function options
  801. &sysTime, // date to be formatted
  802. 0, // date format string
  803. 0, // buffer for storing formatted string
  804. 0); // size of buffer
  805. ASSERT (iLen > 0);
  806. if ( iLen > 0 )
  807. {
  808. int iResult = GetDateFormat (
  809. LOCALE_USER_DEFAULT, // locale for which date is to be formatted
  810. dwDateFlags, // flags specifying function options
  811. &sysTime, // date to be formatted
  812. 0, // date format string
  813. date.GetBufferSetLength (iLen), // buffer for storing formatted string
  814. iLen); // size of buffer
  815. ASSERT (iResult);
  816. date.ReleaseBuffer ();
  817. if ( iResult )
  818. pszDateTime = date;
  819. else
  820. hr = HRESULT_FROM_WIN32 (GetLastError ());
  821. if ( iResult && bGetTime )
  822. {
  823. // Get time
  824. // Get length to allocate buffer of sufficient size
  825. iLen = GetTimeFormat (
  826. LOCALE_USER_DEFAULT, // locale for which date is to be formatted
  827. 0, // flags specifying function options
  828. &sysTime, // date to be formatted
  829. 0, // date format string
  830. 0, // buffer for storing formatted string
  831. 0); // size of buffer
  832. ASSERT (iLen > 0);
  833. if ( iLen > 0 )
  834. {
  835. iResult = GetTimeFormat (
  836. LOCALE_USER_DEFAULT, // locale for which date is to be formatted
  837. 0, // flags specifying function options
  838. &sysTime, // date to be formatted
  839. 0, // date format string
  840. time.GetBufferSetLength (iLen), // buffer for storing formatted string
  841. iLen); // size of buffer
  842. ASSERT (iResult);
  843. time.ReleaseBuffer ();
  844. if ( iResult )
  845. {
  846. pszDateTime = date + L" " + time;
  847. }
  848. else
  849. hr = E_UNEXPECTED;
  850. }
  851. else
  852. hr = E_UNEXPECTED;
  853. }
  854. }
  855. else
  856. {
  857. hr = HRESULT_FROM_WIN32 (GetLastError ());
  858. }
  859. }
  860. else
  861. {
  862. hr = HRESULT_FROM_WIN32 (GetLastError ());
  863. }
  864. }
  865. else
  866. {
  867. hr = HRESULT_FROM_WIN32 (GetLastError ());
  868. }
  869. return hr;
  870. }
  871. void DisplaySystemError (HWND hParent, DWORD dwErr)
  872. {
  873. AFX_MANAGE_STATE (AfxGetStaticModuleState ());
  874. LPVOID lpMsgBuf;
  875. FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  876. NULL,
  877. dwErr,
  878. MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  879. (LPWSTR) &lpMsgBuf, 0, NULL);
  880. // Display the string.
  881. CString caption;
  882. VERIFY (caption.LoadString (IDS_CERTIFICATE_MANAGER));
  883. CThemeContextActivator activator;
  884. ::MessageBox (hParent, (LPWSTR) lpMsgBuf, (LPCWSTR) caption, MB_OK);
  885. // Free the buffer.
  886. LocalFree (lpMsgBuf);
  887. }
  888. CString GetSystemMessage (DWORD dwErr)
  889. {
  890. AFX_MANAGE_STATE (AfxGetStaticModuleState ());
  891. CString message;
  892. LPVOID lpMsgBuf;
  893. FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  894. NULL,
  895. dwErr,
  896. MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  897. (LPWSTR) &lpMsgBuf, 0, NULL );
  898. message = (LPWSTR) lpMsgBuf;
  899. // Free the buffer.
  900. LocalFree (lpMsgBuf);
  901. return message;
  902. }
  903. bool MyGetOIDInfo (CString & string, LPCSTR pszObjId)
  904. {
  905. ASSERT (pszObjId);
  906. PCCRYPT_OID_INFO pOIDInfo; // This points to a constant data structure and must not be freed.
  907. bool bResult = true;
  908. pOIDInfo = ::CryptFindOIDInfo (CRYPT_OID_INFO_OID_KEY, (void *) pszObjId, 0);
  909. if ( pOIDInfo )
  910. {
  911. string = pOIDInfo->pwszName;
  912. }
  913. else
  914. {
  915. int nLen = ::MultiByteToWideChar (CP_ACP, 0, pszObjId, -1, NULL, 0);
  916. ASSERT (nLen);
  917. if ( nLen )
  918. {
  919. nLen = ::MultiByteToWideChar (CP_ACP, 0, pszObjId, -1,
  920. string.GetBufferSetLength (nLen), nLen);
  921. ASSERT (nLen);
  922. string.ReleaseBuffer ();
  923. }
  924. bResult = (nLen > 0) ? true : false;
  925. }
  926. return bResult;
  927. }
  928. bool IsWindowsNT()
  929. {
  930. OSVERSIONINFO versionInfo;
  931. ::ZeroMemory (&versionInfo, sizeof (OSVERSIONINFO));
  932. versionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  933. BOOL bResult = ::GetVersionEx (&versionInfo);
  934. ASSERT (bResult);
  935. if ( bResult )
  936. {
  937. if ( VER_PLATFORM_WIN32_NT == versionInfo.dwPlatformId )
  938. bResult = TRUE;
  939. }
  940. return bResult ? true : false;
  941. }
  942. bool GetNameStringByType (
  943. PCCERT_CONTEXT pCertContext,
  944. DWORD dwFlag,
  945. DWORD dwType,
  946. CString& szNameString)
  947. {
  948. bool bResult = false;
  949. DWORD dwTypePara = CERT_SIMPLE_NAME_STR | CERT_NAME_STR_REVERSE_FLAG;
  950. DWORD cchNameString = 0;
  951. DWORD dwResult = ::CertGetNameString (pCertContext,
  952. dwType,
  953. dwFlag,
  954. &dwTypePara,
  955. NULL,
  956. cchNameString);
  957. if ( dwResult > 1 )
  958. {
  959. cchNameString = dwResult;
  960. LPWSTR pszNameString = new WCHAR[cchNameString];
  961. if ( pszNameString )
  962. {
  963. ::ZeroMemory (pszNameString, cchNameString*sizeof (WCHAR));
  964. dwResult = ::CertGetNameString (pCertContext,
  965. dwType,
  966. dwFlag,
  967. &dwTypePara,
  968. pszNameString,
  969. cchNameString);
  970. ASSERT (dwResult > 1);
  971. if ( dwResult > 1 )
  972. {
  973. szNameString = pszNameString;
  974. bResult = true;
  975. }
  976. delete [] pszNameString;
  977. }
  978. }
  979. return bResult;
  980. }
  981. CString GetNameString (PCCERT_CONTEXT pCertContext, DWORD dwFlag)
  982. {
  983. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  984. CString szNameString;
  985. DWORD dwTypes[] = {CERT_NAME_SIMPLE_DISPLAY_TYPE,
  986. CERT_NAME_EMAIL_TYPE,
  987. CERT_NAME_UPN_TYPE,
  988. CERT_NAME_DNS_TYPE,
  989. CERT_NAME_URL_TYPE,
  990. (DWORD) -1};
  991. int nIndex = 0;
  992. while ( -1 != dwTypes[nIndex])
  993. {
  994. if ( GetNameStringByType (
  995. pCertContext,
  996. dwFlag,
  997. dwTypes[nIndex],
  998. szNameString) )
  999. {
  1000. break;
  1001. }
  1002. nIndex++;
  1003. }
  1004. if ( szNameString.IsEmpty () )
  1005. szNameString.FormatMessage (IDS_NOT_AVAILABLE);
  1006. return szNameString;
  1007. }
  1008. bool CertHasEFSKeyUsage(PCCERT_CONTEXT pCertContext)
  1009. {
  1010. bool bFound = false;
  1011. BOOL bResult = FALSE;
  1012. DWORD cbUsage = 0;
  1013. bResult = ::CertGetEnhancedKeyUsage (pCertContext,
  1014. 0, // get extension and property
  1015. NULL, &cbUsage);
  1016. if ( bResult )
  1017. {
  1018. PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE) new BYTE[cbUsage];
  1019. if ( pUsage )
  1020. {
  1021. bResult = ::CertGetEnhancedKeyUsage (pCertContext,
  1022. 0, // get extension and property
  1023. pUsage, &cbUsage);
  1024. if ( bResult )
  1025. {
  1026. for (DWORD dwIndex = 0; dwIndex < pUsage->cUsageIdentifier; dwIndex++)
  1027. {
  1028. if ( !_stricmp (szOID_EFS_RECOVERY,
  1029. pUsage->rgpszUsageIdentifier[dwIndex]) )
  1030. {
  1031. bFound = true;
  1032. break;
  1033. }
  1034. }
  1035. }
  1036. else
  1037. {
  1038. ASSERT (GetLastError () == CRYPT_E_NOT_FOUND);
  1039. }
  1040. delete [] pUsage;
  1041. }
  1042. }
  1043. else
  1044. {
  1045. ASSERT (GetLastError () == CRYPT_E_NOT_FOUND);
  1046. }
  1047. return bFound;
  1048. }
  1049. ////// This stuff was stolen from windows\gina\snapins\gpedit (eric flo's stuff) //////
  1050. //*************************************************************
  1051. //
  1052. // CheckSlash()
  1053. //
  1054. // Purpose: Checks for an ending slash and adds one if
  1055. // it is missing.
  1056. //
  1057. // Parameters: lpDir - directory
  1058. //
  1059. // Return: Pointer to the end of the string
  1060. //
  1061. // Comments:
  1062. //
  1063. // History: Date Author Comment
  1064. // 6/19/95 ericflo Created
  1065. //
  1066. //*************************************************************
  1067. LPWSTR CheckSlash (LPWSTR lpDir)
  1068. {
  1069. LPWSTR lpEnd = lpDir + lstrlen(lpDir);
  1070. if (*(lpEnd - 1) != TEXT('\\'))
  1071. {
  1072. *lpEnd = TEXT('\\');
  1073. lpEnd++;
  1074. *lpEnd = TEXT('\0');
  1075. }
  1076. return lpEnd;
  1077. }
  1078. //*************************************************************
  1079. //
  1080. // RegDelnodeRecurse()
  1081. //
  1082. // Purpose: Deletes a registry key and all it's subkeys / values.
  1083. // Called by RegDelnode
  1084. //
  1085. // Parameters: hKeyRoot - Root key
  1086. // lpSubKey - SubKey to delete
  1087. //
  1088. // Return: ERROR_SUCCESS if successful
  1089. // something else if an error occurs
  1090. //
  1091. // Comments:
  1092. //
  1093. // History: Date Author Comment
  1094. // 10/3/95 ericflo Created
  1095. // 5/13/98 BryanWal Modified to return LRESULT
  1096. //
  1097. //*************************************************************
  1098. LRESULT RegDelnodeRecurse (HKEY hKeyRoot, LPWSTR lpSubKey)
  1099. {
  1100. //
  1101. // First, see if we can delete the key without having
  1102. // to recurse.
  1103. //
  1104. LONG lResult = RegDeleteKey(hKeyRoot, lpSubKey);
  1105. if (lResult == ERROR_SUCCESS)
  1106. {
  1107. return lResult;
  1108. }
  1109. HKEY hKey = 0;
  1110. lResult = RegOpenKeyEx (hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
  1111. if (lResult != ERROR_SUCCESS)
  1112. {
  1113. return lResult;
  1114. }
  1115. LPWSTR lpEnd = CheckSlash(lpSubKey);
  1116. //
  1117. // Enumerate the keys
  1118. //
  1119. DWORD dwSize = MAX_PATH;
  1120. FILETIME ftWrite;
  1121. WCHAR szName[MAX_PATH];
  1122. lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
  1123. NULL, NULL, &ftWrite);
  1124. if (lResult == ERROR_SUCCESS)
  1125. {
  1126. do {
  1127. lstrcpy (lpEnd, szName);
  1128. if ( ERROR_SUCCESS != RegDelnodeRecurse(hKeyRoot, lpSubKey) )
  1129. {
  1130. break;
  1131. }
  1132. //
  1133. // Enumerate again
  1134. //
  1135. dwSize = MAX_PATH;
  1136. lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
  1137. NULL, NULL, &ftWrite);
  1138. } while (lResult == ERROR_SUCCESS);
  1139. }
  1140. lpEnd--;
  1141. *lpEnd = TEXT('\0');
  1142. RegCloseKey (hKey);
  1143. //
  1144. // Try again to delete the key
  1145. //
  1146. lResult = RegDeleteKey(hKeyRoot, lpSubKey);
  1147. if (lResult == ERROR_SUCCESS)
  1148. {
  1149. return lResult;
  1150. }
  1151. return lResult;
  1152. }
  1153. //*************************************************************
  1154. //
  1155. // RegDelnode()
  1156. //
  1157. // Purpose: Deletes a registry key and all it's subkeys / values
  1158. //
  1159. // Parameters: hKeyRoot - Root key
  1160. // lpSubKey - SubKey to delete
  1161. //
  1162. // Return: ERROR_SUCCESS if successful
  1163. // something else if an error occurs
  1164. //
  1165. // Comments:
  1166. //
  1167. // History: Date Author Comment
  1168. // 10/3/95 ericflo Created
  1169. // 5/13/98 BryanWal Modified to return LRESULT
  1170. //
  1171. //*************************************************************
  1172. LRESULT RegDelnode (HKEY hKeyRoot, LPWSTR lpSubKey)
  1173. {
  1174. const size_t BUF_LEN = 2 * MAX_PATH;
  1175. WCHAR szDelKey[BUF_LEN];
  1176. ::ZeroMemory (szDelKey, BUF_LEN * sizeof (WCHAR));
  1177. wcsncpy (szDelKey, lpSubKey, BUF_LEN - 1);
  1178. return RegDelnodeRecurse(hKeyRoot, szDelKey);
  1179. }
  1180. HRESULT DisplayCertificateCountByStore(LPCONSOLE pConsole, CCertStore* pCertStore, bool bIsGPE)
  1181. {
  1182. if ( !pConsole || !pCertStore )
  1183. return E_POINTER;
  1184. _TRACE (1, L"Entering DisplayCertificateCountByStore- %s \n",
  1185. (LPCWSTR) pCertStore->GetStoreName ());
  1186. AFX_MANAGE_STATE (AfxGetStaticModuleState ( ));
  1187. IConsole2* pConsole2 = 0;
  1188. HRESULT hr = pConsole->QueryInterface (IID_PPV_ARG (IConsole2, &pConsole2));
  1189. if (SUCCEEDED (hr))
  1190. {
  1191. CString statusText;
  1192. int nCertCount = 0;
  1193. switch (pCertStore->GetStoreType ())
  1194. {
  1195. case ACRS_STORE:
  1196. nCertCount = pCertStore->GetCTLCount ();
  1197. break;
  1198. case TRUST_STORE:
  1199. if ( bIsGPE )
  1200. {
  1201. nCertCount = pCertStore->GetCTLCount ();
  1202. }
  1203. else
  1204. nCertCount = pCertStore->GetCertCount ();
  1205. break;
  1206. default:
  1207. nCertCount = pCertStore->GetCertCount ();
  1208. break;
  1209. }
  1210. switch (nCertCount)
  1211. {
  1212. case 0:
  1213. {
  1214. UINT formatID = 0;
  1215. switch (pCertStore->GetStoreType ())
  1216. {
  1217. case ACRS_STORE:
  1218. formatID = IDS_STATUS_NO_AUTOENROLLMENT_OBJECTS;
  1219. break;
  1220. case TRUST_STORE:
  1221. if ( bIsGPE )
  1222. {
  1223. formatID = IDS_STATUS_NO_CTLS;
  1224. }
  1225. else
  1226. formatID = IDS_STATUS_NO_CERTS;
  1227. break;
  1228. default:
  1229. formatID = IDS_STATUS_NO_CERTS;
  1230. break;
  1231. }
  1232. statusText.FormatMessage (formatID, pCertStore->GetLocalizedName ());
  1233. }
  1234. break;
  1235. case 1:
  1236. {
  1237. UINT formatID = 0;
  1238. switch (pCertStore->GetStoreType ())
  1239. {
  1240. case ACRS_STORE:
  1241. formatID = IDS_STATUS_ONE_AUTOENROLLMENT_OBJECT;
  1242. break;
  1243. case TRUST_STORE:
  1244. if ( bIsGPE )
  1245. {
  1246. formatID = IDS_STATUS_ONE_CTL;
  1247. }
  1248. else
  1249. formatID = IDS_STATUS_ONE_CERT;
  1250. break;
  1251. default:
  1252. formatID = IDS_STATUS_ONE_CERT;
  1253. break;
  1254. }
  1255. statusText.FormatMessage (formatID, pCertStore->GetLocalizedName ());
  1256. }
  1257. break;
  1258. default:
  1259. {
  1260. UINT formatID = 0;
  1261. switch (pCertStore->GetStoreType ())
  1262. {
  1263. case ACRS_STORE:
  1264. formatID = IDS_STATUS_X_AUTOENROLLMENT_OBJECTS;
  1265. break;
  1266. case TRUST_STORE:
  1267. if ( bIsGPE )
  1268. {
  1269. formatID = IDS_STATUS_X_CTLS;
  1270. }
  1271. else
  1272. formatID = IDS_STATUS_X_CERTS;
  1273. break;
  1274. default:
  1275. formatID = IDS_STATUS_X_CERTS;
  1276. break;
  1277. }
  1278. statusText.FormatMessage (formatID,
  1279. (LPCWSTR) pCertStore->GetLocalizedName (), nCertCount);
  1280. }
  1281. break;
  1282. }
  1283. hr = pConsole2->SetStatusText ((LPWSTR)(LPCWSTR) statusText);
  1284. pConsole2->Release ();
  1285. }
  1286. _TRACE (-1, L"Leaving DisplayCertificateCountByStore- %s \n",
  1287. (LPCWSTR) pCertStore->GetStoreName ());
  1288. return hr;
  1289. }
  1290. CString GetF1HelpFilename()
  1291. {
  1292. static CString helpFileName;
  1293. if ( helpFileName.IsEmpty () )
  1294. {
  1295. UINT result = ::GetSystemWindowsDirectory (
  1296. helpFileName.GetBufferSetLength (MAX_PATH+1), MAX_PATH);
  1297. ASSERT(result != 0 && result <= MAX_PATH);
  1298. helpFileName.ReleaseBuffer ();
  1299. if ( result != 0 && result <= MAX_PATH )
  1300. helpFileName += CM_CONTEXT_HELP;
  1301. }
  1302. return helpFileName;
  1303. }
  1304. //+---------------------------------------------------------------------------
  1305. //
  1306. // Function: LocaleStrCmp
  1307. //
  1308. // Synopsis: Do a case insensitive string compare that is safe for any
  1309. // locale.
  1310. //
  1311. // Arguments: [ptsz1] - strings to compare
  1312. // [ptsz2]
  1313. //
  1314. // Returns: -1, 0, or 1 just like lstrcmpi
  1315. //
  1316. // History: 10-28-96 DavidMun Created
  1317. //
  1318. // Notes: This is slower than lstrcmpi, but will work when sorting
  1319. // strings even in Japanese.
  1320. //
  1321. //----------------------------------------------------------------------------
  1322. int LocaleStrCmp(LPCWSTR ptsz1, LPCWSTR ptsz2)
  1323. {
  1324. int iRet = 0;
  1325. iRet = CompareString(LOCALE_USER_DEFAULT,
  1326. NORM_IGNORECASE |
  1327. NORM_IGNOREKANATYPE |
  1328. NORM_IGNOREWIDTH,
  1329. ptsz1,
  1330. -1,
  1331. ptsz2,
  1332. -1);
  1333. if (iRet)
  1334. {
  1335. iRet -= 2; // convert to lstrcmpi-style return -1, 0, or 1
  1336. if ( 0 == iRet )
  1337. {
  1338. UNICODE_STRING unistr1;
  1339. unistr1.Length = (USHORT) (wcslen(ptsz1) * sizeof(WCHAR));
  1340. unistr1.MaximumLength = unistr1.Length;
  1341. unistr1.Buffer = (LPWSTR)ptsz1;
  1342. UNICODE_STRING unistr2;
  1343. unistr2.Length = (USHORT) (wcslen(ptsz2) * sizeof(WCHAR));
  1344. unistr2.MaximumLength = unistr2.Length;
  1345. unistr2.Buffer = (LPWSTR)ptsz2;
  1346. iRet = ::RtlCompareUnicodeString(
  1347. &unistr1,
  1348. &unistr2,
  1349. FALSE );
  1350. }
  1351. }
  1352. else
  1353. {
  1354. _TRACE (0, L"CompareString (%s, %s) failed: 0x%x\n", ptsz1, ptsz2, GetLastError ());
  1355. }
  1356. return iRet;
  1357. }
  1358. ///////////////////////////////////////////////////////////////////////////////
  1359. ///////////////////////////////////////////////////////////////////////////////
  1360. HPROPSHEETPAGE MyCreatePropertySheetPage(AFX_OLDPROPSHEETPAGE* psp)
  1361. {
  1362. PROPSHEETPAGE_V3 sp_v3 = {0};
  1363. CopyMemory (&sp_v3, psp, psp->dwSize);
  1364. sp_v3.dwSize = sizeof(sp_v3);
  1365. return (::CreatePropertySheetPage (&sp_v3));
  1366. }
  1367. ///////////////////////////////////////////////////////////////////////////////
  1368. ///////////////////////////////////////////////////////////////////////////////
  1369. #include <winldap.h>
  1370. #include <ntldap.h>
  1371. #include <dsrole.h>
  1372. #include <dsgetdc.h>
  1373. #include <accctrl.h>
  1374. #include <lmaccess.h>
  1375. #include <lmapibuf.h>
  1376. #include <lmerr.h>
  1377. //--------------------------------------------------------------------------
  1378. //
  1379. // Defines
  1380. //
  1381. //--------------------------------------------------------------------------
  1382. #define DS_RETEST_SECONDS 3
  1383. #define CVT_BASE (1000 * 1000 * 10)
  1384. #define CVT_SECONDS (1)
  1385. #define CERTTYPE_SECURITY_DESCRIPTOR_NAME L"NTSecurityDescriptor"
  1386. #define TEMPLATE_CONTAINER_NAME L"CN=Certificate Templates,CN=Public Key Services,CN=Services,"
  1387. #define SCHEMA_CONTAINER_NAME L"CN=Schema,"
  1388. HRESULT myHError(HRESULT hr)
  1389. {
  1390. if (S_OK != hr && S_FALSE != hr && !FAILED(hr))
  1391. {
  1392. hr = HRESULT_FROM_WIN32(hr);
  1393. if ( SUCCEEDED (hr) )
  1394. {
  1395. // A call failed without properly setting an error condition!
  1396. hr = E_UNEXPECTED;
  1397. }
  1398. }
  1399. return(hr);
  1400. }
  1401. HRESULT
  1402. myDupString(
  1403. IN WCHAR const *pwszIn,
  1404. IN WCHAR **ppwszOut)
  1405. {
  1406. HRESULT hr = S_OK;
  1407. size_t cb = (wcslen(pwszIn) + 1) * sizeof(WCHAR);
  1408. *ppwszOut = (WCHAR *) LocalAlloc(LMEM_FIXED, cb);
  1409. if (NULL == *ppwszOut)
  1410. {
  1411. hr = E_OUTOFMEMORY;
  1412. goto error;
  1413. }
  1414. CopyMemory(*ppwszOut, pwszIn, cb);
  1415. hr = S_OK;
  1416. error:
  1417. return(hr);
  1418. }
  1419. DWORD
  1420. CAGetAuthoritativeDomainDn(
  1421. IN LDAP* LdapHandle,
  1422. OUT CString* pszDomainDn,
  1423. OUT CString* pszConfigDn
  1424. )
  1425. /*++
  1426. Routine Description:
  1427. This routine simply queries the operational attributes for the
  1428. domaindn and configdn.
  1429. The strings returned by this routine must be freed by the caller
  1430. using RtlFreeHeap() using the process heap.
  1431. Parameters:
  1432. LdapHandle : a valid handle to an ldap session
  1433. pszDomainDn : a pointer to a string to be allocated in this routine
  1434. pszConfigDn : a pointer to a string to be allocated in this routine
  1435. Return Values:
  1436. An error from the win32 error space.
  1437. ERROR_SUCCESS and
  1438. Other operation errors.
  1439. --*/
  1440. {
  1441. DWORD WinError = ERROR_SUCCESS;
  1442. ULONG LdapError;
  1443. LDAPMessage *SearchResult = NULL;
  1444. LDAPMessage *Entry = NULL;
  1445. WCHAR *Attr = NULL;
  1446. BerElement *BerElement;
  1447. WCHAR **Values = NULL;
  1448. WCHAR *AttrArray[3];
  1449. WCHAR *DefaultNamingContext = L"defaultNamingContext";
  1450. WCHAR *ConfigNamingContext = L"configurationNamingContext";
  1451. WCHAR *ObjectClassFilter = L"objectClass=*";
  1452. //
  1453. // These must be present
  1454. //
  1455. //
  1456. // Set the out parameters to null
  1457. //
  1458. if ( pszDomainDn )
  1459. *pszDomainDn = L"";
  1460. if ( pszConfigDn )
  1461. *pszConfigDn = L"";
  1462. //
  1463. // Query for the ldap server oerational attributes to obtain the default
  1464. // naming context.
  1465. //
  1466. AttrArray[0] = DefaultNamingContext;
  1467. AttrArray[1] = ConfigNamingContext; // this is the sentinel
  1468. AttrArray[2] = NULL; // this is the sentinel
  1469. __try
  1470. {
  1471. LdapError = ldap_search_sW(LdapHandle,
  1472. NULL,
  1473. LDAP_SCOPE_BASE,
  1474. ObjectClassFilter,
  1475. AttrArray,
  1476. FALSE,
  1477. &SearchResult);
  1478. WinError = LdapMapErrorToWin32(LdapError);
  1479. if (ERROR_SUCCESS == WinError) {
  1480. Entry = ldap_first_entry(LdapHandle, SearchResult);
  1481. if (Entry)
  1482. {
  1483. Attr = ldap_first_attributeW(LdapHandle, Entry, &BerElement);
  1484. while (Attr)
  1485. {
  1486. if (!_wcsicmp(Attr, DefaultNamingContext))
  1487. {
  1488. if ( pszDomainDn )
  1489. {
  1490. Values = ldap_get_values(LdapHandle, Entry, Attr);
  1491. if (Values && Values[0])
  1492. {
  1493. *pszDomainDn = Values[0];
  1494. }
  1495. ldap_value_free(Values);
  1496. }
  1497. }
  1498. else if (!_wcsicmp(Attr, ConfigNamingContext))
  1499. {
  1500. if ( pszConfigDn )
  1501. {
  1502. Values = ldap_get_values(LdapHandle, Entry, Attr);
  1503. if (Values && Values[0])
  1504. {
  1505. *pszConfigDn = Values[0];
  1506. }
  1507. ldap_value_free(Values);
  1508. }
  1509. }
  1510. Attr = ldap_next_attribute(LdapHandle, Entry, BerElement);
  1511. }
  1512. }
  1513. if ( pszDomainDn && pszDomainDn->IsEmpty () )
  1514. {
  1515. //
  1516. // We could get the default domain - bail out
  1517. //
  1518. WinError = ERROR_CANT_ACCESS_DOMAIN_INFO;
  1519. }
  1520. else if ( pszConfigDn && pszConfigDn->IsEmpty () )
  1521. {
  1522. //
  1523. // We could get the default domain - bail out
  1524. //
  1525. WinError = ERROR_CANT_ACCESS_DOMAIN_INFO;
  1526. }
  1527. }
  1528. }
  1529. __except(WinError = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)
  1530. {
  1531. }
  1532. // make sure we free this
  1533. if (SearchResult)
  1534. ldap_msgfree( SearchResult );
  1535. return WinError;
  1536. }
  1537. HRESULT myDoesDSExist(IN BOOL fRetry)
  1538. {
  1539. HRESULT hr = S_OK;
  1540. static BOOL s_fKnowDSExists = FALSE;
  1541. static HRESULT s_hrDSExists = HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN);
  1542. static FILETIME s_ftNextTest = {0,0};
  1543. if (s_fKnowDSExists && (s_hrDSExists != S_OK) && fRetry)
  1544. // s_fKnowDSExists = FALSE; // force a retry
  1545. {
  1546. FILETIME ftCurrent;
  1547. GetSystemTimeAsFileTime(&ftCurrent);
  1548. // if Compare is < 0 (next < current), force retest
  1549. if (0 > CompareFileTime(&s_ftNextTest, &ftCurrent))
  1550. s_fKnowDSExists = FALSE;
  1551. }
  1552. if (!s_fKnowDSExists)
  1553. {
  1554. GetSystemTimeAsFileTime(&s_ftNextTest);
  1555. // set NEXT in 100ns increments
  1556. ((LARGE_INTEGER *) &s_ftNextTest)->QuadPart +=
  1557. (__int64) (CVT_BASE * CVT_SECONDS * 60) * DS_RETEST_SECONDS;
  1558. // NetApi32 is delay loaded, so wrap to catch problems when it's not available
  1559. __try
  1560. {
  1561. DOMAIN_CONTROLLER_INFO *pDCI;
  1562. DSROLE_PRIMARY_DOMAIN_INFO_BASIC *pDsRole;
  1563. // ensure we're not standalone
  1564. pDsRole = NULL;
  1565. hr = DsRoleGetPrimaryDomainInformation( // Delayload wrapped
  1566. NULL,
  1567. DsRolePrimaryDomainInfoBasic,
  1568. (BYTE **) &pDsRole);
  1569. if (S_OK == hr &&
  1570. (pDsRole->MachineRole == DsRole_RoleStandaloneServer ||
  1571. pDsRole->MachineRole == DsRole_RoleStandaloneWorkstation))
  1572. {
  1573. hr = HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN);
  1574. }
  1575. if (NULL != pDsRole)
  1576. {
  1577. DsRoleFreeMemory(pDsRole); // Delayload wrapped
  1578. }
  1579. if (S_OK == hr)
  1580. {
  1581. // not standalone; return info on our DS
  1582. pDCI = NULL;
  1583. hr = DsGetDcName( // Delayload wrapped
  1584. NULL,
  1585. NULL,
  1586. NULL,
  1587. NULL,
  1588. DS_DIRECTORY_SERVICE_PREFERRED,
  1589. &pDCI);
  1590. if (S_OK == hr && 0 == (pDCI->Flags & DS_DS_FLAG))
  1591. {
  1592. hr = HRESULT_FROM_WIN32(ERROR_CANT_ACCESS_DOMAIN_INFO);
  1593. }
  1594. if (NULL != pDCI)
  1595. {
  1596. NetApiBufferFree(pDCI); // Delayload wrapped
  1597. }
  1598. }
  1599. s_fKnowDSExists = TRUE;
  1600. }
  1601. __except(hr = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)
  1602. {
  1603. }
  1604. // else just allow users without netapi flounder with timeouts
  1605. // if ds not available...
  1606. s_hrDSExists = myHError(hr);
  1607. }
  1608. return(s_hrDSExists);
  1609. }
  1610. HRESULT
  1611. myRobustLdapBindEx(
  1612. OUT LDAP ** ppldap,
  1613. OPTIONAL OUT LPWSTR* ppszForestDNSName,
  1614. IN BOOL fGC)
  1615. {
  1616. HRESULT hr = S_OK;
  1617. BOOL fForceRediscovery = FALSE;
  1618. DWORD dwGetDCFlags = DS_RETURN_DNS_NAME;
  1619. PDOMAIN_CONTROLLER_INFO pDomainInfo = NULL;
  1620. LDAP *pld = NULL;
  1621. WCHAR const *pwszDomainControllerName = NULL;
  1622. ULONG ldaperr = 0;
  1623. if (fGC)
  1624. {
  1625. dwGetDCFlags |= DS_GC_SERVER_REQUIRED;
  1626. }
  1627. do {
  1628. if (fForceRediscovery)
  1629. {
  1630. dwGetDCFlags |= DS_FORCE_REDISCOVERY;
  1631. }
  1632. ldaperr = LDAP_SERVER_DOWN;
  1633. // netapi32!DsGetDcName is delay loaded, so wrap
  1634. __try
  1635. {
  1636. // Get the GC location
  1637. hr = DsGetDcName(
  1638. NULL, // Delayload wrapped
  1639. NULL,
  1640. NULL,
  1641. NULL,
  1642. dwGetDCFlags,
  1643. &pDomainInfo);
  1644. }
  1645. __except(hr = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)
  1646. {
  1647. }
  1648. if (S_OK != hr)
  1649. {
  1650. hr = HRESULT_FROM_WIN32(hr);
  1651. if (fForceRediscovery)
  1652. {
  1653. goto error;
  1654. }
  1655. fForceRediscovery = TRUE;
  1656. continue;
  1657. }
  1658. if (NULL == pDomainInfo ||
  1659. (fGC && 0 == (DS_GC_FLAG & pDomainInfo->Flags)) ||
  1660. 0 == (DS_DNS_CONTROLLER_FLAG & pDomainInfo->Flags) ||
  1661. NULL == pDomainInfo->DomainControllerName)
  1662. {
  1663. if (!fForceRediscovery)
  1664. {
  1665. fForceRediscovery = TRUE;
  1666. continue;
  1667. }
  1668. hr = HRESULT_FROM_WIN32(ERROR_CANT_ACCESS_DOMAIN_INFO);
  1669. goto error;
  1670. }
  1671. pwszDomainControllerName = pDomainInfo->DomainControllerName;
  1672. // skip past forward slashes (why are they there?)
  1673. while (L'\\' == *pwszDomainControllerName)
  1674. {
  1675. pwszDomainControllerName++;
  1676. }
  1677. // bind to ds
  1678. pld = ldap_init(
  1679. const_cast<WCHAR *>(pwszDomainControllerName),
  1680. fGC? LDAP_GC_PORT : LDAP_PORT);
  1681. if (NULL == pld)
  1682. {
  1683. ldaperr = LdapGetLastError();
  1684. }
  1685. else
  1686. {
  1687. // do this because we're explicitly setting DC name
  1688. ldaperr = ldap_set_option(pld, LDAP_OPT_AREC_EXCLUSIVE, LDAP_OPT_ON);
  1689. ldaperr = ldap_bind_s(pld, NULL, NULL, LDAP_AUTH_NEGOTIATE);
  1690. }
  1691. hr = myHError(LdapMapErrorToWin32(ldaperr));
  1692. if (fForceRediscovery)
  1693. {
  1694. break;
  1695. }
  1696. fForceRediscovery = TRUE;
  1697. } while (LDAP_SERVER_DOWN == ldaperr);
  1698. // everything's cool, party down
  1699. if (S_OK == hr)
  1700. {
  1701. if (NULL != ppszForestDNSName)
  1702. {
  1703. hr = myDupString(
  1704. pDomainInfo->DomainControllerName,
  1705. ppszForestDNSName);
  1706. if(S_OK != hr)
  1707. goto error;
  1708. }
  1709. *ppldap = pld;
  1710. pld = NULL;
  1711. }
  1712. error:
  1713. if (NULL != pld)
  1714. {
  1715. ldap_unbind(pld);
  1716. }
  1717. // we know netapi32 was already loaded safely (that's where we got
  1718. // pDomainInfo), so no need to wrap
  1719. if (NULL != pDomainInfo)
  1720. {
  1721. NetApiBufferFree(pDomainInfo); // Delayload wrapped
  1722. }
  1723. return(hr);
  1724. }
  1725. HRESULT
  1726. myRobustLdapBind(
  1727. OUT LDAP ** ppldap,
  1728. IN BOOL fGC)
  1729. {
  1730. return(myRobustLdapBindEx(ppldap, NULL, fGC));
  1731. }
  1732. void CheckDomainVersion ()
  1733. {
  1734. _TRACE (1, L"Entering CheckDomainVersion()\n");
  1735. AFX_MANAGE_STATE (AfxGetStaticModuleState ());
  1736. HRESULT hr=S_OK;
  1737. DWORD dwErr=0;
  1738. ULONG ldaperr=0;
  1739. struct l_timeval timeout;
  1740. LPWSTR awszAttr[2];
  1741. LDAP *pld = NULL;
  1742. CString szConfig;
  1743. CString szDN;
  1744. LDAPMessage *SearchResult = NULL;
  1745. //*************************************************************
  1746. //
  1747. // check the schema version
  1748. //
  1749. _TRACE (0, L"Checking the schema version...\n");
  1750. //retrieve the ldap handle and the config string
  1751. if(S_OK != myDoesDSExist(TRUE))
  1752. {
  1753. _TRACE (0, L"No DS exists.\n");
  1754. goto error;
  1755. }
  1756. if(S_OK != (hr = myRobustLdapBind(&pld, FALSE)))
  1757. {
  1758. _TRACE (0, L"Error: Failed to bind to the DS.\n");
  1759. goto error;
  1760. }
  1761. dwErr = CAGetAuthoritativeDomainDn(pld, NULL, &szConfig);
  1762. if(ERROR_SUCCESS != dwErr)
  1763. {
  1764. _TRACE (0, L"Error: Failed to get the domain name.\n");
  1765. hr = HRESULT_FROM_WIN32(dwErr);
  1766. goto error;
  1767. }
  1768. szDN = SCHEMA_CONTAINER_NAME;
  1769. szDN += szConfig;
  1770. timeout.tv_sec = 300;
  1771. timeout.tv_usec = 0;
  1772. awszAttr[0]=L"cn";
  1773. awszAttr[1]=NULL;
  1774. ldaperr = ldap_search_stW(
  1775. pld,
  1776. const_cast <PWCHAR>((PCWSTR) szDN),
  1777. LDAP_SCOPE_ONELEVEL,
  1778. L"(cn=ms-PKI-Enrollment-Flag)",
  1779. awszAttr,
  1780. 0,
  1781. &timeout,
  1782. &SearchResult);
  1783. if ( LDAP_SUCCESS != ldaperr )
  1784. {
  1785. _TRACE (0, L"We have W2K Schema. Exit\n");
  1786. g_bSchemaIsW2K = true;
  1787. hr = S_OK;
  1788. goto error;
  1789. }
  1790. error:
  1791. if(SearchResult)
  1792. ldap_msgfree(SearchResult);
  1793. if (pld)
  1794. ldap_unbind(pld);
  1795. _TRACE (1, L"Entering CheckDomainVersion ()\n");
  1796. }