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.

11369 lines
357 KiB

  1. //+-------------------------------------------------------------------------
  2. // Microsoft Windows
  3. //
  4. // Copyright (C) Microsoft Corporation, 1995 - 1999
  5. //
  6. // File: logstor.cpp
  7. //
  8. // Contents: Registry Certificate Store Provider APIs
  9. //
  10. // Functions: I_RegStoreDllMain
  11. // I_CertDllOpenRegStoreProv
  12. // CertRegisterSystemStore
  13. // CertRegisterPhysicalStore
  14. // CertUnregisterSystemStore
  15. // CertUnregisterPhysicalStore
  16. // CertEnumSystemStoreLocation
  17. // CertEnumSystemStore
  18. // CertEnumPhysicalStore
  19. // I_CertDllOpenSystemRegistryStoreProvW
  20. // I_CertDllOpenSystemRegistryStoreProvA
  21. // I_CertDllOpenSystemStoreProvW
  22. // I_CertDllOpenSystemStoreProvA
  23. // I_CertDllOpenPhysicalStoreProvW
  24. //
  25. // History: 28-Dec-96 philh created
  26. // 13-Aug-96 philh added change notify and resync support
  27. // 24-Aug-96 philh added logical store support
  28. //--------------------------------------------------------------------------
  29. #include "global.hxx"
  30. #include <dbgdef.h>
  31. #ifdef STATIC
  32. #undef STATIC
  33. #endif
  34. #define STATIC
  35. // Note, this flag must not collide with CertControlStore dwFlags
  36. #define REG_STORE_CTRL_CANCEL_NOTIFY_FLAG 0x80000000
  37. // Pointer to an allocated LONG containing thread's enum recursion depth
  38. static HCRYPTTLS hTlsEnumPhysicalStoreDepth;
  39. #define MAX_ENUM_PHYSICAL_STORE_DEPTH 20
  40. #define SYSTEM_STORE_REGPATH L"Software\\Microsoft\\SystemCertificates"
  41. #define PHYSICAL_STORES_SUBKEY_NAME L"PhysicalStores"
  42. #define CONST_OID_STR_PREFIX_CHAR '#'
  43. #define SERVICES_REGPATH L"Software\\Microsoft\\Cryptography\\Services"
  44. #define SYSTEM_CERTIFICATES_SUBKEY_NAME L"SystemCertificates"
  45. #define GROUP_POLICY_STORE_REGPATH L"Software\\Policies\\Microsoft\\SystemCertificates"
  46. #define ENTERPRISE_STORE_REGPATH L"Software\\Microsoft\\EnterpriseCertificates"
  47. #define ROAMING_MY_STORE_SUBDIR L"Microsoft\\SystemCertificates\\My"
  48. #define ROAMING_REQUEST_STORE_SUBDIR L"Microsoft\\SystemCertificates\\Request"
  49. #define REGISTER_FLAGS_MASK (CERT_SYSTEM_STORE_MASK | \
  50. CERT_STORE_BACKUP_RESTORE_FLAG | \
  51. CERT_STORE_CREATE_NEW_FLAG)
  52. #define UNREGISTER_FLAGS_MASK (CERT_SYSTEM_STORE_MASK | \
  53. CERT_STORE_DELETE_FLAG | \
  54. CERT_STORE_BACKUP_RESTORE_FLAG | \
  55. CERT_STORE_OPEN_EXISTING_FLAG)
  56. #define ENUM_FLAGS_MASK (CERT_SYSTEM_STORE_MASK | \
  57. CERT_STORE_OPEN_EXISTING_FLAG | \
  58. CERT_STORE_MAXIMUM_ALLOWED_FLAG | \
  59. CERT_STORE_SHARE_CONTEXT_FLAG | \
  60. CERT_STORE_SHARE_STORE_FLAG | \
  61. CERT_STORE_BACKUP_RESTORE_FLAG | \
  62. CERT_STORE_READONLY_FLAG)
  63. #define OPEN_REG_FLAGS_MASK (CERT_STORE_CREATE_NEW_FLAG | \
  64. CERT_STORE_DELETE_FLAG | \
  65. CERT_STORE_OPEN_EXISTING_FLAG | \
  66. CERT_STORE_MAXIMUM_ALLOWED_FLAG | \
  67. CERT_STORE_SHARE_CONTEXT_FLAG | \
  68. CERT_STORE_SHARE_STORE_FLAG | \
  69. CERT_STORE_BACKUP_RESTORE_FLAG | \
  70. CERT_STORE_READONLY_FLAG | \
  71. CERT_STORE_MANIFOLD_FLAG | \
  72. CERT_STORE_UPDATE_KEYID_FLAG | \
  73. CERT_STORE_ENUM_ARCHIVED_FLAG | \
  74. CERT_STORE_SET_LOCALIZED_NAME_FLAG | \
  75. CERT_STORE_NO_CRYPT_RELEASE_FLAG | \
  76. CERT_REGISTRY_STORE_REMOTE_FLAG | \
  77. CERT_REGISTRY_STORE_SERIALIZED_FLAG | \
  78. CERT_REGISTRY_STORE_ROAMING_FLAG | \
  79. CERT_REGISTRY_STORE_CLIENT_GPT_FLAG | \
  80. CERT_REGISTRY_STORE_MY_IE_DIRTY_FLAG | \
  81. CERT_REGISTRY_STORE_LM_GPT_FLAG)
  82. #define OPEN_SYS_FLAGS_MASK (CERT_SYSTEM_STORE_MASK | \
  83. CERT_STORE_CREATE_NEW_FLAG | \
  84. CERT_STORE_DELETE_FLAG | \
  85. CERT_STORE_OPEN_EXISTING_FLAG | \
  86. CERT_STORE_MAXIMUM_ALLOWED_FLAG | \
  87. CERT_STORE_SHARE_CONTEXT_FLAG | \
  88. CERT_STORE_SHARE_STORE_FLAG | \
  89. CERT_STORE_BACKUP_RESTORE_FLAG | \
  90. CERT_STORE_READONLY_FLAG | \
  91. CERT_STORE_MANIFOLD_FLAG | \
  92. CERT_STORE_UPDATE_KEYID_FLAG | \
  93. CERT_STORE_ENUM_ARCHIVED_FLAG | \
  94. CERT_STORE_SET_LOCALIZED_NAME_FLAG | \
  95. CERT_STORE_NO_CRYPT_RELEASE_FLAG)
  96. #define OPEN_PHY_FLAGS_MASK (CERT_SYSTEM_STORE_MASK | \
  97. CERT_STORE_DELETE_FLAG | \
  98. CERT_STORE_OPEN_EXISTING_FLAG | \
  99. CERT_STORE_MAXIMUM_ALLOWED_FLAG | \
  100. CERT_STORE_SHARE_CONTEXT_FLAG | \
  101. CERT_STORE_SHARE_STORE_FLAG | \
  102. CERT_STORE_BACKUP_RESTORE_FLAG | \
  103. CERT_STORE_READONLY_FLAG | \
  104. CERT_STORE_MANIFOLD_FLAG | \
  105. CERT_STORE_UPDATE_KEYID_FLAG | \
  106. CERT_STORE_ENUM_ARCHIVED_FLAG | \
  107. CERT_STORE_SET_LOCALIZED_NAME_FLAG | \
  108. CERT_STORE_NO_CRYPT_RELEASE_FLAG)
  109. //+-------------------------------------------------------------------------
  110. // Common, global logical store critical section. Used by:
  111. // GptStore, Win95Store, RoamingStore.
  112. //--------------------------------------------------------------------------
  113. static CRITICAL_SECTION ILS_CriticalSection;
  114. //+-------------------------------------------------------------------------
  115. // Registry Store Context SubKeys
  116. //--------------------------------------------------------------------------
  117. #define CONTEXT_COUNT 3
  118. static const LPCWSTR rgpwszContextSubKeyName[CONTEXT_COUNT] = {
  119. L"Certificates",
  120. L"CRLs",
  121. L"CTLs"
  122. };
  123. #define KEYID_CONTEXT_NAME L"Keys"
  124. static DWORD rgdwContextTypeFlags[CONTEXT_COUNT] = {
  125. CERT_STORE_CERTIFICATE_CONTEXT_FLAG,
  126. CERT_STORE_CRL_CONTEXT_FLAG,
  127. CERT_STORE_CTL_CONTEXT_FLAG
  128. };
  129. #define MY_SYSTEM_INDEX 0
  130. #define ROOT_SYSTEM_INDEX 1
  131. #define TRUST_SYSTEM_INDEX 2
  132. #define CA_SYSTEM_INDEX 3
  133. #define USER_DS_SYSTEM_INDEX 4
  134. #define TRUST_PUB_SYSTEM_INDEX 5
  135. #define DISALLOWED_SYSTEM_INDEX 6
  136. #define AUTH_ROOT_SYSTEM_INDEX 7
  137. #define TRUST_PEOPLE_SYSTEM_INDEX 8
  138. #define MY_SYSTEM_FLAG (1 << MY_SYSTEM_INDEX)
  139. #define ROOT_SYSTEM_FLAG (1 << ROOT_SYSTEM_INDEX)
  140. #define TRUST_SYSTEM_FLAG (1 << TRUST_SYSTEM_INDEX)
  141. #define CA_SYSTEM_FLAG (1 << CA_SYSTEM_INDEX)
  142. #define USER_DS_SYSTEM_FLAG (1 << USER_DS_SYSTEM_INDEX)
  143. #define TRUST_PUB_SYSTEM_FLAG (1 << TRUST_PUB_SYSTEM_INDEX)
  144. #define DISALLOWED_SYSTEM_FLAG (1 << DISALLOWED_SYSTEM_INDEX)
  145. #define AUTH_ROOT_SYSTEM_FLAG (1 << AUTH_ROOT_SYSTEM_INDEX)
  146. #define TRUST_PEOPLE_SYSTEM_FLAG (1 << TRUST_PEOPLE_SYSTEM_INDEX)
  147. #define COMMON_SYSTEM_FLAGS ( \
  148. MY_SYSTEM_FLAG | \
  149. ROOT_SYSTEM_FLAG | \
  150. TRUST_SYSTEM_FLAG | \
  151. CA_SYSTEM_FLAG | \
  152. TRUST_PUB_SYSTEM_FLAG | \
  153. DISALLOWED_SYSTEM_FLAG | \
  154. AUTH_ROOT_SYSTEM_FLAG | \
  155. TRUST_PEOPLE_SYSTEM_FLAG \
  156. )
  157. #define wsz_MY_STORE L"My"
  158. #define wsz_ROOT_STORE L"Root"
  159. #define wsz_TRUST_STORE L"Trust"
  160. #define wsz_CA_STORE L"CA"
  161. #define wsz_USER_DS_STORE L"UserDS"
  162. #define wsz_TRUST_PUB_STORE L"TrustedPublisher"
  163. #define wsz_DISALLOWED_STORE L"Disallowed"
  164. #define wsz_AUTH_ROOT_STORE L"AuthRoot"
  165. #define wsz_TRUST_PEOPLE_STORE L"TrustedPeople"
  166. static LPCWSTR rgpwszPredefinedSystemStore[] = {
  167. wsz_MY_STORE,
  168. wsz_ROOT_STORE,
  169. wsz_TRUST_STORE,
  170. wsz_CA_STORE,
  171. wsz_USER_DS_STORE,
  172. wsz_TRUST_PUB_STORE,
  173. wsz_DISALLOWED_STORE,
  174. wsz_AUTH_ROOT_STORE,
  175. wsz_TRUST_PEOPLE_STORE
  176. };
  177. #define NUM_PREDEFINED_SYSTEM_STORE (sizeof(rgpwszPredefinedSystemStore) / \
  178. sizeof(rgpwszPredefinedSystemStore[0]))
  179. #define wsz_REQUEST_STORE L"Request"
  180. #define DEFAULT_PHYSICAL_INDEX 0
  181. #define AUTH_ROOT_PHYSICAL_INDEX 1
  182. #define GROUP_POLICY_PHYSICAL_INDEX 2
  183. #define LOCAL_MACHINE_PHYSICAL_INDEX 3
  184. #define DS_USER_CERT_PHYSICAL_INDEX 4
  185. #define LMGP_PHYSICAL_INDEX 5
  186. #define ENTERPRISE_PHYSICAL_INDEX 6
  187. #define NUM_PREDEFINED_PHYSICAL 7
  188. #define DEFAULT_PHYSICAL_FLAG (1 << DEFAULT_PHYSICAL_INDEX)
  189. #define AUTH_ROOT_PHYSICAL_FLAG (1 << AUTH_ROOT_PHYSICAL_INDEX)
  190. #define GROUP_POLICY_PHYSICAL_FLAG (1 << GROUP_POLICY_PHYSICAL_INDEX)
  191. #define LOCAL_MACHINE_PHYSICAL_FLAG (1 << LOCAL_MACHINE_PHYSICAL_INDEX)
  192. #define DS_USER_CERT_PHYSICAL_FLAG (1 << DS_USER_CERT_PHYSICAL_INDEX)
  193. #define LMGP_PHYSICAL_FLAG (1 << LMGP_PHYSICAL_INDEX)
  194. #define ENTERPRISE_PHYSICAL_FLAG (1 << ENTERPRISE_PHYSICAL_INDEX)
  195. static LPCWSTR rgpwszPredefinedPhysical[NUM_PREDEFINED_PHYSICAL] = {
  196. CERT_PHYSICAL_STORE_DEFAULT_NAME,
  197. CERT_PHYSICAL_STORE_AUTH_ROOT_NAME,
  198. CERT_PHYSICAL_STORE_GROUP_POLICY_NAME,
  199. CERT_PHYSICAL_STORE_LOCAL_MACHINE_NAME,
  200. CERT_PHYSICAL_STORE_DS_USER_CERTIFICATE_NAME,
  201. CERT_PHYSICAL_STORE_LOCAL_MACHINE_GROUP_POLICY_NAME,
  202. CERT_PHYSICAL_STORE_ENTERPRISE_NAME,
  203. };
  204. #define NOT_IN_REGISTRY_SYSTEM_STORE_LOCATION_FLAG 0x1
  205. #define REMOTABLE_SYSTEM_STORE_LOCATION_FLAG 0x2
  206. #define SERIALIZED_SYSTEM_STORE_LOCATION_FLAG 0x4
  207. #define LM_SYSTEM_STORE_LOCATION_FLAG 0x8
  208. typedef struct _SYSTEM_STORE_LOCATION_INFO {
  209. DWORD dwFlags;
  210. DWORD dwPredefinedSystemFlags;
  211. DWORD dwPredefinedPhysicalFlags;
  212. } SYSTEM_STORE_LOCATION_INFO, *PSYSTEM_STORE_LOCATION_INFO;
  213. static const SYSTEM_STORE_LOCATION_INFO rgSystemStoreLocationInfo[] = {
  214. // Not Defined 0
  215. NOT_IN_REGISTRY_SYSTEM_STORE_LOCATION_FLAG,
  216. 0,
  217. 0,
  218. // CERT_SYSTEM_STORE_CURRENT_USER_ID 1
  219. 0,
  220. COMMON_SYSTEM_FLAGS | USER_DS_SYSTEM_FLAG,
  221. DEFAULT_PHYSICAL_FLAG | GROUP_POLICY_PHYSICAL_FLAG |
  222. LOCAL_MACHINE_PHYSICAL_FLAG,
  223. // CERT_SYSTEM_STORE_LOCAL_MACHINE_ID 2
  224. LM_SYSTEM_STORE_LOCATION_FLAG | REMOTABLE_SYSTEM_STORE_LOCATION_FLAG,
  225. COMMON_SYSTEM_FLAGS,
  226. DEFAULT_PHYSICAL_FLAG | GROUP_POLICY_PHYSICAL_FLAG |
  227. ENTERPRISE_PHYSICAL_FLAG,
  228. // Not Defined 3
  229. NOT_IN_REGISTRY_SYSTEM_STORE_LOCATION_FLAG,
  230. 0,
  231. 0,
  232. // CERT_SYSTEM_STORE_CURRENT_SERVICE_ID 4
  233. LM_SYSTEM_STORE_LOCATION_FLAG,
  234. COMMON_SYSTEM_FLAGS,
  235. DEFAULT_PHYSICAL_FLAG | LOCAL_MACHINE_PHYSICAL_FLAG,
  236. // CERT_SYSTEM_STORE_SERVICES_ID 5
  237. LM_SYSTEM_STORE_LOCATION_FLAG | REMOTABLE_SYSTEM_STORE_LOCATION_FLAG,
  238. COMMON_SYSTEM_FLAGS,
  239. DEFAULT_PHYSICAL_FLAG | LOCAL_MACHINE_PHYSICAL_FLAG,
  240. // CERT_SYSTEM_STORE_USERS_ID 6
  241. REMOTABLE_SYSTEM_STORE_LOCATION_FLAG,
  242. COMMON_SYSTEM_FLAGS,
  243. DEFAULT_PHYSICAL_FLAG | LOCAL_MACHINE_PHYSICAL_FLAG,
  244. // CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY_ID 7
  245. //SERIALIZED_SYSTEM_STORE_LOCATION_FLAG,
  246. 0,
  247. COMMON_SYSTEM_FLAGS,
  248. DEFAULT_PHYSICAL_FLAG,
  249. // CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY_ID 8
  250. //SERIALIZED_SYSTEM_STORE_LOCATION_FLAG |
  251. LM_SYSTEM_STORE_LOCATION_FLAG | REMOTABLE_SYSTEM_STORE_LOCATION_FLAG,
  252. COMMON_SYSTEM_FLAGS,
  253. DEFAULT_PHYSICAL_FLAG,
  254. // CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE_ID 9
  255. LM_SYSTEM_STORE_LOCATION_FLAG | REMOTABLE_SYSTEM_STORE_LOCATION_FLAG,
  256. COMMON_SYSTEM_FLAGS,
  257. DEFAULT_PHYSICAL_FLAG
  258. };
  259. #define NUM_SYSTEM_STORE_LOCATION (sizeof(rgSystemStoreLocationInfo) / \
  260. sizeof(rgSystemStoreLocationInfo[0]))
  261. #define CURRENT_USER_ROOT_PHYSICAL_FLAGS ( \
  262. DEFAULT_PHYSICAL_FLAG | \
  263. LOCAL_MACHINE_PHYSICAL_FLAG \
  264. )
  265. #define LOCAL_MACHINE_ROOT_PHYSICAL_FLAGS ( \
  266. DEFAULT_PHYSICAL_FLAG | \
  267. AUTH_ROOT_PHYSICAL_FLAG | \
  268. GROUP_POLICY_PHYSICAL_FLAG | \
  269. ENTERPRISE_PHYSICAL_FLAG \
  270. )
  271. #define USERS_ROOT_PHYSICAL_FLAGS ( \
  272. LOCAL_MACHINE_PHYSICAL_FLAG \
  273. )
  274. #define MY_PHYSICAL_FLAGS ( \
  275. DEFAULT_PHYSICAL_FLAG \
  276. )
  277. #define USER_DS_PHYSICAL_FLAGS ( \
  278. DS_USER_CERT_PHYSICAL_FLAG \
  279. )
  280. #define CURRENT_USER_TRUST_PUB_PHYSICAL_FLAGS ( \
  281. DEFAULT_PHYSICAL_FLAG | \
  282. LOCAL_MACHINE_PHYSICAL_FLAG | \
  283. GROUP_POLICY_PHYSICAL_FLAG \
  284. )
  285. #define LOCAL_MACHINE_TRUST_PUB_PHYSICAL_FLAGS ( \
  286. DEFAULT_PHYSICAL_FLAG | \
  287. GROUP_POLICY_PHYSICAL_FLAG | \
  288. ENTERPRISE_PHYSICAL_FLAG \
  289. )
  290. #define sz_CRYPTNET_DLL "cryptnet.dll"
  291. #define sz_GetUserDsStoreUrl "I_CryptNetGetUserDsStoreUrl"
  292. typedef BOOL (WINAPI *PFN_GET_USER_DS_STORE_URL)(
  293. IN LPWSTR pwszUserAttribute,
  294. OUT LPWSTR* ppwszUrl
  295. );
  296. #define wsz_USER_CERTIFICATE_ATTR L"userCertificate"
  297. #define PHYSICAL_NAME_INDEX 0
  298. #define SYSTEM_NAME_INDEX 1
  299. #define SERVICE_NAME_INDEX 2
  300. #define USER_NAME_INDEX 2
  301. #define COMPUTER_NAME_INDEX 3
  302. #define SYSTEM_NAME_PATH_COUNT 4
  303. #define DEFAULT_USER_NAME L".Default"
  304. typedef struct _SYSTEM_NAME_INFO {
  305. LPWSTR rgpwszName[SYSTEM_NAME_PATH_COUNT];
  306. // non-NULL for relocated store. Note hKeyBase isn't opened and
  307. // doesn't need to be closed
  308. HKEY hKeyBase;
  309. } SYSTEM_NAME_INFO, *PSYSTEM_NAME_INFO;
  310. typedef struct _REG_STORE REG_STORE, *PREG_STORE;
  311. typedef struct _ILS_RESYNC_ENTRY {
  312. HANDLE hOrigEvent;
  313. // hDupEvent is NULL for CERT_STORE_CTRL_INHIBIT_DUPLICATE_HANDLE_FLAG
  314. HANDLE hDupEvent;
  315. PREG_STORE pRegStore;
  316. } ILS_RESYNC_ENTRY, *PILS_RESYNC_ENTRY;
  317. #define REG_CHANGE_INFO_TYPE 1
  318. #define CU_GPT_CHANGE_INFO_TYPE 2
  319. #define LM_GPT_CHANGE_INFO_TYPE 3
  320. typedef struct _REGISTRY_STORE_CHANGE_INFO {
  321. // REG_CHANGE_INFO_TYPE
  322. DWORD dwType;
  323. HANDLE hChange;
  324. HANDLE hRegWaitFor;
  325. DWORD cNotifyEntry;
  326. PILS_RESYNC_ENTRY rgNotifyEntry;
  327. } REGISTRY_STORE_CHANGE_INFO, *PREGISTRY_STORE_CHANGE_INFO;
  328. typedef struct _GPT_STORE_CHANGE_INFO {
  329. // CU_GPT_CHANGE_INFO_TYPE or LM_GPT_CHANGE_INFO_TYPE
  330. DWORD dwType;
  331. HKEY hKeyBase; // not duplicated
  332. PREG_STORE pRegStore; // NULL for LM_GPT_CHANGE_INFO_TYPE
  333. HKEY hPoliciesKey;
  334. HANDLE hPoliciesEvent;
  335. HANDLE hRegWaitFor;
  336. HANDLE hGPNotificationEvent;
  337. DWORD cNotifyEntry;
  338. PILS_RESYNC_ENTRY rgNotifyEntry;
  339. } GPT_STORE_CHANGE_INFO, *PGPT_STORE_CHANGE_INFO;
  340. //+-------------------------------------------------------------------------
  341. // Registry Store Provider handle information
  342. //
  343. // hMyNotifyChange is our internal NotifyChange event handle.
  344. //--------------------------------------------------------------------------
  345. struct _REG_STORE {
  346. HCERTSTORE hCertStore; // not duplicated
  347. CRITICAL_SECTION CriticalSection;
  348. HANDLE hMyNotifyChange;
  349. BOOL fResync; // when set, ignore callback deletes
  350. HKEY hKey;
  351. DWORD dwFlags;
  352. // Following field is applicable to the CurrentUser "Root" store
  353. BOOL fProtected;
  354. // Following field is applicable when
  355. // CERT_REGISTRY_STORE_SERIALIZED_FLAG is set in dwFlags
  356. BOOL fTouched; // set for write, delete or set property
  357. union {
  358. // Following field is applicable when
  359. // CERT_REGISTRY_STORE_CLIENT_GPT_FLAG is set in dwFlags
  360. CERT_REGISTRY_STORE_CLIENT_GPT_PARA GptPara;
  361. // Following field is applicable when
  362. // CERT_REGISTRY_STORE_ROAMING_FLAG is set in dwFlags
  363. LPWSTR pwszStoreDirectory;
  364. };
  365. union {
  366. // Following field is applicable for change notify of registry or
  367. // roaming file store
  368. PREGISTRY_STORE_CHANGE_INFO pRegistryStoreChangeInfo;
  369. // Following field is applicable for change notify of CU GPT store
  370. PGPT_STORE_CHANGE_INFO pGptStoreChangeInfo;
  371. };
  372. };
  373. typedef struct _ENUM_SYSTEM_STORE_LOCATION_INFO {
  374. DWORD dwFlags;
  375. LPCWSTR pwszLocation;
  376. } ENUM_SYSTEM_STORE_LOCATION_INFO, *PENUM_SYSTEM_STORE_LOCATION_INFO;
  377. // Predefined crypt32.dll locations. MUST NOT BE REGISTERED!!!
  378. static const ENUM_SYSTEM_STORE_LOCATION_INFO rgEnumSystemStoreLocationInfo[] = {
  379. CERT_SYSTEM_STORE_CURRENT_USER, L"CurrentUser",
  380. CERT_SYSTEM_STORE_LOCAL_MACHINE, L"LocalMachine",
  381. CERT_SYSTEM_STORE_CURRENT_SERVICE, L"CurrentService",
  382. CERT_SYSTEM_STORE_SERVICES, L"Services",
  383. CERT_SYSTEM_STORE_USERS, L"Users",
  384. CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY, L"CurrentUserGroupPolicy",
  385. CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY, L"LocalMachineGroupPolicy",
  386. CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, L"LocalMachineEnterprise"
  387. };
  388. #define ENUM_SYSTEM_STORE_LOCATION_CNT \
  389. (sizeof(rgEnumSystemStoreLocationInfo) / \
  390. sizeof(rgEnumSystemStoreLocationInfo[0]))
  391. #define OPEN_SYSTEM_STORE_PROV_FUNC_SET 0
  392. #define REGISTER_SYSTEM_STORE_FUNC_SET 1
  393. #define UNREGISTER_SYSTEM_STORE_FUNC_SET 2
  394. #define ENUM_SYSTEM_STORE_FUNC_SET 3
  395. #define REGISTER_PHYSICAL_STORE_FUNC_SET 4
  396. #define UNREGISTER_PHYSICAL_STORE_FUNC_SET 5
  397. #define ENUM_PHYSICAL_STORE_FUNC_SET 6
  398. #define FUNC_SET_COUNT 7
  399. static HCRYPTOIDFUNCSET rghFuncSet[FUNC_SET_COUNT];
  400. static const LPCSTR rgpszFuncName[FUNC_SET_COUNT] = {
  401. CRYPT_OID_OPEN_SYSTEM_STORE_PROV_FUNC,
  402. CRYPT_OID_REGISTER_SYSTEM_STORE_FUNC,
  403. CRYPT_OID_UNREGISTER_SYSTEM_STORE_FUNC,
  404. CRYPT_OID_ENUM_SYSTEM_STORE_FUNC,
  405. CRYPT_OID_REGISTER_PHYSICAL_STORE_FUNC,
  406. CRYPT_OID_UNREGISTER_PHYSICAL_STORE_FUNC,
  407. CRYPT_OID_ENUM_PHYSICAL_STORE_FUNC
  408. };
  409. typedef BOOL (WINAPI *PFN_REGISTER_SYSTEM_STORE)(
  410. IN const void *pvSystemStore,
  411. IN DWORD dwFlags,
  412. IN PCERT_SYSTEM_STORE_INFO pStoreInfo,
  413. IN OPTIONAL void *pvReserved
  414. );
  415. typedef BOOL (WINAPI *PFN_UNREGISTER_SYSTEM_STORE)(
  416. IN const void *pvSystemStore,
  417. IN DWORD dwFlags
  418. );
  419. typedef BOOL (WINAPI *PFN_ENUM_SYSTEM_STORE)(
  420. IN DWORD dwFlags,
  421. IN OPTIONAL void *pvSystemStoreLocationPara,
  422. IN void *pvArg,
  423. IN PFN_CERT_ENUM_SYSTEM_STORE pfnEnum
  424. );
  425. typedef BOOL (WINAPI *PFN_REGISTER_PHYSICAL_STORE)(
  426. IN const void *pvSystemStore,
  427. IN DWORD dwFlags,
  428. IN LPCWSTR pwszStoreName,
  429. IN PCERT_PHYSICAL_STORE_INFO pStoreInfo,
  430. IN OPTIONAL void *pvReserved
  431. );
  432. typedef BOOL (WINAPI *PFN_UNREGISTER_PHYSICAL_STORE)(
  433. IN const void *pvSystemStore,
  434. IN DWORD dwFlags,
  435. IN LPCWSTR pwszStoreName
  436. );
  437. typedef BOOL (WINAPI *PFN_ENUM_PHYSICAL_STORE)(
  438. IN const void *pvSystemStore,
  439. IN DWORD dwFlags,
  440. IN void *pvArg,
  441. IN PFN_CERT_ENUM_PHYSICAL_STORE pfnEnum
  442. );
  443. //+-------------------------------------------------------------------------
  444. // Registry Store Provider Functions.
  445. //--------------------------------------------------------------------------
  446. STATIC void WINAPI RegStoreProvClose(
  447. IN HCERTSTOREPROV hStoreProv,
  448. IN DWORD dwFlags
  449. );
  450. STATIC BOOL WINAPI RegStoreProvReadCert(
  451. IN HCERTSTOREPROV hStoreProv,
  452. IN PCCERT_CONTEXT pStoreCertContext,
  453. IN DWORD dwFlags,
  454. OUT PCCERT_CONTEXT *ppProvCertContext
  455. );
  456. STATIC BOOL WINAPI RegStoreProvWriteCert(
  457. IN HCERTSTOREPROV hStoreProv,
  458. IN PCCERT_CONTEXT pCertContext,
  459. IN DWORD dwFlags
  460. );
  461. STATIC BOOL WINAPI RegStoreProvDeleteCert(
  462. IN HCERTSTOREPROV hStoreProv,
  463. IN PCCERT_CONTEXT pCertContext,
  464. IN DWORD dwFlags
  465. );
  466. STATIC BOOL WINAPI RegStoreProvSetCertProperty(
  467. IN HCERTSTOREPROV hStoreProv,
  468. IN PCCERT_CONTEXT pCertContext,
  469. IN DWORD dwPropId,
  470. IN DWORD dwFlags,
  471. IN const void *pvData
  472. );
  473. STATIC BOOL WINAPI RegStoreProvReadCrl(
  474. IN HCERTSTOREPROV hStoreProv,
  475. IN PCCRL_CONTEXT pStoreCrlContext,
  476. IN DWORD dwFlags,
  477. OUT PCCRL_CONTEXT *ppProvCrlContext
  478. );
  479. STATIC BOOL WINAPI RegStoreProvWriteCrl(
  480. IN HCERTSTOREPROV hStoreProv,
  481. IN PCCRL_CONTEXT pCrlContext,
  482. IN DWORD dwFlags
  483. );
  484. STATIC BOOL WINAPI RegStoreProvDeleteCrl(
  485. IN HCERTSTOREPROV hStoreProv,
  486. IN PCCRL_CONTEXT pCrlContext,
  487. IN DWORD dwFlags
  488. );
  489. STATIC BOOL WINAPI RegStoreProvSetCrlProperty(
  490. IN HCERTSTOREPROV hStoreProv,
  491. IN PCCRL_CONTEXT pCrlContext,
  492. IN DWORD dwPropId,
  493. IN DWORD dwFlags,
  494. IN const void *pvData
  495. );
  496. STATIC BOOL WINAPI RegStoreProvReadCtl(
  497. IN HCERTSTOREPROV hStoreProv,
  498. IN PCCTL_CONTEXT pStoreCtlContext,
  499. IN DWORD dwFlags,
  500. OUT PCCTL_CONTEXT *ppProvCtlContext
  501. );
  502. STATIC BOOL WINAPI RegStoreProvWriteCtl(
  503. IN HCERTSTOREPROV hStoreProv,
  504. IN PCCTL_CONTEXT pCtlContext,
  505. IN DWORD dwFlags
  506. );
  507. STATIC BOOL WINAPI RegStoreProvDeleteCtl(
  508. IN HCERTSTOREPROV hStoreProv,
  509. IN PCCTL_CONTEXT pCtlContext,
  510. IN DWORD dwFlags
  511. );
  512. STATIC BOOL WINAPI RegStoreProvSetCtlProperty(
  513. IN HCERTSTOREPROV hStoreProv,
  514. IN PCCTL_CONTEXT pCtlContext,
  515. IN DWORD dwPropId,
  516. IN DWORD dwFlags,
  517. IN const void *pvData
  518. );
  519. STATIC BOOL WINAPI RegStoreProvControl(
  520. IN HCERTSTOREPROV hStoreProv,
  521. IN DWORD dwFlags,
  522. IN DWORD dwCtrlType,
  523. IN void const *pvCtrlPara
  524. );
  525. static void * const rgpvRegStoreProvFunc[] = {
  526. // CERT_STORE_PROV_CLOSE_FUNC 0
  527. RegStoreProvClose,
  528. // CERT_STORE_PROV_READ_CERT_FUNC 1
  529. RegStoreProvReadCert,
  530. // CERT_STORE_PROV_WRITE_CERT_FUNC 2
  531. RegStoreProvWriteCert,
  532. // CERT_STORE_PROV_DELETE_CERT_FUNC 3
  533. RegStoreProvDeleteCert,
  534. // CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC 4
  535. RegStoreProvSetCertProperty,
  536. // CERT_STORE_PROV_READ_CRL_FUNC 5
  537. RegStoreProvReadCrl,
  538. // CERT_STORE_PROV_WRITE_CRL_FUNC 6
  539. RegStoreProvWriteCrl,
  540. // CERT_STORE_PROV_DELETE_CRL_FUNC 7
  541. RegStoreProvDeleteCrl,
  542. // CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC 8
  543. RegStoreProvSetCrlProperty,
  544. // CERT_STORE_PROV_READ_CTL_FUNC 9
  545. RegStoreProvReadCtl,
  546. // CERT_STORE_PROV_WRITE_CTL_FUNC 10
  547. RegStoreProvWriteCtl,
  548. // CERT_STORE_PROV_DELETE_CTL_FUNC 11
  549. RegStoreProvDeleteCtl,
  550. // CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC 12
  551. RegStoreProvSetCtlProperty,
  552. // CERT_STORE_PROV_CONTROL_FUNC 13
  553. RegStoreProvControl
  554. };
  555. #define REG_STORE_PROV_FUNC_COUNT (sizeof(rgpvRegStoreProvFunc) / \
  556. sizeof(rgpvRegStoreProvFunc[0]))
  557. STATIC BOOL WINAPI RootStoreProvWriteCert(
  558. IN HCERTSTOREPROV hStoreProv,
  559. IN PCCERT_CONTEXT pCertContext,
  560. IN DWORD dwFlags
  561. );
  562. STATIC BOOL WINAPI RootStoreProvDeleteCert(
  563. IN HCERTSTOREPROV hStoreProv,
  564. IN PCCERT_CONTEXT pCertContext,
  565. IN DWORD dwFlags
  566. );
  567. static void * const rgpvRootStoreProvFunc[] = {
  568. // CERT_STORE_PROV_CLOSE_FUNC 0
  569. RegStoreProvClose,
  570. // CERT_STORE_PROV_READ_CERT_FUNC 1
  571. RegStoreProvReadCert,
  572. // CERT_STORE_PROV_WRITE_CERT_FUNC 2
  573. RootStoreProvWriteCert,
  574. // CERT_STORE_PROV_DELETE_CERT_FUNC 3
  575. RootStoreProvDeleteCert,
  576. // CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC 4
  577. RegStoreProvSetCertProperty,
  578. // CERT_STORE_PROV_READ_CRL_FUNC 5
  579. RegStoreProvReadCrl,
  580. // CERT_STORE_PROV_WRITE_CRL_FUNC 6
  581. RegStoreProvWriteCrl,
  582. // CERT_STORE_PROV_DELETE_CRL_FUNC 7
  583. RegStoreProvDeleteCrl,
  584. // CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC 8
  585. RegStoreProvSetCrlProperty,
  586. // CERT_STORE_PROV_READ_CTL_FUNC 9
  587. RegStoreProvReadCtl,
  588. // CERT_STORE_PROV_WRITE_CTL_FUNC 10
  589. RegStoreProvWriteCtl,
  590. // CERT_STORE_PROV_DELETE_CTL_FUNC 11
  591. RegStoreProvDeleteCtl,
  592. // CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC 12
  593. RegStoreProvSetCtlProperty,
  594. // CERT_STORE_PROV_CONTROL_FUNC 13
  595. RegStoreProvControl
  596. };
  597. #define ROOT_STORE_PROV_FUNC_COUNT (sizeof(rgpvRootStoreProvFunc) / \
  598. sizeof(rgpvRootStoreProvFunc[0]))
  599. //+-------------------------------------------------------------------------
  600. // Add the serialized store to the store.
  601. //
  602. // from newstor.cpp
  603. //--------------------------------------------------------------------------
  604. extern BOOL WINAPI I_CertAddSerializedStore(
  605. IN HCERTSTORE hCertStore,
  606. IN BYTE *pbStore,
  607. IN DWORD cbStore
  608. );
  609. LPWSTR ILS_AllocAndCopyString(
  610. IN LPCWSTR pwszSrc,
  611. IN LONG cchSrc
  612. )
  613. {
  614. LPWSTR pwszDst;
  615. if (cchSrc < 0)
  616. cchSrc = wcslen(pwszSrc);
  617. if (NULL == (pwszDst = (LPWSTR) PkiNonzeroAlloc(
  618. (cchSrc + 1) * sizeof(WCHAR))))
  619. return NULL;
  620. if (0 < cchSrc)
  621. memcpy((BYTE *) pwszDst, (BYTE *) pwszSrc, cchSrc * sizeof(WCHAR));
  622. pwszDst[cchSrc] = L'\0';
  623. return pwszDst;
  624. }
  625. extern
  626. BOOL
  627. WINAPI
  628. I_ProtectedRootDllMain(
  629. HMODULE hInst,
  630. ULONG ulReason,
  631. LPVOID lpReserved);
  632. //+=========================================================================
  633. // Register WaitFor Forward Function References
  634. //==========================================================================
  635. STATIC void RegWaitForProcessAttach();
  636. STATIC void RegWaitForProcessDetach();
  637. //+=========================================================================
  638. // Client "GPT" Store Forward Function References
  639. //==========================================================================
  640. STATIC void GptStoreProcessAttach();
  641. STATIC void GptStoreProcessDetach();
  642. STATIC BOOL OpenAllFromGptRegistry(
  643. IN PREG_STORE pRegStore,
  644. IN HCERTSTORE hCertStore
  645. );
  646. STATIC BOOL CommitAllToGptRegistry(
  647. IN PREG_STORE pRegStore,
  648. IN DWORD dwFlags
  649. );
  650. STATIC void GptStoreSignalAndFreeRegStoreResyncEntries(
  651. IN PREG_STORE pRegStore
  652. );
  653. STATIC void FreeGptStoreChangeInfo(
  654. IN OUT PGPT_STORE_CHANGE_INFO *ppInfo
  655. );
  656. STATIC BOOL RegGptStoreChange(
  657. IN PREG_STORE pRegStore,
  658. IN HANDLE hEvent,
  659. IN DWORD dwFlags
  660. );
  661. static inline BOOL IsClientGptStore(
  662. IN PSYSTEM_NAME_INFO pInfo,
  663. IN DWORD dwFlags
  664. )
  665. {
  666. DWORD dwStoreLocation = dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK;
  667. if (!(CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY == dwStoreLocation ||
  668. CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY == dwStoreLocation))
  669. return FALSE;
  670. if (dwFlags & (CERT_SYSTEM_STORE_RELOCATE_FLAG | CERT_STORE_DELETE_FLAG))
  671. return FALSE;
  672. return TRUE;
  673. }
  674. //+=========================================================================
  675. // Win95 Notify Store Forward Function References
  676. //==========================================================================
  677. // Following is created at ProcessAttach for Win95 clients
  678. static HANDLE hWin95NotifyEvent = NULL;
  679. STATIC void Win95StoreProcessAttach();
  680. STATIC void Win95StoreProcessDetach();
  681. STATIC void Win95StoreSignalAndFreeRegStoreResyncEntries(
  682. IN PREG_STORE pRegStore
  683. );
  684. STATIC BOOL RegWin95StoreChange(
  685. IN PREG_STORE pRegStore,
  686. IN HANDLE hEvent,
  687. IN DWORD dwFlags
  688. );
  689. //+=========================================================================
  690. // Roaming Store Forward Function References
  691. //==========================================================================
  692. STATIC void RoamingStoreProcessAttach();
  693. STATIC void RoamingStoreProcessDetach();
  694. LPWSTR
  695. ILS_GetRoamingStoreDirectory(
  696. IN LPCWSTR pwszStoreName
  697. );
  698. BOOL
  699. ILS_WriteElementToFile(
  700. IN LPCWSTR pwszStoreDir,
  701. IN LPCWSTR pwszContextName,
  702. IN const WCHAR wszHashName[MAX_HASH_NAME_LEN],
  703. IN DWORD dwFlags, // CERT_STORE_CREATE_NEW_FLAG or
  704. // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  705. IN const BYTE *pbElement,
  706. IN DWORD cbElement
  707. );
  708. BOOL
  709. ILS_ReadElementFromFile(
  710. IN LPCWSTR pwszStoreDir,
  711. IN LPCWSTR pwszContextName,
  712. IN const WCHAR wszHashName[MAX_HASH_NAME_LEN],
  713. IN DWORD dwFlags, // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  714. OUT BYTE **ppbElement,
  715. OUT DWORD *pcbElement
  716. );
  717. BOOL
  718. ILS_DeleteElementFromDirectory(
  719. IN LPCWSTR pwszStoreDir,
  720. IN LPCWSTR pwszContextName,
  721. IN const WCHAR wszHashName[MAX_HASH_NAME_LEN],
  722. IN DWORD dwFlags
  723. );
  724. typedef BOOL (*PFN_ILS_OPEN_ELEMENT)(
  725. IN const WCHAR wszHashName[MAX_HASH_NAME_LEN],
  726. IN const BYTE *pbElement,
  727. IN DWORD cbElement,
  728. IN void *pvArg
  729. );
  730. BOOL
  731. ILS_OpenAllElementsFromDirectory(
  732. IN LPCWSTR pwszStoreDir,
  733. IN LPCWSTR pwszContextName,
  734. IN DWORD dwFlags,
  735. IN void *pvArg,
  736. IN PFN_ILS_OPEN_ELEMENT pfnOpenElement
  737. );
  738. //+=========================================================================
  739. // Registry or Roaming Store Change Notify Functions
  740. //==========================================================================
  741. STATIC BOOL RegRegistryStoreChange(
  742. IN PREG_STORE pRegStore,
  743. IN HANDLE hEvent,
  744. IN DWORD dwFlags
  745. );
  746. STATIC void FreeRegistryStoreChange(
  747. IN PREG_STORE pRegStore
  748. );
  749. //+-------------------------------------------------------------------------
  750. // Dll initialization
  751. //--------------------------------------------------------------------------
  752. BOOL
  753. WINAPI
  754. I_RegStoreDllMain(
  755. HMODULE hInst,
  756. ULONG ulReason,
  757. LPVOID lpReserved)
  758. {
  759. BOOL fRet;
  760. DWORD i;
  761. if (!I_ProtectedRootDllMain(hInst, ulReason, lpReserved))
  762. return FALSE;
  763. switch (ulReason) {
  764. case DLL_PROCESS_ATTACH:
  765. for (i = 0; i < FUNC_SET_COUNT; i++) {
  766. if (NULL == (rghFuncSet[i] = CryptInitOIDFunctionSet(
  767. rgpszFuncName[i], 0)))
  768. goto CryptInitOIDFunctionSetError;
  769. }
  770. if (!Pki_InitializeCriticalSection(&ILS_CriticalSection))
  771. goto InitCritSectionError;
  772. if (NULL == (hTlsEnumPhysicalStoreDepth = I_CryptAllocTls())) {
  773. DeleteCriticalSection(&ILS_CriticalSection);
  774. goto CryptAllocTlsError;
  775. }
  776. RegWaitForProcessAttach();
  777. GptStoreProcessAttach();
  778. Win95StoreProcessAttach();
  779. RoamingStoreProcessAttach();
  780. break;
  781. case DLL_PROCESS_DETACH:
  782. RoamingStoreProcessDetach();
  783. Win95StoreProcessDetach();
  784. GptStoreProcessDetach();
  785. RegWaitForProcessDetach();
  786. DeleteCriticalSection(&ILS_CriticalSection);
  787. I_CryptFreeTls(hTlsEnumPhysicalStoreDepth, PkiFree);
  788. break;
  789. case DLL_THREAD_DETACH:
  790. PkiFree(I_CryptDetachTls(hTlsEnumPhysicalStoreDepth));
  791. break;
  792. default:
  793. break;
  794. }
  795. fRet = TRUE;
  796. CommonReturn:
  797. return fRet;
  798. ErrorReturn:
  799. I_ProtectedRootDllMain(hInst, DLL_PROCESS_DETACH, NULL);
  800. fRet = FALSE;
  801. goto CommonReturn;
  802. TRACE_ERROR(InitCritSectionError)
  803. TRACE_ERROR(CryptInitOIDFunctionSetError)
  804. TRACE_ERROR(CryptAllocTlsError)
  805. }
  806. //+-------------------------------------------------------------------------
  807. // Converts the bytes into UNICODE ASCII HEX
  808. //
  809. // Needs (cb * 2 + 1) * sizeof(WCHAR) bytes of space in wsz
  810. //--------------------------------------------------------------------------
  811. void ILS_BytesToWStr(DWORD cb, void* pv, LPWSTR wsz)
  812. {
  813. BYTE* pb = (BYTE*) pv;
  814. for (DWORD i = 0; i<cb; i++) {
  815. int b;
  816. b = (*pb & 0xF0) >> 4;
  817. *wsz++ = (WCHAR)( (b <= 9) ? b + L'0' : (b - 10) + L'A');
  818. b = *pb & 0x0F;
  819. *wsz++ = (WCHAR)( (b <= 9) ? b + L'0' : (b - 10) + L'A');
  820. pb++;
  821. }
  822. *wsz++ = 0;
  823. }
  824. //+-------------------------------------------------------------------------
  825. // Converts the UNICODE ASCII HEX to an array of bytes
  826. //--------------------------------------------------------------------------
  827. STATIC void WStrToBytes(
  828. IN const WCHAR wsz[MAX_HASH_NAME_LEN],
  829. OUT BYTE rgb[MAX_HASH_LEN],
  830. OUT DWORD *pcb
  831. )
  832. {
  833. BOOL fUpperNibble = TRUE;
  834. DWORD cb = 0;
  835. LPCWSTR pwsz = wsz;
  836. WCHAR wch;
  837. while (cb < MAX_HASH_LEN && (wch = *pwsz++)) {
  838. BYTE b;
  839. // only convert ascii hex characters 0..9, a..f, A..F
  840. // silently ignore all others
  841. if (wch >= L'0' && wch <= L'9')
  842. b = (BYTE) (wch - L'0');
  843. else if (wch >= L'a' && wch <= L'f')
  844. b = (BYTE) (10 + wch - L'a');
  845. else if (wch >= L'A' && wch <= L'F')
  846. b = (BYTE) (10 + wch - L'A');
  847. else
  848. continue;
  849. if (fUpperNibble) {
  850. rgb[cb] = (BYTE)( b << 4);
  851. fUpperNibble = FALSE;
  852. } else {
  853. rgb[cb] = (BYTE)( rgb[cb] | b);
  854. cb++;
  855. fUpperNibble = TRUE;
  856. }
  857. }
  858. *pcb = cb;
  859. }
  860. //+-------------------------------------------------------------------------
  861. // Lock and unlock registry functions
  862. //--------------------------------------------------------------------------
  863. static inline void LockRegStore(IN PREG_STORE pRegStore)
  864. {
  865. EnterCriticalSection(&pRegStore->CriticalSection);
  866. }
  867. static inline void UnlockRegStore(IN PREG_STORE pRegStore)
  868. {
  869. LeaveCriticalSection(&pRegStore->CriticalSection);
  870. }
  871. //+-------------------------------------------------------------------------
  872. // Checks if current thread is doing a Resync. Other threads block until
  873. // the resync completes
  874. //--------------------------------------------------------------------------
  875. STATIC BOOL IsInResync(IN PREG_STORE pRegStore)
  876. {
  877. BOOL fResync;
  878. LockRegStore(pRegStore);
  879. fResync = pRegStore->fResync;
  880. UnlockRegStore(pRegStore);
  881. return fResync;
  882. }
  883. //+=========================================================================
  884. // Low level context support functions
  885. //==========================================================================
  886. //+-------------------------------------------------------------------------
  887. // Get the certificate's registry value name by formatting its SHA1 hash as
  888. // UNICODE hex.
  889. //--------------------------------------------------------------------------
  890. STATIC BOOL GetCertRegValueName(
  891. IN PCCERT_CONTEXT pCertContext,
  892. OUT WCHAR wszRegName[MAX_CERT_REG_VALUE_NAME_LEN]
  893. )
  894. {
  895. BYTE rgbHash[MAX_HASH_LEN];
  896. DWORD cbHash = MAX_HASH_LEN;
  897. // get the thumbprint
  898. if(!CertGetCertificateContextProperty(
  899. pCertContext,
  900. CERT_SHA1_HASH_PROP_ID,
  901. rgbHash,
  902. &cbHash))
  903. return FALSE;
  904. // convert to a string
  905. ILS_BytesToWStr(cbHash, rgbHash, wszRegName);
  906. return TRUE;
  907. }
  908. //+-------------------------------------------------------------------------
  909. // Get the CRL's registry value name by formatting its SHA1 hash as
  910. // UNICODE hex.
  911. //--------------------------------------------------------------------------
  912. STATIC BOOL GetCrlRegValueName(
  913. IN PCCRL_CONTEXT pCrlContext,
  914. OUT WCHAR wszRegName[MAX_CERT_REG_VALUE_NAME_LEN]
  915. )
  916. {
  917. BYTE rgbHash[MAX_HASH_LEN];
  918. DWORD cbHash = MAX_HASH_LEN;
  919. // get the thumbprint
  920. if(!CertGetCRLContextProperty(
  921. pCrlContext,
  922. CERT_SHA1_HASH_PROP_ID,
  923. rgbHash,
  924. &cbHash))
  925. return FALSE;
  926. // convert to a string
  927. ILS_BytesToWStr(cbHash, rgbHash, wszRegName);
  928. return TRUE;
  929. }
  930. //+-------------------------------------------------------------------------
  931. // Get the CTL's registry value name by formatting its SHA1 hash as
  932. // UNICODE hex.
  933. //--------------------------------------------------------------------------
  934. STATIC BOOL GetCtlRegValueName(
  935. IN PCCTL_CONTEXT pCtlContext,
  936. OUT WCHAR wszRegName[MAX_CERT_REG_VALUE_NAME_LEN]
  937. )
  938. {
  939. BYTE rgbHash[MAX_HASH_LEN];
  940. DWORD cbHash = MAX_HASH_LEN;
  941. // get the thumbprint
  942. if(!CertGetCTLContextProperty(
  943. pCtlContext,
  944. CERT_SHA1_HASH_PROP_ID,
  945. rgbHash,
  946. &cbHash))
  947. return FALSE;
  948. // convert to a string
  949. ILS_BytesToWStr(cbHash, rgbHash, wszRegName);
  950. return TRUE;
  951. }
  952. //+-------------------------------------------------------------------------
  953. // Convert's the context's SHA1 hash to UNICODE hex. Returns TRUE if the
  954. // same as the specified Uniocde reg name.
  955. //--------------------------------------------------------------------------
  956. STATIC BOOL IsValidRegValueNameForContext(
  957. IN DWORD dwContextType,
  958. IN const void *pvContext,
  959. IN const WCHAR wszRegName[MAX_CERT_REG_VALUE_NAME_LEN]
  960. )
  961. {
  962. BOOL fResult;
  963. WCHAR wszContextHash[MAX_CERT_REG_VALUE_NAME_LEN];
  964. switch (dwContextType) {
  965. case CERT_STORE_CERTIFICATE_CONTEXT:
  966. fResult = GetCertRegValueName(
  967. (PCCERT_CONTEXT) pvContext, wszContextHash);
  968. break;
  969. case CERT_STORE_CRL_CONTEXT:
  970. fResult = GetCrlRegValueName(
  971. (PCCRL_CONTEXT) pvContext, wszContextHash);
  972. break;
  973. case CERT_STORE_CTL_CONTEXT:
  974. fResult = GetCtlRegValueName(
  975. (PCCTL_CONTEXT) pvContext, wszContextHash);
  976. break;
  977. default:
  978. goto InvalidContext;
  979. }
  980. if (!fResult)
  981. goto GetContextHashError;
  982. if (0 != _wcsicmp(wszRegName, wszContextHash))
  983. goto InvalidRegValueNameForContext;
  984. fResult = TRUE;
  985. CommonReturn:
  986. return fResult;
  987. ErrorReturn:
  988. fResult = FALSE;
  989. goto CommonReturn;
  990. SET_ERROR(InvalidContext, E_UNEXPECTED)
  991. TRACE_ERROR(GetContextHashError)
  992. SET_ERROR(InvalidRegValueNameForContext, ERROR_BAD_PATHNAME)
  993. }
  994. //+-------------------------------------------------------------------------
  995. // Deletes the context from the store.
  996. //--------------------------------------------------------------------------
  997. STATIC void DeleteContextFromStore(
  998. IN DWORD dwContextType,
  999. IN const void *pvContext
  1000. )
  1001. {
  1002. switch (dwContextType) {
  1003. case CERT_STORE_CERTIFICATE_CONTEXT:
  1004. CertDeleteCertificateFromStore((PCCERT_CONTEXT) pvContext);
  1005. break;
  1006. case CERT_STORE_CRL_CONTEXT:
  1007. CertDeleteCRLFromStore((PCCRL_CONTEXT) pvContext);
  1008. break;
  1009. case CERT_STORE_CTL_CONTEXT:
  1010. CertDeleteCTLFromStore((PCCTL_CONTEXT) pvContext);
  1011. break;
  1012. default:
  1013. break;
  1014. }
  1015. }
  1016. //+-------------------------------------------------------------------------
  1017. // Frees the context.
  1018. //--------------------------------------------------------------------------
  1019. STATIC void FreeContext(
  1020. IN DWORD dwContextType,
  1021. IN const void *pvContext
  1022. )
  1023. {
  1024. switch (dwContextType) {
  1025. case CERT_STORE_CERTIFICATE_CONTEXT:
  1026. CertFreeCertificateContext((PCCERT_CONTEXT) pvContext);
  1027. break;
  1028. case CERT_STORE_CRL_CONTEXT:
  1029. CertFreeCRLContext((PCCRL_CONTEXT) pvContext);
  1030. break;
  1031. case CERT_STORE_CTL_CONTEXT:
  1032. CertFreeCTLContext((PCCTL_CONTEXT) pvContext);
  1033. break;
  1034. default:
  1035. break;
  1036. }
  1037. }
  1038. //+=========================================================================
  1039. // Low level registry support functions
  1040. //==========================================================================
  1041. //+-------------------------------------------------------------------------
  1042. // For CERT_STORE_BACKUP_RESTORE_FLAG, enable backup and restore
  1043. // privileges.
  1044. //--------------------------------------------------------------------------
  1045. void ILS_EnableBackupRestorePrivileges()
  1046. {
  1047. IPR_EnableSecurityPrivilege(SE_BACKUP_NAME);
  1048. IPR_EnableSecurityPrivilege(SE_RESTORE_NAME);
  1049. }
  1050. // LastError can get globbered when doing remote registry access
  1051. void
  1052. ILS_CloseRegistryKey(
  1053. IN HKEY hKey
  1054. )
  1055. {
  1056. if (hKey) {
  1057. DWORD dwErr = GetLastError();
  1058. LONG RegCloseKeyStatus;
  1059. RegCloseKeyStatus = RegCloseKey(hKey);
  1060. assert(ERROR_SUCCESS == RegCloseKeyStatus);
  1061. SetLastError(dwErr);
  1062. }
  1063. }
  1064. // Ensure LastError is preserved
  1065. void
  1066. ILS_CloseHandle(
  1067. IN HANDLE h
  1068. )
  1069. {
  1070. if (h) {
  1071. DWORD dwErr = GetLastError();
  1072. CloseHandle(h);
  1073. SetLastError(dwErr);
  1074. }
  1075. }
  1076. STATIC BOOL WriteDWORDValueToRegistry(
  1077. IN HKEY hKey,
  1078. IN LPCWSTR pwszValueName,
  1079. IN DWORD dwValue
  1080. )
  1081. {
  1082. LONG err;
  1083. if (ERROR_SUCCESS == (err = RegSetValueExU(
  1084. hKey,
  1085. pwszValueName,
  1086. 0, // dwReserved
  1087. REG_DWORD,
  1088. (BYTE *) &dwValue,
  1089. sizeof(DWORD))))
  1090. return TRUE;
  1091. else {
  1092. SetLastError((DWORD) err);
  1093. return FALSE;
  1094. }
  1095. }
  1096. BOOL
  1097. ILS_ReadDWORDValueFromRegistry(
  1098. IN HKEY hKey,
  1099. IN LPCWSTR pwszValueName,
  1100. IN DWORD *pdwValue
  1101. )
  1102. {
  1103. BOOL fResult;
  1104. LONG err;
  1105. DWORD dwType;
  1106. DWORD dwValue;
  1107. DWORD cbValue = sizeof(DWORD);
  1108. if (ERROR_SUCCESS != (err = RegQueryValueExU(
  1109. hKey,
  1110. pwszValueName,
  1111. NULL, // pdwReserved
  1112. &dwType,
  1113. (BYTE *) &dwValue,
  1114. &cbValue))) goto RegQueryValueError;
  1115. if (dwType != REG_DWORD || cbValue != sizeof(DWORD))
  1116. goto InvalidRegistryValue;
  1117. fResult = TRUE;
  1118. CommonReturn:
  1119. *pdwValue = dwValue;
  1120. return fResult;
  1121. ErrorReturn:
  1122. dwValue = 0;
  1123. fResult = FALSE;
  1124. goto CommonReturn;
  1125. SET_ERROR_VAR(RegQueryValueError, err)
  1126. SET_ERROR(InvalidRegistryValue, CRYPT_E_FILE_ERROR)
  1127. }
  1128. // Ensure a binary value that may contain a LPCWSTR is NULL terminated.
  1129. // Always adds a NULL terminator not included in the returned cbValue.
  1130. //
  1131. // May return an allocated pbValue with a cbValue = 0.
  1132. BOOL
  1133. ILS_ReadBINARYValueFromRegistry(
  1134. IN HKEY hKey,
  1135. IN LPCWSTR pwszValueName,
  1136. OUT BYTE **ppbValue,
  1137. OUT DWORD *pcbValue
  1138. )
  1139. {
  1140. BOOL fResult;
  1141. LONG err;
  1142. DWORD dwType;
  1143. BYTE *pbValue = NULL;
  1144. DWORD cbValue = 0;
  1145. DWORD cbAllocValue;
  1146. err = RegQueryValueExU(
  1147. hKey,
  1148. pwszValueName,
  1149. NULL, // pdwReserved
  1150. &dwType,
  1151. NULL, // lpData
  1152. &cbValue);
  1153. // For Win95 Remote Registry Access:: returns ERROR_MORE_DATA
  1154. if (!(ERROR_SUCCESS == err || ERROR_MORE_DATA == err))
  1155. goto RegQueryValueError;
  1156. if (dwType != REG_BINARY)
  1157. goto InvalidRegistryValue;
  1158. cbAllocValue = cbValue + 3;
  1159. if (NULL == (pbValue = (BYTE *) PkiNonzeroAlloc(cbAllocValue)))
  1160. goto OutOfMemory;
  1161. if (0 < cbValue) {
  1162. if (ERROR_SUCCESS != (err = RegQueryValueExU(
  1163. hKey,
  1164. pwszValueName,
  1165. NULL, // pdwReserved
  1166. &dwType,
  1167. pbValue,
  1168. &cbValue))) goto RegQueryValueError;
  1169. }
  1170. assert(cbAllocValue >= cbValue + 3);
  1171. // Ensure an LPWSTR is null terminated
  1172. memset(pbValue + cbValue, 0, 3);
  1173. fResult = TRUE;
  1174. CommonReturn:
  1175. *ppbValue = pbValue;
  1176. *pcbValue = cbValue;
  1177. return fResult;
  1178. ErrorReturn:
  1179. fResult = FALSE;
  1180. PkiFree(pbValue);
  1181. pbValue = NULL;
  1182. cbValue = 0;
  1183. goto CommonReturn;
  1184. SET_ERROR_VAR(RegQueryValueError, err)
  1185. SET_ERROR(InvalidRegistryValue, CRYPT_E_FILE_ERROR)
  1186. TRACE_ERROR(OutOfMemory)
  1187. }
  1188. //+-------------------------------------------------------------------------
  1189. // Get and allocate the REG_SZ value
  1190. //--------------------------------------------------------------------------
  1191. LPWSTR ILS_ReadSZValueFromRegistry(
  1192. IN HKEY hKey,
  1193. IN LPCWSTR pwszValueName
  1194. )
  1195. {
  1196. LONG err;
  1197. DWORD dwType;
  1198. LPWSTR pwszValue = NULL;
  1199. DWORD cbValue = 0;
  1200. err = RegQueryValueExU(
  1201. hKey,
  1202. pwszValueName,
  1203. NULL, // pdwReserved
  1204. &dwType,
  1205. NULL, // lpData
  1206. &cbValue);
  1207. // For Win95 Remote Registry Access:: returns ERROR_MORE_DATA
  1208. if (!(ERROR_SUCCESS == err || ERROR_MORE_DATA == err))
  1209. goto RegQueryValueError;
  1210. if (dwType != REG_SZ || cbValue < sizeof(WCHAR))
  1211. goto InvalidRegistryValue;
  1212. // Ensure NULL terminated
  1213. if (NULL == (pwszValue = (LPWSTR) PkiNonzeroAlloc(cbValue + sizeof(WCHAR))))
  1214. goto OutOfMemory;
  1215. if (ERROR_SUCCESS != (err = RegQueryValueExU(
  1216. hKey,
  1217. pwszValueName,
  1218. NULL, // pdwReserved
  1219. &dwType,
  1220. (BYTE *) pwszValue,
  1221. &cbValue))) goto RegQueryValueError;
  1222. pwszValue[cbValue / sizeof(WCHAR)] = L'\0';
  1223. CommonReturn:
  1224. return pwszValue;
  1225. ErrorReturn:
  1226. PkiFree(pwszValue);
  1227. pwszValue = NULL;
  1228. goto CommonReturn;
  1229. SET_ERROR_VAR(RegQueryValueError, err)
  1230. SET_ERROR(InvalidRegistryValue, CRYPT_E_FILE_ERROR)
  1231. TRACE_ERROR(OutOfMemory)
  1232. }
  1233. LPSTR ILS_ReadSZValueFromRegistry(
  1234. IN HKEY hKey,
  1235. IN LPCSTR pszValueName
  1236. )
  1237. {
  1238. LONG err;
  1239. DWORD dwType;
  1240. LPSTR pszValue = NULL;
  1241. DWORD cbValue = 0;
  1242. err = RegQueryValueExA(
  1243. hKey,
  1244. pszValueName,
  1245. NULL, // pdwReserved
  1246. &dwType,
  1247. NULL, // lpData
  1248. &cbValue);
  1249. // For Win95 Remote Registry Access:: returns ERROR_MORE_DATA
  1250. if (!(ERROR_SUCCESS == err || ERROR_MORE_DATA == err))
  1251. goto RegQueryValueError;
  1252. if (dwType != REG_SZ || cbValue == 0)
  1253. goto InvalidRegistryValue;
  1254. // Ensure NULL terminated
  1255. if (NULL == (pszValue = (LPSTR) PkiNonzeroAlloc(cbValue + sizeof(CHAR))))
  1256. goto OutOfMemory;
  1257. if (ERROR_SUCCESS != (err = RegQueryValueExA(
  1258. hKey,
  1259. pszValueName,
  1260. NULL, // pdwReserved
  1261. &dwType,
  1262. (BYTE *) pszValue,
  1263. &cbValue))) goto RegQueryValueError;
  1264. pszValue[cbValue / sizeof(CHAR)] = '\0';
  1265. CommonReturn:
  1266. return pszValue;
  1267. ErrorReturn:
  1268. PkiFree(pszValue);
  1269. pszValue = NULL;
  1270. goto CommonReturn;
  1271. SET_ERROR_VAR(RegQueryValueError, err)
  1272. SET_ERROR(InvalidRegistryValue, CRYPT_E_FILE_ERROR)
  1273. TRACE_ERROR(OutOfMemory)
  1274. }
  1275. STATIC BOOL GetSubKeyInfo(
  1276. IN HKEY hKey,
  1277. OUT OPTIONAL DWORD *pcSubKeys,
  1278. OUT OPTIONAL DWORD *pcchMaxSubKey = NULL
  1279. )
  1280. {
  1281. BOOL fResult;
  1282. LONG err;
  1283. // I have seen a couple of stress failures where the following returns
  1284. // ERROR_SUCCESS without updating *pcSubKeys
  1285. if (pcSubKeys)
  1286. *pcSubKeys = 0;
  1287. if (pcchMaxSubKey)
  1288. *pcchMaxSubKey = 0;
  1289. if (ERROR_SUCCESS != (err = RegQueryInfoKeyU(
  1290. hKey,
  1291. NULL, // lpszClass
  1292. NULL, // lpcchClass
  1293. NULL, // lpdwReserved
  1294. pcSubKeys,
  1295. pcchMaxSubKey,
  1296. NULL, // lpcchMaxClass
  1297. NULL, // lpcValues
  1298. NULL, // lpcchMaxValuesName
  1299. NULL, // lpcbMaxValueData
  1300. NULL, // lpcbSecurityDescriptor
  1301. NULL // lpftLastWriteTime
  1302. ))) goto RegQueryInfoKeyError;
  1303. fResult = TRUE;
  1304. CommonReturn:
  1305. // For Win95 Remote Registry Access:: returns half of the cch
  1306. if (pcchMaxSubKey && *pcchMaxSubKey)
  1307. *pcchMaxSubKey = (*pcchMaxSubKey + 1) * 2 + 2;
  1308. return fResult;
  1309. ErrorReturn:
  1310. fResult = FALSE;
  1311. if (pcSubKeys)
  1312. *pcSubKeys = 0;
  1313. if (pcchMaxSubKey)
  1314. *pcchMaxSubKey = 0;
  1315. goto CommonReturn;
  1316. SET_ERROR_VAR(RegQueryInfoKeyError, err)
  1317. }
  1318. //+-------------------------------------------------------------------------
  1319. // Open the SubKey with support for backup/restore
  1320. //--------------------------------------------------------------------------
  1321. STATIC LONG WINAPI OpenHKCUKeyExU (
  1322. HKEY hKey,
  1323. IN LPCWSTR pwszSubKeyName,
  1324. IN DWORD dwFlags, // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  1325. REGSAM samDesired,
  1326. PHKEY phkResult
  1327. )
  1328. {
  1329. LONG err;
  1330. if (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG) {
  1331. DWORD dwDisposition;
  1332. err = RegCreateHKCUKeyExU(
  1333. hKey,
  1334. pwszSubKeyName,
  1335. NULL,
  1336. NULL,
  1337. REG_OPTION_BACKUP_RESTORE,
  1338. samDesired,
  1339. NULL,
  1340. phkResult,
  1341. &dwDisposition
  1342. );
  1343. } else {
  1344. err = RegOpenHKCUKeyExU(
  1345. hKey,
  1346. pwszSubKeyName,
  1347. 0, // dwReserved
  1348. samDesired,
  1349. phkResult
  1350. );
  1351. }
  1352. return err;
  1353. }
  1354. //+-------------------------------------------------------------------------
  1355. // Open the SubKey.
  1356. //
  1357. // dwFlags:
  1358. // CERT_STORE_READONLY_FLAG
  1359. // CERT_STORE_OPEN_EXISTING_FLAG
  1360. // CERT_STORE_CREATE_NEW_FLAG
  1361. // CERT_STORE_BACKUP_RESTORE_FLAG
  1362. //--------------------------------------------------------------------------
  1363. STATIC HKEY OpenSubKey(
  1364. IN HKEY hKey,
  1365. IN LPCWSTR pwszSubKeyName,
  1366. IN DWORD dwFlags
  1367. )
  1368. {
  1369. LONG err;
  1370. HKEY hSubKey;
  1371. if (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG) {
  1372. DWORD dwDisposition;
  1373. REGSAM samDesired;
  1374. if (dwFlags & CERT_STORE_READONLY_FLAG)
  1375. samDesired = KEY_READ;
  1376. else
  1377. samDesired = KEY_ALL_ACCESS;
  1378. if (NULL == pwszSubKeyName)
  1379. pwszSubKeyName = L"";
  1380. if (ERROR_SUCCESS != (err = RegCreateHKCUKeyExU(
  1381. hKey,
  1382. pwszSubKeyName,
  1383. 0, // dwReserved
  1384. NULL, // lpClass
  1385. REG_OPTION_BACKUP_RESTORE,
  1386. samDesired,
  1387. NULL, // lpSecurityAttributes
  1388. &hSubKey,
  1389. &dwDisposition))) {
  1390. if (dwFlags &
  1391. (CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG))
  1392. err = ERROR_FILE_NOT_FOUND;
  1393. goto RegCreateBackupRestoreKeyError;
  1394. }
  1395. if (dwFlags & CERT_STORE_CREATE_NEW_FLAG) {
  1396. if (REG_CREATED_NEW_KEY != dwDisposition) {
  1397. RegCloseKey(hSubKey);
  1398. goto ExistingSubKey;
  1399. }
  1400. }
  1401. goto CommonReturn;
  1402. }
  1403. if (dwFlags & CERT_STORE_CREATE_NEW_FLAG) {
  1404. // First check if SubKey already exists
  1405. if (hSubKey = OpenSubKey(
  1406. hKey,
  1407. pwszSubKeyName,
  1408. (dwFlags & ~CERT_STORE_CREATE_NEW_FLAG) |
  1409. CERT_STORE_OPEN_EXISTING_FLAG |
  1410. CERT_STORE_READONLY_FLAG
  1411. )) {
  1412. RegCloseKey(hSubKey);
  1413. goto ExistingSubKey;
  1414. } else if (ERROR_FILE_NOT_FOUND != GetLastError())
  1415. goto OpenNewSubKeyError;
  1416. }
  1417. if (dwFlags & (CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG)) {
  1418. REGSAM samDesired;
  1419. if (dwFlags & CERT_STORE_READONLY_FLAG)
  1420. samDesired = KEY_READ;
  1421. else
  1422. samDesired = KEY_ALL_ACCESS;
  1423. if (ERROR_SUCCESS != (err = RegOpenHKCUKeyExU(
  1424. hKey,
  1425. pwszSubKeyName,
  1426. 0, // dwReserved
  1427. samDesired,
  1428. &hSubKey)))
  1429. goto RegOpenKeyError;
  1430. } else {
  1431. DWORD dwDisposition;
  1432. if (ERROR_SUCCESS != (err = RegCreateHKCUKeyExU(
  1433. hKey,
  1434. pwszSubKeyName,
  1435. 0, // dwReserved
  1436. NULL, // lpClass
  1437. REG_OPTION_NON_VOLATILE,
  1438. KEY_ALL_ACCESS,
  1439. NULL, // lpSecurityAttributes
  1440. &hSubKey,
  1441. &dwDisposition)))
  1442. goto RegCreateKeyError;
  1443. }
  1444. CommonReturn:
  1445. return hSubKey;
  1446. ErrorReturn:
  1447. hSubKey = NULL;
  1448. goto CommonReturn;
  1449. SET_ERROR_VAR(RegCreateBackupRestoreKeyError, err)
  1450. SET_ERROR(ExistingSubKey, ERROR_FILE_EXISTS)
  1451. TRACE_ERROR(OpenNewSubKeyError)
  1452. SET_ERROR_VAR(RegOpenKeyError, err)
  1453. SET_ERROR_VAR(RegCreateKeyError, err)
  1454. }
  1455. STATIC BOOL RecursiveDeleteSubKey(
  1456. IN HKEY hKey,
  1457. IN LPCWSTR pwszSubKeyName,
  1458. IN DWORD dwFlags // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  1459. )
  1460. {
  1461. BOOL fResult;
  1462. LONG err;
  1463. while (TRUE) {
  1464. HKEY hSubKey;
  1465. DWORD cSubKeys;
  1466. DWORD cchMaxSubKey;
  1467. BOOL fDidDelete;
  1468. if (ERROR_SUCCESS != OpenHKCUKeyExU(
  1469. hKey,
  1470. pwszSubKeyName,
  1471. dwFlags,
  1472. KEY_ALL_ACCESS,
  1473. &hSubKey))
  1474. break;
  1475. GetSubKeyInfo(
  1476. hSubKey,
  1477. &cSubKeys,
  1478. &cchMaxSubKey
  1479. );
  1480. fDidDelete = FALSE;
  1481. if (cSubKeys && cchMaxSubKey) {
  1482. LPWSTR pwszEnumSubKeyName;
  1483. cchMaxSubKey++;
  1484. if (pwszEnumSubKeyName = (LPWSTR) PkiNonzeroAlloc(
  1485. cchMaxSubKey * sizeof(WCHAR))) {
  1486. if (ERROR_SUCCESS == RegEnumKeyExU(
  1487. hSubKey,
  1488. 0,
  1489. pwszEnumSubKeyName,
  1490. &cchMaxSubKey,
  1491. NULL, // lpdwReserved
  1492. NULL, // lpszClass
  1493. NULL, // lpcchClass
  1494. NULL // lpftLastWriteTime
  1495. ))
  1496. fDidDelete = RecursiveDeleteSubKey(
  1497. hSubKey, pwszEnumSubKeyName, dwFlags);
  1498. PkiFree(pwszEnumSubKeyName);
  1499. }
  1500. }
  1501. RegCloseKey(hSubKey);
  1502. if (!fDidDelete)
  1503. break;
  1504. }
  1505. if (ERROR_SUCCESS != (err = RegDeleteKeyU(hKey, pwszSubKeyName)))
  1506. goto RegDeleteKeyError;
  1507. fResult = TRUE;
  1508. CommonReturn:
  1509. return fResult;
  1510. ErrorReturn:
  1511. fResult = FALSE;
  1512. goto CommonReturn;
  1513. SET_ERROR_VAR(RegDeleteKeyError, err)
  1514. }
  1515. //+=========================================================================
  1516. // Trusted Publisher Registry Functions
  1517. //==========================================================================
  1518. STATIC BOOL OpenKeyAndReadDWORDValueFromRegistry(
  1519. IN BOOL fMachine,
  1520. IN LPCWSTR pwszRegPath,
  1521. IN LPCWSTR pwszValueName,
  1522. OUT DWORD *pdwValue
  1523. )
  1524. {
  1525. BOOL fResult;
  1526. HKEY hKey = NULL;
  1527. LONG err;
  1528. if (ERROR_SUCCESS != (err = RegOpenHKCUKeyExU(
  1529. fMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
  1530. pwszRegPath,
  1531. 0, // dwReserved
  1532. KEY_READ,
  1533. &hKey
  1534. )))
  1535. goto OpenKeyForDWORDValueError;
  1536. if (!ILS_ReadDWORDValueFromRegistry(
  1537. hKey,
  1538. pwszValueName,
  1539. pdwValue
  1540. )) goto ReadDWORDValueError;
  1541. fResult = TRUE;
  1542. CommonReturn:
  1543. ILS_CloseRegistryKey(hKey);
  1544. return fResult;
  1545. ErrorReturn:
  1546. *pdwValue = 0;
  1547. fResult = FALSE;
  1548. goto CommonReturn;
  1549. SET_ERROR_VAR(OpenKeyForDWORDValueError, err)
  1550. TRACE_ERROR(ReadDWORDValueError)
  1551. }
  1552. //+-------------------------------------------------------------------------
  1553. // On the Nth iteration these Safer Grade School programmers decided that the
  1554. // value should be the 'OR' of the 3 different locations: HKLM\GPO, HKCU\GPO,
  1555. // HKLM\Registry.
  1556. //--------------------------------------------------------------------------
  1557. BOOL
  1558. I_CryptReadTrustedPublisherDWORDValueFromRegistry(
  1559. IN LPCWSTR pwszValueName,
  1560. OUT DWORD *pdwValue
  1561. )
  1562. {
  1563. BOOL fResult = FALSE;
  1564. DWORD dwValue = 0;
  1565. DWORD dwRegValue = 0;
  1566. if (OpenKeyAndReadDWORDValueFromRegistry(
  1567. TRUE, // fMachine
  1568. CERT_TRUST_PUB_SAFER_GROUP_POLICY_REGPATH,
  1569. pwszValueName,
  1570. &dwRegValue
  1571. )) {
  1572. fResult = TRUE;
  1573. dwValue |= dwRegValue;
  1574. }
  1575. if (OpenKeyAndReadDWORDValueFromRegistry(
  1576. FALSE, // fMachine
  1577. CERT_TRUST_PUB_SAFER_GROUP_POLICY_REGPATH,
  1578. pwszValueName,
  1579. &dwRegValue
  1580. )) {
  1581. fResult = TRUE;
  1582. dwValue |= dwRegValue;
  1583. }
  1584. if (OpenKeyAndReadDWORDValueFromRegistry(
  1585. TRUE, // fMachine
  1586. CERT_TRUST_PUB_SAFER_LOCAL_MACHINE_REGPATH,
  1587. pwszValueName,
  1588. &dwRegValue
  1589. )) {
  1590. fResult = TRUE;
  1591. dwValue |= dwRegValue;
  1592. }
  1593. *pdwValue = dwValue;
  1594. return fResult;
  1595. }
  1596. //+=========================================================================
  1597. // Win95 Registry Functions
  1598. //
  1599. // Note, as of 10/17/97 the following is also done on NT to allow
  1600. // registry hive roaming from NT to Win95 systems.
  1601. //
  1602. // Certs, CRLs and CTLs are stored in SubKeys instead of as Key values.
  1603. //
  1604. // Note: Win95 has the following registry limitations:
  1605. // - Max single key value is 16K
  1606. // - Max total values per key is 64K
  1607. //
  1608. // For WIN95, write each cert, CRL, CTL to its own key when the
  1609. // above limitations are exceeded. If encoded blob exceeds 12K, partition
  1610. // and write to multiple SubKeys. Blobs are written to values named
  1611. // "Blob". Partitioned blobs, have "BlobCount" and "BlobLength" values and
  1612. // SubKeys named "Blob0", "Blob1", "Blob2" ... .
  1613. //
  1614. // The IE4.0 version of crypt32 wrote the blob to a "File" if the blob
  1615. // exceeded 12K. For backwards compatibility, continue to read "File" based
  1616. // blobs. On write enabled, non-remote opens, "File" blobs are moved to
  1617. // "Blob0", ... SubKeys and the file is deleted.
  1618. //
  1619. // If CERT_REGISTRY_STORE_SERIALIZED_FLAG is set when the registry store
  1620. // is opened, then, the entire store resides in a partitioned blob under the
  1621. // "Serialized" subkey.
  1622. //==========================================================================
  1623. #define KEY_BLOB_VALUE_NAME L"Blob"
  1624. #define KEY_FILE_VALUE_NAME L"File"
  1625. #define KEY_BLOB_COUNT_VALUE_NAME L"BlobCount"
  1626. #define KEY_BLOB_LENGTH_VALUE_NAME L"BlobLength"
  1627. #define KEY_BLOB_N_SUBKEY_PREFIX "Blob"
  1628. #define KEY_BLOB_N_SUBKEY_PREFIX_LENGTH 4
  1629. #define SYSTEM_STORE_SUBDIR L"SystemCertificates"
  1630. #define FILETIME_ASCII_HEX_LEN (2 * sizeof(FILETIME) + 1)
  1631. #define MAX_KEY_BLOB_VALUE_LEN 0x3000
  1632. #define MAX_NEW_FILE_CREATE_ATTEMPTS 100
  1633. #define SERIALIZED_SUBKEY_NAME L"Serialized"
  1634. //+-------------------------------------------------------------------------
  1635. // Read and allocate the element bytes by reading the file pointed to
  1636. // by the SubKey's "File" value
  1637. //--------------------------------------------------------------------------
  1638. STATIC BOOL ReadKeyFileElementFromRegistry(
  1639. IN HKEY hSubKey,
  1640. IN DWORD dwFlags, // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  1641. OUT BYTE **ppbElement,
  1642. OUT DWORD *pcbElement
  1643. )
  1644. {
  1645. BOOL fResult;
  1646. LPWSTR pwszFilename = NULL;
  1647. HANDLE hFile = INVALID_HANDLE_VALUE;
  1648. DWORD cbBytesRead;
  1649. BYTE *pbElement = NULL;
  1650. DWORD cbElement;
  1651. if (NULL == (pwszFilename = ILS_ReadSZValueFromRegistry(
  1652. hSubKey, KEY_FILE_VALUE_NAME)))
  1653. goto GetKeyFilenameError;
  1654. if (INVALID_HANDLE_VALUE == (hFile = CreateFileU(
  1655. pwszFilename,
  1656. GENERIC_READ,
  1657. FILE_SHARE_READ,
  1658. NULL, // lpsa
  1659. OPEN_EXISTING,
  1660. FILE_ATTRIBUTE_NORMAL |
  1661. ((dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG) ?
  1662. FILE_FLAG_BACKUP_SEMANTICS : 0),
  1663. NULL // hTemplateFile
  1664. )))
  1665. goto CreateFileError;
  1666. cbElement = GetFileSize(hFile, NULL);
  1667. if (0xFFFFFFFF == cbElement) goto FileError;
  1668. if (0 == cbElement) goto EmptyFile;
  1669. if (NULL == (pbElement = (BYTE *) PkiNonzeroAlloc(cbElement)))
  1670. goto OutOfMemory;
  1671. if (!ReadFile(
  1672. hFile,
  1673. pbElement,
  1674. cbElement,
  1675. &cbBytesRead,
  1676. NULL // lpOverlapped
  1677. )) goto FileError;
  1678. fResult = TRUE;
  1679. CommonReturn:
  1680. PkiFree(pwszFilename);
  1681. if (INVALID_HANDLE_VALUE != hFile)
  1682. ILS_CloseHandle(hFile);
  1683. *ppbElement = pbElement;
  1684. *pcbElement = cbElement;
  1685. return fResult;
  1686. ErrorReturn:
  1687. fResult = FALSE;
  1688. PkiFree(pbElement);
  1689. pbElement = NULL;
  1690. cbElement = 0;
  1691. goto CommonReturn;
  1692. TRACE_ERROR(GetKeyFilenameError)
  1693. TRACE_ERROR(OutOfMemory)
  1694. TRACE_ERROR(CreateFileError)
  1695. TRACE_ERROR(FileError)
  1696. SET_ERROR(EmptyFile, CRYPT_E_FILE_ERROR)
  1697. }
  1698. //+-------------------------------------------------------------------------
  1699. // Read as multiple SubKeys containing the element bytes. The SubKeys
  1700. // are named Blob0, Blob1, Blob2, ... BlobN.
  1701. // Each BlobN SubKey has a value named "Blob" containing the bytes to be read.
  1702. //
  1703. // The passed in SubKey is expected to have 2 values:
  1704. // BlobCount - # of BlobN SubKeys
  1705. // BlobLength - total length of all the concatenated Blob Subkey bytes
  1706. //
  1707. // A single allocated element byte array is returned.
  1708. //--------------------------------------------------------------------------
  1709. STATIC BOOL ReadMultipleKeyBlobsFromRegistry(
  1710. IN HKEY hSubKey,
  1711. IN DWORD dwFlags, // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  1712. OUT BYTE **ppbElement,
  1713. OUT DWORD *pcbElement
  1714. )
  1715. {
  1716. BOOL fResult;
  1717. LONG err;
  1718. HKEY hBlobKey = NULL;
  1719. BYTE *pbElement = NULL;
  1720. DWORD cbElement;
  1721. DWORD BlobCount;
  1722. DWORD BlobLength;
  1723. DWORD i;
  1724. char szBlobN[KEY_BLOB_N_SUBKEY_PREFIX_LENGTH + 33];
  1725. ILS_ReadDWORDValueFromRegistry(
  1726. hSubKey,
  1727. KEY_BLOB_COUNT_VALUE_NAME,
  1728. &BlobCount
  1729. );
  1730. ILS_ReadDWORDValueFromRegistry(
  1731. hSubKey,
  1732. KEY_BLOB_LENGTH_VALUE_NAME,
  1733. &BlobLength
  1734. );
  1735. if (0 == BlobCount || 0 == BlobLength)
  1736. goto NoMultipleKeyBlobs;
  1737. if (NULL == (pbElement = (BYTE *) PkiNonzeroAlloc(BlobLength)))
  1738. goto OutOfMemory;
  1739. cbElement = 0;
  1740. strcpy(szBlobN, KEY_BLOB_N_SUBKEY_PREFIX);
  1741. for (i = 0; i < BlobCount; i++) {
  1742. DWORD cbData;
  1743. DWORD dwType;
  1744. _ltoa((long) i, szBlobN + KEY_BLOB_N_SUBKEY_PREFIX_LENGTH, 10);
  1745. if (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG) {
  1746. DWORD dwDisposition;
  1747. if (ERROR_SUCCESS != (err = RegCreateKeyExA(
  1748. hSubKey,
  1749. szBlobN,
  1750. 0, // dwReserved
  1751. NULL, // lpClass
  1752. REG_OPTION_BACKUP_RESTORE,
  1753. KEY_READ,
  1754. NULL, // lpSecurityAttributes
  1755. &hBlobKey,
  1756. &dwDisposition)))
  1757. goto OpenBackupRestoreBlobNError;
  1758. } else {
  1759. if (ERROR_SUCCESS != (err = RegOpenKeyExA(
  1760. hSubKey,
  1761. szBlobN,
  1762. 0, // dwReserved
  1763. KEY_READ,
  1764. &hBlobKey)))
  1765. goto OpenBlobNError;
  1766. }
  1767. cbData = BlobLength - cbElement;
  1768. if (0 == cbData)
  1769. goto ExtraMultipleKeyBlobs;
  1770. if (ERROR_SUCCESS != (err = RegQueryValueExU(
  1771. hBlobKey,
  1772. KEY_BLOB_VALUE_NAME,
  1773. NULL, // pdwReserved
  1774. &dwType,
  1775. pbElement + cbElement,
  1776. &cbData)))
  1777. goto RegQueryValueError;
  1778. if (dwType != REG_BINARY)
  1779. goto InvalidRegistryValue;
  1780. cbElement += cbData;
  1781. if (cbElement > BlobLength)
  1782. goto UnexpectedError;
  1783. RegCloseKey(hBlobKey);
  1784. hBlobKey = NULL;
  1785. }
  1786. if (cbElement != BlobLength)
  1787. goto MissingMultipleKeyBlobsBytes;
  1788. assert(NULL == hBlobKey);
  1789. fResult = TRUE;
  1790. CommonReturn:
  1791. *ppbElement = pbElement;
  1792. *pcbElement = cbElement;
  1793. return fResult;
  1794. ErrorReturn:
  1795. PkiFree(pbElement);
  1796. ILS_CloseRegistryKey(hBlobKey);
  1797. fResult = FALSE;
  1798. pbElement = NULL;
  1799. cbElement = 0;
  1800. goto CommonReturn;
  1801. SET_ERROR(NoMultipleKeyBlobs, ERROR_FILE_NOT_FOUND)
  1802. TRACE_ERROR(OutOfMemory)
  1803. SET_ERROR_VAR(OpenBlobNError, err)
  1804. SET_ERROR_VAR(OpenBackupRestoreBlobNError, err)
  1805. SET_ERROR(UnexpectedError, E_UNEXPECTED)
  1806. SET_ERROR(InvalidRegistryValue, CRYPT_E_FILE_ERROR)
  1807. SET_ERROR(ExtraMultipleKeyBlobs, CRYPT_E_FILE_ERROR)
  1808. SET_ERROR_VAR(RegQueryValueError, err)
  1809. SET_ERROR(MissingMultipleKeyBlobsBytes, CRYPT_E_FILE_ERROR)
  1810. }
  1811. //+-------------------------------------------------------------------------
  1812. // Write as multiple BlobN SubKeys containing the element bytes.
  1813. //
  1814. // See ReadMultipleKeyBlobsFromRegistry() for details.
  1815. //--------------------------------------------------------------------------
  1816. STATIC BOOL WriteMultipleKeyBlobsToRegistry(
  1817. IN HKEY hSubKey,
  1818. IN DWORD dwFlags, // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  1819. IN const BYTE *pbElement,
  1820. IN DWORD cbElement
  1821. )
  1822. {
  1823. BOOL fResult;
  1824. LONG err;
  1825. HKEY hBlobKey = NULL;
  1826. DWORD BlobCount = 0;
  1827. DWORD BlobLength;
  1828. DWORD i;
  1829. DWORD dwErr;
  1830. char szBlobN[KEY_BLOB_N_SUBKEY_PREFIX_LENGTH + 33];
  1831. if (0 == cbElement)
  1832. goto UnexpectedError;
  1833. BlobCount = cbElement / MAX_KEY_BLOB_VALUE_LEN;
  1834. if (cbElement % MAX_KEY_BLOB_VALUE_LEN)
  1835. BlobCount++;
  1836. BlobLength = 0;
  1837. strcpy(szBlobN, KEY_BLOB_N_SUBKEY_PREFIX);
  1838. for (i = 0; i < BlobCount; i++) {
  1839. DWORD cbData;
  1840. DWORD dwDisposition;
  1841. _ltoa((long) i, szBlobN + KEY_BLOB_N_SUBKEY_PREFIX_LENGTH, 10);
  1842. if (ERROR_SUCCESS != (err = RegCreateKeyExA(
  1843. hSubKey,
  1844. szBlobN,
  1845. 0, // dwReserved
  1846. NULL, // lpClass
  1847. (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG) ?
  1848. REG_OPTION_BACKUP_RESTORE : REG_OPTION_NON_VOLATILE,
  1849. KEY_WRITE,
  1850. NULL, // lpSecurityAttributes
  1851. &hBlobKey,
  1852. &dwDisposition))) goto RegCreateKeyError;
  1853. assert(cbElement > BlobLength);
  1854. cbData = cbElement - BlobLength;
  1855. if (cbData > MAX_KEY_BLOB_VALUE_LEN)
  1856. cbData = MAX_KEY_BLOB_VALUE_LEN;
  1857. if (ERROR_SUCCESS != (err = RegSetValueExU(
  1858. hBlobKey,
  1859. KEY_BLOB_VALUE_NAME,
  1860. NULL,
  1861. REG_BINARY,
  1862. pbElement + BlobLength,
  1863. cbData))) goto RegSetValueError;
  1864. BlobLength += cbData;
  1865. RegCloseKey(hBlobKey);
  1866. hBlobKey = NULL;
  1867. }
  1868. assert(BlobLength == cbElement);
  1869. if (!WriteDWORDValueToRegistry(
  1870. hSubKey,
  1871. KEY_BLOB_COUNT_VALUE_NAME,
  1872. BlobCount))
  1873. goto WriteDWORDError;
  1874. if (!WriteDWORDValueToRegistry(
  1875. hSubKey,
  1876. KEY_BLOB_LENGTH_VALUE_NAME,
  1877. BlobLength))
  1878. goto WriteDWORDError;
  1879. assert(NULL == hBlobKey);
  1880. fResult = TRUE;
  1881. CommonReturn:
  1882. return fResult;
  1883. ErrorReturn:
  1884. dwErr = GetLastError();
  1885. ILS_CloseRegistryKey(hBlobKey);
  1886. for (i = 0; i < BlobCount; i++) {
  1887. _ltoa((long) i, szBlobN + KEY_BLOB_N_SUBKEY_PREFIX_LENGTH, 10);
  1888. RegDeleteKeyA(hSubKey, szBlobN);
  1889. }
  1890. RegDeleteValueU(hSubKey, KEY_BLOB_COUNT_VALUE_NAME);
  1891. RegDeleteValueU(hSubKey, KEY_BLOB_LENGTH_VALUE_NAME);
  1892. fResult = FALSE;
  1893. SetLastError(dwErr);
  1894. goto CommonReturn;
  1895. SET_ERROR(UnexpectedError, E_UNEXPECTED)
  1896. SET_ERROR_VAR(RegCreateKeyError, err)
  1897. SET_ERROR_VAR(RegSetValueError, err)
  1898. TRACE_ERROR(WriteDWORDError)
  1899. }
  1900. //+-------------------------------------------------------------------------
  1901. // If the SubKey has a "File" value, delete the file.
  1902. //
  1903. // This is only applicable to obscure IE 4.0 cases.
  1904. //--------------------------------------------------------------------------
  1905. STATIC void DeleteKeyFile(
  1906. IN HKEY hKey,
  1907. IN const WCHAR wszSubKeyName[MAX_CERT_REG_VALUE_NAME_LEN],
  1908. IN DWORD dwFlags // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  1909. )
  1910. {
  1911. HKEY hSubKey = NULL;
  1912. if (ERROR_SUCCESS == OpenHKCUKeyExU(
  1913. hKey,
  1914. wszSubKeyName,
  1915. dwFlags,
  1916. KEY_ALL_ACCESS,
  1917. &hSubKey
  1918. )) {
  1919. LPWSTR pwszFilename;
  1920. if (pwszFilename = ILS_ReadSZValueFromRegistry(hSubKey,
  1921. KEY_FILE_VALUE_NAME)) {
  1922. SetFileAttributesU(pwszFilename, FILE_ATTRIBUTE_NORMAL);
  1923. DeleteFileU(pwszFilename);
  1924. PkiFree(pwszFilename);
  1925. }
  1926. RegDeleteValueU(hSubKey, KEY_FILE_VALUE_NAME);
  1927. RegCloseKey(hSubKey);
  1928. }
  1929. }
  1930. //+-------------------------------------------------------------------------
  1931. // Get the context by either getting the SubKey's "Blob" value or getting
  1932. // the SubKey's "BlobCount" and "BlobLength" values and then
  1933. // reading and concatenating multiple Blob<N> SubKeys containing the bytes or
  1934. // reading the file pointed to by the SubKey's "File" value.
  1935. //
  1936. // If the "File" value is found and used, then, migrate to being stored
  1937. // in the registry using multiple Blob<N> SubKeys.
  1938. //
  1939. // If CERT_REGISTRY_STORE_REMOTE_FLAG is set, then, don't attempt to read
  1940. // from the file.
  1941. //
  1942. // If CERT_STORE_READONLY_FLAG is set, don't attempt to migrate from the
  1943. // "File".
  1944. //--------------------------------------------------------------------------
  1945. STATIC BOOL ReadKeyElementFromRegistry(
  1946. IN HKEY hKey,
  1947. IN const WCHAR wszSubKeyName[MAX_CERT_REG_VALUE_NAME_LEN],
  1948. IN DWORD dwFlags,
  1949. OUT BYTE **ppbElement,
  1950. OUT DWORD *pcbElement
  1951. )
  1952. {
  1953. LONG err;
  1954. BOOL fResult;
  1955. BYTE *pbElement = NULL;
  1956. DWORD cbElement;
  1957. HKEY hSubKey = NULL;
  1958. if (ERROR_SUCCESS != (err = OpenHKCUKeyExU(
  1959. hKey,
  1960. wszSubKeyName,
  1961. dwFlags,
  1962. KEY_READ,
  1963. &hSubKey)))
  1964. goto OpenHKCUKeyError;
  1965. fResult = ILS_ReadBINARYValueFromRegistry(hSubKey, KEY_BLOB_VALUE_NAME,
  1966. &pbElement, &cbElement);
  1967. if (!fResult || 0 == cbElement) {
  1968. PkiFree(pbElement);
  1969. fResult = ReadMultipleKeyBlobsFromRegistry(hSubKey, dwFlags, &pbElement,
  1970. &cbElement);
  1971. if (!fResult && 0 == (dwFlags & CERT_REGISTRY_STORE_REMOTE_FLAG)) {
  1972. // For backwards compatibility with IE4.0. See if it exists
  1973. // in a file
  1974. fResult = ReadKeyFileElementFromRegistry(hSubKey, dwFlags,
  1975. &pbElement, &cbElement);
  1976. if (fResult && 0 == (dwFlags & CERT_STORE_READONLY_FLAG)) {
  1977. // Move from the file back to the registry.
  1978. if (WriteMultipleKeyBlobsToRegistry(hSubKey, dwFlags, pbElement,
  1979. cbElement))
  1980. DeleteKeyFile(hKey, wszSubKeyName, dwFlags);
  1981. }
  1982. }
  1983. if (!fResult)
  1984. goto ReadKeyElementError;
  1985. }
  1986. fResult = TRUE;
  1987. CommonReturn:
  1988. ILS_CloseRegistryKey(hSubKey);
  1989. *ppbElement = pbElement;
  1990. *pcbElement = cbElement;
  1991. return fResult;
  1992. ErrorReturn:
  1993. fResult = FALSE;
  1994. PkiFree(pbElement);
  1995. pbElement = NULL;
  1996. cbElement = 0;
  1997. goto CommonReturn;
  1998. SET_ERROR_VAR(OpenHKCUKeyError, err)
  1999. TRACE_ERROR(ReadKeyElementError)
  2000. }
  2001. STATIC BOOL ReadKeyFromRegistry(
  2002. IN HKEY hKey,
  2003. IN const WCHAR wszSubKeyName[MAX_CERT_REG_VALUE_NAME_LEN],
  2004. IN HCERTSTORE hCertStore,
  2005. IN DWORD dwContextTypeFlags,
  2006. IN DWORD dwFlags
  2007. )
  2008. {
  2009. BOOL fResult;
  2010. BYTE *pbElement = NULL;
  2011. DWORD cbElement;
  2012. DWORD dwContextType = 0;
  2013. const void *pvContext = NULL;
  2014. if (!ReadKeyElementFromRegistry(
  2015. hKey,
  2016. wszSubKeyName,
  2017. dwFlags,
  2018. &pbElement,
  2019. &cbElement
  2020. ))
  2021. goto ErrorReturn;
  2022. if (!CertAddSerializedElementToStore(
  2023. hCertStore,
  2024. pbElement,
  2025. cbElement,
  2026. CERT_STORE_ADD_ALWAYS,
  2027. 0, // dwFlags
  2028. dwContextTypeFlags,
  2029. &dwContextType,
  2030. &pvContext
  2031. ))
  2032. goto AddSerializedElementError;
  2033. if (IsValidRegValueNameForContext(
  2034. dwContextType,
  2035. pvContext,
  2036. wszSubKeyName
  2037. ))
  2038. FreeContext(dwContextType, pvContext);
  2039. else {
  2040. DeleteContextFromStore(dwContextType, pvContext);
  2041. goto InvalidRegValueNameForContext;
  2042. }
  2043. CertPerfIncrementRegElementReadCount();
  2044. fResult = TRUE;
  2045. CommonReturn:
  2046. PkiFree(pbElement);
  2047. return fResult;
  2048. ErrorReturn:
  2049. fResult = FALSE;
  2050. goto CommonReturn;
  2051. TRACE_ERROR(AddSerializedElementError)
  2052. TRACE_ERROR(InvalidRegValueNameForContext)
  2053. }
  2054. //+-------------------------------------------------------------------------
  2055. // Get the Certificates, CRLs or CTLs from the registry by reading as
  2056. // SubKeys and not Key values as done by OpenFromRegistry.
  2057. //
  2058. // If CERT_STORE_DELETE_FLAG is set, delete the file, if stored there.
  2059. //
  2060. // If CERT_REGISTRY_STORE_REMOTE_FLAG is set, then, don't attempt to read
  2061. // from the file.
  2062. //
  2063. // If CERT_STORE_READONLY_FLAG is set, don't attempt to migrate from the
  2064. // "File".
  2065. //--------------------------------------------------------------------------
  2066. STATIC BOOL OpenKeysFromRegistry(
  2067. IN HCERTSTORE hCertStore,
  2068. IN HKEY hKey,
  2069. IN DWORD dwFlags
  2070. )
  2071. {
  2072. BOOL fResult;
  2073. LONG err;
  2074. DWORD cSubKeys;
  2075. DWORD i;
  2076. // see how many SubKeys in the registry
  2077. if (!GetSubKeyInfo(hKey, &cSubKeys))
  2078. goto GetSubKeyInfoError;
  2079. for (i = 0; i < cSubKeys; i++) {
  2080. WCHAR wszSubKeyName[MAX_CERT_REG_VALUE_NAME_LEN];
  2081. DWORD cchSubKeyName = MAX_CERT_REG_VALUE_NAME_LEN;
  2082. err = RegEnumKeyExU(
  2083. hKey,
  2084. i,
  2085. wszSubKeyName,
  2086. &cchSubKeyName,
  2087. NULL, // lpdwReserved
  2088. NULL, // lpszClass
  2089. NULL, // lpcchClass
  2090. NULL // lpftLastWriteTime
  2091. );
  2092. if (ERROR_SUCCESS != err) {
  2093. if (ERROR_NO_MORE_ITEMS == err)
  2094. break;
  2095. else
  2096. continue;
  2097. } else if (dwFlags & CERT_STORE_DELETE_FLAG) {
  2098. if (0 == (dwFlags & CERT_REGISTRY_STORE_REMOTE_FLAG))
  2099. DeleteKeyFile(hKey, wszSubKeyName, dwFlags);
  2100. } else
  2101. // Ignore any read errors
  2102. ReadKeyFromRegistry(
  2103. hKey,
  2104. wszSubKeyName,
  2105. hCertStore,
  2106. CERT_STORE_ALL_CONTEXT_FLAG,
  2107. dwFlags
  2108. );
  2109. }
  2110. fResult = TRUE;
  2111. CommonReturn:
  2112. return fResult;
  2113. ErrorReturn:
  2114. fResult = FALSE;
  2115. goto CommonReturn;
  2116. TRACE_ERROR(GetSubKeyInfoError)
  2117. }
  2118. #if 0
  2119. //
  2120. // The following was done in IE4.0 on Win95
  2121. //
  2122. //+-------------------------------------------------------------------------
  2123. // Create the filename to contain the encoded element. The filename will
  2124. // be something like:
  2125. // C:\Windows\SystemCertificates\
  2126. // 00112233445566778899AABBCCDDEEFF00112233.0011223344556677
  2127. // Where:
  2128. // C:\Windows - obtained via GetWindowsDirectory
  2129. // SystemCertificates - subdirectory containing all file elements
  2130. // 00112233445566778899AABBCCDDEEFF00112233
  2131. // - wszSubKeyName (ascii hex sha1)
  2132. // 0011223344556677 - ascii hex of current filetime
  2133. //
  2134. //
  2135. // In addition to creating the filename, also creates the
  2136. // "SystemCertificates" directory under C:\Windows.
  2137. //--------------------------------------------------------------------------
  2138. STATIC LPWSTR CreateKeyFilename(
  2139. IN const WCHAR wszSubKeyName[MAX_CERT_REG_VALUE_NAME_LEN],
  2140. IN LPFILETIME pft
  2141. )
  2142. {
  2143. LPWSTR pwszWindowsDir = NULL;
  2144. DWORD cchWindowsDir;
  2145. WCHAR rgwc[1];
  2146. BYTE rgbft[sizeof(FILETIME)];
  2147. WCHAR wszft[FILETIME_ASCII_HEX_LEN];
  2148. LPWSTR pwszFilename = NULL;
  2149. DWORD cchFilename;
  2150. if (0 == (cchWindowsDir = GetWindowsDirectoryU(rgwc, 1)))
  2151. goto GetWindowsDirError;
  2152. cchWindowsDir++; // bump to include null terminator
  2153. if (NULL == (pwszWindowsDir = (LPWSTR) PkiNonzeroAlloc(
  2154. cchWindowsDir * sizeof(WCHAR))))
  2155. goto OutOfMemory;
  2156. if (0 == GetWindowsDirectoryU(pwszWindowsDir, cchWindowsDir))
  2157. goto GetWindowsDirError;
  2158. // Convert filetime to ascii hex. First reverse the filetime bytes.
  2159. memcpy(rgbft, pft, sizeof(rgbft));
  2160. PkiAsn1ReverseBytes(rgbft, sizeof(rgbft));
  2161. ILS_BytesToWStr(sizeof(rgbft), rgbft, wszft);
  2162. // Get total length of filename and allocate
  2163. cchFilename = cchWindowsDir + 1 +
  2164. wcslen(SYSTEM_STORE_SUBDIR) + 1 +
  2165. MAX_CERT_REG_VALUE_NAME_LEN + 1 +
  2166. FILETIME_ASCII_HEX_LEN + 1;
  2167. if (NULL == (pwszFilename = (LPWSTR) PkiNonzeroAlloc(
  2168. cchFilename * sizeof(WCHAR))))
  2169. goto OutOfMemory;
  2170. // Create C:\Windows\SystemCertificates directory if it doesn't already
  2171. // exist
  2172. wcscpy(pwszFilename, pwszWindowsDir);
  2173. cchWindowsDir = wcslen(pwszWindowsDir);
  2174. if (cchWindowsDir && L'\\' != pwszWindowsDir[cchWindowsDir - 1])
  2175. wcscat(pwszFilename, L"\\");
  2176. wcscat(pwszFilename, SYSTEM_STORE_SUBDIR);
  2177. if (0xFFFFFFFF == GetFileAttributesU(pwszFilename)) {
  2178. if (!CreateDirectoryU(
  2179. pwszFilename,
  2180. NULL // lpsa
  2181. )) goto CreateDirError;
  2182. }
  2183. // Append \<AsciiHexSubKeyName>.<AsciiHexFileTime> to the above directory
  2184. // name to complete the filename string
  2185. wcscat(pwszFilename, L"\\");
  2186. wcscat(pwszFilename, wszSubKeyName);
  2187. wcscat(pwszFilename, L".");
  2188. wcscat(pwszFilename, wszft);
  2189. CommonReturn:
  2190. PkiFree(pwszWindowsDir);
  2191. return pwszFilename;
  2192. ErrorReturn:
  2193. PkiFree(pwszFilename);
  2194. pwszFilename = NULL;
  2195. goto CommonReturn;
  2196. TRACE_ERROR(GetWindowsDirError)
  2197. TRACE_ERROR(OutOfMemory)
  2198. TRACE_ERROR(CreateDirError)
  2199. }
  2200. //+-------------------------------------------------------------------------
  2201. // Write the bytes to a a file and update the SubKey's "File" value to
  2202. // point to.
  2203. //
  2204. // This code is here to show what was done in IE4.0.
  2205. //--------------------------------------------------------------------------
  2206. STATIC BOOL WriteKeyFileElementToRegistry(
  2207. IN HKEY hSubKey,
  2208. IN const WCHAR wszSubKeyName[MAX_CERT_REG_VALUE_NAME_LEN],
  2209. IN DWORD dwFlags, // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  2210. IN BYTE *pbElement,
  2211. IN DWORD cbElement
  2212. )
  2213. {
  2214. BOOL fResult;
  2215. LONG err;
  2216. HANDLE hFile = INVALID_HANDLE_VALUE;
  2217. LPWSTR pwszFilename = NULL;
  2218. SYSTEMTIME st;
  2219. FILETIME ft;
  2220. DWORD i;
  2221. GetSystemTime(&st);
  2222. SystemTimeToFileTime(&st, &ft);
  2223. for (i = 0; i < MAX_NEW_FILE_CREATE_ATTEMPTS; i++) {
  2224. DWORD cbBytesWritten;
  2225. if (NULL == (pwszFilename = CreateKeyFilename(wszSubKeyName, &ft)))
  2226. goto CreateKeyFilenameError;
  2227. if (INVALID_HANDLE_VALUE == (hFile = CreateFileU(
  2228. pwszFilename,
  2229. GENERIC_WRITE,
  2230. 0, // fdwShareMode
  2231. NULL, // lpsa
  2232. CREATE_NEW,
  2233. FILE_ATTRIBUTE_NORMAL |
  2234. ((dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG) ?
  2235. FILE_FLAG_BACKUP_SEMANTICS : 0),
  2236. NULL // hTemplateFile
  2237. ))) {
  2238. if (ERROR_FILE_EXISTS != GetLastError())
  2239. goto CreateFileError;
  2240. else {
  2241. PkiFree(pwszFilename);
  2242. pwszFilename = NULL;
  2243. *((_int64 *) &ft) += 1;
  2244. continue;
  2245. }
  2246. }
  2247. if (!WriteFile(
  2248. hFile,
  2249. pbElement,
  2250. cbElement,
  2251. &cbBytesWritten,
  2252. NULL // lpOverlapped
  2253. )) goto WriteFileError;
  2254. CloseHandle(hFile);
  2255. hFile = INVALID_HANDLE_VALUE;
  2256. if (!SetFileAttributesU(pwszFilename,
  2257. FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY ))
  2258. goto SetFileAttributesError;
  2259. if (ERROR_SUCCESS != (err = RegSetValueExU(
  2260. hSubKey,
  2261. KEY_FILE_VALUE_NAME,
  2262. NULL,
  2263. REG_SZ,
  2264. (BYTE *) pwszFilename,
  2265. (wcslen(pwszFilename) + 1) * sizeof(WCHAR))))
  2266. goto RegSetValueError;
  2267. else
  2268. goto SuccessReturn;
  2269. }
  2270. goto ExceededMaxFileCreateAttemptsError;
  2271. SuccessReturn:
  2272. fResult = TRUE;
  2273. CommonReturn:
  2274. if (INVALID_HANDLE_VALUE != hFile)
  2275. ILS_CloseHandle(hFile);
  2276. PkiFree(pwszFilename);
  2277. return fResult;
  2278. ErrorReturn:
  2279. fResult = FALSE;
  2280. goto CommonReturn;
  2281. SET_ERROR_VAR(RegSetValueError, err)
  2282. TRACE_ERROR(CreateKeyFilenameError)
  2283. TRACE_ERROR(CreateFileError)
  2284. TRACE_ERROR(WriteFileError)
  2285. TRACE_ERROR(SetFileAttributesError)
  2286. SET_ERROR(ExceededMaxFileCreateAttemptsError, CRYPT_E_FILE_ERROR)
  2287. }
  2288. #endif // end of IE4.0 "File" support
  2289. //+-------------------------------------------------------------------------
  2290. // If the length of the element is <= MAX_KEY_BLOB_VALUE_LEN, then,
  2291. // write it as the SubKey's "Blob" value. Otherwise, write it as multiple
  2292. // SubKeys each containing a "Blob" value no larger than
  2293. // MAX_KEY_BLOB_VALUE_LEN.
  2294. //--------------------------------------------------------------------------
  2295. STATIC BOOL WriteKeyToRegistry(
  2296. IN HKEY hKey,
  2297. IN const WCHAR wszSubKeyName[MAX_CERT_REG_VALUE_NAME_LEN],
  2298. IN DWORD dwFlags, // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  2299. IN const BYTE *pbElement,
  2300. IN DWORD cbElement
  2301. )
  2302. {
  2303. BOOL fResult;
  2304. LONG err;
  2305. HKEY hSubKey = NULL;
  2306. DWORD dwDisposition;
  2307. if (ERROR_SUCCESS != (err = RegCreateHKCUKeyExU(
  2308. hKey,
  2309. wszSubKeyName,
  2310. NULL,
  2311. NULL,
  2312. (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG) ?
  2313. REG_OPTION_BACKUP_RESTORE : REG_OPTION_NON_VOLATILE,
  2314. KEY_ALL_ACCESS,
  2315. NULL,
  2316. &hSubKey,
  2317. &dwDisposition))) goto RegCreateKeyError;
  2318. if (MAX_KEY_BLOB_VALUE_LEN >= cbElement) {
  2319. // Write as a single "Blob" value
  2320. if (ERROR_SUCCESS != (err = RegSetValueExU(
  2321. hSubKey,
  2322. KEY_BLOB_VALUE_NAME,
  2323. NULL,
  2324. REG_BINARY,
  2325. pbElement,
  2326. cbElement))) goto RegSetValueError;
  2327. } else {
  2328. // Write as a multiple Blob<N> SubKeys
  2329. if (!WriteMultipleKeyBlobsToRegistry(
  2330. hSubKey, dwFlags, pbElement, cbElement))
  2331. goto WriteMultipleKeyBlobsError;
  2332. // if (!WriteKeyFileElementToRegistry(wszSubKeyName, hSubKey, dwFlags, pbElement, cbElement))
  2333. // goto ErrorReturn;
  2334. }
  2335. fResult = TRUE;
  2336. CommonReturn:
  2337. ILS_CloseRegistryKey(hSubKey);
  2338. return fResult;
  2339. ErrorReturn:
  2340. fResult = FALSE;
  2341. goto CommonReturn;
  2342. SET_ERROR_VAR(RegCreateKeyError, err)
  2343. SET_ERROR_VAR(RegSetValueError, err)
  2344. TRACE_ERROR(WriteMultipleKeyBlobsError)
  2345. }
  2346. //+=========================================================================
  2347. // Registry Functions
  2348. //==========================================================================
  2349. //+-------------------------------------------------------------------------
  2350. // First attempt to read as Key's value. If that fails for Win95, then,
  2351. // read as a value in one or more SubKeys or as a
  2352. // file with a SubKey pointing to it.
  2353. //
  2354. // If CERT_REGISTRY_STORE_REMOTE_FLAG is set, then, don't attempt to read
  2355. // from the file.
  2356. //
  2357. // If CERT_STORE_READONLY_FLAG is set, don't attempt to migrate from the
  2358. // "File".
  2359. //--------------------------------------------------------------------------
  2360. BOOL
  2361. ILS_ReadElementFromRegistry(
  2362. IN HKEY hKey,
  2363. IN LPCWSTR pwszContextName,
  2364. IN const WCHAR wszHashName[MAX_HASH_NAME_LEN],
  2365. IN DWORD dwFlags,
  2366. OUT BYTE **ppbElement,
  2367. OUT DWORD *pcbElement
  2368. )
  2369. {
  2370. LONG err;
  2371. BOOL fResult;
  2372. HKEY hSubKey = NULL;
  2373. DWORD dwType;
  2374. BYTE *pbElement = NULL;
  2375. DWORD cbElement;
  2376. if (pwszContextName) {
  2377. if (NULL == (hSubKey = OpenSubKey(
  2378. hKey,
  2379. pwszContextName,
  2380. dwFlags | CERT_STORE_READONLY_FLAG
  2381. )))
  2382. goto OpenSubKeyError;
  2383. } else
  2384. hSubKey = hKey;
  2385. err = RegQueryValueExU(
  2386. hSubKey,
  2387. wszHashName,
  2388. NULL, // pdwReserved
  2389. &dwType,
  2390. NULL, // lpData
  2391. &cbElement);
  2392. // For Win95 Remote Registry Access:: returns ERROR_MORE_DATA
  2393. if (!(ERROR_SUCCESS == err || ERROR_MORE_DATA == err)) {
  2394. fResult = ReadKeyElementFromRegistry(
  2395. hSubKey,
  2396. wszHashName,
  2397. dwFlags,
  2398. &pbElement,
  2399. &cbElement
  2400. );
  2401. goto CommonReturn;
  2402. }
  2403. if (dwType != REG_BINARY || cbElement == 0)
  2404. goto InvalidRegistryValue;
  2405. if (NULL == (pbElement = (BYTE *) PkiNonzeroAlloc(cbElement)))
  2406. goto OutOfMemory;
  2407. if (ERROR_SUCCESS != (err = RegQueryValueExU(
  2408. hSubKey,
  2409. wszHashName,
  2410. NULL, // pdwReserved
  2411. &dwType,
  2412. pbElement,
  2413. &cbElement))) goto RegQueryValueError;
  2414. fResult = TRUE;
  2415. CommonReturn:
  2416. if (pwszContextName)
  2417. ILS_CloseRegistryKey(hSubKey);
  2418. *ppbElement = pbElement;
  2419. *pcbElement = cbElement;
  2420. return fResult;
  2421. ErrorReturn:
  2422. fResult = FALSE;
  2423. PkiFree(pbElement);
  2424. pbElement = NULL;
  2425. cbElement = 0;
  2426. goto CommonReturn;
  2427. TRACE_ERROR(OpenSubKeyError)
  2428. SET_ERROR_VAR(RegQueryValueError, err)
  2429. SET_ERROR(InvalidRegistryValue, CRYPT_E_FILE_ERROR)
  2430. TRACE_ERROR(OutOfMemory)
  2431. }
  2432. //+-------------------------------------------------------------------------
  2433. // First delete as the Key's value. Then, for Win95 also delete as the
  2434. // Key's SubKey and possibly file.
  2435. //--------------------------------------------------------------------------
  2436. BOOL
  2437. ILS_DeleteElementFromRegistry(
  2438. IN HKEY hKey,
  2439. IN LPCWSTR pwszContextName,
  2440. IN const WCHAR wszHashName[MAX_HASH_NAME_LEN],
  2441. IN DWORD dwFlags
  2442. )
  2443. {
  2444. BOOL fResult;
  2445. HKEY hSubKey = NULL;
  2446. if (NULL == (hSubKey = OpenSubKey(
  2447. hKey,
  2448. pwszContextName,
  2449. dwFlags | CERT_STORE_OPEN_EXISTING_FLAG
  2450. )))
  2451. goto OpenSubKeyError;
  2452. RegDeleteValueU(hSubKey, wszHashName);
  2453. if (0 == (dwFlags & CERT_REGISTRY_STORE_REMOTE_FLAG))
  2454. DeleteKeyFile(hSubKey, wszHashName, dwFlags);
  2455. fResult = RecursiveDeleteSubKey(hSubKey, wszHashName, dwFlags);
  2456. CommonReturn:
  2457. ILS_CloseRegistryKey(hSubKey);
  2458. return fResult;
  2459. ErrorReturn:
  2460. fResult = FALSE;
  2461. goto CommonReturn;
  2462. TRACE_ERROR(OpenSubKeyError)
  2463. }
  2464. //+-------------------------------------------------------------------------
  2465. // If the length of the element is less than the maximum allowed Win95 value
  2466. // length, then, attempt to set the wszRegName SubKey's "Blob" value as
  2467. // a single registry API call. Versus, first doing registry deletes.
  2468. //--------------------------------------------------------------------------
  2469. STATIC BOOL AtomicUpdateRegistry(
  2470. IN HKEY hKey,
  2471. IN const WCHAR wszHashName[MAX_HASH_NAME_LEN],
  2472. IN DWORD dwFlags, // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  2473. IN const BYTE *pbElement,
  2474. IN DWORD cbElement
  2475. )
  2476. {
  2477. BOOL fResult;
  2478. LONG err;
  2479. HKEY hSubKey = NULL;
  2480. DWORD dwDisposition = 0;
  2481. if (MAX_KEY_BLOB_VALUE_LEN < cbElement)
  2482. return FALSE;
  2483. // In case the element still exists as a wszHashName value instead of as a
  2484. // wszHashName subkey
  2485. RegDeleteValueU(hKey, wszHashName);
  2486. if (ERROR_SUCCESS != (err = RegCreateHKCUKeyExU(
  2487. hKey,
  2488. wszHashName,
  2489. NULL,
  2490. NULL,
  2491. (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG) ?
  2492. REG_OPTION_BACKUP_RESTORE : REG_OPTION_NON_VOLATILE,
  2493. KEY_ALL_ACCESS,
  2494. NULL,
  2495. &hSubKey,
  2496. &dwDisposition))) goto AtomicRegCreateKeyError;
  2497. if (REG_OPENED_EXISTING_KEY == dwDisposition) {
  2498. DWORD dwType;
  2499. DWORD cbData;
  2500. assert(hSubKey);
  2501. err = RegQueryValueExU(
  2502. hSubKey,
  2503. KEY_BLOB_VALUE_NAME,
  2504. NULL, // pdwReserved
  2505. &dwType,
  2506. NULL, // lpData
  2507. &cbData);
  2508. if (!(ERROR_SUCCESS == err || ERROR_MORE_DATA == err))
  2509. // Most likely persisted as partioned "Blob0", "Blob1" values.
  2510. // These can't be updated in a single atomic set value.
  2511. goto AtomicQueryValueError;
  2512. // "Blob" value exists. We can do an atomic update.
  2513. }
  2514. // else
  2515. // REG_CREATED_NEW_KEY
  2516. assert(hSubKey);
  2517. // Either update or create the "Blob" value
  2518. if (ERROR_SUCCESS != (err = RegSetValueExU(
  2519. hSubKey,
  2520. KEY_BLOB_VALUE_NAME,
  2521. NULL,
  2522. REG_BINARY,
  2523. pbElement,
  2524. cbElement))) goto AtomicRegSetValueError;
  2525. fResult = TRUE;
  2526. CommonReturn:
  2527. ILS_CloseRegistryKey(hSubKey);
  2528. return fResult;
  2529. ErrorReturn:
  2530. fResult = FALSE;
  2531. goto CommonReturn;
  2532. SET_ERROR_VAR(AtomicRegCreateKeyError, err)
  2533. SET_ERROR_VAR(AtomicQueryValueError, err)
  2534. SET_ERROR_VAR(AtomicRegSetValueError, err)
  2535. }
  2536. //+-------------------------------------------------------------------------
  2537. // First attempt as an atomic registry update of the wszRegName's "Blob"
  2538. // value. If that fails, then, delete everything and write as either a
  2539. // single or partitioned blob value under the wszRegName's subkey.
  2540. //--------------------------------------------------------------------------
  2541. BOOL
  2542. ILS_WriteElementToRegistry(
  2543. IN HKEY hKey,
  2544. IN LPCWSTR pwszContextName,
  2545. IN const WCHAR wszHashName[MAX_HASH_NAME_LEN],
  2546. IN DWORD dwFlags, // CERT_REGISTRY_STORE_REMOTE_FLAG or
  2547. // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  2548. IN const BYTE *pbElement,
  2549. IN DWORD cbElement
  2550. )
  2551. {
  2552. BOOL fResult;
  2553. HKEY hSubKey = NULL;
  2554. if (NULL == (hSubKey = OpenSubKey(
  2555. hKey,
  2556. pwszContextName,
  2557. dwFlags
  2558. )))
  2559. goto OpenSubKeyError;
  2560. // See if we can do the update as a single, atomic, set registry value API
  2561. // call.
  2562. if (AtomicUpdateRegistry(
  2563. hSubKey,
  2564. wszHashName,
  2565. dwFlags,
  2566. pbElement,
  2567. cbElement
  2568. )) {
  2569. fResult = TRUE;
  2570. goto CommonReturn;
  2571. }
  2572. // If any version exists for this guy, get rid of it.
  2573. ILS_DeleteElementFromRegistry(hKey, pwszContextName, wszHashName,
  2574. dwFlags);
  2575. #if 1
  2576. fResult = WriteKeyToRegistry(hSubKey, wszHashName, dwFlags,
  2577. pbElement, cbElement);
  2578. #else
  2579. if (ERROR_SUCCESS != (err = RegSetValueExU(
  2580. hSubKey,
  2581. wszHashName,
  2582. NULL,
  2583. REG_BINARY,
  2584. pbElement,
  2585. cbElement))) {
  2586. // Win95 returns:
  2587. // ERROR_INVALID_PARAMETER if exceeded single SubKey value byte
  2588. // limitation
  2589. // ERROR_OUTOFMEMORY if exceeded total SubKey values byte
  2590. // limitation
  2591. if (ERROR_INVALID_PARAMETER == err ||
  2592. ERROR_OUTOFMEMORY == err ||
  2593. MAX_KEY_BLOB_VALUE_LEN < cbElement)
  2594. return WriteKeyToRegistry(hSubKey, wszHashName, dwFlags,
  2595. pbElement, cbElement);
  2596. goto RegSetValueError;
  2597. }
  2598. fResult = TRUE;
  2599. #endif
  2600. CommonReturn:
  2601. ILS_CloseRegistryKey(hSubKey);
  2602. return fResult;
  2603. ErrorReturn:
  2604. fResult = FALSE;
  2605. goto CommonReturn;
  2606. TRACE_ERROR(OpenSubKeyError)
  2607. #if 1
  2608. #else
  2609. SET_ERROR_VAR(RegSetValueError, err)
  2610. #endif
  2611. }
  2612. BOOL
  2613. ILS_OpenAllElementsFromRegistry(
  2614. IN HKEY hKey,
  2615. IN LPCWSTR pwszContextName,
  2616. IN DWORD dwFlags,
  2617. IN void *pvArg,
  2618. IN PFN_ILS_OPEN_ELEMENT pfnOpenElement
  2619. )
  2620. {
  2621. BOOL fResult;
  2622. HKEY hSubKey = NULL;
  2623. LONG err;
  2624. DWORD cSubKeys;
  2625. DWORD i;
  2626. dwFlags |= CERT_STORE_READONLY_FLAG;
  2627. if (NULL == (hSubKey = OpenSubKey(
  2628. hKey,
  2629. pwszContextName,
  2630. dwFlags
  2631. )))
  2632. goto OpenSubKeyError;
  2633. // see how many SubKeys in the registry
  2634. if (!GetSubKeyInfo(hSubKey, &cSubKeys))
  2635. goto GetSubKeyInfoError;
  2636. for (i = 0; i < cSubKeys; i++) {
  2637. WCHAR wszHashName[MAX_HASH_NAME_LEN];
  2638. DWORD cchHashName = MAX_HASH_NAME_LEN;
  2639. BYTE *pbElement;
  2640. DWORD cbElement;
  2641. err = RegEnumKeyExU(
  2642. hSubKey,
  2643. i,
  2644. wszHashName,
  2645. &cchHashName,
  2646. NULL, // lpdwReserved
  2647. NULL, // lpszClass
  2648. NULL, // lpcchClass
  2649. NULL // lpftLastWriteTime
  2650. );
  2651. if (ERROR_SUCCESS != err) {
  2652. if (ERROR_NO_MORE_ITEMS == err)
  2653. break;
  2654. else
  2655. continue;
  2656. }
  2657. if (ILS_ReadElementFromRegistry(
  2658. hSubKey,
  2659. NULL, // pwszContextName
  2660. wszHashName,
  2661. dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG,
  2662. &pbElement,
  2663. &cbElement
  2664. )) {
  2665. fResult = pfnOpenElement(
  2666. wszHashName,
  2667. pbElement,
  2668. cbElement,
  2669. pvArg
  2670. );
  2671. PkiFree(pbElement);
  2672. if (!fResult)
  2673. goto CommonReturn;
  2674. }
  2675. }
  2676. fResult = TRUE;
  2677. CommonReturn:
  2678. ILS_CloseRegistryKey(hSubKey);
  2679. return fResult;
  2680. ErrorReturn:
  2681. fResult = FALSE;
  2682. goto CommonReturn;
  2683. TRACE_ERROR(GetSubKeyInfoError)
  2684. TRACE_ERROR(OpenSubKeyError)
  2685. }
  2686. //+-------------------------------------------------------------------------
  2687. // Get the Certificates, CRLs or CTLs from the registry
  2688. //
  2689. // If CERT_REGISTRY_STORE_REMOTE_FLAG is set, then, don't attempt to read
  2690. // from the file.
  2691. //
  2692. // If CERT_STORE_READONLY_FLAG is set, don't attempt to migrate from the
  2693. // "File".
  2694. //
  2695. // If any contexts are persisted as values instead of as subkeys, then,
  2696. // if not READONLY, migrate from values to subkeys.
  2697. //--------------------------------------------------------------------------
  2698. STATIC BOOL OpenFromRegistry(
  2699. IN HCERTSTORE hCertStore,
  2700. IN HKEY hKeyT,
  2701. IN DWORD dwFlags
  2702. )
  2703. {
  2704. BOOL fOK = TRUE;
  2705. LONG err;
  2706. DWORD cValues, cchValuesNameMax, cbValuesMax;
  2707. WCHAR * wszValueName = NULL;
  2708. DWORD i, dwType, cchHash;
  2709. BYTE * pbElement = NULL;
  2710. DWORD cbElement;
  2711. // see how many and how big the registry is
  2712. if (ERROR_SUCCESS != (err = RegQueryInfoKeyU(
  2713. hKeyT,
  2714. NULL,
  2715. NULL,
  2716. NULL,
  2717. NULL,
  2718. NULL,
  2719. NULL,
  2720. &cValues,
  2721. &cchValuesNameMax,
  2722. &cbValuesMax,
  2723. NULL,
  2724. NULL))) goto RegQueryInfoKeyError;
  2725. if (cValues && cbValuesMax) {
  2726. // allocate the memory needed to read the reg
  2727. // Remote Registry calls on Win95 includes the NULL terminator, that's
  2728. // why we add +2 and not just +1
  2729. if (NULL == (wszValueName = (WCHAR *) PkiNonzeroAlloc(
  2730. (cchValuesNameMax+2) * sizeof(WCHAR))))
  2731. goto OutOfMemory;
  2732. if (NULL == (pbElement = (BYTE *) PkiNonzeroAlloc(cbValuesMax)))
  2733. goto OutOfMemory;
  2734. // enum the registry getting certs, CRLs or CTLs
  2735. for (i=0; i<cValues; i++ ) {
  2736. cbElement = cbValuesMax;
  2737. // Remote Registry calls on Win95 includes the NULL terminator
  2738. cchHash = cchValuesNameMax + 2;
  2739. err = RegEnumValueU( hKeyT,
  2740. i,
  2741. wszValueName,
  2742. &cchHash,
  2743. NULL,
  2744. &dwType,
  2745. pbElement,
  2746. &cbElement);
  2747. // any error get it set
  2748. // but we want to continue to get all good certs
  2749. if( err != ERROR_SUCCESS )
  2750. continue;
  2751. else {
  2752. fOK &= CertAddSerializedElementToStore(
  2753. hCertStore,
  2754. pbElement,
  2755. cbElement,
  2756. CERT_STORE_ADD_ALWAYS,
  2757. 0, // dwFlags
  2758. CERT_STORE_ALL_CONTEXT_FLAG,
  2759. NULL, // pdwContextType
  2760. NULL); // ppvContext
  2761. CertPerfIncrementRegElementReadCount();
  2762. }
  2763. }
  2764. }
  2765. fOK &= OpenKeysFromRegistry(hCertStore, hKeyT, dwFlags);
  2766. if (cValues && cbValuesMax && fOK &&
  2767. 0 == (dwFlags & CERT_STORE_READONLY_FLAG)) {
  2768. // Migrate from values to subkeys. This allows registry roaming
  2769. // from NT to Win95 without exceeding the Win95 registry
  2770. // limitations
  2771. HKEY hSubKey = NULL;
  2772. while (TRUE) {
  2773. if (NULL == (hSubKey = OpenSubKey(
  2774. hKeyT,
  2775. NULL, // pwszSubKey
  2776. CERT_STORE_OPEN_EXISTING_FLAG |
  2777. (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG)
  2778. )))
  2779. break;
  2780. cbElement = cbValuesMax;
  2781. // Remote Registry calls on Win95 includes the NULL terminator
  2782. cchHash = cchValuesNameMax + 2;
  2783. if (ERROR_SUCCESS != RegEnumValueU(
  2784. hSubKey,
  2785. 0, // iValue
  2786. wszValueName,
  2787. &cchHash,
  2788. NULL,
  2789. &dwType,
  2790. pbElement,
  2791. &cbElement))
  2792. break;
  2793. if (!WriteKeyToRegistry(hSubKey, wszValueName, dwFlags,
  2794. pbElement, cbElement))
  2795. break;
  2796. if (ERROR_SUCCESS != RegDeleteValueU(hSubKey, wszValueName))
  2797. break;
  2798. RegCloseKey(hSubKey);
  2799. }
  2800. if (hSubKey)
  2801. RegCloseKey(hSubKey);
  2802. }
  2803. CommonReturn:
  2804. // done with our memory
  2805. PkiFree(wszValueName);
  2806. PkiFree(pbElement);
  2807. return fOK;
  2808. ErrorReturn:
  2809. fOK = FALSE;
  2810. goto CommonReturn;
  2811. SET_ERROR_VAR(RegQueryInfoKeyError, err)
  2812. TRACE_ERROR(OutOfMemory)
  2813. }
  2814. STATIC BOOL MoveFromRegistryToRoamingFiles(
  2815. IN HKEY hSubKey,
  2816. IN LPCWSTR pwszStoreDirectory,
  2817. IN LPCWSTR pwszContextName,
  2818. IN DWORD dwFlags // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  2819. )
  2820. {
  2821. BYTE *pbElement = NULL;
  2822. DWORD cbElement;
  2823. while (TRUE) {
  2824. WCHAR wszSubKeyName[MAX_CERT_REG_VALUE_NAME_LEN];
  2825. DWORD cchSubKeyName = MAX_CERT_REG_VALUE_NAME_LEN;
  2826. if (ERROR_SUCCESS != RegEnumKeyExU(
  2827. hSubKey,
  2828. 0,
  2829. wszSubKeyName,
  2830. &cchSubKeyName,
  2831. NULL, // lpdwReserved
  2832. NULL, // lpszClass
  2833. NULL, // lpcchClass
  2834. NULL // lpftLastWriteTime
  2835. ))
  2836. break;
  2837. if (!ILS_ReadElementFromRegistry(
  2838. hSubKey,
  2839. NULL, // pwszContextName
  2840. wszSubKeyName,
  2841. CERT_STORE_READONLY_FLAG |
  2842. (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG),
  2843. &pbElement,
  2844. &cbElement
  2845. ))
  2846. goto ReadElementFromRegistryError;
  2847. if (!ILS_WriteElementToFile(
  2848. pwszStoreDirectory,
  2849. pwszContextName,
  2850. wszSubKeyName,
  2851. CERT_STORE_CREATE_NEW_FLAG |
  2852. (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG),
  2853. pbElement,
  2854. cbElement
  2855. )) {
  2856. if (ERROR_FILE_EXISTS != GetLastError())
  2857. goto WriteElementToFileError;
  2858. }
  2859. PkiFree(pbElement);
  2860. pbElement = NULL;
  2861. if (!RecursiveDeleteSubKey(
  2862. hSubKey,
  2863. wszSubKeyName,
  2864. dwFlags
  2865. ))
  2866. goto DeleteSubKeyError;
  2867. }
  2868. CommonReturn:
  2869. return TRUE;
  2870. ErrorReturn:
  2871. PkiFree(pbElement);
  2872. goto CommonReturn;
  2873. TRACE_ERROR(ReadElementFromRegistryError)
  2874. TRACE_ERROR(WriteElementToFileError)
  2875. TRACE_ERROR(DeleteSubKeyError)
  2876. }
  2877. typedef struct _READ_CONTEXT_CALLBACK_ARG {
  2878. BOOL fOK;
  2879. HCERTSTORE hCertStore;
  2880. } READ_CONTEXT_CALLBACK_ARG, *PREAD_CONTEXT_CALLBACK_ARG;
  2881. STATIC BOOL ReadContextCallback(
  2882. IN const WCHAR wszHashName[MAX_HASH_NAME_LEN],
  2883. IN const BYTE *pbElement,
  2884. IN DWORD cbElement,
  2885. IN void *pvArg
  2886. )
  2887. {
  2888. BOOL fResult;
  2889. PREAD_CONTEXT_CALLBACK_ARG pReadContextArg =
  2890. (PREAD_CONTEXT_CALLBACK_ARG) pvArg;
  2891. DWORD dwContextType = 0;
  2892. const void *pvContext = NULL;
  2893. fResult = CertAddSerializedElementToStore(
  2894. pReadContextArg->hCertStore,
  2895. pbElement,
  2896. cbElement,
  2897. CERT_STORE_ADD_ALWAYS,
  2898. 0, // dwFlags
  2899. CERT_STORE_ALL_CONTEXT_FLAG,
  2900. &dwContextType,
  2901. &pvContext
  2902. );
  2903. if (fResult) {
  2904. if (IsValidRegValueNameForContext(
  2905. dwContextType,
  2906. pvContext,
  2907. wszHashName
  2908. ))
  2909. FreeContext(dwContextType, pvContext);
  2910. else {
  2911. DeleteContextFromStore(dwContextType, pvContext);
  2912. pReadContextArg->fOK = FALSE;
  2913. }
  2914. } else
  2915. pReadContextArg->fOK = FALSE;
  2916. CertPerfIncrementRegElementReadCount();
  2917. return TRUE;
  2918. }
  2919. //+-------------------------------------------------------------------------
  2920. // Get all the Certificates, CRLs and CTLs from the registry
  2921. //--------------------------------------------------------------------------
  2922. STATIC BOOL OpenAllFromRegistry(
  2923. IN PREG_STORE pRegStore,
  2924. IN HCERTSTORE hCertStore
  2925. )
  2926. {
  2927. BOOL fResult;
  2928. HKEY hSubKey = NULL;
  2929. DWORD i;
  2930. for (i = 0; i < CONTEXT_COUNT; i++) {
  2931. if (pRegStore->hKey) {
  2932. if (NULL == (hSubKey = OpenSubKey(
  2933. pRegStore->hKey,
  2934. rgpwszContextSubKeyName[i],
  2935. pRegStore->dwFlags
  2936. ))) {
  2937. if (ERROR_FILE_NOT_FOUND != GetLastError())
  2938. goto OpenSubKeyError;
  2939. } else {
  2940. // Ignore any registry errors
  2941. OpenFromRegistry(hCertStore, hSubKey, pRegStore->dwFlags);
  2942. }
  2943. }
  2944. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_ROAMING_FLAG) {
  2945. READ_CONTEXT_CALLBACK_ARG ReadContextArg;
  2946. ReadContextArg.fOK = TRUE;
  2947. ReadContextArg.hCertStore = hCertStore;
  2948. if (!ILS_OpenAllElementsFromDirectory(
  2949. pRegStore->pwszStoreDirectory,
  2950. rgpwszContextSubKeyName[i],
  2951. pRegStore->dwFlags,
  2952. (void *) &ReadContextArg,
  2953. ReadContextCallback
  2954. )) {
  2955. DWORD dwErr = GetLastError();
  2956. if (!(ERROR_PATH_NOT_FOUND == dwErr ||
  2957. ERROR_FILE_NOT_FOUND == dwErr))
  2958. goto OpenRoamingFilesError;
  2959. }
  2960. // Ignore any read context errors
  2961. if (hSubKey &&
  2962. 0 == (pRegStore->dwFlags & CERT_STORE_READONLY_FLAG)) {
  2963. MoveFromRegistryToRoamingFiles(
  2964. hSubKey,
  2965. pRegStore->pwszStoreDirectory,
  2966. rgpwszContextSubKeyName[i],
  2967. pRegStore->dwFlags
  2968. );
  2969. }
  2970. }
  2971. if (hSubKey) {
  2972. ILS_CloseRegistryKey(hSubKey);
  2973. hSubKey = NULL;
  2974. }
  2975. }
  2976. if ((pRegStore->dwFlags & CERT_REGISTRY_STORE_ROAMING_FLAG) &&
  2977. pRegStore->hKey &&
  2978. 0 == (pRegStore->dwFlags & CERT_STORE_READONLY_FLAG)) {
  2979. // Move the Key Identifiers from the registry to roaming files
  2980. if (hSubKey = OpenSubKey(
  2981. pRegStore->hKey,
  2982. KEYID_CONTEXT_NAME,
  2983. pRegStore->dwFlags
  2984. )) {
  2985. MoveFromRegistryToRoamingFiles(
  2986. hSubKey,
  2987. pRegStore->pwszStoreDirectory,
  2988. KEYID_CONTEXT_NAME,
  2989. pRegStore->dwFlags
  2990. );
  2991. ILS_CloseRegistryKey(hSubKey);
  2992. hSubKey = NULL;
  2993. }
  2994. }
  2995. fResult = TRUE;
  2996. CommonReturn:
  2997. return fResult;
  2998. ErrorReturn:
  2999. ILS_CloseRegistryKey(hSubKey);
  3000. fResult = FALSE;
  3001. goto CommonReturn;
  3002. TRACE_ERROR(OpenSubKeyError)
  3003. TRACE_ERROR(OpenRoamingFilesError)
  3004. }
  3005. //+-------------------------------------------------------------------------
  3006. // Delete all the Certificates, CRLs and CTLs context subkeys. For Win95
  3007. // also delete context files.
  3008. //
  3009. // Also, if it exists, delete the "Serialized" subkey.
  3010. //--------------------------------------------------------------------------
  3011. STATIC BOOL DeleteAllFromRegistry(
  3012. IN HKEY hKey,
  3013. IN DWORD dwFlags // CERT_REGISTRY_STORE_REMOTE_FLAG or
  3014. // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  3015. )
  3016. {
  3017. BOOL fResult;
  3018. DWORD i;
  3019. for (i = 0; i < CONTEXT_COUNT; i++) {
  3020. LPCWSTR pwszSubKeyName = rgpwszContextSubKeyName[i];
  3021. if (0 == (dwFlags & CERT_REGISTRY_STORE_REMOTE_FLAG)) {
  3022. // For WIN95, if a context is stored in a file, delete the
  3023. // file
  3024. HKEY hSubKey;
  3025. if (NULL == (hSubKey = OpenSubKey(
  3026. hKey,
  3027. pwszSubKeyName,
  3028. CERT_STORE_OPEN_EXISTING_FLAG |
  3029. (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG)
  3030. ))) {
  3031. if (ERROR_FILE_NOT_FOUND != GetLastError())
  3032. goto OpenContextSubKeyError;
  3033. continue;
  3034. }
  3035. fResult = OpenKeysFromRegistry(
  3036. NULL, // hCertStore
  3037. hSubKey,
  3038. dwFlags
  3039. );
  3040. ILS_CloseRegistryKey(hSubKey);
  3041. if (!fResult)
  3042. goto DeleteKeysError;
  3043. }
  3044. if (!RecursiveDeleteSubKey(hKey, pwszSubKeyName, dwFlags)) {
  3045. if (ERROR_FILE_NOT_FOUND != GetLastError())
  3046. goto DeleteSubKeyError;
  3047. }
  3048. }
  3049. if (!RecursiveDeleteSubKey(hKey, SERIALIZED_SUBKEY_NAME, dwFlags)) {
  3050. if (ERROR_FILE_NOT_FOUND != GetLastError())
  3051. goto DeleteSubKeyError;
  3052. }
  3053. fResult = TRUE;
  3054. CommonReturn:
  3055. return fResult;
  3056. ErrorReturn:
  3057. fResult = FALSE;
  3058. goto CommonReturn;
  3059. TRACE_ERROR(OpenContextSubKeyError)
  3060. TRACE_ERROR(DeleteKeysError)
  3061. TRACE_ERROR(DeleteSubKeyError)
  3062. }
  3063. //+=========================================================================
  3064. // Serialized Registry Functions
  3065. //==========================================================================
  3066. static inline BOOL IsReadSerializedRegistry(
  3067. IN PREG_STORE pRegStore
  3068. )
  3069. {
  3070. return (pRegStore->dwFlags & CERT_REGISTRY_STORE_SERIALIZED_FLAG);
  3071. }
  3072. static inline BOOL IsWriteSerializedRegistry(
  3073. IN PREG_STORE pRegStore
  3074. )
  3075. {
  3076. if (0 == (pRegStore->dwFlags & CERT_REGISTRY_STORE_SERIALIZED_FLAG))
  3077. return FALSE;
  3078. pRegStore->fTouched = TRUE;
  3079. return TRUE;
  3080. }
  3081. //+-------------------------------------------------------------------------
  3082. // Get all the Certificates, CRLs and CTLs from a single serialized
  3083. // partitioned "blob" stored in the registry. The "blob" is stored under
  3084. // the "Serialized" subkey.
  3085. //
  3086. // Either called during initial open or with RegStore locked.
  3087. //--------------------------------------------------------------------------
  3088. STATIC BOOL OpenAllFromSerializedRegistry(
  3089. IN PREG_STORE pRegStore,
  3090. IN HCERTSTORE hCertStore
  3091. )
  3092. {
  3093. BOOL fResult;
  3094. HKEY hSubKey = NULL;
  3095. BYTE *pbStore = NULL;
  3096. DWORD cbStore;
  3097. assert(pRegStore->dwFlags & CERT_REGISTRY_STORE_SERIALIZED_FLAG);
  3098. if (NULL == (hSubKey = OpenSubKey(
  3099. pRegStore->hKey,
  3100. SERIALIZED_SUBKEY_NAME,
  3101. pRegStore->dwFlags
  3102. )))
  3103. goto OpenSubKeyError;
  3104. if (!ReadMultipleKeyBlobsFromRegistry(
  3105. hSubKey,
  3106. pRegStore->dwFlags,
  3107. &pbStore,
  3108. &cbStore
  3109. ))
  3110. goto ReadError;
  3111. if (!I_CertAddSerializedStore(
  3112. hCertStore,
  3113. pbStore,
  3114. cbStore
  3115. ))
  3116. goto AddError;
  3117. fResult = TRUE;
  3118. CommonReturn:
  3119. ILS_CloseRegistryKey(hSubKey);
  3120. PkiFree(pbStore);
  3121. return fResult;
  3122. ErrorReturn:
  3123. if (ERROR_FILE_NOT_FOUND == GetLastError())
  3124. fResult = TRUE;
  3125. else
  3126. fResult = FALSE;
  3127. goto CommonReturn;
  3128. TRACE_ERROR(OpenSubKeyError)
  3129. TRACE_ERROR(ReadError)
  3130. TRACE_ERROR(AddError)
  3131. }
  3132. //+=========================================================================
  3133. // Serialized Control Functions
  3134. //==========================================================================
  3135. STATIC BOOL IsEmptyStore(
  3136. IN HCERTSTORE hCertStore
  3137. )
  3138. {
  3139. PCCERT_CONTEXT pCert;
  3140. PCCRL_CONTEXT pCrl;
  3141. PCCTL_CONTEXT pCtl;
  3142. if (pCert = CertEnumCertificatesInStore(hCertStore, NULL)) {
  3143. CertFreeCertificateContext(pCert);
  3144. return FALSE;
  3145. }
  3146. if (pCrl = CertEnumCRLsInStore(hCertStore, NULL)) {
  3147. CertFreeCRLContext(pCrl);
  3148. return FALSE;
  3149. }
  3150. if (pCtl = CertEnumCTLsInStore(hCertStore, NULL)) {
  3151. CertFreeCTLContext(pCtl);
  3152. return FALSE;
  3153. }
  3154. return TRUE;
  3155. }
  3156. STATIC BOOL CommitAllToSerializedRegistry(
  3157. IN PREG_STORE pRegStore,
  3158. IN DWORD dwFlags
  3159. )
  3160. {
  3161. BOOL fResult;
  3162. BOOL fTouched;
  3163. CRYPT_DATA_BLOB SerializedData = {0, NULL};
  3164. HKEY hSubKey = NULL;
  3165. LockRegStore(pRegStore);
  3166. assert(pRegStore->dwFlags & CERT_REGISTRY_STORE_SERIALIZED_FLAG);
  3167. if (dwFlags & CERT_STORE_CTRL_COMMIT_FORCE_FLAG)
  3168. fTouched = TRUE;
  3169. else if (dwFlags & CERT_STORE_CTRL_COMMIT_CLEAR_FLAG)
  3170. fTouched = FALSE;
  3171. else
  3172. fTouched = pRegStore->fTouched;
  3173. if (fTouched) {
  3174. BOOL fEmpty;
  3175. if (pRegStore->dwFlags & CERT_STORE_READONLY_FLAG)
  3176. goto AccessDenied;
  3177. fEmpty = IsEmptyStore(pRegStore->hCertStore);
  3178. if (!fEmpty) {
  3179. if (!CertSaveStore(
  3180. pRegStore->hCertStore,
  3181. 0, // dwEncodingType
  3182. CERT_STORE_SAVE_AS_STORE,
  3183. CERT_STORE_SAVE_TO_MEMORY,
  3184. &SerializedData,
  3185. 0)) // dwFlags
  3186. goto SaveStoreError;
  3187. assert(SerializedData.cbData);
  3188. if (NULL == (SerializedData.pbData = (BYTE *) PkiNonzeroAlloc(
  3189. SerializedData.cbData)))
  3190. goto OutOfMemory;
  3191. if (!CertSaveStore(
  3192. pRegStore->hCertStore,
  3193. 0, // dwEncodingType
  3194. CERT_STORE_SAVE_AS_STORE,
  3195. CERT_STORE_SAVE_TO_MEMORY,
  3196. &SerializedData,
  3197. 0)) // dwFlags
  3198. goto SaveStoreError;
  3199. }
  3200. if (!RecursiveDeleteSubKey(
  3201. pRegStore->hKey, SERIALIZED_SUBKEY_NAME, pRegStore->dwFlags)) {
  3202. if (ERROR_FILE_NOT_FOUND != GetLastError())
  3203. goto DeleteSubKeyError;
  3204. }
  3205. if (!fEmpty) {
  3206. if (NULL == (hSubKey = OpenSubKey(
  3207. pRegStore->hKey,
  3208. SERIALIZED_SUBKEY_NAME,
  3209. pRegStore->dwFlags
  3210. )))
  3211. goto OpenSubKeyError;
  3212. if (!WriteMultipleKeyBlobsToRegistry(
  3213. hSubKey,
  3214. pRegStore->dwFlags,
  3215. SerializedData.pbData,
  3216. SerializedData.cbData
  3217. ))
  3218. goto WriteStoreError;
  3219. }
  3220. }
  3221. pRegStore->fTouched = FALSE;
  3222. fResult = TRUE;
  3223. CommonReturn:
  3224. ILS_CloseRegistryKey(hSubKey);
  3225. PkiFree(SerializedData.pbData);
  3226. UnlockRegStore(pRegStore);
  3227. return fResult;
  3228. ErrorReturn:
  3229. fResult = FALSE;
  3230. goto CommonReturn;
  3231. SET_ERROR(AccessDenied, E_ACCESSDENIED)
  3232. TRACE_ERROR(SaveStoreError)
  3233. TRACE_ERROR(OutOfMemory)
  3234. TRACE_ERROR(DeleteSubKeyError)
  3235. TRACE_ERROR(OpenSubKeyError)
  3236. TRACE_ERROR(WriteStoreError)
  3237. }
  3238. //+-------------------------------------------------------------------------
  3239. // Open the registry's store by reading its serialized certificates,
  3240. // CRLs and CTLs and adding to the specified certificate store.
  3241. //
  3242. // Note for an error return, the caller will free any certs, CRLs or CTLs
  3243. // successfully added to the store.
  3244. //
  3245. // Only return HKEY for success. For a CertOpenStore error the caller
  3246. // will close the HKEY.
  3247. //--------------------------------------------------------------------------
  3248. BOOL
  3249. WINAPI
  3250. I_CertDllOpenRegStoreProv(
  3251. IN LPCSTR lpszStoreProvider,
  3252. IN DWORD dwEncodingType,
  3253. IN HCRYPTPROV hCryptProv,
  3254. IN DWORD dwFlags,
  3255. IN const void *pvPara,
  3256. IN HCERTSTORE hCertStore,
  3257. IN OUT PCERT_STORE_PROV_INFO pStoreProvInfo
  3258. )
  3259. {
  3260. BOOL fResult;
  3261. HKEY hKey = (HKEY) pvPara;
  3262. PREG_STORE pRegStore = NULL;
  3263. DWORD dwErr;
  3264. assert(hKey);
  3265. if (dwFlags & ~OPEN_REG_FLAGS_MASK)
  3266. goto InvalidArg;
  3267. if (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG)
  3268. ILS_EnableBackupRestorePrivileges();
  3269. if (dwFlags & CERT_STORE_DELETE_FLAG) {
  3270. if (DeleteAllFromRegistry(hKey, dwFlags)) {
  3271. pStoreProvInfo->dwStoreProvFlags |= CERT_STORE_PROV_DELETED_FLAG;
  3272. return TRUE;
  3273. } else
  3274. return FALSE;
  3275. }
  3276. if (NULL == (pRegStore = (PREG_STORE) PkiZeroAlloc(sizeof(REG_STORE))))
  3277. goto OutOfMemory;
  3278. if (!Pki_InitializeCriticalSection(&pRegStore->CriticalSection)) {
  3279. PkiFree(pRegStore);
  3280. pRegStore = NULL;
  3281. goto OutOfMemory;
  3282. }
  3283. pRegStore->hCertStore = hCertStore;
  3284. pRegStore->dwFlags = dwFlags;
  3285. CertPerfIncrementStoreRegTotalCount();
  3286. CertPerfIncrementStoreRegCurrentCount();
  3287. if (dwFlags & CERT_REGISTRY_STORE_CLIENT_GPT_FLAG) {
  3288. PCERT_REGISTRY_STORE_CLIENT_GPT_PARA pGptPara =
  3289. (PCERT_REGISTRY_STORE_CLIENT_GPT_PARA) pvPara;
  3290. DWORD cbRegPath = (wcslen(pGptPara->pwszRegPath) + 1) * sizeof(WCHAR);
  3291. if (NULL == (pRegStore->GptPara.pwszRegPath =
  3292. (LPWSTR) PkiNonzeroAlloc(cbRegPath)))
  3293. goto OutOfMemory;
  3294. memcpy(pRegStore->GptPara.pwszRegPath, pGptPara->pwszRegPath,
  3295. cbRegPath);
  3296. // Make a copy of the base hKey
  3297. // BUG in NT4.0 and NT5.0. Doesn't support opening of the HKLM with
  3298. // a NULL pwszSubKey
  3299. if (HKEY_LOCAL_MACHINE == pGptPara->hKeyBase)
  3300. pRegStore->GptPara.hKeyBase = HKEY_LOCAL_MACHINE;
  3301. else if (NULL == (pRegStore->GptPara.hKeyBase = OpenSubKey(
  3302. pGptPara->hKeyBase,
  3303. NULL, // pwszSubKey
  3304. (dwFlags & ~CERT_STORE_CREATE_NEW_FLAG) |
  3305. CERT_STORE_OPEN_EXISTING_FLAG
  3306. )))
  3307. goto OpenSubKeyError;
  3308. fResult = OpenAllFromGptRegistry(pRegStore,
  3309. pRegStore->hCertStore);
  3310. #if 1
  3311. // For subsequent opens, allow subkey create if it doesn't already
  3312. // exist.
  3313. pRegStore->dwFlags &= ~(CERT_STORE_OPEN_EXISTING_FLAG |
  3314. CERT_STORE_CREATE_NEW_FLAG);
  3315. #else
  3316. // For subsequent opens, allow subkey create if it doesn't already
  3317. // exist. However, preserve open existing.
  3318. pRegStore->dwFlags &= ~CERT_STORE_CREATE_NEW_FLAG;
  3319. #endif
  3320. } else if (dwFlags & CERT_REGISTRY_STORE_ROAMING_FLAG) {
  3321. PCERT_REGISTRY_STORE_ROAMING_PARA pRoamingPara =
  3322. (PCERT_REGISTRY_STORE_ROAMING_PARA) pvPara;
  3323. DWORD cbDir = (wcslen(pRoamingPara->pwszStoreDirectory) + 1) *
  3324. sizeof(WCHAR);
  3325. if (NULL == (pRegStore->pwszStoreDirectory = (LPWSTR) PkiNonzeroAlloc(
  3326. cbDir)))
  3327. goto OutOfMemory;
  3328. memcpy(pRegStore->pwszStoreDirectory, pRoamingPara->pwszStoreDirectory,
  3329. cbDir);
  3330. dwFlags &= ~CERT_STORE_CREATE_NEW_FLAG;
  3331. dwFlags |= CERT_STORE_OPEN_EXISTING_FLAG;
  3332. pRegStore->dwFlags = dwFlags;
  3333. if (pRoamingPara->hKey) {
  3334. // Make a copy of the input hKey
  3335. if (NULL == (pRegStore->hKey = OpenSubKey(
  3336. pRoamingPara->hKey,
  3337. NULL, // pwszSubKey
  3338. dwFlags
  3339. )))
  3340. goto OpenSubKeyError;
  3341. }
  3342. fResult = OpenAllFromRegistry(pRegStore, pRegStore->hCertStore);
  3343. } else {
  3344. // Make a copy of the input hKey
  3345. if (NULL == (pRegStore->hKey = OpenSubKey(
  3346. hKey,
  3347. NULL, // pwszSubKey
  3348. (dwFlags & ~CERT_STORE_CREATE_NEW_FLAG) |
  3349. CERT_STORE_OPEN_EXISTING_FLAG
  3350. )))
  3351. goto OpenSubKeyError;
  3352. if (dwFlags & CERT_REGISTRY_STORE_SERIALIZED_FLAG)
  3353. fResult = OpenAllFromSerializedRegistry(pRegStore,
  3354. pRegStore->hCertStore);
  3355. else
  3356. fResult = OpenAllFromRegistry(pRegStore, pRegStore->hCertStore);
  3357. // For subsequent opens, allow subkey create if it doesn't already
  3358. // exist.
  3359. pRegStore->dwFlags &= ~(CERT_STORE_OPEN_EXISTING_FLAG |
  3360. CERT_STORE_CREATE_NEW_FLAG);
  3361. }
  3362. if (!fResult)
  3363. goto OpenAllError;
  3364. pStoreProvInfo->cStoreProvFunc = REG_STORE_PROV_FUNC_COUNT;
  3365. pStoreProvInfo->rgpvStoreProvFunc = (void **) rgpvRegStoreProvFunc;
  3366. pStoreProvInfo->hStoreProv = (HCERTSTOREPROV) pRegStore;
  3367. fResult = TRUE;
  3368. CommonReturn:
  3369. return fResult;
  3370. ErrorReturn:
  3371. dwErr = GetLastError();
  3372. RegStoreProvClose((HCERTSTOREPROV) pRegStore, 0);
  3373. SetLastError(dwErr);
  3374. fResult = FALSE;
  3375. goto CommonReturn;
  3376. SET_ERROR(InvalidArg, E_INVALIDARG)
  3377. TRACE_ERROR(OutOfMemory)
  3378. TRACE_ERROR(OpenSubKeyError)
  3379. TRACE_ERROR(OpenAllError)
  3380. }
  3381. //+-------------------------------------------------------------------------
  3382. // Close the registry's store by closing its opened registry subkeys
  3383. //--------------------------------------------------------------------------
  3384. STATIC void WINAPI RegStoreProvClose(
  3385. IN HCERTSTOREPROV hStoreProv,
  3386. IN DWORD dwFlags
  3387. )
  3388. {
  3389. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  3390. if (pRegStore) {
  3391. CertPerfDecrementStoreRegCurrentCount();
  3392. FreeRegistryStoreChange(pRegStore);
  3393. if (hWin95NotifyEvent)
  3394. Win95StoreSignalAndFreeRegStoreResyncEntries(pRegStore);
  3395. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_CLIENT_GPT_FLAG) {
  3396. if (pRegStore->fTouched)
  3397. CommitAllToGptRegistry(
  3398. pRegStore,
  3399. 0 // dwFlags
  3400. );
  3401. FreeGptStoreChangeInfo(&pRegStore->pGptStoreChangeInfo);
  3402. GptStoreSignalAndFreeRegStoreResyncEntries(pRegStore);
  3403. PkiFree(pRegStore->GptPara.pwszRegPath);
  3404. // BUG in NT4.0 and NT5.0. Doesn't support opening of the HKLM with
  3405. // a NULL pwszSubKey
  3406. if (pRegStore->GptPara.hKeyBase &&
  3407. HKEY_LOCAL_MACHINE != pRegStore->GptPara.hKeyBase)
  3408. RegCloseKey(pRegStore->GptPara.hKeyBase);
  3409. } else if (pRegStore->dwFlags & CERT_REGISTRY_STORE_ROAMING_FLAG) {
  3410. PkiFree(pRegStore->pwszStoreDirectory);
  3411. } else if (pRegStore->dwFlags & CERT_REGISTRY_STORE_SERIALIZED_FLAG) {
  3412. if (pRegStore->fTouched)
  3413. CommitAllToSerializedRegistry(
  3414. pRegStore,
  3415. 0 // dwFlags
  3416. );
  3417. }
  3418. if (pRegStore->hKey)
  3419. RegCloseKey(pRegStore->hKey);
  3420. if (pRegStore->hMyNotifyChange)
  3421. CloseHandle(pRegStore->hMyNotifyChange);
  3422. DeleteCriticalSection(&pRegStore->CriticalSection);
  3423. PkiFree(pRegStore);
  3424. }
  3425. }
  3426. //+-------------------------------------------------------------------------
  3427. // Read the serialized copy of the context from either the registry or
  3428. // a roaming file and create a new context.
  3429. //--------------------------------------------------------------------------
  3430. STATIC BOOL ReadContext(
  3431. IN PREG_STORE pRegStore,
  3432. IN DWORD dwContextType,
  3433. IN const WCHAR wszSubKeyName[MAX_CERT_REG_VALUE_NAME_LEN],
  3434. OUT const void **ppvContext
  3435. )
  3436. {
  3437. BOOL fResult;
  3438. BYTE *pbElement = NULL;
  3439. DWORD cbElement;
  3440. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_ROAMING_FLAG) {
  3441. if (!ILS_ReadElementFromFile(
  3442. pRegStore->pwszStoreDirectory,
  3443. rgpwszContextSubKeyName[dwContextType],
  3444. wszSubKeyName,
  3445. pRegStore->dwFlags,
  3446. &pbElement,
  3447. &cbElement
  3448. ))
  3449. goto ReadElementFromFileError;
  3450. } else {
  3451. HKEY hKey;
  3452. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_CLIENT_GPT_FLAG) {
  3453. if (NULL == (hKey = OpenSubKey(
  3454. pRegStore->GptPara.hKeyBase,
  3455. pRegStore->GptPara.pwszRegPath,
  3456. pRegStore->dwFlags
  3457. )))
  3458. goto OpenSubKeyError;
  3459. } else
  3460. hKey = pRegStore->hKey;
  3461. fResult = ILS_ReadElementFromRegistry(
  3462. hKey,
  3463. rgpwszContextSubKeyName[dwContextType],
  3464. wszSubKeyName,
  3465. pRegStore->dwFlags,
  3466. &pbElement,
  3467. &cbElement
  3468. );
  3469. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_CLIENT_GPT_FLAG) {
  3470. ILS_CloseRegistryKey(hKey);
  3471. }
  3472. if (!fResult)
  3473. goto ReadElementFromRegistryError;
  3474. }
  3475. if (!CertAddSerializedElementToStore(
  3476. NULL, // hCertStore,
  3477. pbElement,
  3478. cbElement,
  3479. CERT_STORE_ADD_ALWAYS,
  3480. 0, // dwFlags
  3481. rgdwContextTypeFlags[dwContextType],
  3482. NULL, // pdwContextType
  3483. ppvContext))
  3484. goto AddSerializedElementError;
  3485. CertPerfIncrementRegElementReadCount();
  3486. fResult = TRUE;
  3487. CommonReturn:
  3488. PkiFree(pbElement);
  3489. return fResult;
  3490. ErrorReturn:
  3491. fResult = FALSE;
  3492. *ppvContext = NULL;
  3493. goto CommonReturn;
  3494. TRACE_ERROR(ReadElementFromFileError)
  3495. TRACE_ERROR(ReadElementFromRegistryError)
  3496. TRACE_ERROR(AddSerializedElementError)
  3497. TRACE_ERROR(OpenSubKeyError)
  3498. }
  3499. //+-------------------------------------------------------------------------
  3500. // Write the serialized context and its properties to
  3501. // the registry or a roaming file.
  3502. //
  3503. // Called before the context is written to the store.
  3504. //--------------------------------------------------------------------------
  3505. STATIC BOOL WriteSerializedContext(
  3506. IN PREG_STORE pRegStore,
  3507. IN DWORD dwContextType,
  3508. IN const WCHAR wszSubKeyName[MAX_CERT_REG_VALUE_NAME_LEN],
  3509. IN const BYTE *pbElement,
  3510. IN DWORD cbElement
  3511. )
  3512. {
  3513. BOOL fResult;
  3514. CertPerfIncrementRegElementWriteCount();
  3515. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_ROAMING_FLAG)
  3516. fResult = ILS_WriteElementToFile(
  3517. pRegStore->pwszStoreDirectory,
  3518. rgpwszContextSubKeyName[dwContextType],
  3519. wszSubKeyName,
  3520. pRegStore->dwFlags,
  3521. pbElement,
  3522. cbElement
  3523. );
  3524. else {
  3525. HKEY hKey;
  3526. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_CLIENT_GPT_FLAG) {
  3527. if (NULL == (hKey = OpenSubKey(
  3528. pRegStore->GptPara.hKeyBase,
  3529. pRegStore->GptPara.pwszRegPath,
  3530. pRegStore->dwFlags
  3531. )))
  3532. return FALSE;
  3533. } else
  3534. hKey = pRegStore->hKey;
  3535. fResult = ILS_WriteElementToRegistry(
  3536. hKey,
  3537. rgpwszContextSubKeyName[dwContextType],
  3538. wszSubKeyName,
  3539. pRegStore->dwFlags,
  3540. pbElement,
  3541. cbElement
  3542. );
  3543. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_CLIENT_GPT_FLAG) {
  3544. ILS_CloseRegistryKey(hKey);
  3545. }
  3546. if (hWin95NotifyEvent && fResult)
  3547. PulseEvent(hWin95NotifyEvent);
  3548. }
  3549. return fResult;
  3550. }
  3551. //+-------------------------------------------------------------------------
  3552. // Delete the context and its properties from the
  3553. // the registry or a roaming file.
  3554. //
  3555. // Called before the context is deleted from the store.
  3556. //--------------------------------------------------------------------------
  3557. STATIC BOOL DeleteContext(
  3558. IN PREG_STORE pRegStore,
  3559. IN DWORD dwContextType,
  3560. IN const WCHAR wszSubKeyName[MAX_CERT_REG_VALUE_NAME_LEN]
  3561. )
  3562. {
  3563. BOOL fResult;
  3564. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_ROAMING_FLAG)
  3565. fResult = ILS_DeleteElementFromDirectory(
  3566. pRegStore->pwszStoreDirectory,
  3567. rgpwszContextSubKeyName[dwContextType],
  3568. wszSubKeyName,
  3569. pRegStore->dwFlags
  3570. );
  3571. else {
  3572. HKEY hKey;
  3573. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_CLIENT_GPT_FLAG) {
  3574. if (NULL == (hKey = OpenSubKey(
  3575. pRegStore->GptPara.hKeyBase,
  3576. pRegStore->GptPara.pwszRegPath,
  3577. pRegStore->dwFlags
  3578. )))
  3579. return FALSE;
  3580. } else
  3581. hKey = pRegStore->hKey;
  3582. fResult = ILS_DeleteElementFromRegistry(
  3583. hKey,
  3584. rgpwszContextSubKeyName[dwContextType],
  3585. wszSubKeyName,
  3586. pRegStore->dwFlags
  3587. );
  3588. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_CLIENT_GPT_FLAG) {
  3589. ILS_CloseRegistryKey(hKey);
  3590. }
  3591. if (hWin95NotifyEvent && fResult)
  3592. PulseEvent(hWin95NotifyEvent);
  3593. }
  3594. CertPerfIncrementRegElementDeleteCount();
  3595. if (!fResult) {
  3596. DWORD dwErr = GetLastError();
  3597. if (ERROR_PATH_NOT_FOUND == dwErr || ERROR_FILE_NOT_FOUND == dwErr)
  3598. fResult = TRUE;
  3599. }
  3600. return fResult;
  3601. }
  3602. //+-------------------------------------------------------------------------
  3603. // Read the serialized copy of the certificate and its properties from
  3604. // the registry and create a new certificate context.
  3605. //--------------------------------------------------------------------------
  3606. STATIC BOOL WINAPI RegStoreProvReadCert(
  3607. IN HCERTSTOREPROV hStoreProv,
  3608. IN PCCERT_CONTEXT pStoreCertContext,
  3609. IN DWORD dwFlags,
  3610. OUT PCCERT_CONTEXT *ppProvCertContext
  3611. )
  3612. {
  3613. BOOL fResult;
  3614. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  3615. WCHAR wsz[MAX_CERT_REG_VALUE_NAME_LEN];
  3616. assert(pRegStore);
  3617. if (IsReadSerializedRegistry(pRegStore))
  3618. goto UnexpectedReadError;
  3619. if (!GetCertRegValueName(pStoreCertContext, wsz))
  3620. goto GetRegValueNameError;
  3621. fResult = ReadContext(
  3622. pRegStore,
  3623. CERT_STORE_CERTIFICATE_CONTEXT - 1,
  3624. wsz,
  3625. (const void **) ppProvCertContext
  3626. );
  3627. CommonReturn:
  3628. return fResult;
  3629. ErrorReturn:
  3630. fResult = FALSE;
  3631. *ppProvCertContext = NULL;
  3632. goto CommonReturn;
  3633. SET_ERROR(UnexpectedReadError, E_UNEXPECTED)
  3634. TRACE_ERROR(GetRegValueNameError)
  3635. }
  3636. //+-------------------------------------------------------------------------
  3637. // Serialize the encoded certificate and its properties and write to
  3638. // the registry.
  3639. //
  3640. // Called before the certificate is written to the store.
  3641. //
  3642. // Note, don't set the IEDirtyFlag if setting a property.
  3643. //--------------------------------------------------------------------------
  3644. STATIC BOOL WINAPI RegStoreProvWriteCertEx(
  3645. IN HCERTSTOREPROV hStoreProv,
  3646. IN PCCERT_CONTEXT pCertContext,
  3647. IN DWORD dwFlags,
  3648. IN BOOL fSetProperty
  3649. )
  3650. {
  3651. BOOL fResult;
  3652. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  3653. WCHAR wsz[MAX_CERT_REG_VALUE_NAME_LEN];
  3654. BYTE *pbElement = NULL;
  3655. DWORD cbElement;
  3656. assert(pRegStore);
  3657. if (IsInResync(pRegStore))
  3658. // Only update the store cache, don't write back to registry
  3659. return TRUE;
  3660. if (pRegStore->dwFlags & CERT_STORE_READONLY_FLAG)
  3661. goto AccessDenied;
  3662. if (IsWriteSerializedRegistry(pRegStore))
  3663. return TRUE;
  3664. if (!GetCertRegValueName(pCertContext, wsz))
  3665. goto GetRegValueNameError;
  3666. // get the size
  3667. if (!CertSerializeCertificateStoreElement(
  3668. pCertContext, 0, NULL, &cbElement))
  3669. goto SerializeStoreElementError;
  3670. if (NULL == (pbElement = (BYTE *) PkiNonzeroAlloc(cbElement)))
  3671. goto OutOfMemory;
  3672. // put it into the buffer
  3673. if (!CertSerializeCertificateStoreElement(
  3674. pCertContext, 0, pbElement, &cbElement))
  3675. goto SerializeStoreElementError;
  3676. // write it to the registry or roaming file
  3677. fResult = WriteSerializedContext(
  3678. pRegStore,
  3679. CERT_STORE_CERTIFICATE_CONTEXT - 1,
  3680. wsz,
  3681. pbElement,
  3682. cbElement
  3683. );
  3684. CommonReturn:
  3685. PkiFree(pbElement);
  3686. return fResult;
  3687. ErrorReturn:
  3688. fResult = FALSE;
  3689. goto CommonReturn;
  3690. SET_ERROR(AccessDenied, E_ACCESSDENIED)
  3691. TRACE_ERROR(GetRegValueNameError)
  3692. TRACE_ERROR(OutOfMemory)
  3693. TRACE_ERROR(SerializeStoreElementError)
  3694. }
  3695. STATIC BOOL WINAPI RegStoreProvWriteCert(
  3696. IN HCERTSTOREPROV hStoreProv,
  3697. IN PCCERT_CONTEXT pCertContext,
  3698. IN DWORD dwFlags
  3699. )
  3700. {
  3701. return RegStoreProvWriteCertEx(
  3702. hStoreProv,
  3703. pCertContext,
  3704. dwFlags,
  3705. FALSE // fSetProperty
  3706. );
  3707. }
  3708. //+-------------------------------------------------------------------------
  3709. // Delete the specified certificate from the registry.
  3710. //
  3711. // Called before the certificate is deleted from the store.
  3712. //+-------------------------------------------------------------------------
  3713. STATIC BOOL WINAPI RegStoreProvDeleteCert(
  3714. IN HCERTSTOREPROV hStoreProv,
  3715. IN PCCERT_CONTEXT pCertContext,
  3716. IN DWORD dwFlags
  3717. )
  3718. {
  3719. BOOL fResult;
  3720. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  3721. WCHAR wsz[MAX_CERT_REG_VALUE_NAME_LEN];
  3722. assert(pRegStore);
  3723. if (IsInResync(pRegStore))
  3724. // Only delete from store cache, not from registry
  3725. return TRUE;
  3726. if (pRegStore->dwFlags & CERT_STORE_READONLY_FLAG)
  3727. goto AccessDenied;
  3728. if (IsWriteSerializedRegistry(pRegStore))
  3729. return TRUE;
  3730. if (!GetCertRegValueName(pCertContext, wsz))
  3731. goto GetRegValueNameError;
  3732. // delete this cert
  3733. fResult = DeleteContext(
  3734. pRegStore,
  3735. CERT_STORE_CERTIFICATE_CONTEXT - 1,
  3736. wsz
  3737. );
  3738. CommonReturn:
  3739. return fResult;
  3740. ErrorReturn:
  3741. fResult = FALSE;
  3742. goto CommonReturn;
  3743. SET_ERROR(AccessDenied, E_ACCESSDENIED)
  3744. TRACE_ERROR(GetRegValueNameError)
  3745. }
  3746. //+-------------------------------------------------------------------------
  3747. // Read the specified certificate from the registry and update its
  3748. // property.
  3749. //
  3750. // Note, ignore the CERT_SHA1_HASH_PROP_ID property which is implicitly
  3751. // set before we write the certificate to the registry. If we don't ignore,
  3752. // we will have indefinite recursion.
  3753. //
  3754. // Called before setting the property of the certificate in the store.
  3755. //--------------------------------------------------------------------------
  3756. STATIC BOOL WINAPI RegStoreProvSetCertProperty(
  3757. IN HCERTSTOREPROV hStoreProv,
  3758. IN PCCERT_CONTEXT pCertContext,
  3759. IN DWORD dwPropId,
  3760. IN DWORD dwFlags,
  3761. IN const void *pvData
  3762. )
  3763. {
  3764. BOOL fResult;
  3765. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  3766. PCCERT_CONTEXT pProvCertContext = NULL;
  3767. // This property is implicitly written whenever we do a CertWrite.
  3768. if (CERT_SHA1_HASH_PROP_ID == dwPropId)
  3769. return TRUE;
  3770. assert(pRegStore);
  3771. if (IsInResync(pRegStore))
  3772. // Only update the store cache, don't write back to registry
  3773. return TRUE;
  3774. if (pRegStore->dwFlags & CERT_STORE_READONLY_FLAG)
  3775. goto AccessDenied;
  3776. if (IsWriteSerializedRegistry(pRegStore))
  3777. return TRUE;
  3778. // Create a certificate context from the current serialized value stored
  3779. // in the registry.
  3780. if (!RegStoreProvReadCert(
  3781. hStoreProv,
  3782. pCertContext,
  3783. 0, // dwFlags
  3784. &pProvCertContext)) goto ReadError;
  3785. // Set the property in the above created certificate context.
  3786. if (!CertSetCertificateContextProperty(
  3787. pProvCertContext,
  3788. dwPropId,
  3789. dwFlags,
  3790. pvData)) goto SetPropertyError;
  3791. // Serialize and write the above updated certificate back to the
  3792. // registry.
  3793. if (!RegStoreProvWriteCertEx(
  3794. hStoreProv,
  3795. pProvCertContext,
  3796. 0, // dwFlags
  3797. TRUE // fSetProperty
  3798. ))
  3799. goto WriteError;
  3800. fResult = TRUE;
  3801. CommonReturn:
  3802. CertFreeCertificateContext(pProvCertContext);
  3803. return fResult;
  3804. ErrorReturn:
  3805. fResult = FALSE;
  3806. goto CommonReturn;
  3807. SET_ERROR(AccessDenied, E_ACCESSDENIED)
  3808. TRACE_ERROR(ReadError)
  3809. TRACE_ERROR(SetPropertyError)
  3810. TRACE_ERROR(WriteError)
  3811. }
  3812. //+-------------------------------------------------------------------------
  3813. // Read the serialized copy of the CRL and its properties from
  3814. // the registry and create a new CRL context.
  3815. //--------------------------------------------------------------------------
  3816. STATIC BOOL WINAPI RegStoreProvReadCrl(
  3817. IN HCERTSTOREPROV hStoreProv,
  3818. IN PCCRL_CONTEXT pStoreCrlContext,
  3819. IN DWORD dwFlags,
  3820. OUT PCCRL_CONTEXT *ppProvCrlContext
  3821. )
  3822. {
  3823. BOOL fResult;
  3824. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  3825. WCHAR wsz[MAX_CERT_REG_VALUE_NAME_LEN];
  3826. assert(pRegStore);
  3827. if (IsReadSerializedRegistry(pRegStore))
  3828. goto UnexpectedReadError;
  3829. if (!GetCrlRegValueName(pStoreCrlContext, wsz))
  3830. goto GetRegValueNameError;
  3831. fResult = ReadContext(
  3832. pRegStore,
  3833. CERT_STORE_CRL_CONTEXT - 1,
  3834. wsz,
  3835. (const void **) ppProvCrlContext
  3836. );
  3837. CommonReturn:
  3838. return fResult;
  3839. ErrorReturn:
  3840. fResult = FALSE;
  3841. *ppProvCrlContext = NULL;
  3842. goto CommonReturn;
  3843. SET_ERROR(UnexpectedReadError, E_UNEXPECTED)
  3844. TRACE_ERROR(GetRegValueNameError)
  3845. }
  3846. //+-------------------------------------------------------------------------
  3847. // Serialize the encoded CRL and its properties and write to
  3848. // the registry.
  3849. //
  3850. // Called before the CRL is written to the store.
  3851. //--------------------------------------------------------------------------
  3852. STATIC BOOL WINAPI RegStoreProvWriteCrl(
  3853. IN HCERTSTOREPROV hStoreProv,
  3854. IN PCCRL_CONTEXT pCrlContext,
  3855. IN DWORD dwFlags
  3856. )
  3857. {
  3858. BOOL fResult;
  3859. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  3860. WCHAR wsz[MAX_CERT_REG_VALUE_NAME_LEN];
  3861. BYTE *pbElement = NULL;
  3862. DWORD cbElement;
  3863. assert(pRegStore);
  3864. if (IsInResync(pRegStore))
  3865. // Only update the store cache, don't write back to registry
  3866. return TRUE;
  3867. if (pRegStore->dwFlags & CERT_STORE_READONLY_FLAG)
  3868. goto AccessDenied;
  3869. if (IsWriteSerializedRegistry(pRegStore))
  3870. return TRUE;
  3871. if (!GetCrlRegValueName(pCrlContext, wsz))
  3872. goto GetRegValueNameError;
  3873. // get the size
  3874. if (!CertSerializeCRLStoreElement(pCrlContext, 0, NULL, &cbElement))
  3875. goto SerializeStoreElementError;
  3876. if (NULL == (pbElement = (BYTE *) PkiNonzeroAlloc(cbElement)))
  3877. goto OutOfMemory;
  3878. // put it into the buffer
  3879. if (!CertSerializeCRLStoreElement(pCrlContext, 0, pbElement, &cbElement))
  3880. goto SerializeStoreElementError;
  3881. // write it to the registry or roaming file
  3882. fResult = WriteSerializedContext(
  3883. pRegStore,
  3884. CERT_STORE_CRL_CONTEXT - 1,
  3885. wsz,
  3886. pbElement,
  3887. cbElement
  3888. );
  3889. CommonReturn:
  3890. PkiFree(pbElement);
  3891. return fResult;
  3892. ErrorReturn:
  3893. fResult = FALSE;
  3894. goto CommonReturn;
  3895. SET_ERROR(AccessDenied, E_ACCESSDENIED)
  3896. TRACE_ERROR(GetRegValueNameError)
  3897. TRACE_ERROR(OutOfMemory)
  3898. TRACE_ERROR(SerializeStoreElementError)
  3899. }
  3900. //+-------------------------------------------------------------------------
  3901. // Delete the specified CRL from the registry.
  3902. //
  3903. // Called before the CRL is deleted from the store.
  3904. //+-------------------------------------------------------------------------
  3905. STATIC BOOL WINAPI RegStoreProvDeleteCrl(
  3906. IN HCERTSTOREPROV hStoreProv,
  3907. IN PCCRL_CONTEXT pCrlContext,
  3908. IN DWORD dwFlags
  3909. )
  3910. {
  3911. BOOL fResult;
  3912. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  3913. WCHAR wsz[MAX_CERT_REG_VALUE_NAME_LEN];
  3914. assert(pRegStore);
  3915. if (IsInResync(pRegStore))
  3916. // Only delete from store cache, not from registry
  3917. return TRUE;
  3918. if (pRegStore->dwFlags & CERT_STORE_READONLY_FLAG)
  3919. goto AccessDenied;
  3920. if (IsWriteSerializedRegistry(pRegStore))
  3921. return TRUE;
  3922. if (!GetCrlRegValueName(pCrlContext, wsz))
  3923. goto GetRegValueNameError;
  3924. // delete this CRL
  3925. fResult = DeleteContext(
  3926. pRegStore,
  3927. CERT_STORE_CRL_CONTEXT - 1,
  3928. wsz
  3929. );
  3930. CommonReturn:
  3931. return fResult;
  3932. ErrorReturn:
  3933. fResult = FALSE;
  3934. goto CommonReturn;
  3935. SET_ERROR(AccessDenied, E_ACCESSDENIED)
  3936. TRACE_ERROR(GetRegValueNameError)
  3937. }
  3938. //+-------------------------------------------------------------------------
  3939. // Read the specified CRL from the registry and update its
  3940. // property.
  3941. //
  3942. // Note, ignore the CERT_SHA1_HASH_PROP_ID property which is implicitly
  3943. // set before we write the CRL to the registry. If we don't ignore,
  3944. // we will have indefinite recursion.
  3945. //
  3946. // Called before setting the property of the CRL in the store.
  3947. //--------------------------------------------------------------------------
  3948. STATIC BOOL WINAPI RegStoreProvSetCrlProperty(
  3949. IN HCERTSTOREPROV hStoreProv,
  3950. IN PCCRL_CONTEXT pCrlContext,
  3951. IN DWORD dwPropId,
  3952. IN DWORD dwFlags,
  3953. IN const void *pvData
  3954. )
  3955. {
  3956. BOOL fResult;
  3957. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  3958. PCCRL_CONTEXT pProvCrlContext = NULL;
  3959. // This property is implicitly written whenever we do a CertWrite.
  3960. if (CERT_SHA1_HASH_PROP_ID == dwPropId)
  3961. return TRUE;
  3962. assert(pRegStore);
  3963. if (IsInResync(pRegStore))
  3964. // Only update the store cache, don't write back to registry
  3965. return TRUE;
  3966. if (pRegStore->dwFlags & CERT_STORE_READONLY_FLAG)
  3967. goto AccessDenied;
  3968. if (IsWriteSerializedRegistry(pRegStore))
  3969. return TRUE;
  3970. // Create a certificate context from the current serialized value stored
  3971. // in the registry.
  3972. if (!RegStoreProvReadCrl(
  3973. hStoreProv,
  3974. pCrlContext,
  3975. 0, // dwFlags
  3976. &pProvCrlContext)) goto ReadError;
  3977. // Set the property in the above created certificate context.
  3978. if (!CertSetCRLContextProperty(
  3979. pProvCrlContext,
  3980. dwPropId,
  3981. dwFlags,
  3982. pvData)) goto SetPropertyError;
  3983. // Serialize and write the above updated certificate back to the
  3984. // registry.
  3985. if (!RegStoreProvWriteCrl(
  3986. hStoreProv,
  3987. pProvCrlContext,
  3988. 0)) //dwFlags
  3989. goto WriteError;
  3990. fResult = TRUE;
  3991. CommonReturn:
  3992. CertFreeCRLContext(pProvCrlContext);
  3993. return fResult;
  3994. ErrorReturn:
  3995. fResult = FALSE;
  3996. goto CommonReturn;
  3997. SET_ERROR(AccessDenied, E_ACCESSDENIED)
  3998. TRACE_ERROR(ReadError)
  3999. TRACE_ERROR(SetPropertyError)
  4000. TRACE_ERROR(WriteError)
  4001. }
  4002. //+-------------------------------------------------------------------------
  4003. // Read the serialized copy of the CTL and its properties from
  4004. // the registry and create a new CTL context.
  4005. //--------------------------------------------------------------------------
  4006. STATIC BOOL WINAPI RegStoreProvReadCtl(
  4007. IN HCERTSTOREPROV hStoreProv,
  4008. IN PCCTL_CONTEXT pStoreCtlContext,
  4009. IN DWORD dwFlags,
  4010. OUT PCCTL_CONTEXT *ppProvCtlContext
  4011. )
  4012. {
  4013. BOOL fResult;
  4014. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  4015. WCHAR wsz[MAX_CERT_REG_VALUE_NAME_LEN];
  4016. assert(pRegStore);
  4017. if (IsReadSerializedRegistry(pRegStore))
  4018. goto UnexpectedReadError;
  4019. if (!GetCtlRegValueName(pStoreCtlContext, wsz))
  4020. goto GetRegValueNameError;
  4021. fResult = ReadContext(
  4022. pRegStore,
  4023. CERT_STORE_CTL_CONTEXT - 1,
  4024. wsz,
  4025. (const void **) ppProvCtlContext
  4026. );
  4027. CommonReturn:
  4028. return fResult;
  4029. ErrorReturn:
  4030. fResult = FALSE;
  4031. *ppProvCtlContext = NULL;
  4032. goto CommonReturn;
  4033. SET_ERROR(UnexpectedReadError, E_UNEXPECTED)
  4034. TRACE_ERROR(GetRegValueNameError)
  4035. }
  4036. //+-------------------------------------------------------------------------
  4037. // Serialize the encoded CTL and its properties and write to
  4038. // the registry.
  4039. //
  4040. // Called before the CTL is written to the store.
  4041. //--------------------------------------------------------------------------
  4042. STATIC BOOL WINAPI RegStoreProvWriteCtl(
  4043. IN HCERTSTOREPROV hStoreProv,
  4044. IN PCCTL_CONTEXT pCtlContext,
  4045. IN DWORD dwFlags
  4046. )
  4047. {
  4048. BOOL fResult;
  4049. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  4050. WCHAR wsz[MAX_CERT_REG_VALUE_NAME_LEN];
  4051. BYTE *pbElement = NULL;
  4052. DWORD cbElement;
  4053. assert(pRegStore);
  4054. if (IsInResync(pRegStore))
  4055. // Only update the store cache, don't write back to registry
  4056. return TRUE;
  4057. if (pRegStore->dwFlags & CERT_STORE_READONLY_FLAG)
  4058. goto AccessDenied;
  4059. if (IsWriteSerializedRegistry(pRegStore))
  4060. return TRUE;
  4061. if (!GetCtlRegValueName(pCtlContext, wsz))
  4062. goto GetRegValueNameError;
  4063. // get the size
  4064. if (!CertSerializeCTLStoreElement(pCtlContext, 0, NULL, &cbElement))
  4065. goto SerializeStoreElementError;
  4066. if (NULL == (pbElement = (BYTE *) PkiNonzeroAlloc(cbElement)))
  4067. goto OutOfMemory;
  4068. // put it into the buffer
  4069. if (!CertSerializeCTLStoreElement(pCtlContext, 0, pbElement, &cbElement))
  4070. goto SerializeStoreElementError;
  4071. // write it to the registry or roaming file
  4072. fResult = WriteSerializedContext(
  4073. pRegStore,
  4074. CERT_STORE_CTL_CONTEXT - 1,
  4075. wsz,
  4076. pbElement,
  4077. cbElement
  4078. );
  4079. CommonReturn:
  4080. PkiFree(pbElement);
  4081. return fResult;
  4082. ErrorReturn:
  4083. fResult = FALSE;
  4084. goto CommonReturn;
  4085. SET_ERROR(AccessDenied, E_ACCESSDENIED)
  4086. TRACE_ERROR(GetRegValueNameError)
  4087. TRACE_ERROR(OutOfMemory)
  4088. TRACE_ERROR(SerializeStoreElementError)
  4089. }
  4090. //+-------------------------------------------------------------------------
  4091. // Delete the specified CTL from the registry.
  4092. //
  4093. // Called before the CTL is deleted from the store.
  4094. //+-------------------------------------------------------------------------
  4095. STATIC BOOL WINAPI RegStoreProvDeleteCtl(
  4096. IN HCERTSTOREPROV hStoreProv,
  4097. IN PCCTL_CONTEXT pCtlContext,
  4098. IN DWORD dwFlags
  4099. )
  4100. {
  4101. BOOL fResult;
  4102. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  4103. WCHAR wsz[MAX_CERT_REG_VALUE_NAME_LEN];
  4104. assert(pRegStore);
  4105. if (IsInResync(pRegStore))
  4106. // Only delete from store cache, not from registry
  4107. return TRUE;
  4108. if (pRegStore->dwFlags & CERT_STORE_READONLY_FLAG)
  4109. goto AccessDenied;
  4110. if (IsWriteSerializedRegistry(pRegStore))
  4111. return TRUE;
  4112. if (!GetCtlRegValueName(pCtlContext, wsz))
  4113. goto GetRegValueNameError;
  4114. // delete this CTL
  4115. fResult = DeleteContext(
  4116. pRegStore,
  4117. CERT_STORE_CTL_CONTEXT - 1,
  4118. wsz
  4119. );
  4120. CommonReturn:
  4121. return fResult;
  4122. ErrorReturn:
  4123. fResult = FALSE;
  4124. goto CommonReturn;
  4125. SET_ERROR(AccessDenied, E_ACCESSDENIED)
  4126. TRACE_ERROR(GetRegValueNameError)
  4127. }
  4128. //+-------------------------------------------------------------------------
  4129. // Read the specified CTL from the registry and update its
  4130. // property.
  4131. //
  4132. // Note, ignore the CERT_SHA1_HASH_PROP_ID property which is implicitly
  4133. // set before we write the CTL to the registry. If we don't ignore,
  4134. // we will have indefinite recursion.
  4135. //
  4136. // Called before setting the property of the CTL in the store.
  4137. //--------------------------------------------------------------------------
  4138. STATIC BOOL WINAPI RegStoreProvSetCtlProperty(
  4139. IN HCERTSTOREPROV hStoreProv,
  4140. IN PCCTL_CONTEXT pCtlContext,
  4141. IN DWORD dwPropId,
  4142. IN DWORD dwFlags,
  4143. IN const void *pvData
  4144. )
  4145. {
  4146. BOOL fResult;
  4147. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  4148. PCCTL_CONTEXT pProvCtlContext = NULL;
  4149. // This property is implicitly written whenever we do a CertWrite.
  4150. if (CERT_SHA1_HASH_PROP_ID == dwPropId)
  4151. return TRUE;
  4152. assert(pRegStore);
  4153. if (IsInResync(pRegStore))
  4154. // Only update the store cache, don't write back to registry
  4155. return TRUE;
  4156. if (pRegStore->dwFlags & CERT_STORE_READONLY_FLAG)
  4157. goto AccessDenied;
  4158. if (IsWriteSerializedRegistry(pRegStore))
  4159. return TRUE;
  4160. // Create a CTL context from the current serialized value stored
  4161. // in the registry.
  4162. if (!RegStoreProvReadCtl(
  4163. hStoreProv,
  4164. pCtlContext,
  4165. 0, // dwFlags
  4166. &pProvCtlContext)) goto ReadError;
  4167. // Set the property in the above created certificate context.
  4168. if (!CertSetCTLContextProperty(
  4169. pProvCtlContext,
  4170. dwPropId,
  4171. dwFlags,
  4172. pvData)) goto SetPropertyError;
  4173. // Serialize and write the above updated certificate back to the
  4174. // registry.
  4175. if (!RegStoreProvWriteCtl(
  4176. hStoreProv,
  4177. pProvCtlContext,
  4178. 0)) //dwFlags
  4179. goto WriteError;
  4180. fResult = TRUE;
  4181. CommonReturn:
  4182. CertFreeCTLContext(pProvCtlContext);
  4183. return fResult;
  4184. ErrorReturn:
  4185. fResult = FALSE;
  4186. goto CommonReturn;
  4187. SET_ERROR(AccessDenied, E_ACCESSDENIED)
  4188. TRACE_ERROR(ReadError)
  4189. TRACE_ERROR(SetPropertyError)
  4190. TRACE_ERROR(WriteError)
  4191. }
  4192. //+=========================================================================
  4193. // Control functions
  4194. //==========================================================================
  4195. STATIC BOOL RegNotifyChange(
  4196. IN PREG_STORE pRegStore,
  4197. IN HANDLE hEvent,
  4198. IN DWORD dwFlags
  4199. )
  4200. {
  4201. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_ROAMING_FLAG)
  4202. return RegRegistryStoreChange(pRegStore, hEvent, dwFlags);
  4203. else if (hWin95NotifyEvent)
  4204. return RegWin95StoreChange(pRegStore, hEvent, dwFlags);
  4205. else if (pRegStore->dwFlags & CERT_REGISTRY_STORE_CLIENT_GPT_FLAG)
  4206. return RegGptStoreChange(pRegStore, hEvent, dwFlags);
  4207. else
  4208. return RegRegistryStoreChange(pRegStore, hEvent, dwFlags);
  4209. }
  4210. STATIC BOOL ResyncFromRegistry(
  4211. IN PREG_STORE pRegStore,
  4212. IN OPTIONAL HANDLE hEvent,
  4213. IN DWORD dwFlags
  4214. )
  4215. {
  4216. BOOL fResult;
  4217. HCERTSTORE hNewStore = NULL;
  4218. HANDLE hMyNotifyChange;
  4219. // Serialize resyncs
  4220. LockRegStore(pRegStore);
  4221. if (hEvent) {
  4222. // Re-arm the specified event
  4223. if (!RegNotifyChange(pRegStore, hEvent, dwFlags))
  4224. goto NotifyChangeError;
  4225. }
  4226. hMyNotifyChange = pRegStore->hMyNotifyChange;
  4227. if (hMyNotifyChange) {
  4228. // Check if any changes since last resync
  4229. if (WAIT_TIMEOUT == WaitForSingleObjectEx(
  4230. hMyNotifyChange,
  4231. 0, // dwMilliseconds
  4232. FALSE // bAlertable
  4233. )) {
  4234. // No change
  4235. fResult = TRUE;
  4236. goto CommonReturn;
  4237. } else {
  4238. // Re-arm our event handle
  4239. if (!RegNotifyChange(pRegStore, hMyNotifyChange,
  4240. CERT_STORE_CTRL_INHIBIT_DUPLICATE_HANDLE_FLAG))
  4241. goto NotifyChangeError;
  4242. }
  4243. }
  4244. if (NULL == (hNewStore = CertOpenStore(
  4245. CERT_STORE_PROV_MEMORY,
  4246. 0, // dwEncodingType
  4247. 0, // hCryptProv
  4248. CERT_STORE_SHARE_CONTEXT_FLAG,
  4249. NULL // pvPara
  4250. )))
  4251. goto OpenMemoryStoreError;
  4252. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_CLIENT_GPT_FLAG) {
  4253. fResult = OpenAllFromGptRegistry(pRegStore, hNewStore);
  4254. pRegStore->fTouched = FALSE;
  4255. } else if (pRegStore->dwFlags & CERT_REGISTRY_STORE_SERIALIZED_FLAG) {
  4256. fResult = OpenAllFromSerializedRegistry(pRegStore, hNewStore);
  4257. pRegStore->fTouched = FALSE;
  4258. } else
  4259. fResult = OpenAllFromRegistry(pRegStore, hNewStore);
  4260. if (!fResult) {
  4261. if (ERROR_KEY_DELETED == GetLastError())
  4262. fResult = TRUE;
  4263. }
  4264. if (fResult) {
  4265. if (pRegStore->fProtected) {
  4266. BOOL fProtected;
  4267. // For the "Root" delete any roots that aren't in the protected root
  4268. // list.
  4269. if (!IPR_DeleteUnprotectedRootsFromStore(
  4270. hNewStore,
  4271. &fProtected
  4272. )) goto DeleteUnprotectedRootsError;
  4273. }
  4274. // Set fResync to inhibit the sync from writing back to the registry.
  4275. pRegStore->fResync = TRUE;
  4276. I_CertSyncStore(pRegStore->hCertStore, hNewStore);
  4277. pRegStore->fResync = FALSE;
  4278. }
  4279. CommonReturn:
  4280. UnlockRegStore(pRegStore);
  4281. if (hNewStore)
  4282. CertCloseStore(hNewStore, 0);
  4283. return fResult;
  4284. ErrorReturn:
  4285. fResult = FALSE;
  4286. goto CommonReturn;
  4287. TRACE_ERROR(NotifyChangeError)
  4288. TRACE_ERROR(OpenMemoryStoreError)
  4289. TRACE_ERROR(DeleteUnprotectedRootsError)
  4290. }
  4291. STATIC BOOL RegistryNotifyChange(
  4292. IN PREG_STORE pRegStore,
  4293. IN HANDLE hEvent,
  4294. IN DWORD dwFlags
  4295. )
  4296. {
  4297. BOOL fResult;
  4298. HANDLE hMyNotifyChange;
  4299. BOOL fFirstNotify;
  4300. LockRegStore(pRegStore);
  4301. hMyNotifyChange = pRegStore->hMyNotifyChange;
  4302. if (NULL == hMyNotifyChange) {
  4303. // Create "my" event and register it to be signaled for any changes
  4304. if (NULL == (hMyNotifyChange = CreateEvent(
  4305. NULL, // lpsa
  4306. FALSE, // fManualReset
  4307. FALSE, // fInitialState
  4308. NULL))) // lpszEventName
  4309. goto CreateEventError;
  4310. // For the first notification, want to ensure the store is in sync.
  4311. // Also does a RegNotifyChange
  4312. if (!ResyncFromRegistry(pRegStore, hMyNotifyChange,
  4313. CERT_STORE_CTRL_INHIBIT_DUPLICATE_HANDLE_FLAG)) {
  4314. DWORD dwErr = GetLastError();
  4315. // Bug 484023 Certificate store event handle closed before
  4316. // being removed from list.
  4317. RegNotifyChange(pRegStore, hMyNotifyChange,
  4318. REG_STORE_CTRL_CANCEL_NOTIFY_FLAG);
  4319. CloseHandle(hMyNotifyChange);
  4320. SetLastError(dwErr);
  4321. goto ResyncFromRegistryError;
  4322. }
  4323. // Note, must update after making the above Resync call to
  4324. // force the store to be resync'ed
  4325. pRegStore->hMyNotifyChange = hMyNotifyChange;
  4326. fFirstNotify = TRUE;
  4327. } else
  4328. fFirstNotify = FALSE;
  4329. if (hEvent) {
  4330. if (fFirstNotify ||
  4331. 0 != (dwFlags & REG_STORE_CTRL_CANCEL_NOTIFY_FLAG)) {
  4332. if (!RegNotifyChange(pRegStore, hEvent, dwFlags))
  4333. goto NotifyChangeError;
  4334. } else {
  4335. // For subsequent notification, want to ensure the store
  4336. // is in sync. Also does a RegNotifyChange.
  4337. if (!ResyncFromRegistry(pRegStore, hEvent, dwFlags))
  4338. goto ResyncFromRegistryError;
  4339. }
  4340. }
  4341. fResult = TRUE;
  4342. CommonReturn:
  4343. UnlockRegStore(pRegStore);
  4344. return fResult;
  4345. ErrorReturn:
  4346. fResult = FALSE;
  4347. goto CommonReturn;
  4348. TRACE_ERROR(CreateEventError)
  4349. TRACE_ERROR(ResyncFromRegistryError)
  4350. TRACE_ERROR(NotifyChangeError)
  4351. }
  4352. STATIC BOOL WINAPI RegStoreProvControl(
  4353. IN HCERTSTOREPROV hStoreProv,
  4354. IN DWORD dwFlags,
  4355. IN DWORD dwCtrlType,
  4356. IN void const *pvCtrlPara
  4357. )
  4358. {
  4359. BOOL fResult;
  4360. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  4361. switch (dwCtrlType) {
  4362. case CERT_STORE_CTRL_RESYNC:
  4363. {
  4364. HANDLE *phEvent = (HANDLE *) pvCtrlPara;
  4365. HANDLE hEvent = phEvent ? *phEvent : NULL;
  4366. fResult = ResyncFromRegistry(pRegStore, hEvent, dwFlags);
  4367. }
  4368. break;
  4369. case CERT_STORE_CTRL_NOTIFY_CHANGE:
  4370. {
  4371. HANDLE *phEvent = (HANDLE *) pvCtrlPara;
  4372. HANDLE hEvent = phEvent ? *phEvent : NULL;
  4373. fResult = RegistryNotifyChange(pRegStore, hEvent, dwFlags);
  4374. }
  4375. break;
  4376. case CERT_STORE_CTRL_COMMIT:
  4377. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_CLIENT_GPT_FLAG)
  4378. fResult = CommitAllToGptRegistry(pRegStore, dwFlags);
  4379. else if (pRegStore->dwFlags & CERT_REGISTRY_STORE_SERIALIZED_FLAG)
  4380. fResult = CommitAllToSerializedRegistry(pRegStore, dwFlags);
  4381. else
  4382. fResult = TRUE;
  4383. break;
  4384. case CERT_STORE_CTRL_CANCEL_NOTIFY:
  4385. {
  4386. HANDLE *phEvent = (HANDLE *) pvCtrlPara;
  4387. HANDLE hEvent = phEvent ? *phEvent : NULL;
  4388. if (hEvent)
  4389. fResult = RegistryNotifyChange(pRegStore, hEvent,
  4390. REG_STORE_CTRL_CANCEL_NOTIFY_FLAG);
  4391. else
  4392. fResult = TRUE;
  4393. }
  4394. break;
  4395. default:
  4396. goto NotSupported;
  4397. }
  4398. CommonReturn:
  4399. return fResult;
  4400. ErrorReturn:
  4401. fResult = FALSE;
  4402. goto CommonReturn;
  4403. SET_ERROR(NotSupported, ERROR_CALL_NOT_IMPLEMENTED)
  4404. }
  4405. //+=========================================================================
  4406. // System and physical store support functions
  4407. //==========================================================================
  4408. STATIC BOOL HasBackslash(
  4409. IN LPCWSTR pwsz
  4410. )
  4411. {
  4412. WCHAR wch;
  4413. if (NULL == pwsz)
  4414. return FALSE;
  4415. while (L'\0' != (wch = *pwsz++)) {
  4416. if (L'\\' == wch)
  4417. return TRUE;
  4418. }
  4419. return FALSE;
  4420. }
  4421. static inline LPCSTR GetSystemStoreLocationOID(
  4422. IN DWORD dwFlags
  4423. )
  4424. {
  4425. return (LPCSTR)(DWORD_PTR) ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) >>
  4426. CERT_SYSTEM_STORE_LOCATION_SHIFT);
  4427. }
  4428. static inline DWORD GetSystemStoreLocationID(
  4429. IN DWORD dwFlags
  4430. )
  4431. {
  4432. return ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) >>
  4433. CERT_SYSTEM_STORE_LOCATION_SHIFT);
  4434. }
  4435. static inline BOOL IsSystemStoreLocationInRegistry(
  4436. IN DWORD dwFlags
  4437. )
  4438. {
  4439. DWORD dwID = GetSystemStoreLocationID(dwFlags);
  4440. return (dwID < NUM_SYSTEM_STORE_LOCATION &&
  4441. 0 == (rgSystemStoreLocationInfo[dwID].dwFlags &
  4442. NOT_IN_REGISTRY_SYSTEM_STORE_LOCATION_FLAG));
  4443. }
  4444. static inline BOOL IsRemotableSystemStoreLocationInRegistry(
  4445. IN DWORD dwFlags
  4446. )
  4447. {
  4448. DWORD dwID = GetSystemStoreLocationID(dwFlags);
  4449. return (dwID < NUM_SYSTEM_STORE_LOCATION &&
  4450. 0 != (rgSystemStoreLocationInfo[dwID].dwFlags &
  4451. REMOTABLE_SYSTEM_STORE_LOCATION_FLAG));
  4452. }
  4453. static inline BOOL IsLMSystemStoreLocationInRegistry(
  4454. IN DWORD dwFlags
  4455. )
  4456. {
  4457. DWORD dwID = GetSystemStoreLocationID(dwFlags);
  4458. return (dwID < NUM_SYSTEM_STORE_LOCATION &&
  4459. 0 != (rgSystemStoreLocationInfo[dwID].dwFlags &
  4460. LM_SYSTEM_STORE_LOCATION_FLAG));
  4461. }
  4462. static inline BOOL IsSerializedSystemStoreLocationInRegistry(
  4463. IN DWORD dwFlags
  4464. )
  4465. {
  4466. DWORD dwID = GetSystemStoreLocationID(dwFlags);
  4467. return (dwID < NUM_SYSTEM_STORE_LOCATION &&
  4468. 0 != (rgSystemStoreLocationInfo[dwID].dwFlags &
  4469. SERIALIZED_SYSTEM_STORE_LOCATION_FLAG));
  4470. }
  4471. STATIC BOOL IsPredefinedSystemStore(
  4472. IN LPCWSTR pwszSystemName,
  4473. IN DWORD dwFlags
  4474. )
  4475. {
  4476. DWORD i;
  4477. DWORD dwCheckFlag;
  4478. DWORD dwLocID;
  4479. DWORD dwPredefinedSystemFlags;
  4480. dwLocID = GetSystemStoreLocationID(dwFlags);
  4481. assert(NUM_SYSTEM_STORE_LOCATION > dwLocID);
  4482. dwPredefinedSystemFlags =
  4483. rgSystemStoreLocationInfo[dwLocID].dwPredefinedSystemFlags;
  4484. for (i = 0, dwCheckFlag = 1; i < NUM_PREDEFINED_SYSTEM_STORE;
  4485. i++, dwCheckFlag = dwCheckFlag << 1) {
  4486. if ((dwCheckFlag & dwPredefinedSystemFlags) &&
  4487. 0 == _wcsicmp(rgpwszPredefinedSystemStore[i], pwszSystemName))
  4488. return TRUE;
  4489. }
  4490. return FALSE;
  4491. }
  4492. #define UNICODE_SYSTEM_PROVIDER_FLAG 0x1
  4493. #define ASCII_SYSTEM_PROVIDER_FLAG 0x2
  4494. #define PHYSICAL_PROVIDER_FLAG 0x4
  4495. STATIC DWORD GetSystemProviderFlags(
  4496. IN LPCSTR pszStoreProvider
  4497. )
  4498. {
  4499. DWORD dwFlags;
  4500. if (0xFFFF < (DWORD_PTR) pszStoreProvider &&
  4501. CONST_OID_STR_PREFIX_CHAR == pszStoreProvider[0])
  4502. // Convert "#<number>" string to its corresponding constant OID value
  4503. pszStoreProvider = (LPCSTR)(DWORD_PTR) atol(pszStoreProvider + 1);
  4504. dwFlags = 0;
  4505. if (CERT_STORE_PROV_SYSTEM_A == pszStoreProvider)
  4506. dwFlags = ASCII_SYSTEM_PROVIDER_FLAG;
  4507. else if (CERT_STORE_PROV_SYSTEM_W == pszStoreProvider)
  4508. dwFlags = UNICODE_SYSTEM_PROVIDER_FLAG;
  4509. else if (CERT_STORE_PROV_SYSTEM_REGISTRY_A == pszStoreProvider)
  4510. dwFlags = ASCII_SYSTEM_PROVIDER_FLAG;
  4511. else if (CERT_STORE_PROV_SYSTEM_REGISTRY_W == pszStoreProvider)
  4512. dwFlags = UNICODE_SYSTEM_PROVIDER_FLAG;
  4513. else if (CERT_STORE_PROV_PHYSICAL_W == pszStoreProvider)
  4514. dwFlags = UNICODE_SYSTEM_PROVIDER_FLAG | PHYSICAL_PROVIDER_FLAG;
  4515. else if (0xFFFF < (DWORD_PTR) pszStoreProvider) {
  4516. if (0 == _stricmp(sz_CERT_STORE_PROV_SYSTEM_W, pszStoreProvider))
  4517. dwFlags = UNICODE_SYSTEM_PROVIDER_FLAG;
  4518. else if (0 == _stricmp(sz_CERT_STORE_PROV_SYSTEM_REGISTRY_W,
  4519. pszStoreProvider))
  4520. dwFlags = UNICODE_SYSTEM_PROVIDER_FLAG;
  4521. else if (0 == _stricmp(sz_CERT_STORE_PROV_PHYSICAL_W,
  4522. pszStoreProvider))
  4523. dwFlags = UNICODE_SYSTEM_PROVIDER_FLAG | PHYSICAL_PROVIDER_FLAG;
  4524. }
  4525. return dwFlags;
  4526. }
  4527. STATIC LPCSTR ChangeAsciiToUnicodeProvider(
  4528. IN LPCSTR pszStoreProvider
  4529. )
  4530. {
  4531. LPCSTR pszUnicodeProvider = NULL;
  4532. if (0xFFFF < (DWORD_PTR) pszStoreProvider &&
  4533. CONST_OID_STR_PREFIX_CHAR == pszStoreProvider[0])
  4534. // Convert "#<number>" string to its corresponding constant OID value
  4535. pszStoreProvider = (LPCSTR)(DWORD_PTR) atol(pszStoreProvider + 1);
  4536. if (CERT_STORE_PROV_SYSTEM_A == pszStoreProvider)
  4537. pszUnicodeProvider = CERT_STORE_PROV_SYSTEM_W;
  4538. else if (CERT_STORE_PROV_SYSTEM_REGISTRY_A == pszStoreProvider)
  4539. pszUnicodeProvider = CERT_STORE_PROV_SYSTEM_REGISTRY_W;
  4540. assert(pszUnicodeProvider);
  4541. return pszUnicodeProvider;
  4542. }
  4543. STATIC void FreeSystemNameInfo(
  4544. IN PSYSTEM_NAME_INFO pInfo
  4545. )
  4546. {
  4547. DWORD i;
  4548. for (i = 0; i < SYSTEM_NAME_PATH_COUNT; i++) {
  4549. if (pInfo->rgpwszName[i]) {
  4550. PkiFree(pInfo->rgpwszName[i]);
  4551. pInfo->rgpwszName[i] = NULL;
  4552. }
  4553. }
  4554. }
  4555. //+-------------------------------------------------------------------------
  4556. // If CERT_SYSTEM_STORE_RELOCATE_FLAG is set in dwFlags, then, treat the
  4557. // parameter as a pointer to a relocate data structure consisting of
  4558. // the relocate HKEY base and the pointer to the system name path.
  4559. // Otherwise, treat the parameter as a pointer to the system name path.
  4560. //
  4561. // Parses and validates the system name path according to the system store
  4562. // location and the number of required System and Physical name components.
  4563. // All name components are separated by the backslash, "\", character.
  4564. //
  4565. // Depending on the system store location and the number of required System
  4566. // and Physical name components, the system name path can have the following
  4567. // name components:
  4568. //
  4569. // CERT_SYSTEM_STORE_CURRENT_USER or
  4570. // CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY
  4571. // []
  4572. // SystemName
  4573. // SystemName\PhysicalName
  4574. // CERT_SYSTEM_STORE_LOCAL_MACHINE or
  4575. // CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY or
  4576. // CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE
  4577. // []
  4578. // [[\\]ComputerName]
  4579. // [[\\]ComputerName\]SystemName
  4580. // [[\\]ComputerName\]SystemName\PhysicalName
  4581. // CERT_SYSTEM_STORE_CURRENT_SERVICE
  4582. // []
  4583. // SystemName
  4584. // SystemName\PhysicalName
  4585. // CERT_SYSTEM_STORE_SERVICES
  4586. // []
  4587. // [\\ComputerName]
  4588. // [[\\]ComputerName\]
  4589. // [ServiceName]
  4590. // [[\\]ComputerName\ServiceName]
  4591. // [[\\]ComputerName\]ServiceName\SystemName
  4592. // [[\\]ComputerName\]ServiceName\SystemName\PhysicalName
  4593. // CERT_SYSTEM_STORE_USERS
  4594. // []
  4595. // [\\ComputerName]
  4596. // [[\\]ComputerName\]
  4597. // [UserName]
  4598. // [[\\]ComputerName\UserName]
  4599. // [[\\]ComputerName\]UserName\SystemName
  4600. // [[\\]ComputerName\]UserName\SystemName\PhysicalName
  4601. //
  4602. // For enumeration, where cReqName = 0, all store locations allow the no name
  4603. // components option. CERT_SYSTEM_STORE_CURRENT_USER,
  4604. // CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY,
  4605. // CERT_SYSTEM_CURRENT_SERVICE only allow the no name component option.
  4606. //
  4607. // The leading \\ before the ComputerName is optional.
  4608. //
  4609. // A PhysicalName always requires a preceding SystemName.
  4610. //
  4611. // For CERT_SYSTEM_STORE_SERVICES or CERT_SYSTEM_STORE_USERS,
  4612. // for enumeration, if only a single
  4613. // name component, then, interpretted as a ServiceName or UserName unless it
  4614. // contains a leading \\ or a trailing \, in which case its interpretted as a
  4615. // ComputerName. Otherwise, when not enumeration, the ServiceName or UserName
  4616. // is required.
  4617. //--------------------------------------------------------------------------
  4618. STATIC BOOL ParseSystemStorePara(
  4619. IN const void *pvPara,
  4620. IN DWORD dwFlags,
  4621. IN DWORD cReqName, // 0 for enum, 1 for OpenSystem, 2 for OpenPhysical
  4622. OUT PSYSTEM_NAME_INFO pInfo
  4623. )
  4624. {
  4625. LPCWSTR pwszPath; // not allocated
  4626. BOOL fResult;
  4627. DWORD cMaxOptName;
  4628. DWORD cMaxTotalName;
  4629. DWORD cOptName;
  4630. DWORD cTotalName;
  4631. BOOL fHasComputerNameBackslashes;
  4632. DWORD i;
  4633. LPCWSTR pwszEnd;
  4634. LPCWSTR pwsz;
  4635. LPCWSTR rgpwszStart[SYSTEM_NAME_PATH_COUNT];
  4636. DWORD cchName[SYSTEM_NAME_PATH_COUNT];
  4637. memset(pInfo, 0, sizeof(*pInfo));
  4638. if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) {
  4639. PCERT_SYSTEM_STORE_RELOCATE_PARA pRelocatePara =
  4640. (PCERT_SYSTEM_STORE_RELOCATE_PARA) pvPara;
  4641. if (NULL == pRelocatePara)
  4642. goto NullRelocateParaError;
  4643. if (NULL == pRelocatePara->hKeyBase)
  4644. goto NullRelocateHKEYError;
  4645. pInfo->hKeyBase = pRelocatePara->hKeyBase;
  4646. pwszPath = pRelocatePara->pwszSystemStore;
  4647. } else
  4648. pwszPath = (LPCWSTR) pvPara;
  4649. if (NULL == pwszPath || L'\0' == *pwszPath) {
  4650. if (0 == cReqName)
  4651. goto SuccessReturn;
  4652. else
  4653. goto MissingSystemName;
  4654. }
  4655. dwFlags &= CERT_SYSTEM_STORE_LOCATION_MASK;
  4656. switch (dwFlags) {
  4657. case CERT_SYSTEM_STORE_CURRENT_USER:
  4658. case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
  4659. case CERT_SYSTEM_STORE_CURRENT_SERVICE:
  4660. cMaxOptName = 0;
  4661. break;
  4662. case CERT_SYSTEM_STORE_LOCAL_MACHINE:
  4663. case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
  4664. case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
  4665. cMaxOptName = 1; // Allow ComputerName
  4666. break;
  4667. case CERT_SYSTEM_STORE_SERVICES:
  4668. case CERT_SYSTEM_STORE_USERS:
  4669. // Allow ComputerName and/or ServiceOrUserName
  4670. cMaxOptName = 2;
  4671. break;
  4672. default:
  4673. goto InvalidStoreLocation;
  4674. }
  4675. cMaxTotalName = cReqName + cMaxOptName;
  4676. assert(cReqName <= SERVICE_NAME_INDEX);
  4677. assert(cMaxTotalName <= SYSTEM_NAME_PATH_COUNT);
  4678. if (0 == cMaxTotalName)
  4679. goto MachineOrServiceNameNotAllowed;
  4680. if (L'\\' == pwszPath[0] && L'\\' == pwszPath[1]) {
  4681. pwszPath += 2;
  4682. fHasComputerNameBackslashes = TRUE;
  4683. } else
  4684. fHasComputerNameBackslashes = FALSE;
  4685. // Starting at the end, get up through cMaxTotalName strings separated
  4686. // by backslashes. Note, don't parse the left-most name component. This
  4687. // allows a ComputerName to contain embedded backslashes.
  4688. pwszEnd = pwszPath + wcslen(pwszPath);
  4689. pwsz = pwszEnd;
  4690. cTotalName = 0;
  4691. while (cTotalName < cMaxTotalName - 1) {
  4692. while (pwsz > pwszPath && L'\\' != *pwsz)
  4693. pwsz--;
  4694. if (L'\\' != *pwsz) {
  4695. // Left-most name component.
  4696. assert(pwsz == pwszPath);
  4697. break;
  4698. }
  4699. assert(L'\\' == *pwsz);
  4700. cchName[cTotalName] = (DWORD)(pwszEnd - pwsz) - 1; // exclude "\"
  4701. rgpwszStart[cTotalName] = pwsz + 1; // exclude "\"
  4702. cTotalName++;
  4703. pwszEnd = pwsz; // remember pointer to "\"
  4704. if (pwsz == pwszPath)
  4705. // Left-most name component is empty
  4706. break;
  4707. pwsz--; // skip before the "\"
  4708. }
  4709. // Left-most name component. Note, it may have embedded backslashes
  4710. cchName[cTotalName] = (DWORD)(pwszEnd - pwszPath);
  4711. rgpwszStart[cTotalName] = pwszPath;
  4712. cTotalName++;
  4713. if (cTotalName < cReqName)
  4714. goto MissingSystemOrPhysicalName;
  4715. // Allocate and copy the required name components
  4716. for (i = 0; i < cReqName; i++) {
  4717. if (0 == cchName[i])
  4718. goto EmptySystemOrPhysicalName;
  4719. if (NULL == (pInfo->rgpwszName[SERVICE_NAME_INDEX - cReqName + i] =
  4720. ILS_AllocAndCopyString(rgpwszStart[i], cchName[i])))
  4721. goto OutOfMemory;
  4722. }
  4723. cOptName = cTotalName - cReqName;
  4724. assert(cOptName || cReqName);
  4725. if (0 == cOptName) {
  4726. assert(cReqName);
  4727. // No ComputerName and/or ServiceName prefix
  4728. // Check if left-most name component (SystemName) has any backslashes
  4729. assert(pInfo->rgpwszName[SYSTEM_NAME_INDEX]);
  4730. if (fHasComputerNameBackslashes || HasBackslash(
  4731. pInfo->rgpwszName[SYSTEM_NAME_INDEX]))
  4732. goto InvalidBackslashInSystemName;
  4733. if (CERT_SYSTEM_STORE_SERVICES == dwFlags ||
  4734. CERT_SYSTEM_STORE_USERS == dwFlags)
  4735. // For non-enumeration, require the ServiceName
  4736. goto MissingServiceOrUserName;
  4737. } else {
  4738. if (CERT_SYSTEM_STORE_SERVICES == dwFlags ||
  4739. CERT_SYSTEM_STORE_USERS == dwFlags) {
  4740. // ServiceName or UserName prefix
  4741. if (0 == cchName[cReqName] ||
  4742. (1 == cOptName && fHasComputerNameBackslashes)) {
  4743. if (0 != cReqName)
  4744. goto MissingServiceOrUserName;
  4745. // else
  4746. // ComputerName only Enumeration with either:
  4747. // ComputerName\ <- trailing backslash
  4748. // \\ComputerName <- leading backslashes
  4749. // \\ComputerName\ <- both
  4750. } else {
  4751. if (NULL == (pInfo->rgpwszName[SERVICE_NAME_INDEX] =
  4752. ILS_AllocAndCopyString(rgpwszStart[cReqName],
  4753. cchName[cReqName])))
  4754. goto OutOfMemory;
  4755. }
  4756. }
  4757. if (CERT_SYSTEM_STORE_LOCAL_MACHINE == dwFlags ||
  4758. CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY == dwFlags ||
  4759. CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE == dwFlags ||
  4760. 2 == cOptName || fHasComputerNameBackslashes) {
  4761. // ComputerName prefix
  4762. DWORD cchComputer = cchName[cTotalName - 1];
  4763. if (0 == cchComputer)
  4764. goto EmptyComputerName;
  4765. if (pInfo->hKeyBase)
  4766. goto BothRemoteAndRelocateNotAllowed;
  4767. if (NULL == (pInfo->rgpwszName[COMPUTER_NAME_INDEX] =
  4768. (LPWSTR) PkiNonzeroAlloc(
  4769. (2 + cchComputer + 1) * sizeof(WCHAR))))
  4770. goto OutOfMemory;
  4771. wcscpy(pInfo->rgpwszName[COMPUTER_NAME_INDEX], L"\\\\");
  4772. memcpy((BYTE *) (pInfo->rgpwszName[COMPUTER_NAME_INDEX] + 2),
  4773. (BYTE *) rgpwszStart[cTotalName -1],
  4774. cchComputer * sizeof(WCHAR));
  4775. *(pInfo->rgpwszName[COMPUTER_NAME_INDEX] + 2 + cchComputer) = L'\0';
  4776. }
  4777. }
  4778. SuccessReturn:
  4779. fResult = TRUE;
  4780. CommonReturn:
  4781. return fResult;
  4782. ErrorReturn:
  4783. FreeSystemNameInfo(pInfo);
  4784. fResult = FALSE;
  4785. goto CommonReturn;
  4786. SET_ERROR(MissingSystemName, E_INVALIDARG)
  4787. SET_ERROR(NullRelocateParaError, E_INVALIDARG)
  4788. SET_ERROR(NullRelocateHKEYError, E_INVALIDARG)
  4789. SET_ERROR(MissingSystemOrPhysicalName, E_INVALIDARG)
  4790. SET_ERROR(InvalidStoreLocation, E_INVALIDARG)
  4791. SET_ERROR(MachineOrServiceNameNotAllowed, E_INVALIDARG)
  4792. SET_ERROR(EmptySystemOrPhysicalName, E_INVALIDARG)
  4793. SET_ERROR(InvalidBackslashInSystemName, E_INVALIDARG)
  4794. SET_ERROR(MissingServiceOrUserName, E_INVALIDARG)
  4795. SET_ERROR(EmptyComputerName, E_INVALIDARG)
  4796. SET_ERROR(BothRemoteAndRelocateNotAllowed, E_INVALIDARG)
  4797. TRACE_ERROR(OutOfMemory)
  4798. }
  4799. typedef struct _SYSTEM_NAME_GROUP {
  4800. DWORD cName;
  4801. LPCWSTR *rgpwszName;
  4802. } SYSTEM_NAME_GROUP, *PSYSTEM_NAME_GROUP;
  4803. //+-------------------------------------------------------------------------
  4804. // Formats a System Name Path by concatenating together the name components
  4805. // with an intervening "\" separator.
  4806. //--------------------------------------------------------------------------
  4807. STATIC LPWSTR FormatSystemNamePath(
  4808. IN DWORD cNameGroup,
  4809. IN SYSTEM_NAME_GROUP rgNameGroup[]
  4810. )
  4811. {
  4812. DWORD cchPath;
  4813. LPWSTR pwszPath;
  4814. BOOL fFirst;
  4815. DWORD iGroup;
  4816. // First, get total length of formatted path
  4817. cchPath = 0;
  4818. fFirst = TRUE;
  4819. for (iGroup = 0; iGroup < cNameGroup; iGroup++) {
  4820. DWORD iName;
  4821. for (iName = 0; iName < rgNameGroup[iGroup].cName; iName++) {
  4822. LPCWSTR pwszName = rgNameGroup[iGroup].rgpwszName[iName];
  4823. if (pwszName && *pwszName) {
  4824. if (fFirst)
  4825. fFirst = FALSE;
  4826. else
  4827. cchPath++; // "\" separator
  4828. cchPath += wcslen(pwszName);
  4829. }
  4830. }
  4831. }
  4832. cchPath++; // "\0" terminator
  4833. if (NULL == (pwszPath = (LPWSTR) PkiNonzeroAlloc(cchPath * sizeof(WCHAR))))
  4834. return NULL;
  4835. // Now do concatenated copies with intervening '\'
  4836. fFirst = TRUE;
  4837. for (iGroup = 0; iGroup < cNameGroup; iGroup++) {
  4838. DWORD iName;
  4839. for (iName = 0; iName < rgNameGroup[iGroup].cName; iName++) {
  4840. LPCWSTR pwszName = rgNameGroup[iGroup].rgpwszName[iName];
  4841. if (pwszName && *pwszName) {
  4842. if (fFirst) {
  4843. wcscpy(pwszPath, pwszName);
  4844. fFirst = FALSE;
  4845. } else {
  4846. wcscat(pwszPath, L"\\");
  4847. wcscat(pwszPath, pwszName);
  4848. }
  4849. }
  4850. }
  4851. }
  4852. if (fFirst)
  4853. // Empty string
  4854. *pwszPath = L'\0';
  4855. return pwszPath;
  4856. }
  4857. //+-------------------------------------------------------------------------
  4858. // If the SystemNameInfo has a non-NULL hKeyBase, then, the returned
  4859. // pvPara is a pointer to a CERT_SYSTEM_STORE_RELOCATE_PARA containing both
  4860. // the hKeyBase and the formatted system name path. Otherwise, returns
  4861. // pointer to only the formatted system name path.
  4862. //
  4863. // Calls the above FormatSystemNamePath() to do the actual formatting.
  4864. //--------------------------------------------------------------------------
  4865. STATIC void * FormatSystemNamePara(
  4866. IN DWORD cNameGroup,
  4867. IN SYSTEM_NAME_GROUP rgNameGroup[],
  4868. IN PSYSTEM_NAME_INFO pSystemNameInfo
  4869. )
  4870. {
  4871. if (NULL == pSystemNameInfo->hKeyBase)
  4872. return FormatSystemNamePath(cNameGroup, rgNameGroup);
  4873. else {
  4874. PCERT_SYSTEM_STORE_RELOCATE_PARA pRelocatePara;
  4875. if (NULL == (pRelocatePara =
  4876. (PCERT_SYSTEM_STORE_RELOCATE_PARA) PkiNonzeroAlloc(
  4877. sizeof(CERT_SYSTEM_STORE_RELOCATE_PARA))))
  4878. return NULL;
  4879. pRelocatePara->hKeyBase = pSystemNameInfo->hKeyBase;
  4880. if (NULL == (pRelocatePara->pwszSystemStore = FormatSystemNamePath(
  4881. cNameGroup, rgNameGroup))) {
  4882. PkiFree(pRelocatePara);
  4883. return NULL;
  4884. } else
  4885. return pRelocatePara;
  4886. }
  4887. }
  4888. STATIC void FreeSystemNamePara(
  4889. IN void *pvSystemNamePara,
  4890. IN PSYSTEM_NAME_INFO pSystemNameInfo
  4891. )
  4892. {
  4893. if (pvSystemNamePara) {
  4894. if (pSystemNameInfo->hKeyBase) {
  4895. PCERT_SYSTEM_STORE_RELOCATE_PARA pRelocatePara =
  4896. (PCERT_SYSTEM_STORE_RELOCATE_PARA) pvSystemNamePara;
  4897. PkiFree((LPWSTR) pRelocatePara->pwszSystemStore);
  4898. }
  4899. PkiFree(pvSystemNamePara);
  4900. }
  4901. }
  4902. //+-------------------------------------------------------------------------
  4903. // Localizes the physical, system and service name components. If unable
  4904. // to find a localized name string, uses the unlocalized name component.
  4905. //
  4906. // Re-formats the system name path with intervening backslashes and
  4907. // sets the store's CERT_STORE_LOCALIZED_NAME_PROP_ID property.
  4908. //--------------------------------------------------------------------------
  4909. STATIC void SetLocalizedNameStoreProperty(
  4910. IN HCERTSTORE hCertStore,
  4911. IN PSYSTEM_NAME_INFO pSystemNameInfo
  4912. )
  4913. {
  4914. LPWSTR pwszLocalizedPath = NULL;
  4915. LPCWSTR rgpwszLocalizedName[SYSTEM_NAME_PATH_COUNT];
  4916. SYSTEM_NAME_GROUP NameGroup;
  4917. CRYPT_DATA_BLOB Property;
  4918. DWORD i;
  4919. // Except for the computer name, try to get localized name components.
  4920. // If unable to find a localized name, use the original name component.
  4921. for (i = 0; i < SYSTEM_NAME_PATH_COUNT; i++) {
  4922. LPCWSTR pwszName;
  4923. LPCWSTR pwszLocalizedName;
  4924. pwszName = pSystemNameInfo->rgpwszName[i];
  4925. if (NULL == pwszName || COMPUTER_NAME_INDEX == i)
  4926. pwszLocalizedName = pwszName;
  4927. else {
  4928. // Returned pwszLocalizedName isn't allocated
  4929. if (NULL == (pwszLocalizedName = CryptFindLocalizedName(
  4930. pwszName)) || L'\0' == *pwszLocalizedName)
  4931. pwszLocalizedName = pwszName;
  4932. }
  4933. // Before formatting, need to reverse.
  4934. rgpwszLocalizedName[SYSTEM_NAME_PATH_COUNT - 1 - i] =
  4935. pwszLocalizedName;
  4936. }
  4937. NameGroup.cName = SYSTEM_NAME_PATH_COUNT;
  4938. NameGroup.rgpwszName = rgpwszLocalizedName;
  4939. if (NULL == (pwszLocalizedPath = FormatSystemNamePath(1, &NameGroup)))
  4940. goto FormatSystemNamePathError;
  4941. Property.pbData = (BYTE *) pwszLocalizedPath;
  4942. Property.cbData = (wcslen(pwszLocalizedPath) + 1) * sizeof(WCHAR);
  4943. if (!CertSetStoreProperty(
  4944. hCertStore,
  4945. CERT_STORE_LOCALIZED_NAME_PROP_ID,
  4946. 0, // dwFlags
  4947. (const void *) &Property
  4948. ))
  4949. goto SetStorePropertyError;
  4950. CommonReturn:
  4951. PkiFree(pwszLocalizedPath);
  4952. return;
  4953. ErrorReturn:
  4954. goto CommonReturn;
  4955. TRACE_ERROR(FormatSystemNamePathError)
  4956. TRACE_ERROR(SetStorePropertyError)
  4957. }
  4958. //+-------------------------------------------------------------------------
  4959. // For NT, get the formatted SID. For Win95, get the current user name.
  4960. //--------------------------------------------------------------------------
  4961. STATIC LPWSTR GetCurrentServiceOrUserName()
  4962. {
  4963. LPWSTR pwszCurrentService = NULL;
  4964. if (!FIsWinNT()) {
  4965. DWORD cch = _MAX_PATH;
  4966. if (NULL == (pwszCurrentService = (LPWSTR) PkiNonzeroAlloc(
  4967. (cch + 1) * sizeof(WCHAR))))
  4968. goto OutOfMemory;
  4969. if (!GetUserNameU(pwszCurrentService, &cch))
  4970. goto GetUserNameError;
  4971. } else {
  4972. DWORD cch = 256;
  4973. if (NULL == (pwszCurrentService = (LPWSTR) PkiNonzeroAlloc(
  4974. (cch + 1) * sizeof(WCHAR))))
  4975. goto OutOfMemory;
  4976. if (!GetUserTextualSidHKCU(pwszCurrentService, &cch)) {
  4977. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  4978. goto GetUserTextualSidHKUCError;
  4979. PkiFree(pwszCurrentService);
  4980. if (NULL == (pwszCurrentService = (LPWSTR) PkiNonzeroAlloc(
  4981. (cch + 1) * sizeof(WCHAR))))
  4982. goto OutOfMemory;
  4983. if (!GetUserTextualSidHKCU(pwszCurrentService, &cch))
  4984. goto GetUserTextualSidHKUCError;
  4985. }
  4986. }
  4987. CommonReturn:
  4988. return pwszCurrentService;
  4989. ErrorReturn:
  4990. if (pwszCurrentService)
  4991. wcscpy(pwszCurrentService, DEFAULT_USER_NAME);
  4992. goto CommonReturn;
  4993. TRACE_ERROR(OutOfMemory)
  4994. TRACE_ERROR(GetUserNameError)
  4995. TRACE_ERROR(GetUserTextualSidHKUCError)
  4996. }
  4997. //+-------------------------------------------------------------------------
  4998. // For NT and Win95, get the computer name
  4999. //--------------------------------------------------------------------------
  5000. STATIC LPWSTR GetCurrentComputerName()
  5001. {
  5002. LPWSTR pwszCurrentComputer = NULL;
  5003. DWORD cch = _MAX_PATH;
  5004. if (NULL == (pwszCurrentComputer = (LPWSTR) PkiNonzeroAlloc(
  5005. (cch + 1) * sizeof(WCHAR))))
  5006. goto OutOfMemory;
  5007. if (!GetComputerNameU(pwszCurrentComputer, &cch))
  5008. goto GetComputerNameError;
  5009. CommonReturn:
  5010. return pwszCurrentComputer;
  5011. ErrorReturn:
  5012. PkiFree(pwszCurrentComputer);
  5013. pwszCurrentComputer = NULL;
  5014. goto CommonReturn;
  5015. TRACE_ERROR(OutOfMemory)
  5016. TRACE_ERROR(GetComputerNameError)
  5017. }
  5018. //+-------------------------------------------------------------------------
  5019. // Uses the store location in the upper word of dwFlags, the parsed
  5020. // System Name components consisting of: computer, service/user, system and
  5021. // physical names, and the optional SubKey name to open the appropriate
  5022. // registry key. If the Computer name is non-NULL, does a RegConnectRegistry
  5023. // to connect a registry key on a remote computer. If the hKeyBase is
  5024. // non-NULL, does a relocated open instead of using HKCU or HKLM.
  5025. //--------------------------------------------------------------------------
  5026. STATIC LPWSTR FormatSystemRegPath(
  5027. IN PSYSTEM_NAME_INFO pInfo,
  5028. IN OPTIONAL LPCWSTR pwszSubKeyName,
  5029. IN DWORD dwFlags,
  5030. OUT HKEY *phKey
  5031. )
  5032. {
  5033. LONG err;
  5034. HKEY hKey = NULL;
  5035. LPWSTR pwszRegPath = NULL;
  5036. LPWSTR pwszCurrentService = NULL;
  5037. DWORD dwStoreLocation;
  5038. SYSTEM_NAME_GROUP rgNameGroup[3];
  5039. DWORD cNameGroup;
  5040. LPCWSTR rgpwszService[3];
  5041. LPCWSTR rgpwszUser[2];
  5042. LPCWSTR rgpwszStore[3];
  5043. if (pwszSubKeyName) {
  5044. cNameGroup = 3;
  5045. rgNameGroup[2].cName = 1;
  5046. rgNameGroup[2].rgpwszName = &pwszSubKeyName;
  5047. } else
  5048. cNameGroup = 2;
  5049. dwStoreLocation = dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK;
  5050. switch (dwStoreLocation) {
  5051. case CERT_SYSTEM_STORE_CURRENT_SERVICE:
  5052. case CERT_SYSTEM_STORE_SERVICES:
  5053. rgNameGroup[0].cName = 3;
  5054. rgNameGroup[0].rgpwszName = rgpwszService;
  5055. rgpwszService[0] = SERVICES_REGPATH;
  5056. rgpwszService[2] = SYSTEM_CERTIFICATES_SUBKEY_NAME;
  5057. if (CERT_SYSTEM_STORE_CURRENT_SERVICE == dwStoreLocation) {
  5058. assert(NULL == pInfo->rgpwszName[COMPUTER_NAME_INDEX]);
  5059. assert(NULL == pInfo->rgpwszName[SERVICE_NAME_INDEX]);
  5060. if (NULL == (pwszCurrentService =
  5061. GetCurrentServiceOrUserName()))
  5062. goto GetCurrentServiceNameError;
  5063. rgpwszService[1] = pwszCurrentService;
  5064. } else {
  5065. if (NULL == pInfo->rgpwszName[SERVICE_NAME_INDEX]) {
  5066. // May be NULL for CertEnumSystemStore
  5067. assert(NULL == pInfo->rgpwszName[SYSTEM_NAME_INDEX]);
  5068. assert(NULL == pInfo->rgpwszName[PHYSICAL_NAME_INDEX]);
  5069. rgNameGroup[0].cName = 1;
  5070. } else
  5071. rgpwszService[1] = pInfo->rgpwszName[SERVICE_NAME_INDEX];
  5072. }
  5073. break;
  5074. case CERT_SYSTEM_STORE_CURRENT_USER:
  5075. case CERT_SYSTEM_STORE_LOCAL_MACHINE:
  5076. rgpwszUser[0] = SYSTEM_STORE_REGPATH;
  5077. rgNameGroup[0].cName = 1;
  5078. rgNameGroup[0].rgpwszName = rgpwszUser;
  5079. break;
  5080. case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
  5081. case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
  5082. rgpwszUser[0] = GROUP_POLICY_STORE_REGPATH;
  5083. rgNameGroup[0].cName = 1;
  5084. rgNameGroup[0].rgpwszName = rgpwszUser;
  5085. break;
  5086. case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
  5087. rgpwszUser[0] = ENTERPRISE_STORE_REGPATH;
  5088. rgNameGroup[0].cName = 1;
  5089. rgNameGroup[0].rgpwszName = rgpwszUser;
  5090. break;
  5091. case CERT_SYSTEM_STORE_USERS:
  5092. if (NULL == pInfo->rgpwszName[USER_NAME_INDEX]) {
  5093. // May be NULL for CertEnumSystemStore
  5094. assert(NULL == pInfo->rgpwszName[SYSTEM_NAME_INDEX]);
  5095. assert(NULL == pInfo->rgpwszName[PHYSICAL_NAME_INDEX]);
  5096. rgNameGroup[0].cName = 0;
  5097. } else {
  5098. rgpwszUser[0] = pInfo->rgpwszName[USER_NAME_INDEX];
  5099. rgpwszUser[1] = SYSTEM_STORE_REGPATH;
  5100. rgNameGroup[0].cName = 2;
  5101. rgNameGroup[0].rgpwszName = rgpwszUser;
  5102. }
  5103. break;
  5104. default:
  5105. goto InvalidArg;
  5106. }
  5107. rgNameGroup[1].rgpwszName = rgpwszStore;
  5108. rgpwszStore[0] = pInfo->rgpwszName[SYSTEM_NAME_INDEX];
  5109. if (pInfo->rgpwszName[PHYSICAL_NAME_INDEX]) {
  5110. assert(pInfo->rgpwszName[SYSTEM_NAME_INDEX]);
  5111. rgNameGroup[1].cName = 3;
  5112. rgpwszStore[1] = PHYSICAL_STORES_SUBKEY_NAME;
  5113. rgpwszStore[2] = pInfo->rgpwszName[PHYSICAL_NAME_INDEX];
  5114. } else
  5115. rgNameGroup[1].cName = 1;
  5116. if (pInfo->rgpwszName[COMPUTER_NAME_INDEX]) {
  5117. assert(IsRemotableSystemStoreLocationInRegistry(dwFlags));
  5118. assert(NULL == pInfo->hKeyBase);
  5119. if (ERROR_SUCCESS != (err = RegConnectRegistryU(
  5120. pInfo->rgpwszName[COMPUTER_NAME_INDEX],
  5121. (CERT_SYSTEM_STORE_USERS == dwStoreLocation) ?
  5122. HKEY_USERS : HKEY_LOCAL_MACHINE,
  5123. &hKey)))
  5124. goto RegConnectRegistryError;
  5125. } else if (pInfo->hKeyBase) {
  5126. assert(dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG);
  5127. hKey = pInfo->hKeyBase;
  5128. } else {
  5129. switch (dwStoreLocation) {
  5130. case CERT_SYSTEM_STORE_CURRENT_USER:
  5131. case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
  5132. hKey = HKEY_CURRENT_USER;
  5133. break;
  5134. case CERT_SYSTEM_STORE_LOCAL_MACHINE:
  5135. case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
  5136. case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
  5137. case CERT_SYSTEM_STORE_CURRENT_SERVICE:
  5138. case CERT_SYSTEM_STORE_SERVICES:
  5139. hKey = HKEY_LOCAL_MACHINE;
  5140. break;
  5141. case CERT_SYSTEM_STORE_USERS:
  5142. hKey = HKEY_USERS;
  5143. break;
  5144. default:
  5145. goto InvalidArg;
  5146. }
  5147. }
  5148. if (NULL == (pwszRegPath = FormatSystemNamePath(
  5149. cNameGroup,
  5150. rgNameGroup
  5151. )))
  5152. goto FormatSystemNamePathError;
  5153. CommonReturn:
  5154. PkiFree(pwszCurrentService);
  5155. *phKey = hKey;
  5156. return pwszRegPath;
  5157. ErrorReturn:
  5158. pwszRegPath = NULL;
  5159. goto CommonReturn;
  5160. TRACE_ERROR(GetCurrentServiceNameError)
  5161. SET_ERROR(InvalidArg, E_INVALIDARG)
  5162. SET_ERROR_VAR(RegConnectRegistryError, err)
  5163. TRACE_ERROR(FormatSystemNamePathError)
  5164. }
  5165. STATIC HKEY OpenSystemRegPathKey(
  5166. IN PSYSTEM_NAME_INFO pInfo,
  5167. IN OPTIONAL LPCWSTR pwszSubKeyName,
  5168. IN DWORD dwFlags
  5169. )
  5170. {
  5171. LPWSTR pwszRegPath;
  5172. HKEY hKey = NULL;
  5173. HKEY hKeyRegPath;
  5174. if (NULL == (pwszRegPath = FormatSystemRegPath(
  5175. pInfo,
  5176. pwszSubKeyName,
  5177. dwFlags,
  5178. &hKey
  5179. )))
  5180. goto FormatSystemRegPathError;
  5181. hKeyRegPath = OpenSubKey(
  5182. hKey,
  5183. pwszRegPath,
  5184. dwFlags
  5185. );
  5186. CommonReturn:
  5187. PkiFree(pwszRegPath);
  5188. if (pInfo->rgpwszName[COMPUTER_NAME_INDEX] && hKey)
  5189. ILS_CloseRegistryKey(hKey);
  5190. return hKeyRegPath;
  5191. ErrorReturn:
  5192. hKeyRegPath = NULL;
  5193. goto CommonReturn;
  5194. TRACE_ERROR(FormatSystemRegPathError)
  5195. }
  5196. STATIC HKEY OpenSystemStore(
  5197. IN const void *pvPara,
  5198. IN DWORD dwFlags
  5199. )
  5200. {
  5201. HKEY hKey;
  5202. SYSTEM_NAME_INFO SystemNameInfo;
  5203. if (!ParseSystemStorePara(
  5204. pvPara,
  5205. dwFlags,
  5206. 1, // cReqName
  5207. &SystemNameInfo)) // zero'ed on error
  5208. goto ParseSystemStoreParaError;
  5209. hKey = OpenSystemRegPathKey(
  5210. &SystemNameInfo,
  5211. NULL, // pwszSubKeyName
  5212. dwFlags
  5213. );
  5214. CommonReturn:
  5215. FreeSystemNameInfo(&SystemNameInfo);
  5216. return hKey;
  5217. ErrorReturn:
  5218. hKey = NULL;
  5219. goto CommonReturn;
  5220. TRACE_ERROR(ParseSystemStoreParaError)
  5221. }
  5222. STATIC HKEY OpenPhysicalStores(
  5223. IN const void *pvPara,
  5224. IN DWORD dwFlags
  5225. )
  5226. {
  5227. HKEY hKey;
  5228. SYSTEM_NAME_INFO SystemNameInfo;
  5229. if (!ParseSystemStorePara(
  5230. pvPara,
  5231. dwFlags,
  5232. 1, // cReqName
  5233. &SystemNameInfo)) // zero'ed on error
  5234. goto ParseSystemStoreParaError;
  5235. hKey = OpenSystemRegPathKey(
  5236. &SystemNameInfo,
  5237. PHYSICAL_STORES_SUBKEY_NAME,
  5238. dwFlags
  5239. );
  5240. CommonReturn:
  5241. FreeSystemNameInfo(&SystemNameInfo);
  5242. return hKey;
  5243. ErrorReturn:
  5244. hKey = NULL;
  5245. goto CommonReturn;
  5246. TRACE_ERROR(ParseSystemStoreParaError)
  5247. }
  5248. //+-------------------------------------------------------------------------
  5249. // Register a system store.
  5250. //
  5251. // The upper word of the dwFlags parameter is used to specify the location of
  5252. // the system store.
  5253. //
  5254. // Set CERT_STORE_CREATE_NEW_FLAG to cause a failure if the system store
  5255. // already exists in the store location.
  5256. //--------------------------------------------------------------------------
  5257. BOOL
  5258. WINAPI
  5259. CertRegisterSystemStore(
  5260. IN const void *pvSystemStore,
  5261. IN DWORD dwFlags,
  5262. IN PCERT_SYSTEM_STORE_INFO pStoreInfo,
  5263. IN OPTIONAL void *pvReserved
  5264. )
  5265. {
  5266. BOOL fResult;
  5267. HKEY hKey;
  5268. if (!IsSystemStoreLocationInRegistry(dwFlags)) {
  5269. void *pvFuncAddr;
  5270. HCRYPTOIDFUNCADDR hFuncAddr;
  5271. if (!CryptGetOIDFunctionAddress(
  5272. rghFuncSet[REGISTER_SYSTEM_STORE_FUNC_SET],
  5273. 0, // dwEncodingType,
  5274. GetSystemStoreLocationOID(dwFlags),
  5275. 0, // dwFlags
  5276. &pvFuncAddr,
  5277. &hFuncAddr))
  5278. return FALSE;
  5279. fResult = ((PFN_REGISTER_SYSTEM_STORE) pvFuncAddr)(
  5280. pvSystemStore,
  5281. dwFlags,
  5282. pStoreInfo,
  5283. pvReserved
  5284. );
  5285. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  5286. return fResult;
  5287. }
  5288. if (dwFlags & ~REGISTER_FLAGS_MASK)
  5289. goto InvalidArg;
  5290. if (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG)
  5291. ILS_EnableBackupRestorePrivileges();
  5292. if (NULL == (hKey = OpenSystemStore(pvSystemStore, dwFlags)))
  5293. goto OpenSystemStoreError;
  5294. RegCloseKey(hKey);
  5295. fResult = TRUE;
  5296. CommonReturn:
  5297. return fResult;
  5298. ErrorReturn:
  5299. fResult = FALSE;
  5300. goto CommonReturn;
  5301. SET_ERROR(InvalidArg, E_INVALIDARG)
  5302. TRACE_ERROR(OpenSystemStoreError)
  5303. }
  5304. //+-------------------------------------------------------------------------
  5305. // Register a physical store for the specified system store.
  5306. //
  5307. // The upper word of the dwFlags parameter is used to specify the location of
  5308. // the system store.
  5309. //
  5310. // Set CERT_STORE_CREATE_NEW_FLAG to cause a failure if the physical store
  5311. // already exists in the system store.
  5312. //--------------------------------------------------------------------------
  5313. BOOL
  5314. WINAPI
  5315. CertRegisterPhysicalStore(
  5316. IN const void *pvSystemStore,
  5317. IN DWORD dwFlags,
  5318. IN LPCWSTR pwszStoreName,
  5319. IN PCERT_PHYSICAL_STORE_INFO pStoreInfo,
  5320. IN OPTIONAL void *pvReserved
  5321. )
  5322. {
  5323. BOOL fResult;
  5324. LONG err;
  5325. HKEY hKey = NULL;
  5326. SYSTEM_NAME_INFO SystemNameInfo;
  5327. char szOID[34];
  5328. LPCSTR pszOID;
  5329. if (!IsSystemStoreLocationInRegistry(dwFlags)) {
  5330. void *pvFuncAddr;
  5331. HCRYPTOIDFUNCADDR hFuncAddr;
  5332. if (!CryptGetOIDFunctionAddress(
  5333. rghFuncSet[REGISTER_PHYSICAL_STORE_FUNC_SET],
  5334. 0, // dwEncodingType,
  5335. GetSystemStoreLocationOID(dwFlags),
  5336. 0, // dwFlags
  5337. &pvFuncAddr,
  5338. &hFuncAddr))
  5339. return FALSE;
  5340. fResult = ((PFN_REGISTER_PHYSICAL_STORE) pvFuncAddr)(
  5341. pvSystemStore,
  5342. dwFlags,
  5343. pwszStoreName,
  5344. pStoreInfo,
  5345. pvReserved
  5346. );
  5347. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  5348. return fResult;
  5349. }
  5350. if (!ParseSystemStorePara(
  5351. pvSystemStore,
  5352. dwFlags,
  5353. 1, // cReqName
  5354. &SystemNameInfo)) // zero'ed on error
  5355. goto ParseSystemStoreParaError;
  5356. if (NULL == pwszStoreName || L'\0' == *pwszStoreName ||
  5357. HasBackslash(pwszStoreName))
  5358. goto InvalidArg;
  5359. assert(SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX]);
  5360. assert(NULL == SystemNameInfo.rgpwszName[PHYSICAL_NAME_INDEX]);
  5361. SystemNameInfo.rgpwszName[PHYSICAL_NAME_INDEX] = (LPWSTR) pwszStoreName;
  5362. if (dwFlags & ~REGISTER_FLAGS_MASK)
  5363. goto InvalidArg;
  5364. if (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG)
  5365. ILS_EnableBackupRestorePrivileges();
  5366. if (NULL == pStoreInfo ||
  5367. sizeof(CERT_PHYSICAL_STORE_INFO) > pStoreInfo->cbSize)
  5368. goto InvalidArg;
  5369. if (NULL == (hKey = OpenSystemRegPathKey(
  5370. &SystemNameInfo,
  5371. NULL, // pwszSubKeyName
  5372. dwFlags
  5373. )))
  5374. goto OpenSystemRegPathKeyError;
  5375. pszOID = pStoreInfo->pszOpenStoreProvider;
  5376. if (0xFFFF >= (DWORD_PTR) pszOID) {
  5377. // Convert to "#<number>" string
  5378. szOID[0] = CONST_OID_STR_PREFIX_CHAR;
  5379. _ltoa((long) ((DWORD_PTR) pszOID), szOID + 1, 10);
  5380. pszOID = szOID;
  5381. }
  5382. if (ERROR_SUCCESS != (err = RegSetValueExA(
  5383. hKey,
  5384. "OpenStoreProvider",
  5385. 0, // dwReserved
  5386. REG_SZ,
  5387. (BYTE *) pszOID,
  5388. strlen(pszOID) + 1)))
  5389. goto RegSetOpenStoreProviderError;
  5390. if (!WriteDWORDValueToRegistry(
  5391. hKey,
  5392. L"OpenEncodingType",
  5393. pStoreInfo->dwOpenEncodingType))
  5394. goto WriteDWORDError;
  5395. if (!WriteDWORDValueToRegistry(
  5396. hKey,
  5397. L"OpenFlags",
  5398. pStoreInfo->dwOpenFlags))
  5399. goto WriteDWORDError;
  5400. if (ERROR_SUCCESS != (err = RegSetValueExU(
  5401. hKey,
  5402. L"OpenParameters",
  5403. 0, // dwReserved
  5404. REG_BINARY,
  5405. pStoreInfo->OpenParameters.pbData,
  5406. pStoreInfo->OpenParameters.cbData)))
  5407. goto RegSetOpenParametersError;
  5408. if (!WriteDWORDValueToRegistry(
  5409. hKey,
  5410. L"Flags",
  5411. pStoreInfo->dwFlags))
  5412. goto WriteDWORDError;
  5413. if (!WriteDWORDValueToRegistry(
  5414. hKey,
  5415. L"Priority",
  5416. pStoreInfo->dwPriority))
  5417. goto WriteDWORDError;
  5418. fResult = TRUE;
  5419. CommonReturn:
  5420. SystemNameInfo.rgpwszName[PHYSICAL_NAME_INDEX] = NULL; // not allocated
  5421. FreeSystemNameInfo(&SystemNameInfo);
  5422. ILS_CloseRegistryKey(hKey);
  5423. return fResult;
  5424. ErrorReturn:
  5425. fResult = FALSE;
  5426. goto CommonReturn;
  5427. SET_ERROR(InvalidArg, E_INVALIDARG)
  5428. TRACE_ERROR(ParseSystemStoreParaError)
  5429. TRACE_ERROR(OpenSystemRegPathKeyError)
  5430. SET_ERROR_VAR(RegSetOpenStoreProviderError, err)
  5431. SET_ERROR_VAR(RegSetOpenParametersError, err)
  5432. TRACE_ERROR(WriteDWORDError)
  5433. }
  5434. //+-------------------------------------------------------------------------
  5435. // Unregister the specified system store.
  5436. //--------------------------------------------------------------------------
  5437. BOOL
  5438. WINAPI
  5439. CertUnregisterSystemStore(
  5440. IN const void *pvSystemStore,
  5441. IN DWORD dwFlags
  5442. )
  5443. {
  5444. BOOL fResult;
  5445. HKEY hKey = NULL;
  5446. SYSTEM_NAME_INFO SystemNameInfo;
  5447. LPWSTR pwszStore; // not allocated
  5448. if (!IsSystemStoreLocationInRegistry(dwFlags)) {
  5449. void *pvFuncAddr;
  5450. HCRYPTOIDFUNCADDR hFuncAddr;
  5451. if (!CryptGetOIDFunctionAddress(
  5452. rghFuncSet[UNREGISTER_SYSTEM_STORE_FUNC_SET],
  5453. 0, // dwEncodingType,
  5454. GetSystemStoreLocationOID(dwFlags),
  5455. 0, // dwFlags
  5456. &pvFuncAddr,
  5457. &hFuncAddr))
  5458. return FALSE;
  5459. fResult = ((PFN_UNREGISTER_SYSTEM_STORE) pvFuncAddr)(
  5460. pvSystemStore,
  5461. dwFlags
  5462. );
  5463. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  5464. return fResult;
  5465. }
  5466. if (!ParseSystemStorePara(
  5467. pvSystemStore,
  5468. dwFlags,
  5469. 1, // cReqName
  5470. &SystemNameInfo)) // zero'ed on error
  5471. goto ParseSystemStoreParaError;
  5472. if (dwFlags & ~UNREGISTER_FLAGS_MASK)
  5473. goto InvalidArg;
  5474. if (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG)
  5475. ILS_EnableBackupRestorePrivileges();
  5476. // Delete the SystemRegistry components
  5477. if (NULL == (hKey = OpenSystemRegPathKey(
  5478. &SystemNameInfo,
  5479. NULL, // pwszSubKeyName
  5480. dwFlags | CERT_STORE_OPEN_EXISTING_FLAG
  5481. )))
  5482. goto OpenSystemRegPathKeyError;
  5483. if (!DeleteAllFromRegistry(
  5484. hKey,
  5485. (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG) |
  5486. (SystemNameInfo.rgpwszName[COMPUTER_NAME_INDEX] ?
  5487. CERT_REGISTRY_STORE_REMOTE_FLAG : 0)
  5488. ))
  5489. goto DeleteAllError;
  5490. RegCloseKey(hKey);
  5491. hKey = NULL;
  5492. // Open SystemCertificates SubKey preceding the store. In order to do this
  5493. // the SYSTEM_NAME component must be NULL.
  5494. assert(SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX]);
  5495. pwszStore = SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX];
  5496. SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX] = NULL;
  5497. hKey = OpenSystemRegPathKey(
  5498. &SystemNameInfo,
  5499. NULL, // pwszSubKeyName
  5500. dwFlags | CERT_STORE_OPEN_EXISTING_FLAG
  5501. );
  5502. SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX] = pwszStore;
  5503. if (NULL == hKey)
  5504. goto OpenSystemRegPathKeyError;
  5505. // Delete the remaining System components (such as PhysicalStores) and
  5506. // the System store itself
  5507. if (!RecursiveDeleteSubKey(hKey, pwszStore, dwFlags))
  5508. goto DeleteSubKeyError;
  5509. fResult = TRUE;
  5510. CommonReturn:
  5511. FreeSystemNameInfo(&SystemNameInfo);
  5512. ILS_CloseRegistryKey(hKey);
  5513. return fResult;
  5514. ErrorReturn:
  5515. fResult = FALSE;
  5516. goto CommonReturn;
  5517. TRACE_ERROR(ParseSystemStoreParaError)
  5518. SET_ERROR(InvalidArg, E_INVALIDARG)
  5519. TRACE_ERROR(DeleteAllError)
  5520. TRACE_ERROR(OpenSystemRegPathKeyError)
  5521. TRACE_ERROR(DeleteSubKeyError)
  5522. }
  5523. //+-------------------------------------------------------------------------
  5524. // Unregister the physical store from the specified system store.
  5525. //--------------------------------------------------------------------------
  5526. BOOL
  5527. WINAPI
  5528. CertUnregisterPhysicalStore(
  5529. IN const void *pvSystemStore,
  5530. IN DWORD dwFlags,
  5531. IN LPCWSTR pwszStoreName
  5532. )
  5533. {
  5534. BOOL fResult;
  5535. HKEY hKey = NULL;
  5536. if (!IsSystemStoreLocationInRegistry(dwFlags)) {
  5537. void *pvFuncAddr;
  5538. HCRYPTOIDFUNCADDR hFuncAddr;
  5539. if (!CryptGetOIDFunctionAddress(
  5540. rghFuncSet[UNREGISTER_PHYSICAL_STORE_FUNC_SET],
  5541. 0, // dwEncodingType,
  5542. GetSystemStoreLocationOID(dwFlags),
  5543. 0, // dwFlags
  5544. &pvFuncAddr,
  5545. &hFuncAddr))
  5546. return FALSE;
  5547. fResult = ((PFN_UNREGISTER_PHYSICAL_STORE) pvFuncAddr)(
  5548. pvSystemStore,
  5549. dwFlags,
  5550. pwszStoreName
  5551. );
  5552. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  5553. return fResult;
  5554. }
  5555. if (dwFlags & ~UNREGISTER_FLAGS_MASK)
  5556. goto InvalidArg;
  5557. if (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG)
  5558. ILS_EnableBackupRestorePrivileges();
  5559. if (NULL == (hKey = OpenPhysicalStores(
  5560. pvSystemStore,
  5561. dwFlags | CERT_STORE_OPEN_EXISTING_FLAG
  5562. )))
  5563. goto OpenPhysicalStoresError;
  5564. if (!RecursiveDeleteSubKey(hKey, pwszStoreName, dwFlags))
  5565. goto DeleteSubKeyError;
  5566. fResult = TRUE;
  5567. CommonReturn:
  5568. ILS_CloseRegistryKey(hKey);
  5569. return fResult;
  5570. ErrorReturn:
  5571. fResult = FALSE;
  5572. goto CommonReturn;
  5573. SET_ERROR(InvalidArg, E_INVALIDARG)
  5574. TRACE_ERROR(OpenPhysicalStoresError)
  5575. TRACE_ERROR(DeleteSubKeyError)
  5576. }
  5577. typedef struct _ENUM_REGISTERED_SYSTEM_STORE_LOCATION_INFO {
  5578. DWORD dwLastError;
  5579. void *pvArg;
  5580. PFN_CERT_ENUM_SYSTEM_STORE_LOCATION pfnEnum;
  5581. } ENUM_REGISTERED_SYSTEM_STORE_LOCATION_INFO,
  5582. *PENUM_REGISTERED_SYSTEM_STORE_LOCATION_INFO;
  5583. STATIC BOOL WINAPI EnumRegisteredSystemStoreLocationCallback(
  5584. IN DWORD dwEncodingType,
  5585. IN LPCSTR pszFuncName,
  5586. IN LPCSTR pszOID,
  5587. IN DWORD cValue,
  5588. IN const DWORD rgdwValueType[],
  5589. IN LPCWSTR const rgpwszValueName[],
  5590. IN const BYTE * const rgpbValueData[],
  5591. IN const DWORD rgcbValueData[],
  5592. IN void *pvArg
  5593. )
  5594. {
  5595. PENUM_REGISTERED_SYSTEM_STORE_LOCATION_INFO pEnumRegisteredInfo =
  5596. (PENUM_REGISTERED_SYSTEM_STORE_LOCATION_INFO) pvArg;
  5597. LPCWSTR pwszLocation = L"";
  5598. DWORD dwFlags;
  5599. if (0 != pEnumRegisteredInfo->dwLastError)
  5600. return FALSE;
  5601. if (CONST_OID_STR_PREFIX_CHAR != *pszOID)
  5602. return TRUE;
  5603. dwFlags =
  5604. (((DWORD) atol(pszOID + 1)) << CERT_SYSTEM_STORE_LOCATION_SHIFT) &
  5605. CERT_SYSTEM_STORE_LOCATION_MASK;
  5606. if (0 == dwFlags)
  5607. return TRUE;
  5608. // Try to find the SystemStoreLocation value
  5609. while (cValue--) {
  5610. if (0 == _wcsicmp(rgpwszValueName[cValue],
  5611. CRYPT_OID_SYSTEM_STORE_LOCATION_VALUE_NAME) &&
  5612. REG_SZ == rgdwValueType[cValue]) {
  5613. pwszLocation = (LPCWSTR) rgpbValueData[cValue];
  5614. break;
  5615. }
  5616. }
  5617. if (!pEnumRegisteredInfo->pfnEnum(
  5618. pwszLocation,
  5619. dwFlags,
  5620. NULL, // pvReserved
  5621. pEnumRegisteredInfo->pvArg
  5622. )) {
  5623. if (0 == (pEnumRegisteredInfo->dwLastError = GetLastError()))
  5624. pEnumRegisteredInfo->dwLastError = (DWORD) E_UNEXPECTED;
  5625. return FALSE;
  5626. } else
  5627. return TRUE;
  5628. }
  5629. //+-------------------------------------------------------------------------
  5630. // Enumerate the system store locations.
  5631. //--------------------------------------------------------------------------
  5632. BOOL
  5633. WINAPI
  5634. CertEnumSystemStoreLocation(
  5635. IN DWORD dwFlags,
  5636. IN void *pvArg,
  5637. IN PFN_CERT_ENUM_SYSTEM_STORE_LOCATION pfnEnum
  5638. )
  5639. {
  5640. DWORD i;
  5641. ENUM_REGISTERED_SYSTEM_STORE_LOCATION_INFO EnumRegisteredInfo;
  5642. if (dwFlags & ~ENUM_FLAGS_MASK) {
  5643. SetLastError((DWORD) E_INVALIDARG);
  5644. return FALSE;
  5645. }
  5646. // Enumerate through the predefined, crypt32.dll system store locations
  5647. for (i = 0; i < ENUM_SYSTEM_STORE_LOCATION_CNT; i++) {
  5648. if (!pfnEnum(
  5649. rgEnumSystemStoreLocationInfo[i].pwszLocation,
  5650. rgEnumSystemStoreLocationInfo[i].dwFlags,
  5651. NULL, // pvReserved
  5652. pvArg
  5653. ))
  5654. return FALSE;
  5655. }
  5656. // Enumerate through the registered system store locations
  5657. EnumRegisteredInfo.dwLastError = 0;
  5658. EnumRegisteredInfo.pvArg = pvArg;
  5659. EnumRegisteredInfo.pfnEnum = pfnEnum;
  5660. CryptEnumOIDFunction(
  5661. 0, // dwEncodingType
  5662. CRYPT_OID_ENUM_SYSTEM_STORE_FUNC,
  5663. NULL, // pszOID
  5664. 0, // dwFlags
  5665. (void *) &EnumRegisteredInfo, // pvArg
  5666. EnumRegisteredSystemStoreLocationCallback
  5667. );
  5668. if (0 != EnumRegisteredInfo.dwLastError) {
  5669. SetLastError(EnumRegisteredInfo.dwLastError);
  5670. return FALSE;
  5671. } else
  5672. return TRUE;
  5673. }
  5674. STATIC BOOL EnumServicesOrUsersSystemStore(
  5675. IN OUT PSYSTEM_NAME_INFO pLocationNameInfo,
  5676. IN DWORD dwFlags,
  5677. IN void *pvArg,
  5678. IN PFN_CERT_ENUM_SYSTEM_STORE pfnEnum
  5679. )
  5680. {
  5681. BOOL fResult;
  5682. HKEY hKey = NULL;
  5683. DWORD cSubKeys;
  5684. DWORD cchMaxSubKey;
  5685. LPWSTR pwszEnumServiceName = NULL;
  5686. void *pvEnumServicePara = NULL;
  5687. BOOL fDidEnum;
  5688. assert(NULL == pLocationNameInfo->rgpwszName[SERVICE_NAME_INDEX]);
  5689. // Opens ..\Cryptography\Services SubKey or HKEY_USERS SubKey
  5690. if (NULL == (hKey = OpenSystemRegPathKey(
  5691. pLocationNameInfo,
  5692. NULL, // pwszSubKeyName
  5693. dwFlags | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG
  5694. )))
  5695. goto OpenSystemRegPathKeyError;
  5696. if (!GetSubKeyInfo(
  5697. hKey,
  5698. &cSubKeys,
  5699. &cchMaxSubKey
  5700. ))
  5701. goto GetSubKeyInfoError;
  5702. // Enumerates the ServiceOrUserNames
  5703. fDidEnum = FALSE;
  5704. if (cSubKeys && cchMaxSubKey) {
  5705. DWORD i;
  5706. LPCWSTR rgpwszEnumName[2];
  5707. SYSTEM_NAME_GROUP EnumNameGroup;
  5708. EnumNameGroup.cName = 2;
  5709. EnumNameGroup.rgpwszName = rgpwszEnumName;
  5710. cchMaxSubKey++;
  5711. if (NULL == (pwszEnumServiceName = (LPWSTR) PkiNonzeroAlloc(
  5712. cchMaxSubKey * sizeof(WCHAR))))
  5713. goto OutOfMemory;
  5714. rgpwszEnumName[0] = pLocationNameInfo->rgpwszName[COMPUTER_NAME_INDEX];
  5715. rgpwszEnumName[1] = pwszEnumServiceName;
  5716. for (i = 0; i < cSubKeys; i++) {
  5717. DWORD cchEnumServiceName = cchMaxSubKey;
  5718. LONG err;
  5719. if (ERROR_SUCCESS != (err = RegEnumKeyExU(
  5720. hKey,
  5721. i,
  5722. pwszEnumServiceName,
  5723. &cchEnumServiceName,
  5724. NULL, // lpdwReserved
  5725. NULL, // lpszClass
  5726. NULL, // lpcchClass
  5727. NULL // lpftLastWriteTime
  5728. )) || 0 == cchEnumServiceName ||
  5729. L'\0' == *pwszEnumServiceName) {
  5730. if (ERROR_NO_MORE_ITEMS == err)
  5731. break;
  5732. else
  5733. continue;
  5734. }
  5735. if (NULL == (pvEnumServicePara = FormatSystemNamePara(
  5736. 1, &EnumNameGroup, pLocationNameInfo)))
  5737. goto FormatSystemNameParaError;
  5738. if (!CertEnumSystemStore(
  5739. dwFlags,
  5740. pvEnumServicePara,
  5741. pvArg,
  5742. pfnEnum
  5743. )) {
  5744. if (ERROR_FILE_NOT_FOUND != GetLastError())
  5745. goto EnumSystemStoreError;
  5746. } else
  5747. fDidEnum = TRUE;
  5748. FreeSystemNamePara(pvEnumServicePara, pLocationNameInfo);
  5749. pvEnumServicePara = NULL;
  5750. }
  5751. }
  5752. if (!fDidEnum)
  5753. goto NoSystemStores;
  5754. fResult = TRUE;
  5755. CommonReturn:
  5756. ILS_CloseRegistryKey(hKey);
  5757. PkiFree(pwszEnumServiceName);
  5758. FreeSystemNamePara(pvEnumServicePara, pLocationNameInfo);
  5759. FreeSystemNameInfo(pLocationNameInfo);
  5760. return fResult;
  5761. ErrorReturn:
  5762. fResult = FALSE;
  5763. goto CommonReturn;
  5764. TRACE_ERROR(OpenSystemRegPathKeyError)
  5765. TRACE_ERROR(GetSubKeyInfoError)
  5766. TRACE_ERROR(OutOfMemory)
  5767. TRACE_ERROR(FormatSystemNameParaError)
  5768. TRACE_ERROR(EnumSystemStoreError)
  5769. SET_ERROR(NoSystemStores, ERROR_FILE_NOT_FOUND)
  5770. }
  5771. //+-------------------------------------------------------------------------
  5772. // Enumerate the system stores.
  5773. //
  5774. // The upper word of the dwFlags parameter is used to specify the location of
  5775. // the system store.
  5776. //
  5777. // All registry based system store locations have the predefined stores
  5778. // of: My, Root, Trust and CA.
  5779. //--------------------------------------------------------------------------
  5780. BOOL
  5781. WINAPI
  5782. CertEnumSystemStore(
  5783. IN DWORD dwFlags,
  5784. IN OPTIONAL void *pvSystemStoreLocationPara,
  5785. IN void *pvArg,
  5786. IN PFN_CERT_ENUM_SYSTEM_STORE pfnEnum
  5787. )
  5788. {
  5789. BOOL fResult;
  5790. HKEY hKey = NULL;
  5791. DWORD cSubKeys;
  5792. DWORD cchMaxSubKey = 0;
  5793. SYSTEM_NAME_INFO LocationNameInfo;
  5794. LPWSTR pwszEnumSystemStore = NULL;
  5795. void *pvEnumSystemPara = NULL;
  5796. DWORD i;
  5797. DWORD dwCheckFlag;
  5798. DWORD dwLocID;
  5799. DWORD dwPredefinedSystemFlags;
  5800. CERT_SYSTEM_STORE_INFO NullSystemStoreInfo;
  5801. LPCWSTR rgpwszEnumName[3];
  5802. SYSTEM_NAME_GROUP EnumNameGroup;
  5803. if (!IsSystemStoreLocationInRegistry(dwFlags)) {
  5804. void *pvFuncAddr;
  5805. HCRYPTOIDFUNCADDR hFuncAddr;
  5806. if (!CryptGetOIDFunctionAddress(
  5807. rghFuncSet[ENUM_SYSTEM_STORE_FUNC_SET],
  5808. 0, // dwEncodingType,
  5809. GetSystemStoreLocationOID(dwFlags),
  5810. 0, // dwFlags
  5811. &pvFuncAddr,
  5812. &hFuncAddr))
  5813. return FALSE;
  5814. fResult = ((PFN_ENUM_SYSTEM_STORE) pvFuncAddr)(
  5815. dwFlags,
  5816. pvSystemStoreLocationPara,
  5817. pvArg,
  5818. pfnEnum
  5819. );
  5820. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  5821. return fResult;
  5822. }
  5823. if (!ParseSystemStorePara(
  5824. pvSystemStoreLocationPara,
  5825. dwFlags,
  5826. 0, // cReqName, none for enumeration
  5827. &LocationNameInfo // zero'ed for error
  5828. ))
  5829. goto ParseSystemStoreParaError;
  5830. if (dwFlags & ~ENUM_FLAGS_MASK)
  5831. goto InvalidArg;
  5832. if (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG)
  5833. ILS_EnableBackupRestorePrivileges();
  5834. dwLocID = GetSystemStoreLocationID(dwFlags);
  5835. if ((CERT_SYSTEM_STORE_SERVICES_ID == dwLocID ||
  5836. CERT_SYSTEM_STORE_USERS_ID == dwLocID)
  5837. &&
  5838. NULL == LocationNameInfo.rgpwszName[SERVICE_NAME_INDEX])
  5839. // Following frees rgpwszLocationName entries
  5840. return EnumServicesOrUsersSystemStore(
  5841. &LocationNameInfo,
  5842. dwFlags,
  5843. pvArg,
  5844. pfnEnum
  5845. );
  5846. // Opens SystemCertificates subkey
  5847. if (NULL == (hKey = OpenSystemRegPathKey(
  5848. &LocationNameInfo,
  5849. NULL, // pwszSubKeyName
  5850. dwFlags | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG
  5851. ))) {
  5852. if (ERROR_FILE_NOT_FOUND != GetLastError())
  5853. goto OpenSystemRegPathKeyError;
  5854. // Note, a registry entry isn't needed for the predefined stores
  5855. cSubKeys = 0;
  5856. } else if (!GetSubKeyInfo(
  5857. hKey,
  5858. &cSubKeys,
  5859. &cchMaxSubKey
  5860. ))
  5861. goto GetSubKeyInfoError;
  5862. memset(&NullSystemStoreInfo, 0, sizeof(NullSystemStoreInfo));
  5863. NullSystemStoreInfo.cbSize = sizeof(NullSystemStoreInfo);
  5864. EnumNameGroup.cName = 3;
  5865. EnumNameGroup.rgpwszName = rgpwszEnumName;
  5866. rgpwszEnumName[0] = LocationNameInfo.rgpwszName[COMPUTER_NAME_INDEX];
  5867. rgpwszEnumName[1] = LocationNameInfo.rgpwszName[SERVICE_NAME_INDEX];
  5868. // Enumerate the predefined system stores.
  5869. assert(NUM_SYSTEM_STORE_LOCATION > dwLocID);
  5870. dwPredefinedSystemFlags =
  5871. rgSystemStoreLocationInfo[dwLocID].dwPredefinedSystemFlags;
  5872. for (i = 0, dwCheckFlag = 1; i < NUM_PREDEFINED_SYSTEM_STORE;
  5873. i++, dwCheckFlag = dwCheckFlag << 1) {
  5874. if (0 == (dwCheckFlag & dwPredefinedSystemFlags))
  5875. continue;
  5876. rgpwszEnumName[2] = rgpwszPredefinedSystemStore[i];
  5877. if (NULL == (pvEnumSystemPara = FormatSystemNamePara(
  5878. 1, &EnumNameGroup, &LocationNameInfo)))
  5879. goto FormatSystemNameParaError;
  5880. if (!pfnEnum(
  5881. pvEnumSystemPara,
  5882. dwFlags & CERT_SYSTEM_STORE_MASK,
  5883. &NullSystemStoreInfo,
  5884. NULL, // pvReserved
  5885. pvArg
  5886. ))
  5887. goto EnumCallbackError;
  5888. FreeSystemNamePara(pvEnumSystemPara, &LocationNameInfo);
  5889. pvEnumSystemPara = NULL;
  5890. }
  5891. // Enumerate the registered systems stores. Skip past any of the above
  5892. // predefined stores
  5893. if (cSubKeys && cchMaxSubKey) {
  5894. cchMaxSubKey++;
  5895. if (NULL == (pwszEnumSystemStore = (LPWSTR) PkiNonzeroAlloc(
  5896. cchMaxSubKey * sizeof(WCHAR))))
  5897. goto OutOfMemory;
  5898. rgpwszEnumName[2] = pwszEnumSystemStore;
  5899. for (i = 0; i < cSubKeys; i++) {
  5900. DWORD cchEnumSystemStore = cchMaxSubKey;
  5901. LONG err;
  5902. if (ERROR_SUCCESS != (err = RegEnumKeyExU(
  5903. hKey,
  5904. i,
  5905. pwszEnumSystemStore,
  5906. &cchEnumSystemStore,
  5907. NULL, // lpdwReserved
  5908. NULL, // lpszClass
  5909. NULL, // lpcchClass
  5910. NULL // lpftLastWriteTime
  5911. )) || 0 == cchEnumSystemStore) {
  5912. if (ERROR_NO_MORE_ITEMS == err)
  5913. break;
  5914. else
  5915. continue;
  5916. }
  5917. if (IsPredefinedSystemStore(pwszEnumSystemStore, dwFlags))
  5918. // Already enumerated above
  5919. continue;
  5920. if (NULL == (pvEnumSystemPara = FormatSystemNamePara(
  5921. 1, &EnumNameGroup, &LocationNameInfo)))
  5922. goto FormatSystemNameParaError;
  5923. if (!pfnEnum(
  5924. pvEnumSystemPara,
  5925. dwFlags & CERT_SYSTEM_STORE_MASK,
  5926. &NullSystemStoreInfo,
  5927. NULL, // pvReserved
  5928. pvArg
  5929. ))
  5930. goto EnumCallbackError;
  5931. FreeSystemNamePara(pvEnumSystemPara, &LocationNameInfo);
  5932. pvEnumSystemPara = NULL;
  5933. }
  5934. }
  5935. fResult = TRUE;
  5936. CommonReturn:
  5937. ILS_CloseRegistryKey(hKey);
  5938. PkiFree(pwszEnumSystemStore);
  5939. FreeSystemNamePara(pvEnumSystemPara, &LocationNameInfo);
  5940. FreeSystemNameInfo(&LocationNameInfo);
  5941. return fResult;
  5942. ErrorReturn:
  5943. fResult = FALSE;
  5944. goto CommonReturn;
  5945. TRACE_ERROR(ParseSystemStoreParaError)
  5946. SET_ERROR(InvalidArg, E_INVALIDARG)
  5947. TRACE_ERROR(OpenSystemRegPathKeyError)
  5948. TRACE_ERROR(GetSubKeyInfoError)
  5949. TRACE_ERROR(OutOfMemory)
  5950. TRACE_ERROR(FormatSystemNameParaError)
  5951. TRACE_ERROR(EnumCallbackError)
  5952. }
  5953. typedef struct _ENUM_PHYSICAL_STORE_INFO ENUM_PHYSICAL_STORE_INFO,
  5954. *PENUM_PHYSICAL_STORE_INFO;
  5955. struct _ENUM_PHYSICAL_STORE_INFO {
  5956. CERT_PHYSICAL_STORE_INFO RegistryInfo;
  5957. LPWSTR pwszStoreName;
  5958. PENUM_PHYSICAL_STORE_INFO pNext;
  5959. };
  5960. STATIC void FreeEnumPhysicalStoreInfo(
  5961. IN PENUM_PHYSICAL_STORE_INFO pStoreInfo
  5962. )
  5963. {
  5964. PCERT_PHYSICAL_STORE_INFO pRegistryInfo = &pStoreInfo->RegistryInfo;
  5965. PkiFree(pRegistryInfo->OpenParameters.pbData);
  5966. PkiFree(pRegistryInfo->pszOpenStoreProvider);
  5967. PkiFree(pStoreInfo->pwszStoreName);
  5968. PkiFree(pStoreInfo);
  5969. }
  5970. STATIC PENUM_PHYSICAL_STORE_INFO GetEnumPhysicalStoreInfo(
  5971. IN HKEY hKey,
  5972. IN LPCWSTR pwszStoreName,
  5973. IN DWORD dwFlags // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  5974. )
  5975. {
  5976. LONG err;
  5977. HKEY hSubKey = NULL;
  5978. PENUM_PHYSICAL_STORE_INFO pStoreInfo;
  5979. PCERT_PHYSICAL_STORE_INFO pRegistryInfo; // not allocated
  5980. if (NULL == (pStoreInfo = (PENUM_PHYSICAL_STORE_INFO) PkiZeroAlloc(
  5981. sizeof(ENUM_PHYSICAL_STORE_INFO))))
  5982. return NULL;
  5983. pRegistryInfo = &pStoreInfo->RegistryInfo;
  5984. pRegistryInfo->cbSize = sizeof(*pRegistryInfo);
  5985. if (NULL == (pStoreInfo->pwszStoreName =
  5986. ILS_AllocAndCopyString(pwszStoreName)))
  5987. goto OutOfMemory;
  5988. if (ERROR_SUCCESS != (err = OpenHKCUKeyExU(
  5989. hKey,
  5990. pwszStoreName,
  5991. dwFlags,
  5992. KEY_READ,
  5993. &hSubKey)))
  5994. goto OpenHKCUKeyError;
  5995. if (!ILS_ReadBINARYValueFromRegistry(
  5996. hSubKey,
  5997. L"OpenParameters",
  5998. &pRegistryInfo->OpenParameters.pbData,
  5999. &pRegistryInfo->OpenParameters.cbData
  6000. )) {
  6001. LPWSTR pwszParameters;
  6002. if (pwszParameters = ILS_ReadSZValueFromRegistry(
  6003. hSubKey,
  6004. L"OpenParameters"
  6005. )) {
  6006. pRegistryInfo->OpenParameters.pbData = (BYTE *) pwszParameters;
  6007. pRegistryInfo->OpenParameters.cbData =
  6008. (wcslen(pwszParameters) + 1) * sizeof(WCHAR);
  6009. } else {
  6010. // Default to empty string
  6011. if (NULL == (pRegistryInfo->OpenParameters.pbData =
  6012. (BYTE *) ILS_AllocAndCopyString(L"")))
  6013. goto OutOfMemory;
  6014. pRegistryInfo->OpenParameters.cbData = 0;
  6015. }
  6016. }
  6017. if (NULL == (pRegistryInfo->pszOpenStoreProvider = ILS_ReadSZValueFromRegistry(
  6018. hSubKey,
  6019. "OpenStoreProvider"
  6020. )))
  6021. goto NoOpenStoreProviderError;
  6022. ILS_ReadDWORDValueFromRegistry(
  6023. hSubKey,
  6024. L"OpenFlags",
  6025. &pRegistryInfo->dwOpenFlags
  6026. );
  6027. ILS_ReadDWORDValueFromRegistry(
  6028. hSubKey,
  6029. L"OpenEncodingType",
  6030. &pRegistryInfo->dwOpenEncodingType
  6031. );
  6032. ILS_ReadDWORDValueFromRegistry(
  6033. hSubKey,
  6034. L"Flags",
  6035. &pRegistryInfo->dwFlags
  6036. );
  6037. ILS_ReadDWORDValueFromRegistry(
  6038. hSubKey,
  6039. L"Priority",
  6040. &pRegistryInfo->dwPriority
  6041. );
  6042. CommonReturn:
  6043. ILS_CloseRegistryKey(hSubKey);
  6044. return pStoreInfo;
  6045. ErrorReturn:
  6046. FreeEnumPhysicalStoreInfo(pStoreInfo);
  6047. pStoreInfo = NULL;
  6048. goto CommonReturn;
  6049. TRACE_ERROR(OutOfMemory)
  6050. SET_ERROR_VAR(OpenHKCUKeyError, err)
  6051. TRACE_ERROR(NoOpenStoreProviderError)
  6052. }
  6053. STATIC BOOL IsSelfPhysicalStoreInfo(
  6054. IN PSYSTEM_NAME_INFO pSystemNameInfo,
  6055. IN DWORD dwFlags,
  6056. IN PCERT_PHYSICAL_STORE_INFO pStoreInfo,
  6057. OUT DWORD *pdwSystemProviderFlags
  6058. )
  6059. {
  6060. BOOL fResult;
  6061. DWORD dwSystemProviderFlags;
  6062. LPWSTR pwszStoreName = (LPWSTR) pStoreInfo->OpenParameters.pbData;
  6063. SYSTEM_NAME_INFO StoreNameInfo;
  6064. LPWSTR pwszCurrentServiceName = NULL;
  6065. LPWSTR pwszCurrentComputerName = NULL;
  6066. DWORD dwSystemLocation;
  6067. DWORD dwInfoLocation;
  6068. BOOL fSameLocation;
  6069. *pdwSystemProviderFlags = 0;
  6070. dwSystemLocation = dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK;
  6071. // Note, if the RELOCATE_FLAG is incorrectly set in the dwOpenFlags
  6072. // then, never match
  6073. dwInfoLocation = pStoreInfo->dwOpenFlags &
  6074. (CERT_SYSTEM_STORE_LOCATION_MASK | CERT_SYSTEM_STORE_RELOCATE_FLAG);
  6075. // Check if in same system store location
  6076. fSameLocation = (dwSystemLocation == dwInfoLocation);
  6077. if (!fSameLocation) {
  6078. if (CERT_SYSTEM_STORE_CURRENT_SERVICE == dwInfoLocation)
  6079. dwInfoLocation = CERT_SYSTEM_STORE_SERVICES;
  6080. if (CERT_SYSTEM_STORE_CURRENT_SERVICE == dwSystemLocation)
  6081. dwSystemLocation = CERT_SYSTEM_STORE_SERVICES;
  6082. if (CERT_SYSTEM_STORE_CURRENT_USER == dwInfoLocation)
  6083. dwInfoLocation = CERT_SYSTEM_STORE_USERS;
  6084. if (CERT_SYSTEM_STORE_CURRENT_USER == dwSystemLocation)
  6085. dwSystemLocation = CERT_SYSTEM_STORE_USERS;
  6086. if (dwSystemLocation != dwInfoLocation)
  6087. return FALSE;
  6088. }
  6089. // Check if SYSTEM or SYSTEM_REGISTRY store.
  6090. dwSystemProviderFlags = GetSystemProviderFlags(
  6091. pStoreInfo->pszOpenStoreProvider);
  6092. if (0 == dwSystemProviderFlags ||
  6093. (dwSystemProviderFlags & PHYSICAL_PROVIDER_FLAG))
  6094. return FALSE;
  6095. if (dwSystemProviderFlags & ASCII_SYSTEM_PROVIDER_FLAG) {
  6096. if (NULL == (pwszStoreName = MkWStr((LPSTR) pwszStoreName)))
  6097. return FALSE;
  6098. }
  6099. if (!ParseSystemStorePara(
  6100. pwszStoreName,
  6101. pStoreInfo->dwOpenFlags,
  6102. 1, // cReq, 1 for OpenSystemStore
  6103. &StoreNameInfo // zero'ed for error
  6104. ))
  6105. goto ParseSystemStoreParaError;
  6106. // Default to not self
  6107. fResult = FALSE;
  6108. if (StoreNameInfo.rgpwszName[COMPUTER_NAME_INDEX]) {
  6109. if (NULL == pSystemNameInfo->rgpwszName[COMPUTER_NAME_INDEX]) {
  6110. LPCWSTR pwszStoreComputerName;
  6111. if (NULL == (pwszCurrentComputerName = GetCurrentComputerName()))
  6112. goto GetCurrentComputerNameError;
  6113. pwszStoreComputerName =
  6114. StoreNameInfo.rgpwszName[COMPUTER_NAME_INDEX];
  6115. assert(L'\\' == pwszStoreComputerName[0] &&
  6116. L'\\' == pwszStoreComputerName[1]);
  6117. if (!('\\' == pwszCurrentComputerName[0] &&
  6118. L'\\' == pwszCurrentComputerName[1]))
  6119. pwszStoreComputerName += 2;
  6120. if (0 != _wcsicmp(pwszStoreComputerName, pwszCurrentComputerName))
  6121. goto CommonReturn;
  6122. } else if (0 != _wcsicmp(StoreNameInfo.rgpwszName[COMPUTER_NAME_INDEX],
  6123. pSystemNameInfo->rgpwszName[COMPUTER_NAME_INDEX]))
  6124. goto CommonReturn;
  6125. }
  6126. // else
  6127. // Opening using none or the same computer name
  6128. if (StoreNameInfo.rgpwszName[SERVICE_NAME_INDEX]) {
  6129. if (NULL == pSystemNameInfo->rgpwszName[SERVICE_NAME_INDEX]) {
  6130. if (NULL == (pwszCurrentServiceName =
  6131. GetCurrentServiceOrUserName()))
  6132. goto GetCurrentServiceOrUserNameError;
  6133. if (0 != _wcsicmp(StoreNameInfo.rgpwszName[SERVICE_NAME_INDEX],
  6134. pwszCurrentServiceName))
  6135. goto CommonReturn;
  6136. } else if (0 != _wcsicmp(StoreNameInfo.rgpwszName[SERVICE_NAME_INDEX],
  6137. pSystemNameInfo->rgpwszName[SERVICE_NAME_INDEX]))
  6138. goto CommonReturn;
  6139. }
  6140. // else
  6141. // Opening using none or the same service/user name
  6142. assert(StoreNameInfo.rgpwszName[SYSTEM_NAME_INDEX] &&
  6143. pSystemNameInfo->rgpwszName[SYSTEM_NAME_INDEX]);
  6144. if (0 != _wcsicmp(StoreNameInfo.rgpwszName[SYSTEM_NAME_INDEX],
  6145. pSystemNameInfo->rgpwszName[SYSTEM_NAME_INDEX]))
  6146. goto CommonReturn;
  6147. // We have a match !!!
  6148. fResult = TRUE;
  6149. *pdwSystemProviderFlags = dwSystemProviderFlags;
  6150. CommonReturn:
  6151. if (dwSystemProviderFlags & ASCII_SYSTEM_PROVIDER_FLAG)
  6152. FreeWStr(pwszStoreName);
  6153. FreeSystemNameInfo(&StoreNameInfo);
  6154. PkiFree(pwszCurrentServiceName);
  6155. PkiFree(pwszCurrentComputerName);
  6156. return fResult;
  6157. ErrorReturn:
  6158. fResult = FALSE;
  6159. goto CommonReturn;
  6160. TRACE_ERROR(GetCurrentComputerNameError)
  6161. TRACE_ERROR(GetCurrentServiceOrUserNameError)
  6162. TRACE_ERROR(ParseSystemStoreParaError)
  6163. }
  6164. // List is sorted according to physical store priority
  6165. STATIC void AddToEnumPhysicalStoreList(
  6166. IN PENUM_PHYSICAL_STORE_INFO *ppStoreInfoHead,
  6167. IN PENUM_PHYSICAL_STORE_INFO pAddInfo
  6168. )
  6169. {
  6170. if (NULL == *ppStoreInfoHead)
  6171. *ppStoreInfoHead = pAddInfo;
  6172. else {
  6173. PENUM_PHYSICAL_STORE_INFO pListInfo;
  6174. DWORD dwPriority = pAddInfo->RegistryInfo.dwPriority;
  6175. pListInfo = *ppStoreInfoHead;
  6176. if (dwPriority > pListInfo->RegistryInfo.dwPriority) {
  6177. // Insert at beginning before first entry
  6178. pAddInfo->pNext = pListInfo;
  6179. *ppStoreInfoHead = pAddInfo;
  6180. } else {
  6181. // Insert after the entry whose next entry has
  6182. // lower priority or insert after the last entry
  6183. while (pListInfo->pNext &&
  6184. dwPriority <= pListInfo->pNext->RegistryInfo.dwPriority)
  6185. pListInfo = pListInfo->pNext;
  6186. pAddInfo->pNext = pListInfo->pNext;
  6187. pListInfo->pNext = pAddInfo;
  6188. }
  6189. }
  6190. }
  6191. STATIC void FreeEnumPhysicalStoreList(
  6192. IN PENUM_PHYSICAL_STORE_INFO pStoreInfoHead
  6193. )
  6194. {
  6195. while (pStoreInfoHead) {
  6196. PENUM_PHYSICAL_STORE_INFO pStoreInfo = pStoreInfoHead;
  6197. pStoreInfoHead = pStoreInfo->pNext;
  6198. FreeEnumPhysicalStoreInfo(pStoreInfo);
  6199. }
  6200. }
  6201. // Returns NULL if unable to successfully get the Url. Returned string
  6202. // must be freed by calling CryptMemFree
  6203. STATIC LPWSTR GetUserDsUserCertificateUrl()
  6204. {
  6205. DWORD dwErr;
  6206. LPWSTR pwszUrl = NULL;
  6207. HMODULE hDll = NULL;
  6208. PFN_GET_USER_DS_STORE_URL pfnGetUserDsStoreUrl;
  6209. if (NULL == (hDll = LoadLibraryA(sz_CRYPTNET_DLL)))
  6210. goto LoadCryptNetDllError;
  6211. if (NULL == (pfnGetUserDsStoreUrl =
  6212. (PFN_GET_USER_DS_STORE_URL) GetProcAddress(hDll,
  6213. sz_GetUserDsStoreUrl)))
  6214. goto GetUserDsStoreUrlProcAddressError;
  6215. if (!pfnGetUserDsStoreUrl(wsz_USER_CERTIFICATE_ATTR, &pwszUrl)) {
  6216. dwErr = GetLastError();
  6217. goto GetUserDsStoreUrlError;
  6218. }
  6219. CommonReturn:
  6220. if (hDll) {
  6221. dwErr = GetLastError();
  6222. FreeLibrary(hDll);
  6223. SetLastError(dwErr);
  6224. }
  6225. return pwszUrl;
  6226. ErrorReturn:
  6227. pwszUrl = NULL;
  6228. goto CommonReturn;
  6229. TRACE_ERROR(LoadCryptNetDllError)
  6230. TRACE_ERROR(GetUserDsStoreUrlProcAddressError)
  6231. SET_ERROR_VAR(GetUserDsStoreUrlError, dwErr)
  6232. }
  6233. STATIC BOOL IsCurrentUserTrustedPublishersAllowed()
  6234. {
  6235. DWORD dwFlags = 0;
  6236. I_CryptReadTrustedPublisherDWORDValueFromRegistry(
  6237. CERT_TRUST_PUB_AUTHENTICODE_FLAGS_VALUE_NAME,
  6238. &dwFlags
  6239. );
  6240. return 0 == (dwFlags &
  6241. (CERT_TRUST_PUB_ALLOW_MACHINE_ADMIN_TRUST |
  6242. CERT_TRUST_PUB_ALLOW_ENTERPRISE_ADMIN_TRUST));
  6243. }
  6244. STATIC BOOL IsLocalMachineTrustedPublishersAllowed()
  6245. {
  6246. DWORD dwFlags = 0;
  6247. I_CryptReadTrustedPublisherDWORDValueFromRegistry(
  6248. CERT_TRUST_PUB_AUTHENTICODE_FLAGS_VALUE_NAME,
  6249. &dwFlags
  6250. );
  6251. return 0 == (dwFlags & CERT_TRUST_PUB_ALLOW_ENTERPRISE_ADMIN_TRUST);
  6252. }
  6253. //+-------------------------------------------------------------------------
  6254. // Unless, CERT_STORE_OPEN_EXISTING_FLAG or CERT_STORE_READONLY_FLAG is
  6255. // set, the pvSystemStore will be created if it doesn't already exist.
  6256. //
  6257. // Note, depending on the store location and possibly the store name, there
  6258. // are predefined physical stores of .Default, .LocalMachine, .GroupPolicy,
  6259. // .Enterprise
  6260. //--------------------------------------------------------------------------
  6261. STATIC BOOL EnumPhysicalStore(
  6262. IN const void *pvSystemStore,
  6263. IN DWORD dwFlags,
  6264. IN void *pvArg,
  6265. IN PFN_CERT_ENUM_PHYSICAL_STORE pfnEnum
  6266. )
  6267. {
  6268. BOOL fResult;
  6269. LONG *plDepth = NULL; // allocated per thread, don't free here
  6270. HKEY hKey = NULL;
  6271. DWORD cSubKeys;
  6272. DWORD cchMaxSubKey = 0;
  6273. LPWSTR pwszStoreName = NULL;
  6274. PENUM_PHYSICAL_STORE_INFO pStoreInfoHead = NULL;
  6275. PENUM_PHYSICAL_STORE_INFO pStoreInfo; // not allocated
  6276. SYSTEM_NAME_INFO SystemNameInfo;
  6277. DWORD dwStoreLocationID;
  6278. DWORD dwPredefinedPhysicalFlags;
  6279. if (!IsSystemStoreLocationInRegistry(dwFlags)) {
  6280. void *pvFuncAddr;
  6281. HCRYPTOIDFUNCADDR hFuncAddr;
  6282. if (!CryptGetOIDFunctionAddress(
  6283. rghFuncSet[ENUM_PHYSICAL_STORE_FUNC_SET],
  6284. 0, // dwEncodingType,
  6285. GetSystemStoreLocationOID(dwFlags),
  6286. 0, // dwFlags
  6287. &pvFuncAddr,
  6288. &hFuncAddr))
  6289. return FALSE;
  6290. fResult = ((PFN_ENUM_PHYSICAL_STORE) pvFuncAddr)(
  6291. pvSystemStore,
  6292. dwFlags,
  6293. pvArg,
  6294. pfnEnum
  6295. );
  6296. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  6297. return fResult;
  6298. }
  6299. if (!ParseSystemStorePara(
  6300. pvSystemStore,
  6301. dwFlags,
  6302. 1, // cReqName
  6303. &SystemNameInfo)) // zero'ed on error
  6304. goto ParseSystemStoreParaError;
  6305. if (dwFlags & ~ENUM_FLAGS_MASK)
  6306. goto InvalidArg;
  6307. if (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG)
  6308. ILS_EnableBackupRestorePrivileges();
  6309. // Check for cross store recursion by checking the thread's enum
  6310. // depth
  6311. if (NULL == (plDepth = (LONG *) I_CryptGetTls(
  6312. hTlsEnumPhysicalStoreDepth))) {
  6313. if (NULL == (plDepth = (LONG *) PkiNonzeroAlloc(sizeof(*plDepth))))
  6314. goto OutOfMemory;
  6315. *plDepth = 1;
  6316. I_CryptSetTls(hTlsEnumPhysicalStoreDepth, plDepth);
  6317. } else {
  6318. *plDepth += 1;
  6319. if (MAX_ENUM_PHYSICAL_STORE_DEPTH < *plDepth)
  6320. goto ExceededEnumPhysicalStoreDepth_PossibleCrossStoreRecursion;
  6321. }
  6322. if (IsClientGptStore(&SystemNameInfo, dwFlags)) {
  6323. cSubKeys = 0;
  6324. } else if (NULL == (hKey = OpenSystemRegPathKey(
  6325. &SystemNameInfo,
  6326. PHYSICAL_STORES_SUBKEY_NAME,
  6327. dwFlags | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG
  6328. ))) {
  6329. if (ERROR_FILE_NOT_FOUND != GetLastError())
  6330. goto OpenPhysicalStoresError;
  6331. // Check if we have a system store without the "PhysicalStores" subkey
  6332. if (NULL == (hKey = OpenSystemRegPathKey(
  6333. &SystemNameInfo,
  6334. NULL, // pwszSubKeyName
  6335. dwFlags
  6336. ))) {
  6337. if (dwFlags & CERT_STORE_MAXIMUM_ALLOWED_FLAG)
  6338. hKey = OpenSystemRegPathKey(
  6339. &SystemNameInfo,
  6340. NULL, // pwszSubKeyName
  6341. dwFlags | CERT_STORE_OPEN_EXISTING_FLAG |
  6342. CERT_STORE_READONLY_FLAG
  6343. );
  6344. }
  6345. if (NULL == hKey) {
  6346. // Note, the predefined stores don't need to exist in the
  6347. // registry
  6348. if (ERROR_FILE_NOT_FOUND != GetLastError())
  6349. goto OpenSystemStoreError;
  6350. } else {
  6351. RegCloseKey(hKey);
  6352. hKey = NULL;
  6353. }
  6354. cSubKeys = 0;
  6355. } else if (!GetSubKeyInfo(
  6356. hKey,
  6357. &cSubKeys,
  6358. &cchMaxSubKey
  6359. ))
  6360. goto GetSubKeyInfoError;
  6361. // Get flags containing list of predefined physical stores according to
  6362. // store name and/or store location
  6363. dwStoreLocationID = GetSystemStoreLocationID(dwFlags);
  6364. if (0 == _wcsicmp(SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX],
  6365. wsz_MY_STORE) ||
  6366. 0 == _wcsicmp(SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX],
  6367. wsz_REQUEST_STORE))
  6368. // Only .Default is predefined for "My" or "Request" store
  6369. dwPredefinedPhysicalFlags = MY_PHYSICAL_FLAGS;
  6370. else if (0 == _wcsicmp(SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX],
  6371. wsz_ROOT_STORE)) {
  6372. if (CERT_SYSTEM_STORE_CURRENT_USER_ID == dwStoreLocationID) {
  6373. if (IPR_IsCurrentUserRootsAllowed()) {
  6374. // .Default and .LocalMachine physical stores are predefined
  6375. dwPredefinedPhysicalFlags = CURRENT_USER_ROOT_PHYSICAL_FLAGS;
  6376. } else {
  6377. // Don't read the CurrentUser's SystemRegistry
  6378. dwPredefinedPhysicalFlags = CURRENT_USER_ROOT_PHYSICAL_FLAGS &
  6379. ~DEFAULT_PHYSICAL_FLAG;
  6380. // Since we won't be reading the SystemRegistry, ensure
  6381. // the protected list of roots is initialized.
  6382. IPR_InitProtectedRootInfo();
  6383. }
  6384. // Only the predefined physical stores are allowed for Root
  6385. cSubKeys = 0;
  6386. } else if (CERT_SYSTEM_STORE_LOCAL_MACHINE_ID == dwStoreLocationID) {
  6387. if (IPR_IsAuthRootsAllowed()) {
  6388. // .Default, .AuthRoot, .GroupPolicy and .Enterprise
  6389. // physical stores are predefined
  6390. dwPredefinedPhysicalFlags = LOCAL_MACHINE_ROOT_PHYSICAL_FLAGS;
  6391. } else {
  6392. // Don't read the AuthRoot's SystemRegistry
  6393. dwPredefinedPhysicalFlags = LOCAL_MACHINE_ROOT_PHYSICAL_FLAGS &
  6394. ~AUTH_ROOT_PHYSICAL_FLAG;
  6395. }
  6396. // Only the predefined physical stores are allowed for Root
  6397. cSubKeys = 0;
  6398. } else if (CERT_SYSTEM_STORE_USERS_ID == dwStoreLocationID) {
  6399. // Only .LocalMachine physical stores is predefined
  6400. dwPredefinedPhysicalFlags = USERS_ROOT_PHYSICAL_FLAGS;
  6401. // Only the predefined physical stores are allowed for Root
  6402. cSubKeys = 0;
  6403. } else {
  6404. // According to store location.
  6405. dwPredefinedPhysicalFlags =
  6406. rgSystemStoreLocationInfo[
  6407. dwStoreLocationID].dwPredefinedPhysicalFlags;
  6408. }
  6409. } else if (0 == _wcsicmp(SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX],
  6410. wsz_TRUST_PUB_STORE) ||
  6411. 0 == _wcsicmp(SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX],
  6412. wsz_DISALLOWED_STORE)) {
  6413. if (CERT_SYSTEM_STORE_CURRENT_USER_ID == dwStoreLocationID) {
  6414. if (IsCurrentUserTrustedPublishersAllowed()) {
  6415. // .Default, .GroupPolicy and .LocalMachine physical stores
  6416. // are predefined
  6417. dwPredefinedPhysicalFlags =
  6418. CURRENT_USER_TRUST_PUB_PHYSICAL_FLAGS;
  6419. } else {
  6420. // Don't read the CurrentUser's SystemRegistry
  6421. dwPredefinedPhysicalFlags =
  6422. CURRENT_USER_TRUST_PUB_PHYSICAL_FLAGS &
  6423. ~DEFAULT_PHYSICAL_FLAG;
  6424. }
  6425. // Only the predefined physical stores are allowed for
  6426. // HKCU TrustedPublisher
  6427. cSubKeys = 0;
  6428. } else if (CERT_SYSTEM_STORE_LOCAL_MACHINE_ID == dwStoreLocationID) {
  6429. if (IsLocalMachineTrustedPublishersAllowed()) {
  6430. // .Default, .GroupPolicy and .Enterprise
  6431. // physical stores are predefined
  6432. dwPredefinedPhysicalFlags =
  6433. LOCAL_MACHINE_TRUST_PUB_PHYSICAL_FLAGS;
  6434. } else {
  6435. // Don't read the LocalMachine's SystemRegistry
  6436. dwPredefinedPhysicalFlags =
  6437. LOCAL_MACHINE_TRUST_PUB_PHYSICAL_FLAGS &
  6438. ~DEFAULT_PHYSICAL_FLAG;
  6439. }
  6440. // Only the predefined physical stores are allowed for
  6441. // HKLM TrustedPublisher
  6442. cSubKeys = 0;
  6443. } else {
  6444. // According to store location.
  6445. dwPredefinedPhysicalFlags =
  6446. rgSystemStoreLocationInfo[
  6447. dwStoreLocationID].dwPredefinedPhysicalFlags;
  6448. }
  6449. } else if (0 == _wcsicmp(SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX],
  6450. wsz_USER_DS_STORE)) {
  6451. // Only .UserCertificate is predefined for "UserDS"
  6452. dwPredefinedPhysicalFlags = USER_DS_PHYSICAL_FLAGS;
  6453. } else
  6454. // According to store location
  6455. dwPredefinedPhysicalFlags =
  6456. rgSystemStoreLocationInfo[
  6457. dwStoreLocationID].dwPredefinedPhysicalFlags;
  6458. if (cSubKeys && cchMaxSubKey) {
  6459. DWORD i;
  6460. cchMaxSubKey++;
  6461. if (NULL == (pwszStoreName = (LPWSTR) PkiNonzeroAlloc(
  6462. cchMaxSubKey * sizeof(WCHAR))))
  6463. goto OutOfMemory;
  6464. for (i = 0; i < cSubKeys; i++) {
  6465. DWORD cchStoreName = cchMaxSubKey;
  6466. LONG err;
  6467. if (ERROR_SUCCESS != (err = RegEnumKeyExU(
  6468. hKey,
  6469. i,
  6470. pwszStoreName,
  6471. &cchStoreName,
  6472. NULL, // lpdwReserved
  6473. NULL, // lpszClass
  6474. NULL, // lpcchClass
  6475. NULL // lpftLastWriteTime
  6476. )) || 0 == cchStoreName) {
  6477. if (ERROR_NO_MORE_ITEMS == err)
  6478. break;
  6479. else
  6480. continue;
  6481. }
  6482. if (NULL == (pStoreInfo = GetEnumPhysicalStoreInfo(
  6483. hKey,
  6484. pwszStoreName,
  6485. dwFlags
  6486. )))
  6487. continue;
  6488. AddToEnumPhysicalStoreList(&pStoreInfoHead, pStoreInfo);
  6489. }
  6490. }
  6491. for (pStoreInfo = pStoreInfoHead; pStoreInfo;
  6492. pStoreInfo = pStoreInfo->pNext) {
  6493. PCERT_PHYSICAL_STORE_INFO pRegistryInfo = &pStoreInfo->RegistryInfo;
  6494. BOOL fSelfPhysicalStoreInfo;
  6495. DWORD dwSystemProviderFlags;
  6496. char szOID[34];
  6497. if (IsSelfPhysicalStoreInfo(
  6498. &SystemNameInfo,
  6499. dwFlags,
  6500. pRegistryInfo,
  6501. &dwSystemProviderFlags)) {
  6502. assert((dwSystemProviderFlags & UNICODE_SYSTEM_PROVIDER_FLAG) ||
  6503. (dwSystemProviderFlags & ASCII_SYSTEM_PROVIDER_FLAG));
  6504. // Force to use SYSTEM_REGISTRY provider to inhibit recursion.
  6505. PkiFree(pRegistryInfo->pszOpenStoreProvider);
  6506. if (dwSystemProviderFlags & ASCII_SYSTEM_PROVIDER_FLAG) {
  6507. // Convert to "#<number>" string
  6508. szOID[0] = CONST_OID_STR_PREFIX_CHAR;
  6509. _ltoa((long) ((DWORD_PTR)CERT_STORE_PROV_SYSTEM_REGISTRY_A), szOID + 1, 10);
  6510. pRegistryInfo->pszOpenStoreProvider = szOID;
  6511. } else
  6512. pRegistryInfo->pszOpenStoreProvider =
  6513. sz_CERT_STORE_PROV_SYSTEM_REGISTRY_W;
  6514. dwPredefinedPhysicalFlags &= ~DEFAULT_PHYSICAL_FLAG;
  6515. fSelfPhysicalStoreInfo = TRUE;
  6516. } else {
  6517. if (0 != dwPredefinedPhysicalFlags) {
  6518. // Check if matches one of the predefined physical stores
  6519. DWORD i;
  6520. DWORD dwCheckFlag;
  6521. for (i = 0, dwCheckFlag = 1; i < NUM_PREDEFINED_PHYSICAL;
  6522. i++, dwCheckFlag = dwCheckFlag << 1) {
  6523. if ((dwCheckFlag & dwPredefinedPhysicalFlags) &&
  6524. 0 == _wcsicmp(pStoreInfo->pwszStoreName,
  6525. rgpwszPredefinedPhysical[i])) {
  6526. dwPredefinedPhysicalFlags &= ~dwCheckFlag;
  6527. break;
  6528. }
  6529. }
  6530. }
  6531. fSelfPhysicalStoreInfo = FALSE;
  6532. }
  6533. if (dwFlags & CERT_STORE_MAXIMUM_ALLOWED_FLAG) {
  6534. pRegistryInfo->dwOpenFlags |= CERT_STORE_MAXIMUM_ALLOWED_FLAG;
  6535. pRegistryInfo->dwOpenFlags &= ~CERT_STORE_READONLY_FLAG;
  6536. }
  6537. if (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG) {
  6538. pRegistryInfo->dwOpenFlags |= CERT_STORE_BACKUP_RESTORE_FLAG;
  6539. }
  6540. fResult = pfnEnum(
  6541. pvSystemStore,
  6542. dwFlags & CERT_SYSTEM_STORE_MASK,
  6543. pStoreInfo->pwszStoreName,
  6544. &pStoreInfo->RegistryInfo,
  6545. NULL, // pvReserved
  6546. pvArg
  6547. );
  6548. if (fSelfPhysicalStoreInfo) {
  6549. // Not allocated. Set to NULL to inhibit subsequent free.
  6550. pRegistryInfo->pszOpenStoreProvider = NULL;
  6551. }
  6552. if (!fResult)
  6553. goto EnumCallbackError;
  6554. }
  6555. if (0 != dwPredefinedPhysicalFlags) {
  6556. CERT_PHYSICAL_STORE_INFO SelfInfo;
  6557. LPWSTR pwszLocalStore;
  6558. DWORD cbLocalStore;
  6559. DWORD i;
  6560. DWORD dwCheckFlag;
  6561. if (SystemNameInfo.rgpwszName[COMPUTER_NAME_INDEX]) {
  6562. // Format local store name without the ComputerName
  6563. LPCWSTR rgpwszGroupName[2];
  6564. SYSTEM_NAME_GROUP NameGroup;
  6565. NameGroup.cName = 2;
  6566. NameGroup.rgpwszName = rgpwszGroupName;
  6567. assert(IsRemotableSystemStoreLocationInRegistry(dwFlags));
  6568. rgpwszGroupName[0] = SystemNameInfo.rgpwszName[SERVICE_NAME_INDEX];
  6569. rgpwszGroupName[1] = SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX];
  6570. if (NULL == (pwszLocalStore = FormatSystemNamePath(1, &NameGroup)))
  6571. goto FormatSystemNamePathError;
  6572. } else {
  6573. if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) {
  6574. PCERT_SYSTEM_STORE_RELOCATE_PARA pRelocatePara =
  6575. (PCERT_SYSTEM_STORE_RELOCATE_PARA) pvSystemStore;
  6576. pwszLocalStore = (LPWSTR) pRelocatePara->pwszSystemStore;
  6577. } else
  6578. pwszLocalStore = (LPWSTR) pvSystemStore;
  6579. }
  6580. cbLocalStore = (wcslen(pwszLocalStore) + 1) * sizeof(WCHAR);
  6581. memset(&SelfInfo, 0, sizeof(SelfInfo));
  6582. SelfInfo.cbSize = sizeof(SelfInfo);
  6583. fResult = TRUE;
  6584. for (i = 0, dwCheckFlag = 1; i < NUM_PREDEFINED_PHYSICAL;
  6585. i++, dwCheckFlag = dwCheckFlag << 1) {
  6586. LPWSTR pwszUserDsUserCertificateUrl;
  6587. if (0 == (dwCheckFlag & dwPredefinedPhysicalFlags))
  6588. continue;
  6589. SelfInfo.pszOpenStoreProvider = sz_CERT_STORE_PROV_SYSTEM_W;
  6590. SelfInfo.OpenParameters.pbData =
  6591. (BYTE *) SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX];
  6592. SelfInfo.OpenParameters.cbData =
  6593. (wcslen(SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX]) + 1) *
  6594. sizeof(WCHAR);
  6595. SelfInfo.dwFlags = 0;
  6596. pwszUserDsUserCertificateUrl = NULL;
  6597. switch (i) {
  6598. case DEFAULT_PHYSICAL_INDEX:
  6599. SelfInfo.pszOpenStoreProvider =
  6600. sz_CERT_STORE_PROV_SYSTEM_REGISTRY_W;
  6601. SelfInfo.dwOpenFlags = dwFlags &
  6602. CERT_SYSTEM_STORE_LOCATION_MASK;
  6603. if (0 == _wcsicmp(
  6604. SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX],
  6605. wsz_MY_STORE))
  6606. SelfInfo.dwOpenFlags |= CERT_STORE_UPDATE_KEYID_FLAG;
  6607. SelfInfo.OpenParameters.pbData = (BYTE *) pwszLocalStore;
  6608. SelfInfo.OpenParameters.cbData = cbLocalStore;
  6609. SelfInfo.dwFlags = CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG;
  6610. break;
  6611. case AUTH_ROOT_PHYSICAL_INDEX:
  6612. SelfInfo.pszOpenStoreProvider =
  6613. sz_CERT_STORE_PROV_SYSTEM_REGISTRY_W;
  6614. SelfInfo.dwOpenFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
  6615. SelfInfo.OpenParameters.pbData =
  6616. (BYTE *) wsz_AUTH_ROOT_STORE;
  6617. SelfInfo.OpenParameters.cbData =
  6618. (wcslen(wsz_AUTH_ROOT_STORE) + 1) * sizeof(WCHAR);
  6619. SelfInfo.dwFlags = CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG;
  6620. break;
  6621. case GROUP_POLICY_PHYSICAL_INDEX:
  6622. if (CERT_SYSTEM_STORE_LOCAL_MACHINE_ID ==
  6623. dwStoreLocationID)
  6624. SelfInfo.dwOpenFlags =
  6625. CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY |
  6626. CERT_STORE_READONLY_FLAG;
  6627. else
  6628. SelfInfo.dwOpenFlags =
  6629. CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY |
  6630. CERT_STORE_READONLY_FLAG;
  6631. break;
  6632. case LOCAL_MACHINE_PHYSICAL_INDEX:
  6633. SelfInfo.dwOpenFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE |
  6634. CERT_STORE_READONLY_FLAG;
  6635. break;
  6636. case DS_USER_CERT_PHYSICAL_INDEX:
  6637. if (NULL == (pwszUserDsUserCertificateUrl =
  6638. GetUserDsUserCertificateUrl()))
  6639. continue;
  6640. SelfInfo.pszOpenStoreProvider = sz_CERT_STORE_PROV_LDAP_W;
  6641. SelfInfo.dwOpenFlags = 0;
  6642. SelfInfo.OpenParameters.pbData =
  6643. (BYTE *) pwszUserDsUserCertificateUrl;
  6644. SelfInfo.OpenParameters.cbData = (wcslen(
  6645. pwszUserDsUserCertificateUrl) + 1) * sizeof(WCHAR);
  6646. SelfInfo.dwFlags = CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG;
  6647. break;
  6648. case LMGP_PHYSICAL_INDEX:
  6649. SelfInfo.dwOpenFlags =
  6650. CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY |
  6651. CERT_STORE_READONLY_FLAG;
  6652. break;
  6653. case ENTERPRISE_PHYSICAL_INDEX:
  6654. SelfInfo.dwOpenFlags =
  6655. CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE |
  6656. CERT_STORE_READONLY_FLAG;
  6657. break;
  6658. default:
  6659. assert(i < NUM_PREDEFINED_PHYSICAL);
  6660. continue;
  6661. }
  6662. if (dwFlags & CERT_STORE_MAXIMUM_ALLOWED_FLAG) {
  6663. SelfInfo.dwOpenFlags |= CERT_STORE_MAXIMUM_ALLOWED_FLAG;
  6664. SelfInfo.dwOpenFlags &= ~CERT_STORE_READONLY_FLAG;
  6665. }
  6666. if (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG) {
  6667. SelfInfo.dwOpenFlags |= CERT_STORE_BACKUP_RESTORE_FLAG;
  6668. }
  6669. fResult = pfnEnum(
  6670. pvSystemStore,
  6671. (dwFlags & CERT_SYSTEM_STORE_MASK) |
  6672. CERT_PHYSICAL_STORE_PREDEFINED_ENUM_FLAG,
  6673. rgpwszPredefinedPhysical[i], // pwszStoreName
  6674. &SelfInfo,
  6675. NULL, // pvReserved
  6676. pvArg
  6677. );
  6678. if (pwszUserDsUserCertificateUrl)
  6679. CryptMemFree(pwszUserDsUserCertificateUrl);
  6680. if (!fResult)
  6681. break;
  6682. }
  6683. if (SystemNameInfo.rgpwszName[COMPUTER_NAME_INDEX])
  6684. PkiFree(pwszLocalStore);
  6685. if (!fResult)
  6686. goto EnumCallbackError;
  6687. }
  6688. fResult = TRUE;
  6689. CommonReturn:
  6690. if (plDepth)
  6691. *plDepth -= 1;
  6692. ILS_CloseRegistryKey(hKey);
  6693. FreeSystemNameInfo(&SystemNameInfo);
  6694. PkiFree(pwszStoreName);
  6695. FreeEnumPhysicalStoreList(pStoreInfoHead);
  6696. return fResult;
  6697. ErrorReturn:
  6698. fResult = FALSE;
  6699. goto CommonReturn;
  6700. TRACE_ERROR(ParseSystemStoreParaError)
  6701. SET_ERROR(InvalidArg, E_INVALIDARG)
  6702. TRACE_ERROR(OutOfMemory)
  6703. SET_ERROR(ExceededEnumPhysicalStoreDepth_PossibleCrossStoreRecursion, E_UNEXPECTED)
  6704. TRACE_ERROR(OpenPhysicalStoresError)
  6705. TRACE_ERROR(OpenSystemStoreError)
  6706. TRACE_ERROR(GetSubKeyInfoError)
  6707. TRACE_ERROR(FormatSystemNamePathError)
  6708. TRACE_ERROR(EnumCallbackError)
  6709. }
  6710. //+-------------------------------------------------------------------------
  6711. // Enumerate the physical stores for the specified system store.
  6712. //
  6713. // The upper word of the dwFlags parameter is used to specify the location of
  6714. // the system store.
  6715. //
  6716. // If the system store location only supports system stores and doesn't
  6717. // support physical stores, LastError is set to ERROR_CALL_NOT_IMPLEMENTED.
  6718. //--------------------------------------------------------------------------
  6719. BOOL
  6720. WINAPI
  6721. CertEnumPhysicalStore(
  6722. IN const void *pvSystemStore,
  6723. IN DWORD dwFlags,
  6724. IN void *pvArg,
  6725. IN PFN_CERT_ENUM_PHYSICAL_STORE pfnEnum
  6726. )
  6727. {
  6728. return EnumPhysicalStore(
  6729. pvSystemStore,
  6730. dwFlags | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG,
  6731. pvArg,
  6732. pfnEnum
  6733. );
  6734. }
  6735. STATIC BOOL IsHKCUStore(
  6736. IN LPCWSTR pwszStoreName,
  6737. IN PSYSTEM_NAME_INFO pInfo,
  6738. IN DWORD dwFlags
  6739. )
  6740. {
  6741. DWORD dwStoreLocation = dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK;
  6742. if (CERT_SYSTEM_STORE_CURRENT_USER != dwStoreLocation ||
  6743. 0 != _wcsicmp(pInfo->rgpwszName[SYSTEM_NAME_INDEX], pwszStoreName))
  6744. return FALSE;
  6745. if (dwFlags & (CERT_SYSTEM_STORE_RELOCATE_FLAG | CERT_STORE_DELETE_FLAG))
  6746. return FALSE;
  6747. return TRUE;
  6748. }
  6749. //+-------------------------------------------------------------------------
  6750. // Open the system registry store provider (unicode version)
  6751. //
  6752. // Open the system registry store specified by its name. For example,
  6753. // L"My".
  6754. //
  6755. // pvPara contains the LPCWSTR system registry store name.
  6756. //
  6757. // Note for an error return, the caller will free any certs, CRLs or CTLs
  6758. // successfully added to the store.
  6759. //--------------------------------------------------------------------------
  6760. BOOL
  6761. WINAPI
  6762. I_CertDllOpenSystemRegistryStoreProvW(
  6763. IN LPCSTR lpszStoreProvider,
  6764. IN DWORD dwEncodingType,
  6765. IN HCRYPTPROV hCryptProv,
  6766. IN DWORD dwFlags,
  6767. IN const void *pvPara,
  6768. IN HCERTSTORE hCertStore,
  6769. IN OUT PCERT_STORE_PROV_INFO pStoreProvInfo
  6770. )
  6771. {
  6772. BOOL fResult;
  6773. LONG err;
  6774. HKEY hKey = NULL;
  6775. SYSTEM_NAME_INFO SystemNameInfo;
  6776. BOOL fUserRoot;
  6777. HKEY hHKCURoot = NULL;
  6778. DWORD dwOpenRegFlags;
  6779. const void *pvOpenRegPara;
  6780. LPWSTR pwszRoamingDirectory = NULL;
  6781. CERT_REGISTRY_STORE_ROAMING_PARA RoamingStorePara;
  6782. CERT_REGISTRY_STORE_CLIENT_GPT_PARA ClientGptStorePara;
  6783. memset(&ClientGptStorePara, 0, sizeof(ClientGptStorePara));
  6784. if (dwFlags & CERT_STORE_UNSAFE_PHYSICAL_FLAG) {
  6785. if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) {
  6786. SetLastError((DWORD) E_INVALIDARG);
  6787. return FALSE;
  6788. }
  6789. dwFlags &= ~CERT_STORE_UNSAFE_PHYSICAL_FLAG;
  6790. }
  6791. if (!ParseSystemStorePara(
  6792. pvPara,
  6793. dwFlags,
  6794. 1, // cReqName
  6795. &SystemNameInfo)) // zero'ed on error
  6796. goto ParseSystemStoreParaError;
  6797. if (dwFlags & ~OPEN_SYS_FLAGS_MASK)
  6798. goto InvalidArg;
  6799. if (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG)
  6800. ILS_EnableBackupRestorePrivileges();
  6801. // Check for the CurrentUser "Root" store.
  6802. fUserRoot = FALSE;
  6803. if (0 == _wcsicmp(SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX],
  6804. wsz_ROOT_STORE) &&
  6805. 0 == (dwFlags & CERT_SYSTEM_STORE_UNPROTECTED_FLAG)) {
  6806. DWORD dwStoreLocation = dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK;
  6807. // Note, LOCAL_MACHINE check is needed to prevent use of relocation
  6808. // to access the current user's root store
  6809. if (CERT_SYSTEM_STORE_CURRENT_USER == dwStoreLocation) {
  6810. fUserRoot = TRUE;
  6811. if (NULL == SystemNameInfo.hKeyBase) {
  6812. if (ERROR_SUCCESS != (err = RegOpenHKCUEx(
  6813. &hHKCURoot,
  6814. REG_HKCU_DISABLE_DEFAULT_FLAG
  6815. )))
  6816. goto RegOpenHKCUExRootError;
  6817. SystemNameInfo.hKeyBase = hHKCURoot;
  6818. dwFlags |= CERT_SYSTEM_STORE_RELOCATE_FLAG;
  6819. }
  6820. } else if (CERT_SYSTEM_STORE_USERS == dwStoreLocation ||
  6821. ((dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) &&
  6822. CERT_SYSTEM_STORE_LOCAL_MACHINE == dwStoreLocation))
  6823. goto RootAccessDenied;
  6824. }
  6825. if (IsClientGptStore(&SystemNameInfo, dwFlags)) {
  6826. DWORD dwStoreLocation;
  6827. assert(!fUserRoot);
  6828. if (NULL == (ClientGptStorePara.pwszRegPath = FormatSystemRegPath(
  6829. &SystemNameInfo,
  6830. NULL, // pwszSubKeyName
  6831. dwFlags,
  6832. &ClientGptStorePara.hKeyBase)))
  6833. goto FormatSystemRegPathError;
  6834. pvOpenRegPara = (const void *) &ClientGptStorePara;
  6835. dwOpenRegFlags =
  6836. dwFlags & ~(CERT_SYSTEM_STORE_MASK |
  6837. CERT_STORE_SET_LOCALIZED_NAME_FLAG);
  6838. dwOpenRegFlags |= CERT_REGISTRY_STORE_CLIENT_GPT_FLAG;
  6839. // | CERT_REGISTRY_STORE_SERIALIZED_FLAG;
  6840. dwStoreLocation = dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK;
  6841. if (CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY == dwStoreLocation)
  6842. dwOpenRegFlags |= CERT_REGISTRY_STORE_LM_GPT_FLAG;
  6843. if (SystemNameInfo.rgpwszName[COMPUTER_NAME_INDEX])
  6844. dwOpenRegFlags |= CERT_REGISTRY_STORE_REMOTE_FLAG;
  6845. } else {
  6846. BOOL fIsHKCUMyStore;
  6847. fIsHKCUMyStore = IsHKCUStore(wsz_MY_STORE, &SystemNameInfo, dwFlags);
  6848. if (fIsHKCUMyStore) {
  6849. pwszRoamingDirectory =
  6850. ILS_GetRoamingStoreDirectory(ROAMING_MY_STORE_SUBDIR);
  6851. } else if (IsHKCUStore(wsz_REQUEST_STORE, &SystemNameInfo, dwFlags)) {
  6852. pwszRoamingDirectory =
  6853. ILS_GetRoamingStoreDirectory(ROAMING_REQUEST_STORE_SUBDIR);
  6854. }
  6855. if (NULL != pwszRoamingDirectory) {
  6856. // OK for this to fail. After the first open, all contexts should
  6857. // be persisted in files and not the registry.
  6858. hKey = OpenSystemRegPathKey(
  6859. &SystemNameInfo,
  6860. NULL, // pwszSubKeyName
  6861. (dwFlags & ~CERT_STORE_CREATE_NEW_FLAG) |
  6862. CERT_STORE_OPEN_EXISTING_FLAG
  6863. );
  6864. RoamingStorePara.hKey = hKey;
  6865. RoamingStorePara.pwszStoreDirectory = pwszRoamingDirectory;
  6866. pvOpenRegPara = (const void *) &RoamingStorePara;
  6867. dwOpenRegFlags =
  6868. dwFlags & ~(CERT_SYSTEM_STORE_MASK |
  6869. CERT_STORE_CREATE_NEW_FLAG |
  6870. CERT_STORE_SET_LOCALIZED_NAME_FLAG);
  6871. dwOpenRegFlags |= CERT_REGISTRY_STORE_ROAMING_FLAG;
  6872. } else {
  6873. if (NULL == (hKey = OpenSystemRegPathKey(
  6874. &SystemNameInfo,
  6875. NULL, // pwszSubKeyName
  6876. dwFlags)))
  6877. goto OpenSystemStoreError;
  6878. pvOpenRegPara = (const void *) hKey;
  6879. dwOpenRegFlags =
  6880. dwFlags & ~(CERT_SYSTEM_STORE_MASK |
  6881. CERT_STORE_CREATE_NEW_FLAG |
  6882. CERT_STORE_SET_LOCALIZED_NAME_FLAG);
  6883. if (SystemNameInfo.rgpwszName[COMPUTER_NAME_INDEX])
  6884. dwOpenRegFlags |= CERT_REGISTRY_STORE_REMOTE_FLAG;
  6885. if (IsSerializedSystemStoreLocationInRegistry(dwFlags)) {
  6886. assert(!fUserRoot);
  6887. dwOpenRegFlags |= CERT_REGISTRY_STORE_SERIALIZED_FLAG;
  6888. }
  6889. }
  6890. }
  6891. if (fUserRoot)
  6892. IPR_InitProtectedRootInfo();
  6893. if (!I_CertDllOpenRegStoreProv(
  6894. NULL, // lpszStoreProvider
  6895. dwEncodingType,
  6896. hCryptProv,
  6897. dwOpenRegFlags,
  6898. pvOpenRegPara,
  6899. hCertStore,
  6900. pStoreProvInfo))
  6901. goto OpenRegStoreProvError;
  6902. if (fUserRoot) {
  6903. PREG_STORE pRegStore = (PREG_STORE) pStoreProvInfo->hStoreProv;
  6904. // Set count to 0 to inhibit any callbacks from being called.
  6905. pStoreProvInfo->cStoreProvFunc = 0;
  6906. // For the "Root" delete any roots that aren't in the protected root
  6907. // list.
  6908. if (!IPR_DeleteUnprotectedRootsFromStore(
  6909. hCertStore,
  6910. &pRegStore->fProtected
  6911. )) goto DeleteUnprotectedRootsError;
  6912. // For the "Root" replace some of the provider callback functions
  6913. // that first prompt the user directly (if not protected) or
  6914. // prompt the user via the system service (if protected).
  6915. pStoreProvInfo->cStoreProvFunc = ROOT_STORE_PROV_FUNC_COUNT;
  6916. pStoreProvInfo->rgpvStoreProvFunc = (void **) rgpvRootStoreProvFunc;
  6917. }
  6918. if (dwFlags & CERT_STORE_SET_LOCALIZED_NAME_FLAG)
  6919. SetLocalizedNameStoreProperty(hCertStore, &SystemNameInfo);
  6920. pStoreProvInfo->dwStoreProvFlags |= CERT_STORE_PROV_SYSTEM_STORE_FLAG;
  6921. if (IsLMSystemStoreLocationInRegistry(dwFlags))
  6922. pStoreProvInfo->dwStoreProvFlags |=
  6923. CERT_STORE_PROV_LM_SYSTEM_STORE_FLAG;
  6924. fResult = TRUE;
  6925. CommonReturn:
  6926. if (SystemNameInfo.rgpwszName[COMPUTER_NAME_INDEX] &&
  6927. ClientGptStorePara.hKeyBase)
  6928. ILS_CloseRegistryKey(ClientGptStorePara.hKeyBase);
  6929. PkiFree(ClientGptStorePara.pwszRegPath);
  6930. FreeSystemNameInfo(&SystemNameInfo);
  6931. PkiFree(pwszRoamingDirectory);
  6932. ILS_CloseRegistryKey(hKey);
  6933. if (hHKCURoot) {
  6934. DWORD dwErr = GetLastError();
  6935. RegCloseHKCU(hHKCURoot);
  6936. SetLastError(dwErr);
  6937. }
  6938. return fResult;
  6939. ErrorReturn:
  6940. fResult = FALSE;
  6941. goto CommonReturn;
  6942. TRACE_ERROR(ParseSystemStoreParaError)
  6943. SET_ERROR(InvalidArg, E_INVALIDARG)
  6944. SET_ERROR(RootAccessDenied, E_ACCESSDENIED)
  6945. SET_ERROR_VAR(RegOpenHKCUExRootError, err)
  6946. TRACE_ERROR(FormatSystemRegPathError)
  6947. TRACE_ERROR(OpenSystemStoreError)
  6948. TRACE_ERROR(OpenRegStoreProvError)
  6949. TRACE_ERROR(DeleteUnprotectedRootsError)
  6950. }
  6951. //+-------------------------------------------------------------------------
  6952. // Open the system registry store provider (ascii version)
  6953. //
  6954. // Open the system registry store specified by its name. For example,
  6955. // "My".
  6956. //
  6957. // pvPara contains the LPCSTR system store name.
  6958. //
  6959. // Note for an error return, the caller will free any certs or CRLs
  6960. // successfully added to the store.
  6961. //--------------------------------------------------------------------------
  6962. BOOL
  6963. WINAPI
  6964. I_CertDllOpenSystemRegistryStoreProvA(
  6965. IN LPCSTR lpszStoreProvider,
  6966. IN DWORD dwEncodingType,
  6967. IN HCRYPTPROV hCryptProv,
  6968. IN DWORD dwFlags,
  6969. IN const void *pvPara,
  6970. IN HCERTSTORE hCertStore,
  6971. IN OUT PCERT_STORE_PROV_INFO pStoreProvInfo
  6972. )
  6973. {
  6974. BOOL fResult;
  6975. LPCSTR pszStoreName; // not allocated
  6976. LPWSTR pwszStoreName;
  6977. CERT_SYSTEM_STORE_RELOCATE_PARA RelocatePara;
  6978. if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) {
  6979. PCERT_SYSTEM_STORE_RELOCATE_PARA pInPara;
  6980. if (dwFlags & CERT_STORE_UNSAFE_PHYSICAL_FLAG) {
  6981. SetLastError((DWORD) E_INVALIDARG);
  6982. return FALSE;
  6983. }
  6984. assert(pvPara);
  6985. pInPara = (PCERT_SYSTEM_STORE_RELOCATE_PARA) pvPara;
  6986. RelocatePara.hKeyBase = pInPara->hKeyBase;
  6987. pszStoreName = pInPara->pszSystemStore;
  6988. } else
  6989. pszStoreName = (LPCSTR) pvPara;
  6990. assert(pszStoreName);
  6991. if (NULL == (pwszStoreName = MkWStr((LPSTR) pszStoreName)))
  6992. fResult = FALSE;
  6993. else {
  6994. const void *pvParaW;
  6995. if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) {
  6996. RelocatePara.pwszSystemStore = pwszStoreName;
  6997. pvParaW = (const void *) &RelocatePara;
  6998. } else
  6999. pvParaW = (const void *) pwszStoreName;
  7000. fResult = I_CertDllOpenSystemRegistryStoreProvW(
  7001. NULL, // lpszStoreProvider
  7002. dwEncodingType,
  7003. hCryptProv,
  7004. dwFlags,
  7005. pvParaW,
  7006. hCertStore,
  7007. pStoreProvInfo
  7008. );
  7009. FreeWStr(pwszStoreName);
  7010. }
  7011. return fResult;
  7012. }
  7013. typedef struct _OPEN_PHYSICAL_STORE_INFO {
  7014. HCERTSTORE hCollectionStore;
  7015. LPCWSTR pwszComputerName; // NULL implies local
  7016. LPCWSTR pwszServiceName; // NULL implies current
  7017. LPCWSTR pwszPhysicalName; // NULL implies any
  7018. HKEY hKeyBase; // non-NULL, relocatable
  7019. DWORD dwFlags;
  7020. BOOL fDidOpen;
  7021. } OPEN_PHYSICAL_STORE_INFO, *POPEN_PHYSICAL_STORE_INFO;
  7022. STATIC BOOL WINAPI OpenPhysicalStoreCallback(
  7023. IN const void *pvSystemStore,
  7024. IN DWORD dwFlags,
  7025. IN LPCWSTR pwszStoreName,
  7026. IN PCERT_PHYSICAL_STORE_INFO pStoreInfo,
  7027. IN OPTIONAL void *pvReserved,
  7028. IN OPTIONAL void *pvArg
  7029. )
  7030. {
  7031. BOOL fResult;
  7032. HCERTSTORE hPhysicalStore = NULL;
  7033. POPEN_PHYSICAL_STORE_INFO pOpenInfo =
  7034. (POPEN_PHYSICAL_STORE_INFO) pvArg;
  7035. void *pvOpenParameters;
  7036. LPWSTR pwszRemoteOpenParameters = NULL;
  7037. LPCSTR pszOpenStoreProvider;
  7038. DWORD dwOpenFlags;
  7039. DWORD dwAddFlags;
  7040. CERT_SYSTEM_STORE_RELOCATE_PARA RelocateOpenParameters;
  7041. if ((pStoreInfo->dwFlags & CERT_PHYSICAL_STORE_OPEN_DISABLE_FLAG)
  7042. ||
  7043. (pOpenInfo->pwszPhysicalName &&
  7044. 0 != _wcsicmp(pOpenInfo->pwszPhysicalName, pwszStoreName))
  7045. ||
  7046. (pOpenInfo->pwszComputerName &&
  7047. (pStoreInfo->dwFlags &
  7048. CERT_PHYSICAL_STORE_REMOTE_OPEN_DISABLE_FLAG)))
  7049. return TRUE;
  7050. pvOpenParameters = pStoreInfo->OpenParameters.pbData;
  7051. assert(pvOpenParameters);
  7052. dwOpenFlags = pStoreInfo->dwOpenFlags;
  7053. pszOpenStoreProvider = pStoreInfo->pszOpenStoreProvider;
  7054. if (!(dwFlags & CERT_PHYSICAL_STORE_PREDEFINED_ENUM_FLAG)) {
  7055. // The parameters for the physical were read from the registry.
  7056. // Set the unsafe flag to alert the physical store provider to be
  7057. // called.
  7058. dwOpenFlags |= CERT_STORE_UNSAFE_PHYSICAL_FLAG;
  7059. // Check for potentially unsafe open flags
  7060. if (dwOpenFlags & (
  7061. CERT_STORE_NO_CRYPT_RELEASE_FLAG |
  7062. CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG |
  7063. CERT_STORE_DELETE_FLAG |
  7064. CERT_STORE_SHARE_STORE_FLAG |
  7065. CERT_STORE_SHARE_CONTEXT_FLAG |
  7066. CERT_STORE_MANIFOLD_FLAG |
  7067. CERT_STORE_BACKUP_RESTORE_FLAG
  7068. ))
  7069. goto UnsafeOpenPhysicalFlagsError;
  7070. // Following flags can be set
  7071. // CERT_STORE_SET_LOCALIZED_NAME_FLAG
  7072. // CERT_STORE_UNSAFE_PHYSICAL_FLAG
  7073. // CERT_STORE_ENUM_ARCHIVED_FLAG
  7074. // CERT_STORE_UPDATE_KEYID_FLAG
  7075. // CERT_STORE_READONLY_FLAG
  7076. // CERT_STORE_OPEN_EXISTING_FLAG
  7077. // CERT_STORE_CREATE_NEW_FLAG
  7078. // CERT_STORE_MAXIMUM_ALLOWED_FLAG
  7079. }
  7080. if (pOpenInfo->pwszComputerName || pOpenInfo->pwszServiceName) {
  7081. // Possibly insert the \\ComputerName\ServiceName before the
  7082. // OpenParameters
  7083. LPCWSTR pwszComputerName = NULL;
  7084. LPCWSTR pwszServiceName = NULL;
  7085. LPWSTR pwszSystemStore = (LPWSTR) pvOpenParameters;
  7086. DWORD dwSystemProviderFlags =
  7087. GetSystemProviderFlags(pszOpenStoreProvider);
  7088. if (0 != dwSystemProviderFlags) {
  7089. SYSTEM_NAME_INFO ProviderNameInfo;
  7090. DWORD cReqName;
  7091. if (dwOpenFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
  7092. goto RelocateFlagSetInPhysicalStoreInfoError;
  7093. if (dwSystemProviderFlags & ASCII_SYSTEM_PROVIDER_FLAG) {
  7094. if (NULL == (pwszSystemStore =
  7095. MkWStr((LPSTR) pvOpenParameters)))
  7096. goto OutOfMemory;
  7097. }
  7098. if (dwSystemProviderFlags & PHYSICAL_PROVIDER_FLAG)
  7099. cReqName = 2;
  7100. else
  7101. cReqName = 1;
  7102. ParseSystemStorePara(
  7103. pwszSystemStore,
  7104. dwOpenFlags,
  7105. cReqName,
  7106. &ProviderNameInfo // zero'ed on error
  7107. );
  7108. if (ProviderNameInfo.rgpwszName[COMPUTER_NAME_INDEX]) {
  7109. // Already has \\ComputerName\ prefix. For Services or
  7110. // Users, already has ServiceName\ prefix.
  7111. ;
  7112. } else if (ProviderNameInfo.rgpwszName[SYSTEM_NAME_INDEX]) {
  7113. // Needed above check if ParseSystemStorePara failed.
  7114. pwszComputerName = pOpenInfo->pwszComputerName;
  7115. if (pOpenInfo->pwszServiceName) {
  7116. // If the provider store is located in CURRENT_SERVICE or
  7117. // CURRENT_USER use outer store's SERVICE_NAME and change
  7118. // store location accordingly
  7119. DWORD dwOpenLocation =
  7120. dwOpenFlags & CERT_SYSTEM_STORE_LOCATION_MASK;
  7121. if (CERT_SYSTEM_STORE_CURRENT_SERVICE == dwOpenLocation) {
  7122. pwszServiceName = pOpenInfo->pwszServiceName;
  7123. dwOpenFlags =
  7124. (dwOpenFlags & ~CERT_SYSTEM_STORE_LOCATION_MASK) |
  7125. CERT_SYSTEM_STORE_SERVICES;
  7126. } else if (CERT_SYSTEM_STORE_CURRENT_USER ==
  7127. dwOpenLocation) {
  7128. pwszServiceName = pOpenInfo->pwszServiceName;
  7129. dwOpenFlags =
  7130. (dwOpenFlags & ~CERT_SYSTEM_STORE_LOCATION_MASK) |
  7131. CERT_SYSTEM_STORE_USERS;
  7132. }
  7133. }
  7134. }
  7135. FreeSystemNameInfo(&ProviderNameInfo);
  7136. } else if (pStoreInfo->dwFlags &
  7137. CERT_PHYSICAL_STORE_INSERT_COMPUTER_NAME_ENABLE_FLAG)
  7138. pwszComputerName = pOpenInfo->pwszComputerName;
  7139. if (pwszComputerName || pwszServiceName) {
  7140. // Insert \\ComputerName\ServiceName before and re-format
  7141. // open parameters
  7142. LPCWSTR rgpwszName[3];
  7143. SYSTEM_NAME_GROUP NameGroup;
  7144. assert(pwszSystemStore);
  7145. NameGroup.cName = 3;
  7146. NameGroup.rgpwszName = rgpwszName;
  7147. rgpwszName[0] = pwszComputerName;
  7148. rgpwszName[1] = pwszServiceName;
  7149. rgpwszName[2] = pwszSystemStore;
  7150. pwszRemoteOpenParameters = FormatSystemNamePath(1, &NameGroup);
  7151. pvOpenParameters = pwszRemoteOpenParameters;
  7152. if (dwSystemProviderFlags & ASCII_SYSTEM_PROVIDER_FLAG)
  7153. pszOpenStoreProvider = ChangeAsciiToUnicodeProvider(
  7154. pszOpenStoreProvider);
  7155. }
  7156. if (dwSystemProviderFlags & ASCII_SYSTEM_PROVIDER_FLAG) {
  7157. FreeWStr(pwszSystemStore);
  7158. if (NULL == pszOpenStoreProvider)
  7159. goto UnableToChangeToUnicodeProvider;
  7160. }
  7161. if (NULL == pvOpenParameters)
  7162. goto FormatSystemNamePathError;
  7163. }
  7164. if (NULL != pOpenInfo->hKeyBase &&
  7165. 0 != GetSystemProviderFlags(pszOpenStoreProvider)) {
  7166. if (dwOpenFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
  7167. goto RelocateFlagSetInPhysicalStoreInfoError;
  7168. // Inherit outer store's hKeyBase and convert to a relocated
  7169. // physical store
  7170. RelocateOpenParameters.hKeyBase = pOpenInfo->hKeyBase;
  7171. RelocateOpenParameters.pvSystemStore = pvOpenParameters;
  7172. pvOpenParameters = &RelocateOpenParameters;
  7173. dwOpenFlags |= CERT_SYSTEM_STORE_RELOCATE_FLAG;
  7174. }
  7175. if (NULL == (hPhysicalStore = CertOpenStore(
  7176. pszOpenStoreProvider,
  7177. pStoreInfo->dwOpenEncodingType,
  7178. 0, // hCryptProv
  7179. dwOpenFlags | (pOpenInfo->dwFlags &
  7180. (CERT_STORE_READONLY_FLAG |
  7181. CERT_STORE_OPEN_EXISTING_FLAG |
  7182. CERT_STORE_MANIFOLD_FLAG |
  7183. CERT_STORE_SHARE_CONTEXT_FLAG |
  7184. CERT_STORE_SHARE_STORE_FLAG |
  7185. CERT_STORE_BACKUP_RESTORE_FLAG |
  7186. CERT_STORE_UPDATE_KEYID_FLAG |
  7187. CERT_STORE_ENUM_ARCHIVED_FLAG)),
  7188. pvOpenParameters))) {
  7189. DWORD dwErr = GetLastError();
  7190. if (ERROR_FILE_NOT_FOUND == dwErr || ERROR_PROC_NOT_FOUND == dwErr ||
  7191. ERROR_GEN_FAILURE == dwErr) {
  7192. if (pOpenInfo->pwszPhysicalName &&
  7193. (dwFlags & CERT_PHYSICAL_STORE_PREDEFINED_ENUM_FLAG)) {
  7194. // For a predefined physical convert to an empty collection
  7195. CertAddStoreToCollection(
  7196. pOpenInfo->hCollectionStore,
  7197. NULL, // hSiblingStore, NULL implies convert only
  7198. 0, // dwFlags
  7199. 0 // dwPriority
  7200. );
  7201. goto OpenReturn;
  7202. } else
  7203. goto SuccessReturn;
  7204. } else
  7205. goto OpenPhysicalStoreError;
  7206. }
  7207. dwAddFlags = pStoreInfo->dwFlags;
  7208. if ((dwOpenFlags & CERT_STORE_MAXIMUM_ALLOWED_FLAG) &&
  7209. 0 == (dwAddFlags & CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG) &&
  7210. pOpenInfo->pwszPhysicalName) {
  7211. DWORD dwAccessStateFlags;
  7212. DWORD cbData = sizeof(dwAccessStateFlags);
  7213. if (CertGetStoreProperty(
  7214. hPhysicalStore,
  7215. CERT_ACCESS_STATE_PROP_ID,
  7216. &dwAccessStateFlags,
  7217. &cbData
  7218. )) {
  7219. if (dwAccessStateFlags & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG)
  7220. dwAddFlags |= CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG;
  7221. }
  7222. }
  7223. if (!CertAddStoreToCollection(
  7224. pOpenInfo->hCollectionStore,
  7225. hPhysicalStore,
  7226. dwAddFlags,
  7227. pStoreInfo->dwPriority))
  7228. goto AddStoreToCollectionError;
  7229. OpenReturn:
  7230. pOpenInfo->fDidOpen = TRUE;
  7231. SuccessReturn:
  7232. fResult = TRUE;
  7233. CommonReturn:
  7234. PkiFree(pwszRemoteOpenParameters);
  7235. if (hPhysicalStore)
  7236. CertCloseStore(hPhysicalStore, 0);
  7237. return fResult;
  7238. ErrorReturn:
  7239. fResult = FALSE;
  7240. goto CommonReturn;
  7241. TRACE_ERROR(OutOfMemory)
  7242. SET_ERROR(UnableToChangeToUnicodeProvider, E_UNEXPECTED)
  7243. TRACE_ERROR(OpenPhysicalStoreError)
  7244. TRACE_ERROR(AddStoreToCollectionError)
  7245. TRACE_ERROR(FormatSystemNamePathError)
  7246. SET_ERROR(UnsafeOpenPhysicalFlagsError, E_INVALIDARG)
  7247. SET_ERROR(RelocateFlagSetInPhysicalStoreInfoError, E_INVALIDARG)
  7248. }
  7249. //+-------------------------------------------------------------------------
  7250. // Open the system store provider (unicode version)
  7251. //
  7252. // Open the system store specified by its name. For example,
  7253. // L"My".
  7254. //
  7255. // pvPara contains the LPCWSTR system store name.
  7256. //
  7257. // Note for an error return, the caller will free any certs, CRLs or CTLs
  7258. // successfully added to the store.
  7259. //--------------------------------------------------------------------------
  7260. BOOL
  7261. WINAPI
  7262. I_CertDllOpenSystemStoreProvW(
  7263. IN LPCSTR lpszStoreProvider,
  7264. IN DWORD dwEncodingType,
  7265. IN HCRYPTPROV hCryptProv,
  7266. IN DWORD dwFlags,
  7267. IN const void *pvPara,
  7268. IN HCERTSTORE hCertStore,
  7269. IN OUT PCERT_STORE_PROV_INFO pStoreProvInfo
  7270. )
  7271. {
  7272. BOOL fResult;
  7273. SYSTEM_NAME_INFO SystemNameInfo;
  7274. pStoreProvInfo->dwStoreProvFlags |= CERT_STORE_PROV_SYSTEM_STORE_FLAG;
  7275. if (IsLMSystemStoreLocationInRegistry(dwFlags))
  7276. pStoreProvInfo->dwStoreProvFlags |=
  7277. CERT_STORE_PROV_LM_SYSTEM_STORE_FLAG;
  7278. if (!IsSystemStoreLocationInRegistry(dwFlags)) {
  7279. void *pvFuncAddr;
  7280. assert(NULL == pStoreProvInfo->hStoreProvFuncAddr2);
  7281. if (!CryptGetOIDFunctionAddress(
  7282. rghFuncSet[OPEN_SYSTEM_STORE_PROV_FUNC_SET],
  7283. 0, // dwEncodingType,
  7284. GetSystemStoreLocationOID(dwFlags),
  7285. 0, // dwFlags
  7286. &pvFuncAddr,
  7287. &pStoreProvInfo->hStoreProvFuncAddr2))
  7288. return FALSE;
  7289. fResult = ((PFN_CERT_DLL_OPEN_STORE_PROV_FUNC) pvFuncAddr)(
  7290. lpszStoreProvider,
  7291. dwEncodingType,
  7292. hCryptProv,
  7293. dwFlags,
  7294. pvPara,
  7295. hCertStore,
  7296. pStoreProvInfo
  7297. );
  7298. // Note, hStoreProvFuncAddr2 is CryptFreeOIDFunctionAddress'ed by
  7299. // CertCloseStore()
  7300. return fResult;
  7301. }
  7302. if (dwFlags & CERT_STORE_UNSAFE_PHYSICAL_FLAG) {
  7303. if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) {
  7304. SetLastError((DWORD) E_INVALIDARG);
  7305. return FALSE;
  7306. }
  7307. dwFlags &= ~CERT_STORE_UNSAFE_PHYSICAL_FLAG;
  7308. }
  7309. if (!ParseSystemStorePara(
  7310. pvPara,
  7311. dwFlags,
  7312. 1, // cReqName
  7313. &SystemNameInfo)) // zero'ed on error
  7314. goto ParseSystemStoreParaError;
  7315. if (dwFlags & ~OPEN_SYS_FLAGS_MASK)
  7316. goto InvalidArg;
  7317. if (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG)
  7318. ILS_EnableBackupRestorePrivileges();
  7319. if (dwFlags & CERT_STORE_DELETE_FLAG) {
  7320. // Need to clear out CERT_STORE_NO_CRYPT_RELEASE_FLAG
  7321. if (!CertUnregisterSystemStore(
  7322. pvPara,
  7323. dwFlags & UNREGISTER_FLAGS_MASK
  7324. ))
  7325. goto UnregisterSystemStoreError;
  7326. pStoreProvInfo->dwStoreProvFlags |= CERT_STORE_PROV_DELETED_FLAG;
  7327. } else {
  7328. OPEN_PHYSICAL_STORE_INFO OpenInfo;
  7329. if (dwFlags & CERT_STORE_CREATE_NEW_FLAG) {
  7330. HKEY hKey;
  7331. if (NULL == (hKey = OpenSystemStore(pvPara, dwFlags)))
  7332. goto OpenSystemStoreError;
  7333. RegCloseKey(hKey);
  7334. dwFlags &= ~CERT_STORE_CREATE_NEW_FLAG;
  7335. }
  7336. OpenInfo.hCollectionStore = hCertStore;
  7337. OpenInfo.pwszComputerName =
  7338. SystemNameInfo.rgpwszName[COMPUTER_NAME_INDEX];
  7339. OpenInfo.pwszServiceName =
  7340. SystemNameInfo.rgpwszName[SERVICE_NAME_INDEX];
  7341. OpenInfo.pwszPhysicalName = NULL; // NULL implies any
  7342. OpenInfo.hKeyBase = SystemNameInfo.hKeyBase;
  7343. OpenInfo.dwFlags = dwFlags & ~CERT_STORE_SET_LOCALIZED_NAME_FLAG;
  7344. OpenInfo.fDidOpen = FALSE;
  7345. // Need to clear out CERT_STORE_NO_CRYPT_RELEASE_FLAG
  7346. if (!EnumPhysicalStore(
  7347. pvPara,
  7348. dwFlags & ENUM_FLAGS_MASK,
  7349. &OpenInfo,
  7350. OpenPhysicalStoreCallback
  7351. ))
  7352. goto EnumPhysicalStoreError;
  7353. if (!OpenInfo.fDidOpen) {
  7354. if (IsPredefinedSystemStore(
  7355. SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX], dwFlags))
  7356. // Convert to a collection store
  7357. CertAddStoreToCollection(
  7358. hCertStore,
  7359. NULL, // hSiblingStore, NULL implies convert only
  7360. 0, // dwFlags
  7361. 0 // dwPriority
  7362. );
  7363. else
  7364. goto PhysicalStoreNotFound;
  7365. }
  7366. if (dwFlags & CERT_STORE_SET_LOCALIZED_NAME_FLAG)
  7367. SetLocalizedNameStoreProperty(hCertStore, &SystemNameInfo);
  7368. }
  7369. fResult = TRUE;
  7370. CommonReturn:
  7371. FreeSystemNameInfo(&SystemNameInfo);
  7372. return fResult;
  7373. ErrorReturn:
  7374. fResult = FALSE;
  7375. goto CommonReturn;
  7376. TRACE_ERROR(ParseSystemStoreParaError)
  7377. SET_ERROR(InvalidArg, E_INVALIDARG)
  7378. TRACE_ERROR(UnregisterSystemStoreError)
  7379. TRACE_ERROR(OpenSystemStoreError)
  7380. TRACE_ERROR(EnumPhysicalStoreError)
  7381. SET_ERROR(PhysicalStoreNotFound, ERROR_FILE_NOT_FOUND)
  7382. }
  7383. //+-------------------------------------------------------------------------
  7384. // Open the system store provider (ascii version)
  7385. //
  7386. // Open the system store specified by its name. For example,
  7387. // "My".
  7388. //
  7389. // pvPara contains the LPCSTR system store name.
  7390. //
  7391. // Note for an error return, the caller will free any certs or CRLs
  7392. // successfully added to the store.
  7393. //--------------------------------------------------------------------------
  7394. BOOL
  7395. WINAPI
  7396. I_CertDllOpenSystemStoreProvA(
  7397. IN LPCSTR lpszStoreProvider,
  7398. IN DWORD dwEncodingType,
  7399. IN HCRYPTPROV hCryptProv,
  7400. IN DWORD dwFlags,
  7401. IN const void *pvPara,
  7402. IN HCERTSTORE hCertStore,
  7403. IN OUT PCERT_STORE_PROV_INFO pStoreProvInfo
  7404. )
  7405. {
  7406. BOOL fResult;
  7407. LPCSTR pszStoreName; // not allocated
  7408. LPWSTR pwszStoreName;
  7409. CERT_SYSTEM_STORE_RELOCATE_PARA RelocatePara;
  7410. if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) {
  7411. PCERT_SYSTEM_STORE_RELOCATE_PARA pInPara;
  7412. if (dwFlags & CERT_STORE_UNSAFE_PHYSICAL_FLAG) {
  7413. SetLastError((DWORD) E_INVALIDARG);
  7414. return FALSE;
  7415. }
  7416. assert(pvPara);
  7417. pInPara = (PCERT_SYSTEM_STORE_RELOCATE_PARA) pvPara;
  7418. RelocatePara.hKeyBase = pInPara->hKeyBase;
  7419. pszStoreName = pInPara->pszSystemStore;
  7420. } else
  7421. pszStoreName = (LPCSTR) pvPara;
  7422. assert(pszStoreName);
  7423. if (NULL == (pwszStoreName = MkWStr((LPSTR) pszStoreName)))
  7424. fResult = FALSE;
  7425. else {
  7426. const void *pvParaW;
  7427. if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) {
  7428. RelocatePara.pwszSystemStore = pwszStoreName;
  7429. pvParaW = (const void *) &RelocatePara;
  7430. } else
  7431. pvParaW = (const void *) pwszStoreName;
  7432. fResult = I_CertDllOpenSystemStoreProvW(
  7433. NULL, // lpszStoreProvider
  7434. dwEncodingType,
  7435. hCryptProv,
  7436. dwFlags,
  7437. pvParaW,
  7438. hCertStore,
  7439. pStoreProvInfo
  7440. );
  7441. FreeWStr(pwszStoreName);
  7442. }
  7443. return fResult;
  7444. }
  7445. //+-------------------------------------------------------------------------
  7446. // Open the physical store provider (unicode version)
  7447. //
  7448. // Open the physical store in the specified system store. For example,
  7449. // L"My\.Default".
  7450. //
  7451. // pvPara contains the LPCWSTR pwszSystemAndPhysicalName which is the
  7452. // concatenation of the system and physical store names with an
  7453. // intervening "\".
  7454. //
  7455. // Note for an error return, the caller will free any certs, CRLs or CTLs
  7456. // successfully added to the store.
  7457. //--------------------------------------------------------------------------
  7458. BOOL
  7459. WINAPI
  7460. I_CertDllOpenPhysicalStoreProvW(
  7461. IN LPCSTR lpszStoreProvider,
  7462. IN DWORD dwEncodingType,
  7463. IN HCRYPTPROV hCryptProv,
  7464. IN DWORD dwFlags,
  7465. IN const void *pvPara,
  7466. IN HCERTSTORE hCertStore,
  7467. IN OUT PCERT_STORE_PROV_INFO pStoreProvInfo
  7468. )
  7469. {
  7470. BOOL fResult;
  7471. LPCWSTR pwszBoth; // not allocated
  7472. LPWSTR pwszSystem = NULL; // allocated
  7473. DWORD cchSystem;
  7474. LPCWSTR pwszPhysical; // not allocated
  7475. void *pvSystemPara; // not allocated
  7476. CERT_SYSTEM_STORE_RELOCATE_PARA RelocatePara;
  7477. if (dwFlags & CERT_STORE_UNSAFE_PHYSICAL_FLAG) {
  7478. if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
  7479. goto InvalidArg;
  7480. dwFlags &= ~CERT_STORE_UNSAFE_PHYSICAL_FLAG;
  7481. }
  7482. if (dwFlags & ~OPEN_PHY_FLAGS_MASK)
  7483. goto InvalidArg;
  7484. if (dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG)
  7485. ILS_EnableBackupRestorePrivileges();
  7486. if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) {
  7487. PCERT_SYSTEM_STORE_RELOCATE_PARA pInPara;
  7488. if (NULL == pvPara)
  7489. goto InvalidArg;
  7490. pInPara = (PCERT_SYSTEM_STORE_RELOCATE_PARA) pvPara;
  7491. pwszBoth = pInPara->pwszSystemStore;
  7492. } else
  7493. pwszBoth = (LPCWSTR) pvPara;
  7494. // Extract the system and physical name components by starting at
  7495. // the end and searching backwards for the first "\"
  7496. if (NULL == pwszBoth)
  7497. goto InvalidArg;
  7498. pwszPhysical = pwszBoth + wcslen(pwszBoth);
  7499. while (pwszPhysical > pwszBoth && L'\\' != *pwszPhysical)
  7500. pwszPhysical--;
  7501. cchSystem = (DWORD)(pwszPhysical - pwszBoth);
  7502. pwszPhysical++; // advance past "\"
  7503. if (0 < cchSystem && L'\0' != *pwszPhysical) {
  7504. if (NULL == (pwszSystem = ILS_AllocAndCopyString(pwszBoth, cchSystem)))
  7505. goto OutOfMemory;
  7506. } else
  7507. // Missing "\" or empty System or Physical Name.
  7508. goto InvalidArg;
  7509. if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) {
  7510. PCERT_SYSTEM_STORE_RELOCATE_PARA pInPara =
  7511. (PCERT_SYSTEM_STORE_RELOCATE_PARA) pvPara;
  7512. RelocatePara.hKeyBase = pInPara->hKeyBase;
  7513. RelocatePara.pwszSystemStore = pwszSystem;
  7514. pvSystemPara = &RelocatePara;
  7515. } else
  7516. pvSystemPara = pwszSystem;
  7517. if (dwFlags & CERT_STORE_DELETE_FLAG) {
  7518. // Need to clear out CERT_STORE_NO_CRYPT_RELEASE_FLAG
  7519. if (!CertUnregisterPhysicalStore(
  7520. pvSystemPara,
  7521. dwFlags & UNREGISTER_FLAGS_MASK,
  7522. pwszPhysical
  7523. ))
  7524. goto UnregisterPhysicalStoreError;
  7525. pStoreProvInfo->dwStoreProvFlags |= CERT_STORE_PROV_DELETED_FLAG;
  7526. } else {
  7527. SYSTEM_NAME_INFO SystemNameInfo;
  7528. OPEN_PHYSICAL_STORE_INFO OpenInfo;
  7529. // Note, already removed PhysicalName above. That's why
  7530. // cReqName is 1 and not 2.
  7531. if (!ParseSystemStorePara(
  7532. pvSystemPara,
  7533. dwFlags,
  7534. 1, // cReqName
  7535. &SystemNameInfo)) // zero'ed on error
  7536. goto ParseSystemStoreParaError;
  7537. OpenInfo.hCollectionStore = hCertStore;
  7538. OpenInfo.pwszComputerName =
  7539. SystemNameInfo.rgpwszName[COMPUTER_NAME_INDEX];
  7540. OpenInfo.pwszServiceName =
  7541. SystemNameInfo.rgpwszName[SERVICE_NAME_INDEX];
  7542. OpenInfo.pwszPhysicalName = pwszPhysical;
  7543. OpenInfo.hKeyBase = SystemNameInfo.hKeyBase;
  7544. OpenInfo.dwFlags = dwFlags & ~CERT_STORE_SET_LOCALIZED_NAME_FLAG;
  7545. OpenInfo.fDidOpen = FALSE;
  7546. // For .Default physical store, allow the store to be created.
  7547. // Otherwise, the store must already exist.
  7548. if (0 != _wcsicmp(CERT_PHYSICAL_STORE_DEFAULT_NAME, pwszPhysical))
  7549. dwFlags |= CERT_STORE_OPEN_EXISTING_FLAG |
  7550. CERT_STORE_READONLY_FLAG;
  7551. // Need to clear out CERT_STORE_NO_CRYPT_RELEASE_FLAG
  7552. fResult = EnumPhysicalStore(
  7553. pvSystemPara,
  7554. dwFlags & ENUM_FLAGS_MASK,
  7555. &OpenInfo,
  7556. OpenPhysicalStoreCallback
  7557. );
  7558. if (dwFlags & CERT_STORE_SET_LOCALIZED_NAME_FLAG) {
  7559. assert(NULL == SystemNameInfo.rgpwszName[PHYSICAL_NAME_INDEX]);
  7560. SystemNameInfo.rgpwszName[PHYSICAL_NAME_INDEX] =
  7561. (LPWSTR) pwszPhysical;
  7562. SetLocalizedNameStoreProperty(hCertStore, &SystemNameInfo);
  7563. SystemNameInfo.rgpwszName[PHYSICAL_NAME_INDEX] = NULL;
  7564. }
  7565. FreeSystemNameInfo(&SystemNameInfo);
  7566. if (!fResult)
  7567. goto EnumPhysicalStoreError;
  7568. if (!OpenInfo.fDidOpen)
  7569. goto PhysicalStoreNotFound;
  7570. }
  7571. pStoreProvInfo->dwStoreProvFlags |= CERT_STORE_PROV_SYSTEM_STORE_FLAG;
  7572. if (IsLMSystemStoreLocationInRegistry(dwFlags))
  7573. pStoreProvInfo->dwStoreProvFlags |=
  7574. CERT_STORE_PROV_LM_SYSTEM_STORE_FLAG;
  7575. fResult = TRUE;
  7576. CommonReturn:
  7577. PkiFree(pwszSystem);
  7578. return fResult;
  7579. ErrorReturn:
  7580. fResult = FALSE;
  7581. goto CommonReturn;
  7582. TRACE_ERROR(OutOfMemory)
  7583. SET_ERROR(InvalidArg, E_INVALIDARG)
  7584. TRACE_ERROR(UnregisterPhysicalStoreError)
  7585. TRACE_ERROR(ParseSystemStoreParaError)
  7586. TRACE_ERROR(EnumPhysicalStoreError)
  7587. SET_ERROR(PhysicalStoreNotFound, ERROR_FILE_NOT_FOUND)
  7588. }
  7589. //+=========================================================================
  7590. // "ROOT" STORE
  7591. //==========================================================================
  7592. //+-------------------------------------------------------------------------
  7593. // For "Root": prompt before adding a cert.
  7594. //--------------------------------------------------------------------------
  7595. STATIC BOOL WINAPI RootStoreProvWriteCert(
  7596. IN HCERTSTOREPROV hStoreProv,
  7597. IN PCCERT_CONTEXT pCertContext,
  7598. IN DWORD dwFlags
  7599. )
  7600. {
  7601. BOOL fResult;
  7602. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  7603. PCCERT_CONTEXT pProvCertContext = NULL;
  7604. BYTE *pbSerializedElement = NULL;
  7605. DWORD cbSerializedElement;
  7606. assert(pRegStore);
  7607. if (pRegStore->dwFlags & CERT_STORE_READONLY_FLAG)
  7608. goto AccessDenied;
  7609. if (pRegStore->fProtected) {
  7610. if (!CertSerializeCertificateStoreElement(
  7611. pCertContext,
  7612. 0, // dwFlags
  7613. NULL, // pbElement
  7614. &cbSerializedElement
  7615. )) goto SerializeCertError;
  7616. if (NULL == (pbSerializedElement = (BYTE *) PkiNonzeroAlloc(
  7617. cbSerializedElement)))
  7618. goto OutOfMemory;
  7619. if (!CertSerializeCertificateStoreElement(
  7620. pCertContext,
  7621. 0, // dwFlags
  7622. pbSerializedElement,
  7623. &cbSerializedElement
  7624. )) goto SerializeCertError;
  7625. fResult = I_CertProtectFunction(
  7626. CERT_PROT_ADD_ROOT_FUNC_ID,
  7627. 0, // dwFlags
  7628. NULL, // pwszIn
  7629. pbSerializedElement,
  7630. cbSerializedElement,
  7631. NULL, // ppbOut
  7632. NULL // pcbOut
  7633. );
  7634. } else {
  7635. // If the certificate doesn't already exist, then, prompt the user
  7636. if (!RegStoreProvReadCert(
  7637. hStoreProv,
  7638. pCertContext,
  7639. 0, // dwFlags
  7640. &pProvCertContext)) {
  7641. if (IDYES != IPR_ProtectedRootMessageBox(
  7642. NULL, // hRpc
  7643. pCertContext,
  7644. IDS_ROOT_MSG_BOX_ADD_ACTION,
  7645. 0))
  7646. goto Cancelled;
  7647. }
  7648. fResult = RegStoreProvWriteCert(
  7649. hStoreProv,
  7650. pCertContext,
  7651. dwFlags
  7652. );
  7653. }
  7654. CommonReturn:
  7655. CertFreeCertificateContext(pProvCertContext);
  7656. PkiFree(pbSerializedElement);
  7657. return fResult;
  7658. ErrorReturn:
  7659. fResult = FALSE;
  7660. goto CommonReturn;
  7661. SET_ERROR(AccessDenied, E_ACCESSDENIED)
  7662. SET_ERROR(Cancelled, ERROR_CANCELLED)
  7663. TRACE_ERROR(SerializeCertError)
  7664. TRACE_ERROR(OutOfMemory)
  7665. }
  7666. //+-------------------------------------------------------------------------
  7667. // For "Root": prompt before deleting a cert.
  7668. //--------------------------------------------------------------------------
  7669. STATIC BOOL WINAPI RootStoreProvDeleteCert(
  7670. IN HCERTSTOREPROV hStoreProv,
  7671. IN PCCERT_CONTEXT pCertContext,
  7672. IN DWORD dwFlags
  7673. )
  7674. {
  7675. BOOL fResult;
  7676. PREG_STORE pRegStore = (PREG_STORE) hStoreProv;
  7677. PCCERT_CONTEXT pProvCertContext = NULL;
  7678. assert(pRegStore);
  7679. if (IsInResync(pRegStore))
  7680. // Only delete from store cache, not from registry
  7681. return TRUE;
  7682. if (pRegStore->dwFlags & CERT_STORE_READONLY_FLAG)
  7683. goto AccessDenied;
  7684. if (pRegStore->fProtected) {
  7685. BYTE rgbHash[MAX_HASH_LEN];
  7686. DWORD cbHash = MAX_HASH_LEN;
  7687. // get the thumbprint
  7688. if(!CertGetCertificateContextProperty(
  7689. pCertContext,
  7690. CERT_SHA1_HASH_PROP_ID,
  7691. rgbHash,
  7692. &cbHash
  7693. )) goto GetCertHashPropError;
  7694. fResult = I_CertProtectFunction(
  7695. CERT_PROT_DELETE_ROOT_FUNC_ID,
  7696. 0, // dwFlags
  7697. NULL, // pwszIn
  7698. rgbHash,
  7699. cbHash,
  7700. NULL, // ppbOut
  7701. NULL // pcbOut
  7702. );
  7703. } else {
  7704. // Prompt the user before deleting
  7705. if (RegStoreProvReadCert(
  7706. hStoreProv,
  7707. pCertContext,
  7708. 0, // dwFlags
  7709. &pProvCertContext)) {
  7710. if (IDYES != IPR_ProtectedRootMessageBox(
  7711. NULL, // hRpc
  7712. pCertContext,
  7713. IDS_ROOT_MSG_BOX_DELETE_ACTION,
  7714. 0))
  7715. goto Cancelled;
  7716. fResult = RegStoreProvDeleteCert(
  7717. hStoreProv,
  7718. pCertContext,
  7719. dwFlags
  7720. );
  7721. } else
  7722. fResult = TRUE;
  7723. }
  7724. CommonReturn:
  7725. CertFreeCertificateContext(pProvCertContext);
  7726. return fResult;
  7727. ErrorReturn:
  7728. fResult = FALSE;
  7729. goto CommonReturn;
  7730. SET_ERROR(AccessDenied, E_ACCESSDENIED)
  7731. SET_ERROR(Cancelled, ERROR_CANCELLED)
  7732. TRACE_ERROR(GetCertHashPropError)
  7733. }
  7734. //+=========================================================================
  7735. // Change Notify Support Functions
  7736. //==========================================================================
  7737. #if 0
  7738. typedef VOID (NTAPI * WAITORTIMERCALLBACKFUNC) (PVOID, BOOLEAN );
  7739. typedef WAITORTIMERCALLBACKFUNC WAITORTIMERCALLBACK ;
  7740. WINBASEAPI
  7741. BOOL
  7742. WINAPI
  7743. RegisterWaitForSingleObject(
  7744. PHANDLE hNewWaitObject,
  7745. HANDLE hObject,
  7746. WAITORTIMERCALLBACK Callback,
  7747. PVOID Context,
  7748. ULONG dwMilliseconds,
  7749. ULONG dwFlags
  7750. );
  7751. WINBASEAPI
  7752. BOOL
  7753. WINAPI
  7754. UnregisterWait(
  7755. HANDLE WaitHandle
  7756. );
  7757. WINBASEAPI
  7758. BOOL
  7759. WINAPI
  7760. UnregisterWaitEx(
  7761. HANDLE WaitHandle,
  7762. HANDLE CompletionEvent // INVALID_HANDLE_VALUE => create event
  7763. // to wait for
  7764. );
  7765. #endif
  7766. typedef BOOL (WINAPI *PFN_ILS_REGISTER_WAIT_FOR_SINGLE_OBJECT)(
  7767. PHANDLE hNewWaitObject,
  7768. HANDLE hObject,
  7769. ILS_WAITORTIMERCALLBACK Callback,
  7770. PVOID Context,
  7771. ULONG dwMilliseconds,
  7772. ULONG dwFlags
  7773. );
  7774. typedef BOOL (WINAPI *PFN_ILS_UNREGISTER_WAIT_EX)(
  7775. HANDLE WaitHandle,
  7776. HANDLE CompletionEvent // INVALID_HANDLE_VALUE => create event
  7777. // to wait for
  7778. );
  7779. #define sz_KERNEL32_DLL "kernel32.dll"
  7780. #define sz_RegisterWaitForSingleObject "RegisterWaitForSingleObject"
  7781. #define sz_UnregisterWaitEx "UnregisterWaitEx"
  7782. static HMODULE hKernel32Dll = NULL;
  7783. PFN_ILS_REGISTER_WAIT_FOR_SINGLE_OBJECT pfnILS_RegisterWaitForSingleObject;
  7784. PFN_ILS_UNREGISTER_WAIT_EX pfnILS_UnregisterWaitEx;
  7785. #define ILS_REG_WAIT_EXIT_HANDLE_INDEX 0
  7786. #define ILS_REG_WAIT_OBJECT_HANDLE_INDEX 1
  7787. #define ILS_REG_WAIT_HANDLE_COUNT 2
  7788. typedef struct _ILS_REG_WAIT_INFO {
  7789. HANDLE hThread;
  7790. DWORD dwThreadId;
  7791. HANDLE rghWait[ILS_REG_WAIT_HANDLE_COUNT];
  7792. ILS_WAITORTIMERCALLBACK Callback;
  7793. PVOID Context;
  7794. ULONG dwMilliseconds;
  7795. HANDLE hDoneEvent;
  7796. } ILS_REG_WAIT_INFO, *PILS_REG_WAIT_INFO;
  7797. DWORD WINAPI ILS_WaitForThreadProc(
  7798. LPVOID lpThreadParameter
  7799. )
  7800. {
  7801. PILS_REG_WAIT_INFO pWaitInfo = (PILS_REG_WAIT_INFO) lpThreadParameter;
  7802. DWORD cWait;
  7803. if (pWaitInfo->rghWait[ILS_REG_WAIT_OBJECT_HANDLE_INDEX])
  7804. cWait = ILS_REG_WAIT_HANDLE_COUNT;
  7805. else
  7806. cWait = ILS_REG_WAIT_HANDLE_COUNT - 1;
  7807. while (TRUE) {
  7808. DWORD dwWaitObject;
  7809. dwWaitObject = WaitForMultipleObjectsEx(
  7810. cWait,
  7811. pWaitInfo->rghWait,
  7812. FALSE, // bWaitAll
  7813. pWaitInfo->dwMilliseconds,
  7814. FALSE // bAlertable
  7815. );
  7816. switch (dwWaitObject) {
  7817. case WAIT_OBJECT_0 + ILS_REG_WAIT_OBJECT_HANDLE_INDEX:
  7818. pWaitInfo->Callback(pWaitInfo->Context, TRUE);
  7819. break;
  7820. case WAIT_TIMEOUT:
  7821. pWaitInfo->Callback(pWaitInfo->Context, FALSE);
  7822. break;
  7823. case WAIT_OBJECT_0 + ILS_REG_WAIT_EXIT_HANDLE_INDEX:
  7824. if (pWaitInfo->hDoneEvent) {
  7825. SetEvent(pWaitInfo->hDoneEvent);
  7826. }
  7827. goto CommonReturn;
  7828. break;
  7829. default:
  7830. goto InvalidWaitForObject;
  7831. }
  7832. }
  7833. CommonReturn:
  7834. return 0;
  7835. ErrorReturn:
  7836. goto CommonReturn;
  7837. TRACE_ERROR(InvalidWaitForObject)
  7838. }
  7839. BOOL
  7840. WINAPI
  7841. ILS_RegisterWaitForSingleObject(
  7842. PHANDLE hNewWaitObject,
  7843. HANDLE hObject,
  7844. ILS_WAITORTIMERCALLBACK Callback,
  7845. PVOID Context,
  7846. ULONG dwMilliseconds,
  7847. ULONG dwFlags
  7848. )
  7849. {
  7850. BOOL fResult;
  7851. PILS_REG_WAIT_INFO pWaitInfo = NULL;
  7852. HANDLE hDupObject = NULL;
  7853. if ( dwMilliseconds == 0 )
  7854. {
  7855. dwMilliseconds = INFINITE ;
  7856. }
  7857. if (NULL == (pWaitInfo = (PILS_REG_WAIT_INFO) PkiZeroAlloc(
  7858. sizeof(ILS_REG_WAIT_INFO))))
  7859. goto OutOfMemory;
  7860. if (hObject) {
  7861. if (!DuplicateHandle(
  7862. GetCurrentProcess(),
  7863. hObject,
  7864. GetCurrentProcess(),
  7865. &hDupObject,
  7866. 0, // dwDesiredAccess
  7867. FALSE, // bInheritHandle
  7868. DUPLICATE_SAME_ACCESS
  7869. ) || NULL == hDupObject)
  7870. goto DuplicateEventError;
  7871. pWaitInfo->rghWait[ILS_REG_WAIT_OBJECT_HANDLE_INDEX] = hDupObject;
  7872. }
  7873. pWaitInfo->Callback = Callback;
  7874. pWaitInfo->Context = Context;
  7875. pWaitInfo->dwMilliseconds = dwMilliseconds;
  7876. // Create event to be signaled to terminate the thread
  7877. if (NULL == (pWaitInfo->rghWait[ILS_REG_WAIT_EXIT_HANDLE_INDEX] =
  7878. CreateEvent(
  7879. NULL, // lpsa
  7880. FALSE, // fManualReset
  7881. FALSE, // fInitialState
  7882. NULL))) // lpszEventName
  7883. goto CreateThreadExitEventError;
  7884. // Create the thread to do the wait for
  7885. if (NULL == (pWaitInfo->hThread = CreateThread(
  7886. NULL, // lpThreadAttributes
  7887. 0, // dwStackSize
  7888. ILS_WaitForThreadProc,
  7889. pWaitInfo,
  7890. 0, // dwCreationFlags
  7891. &pWaitInfo->dwThreadId
  7892. )))
  7893. goto CreateThreadError;
  7894. fResult = TRUE;
  7895. CommonReturn:
  7896. *hNewWaitObject = (HANDLE) pWaitInfo;
  7897. return fResult;
  7898. ErrorReturn:
  7899. if (pWaitInfo) {
  7900. DWORD dwErr = GetLastError();
  7901. for (DWORD i = 0; i < ILS_REG_WAIT_HANDLE_COUNT; i++) {
  7902. if (pWaitInfo->rghWait[i])
  7903. CloseHandle(pWaitInfo->rghWait[i]);
  7904. }
  7905. PkiFree(pWaitInfo);
  7906. pWaitInfo = NULL;
  7907. SetLastError(dwErr);
  7908. }
  7909. fResult = FALSE;
  7910. goto CommonReturn;
  7911. TRACE_ERROR(OutOfMemory)
  7912. TRACE_ERROR(DuplicateEventError)
  7913. TRACE_ERROR(CreateThreadExitEventError)
  7914. TRACE_ERROR(CreateThreadError)
  7915. }
  7916. BOOL
  7917. WINAPI
  7918. ILS_UnregisterWait(
  7919. HANDLE WaitHandle
  7920. )
  7921. {
  7922. PILS_REG_WAIT_INFO pWaitInfo = (PILS_REG_WAIT_INFO) WaitHandle;
  7923. if (pWaitInfo->dwThreadId != GetCurrentThreadId()) {
  7924. DWORD cWait;
  7925. HANDLE rghWait[2];
  7926. // On Win98 at ProcessDetach it might switch to one of the
  7927. // threads we created.
  7928. //
  7929. // Alternatively, we may be called from the callback itself via
  7930. // ILS_ExitWait()
  7931. // Create event to be signaled by thread when its done executing
  7932. pWaitInfo->hDoneEvent = CreateEvent(
  7933. NULL,
  7934. FALSE,
  7935. FALSE,
  7936. NULL
  7937. );
  7938. // Wake up the wait for thread.
  7939. SetEvent(pWaitInfo->rghWait[ILS_REG_WAIT_EXIT_HANDLE_INDEX]);
  7940. // Wait for either the thread to exit or the thread to signal us.
  7941. // We can't just wait on the thread handle because the
  7942. // loader lock might already be held if we are being called
  7943. // from a PROCESS_DETACH (in WinINet's DllMain for example).
  7944. rghWait[0] = pWaitInfo->hThread;
  7945. if (pWaitInfo->hDoneEvent) {
  7946. rghWait[1] = pWaitInfo->hDoneEvent;
  7947. cWait = 2;
  7948. } else {
  7949. cWait = 1;
  7950. }
  7951. WaitForMultipleObjectsEx(
  7952. cWait,
  7953. rghWait,
  7954. FALSE, // bWaitAll
  7955. INFINITE,
  7956. FALSE // bAlertable
  7957. );
  7958. if (pWaitInfo->hDoneEvent)
  7959. CloseHandle(pWaitInfo->hDoneEvent);
  7960. }
  7961. CloseHandle(pWaitInfo->hThread);
  7962. for (DWORD i = 0; i < ILS_REG_WAIT_HANDLE_COUNT; i++) {
  7963. if (pWaitInfo->rghWait[i])
  7964. CloseHandle(pWaitInfo->rghWait[i]);
  7965. }
  7966. PkiFree(pWaitInfo);
  7967. return TRUE;
  7968. }
  7969. BOOL
  7970. WINAPI
  7971. ILS_UnregisterWaitEx(
  7972. HANDLE WaitHandle,
  7973. HANDLE CompletionEvent // INVALID_HANDLE_VALUE => create event
  7974. // to wait for
  7975. )
  7976. {
  7977. assert(CompletionEvent == INVALID_HANDLE_VALUE);
  7978. return ILS_UnregisterWait(WaitHandle);
  7979. }
  7980. // Called from the callback function
  7981. BOOL
  7982. WINAPI
  7983. ILS_ExitWait(
  7984. HANDLE WaitHandle,
  7985. HMODULE hLibModule
  7986. )
  7987. {
  7988. ILS_UnregisterWait(WaitHandle);
  7989. if (hLibModule)
  7990. FreeLibraryAndExitThread(hLibModule, 0);
  7991. else
  7992. ExitThread(0);
  7993. }
  7994. STATIC void RegWaitForProcessAttach()
  7995. {
  7996. if (NULL == (hKernel32Dll = LoadLibraryA(sz_KERNEL32_DLL)))
  7997. goto LoadKernel32DllError;
  7998. if (NULL == (pfnILS_RegisterWaitForSingleObject =
  7999. (PFN_ILS_REGISTER_WAIT_FOR_SINGLE_OBJECT) GetProcAddress(
  8000. hKernel32Dll, sz_RegisterWaitForSingleObject)))
  8001. goto GetRegisterWaitForSingleObjectProcAddressError;
  8002. if (NULL == (pfnILS_UnregisterWaitEx =
  8003. (PFN_ILS_UNREGISTER_WAIT_EX) GetProcAddress(
  8004. hKernel32Dll, sz_UnregisterWaitEx)))
  8005. goto GetUnregisterWaitExProcAddressError;
  8006. CommonReturn:
  8007. return;
  8008. ErrorReturn:
  8009. pfnILS_RegisterWaitForSingleObject = ILS_RegisterWaitForSingleObject;
  8010. pfnILS_UnregisterWaitEx = ILS_UnregisterWaitEx;
  8011. goto CommonReturn;
  8012. TRACE_ERROR(LoadKernel32DllError)
  8013. TRACE_ERROR(GetRegisterWaitForSingleObjectProcAddressError)
  8014. TRACE_ERROR(GetUnregisterWaitExProcAddressError)
  8015. }
  8016. STATIC void RegWaitForProcessDetach()
  8017. {
  8018. if (hKernel32Dll) {
  8019. FreeLibrary(hKernel32Dll);
  8020. hKernel32Dll = NULL;
  8021. }
  8022. }
  8023. // Upon entry/exit, the resync list is locked by the caller
  8024. void ILS_RemoveEventFromResyncList(
  8025. IN HANDLE hEvent,
  8026. IN OUT DWORD *pcEntry,
  8027. IN OUT PILS_RESYNC_ENTRY *ppEntry
  8028. )
  8029. {
  8030. DWORD cOrigEntry = *pcEntry;
  8031. DWORD cNewEntry = 0;
  8032. PILS_RESYNC_ENTRY pEntry = *ppEntry;
  8033. DWORD i;
  8034. for (i = 0; i < cOrigEntry; i++) {
  8035. if (pEntry[i].hOrigEvent == hEvent) {
  8036. HANDLE hDupEvent;
  8037. hDupEvent = pEntry[i].hDupEvent;
  8038. if (hDupEvent)
  8039. CloseHandle(hDupEvent);
  8040. } else {
  8041. if (i != cNewEntry)
  8042. pEntry[cNewEntry] = pEntry[i];
  8043. cNewEntry++;
  8044. }
  8045. }
  8046. *pcEntry = cNewEntry;
  8047. }
  8048. // Upon entry/exit, the resync list is locked by the caller
  8049. BOOL ILS_AddRemoveEventToFromResyncList(
  8050. IN PREG_STORE pRegStore,
  8051. IN HANDLE hEvent,
  8052. IN DWORD dwFlags,
  8053. IN OUT DWORD *pcEntry,
  8054. IN OUT PILS_RESYNC_ENTRY *ppEntry
  8055. )
  8056. {
  8057. BOOL fResult;
  8058. HANDLE hDupEvent = NULL;
  8059. DWORD cEntry;
  8060. PILS_RESYNC_ENTRY pEntry;
  8061. DWORD i;
  8062. assert(hEvent);
  8063. if (dwFlags & REG_STORE_CTRL_CANCEL_NOTIFY_FLAG) {
  8064. ILS_RemoveEventFromResyncList(
  8065. hEvent,
  8066. pcEntry,
  8067. ppEntry
  8068. );
  8069. return TRUE;
  8070. }
  8071. cEntry = *pcEntry;
  8072. pEntry = *ppEntry;
  8073. // First check if the hEvent is already in the list
  8074. for (i = 0; i < cEntry; i++) {
  8075. if (hEvent == pEntry[i].hOrigEvent)
  8076. return TRUE;
  8077. }
  8078. if (0 == (dwFlags & CERT_STORE_CTRL_INHIBIT_DUPLICATE_HANDLE_FLAG)) {
  8079. if (!DuplicateHandle(
  8080. GetCurrentProcess(),
  8081. hEvent,
  8082. GetCurrentProcess(),
  8083. &hDupEvent,
  8084. 0, // dwDesiredAccess
  8085. FALSE, // bInheritHandle
  8086. DUPLICATE_SAME_ACCESS
  8087. ) || NULL == hDupEvent)
  8088. goto DuplicateEventError;
  8089. }
  8090. if (NULL == (pEntry = (PILS_RESYNC_ENTRY) PkiRealloc(pEntry,
  8091. (cEntry + 1) * sizeof(ILS_RESYNC_ENTRY))))
  8092. goto OutOfMemory;
  8093. pEntry[cEntry].hOrigEvent = hEvent;
  8094. pEntry[cEntry].pRegStore = pRegStore;
  8095. pEntry[cEntry].hDupEvent = hDupEvent;
  8096. *pcEntry = cEntry + 1;
  8097. *ppEntry = pEntry;
  8098. fResult = TRUE;
  8099. CommonReturn:
  8100. return fResult;
  8101. ErrorReturn:
  8102. if (hDupEvent)
  8103. ILS_CloseHandle(hDupEvent);
  8104. fResult = FALSE;
  8105. goto CommonReturn;
  8106. TRACE_ERROR(DuplicateEventError)
  8107. TRACE_ERROR(OutOfMemory)
  8108. }
  8109. // Upon entry/exit, the resync list is locked by the caller
  8110. void ILS_SignalEventsOnResyncList(
  8111. IN OUT DWORD *pcEntry,
  8112. IN OUT PILS_RESYNC_ENTRY *ppEntry
  8113. )
  8114. {
  8115. DWORD cEntry = *pcEntry;
  8116. PILS_RESYNC_ENTRY pEntry = *ppEntry;
  8117. while (cEntry--) {
  8118. HANDLE hDupEvent;
  8119. hDupEvent = pEntry[cEntry].hDupEvent;
  8120. if (hDupEvent) {
  8121. SetEvent(hDupEvent);
  8122. CloseHandle(hDupEvent);
  8123. } else
  8124. SetEvent(pEntry[cEntry].hOrigEvent);
  8125. }
  8126. PkiFree(pEntry);
  8127. *pcEntry = 0;
  8128. *ppEntry = NULL;
  8129. }
  8130. // Upon entry/exit, the resync list is locked by the caller
  8131. void ILS_SignalAndFreeRegStoreResyncEntries(
  8132. IN PREG_STORE pRegStore,
  8133. IN OUT DWORD *pcEntry,
  8134. IN OUT PILS_RESYNC_ENTRY *ppEntry
  8135. )
  8136. {
  8137. DWORD cOrigEntry = *pcEntry;
  8138. DWORD cNewEntry = 0;
  8139. PILS_RESYNC_ENTRY pEntry = *ppEntry;
  8140. DWORD i;
  8141. for (i = 0; i < cOrigEntry; i++) {
  8142. if (pEntry[i].pRegStore == pRegStore) {
  8143. HANDLE hDupEvent;
  8144. hDupEvent = pEntry[i].hDupEvent;
  8145. if (hDupEvent) {
  8146. SetEvent(hDupEvent);
  8147. CloseHandle(hDupEvent);
  8148. } else
  8149. SetEvent(pEntry[i].hOrigEvent);
  8150. } else {
  8151. if (i != cNewEntry)
  8152. pEntry[cNewEntry] = pEntry[i];
  8153. cNewEntry++;
  8154. }
  8155. }
  8156. *pcEntry = cNewEntry;
  8157. }
  8158. STATIC BOOL ILS_RegNotifyChangeKeyValue(
  8159. IN HKEY hKey,
  8160. IN HANDLE hEvent
  8161. )
  8162. {
  8163. BOOL fResult;
  8164. LONG err;
  8165. err = RegNotifyChangeKeyValue(
  8166. hKey,
  8167. TRUE, // bWatchSubtree
  8168. REG_NOTIFY_CHANGE_NAME |
  8169. REG_NOTIFY_CHANGE_LAST_SET,
  8170. hEvent,
  8171. TRUE // fAsynchronus
  8172. );
  8173. if (!(ERROR_SUCCESS == err || ERROR_KEY_DELETED == err))
  8174. goto RegNotifyChangeKeyValueError;
  8175. fResult = TRUE;
  8176. CommonReturn:
  8177. return fResult;
  8178. ErrorReturn:
  8179. fResult = FALSE;
  8180. goto CommonReturn;
  8181. SET_ERROR_VAR(RegNotifyChangeKeyValueError, err)
  8182. }
  8183. //+=========================================================================
  8184. // Client "GPT" Store Data Structures and Functions
  8185. //==========================================================================
  8186. static PGPT_STORE_CHANGE_INFO pLMGptStoreChangeInfo;
  8187. typedef HANDLE (WINAPI *PFN_ENTER_CRITICAL_POLICY_SECTION)(
  8188. IN BOOL bMachine
  8189. );
  8190. typedef BOOL (WINAPI *PFN_LEAVE_CRITICAL_POLICY_SECTION)(
  8191. IN HANDLE hSection
  8192. );
  8193. typedef BOOL (WINAPI *PFN_REGISTER_GP_NOTIFICATION)(
  8194. IN HANDLE hEvent,
  8195. IN BOOL bMachine
  8196. );
  8197. typedef BOOL (WINAPI *PFN_UNREGISTER_GP_NOTIFICATION)(
  8198. IN HANDLE hEvent
  8199. );
  8200. #define sz_USERENV_DLL "userenv.dll"
  8201. #define sz_EnterCriticalPolicySection "EnterCriticalPolicySection"
  8202. #define sz_LeaveCriticalPolicySection "LeaveCriticalPolicySection"
  8203. #define sz_RegisterGPNotification "RegisterGPNotification"
  8204. #define sz_UnregisterGPNotification "UnregisterGPNotification"
  8205. static fLoadedUserEnvDll = FALSE;
  8206. static HMODULE hUserEnvDll = NULL;
  8207. static PFN_ENTER_CRITICAL_POLICY_SECTION pfnEnterCriticalPolicySection = NULL;
  8208. static PFN_LEAVE_CRITICAL_POLICY_SECTION pfnLeaveCriticalPolicySection = NULL;
  8209. static PFN_REGISTER_GP_NOTIFICATION pfnRegisterGPNotification = NULL;
  8210. static PFN_UNREGISTER_GP_NOTIFICATION pfnUnregisterGPNotification = NULL;
  8211. //+-------------------------------------------------------------------------
  8212. // Lock and unlock GPT_STORE functions
  8213. //--------------------------------------------------------------------------
  8214. static inline void GptStoreLock()
  8215. {
  8216. EnterCriticalSection(&ILS_CriticalSection);
  8217. }
  8218. static inline void GptStoreUnlock()
  8219. {
  8220. LeaveCriticalSection(&ILS_CriticalSection);
  8221. }
  8222. STATIC void GptLoadUserEnvDll()
  8223. {
  8224. HMODULE hDll;
  8225. if (fLoadedUserEnvDll)
  8226. return;
  8227. // Do load library without holding a lock
  8228. hDll = LoadLibraryA(sz_USERENV_DLL);
  8229. GptStoreLock();
  8230. if (fLoadedUserEnvDll) {
  8231. if (hDll)
  8232. FreeLibrary(hDll);
  8233. goto CommonReturn;
  8234. }
  8235. if (NULL == hDll)
  8236. goto LoadUserEnvDllError;
  8237. if (pfnEnterCriticalPolicySection =
  8238. (PFN_ENTER_CRITICAL_POLICY_SECTION) GetProcAddress(
  8239. hDll, sz_EnterCriticalPolicySection)) {
  8240. if (NULL == (pfnLeaveCriticalPolicySection =
  8241. (PFN_LEAVE_CRITICAL_POLICY_SECTION) GetProcAddress(
  8242. hDll, sz_LeaveCriticalPolicySection))) {
  8243. pfnEnterCriticalPolicySection = NULL;
  8244. #if DBG
  8245. DWORD dwErr = GetLastError();
  8246. DbgPrintf(DBG_SS_CRYPT32,
  8247. "userenv.dll:: GetProcAddress(%s) returned error: %d 0x%x\n",
  8248. sz_LeaveCriticalPolicySection, dwErr, dwErr);
  8249. #endif
  8250. }
  8251. } else {
  8252. #if DBG
  8253. DWORD dwErr = GetLastError();
  8254. DbgPrintf(DBG_SS_CRYPT32,
  8255. "userenv.dll:: GetProcAddress(%s) returned error: %d 0x%x\n",
  8256. sz_EnterCriticalPolicySection, dwErr, dwErr);
  8257. #endif
  8258. }
  8259. if (pfnRegisterGPNotification =
  8260. (PFN_REGISTER_GP_NOTIFICATION) GetProcAddress(
  8261. hDll, sz_RegisterGPNotification)) {
  8262. if (NULL == (pfnUnregisterGPNotification =
  8263. (PFN_UNREGISTER_GP_NOTIFICATION) GetProcAddress(
  8264. hDll, sz_UnregisterGPNotification))) {
  8265. pfnRegisterGPNotification = NULL;
  8266. #if DBG
  8267. DWORD dwErr = GetLastError();
  8268. DbgPrintf(DBG_SS_CRYPT32,
  8269. "userenv.dll:: GetProcAddress(%s) returned error: %d 0x%x\n",
  8270. sz_UnregisterGPNotification, dwErr, dwErr);
  8271. #endif
  8272. }
  8273. } else {
  8274. #if DBG
  8275. DWORD dwErr = GetLastError();
  8276. DbgPrintf(DBG_SS_CRYPT32,
  8277. "userenv.dll:: GetProcAddress(%s) returned error: %d 0x%x\n",
  8278. sz_RegisterGPNotification, dwErr, dwErr);
  8279. #endif
  8280. }
  8281. if (pfnEnterCriticalPolicySection || pfnRegisterGPNotification)
  8282. hUserEnvDll = hDll;
  8283. else
  8284. FreeLibrary(hDll);
  8285. CommonReturn:
  8286. fLoadedUserEnvDll = TRUE;
  8287. GptStoreUnlock();
  8288. return;
  8289. ErrorReturn:
  8290. goto CommonReturn;
  8291. TRACE_ERROR(LoadUserEnvDllError)
  8292. }
  8293. STATIC HANDLE GptStoreEnterCriticalPolicySection(
  8294. IN BOOL bMachine
  8295. )
  8296. {
  8297. #if 1
  8298. // ATTENTION:: entering this critical section is causing numerous hanging,
  8299. // deadlock problems
  8300. return NULL;
  8301. #else
  8302. HANDLE hSection;
  8303. GptLoadUserEnvDll();
  8304. if (NULL == pfnEnterCriticalPolicySection)
  8305. return NULL;
  8306. assert(hUserEnvDll);
  8307. assert(pfnLeaveCriticalPolicySection);
  8308. if (NULL == (hSection = pfnEnterCriticalPolicySection(bMachine)))
  8309. goto EnterCriticalPolicySectionError;
  8310. CommonReturn:
  8311. return hSection;
  8312. ErrorReturn:
  8313. goto CommonReturn;
  8314. TRACE_ERROR(EnterCriticalPolicySectionError)
  8315. #endif
  8316. }
  8317. STATIC void GptStoreLeaveCriticalPolicySection(
  8318. IN HANDLE hSection
  8319. )
  8320. {
  8321. if (hSection) {
  8322. assert(hUserEnvDll);
  8323. assert(pfnLeaveCriticalPolicySection);
  8324. if (!pfnLeaveCriticalPolicySection(hSection))
  8325. goto LeaveCriticalPolicySectionError;
  8326. }
  8327. CommonReturn:
  8328. return;
  8329. ErrorReturn:
  8330. goto CommonReturn;
  8331. TRACE_ERROR(LeaveCriticalPolicySectionError)
  8332. }
  8333. STATIC void GptStoreSignalAndFreeRegStoreResyncEntries(
  8334. IN PREG_STORE pRegStore
  8335. )
  8336. {
  8337. GptStoreLock();
  8338. if (pLMGptStoreChangeInfo)
  8339. ILS_SignalAndFreeRegStoreResyncEntries(
  8340. pRegStore,
  8341. &pLMGptStoreChangeInfo->cNotifyEntry,
  8342. &pLMGptStoreChangeInfo->rgNotifyEntry
  8343. );
  8344. GptStoreUnlock();
  8345. }
  8346. STATIC void GptStoreProcessAttach()
  8347. {
  8348. }
  8349. STATIC void GptStoreProcessDetach()
  8350. {
  8351. FreeGptStoreChangeInfo(&pLMGptStoreChangeInfo);
  8352. if (hUserEnvDll) {
  8353. FreeLibrary(hUserEnvDll);
  8354. hUserEnvDll = NULL;
  8355. }
  8356. }
  8357. STATIC VOID NTAPI GptWaitForCallback(
  8358. PVOID Context,
  8359. BOOLEAN fWaitOrTimedOut // ???
  8360. )
  8361. {
  8362. PGPT_STORE_CHANGE_INFO pInfo = (PGPT_STORE_CHANGE_INFO) Context;
  8363. DWORD cEntry;
  8364. PILS_RESYNC_ENTRY pEntry;
  8365. assert(pInfo);
  8366. assert(LM_GPT_CHANGE_INFO_TYPE == pInfo->dwType ||
  8367. CU_GPT_CHANGE_INFO_TYPE == pInfo->dwType);
  8368. if (NULL == pInfo)
  8369. return;
  8370. if (!(LM_GPT_CHANGE_INFO_TYPE == pInfo->dwType ||
  8371. CU_GPT_CHANGE_INFO_TYPE == pInfo->dwType))
  8372. return;
  8373. if (pInfo->hGPNotificationEvent) {
  8374. // We are called for all GPNotification events.
  8375. // Check that we also have a registry change notify.
  8376. if (pInfo->hPoliciesKey) {
  8377. assert(pInfo->hPoliciesEvent);
  8378. if (WAIT_OBJECT_0 != WaitForSingleObjectEx(
  8379. pInfo->hPoliciesEvent,
  8380. 0, // dwMilliseconds
  8381. FALSE // bAlertable
  8382. ))
  8383. return;
  8384. // When policy is applied, the registry key is deleted before
  8385. // reapplying policy.
  8386. ILS_CloseRegistryKey(pInfo->hPoliciesKey);
  8387. }
  8388. // Re-Open the Software\Policies\Microsoft\SystemCertificates registry
  8389. // key
  8390. //
  8391. // Ignore BACKUP_RESTORE case, in a different thread
  8392. pInfo->hPoliciesKey = OpenSubKey(
  8393. pInfo->hKeyBase,
  8394. GROUP_POLICY_STORE_REGPATH,
  8395. CERT_STORE_READONLY_FLAG
  8396. );
  8397. }
  8398. if (pInfo->hPoliciesKey) {
  8399. assert(pInfo->hPoliciesEvent);
  8400. // Re-arm the registry notify
  8401. ILS_RegNotifyChangeKeyValue(
  8402. pInfo->hPoliciesKey,
  8403. pInfo->hPoliciesEvent
  8404. );
  8405. }
  8406. // Minimize window of potential deadlock by only getting the values
  8407. // while holding the lock.
  8408. if (pInfo->pRegStore) {
  8409. assert(CU_GPT_CHANGE_INFO_TYPE == pInfo->dwType);
  8410. CertPerfIncrementChangeNotifyCuGpCount();
  8411. LockRegStore(pInfo->pRegStore);
  8412. } else {
  8413. assert(LM_GPT_CHANGE_INFO_TYPE == pInfo->dwType);
  8414. CertPerfIncrementChangeNotifyLmGpCount();
  8415. GptStoreLock();
  8416. }
  8417. cEntry = pInfo->cNotifyEntry;
  8418. pEntry = pInfo->rgNotifyEntry;
  8419. pInfo->cNotifyEntry = 0;
  8420. pInfo->rgNotifyEntry = NULL;
  8421. ILS_SignalEventsOnResyncList(&cEntry, &pEntry);
  8422. if (pInfo->pRegStore)
  8423. UnlockRegStore(pInfo->pRegStore);
  8424. else
  8425. GptStoreUnlock();
  8426. CertPerfIncrementChangeNotifyCount();
  8427. }
  8428. STATIC void FreeGptStoreChangeInfo(
  8429. IN OUT PGPT_STORE_CHANGE_INFO *ppInfo
  8430. )
  8431. {
  8432. PGPT_STORE_CHANGE_INFO pInfo = *ppInfo;
  8433. if (NULL == pInfo)
  8434. return;
  8435. if (!(LM_GPT_CHANGE_INFO_TYPE == pInfo->dwType ||
  8436. CU_GPT_CHANGE_INFO_TYPE == pInfo->dwType))
  8437. return;
  8438. // Unregister the wait for callback
  8439. if (pInfo->hRegWaitFor)
  8440. pfnILS_UnregisterWaitEx(pInfo->hRegWaitFor, INVALID_HANDLE_VALUE);
  8441. if (pInfo->hGPNotificationEvent) {
  8442. assert(hUserEnvDll && pfnUnregisterGPNotification);
  8443. pfnUnregisterGPNotification(
  8444. pInfo->hGPNotificationEvent);
  8445. CloseHandle(pInfo->hGPNotificationEvent);
  8446. }
  8447. ILS_CloseRegistryKey(pInfo->hPoliciesKey);
  8448. if (pInfo->hPoliciesEvent)
  8449. CloseHandle(pInfo->hPoliciesEvent);
  8450. // To inhibit any potential deadlock, do following without entering
  8451. // the critical section
  8452. ILS_SignalEventsOnResyncList(
  8453. &pInfo->cNotifyEntry,
  8454. &pInfo->rgNotifyEntry
  8455. );
  8456. PkiFree(pInfo);
  8457. *ppInfo = NULL;
  8458. }
  8459. STATIC PGPT_STORE_CHANGE_INFO CreateGptStoreChangeInfo(
  8460. IN PREG_STORE pRegStore,
  8461. IN BOOL fMachine
  8462. )
  8463. {
  8464. PGPT_STORE_CHANGE_INFO pInfo = NULL;
  8465. DWORD dwErr;
  8466. BOOL fGPNotify = FALSE;
  8467. GptLoadUserEnvDll();
  8468. if (NULL == (pInfo = (PGPT_STORE_CHANGE_INFO) PkiZeroAlloc(
  8469. sizeof(GPT_STORE_CHANGE_INFO))))
  8470. goto OutOfMemory;
  8471. if (fMachine) {
  8472. pInfo->dwType = LM_GPT_CHANGE_INFO_TYPE;
  8473. // pInfo->pRegStore = NULL;
  8474. } else {
  8475. pInfo->dwType = CU_GPT_CHANGE_INFO_TYPE;
  8476. pInfo->pRegStore = pRegStore;
  8477. }
  8478. pInfo->hKeyBase = pRegStore->GptPara.hKeyBase;
  8479. // Create our own event to be notified on a change
  8480. if (NULL == (pInfo->hPoliciesEvent = CreateEvent(
  8481. NULL, // lpsa
  8482. FALSE, // fManualReset
  8483. FALSE, // fInitialState
  8484. NULL))) // lpszEventName
  8485. goto CreateEventError;
  8486. // If the RegisterGPNotification API exists in userenv.dll, use it.
  8487. if (pfnRegisterGPNotification) {
  8488. if (NULL == (pInfo->hGPNotificationEvent = CreateEvent(
  8489. NULL, // lpsa
  8490. FALSE, // fManualReset
  8491. FALSE, // fInitialState
  8492. NULL))) // lpszEventName
  8493. goto CreateEventError;
  8494. if (pfnRegisterGPNotification(
  8495. pInfo->hGPNotificationEvent,
  8496. fMachine
  8497. ))
  8498. fGPNotify = TRUE;
  8499. else {
  8500. #if DBG
  8501. dwErr = GetLastError();
  8502. DbgPrintf(DBG_SS_CRYPT32,
  8503. "RegisterGPNotification returned error: %d 0x%x\n",
  8504. dwErr, dwErr);
  8505. #endif
  8506. CloseHandle(pInfo->hGPNotificationEvent);
  8507. pInfo->hGPNotificationEvent = NULL;
  8508. }
  8509. }
  8510. // Open the Software\Policies\Microsoft\SystemCertificates registry key
  8511. //
  8512. // Ignore BACKUP_RESTORE case
  8513. if (NULL == (pInfo->hPoliciesKey = OpenSubKey(
  8514. pInfo->hKeyBase,
  8515. GROUP_POLICY_STORE_REGPATH,
  8516. CERT_STORE_READONLY_FLAG
  8517. ))) {
  8518. if (!fGPNotify) {
  8519. // Ignore error if subkey doesn't exist.
  8520. if (ERROR_FILE_NOT_FOUND == GetLastError())
  8521. goto SuccessReturn;
  8522. goto OpenSubKeyError;
  8523. }
  8524. } else {
  8525. // Arm the registry notify
  8526. if (!ILS_RegNotifyChangeKeyValue(
  8527. pInfo->hPoliciesKey,
  8528. pInfo->hPoliciesEvent
  8529. ))
  8530. goto RegNotifyChangeKeyValueError;
  8531. }
  8532. if (!pfnILS_RegisterWaitForSingleObject(
  8533. &pInfo->hRegWaitFor,
  8534. fGPNotify ? pInfo->hGPNotificationEvent : pInfo->hPoliciesEvent,
  8535. GptWaitForCallback,
  8536. (PVOID) pInfo,
  8537. INFINITE, // no timeout
  8538. WT_EXECUTEINWAITTHREAD
  8539. )) {
  8540. pInfo->hRegWaitFor = NULL;
  8541. dwErr = GetLastError();
  8542. goto RegisterWaitForError;
  8543. }
  8544. SuccessReturn:
  8545. CommonReturn:
  8546. return pInfo;
  8547. ErrorReturn:
  8548. dwErr = GetLastError();
  8549. FreeGptStoreChangeInfo(&pInfo);
  8550. SetLastError(dwErr);
  8551. goto CommonReturn;
  8552. TRACE_ERROR(OutOfMemory)
  8553. TRACE_ERROR(CreateEventError)
  8554. TRACE_ERROR(OpenSubKeyError)
  8555. TRACE_ERROR(RegNotifyChangeKeyValueError)
  8556. SET_ERROR_VAR(RegisterWaitForError, dwErr)
  8557. }
  8558. // For LocalMachine: a single store change info data structure for all LMGP
  8559. // stores.
  8560. //
  8561. // For CurrentUser: each CUCP store has its own store change info.
  8562. STATIC BOOL RegGptStoreChange(
  8563. IN PREG_STORE pRegStore,
  8564. IN HANDLE hEvent,
  8565. IN DWORD dwFlags
  8566. )
  8567. {
  8568. BOOL fResult;
  8569. PGPT_STORE_CHANGE_INFO pInfo;
  8570. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_REMOTE_FLAG) {
  8571. SetLastError(ERROR_INVALID_HANDLE);
  8572. return FALSE;
  8573. }
  8574. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_LM_GPT_FLAG) {
  8575. if (NULL == (pInfo = pLMGptStoreChangeInfo)) {
  8576. if (NULL == (pInfo = CreateGptStoreChangeInfo(
  8577. pRegStore,
  8578. TRUE // fMachine
  8579. )))
  8580. goto CreateChangeInfoError;
  8581. GptStoreLock();
  8582. if (pLMGptStoreChangeInfo) {
  8583. GptStoreUnlock();
  8584. FreeGptStoreChangeInfo(&pInfo);
  8585. pInfo = pLMGptStoreChangeInfo;
  8586. } else {
  8587. pLMGptStoreChangeInfo = pInfo;
  8588. GptStoreUnlock();
  8589. }
  8590. }
  8591. assert(LM_GPT_CHANGE_INFO_TYPE == pInfo->dwType);
  8592. GptStoreLock();
  8593. fResult = ILS_AddRemoveEventToFromResyncList(
  8594. pRegStore,
  8595. hEvent,
  8596. dwFlags,
  8597. &pInfo->cNotifyEntry,
  8598. &pInfo->rgNotifyEntry
  8599. );
  8600. GptStoreUnlock();
  8601. } else {
  8602. if (NULL == (pInfo = pRegStore->pGptStoreChangeInfo)) {
  8603. if (NULL == (pInfo = CreateGptStoreChangeInfo(
  8604. pRegStore,
  8605. FALSE // fMachine
  8606. )))
  8607. goto CreateChangeInfoError;
  8608. LockRegStore(pRegStore);
  8609. if (pRegStore->pGptStoreChangeInfo) {
  8610. UnlockRegStore(pRegStore);
  8611. FreeGptStoreChangeInfo(&pInfo);
  8612. pInfo = pRegStore->pGptStoreChangeInfo;
  8613. } else {
  8614. pRegStore->pGptStoreChangeInfo = pInfo;
  8615. UnlockRegStore(pRegStore);
  8616. }
  8617. }
  8618. assert(CU_GPT_CHANGE_INFO_TYPE == pInfo->dwType);
  8619. LockRegStore(pRegStore);
  8620. fResult = ILS_AddRemoveEventToFromResyncList(
  8621. pRegStore,
  8622. hEvent,
  8623. dwFlags,
  8624. &pInfo->cNotifyEntry,
  8625. &pInfo->rgNotifyEntry
  8626. );
  8627. UnlockRegStore(pRegStore);
  8628. }
  8629. CommonReturn:
  8630. return fResult;
  8631. ErrorReturn:
  8632. fResult = FALSE;
  8633. goto CommonReturn;
  8634. TRACE_ERROR(CreateChangeInfoError)
  8635. }
  8636. STATIC BOOL OpenAllFromGptRegistry(
  8637. IN PREG_STORE pRegStore,
  8638. IN HCERTSTORE hCertStore
  8639. )
  8640. {
  8641. BOOL fResult;
  8642. HANDLE hSection = NULL;
  8643. LockRegStore(pRegStore);
  8644. if (0 == (pRegStore->dwFlags & CERT_REGISTRY_STORE_REMOTE_FLAG))
  8645. hSection = GptStoreEnterCriticalPolicySection(
  8646. pRegStore->dwFlags & CERT_REGISTRY_STORE_LM_GPT_FLAG
  8647. );
  8648. assert(NULL == pRegStore->hKey);
  8649. if (NULL == (pRegStore->hKey = OpenSubKey(
  8650. pRegStore->GptPara.hKeyBase,
  8651. pRegStore->GptPara.pwszRegPath,
  8652. pRegStore->dwFlags
  8653. ))) {
  8654. if (ERROR_FILE_NOT_FOUND != GetLastError() ||
  8655. (pRegStore->dwFlags & CERT_STORE_OPEN_EXISTING_FLAG))
  8656. goto OpenSubKeyError;
  8657. fResult = TRUE;
  8658. goto CommonReturn;
  8659. }
  8660. // fResult = OpenAllFromSerializedRegistry(pRegStore, hCertStore);
  8661. // Ignore any errors
  8662. OpenAllFromRegistry(pRegStore, hCertStore);
  8663. fResult = TRUE;
  8664. CommonReturn:
  8665. ILS_CloseRegistryKey(pRegStore->hKey);
  8666. pRegStore->hKey = NULL;
  8667. GptStoreLeaveCriticalPolicySection(hSection);
  8668. UnlockRegStore(pRegStore);
  8669. return fResult;
  8670. ErrorReturn:
  8671. fResult = FALSE;
  8672. goto CommonReturn;
  8673. TRACE_ERROR(OpenSubKeyError)
  8674. }
  8675. STATIC BOOL CommitAllToGptRegistry(
  8676. IN PREG_STORE pRegStore,
  8677. IN DWORD dwFlags
  8678. )
  8679. {
  8680. #if 1
  8681. return TRUE;
  8682. #else
  8683. BOOL fResult;
  8684. BOOL fTouched;
  8685. DWORD dwSaveFlags;
  8686. LockRegStore(pRegStore);
  8687. if (dwFlags & CERT_STORE_CTRL_COMMIT_FORCE_FLAG)
  8688. fTouched = TRUE;
  8689. else if (dwFlags & CERT_STORE_CTRL_COMMIT_CLEAR_FLAG)
  8690. fTouched = FALSE;
  8691. else
  8692. fTouched = pRegStore->fTouched;
  8693. if (fTouched) {
  8694. if (pRegStore->dwFlags & CERT_STORE_READONLY_FLAG)
  8695. goto AccessDenied;
  8696. } else {
  8697. pRegStore->fTouched = FALSE;
  8698. fResult = TRUE;
  8699. goto CommonReturn;
  8700. }
  8701. assert(NULL == pRegStore->hKey);
  8702. if (NULL == (pRegStore->hKey = OpenSubKey(
  8703. pRegStore->GptPara.hKeyBase,
  8704. pRegStore->GptPara.pwszRegPath,
  8705. pRegStore->dwFlags
  8706. )))
  8707. goto OpenSubKeyError;
  8708. dwSaveFlags = pRegStore->dwFlags;
  8709. pRegStore->dwFlags &= ~CERT_STORE_OPEN_EXISTING_FLAG;
  8710. fResult = CommitAllToSerializedRegistry(pRegStore, dwFlags);
  8711. pRegStore->dwFlags = dwSaveFlags;
  8712. CommonReturn:
  8713. ILS_CloseRegistryKey(pRegStore->hKey);
  8714. pRegStore->hKey = NULL;
  8715. UnlockRegStore(pRegStore);
  8716. return fResult;
  8717. ErrorReturn:
  8718. fResult = FALSE;
  8719. goto CommonReturn;
  8720. SET_ERROR(AccessDenied, E_ACCESSDENIED)
  8721. TRACE_ERROR(OpenSubKeyError)
  8722. #endif
  8723. }
  8724. //+=========================================================================
  8725. // Win95 Notify Store Data Structures and Functions
  8726. //
  8727. // Win95/Win98 don't support registry change notification.
  8728. //
  8729. // On Win95 we pulse an event each time a store context element is written
  8730. // or deleted.
  8731. //==========================================================================
  8732. static BOOL fWin95StoreInitialized;
  8733. static HANDLE hWin95RegWaitFor;
  8734. static DWORD cWin95StoreResyncEntry;
  8735. static ILS_RESYNC_ENTRY *pWin95StoreResyncEntry;
  8736. //+-------------------------------------------------------------------------
  8737. // Lock and unlock WIN95_STORE functions
  8738. //--------------------------------------------------------------------------
  8739. static inline void Win95StoreLock()
  8740. {
  8741. EnterCriticalSection(&ILS_CriticalSection);
  8742. }
  8743. static inline void Win95StoreUnlock()
  8744. {
  8745. LeaveCriticalSection(&ILS_CriticalSection);
  8746. }
  8747. STATIC void Win95StoreSignalAndFreeRegStoreResyncEntries(
  8748. IN PREG_STORE pRegStore
  8749. )
  8750. {
  8751. if (NULL == hWin95NotifyEvent)
  8752. return;
  8753. Win95StoreLock();
  8754. ILS_SignalAndFreeRegStoreResyncEntries(
  8755. pRegStore,
  8756. &cWin95StoreResyncEntry,
  8757. &pWin95StoreResyncEntry
  8758. );
  8759. Win95StoreUnlock();
  8760. }
  8761. STATIC void Win95StoreProcessAttach()
  8762. {
  8763. if (FIsWinNT())
  8764. return;
  8765. hWin95NotifyEvent = CreateEventA(
  8766. NULL, // lpsa
  8767. TRUE, // fManualReset
  8768. FALSE, // fInitialState
  8769. "Win95CertStoreNotifyEvent"
  8770. );
  8771. if (NULL == hWin95NotifyEvent)
  8772. goto CreateWin95NotifyEventError;
  8773. CommonReturn:
  8774. return;
  8775. ErrorReturn:
  8776. goto CommonReturn;
  8777. TRACE_ERROR(CreateWin95NotifyEventError)
  8778. }
  8779. STATIC void Win95StoreProcessDetach()
  8780. {
  8781. if (NULL == hWin95NotifyEvent)
  8782. return;
  8783. if (fWin95StoreInitialized) {
  8784. // Unregister the wait for callback
  8785. assert(hWin95RegWaitFor);
  8786. pfnILS_UnregisterWaitEx(hWin95RegWaitFor, INVALID_HANDLE_VALUE);
  8787. // To inhibit any potential deadlock, do following without entering
  8788. // the critical section
  8789. ILS_SignalEventsOnResyncList(
  8790. &cWin95StoreResyncEntry,
  8791. &pWin95StoreResyncEntry
  8792. );
  8793. fWin95StoreInitialized = FALSE;
  8794. }
  8795. CloseHandle(hWin95NotifyEvent);
  8796. }
  8797. STATIC VOID NTAPI Win95WaitForCallback(
  8798. PVOID Context,
  8799. BOOLEAN fWaitOrTimedOut // ???
  8800. )
  8801. {
  8802. DWORD cEntry;
  8803. PILS_RESYNC_ENTRY pEntry;
  8804. Win95StoreLock();
  8805. cEntry = cWin95StoreResyncEntry;
  8806. pEntry = pWin95StoreResyncEntry;
  8807. cWin95StoreResyncEntry = 0;
  8808. pWin95StoreResyncEntry = NULL;
  8809. Win95StoreUnlock();
  8810. ILS_SignalEventsOnResyncList(
  8811. &cEntry,
  8812. &pEntry
  8813. );
  8814. }
  8815. STATIC BOOL Win95StoreChangeInit()
  8816. {
  8817. BOOL fResult;
  8818. DWORD dwErr;
  8819. HANDLE hRegWaitFor;
  8820. if (fWin95StoreInitialized)
  8821. return TRUE;
  8822. Win95StoreLock();
  8823. if (fWin95StoreInitialized)
  8824. goto SuccessReturn;
  8825. assert(hWin95NotifyEvent);
  8826. if (!pfnILS_RegisterWaitForSingleObject(
  8827. &hRegWaitFor,
  8828. hWin95NotifyEvent,
  8829. Win95WaitForCallback,
  8830. NULL, // Context
  8831. INFINITE, // no timeout
  8832. 0 // no flags (normal)
  8833. )) {
  8834. dwErr = GetLastError();
  8835. goto RegisterWaitForError;
  8836. }
  8837. hWin95RegWaitFor = hRegWaitFor;
  8838. SuccessReturn:
  8839. fResult = TRUE;
  8840. fWin95StoreInitialized = TRUE;
  8841. CommonReturn:
  8842. Win95StoreUnlock();
  8843. return fResult;;
  8844. ErrorReturn:
  8845. fResult = FALSE;
  8846. goto CommonReturn;
  8847. SET_ERROR_VAR(RegisterWaitForError, dwErr)
  8848. }
  8849. STATIC BOOL RegWin95StoreChange(
  8850. IN PREG_STORE pRegStore,
  8851. IN HANDLE hEvent,
  8852. IN DWORD dwFlags
  8853. )
  8854. {
  8855. BOOL fResult;
  8856. assert(hWin95NotifyEvent);
  8857. if (!Win95StoreChangeInit())
  8858. return FALSE;
  8859. Win95StoreLock();
  8860. fResult = ILS_AddRemoveEventToFromResyncList(
  8861. pRegStore,
  8862. hEvent,
  8863. dwFlags,
  8864. &cWin95StoreResyncEntry,
  8865. &pWin95StoreResyncEntry
  8866. );
  8867. Win95StoreUnlock();
  8868. return fResult;
  8869. }
  8870. //+=========================================================================
  8871. // Roaming Store Functions
  8872. //==========================================================================
  8873. #if 0
  8874. SHSTDAPI SHGetFolderPathW(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPWSTR lpszPath);
  8875. #endif
  8876. typedef HRESULT (STDAPICALLTYPE *PFN_GET_FOLDER_PATH) (
  8877. HWND hwnd,
  8878. int csidl,
  8879. HANDLE hToken,
  8880. DWORD dwFlags,
  8881. LPWSTR lpszPath
  8882. );
  8883. #define sz_SHELL32_DLL "shell32.dll"
  8884. #define sz_GetFolderPath "SHGetFolderPathW"
  8885. static fLoadedShell32Dll = FALSE;
  8886. static HMODULE hShell32Dll = NULL;
  8887. static PFN_GET_FOLDER_PATH pfnGetFolderPath = NULL;
  8888. #if 0
  8889. // from \nt\public\internal\ds\inc\userenvp.h
  8890. USERENVAPI
  8891. DWORD
  8892. WINAPI
  8893. GetUserAppDataPathW(
  8894. IN HANDLE hToken,
  8895. IN BOOL fLocalAppData,
  8896. OUT LPWSTR lpFolderPath
  8897. );
  8898. #endif
  8899. typedef DWORD (WINAPI *PFN_GET_USER_APP_DATA_PATH) (
  8900. IN HANDLE hToken,
  8901. IN BOOL fLocalAppData,
  8902. OUT LPWSTR lpFolderPath
  8903. );
  8904. #define sz_ROAMING_USERENV_DLL "userenv.dll"
  8905. #define wsz_ROAMING_USERENV_DLL L"userenv.dll"
  8906. // From \nt\ds\security\gina\userenv\main\userenv.def
  8907. // GetUserAppDataPathW @149 NONAME ;Internal
  8908. #define ORDINAL_GetUserAppDataPath 149
  8909. // First version to support GetUserAppDataPath
  8910. #define ROAMING_USERENV_DLL_VER_MS (( 5 << 16) | 1 )
  8911. #define ROAMING_USERENV_DLL_VER_LS (( 2465 << 16) | 0 )
  8912. static fLoadedRoamingUserenvDll = FALSE;
  8913. static HMODULE hRoamingUserenvDll = NULL;
  8914. static PFN_GET_USER_APP_DATA_PATH pfnGetUserAppDataPath = NULL;
  8915. static inline void RoamingStoreLock()
  8916. {
  8917. EnterCriticalSection(&ILS_CriticalSection);
  8918. }
  8919. static inline void RoamingStoreUnlock()
  8920. {
  8921. LeaveCriticalSection(&ILS_CriticalSection);
  8922. }
  8923. STATIC void RoamingStoreProcessAttach()
  8924. {
  8925. }
  8926. STATIC void RoamingStoreProcessDetach()
  8927. {
  8928. if (hShell32Dll) {
  8929. FreeLibrary(hShell32Dll);
  8930. hShell32Dll = NULL;
  8931. }
  8932. if (hRoamingUserenvDll) {
  8933. FreeLibrary(hRoamingUserenvDll);
  8934. hRoamingUserenvDll = NULL;
  8935. }
  8936. }
  8937. STATIC void RoamingStoreLoadShell32Dll()
  8938. {
  8939. if (fLoadedShell32Dll)
  8940. return;
  8941. RoamingStoreLock();
  8942. if (fLoadedShell32Dll)
  8943. goto CommonReturn;
  8944. if (NULL == (hShell32Dll = LoadLibraryA(sz_SHELL32_DLL)))
  8945. goto LoadShell32DllError;
  8946. if (NULL == (pfnGetFolderPath =
  8947. (PFN_GET_FOLDER_PATH) GetProcAddress(hShell32Dll,
  8948. sz_GetFolderPath)))
  8949. goto GetFolderPathProcAddressError;
  8950. CommonReturn:
  8951. fLoadedShell32Dll = TRUE;
  8952. RoamingStoreUnlock();
  8953. return;
  8954. ErrorReturn:
  8955. if (hShell32Dll) {
  8956. FreeLibrary(hShell32Dll);
  8957. hShell32Dll = NULL;
  8958. pfnGetFolderPath = NULL;
  8959. }
  8960. goto CommonReturn;
  8961. TRACE_ERROR(LoadShell32DllError)
  8962. TRACE_ERROR(GetFolderPathProcAddressError)
  8963. }
  8964. STATIC void RoamingStoreLoadUserenvDll()
  8965. {
  8966. DWORD dwFileVersionMS;
  8967. DWORD dwFileVersionLS;
  8968. if (fLoadedRoamingUserenvDll)
  8969. return;
  8970. RoamingStoreLock();
  8971. if (fLoadedRoamingUserenvDll)
  8972. goto CommonReturn;
  8973. // GetUserAppDataPath() not supported until later versions of userenv.dll
  8974. // in WXP
  8975. if (!I_CryptGetFileVersion(
  8976. wsz_ROAMING_USERENV_DLL,
  8977. &dwFileVersionMS,
  8978. &dwFileVersionLS
  8979. ))
  8980. goto GetUserenvFileVersionError;
  8981. if (ROAMING_USERENV_DLL_VER_MS < dwFileVersionMS)
  8982. ;
  8983. else if (ROAMING_USERENV_DLL_VER_MS == dwFileVersionMS &&
  8984. ROAMING_USERENV_DLL_VER_LS <= dwFileVersionLS)
  8985. ;
  8986. else
  8987. goto Userenv_GetUserAppDataPathNotSupported;
  8988. if (NULL == (hRoamingUserenvDll = LoadLibraryA(sz_ROAMING_USERENV_DLL)))
  8989. goto LoadUserenvDllError;
  8990. if (NULL == (pfnGetUserAppDataPath =
  8991. (PFN_GET_USER_APP_DATA_PATH) GetProcAddress(hRoamingUserenvDll,
  8992. (LPCSTR) ORDINAL_GetUserAppDataPath)))
  8993. goto GetUserAppDataPathProcAddressError;
  8994. CommonReturn:
  8995. fLoadedRoamingUserenvDll = TRUE;
  8996. RoamingStoreUnlock();
  8997. return;
  8998. ErrorReturn:
  8999. if (hRoamingUserenvDll) {
  9000. FreeLibrary(hRoamingUserenvDll);
  9001. hRoamingUserenvDll = NULL;
  9002. pfnGetUserAppDataPath = NULL;
  9003. }
  9004. goto CommonReturn;
  9005. TRACE_ERROR(GetUserenvFileVersionError)
  9006. SET_ERROR_VAR(Userenv_GetUserAppDataPathNotSupported, ERROR_NOT_SUPPORTED)
  9007. TRACE_ERROR(LoadUserenvDllError)
  9008. TRACE_ERROR(GetUserAppDataPathProcAddressError)
  9009. }
  9010. STATIC HANDLE GetRoamingToken()
  9011. {
  9012. HANDLE hToken = NULL;
  9013. DWORD dwErr;
  9014. if (!FIsWinNT()) {
  9015. return NULL;
  9016. }
  9017. //
  9018. // first, attempt to look at the thread token. If none exists,
  9019. // which is true if the thread is not impersonating, try the
  9020. // process token.
  9021. //
  9022. if (!OpenThreadToken(
  9023. GetCurrentThread(),
  9024. TOKEN_QUERY | TOKEN_IMPERSONATE,
  9025. TRUE,
  9026. &hToken
  9027. )) {
  9028. dwErr = GetLastError();
  9029. if (ERROR_NO_TOKEN != dwErr)
  9030. goto OpenThreadTokenError;
  9031. if (!OpenProcessToken(GetCurrentProcess(),
  9032. TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &hToken)) {
  9033. dwErr = GetLastError();
  9034. goto OpenProcessTokenError;
  9035. }
  9036. }
  9037. CommonReturn:
  9038. return hToken;
  9039. ErrorReturn:
  9040. hToken = NULL;
  9041. goto CommonReturn;
  9042. SET_ERROR_VAR(OpenThreadTokenError, dwErr)
  9043. SET_ERROR_VAR(OpenProcessTokenError, dwErr)
  9044. }
  9045. STATIC
  9046. DWORD
  9047. FastGetUserAppDataPath(
  9048. IN HANDLE hToken,
  9049. OUT WCHAR wszFolderPath[MAX_PATH]
  9050. )
  9051. {
  9052. DWORD dwErr;
  9053. RoamingStoreLoadUserenvDll();
  9054. if (NULL == hRoamingUserenvDll)
  9055. goto ErrorReturn;
  9056. assert(pfnGetUserAppDataPath);
  9057. wszFolderPath[0] = L'\0';
  9058. __try {
  9059. dwErr = pfnGetUserAppDataPath(
  9060. hToken,
  9061. FALSE,
  9062. wszFolderPath
  9063. );
  9064. } __except(EXCEPTION_EXECUTE_HANDLER) {
  9065. dwErr = GetExceptionCode();
  9066. goto GetUserAppDataPathException;
  9067. }
  9068. if (ERROR_SUCCESS != dwErr || L'\0' == wszFolderPath[0])
  9069. goto GetUserAppDataPathError;
  9070. #if DBG
  9071. DbgPrintf(DBG_SS_CRYPT32, "userenv!GetUserAppDataPath:: %S\n",
  9072. wszFolderPath);
  9073. #endif
  9074. dwErr = ERROR_SUCCESS;
  9075. CommonReturn:
  9076. return dwErr;
  9077. ErrorReturn:
  9078. dwErr = ERROR_FILE_NOT_FOUND;
  9079. goto CommonReturn;
  9080. SET_ERROR_VAR(GetUserAppDataPathException, dwErr)
  9081. SET_ERROR_VAR(GetUserAppDataPathError, dwErr)
  9082. }
  9083. STATIC
  9084. DWORD
  9085. SlowGetUserAppDataPath(
  9086. IN HANDLE hToken,
  9087. OUT WCHAR wszFolderPath[MAX_PATH]
  9088. )
  9089. {
  9090. DWORD dwErr;
  9091. HRESULT hr;
  9092. RoamingStoreLoadShell32Dll();
  9093. if (NULL == hShell32Dll)
  9094. goto ErrorReturn;
  9095. assert(pfnGetFolderPath);
  9096. wszFolderPath[0] = L'\0';
  9097. hr = pfnGetFolderPath(
  9098. NULL, // hwndOwner
  9099. CSIDL_APPDATA | CSIDL_FLAG_CREATE,
  9100. hToken,
  9101. 0, // dwFlags
  9102. wszFolderPath
  9103. );
  9104. if (S_OK != hr || L'\0' == wszFolderPath[0])
  9105. goto GetFolderPathError;
  9106. #if DBG
  9107. DbgPrintf(DBG_SS_CRYPT32, "SHFolderPath(CSIDL_APPDATA):: %S\n",
  9108. wszFolderPath);
  9109. #endif
  9110. dwErr = ERROR_SUCCESS;
  9111. CommonReturn:
  9112. return dwErr;
  9113. ErrorReturn:
  9114. dwErr = ERROR_FILE_NOT_FOUND;
  9115. goto CommonReturn;
  9116. SET_ERROR_VAR(GetFolderPathError, hr)
  9117. }
  9118. LPWSTR
  9119. ILS_GetRoamingStoreDirectory(
  9120. IN LPCWSTR pwszStoreName
  9121. )
  9122. {
  9123. DWORD dwErr;
  9124. HANDLE hToken = NULL;
  9125. LPWSTR pwszDir = NULL;
  9126. WCHAR wszFolderPath[MAX_PATH];
  9127. LPCWSTR rgpwszName[] = { wszFolderPath, pwszStoreName };
  9128. SYSTEM_NAME_GROUP NameGroup;
  9129. hToken = GetRoamingToken();
  9130. dwErr = FastGetUserAppDataPath(hToken, wszFolderPath);
  9131. if (ERROR_SUCCESS != dwErr)
  9132. dwErr = SlowGetUserAppDataPath(hToken, wszFolderPath);
  9133. if (ERROR_SUCCESS != dwErr)
  9134. goto GetUserAppDataPathError;
  9135. NameGroup.cName = sizeof(rgpwszName) / sizeof(rgpwszName[0]);
  9136. NameGroup.rgpwszName = rgpwszName;
  9137. if (NULL == (pwszDir = FormatSystemNamePath(1, &NameGroup)))
  9138. goto FormatSystemNamePathError;
  9139. CommonReturn:
  9140. if (hToken)
  9141. ILS_CloseHandle(hToken);
  9142. return pwszDir;
  9143. ErrorReturn:
  9144. pwszDir = NULL;
  9145. goto CommonReturn;
  9146. SET_ERROR_VAR(GetUserAppDataPathError, dwErr)
  9147. TRACE_ERROR(FormatSystemNamePathError)
  9148. }
  9149. static DWORD rgdwCreateFileRetryMilliseconds[] =
  9150. { 1, 10, 100, 500, 1000, 5000 };
  9151. #define MAX_CREATE_FILE_RETRY_COUNT \
  9152. (sizeof(rgdwCreateFileRetryMilliseconds) / \
  9153. sizeof(rgdwCreateFileRetryMilliseconds[0]))
  9154. BOOL
  9155. ILS_ReadElementFromFile(
  9156. IN LPCWSTR pwszStoreDir,
  9157. IN LPCWSTR pwszContextName,
  9158. IN const WCHAR wszHashName[MAX_HASH_NAME_LEN],
  9159. IN DWORD dwFlags, // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  9160. OUT BYTE **ppbElement,
  9161. OUT DWORD *pcbElement
  9162. )
  9163. {
  9164. BOOL fResult;
  9165. DWORD dwErr;
  9166. LPWSTR pwszFilename = NULL;
  9167. LPCWSTR rgpwszName[] = { pwszStoreDir, pwszContextName, wszHashName };
  9168. SYSTEM_NAME_GROUP NameGroup;
  9169. HANDLE hFile = INVALID_HANDLE_VALUE;
  9170. DWORD cbBytesRead;
  9171. BYTE *pbElement = NULL;
  9172. DWORD cbElement;
  9173. DWORD dwRetryCount;
  9174. NameGroup.cName = sizeof(rgpwszName) / sizeof(rgpwszName[0]);
  9175. NameGroup.rgpwszName = rgpwszName;
  9176. if (NULL == (pwszFilename = FormatSystemNamePath(1, &NameGroup)))
  9177. goto FormatSystemNamePathError;
  9178. dwRetryCount = 0;
  9179. while (INVALID_HANDLE_VALUE == (hFile = CreateFileU(
  9180. pwszFilename,
  9181. GENERIC_READ,
  9182. FILE_SHARE_READ,
  9183. NULL, // lpsa
  9184. OPEN_EXISTING,
  9185. FILE_ATTRIBUTE_NORMAL |
  9186. ((dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG) ?
  9187. FILE_FLAG_BACKUP_SEMANTICS : 0),
  9188. NULL // hTemplateFile
  9189. ))) {
  9190. dwErr = GetLastError();
  9191. if ((ERROR_SHARING_VIOLATION == dwErr ||
  9192. ERROR_ACCESS_DENIED == dwErr) &&
  9193. MAX_CREATE_FILE_RETRY_COUNT > dwRetryCount) {
  9194. Sleep(rgdwCreateFileRetryMilliseconds[dwRetryCount]);
  9195. dwRetryCount++;
  9196. } else {
  9197. if (ERROR_PATH_NOT_FOUND == dwErr)
  9198. dwErr = ERROR_FILE_NOT_FOUND;
  9199. goto CreateFileError;
  9200. }
  9201. }
  9202. cbElement = GetFileSize(hFile, NULL);
  9203. if (0xFFFFFFFF == cbElement) goto FileSizeError;
  9204. if (0 == cbElement) goto EmptyFile;
  9205. if (NULL == (pbElement = (BYTE *) PkiNonzeroAlloc(cbElement)))
  9206. goto OutOfMemory;
  9207. if (!ReadFile(
  9208. hFile,
  9209. pbElement,
  9210. cbElement,
  9211. &cbBytesRead,
  9212. NULL // lpOverlapped
  9213. )) {
  9214. dwErr = GetLastError();
  9215. goto FileError;
  9216. }
  9217. fResult = TRUE;
  9218. CommonReturn:
  9219. PkiFree(pwszFilename);
  9220. if (INVALID_HANDLE_VALUE != hFile)
  9221. ILS_CloseHandle(hFile);
  9222. *ppbElement = pbElement;
  9223. *pcbElement = cbElement;
  9224. return fResult;
  9225. ErrorReturn:
  9226. fResult = FALSE;
  9227. PkiFree(pbElement);
  9228. pbElement = NULL;
  9229. cbElement = 0;
  9230. goto CommonReturn;
  9231. TRACE_ERROR(FormatSystemNamePathError)
  9232. TRACE_ERROR(OutOfMemory)
  9233. SET_ERROR_VAR(CreateFileError, dwErr)
  9234. TRACE_ERROR(FileSizeError)
  9235. SET_ERROR_VAR(FileError, dwErr)
  9236. SET_ERROR(EmptyFile, CRYPT_E_FILE_ERROR)
  9237. }
  9238. BOOL
  9239. ILS_WriteElementToFile(
  9240. IN LPCWSTR pwszStoreDir,
  9241. IN LPCWSTR pwszContextName,
  9242. IN const WCHAR wszHashName[MAX_HASH_NAME_LEN],
  9243. IN DWORD dwFlags, // CERT_STORE_CREATE_NEW_FLAG or
  9244. // CERT_STORE_BACKUP_RESTORE_FLAG may be set
  9245. IN const BYTE *pbElement,
  9246. IN DWORD cbElement
  9247. )
  9248. {
  9249. BOOL fResult;
  9250. DWORD dwErr;
  9251. LPWSTR pwszDir = NULL;
  9252. LPWSTR pwszFilename = NULL;
  9253. LPCWSTR rgpwszName[] = { pwszStoreDir, pwszContextName, wszHashName };
  9254. SYSTEM_NAME_GROUP NameGroup;
  9255. HANDLE hFile = INVALID_HANDLE_VALUE;
  9256. DWORD cbBytesWritten;
  9257. DWORD dwRetryCount;
  9258. NameGroup.cName = sizeof(rgpwszName) / sizeof(rgpwszName[0]);
  9259. NameGroup.rgpwszName = rgpwszName;
  9260. if (NULL == (pwszFilename = FormatSystemNamePath(1, &NameGroup)))
  9261. goto FormatSystemNamePathError;
  9262. NameGroup.cName--;
  9263. if (NULL == (pwszDir = FormatSystemNamePath(1, &NameGroup)))
  9264. goto FormatSystemNamePathError;
  9265. if (!I_RecursiveCreateDirectory(pwszDir, NULL))
  9266. goto CreateDirError;
  9267. dwRetryCount = 0;
  9268. while (INVALID_HANDLE_VALUE == (hFile = CreateFileU(
  9269. pwszFilename,
  9270. GENERIC_WRITE,
  9271. 0, // fdwShareMode
  9272. NULL, // lpsa
  9273. (dwFlags & CERT_STORE_CREATE_NEW_FLAG) ?
  9274. CREATE_NEW : CREATE_ALWAYS,
  9275. FILE_ATTRIBUTE_SYSTEM |
  9276. ((dwFlags & CERT_STORE_BACKUP_RESTORE_FLAG) ?
  9277. FILE_FLAG_BACKUP_SEMANTICS : 0),
  9278. NULL // hTemplateFile
  9279. ))) {
  9280. dwErr = GetLastError();
  9281. if ((ERROR_SHARING_VIOLATION == dwErr ||
  9282. ERROR_ACCESS_DENIED == dwErr) &&
  9283. MAX_CREATE_FILE_RETRY_COUNT > dwRetryCount) {
  9284. Sleep(rgdwCreateFileRetryMilliseconds[dwRetryCount]);
  9285. dwRetryCount++;
  9286. } else
  9287. goto CreateFileError;
  9288. }
  9289. if (!WriteFile(
  9290. hFile,
  9291. pbElement,
  9292. cbElement,
  9293. &cbBytesWritten,
  9294. NULL // lpOverlapped
  9295. )) {
  9296. dwErr = GetLastError();
  9297. goto WriteFileError;
  9298. }
  9299. fResult = TRUE;
  9300. CommonReturn:
  9301. if (INVALID_HANDLE_VALUE != hFile)
  9302. ILS_CloseHandle(hFile);
  9303. PkiFree(pwszFilename);
  9304. PkiFree(pwszDir);
  9305. return fResult;
  9306. ErrorReturn:
  9307. fResult = FALSE;
  9308. goto CommonReturn;
  9309. TRACE_ERROR(FormatSystemNamePathError)
  9310. TRACE_ERROR(CreateDirError)
  9311. SET_ERROR_VAR(CreateFileError, dwErr)
  9312. SET_ERROR_VAR(WriteFileError, dwErr)
  9313. }
  9314. BOOL
  9315. ILS_DeleteElementFromDirectory(
  9316. IN LPCWSTR pwszStoreDir,
  9317. IN LPCWSTR pwszContextName,
  9318. IN const WCHAR wszHashName[MAX_HASH_NAME_LEN],
  9319. IN DWORD dwFlags
  9320. )
  9321. {
  9322. BOOL fResult;
  9323. DWORD dwErr;
  9324. LPWSTR pwszFilename = NULL;
  9325. LPCWSTR rgpwszName[] = { pwszStoreDir, pwszContextName, wszHashName };
  9326. SYSTEM_NAME_GROUP NameGroup;
  9327. DWORD dwRetryCount;
  9328. NameGroup.cName = sizeof(rgpwszName) / sizeof(rgpwszName[0]);
  9329. NameGroup.rgpwszName = rgpwszName;
  9330. if (NULL == (pwszFilename = FormatSystemNamePath(1, &NameGroup)))
  9331. goto FormatSystemNamePathError;
  9332. dwRetryCount = 0;
  9333. while (!DeleteFileU(pwszFilename)) {
  9334. dwErr = GetLastError();
  9335. if ((ERROR_SHARING_VIOLATION == dwErr ||
  9336. ERROR_ACCESS_DENIED == dwErr) &&
  9337. MAX_CREATE_FILE_RETRY_COUNT > dwRetryCount) {
  9338. Sleep(rgdwCreateFileRetryMilliseconds[dwRetryCount]);
  9339. dwRetryCount++;
  9340. } else
  9341. goto DeleteFileError;
  9342. }
  9343. fResult = TRUE;
  9344. CommonReturn:
  9345. PkiFree(pwszFilename);
  9346. return fResult;
  9347. ErrorReturn:
  9348. fResult = FALSE;
  9349. goto CommonReturn;
  9350. TRACE_ERROR(FormatSystemNamePathError)
  9351. SET_ERROR_VAR(DeleteFileError, dwErr)
  9352. }
  9353. BOOL
  9354. ILS_OpenAllElementsFromDirectory(
  9355. IN LPCWSTR pwszStoreDir,
  9356. IN LPCWSTR pwszContextName,
  9357. IN DWORD dwFlags,
  9358. IN void *pvArg,
  9359. IN PFN_ILS_OPEN_ELEMENT pfnOpenElement
  9360. )
  9361. {
  9362. BOOL fResult;
  9363. DWORD dwErr;
  9364. LPWSTR pwszDir = NULL;
  9365. LPCWSTR rgpwszName[] = { pwszStoreDir, pwszContextName, L"*" };
  9366. SYSTEM_NAME_GROUP NameGroup;
  9367. HANDLE hFindFile = INVALID_HANDLE_VALUE;
  9368. WIN32_FIND_DATAW FindFileData;
  9369. NameGroup.cName = sizeof(rgpwszName) / sizeof(rgpwszName[0]);
  9370. NameGroup.rgpwszName = rgpwszName;
  9371. if (NULL == (pwszDir = FormatSystemNamePath(1, &NameGroup)))
  9372. goto FormatSystemNamePathError;
  9373. if (INVALID_HANDLE_VALUE == (hFindFile = FindFirstFileU(
  9374. pwszDir,
  9375. &FindFileData
  9376. ))) {
  9377. dwErr = GetLastError();
  9378. if (!(ERROR_PATH_NOT_FOUND == dwErr || ERROR_FILE_NOT_FOUND == dwErr))
  9379. goto FindFirstFileError;
  9380. if (dwFlags & CERT_STORE_READONLY_FLAG)
  9381. goto FindFirstFileError;
  9382. // Attempt to create the directory. Need to remove trailing L"*".
  9383. PkiFree(pwszDir);
  9384. NameGroup.cName--;
  9385. if (NULL == (pwszDir = FormatSystemNamePath(1, &NameGroup)))
  9386. goto FormatSystemNamePathError;
  9387. if (!I_RecursiveCreateDirectory(pwszDir, NULL))
  9388. goto CreateDirError;
  9389. goto SuccessReturn;
  9390. }
  9391. while (TRUE) {
  9392. if (0 == (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes) &&
  9393. 0 == FindFileData.nFileSizeHigh &&
  9394. 0 != FindFileData.nFileSizeLow &&
  9395. L'\0' != FindFileData.cFileName[0]) {
  9396. BYTE *pbElement;
  9397. DWORD cbElement;
  9398. if (ILS_ReadElementFromFile(
  9399. pwszStoreDir,
  9400. pwszContextName,
  9401. FindFileData.cFileName,
  9402. dwFlags,
  9403. &pbElement,
  9404. &cbElement
  9405. )) {
  9406. fResult = pfnOpenElement(
  9407. FindFileData.cFileName,
  9408. pbElement,
  9409. cbElement,
  9410. pvArg
  9411. );
  9412. PkiFree(pbElement);
  9413. if (!fResult)
  9414. goto CommonReturn;
  9415. }
  9416. }
  9417. if (!FindNextFileU(hFindFile, &FindFileData)) {
  9418. dwErr = GetLastError();
  9419. if (ERROR_NO_MORE_FILES == dwErr)
  9420. goto SuccessReturn;
  9421. else
  9422. goto FindNextFileError;
  9423. }
  9424. }
  9425. SuccessReturn:
  9426. fResult = TRUE;
  9427. CommonReturn:
  9428. PkiFree(pwszDir);
  9429. if (INVALID_HANDLE_VALUE != hFindFile) {
  9430. dwErr = GetLastError();
  9431. FindClose(hFindFile);
  9432. SetLastError(dwErr);
  9433. }
  9434. return fResult;
  9435. ErrorReturn:
  9436. fResult = FALSE;
  9437. goto CommonReturn;
  9438. TRACE_ERROR(FormatSystemNamePathError)
  9439. SET_ERROR_VAR(FindFirstFileError, dwErr)
  9440. TRACE_ERROR(CreateDirError)
  9441. SET_ERROR_VAR(FindNextFileError, dwErr)
  9442. }
  9443. //+=========================================================================
  9444. // Registry or Roaming Store Change Notify Functions
  9445. //==========================================================================
  9446. STATIC VOID NTAPI RegistryStoreChangeCallback(
  9447. PVOID Context,
  9448. BOOLEAN fWaitOrTimedOut // ???
  9449. )
  9450. {
  9451. BOOL fRearm;
  9452. DWORD dwErr = 0;
  9453. PREG_STORE pRegStore = (PREG_STORE) Context;
  9454. PREGISTRY_STORE_CHANGE_INFO pInfo;
  9455. DWORD cEntry;
  9456. PILS_RESYNC_ENTRY pEntry;
  9457. pInfo = pRegStore->pRegistryStoreChangeInfo;
  9458. assert(pInfo);
  9459. if (NULL == pInfo)
  9460. return;
  9461. CertPerfIncrementChangeNotifyCount();
  9462. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_ROAMING_FLAG) {
  9463. fRearm = FindNextChangeNotification(pInfo->hChange);
  9464. CertPerfIncrementChangeNotifyCuMyCount();
  9465. } else {
  9466. fRearm = ILS_RegNotifyChangeKeyValue(pRegStore->hKey, pInfo->hChange);
  9467. CertPerfIncrementChangeNotifyRegCount();
  9468. }
  9469. if (!fRearm)
  9470. dwErr = GetLastError();
  9471. // Minimize window of potential deadlock by only getting the values
  9472. // while holding the lock.
  9473. LockRegStore(pRegStore);
  9474. cEntry = pInfo->cNotifyEntry;
  9475. pEntry = pInfo->rgNotifyEntry;
  9476. pInfo->cNotifyEntry = 0;
  9477. pInfo->rgNotifyEntry = NULL;
  9478. UnlockRegStore(pRegStore);
  9479. ILS_SignalEventsOnResyncList(&cEntry, &pEntry);
  9480. if (!fRearm)
  9481. goto RegistryStoreChangeRearmError;
  9482. CommonReturn:
  9483. return;
  9484. ErrorReturn:
  9485. goto CommonReturn;
  9486. SET_ERROR_VAR(RegistryStoreChangeRearmError, dwErr)
  9487. }
  9488. // Upon entry/exit the pRegStore is locked
  9489. STATIC BOOL InitRegistryStoreChange(
  9490. IN PREG_STORE pRegStore
  9491. )
  9492. {
  9493. BOOL fResult;
  9494. DWORD dwErr;
  9495. BOOL fRoaming;
  9496. PREGISTRY_STORE_CHANGE_INFO pInfo = NULL;
  9497. HANDLE hChange = INVALID_HANDLE_VALUE;
  9498. HANDLE hRegWaitFor;
  9499. fRoaming = (pRegStore->dwFlags & CERT_REGISTRY_STORE_ROAMING_FLAG);
  9500. assert(NULL == pRegStore->pRegistryStoreChangeInfo);
  9501. if (NULL == (pInfo = (PREGISTRY_STORE_CHANGE_INFO) PkiZeroAlloc(
  9502. sizeof(REGISTRY_STORE_CHANGE_INFO))))
  9503. goto OutOfMemory;
  9504. pInfo->dwType = REG_CHANGE_INFO_TYPE;
  9505. if (fRoaming) {
  9506. if (INVALID_HANDLE_VALUE == (hChange = FindFirstChangeNotificationU(
  9507. pRegStore->pwszStoreDirectory,
  9508. TRUE, // bWatchSubtree
  9509. FILE_NOTIFY_CHANGE_FILE_NAME |
  9510. FILE_NOTIFY_CHANGE_DIR_NAME |
  9511. FILE_NOTIFY_CHANGE_SIZE |
  9512. FILE_NOTIFY_CHANGE_LAST_WRITE
  9513. ))) {
  9514. dwErr = GetLastError();
  9515. goto FindFirstChangeNotificationError;
  9516. }
  9517. } else {
  9518. if (NULL == (hChange = CreateEvent(
  9519. NULL, // lpsa
  9520. FALSE, // fManualReset
  9521. FALSE, // fInitialState
  9522. NULL))) // lpszEventName
  9523. goto CreateEventError;
  9524. assert(pRegStore->hKey);
  9525. if (!ILS_RegNotifyChangeKeyValue(pRegStore->hKey, hChange))
  9526. goto RegNotifyChangeKeyValueError;
  9527. }
  9528. pInfo->hChange = hChange;
  9529. // The following must be set before the following register.
  9530. // The thread may be scheduled to run before the function returns.
  9531. pRegStore->pRegistryStoreChangeInfo = pInfo;
  9532. if (!pfnILS_RegisterWaitForSingleObject(
  9533. &hRegWaitFor,
  9534. hChange,
  9535. RegistryStoreChangeCallback,
  9536. (PVOID) pRegStore,
  9537. INFINITE, // no timeout
  9538. WT_EXECUTEINWAITTHREAD
  9539. )) {
  9540. pRegStore->pRegistryStoreChangeInfo = NULL;
  9541. dwErr = GetLastError();
  9542. goto RegisterWaitForError;
  9543. }
  9544. pInfo->hRegWaitFor = hRegWaitFor;
  9545. fResult = TRUE;
  9546. CommonReturn:
  9547. return fResult;
  9548. ErrorReturn:
  9549. if (INVALID_HANDLE_VALUE != hChange && hChange) {
  9550. dwErr = GetLastError();
  9551. if (fRoaming)
  9552. FindCloseChangeNotification(hChange);
  9553. else
  9554. CloseHandle(hChange);
  9555. SetLastError(dwErr);
  9556. }
  9557. PkiFree(pInfo);
  9558. fResult = FALSE;
  9559. goto CommonReturn;
  9560. TRACE_ERROR(OutOfMemory)
  9561. SET_ERROR_VAR(FindFirstChangeNotificationError, dwErr)
  9562. TRACE_ERROR(CreateEventError)
  9563. TRACE_ERROR(RegNotifyChangeKeyValueError)
  9564. SET_ERROR_VAR(RegisterWaitForError, dwErr)
  9565. }
  9566. STATIC BOOL RegRegistryStoreChange(
  9567. IN PREG_STORE pRegStore,
  9568. IN HANDLE hEvent,
  9569. IN DWORD dwFlags
  9570. )
  9571. {
  9572. BOOL fResult;
  9573. PREGISTRY_STORE_CHANGE_INFO pInfo;
  9574. LockRegStore(pRegStore);
  9575. if (NULL == (pInfo = pRegStore->pRegistryStoreChangeInfo)) {
  9576. if (!InitRegistryStoreChange(pRegStore))
  9577. goto ChangeInitError;
  9578. pInfo = pRegStore->pRegistryStoreChangeInfo;
  9579. assert(pInfo);
  9580. assert(REG_CHANGE_INFO_TYPE == pInfo->dwType);
  9581. }
  9582. if (!ILS_AddRemoveEventToFromResyncList(
  9583. pRegStore,
  9584. hEvent,
  9585. dwFlags,
  9586. &pInfo->cNotifyEntry,
  9587. &pInfo->rgNotifyEntry
  9588. ))
  9589. goto AddRemoveEventError;
  9590. fResult = TRUE;
  9591. CommonReturn:
  9592. UnlockRegStore(pRegStore);
  9593. return fResult;
  9594. ErrorReturn:
  9595. fResult = FALSE;
  9596. goto CommonReturn;
  9597. TRACE_ERROR(ChangeInitError)
  9598. TRACE_ERROR(AddRemoveEventError)
  9599. }
  9600. STATIC void FreeRegistryStoreChange(
  9601. IN PREG_STORE pRegStore
  9602. )
  9603. {
  9604. PREGISTRY_STORE_CHANGE_INFO pInfo;
  9605. if (NULL == (pInfo = pRegStore->pRegistryStoreChangeInfo))
  9606. return;
  9607. if (REG_CHANGE_INFO_TYPE != pInfo->dwType)
  9608. return;
  9609. assert(pInfo->hRegWaitFor);
  9610. pfnILS_UnregisterWaitEx(pInfo->hRegWaitFor, INVALID_HANDLE_VALUE);
  9611. assert(pInfo->hChange);
  9612. if (pRegStore->dwFlags & CERT_REGISTRY_STORE_ROAMING_FLAG)
  9613. FindCloseChangeNotification(pInfo->hChange);
  9614. else
  9615. CloseHandle(pInfo->hChange);
  9616. ILS_SignalEventsOnResyncList(
  9617. &pInfo->cNotifyEntry,
  9618. &pInfo->rgNotifyEntry
  9619. );
  9620. PkiFree(pInfo);
  9621. pRegStore->pRegistryStoreChangeInfo = NULL;
  9622. }
  9623. //+=========================================================================
  9624. // Key Identifier Functions
  9625. //==========================================================================
  9626. STATIC HKEY OpenKeyIdStoreSubKey(
  9627. IN DWORD dwFlags,
  9628. IN OPTIONAL LPCWSTR pwszComputerName
  9629. )
  9630. {
  9631. SYSTEM_NAME_INFO SystemNameInfo;
  9632. memset(&SystemNameInfo, 0, sizeof(SystemNameInfo));
  9633. SystemNameInfo.rgpwszName[SYSTEM_NAME_INDEX] = wsz_MY_STORE;
  9634. SystemNameInfo.rgpwszName[COMPUTER_NAME_INDEX] = (LPWSTR) pwszComputerName;
  9635. return OpenSystemRegPathKey(
  9636. &SystemNameInfo,
  9637. NULL, // pwszSubKeyName
  9638. dwFlags
  9639. );
  9640. }
  9641. BOOL
  9642. ILS_ReadKeyIdElement(
  9643. IN const CRYPT_HASH_BLOB *pKeyIdentifier,
  9644. IN BOOL fLocalMachine,
  9645. IN OPTIONAL LPCWSTR pwszComputerName,
  9646. OUT BYTE **ppbElement,
  9647. OUT DWORD *pcbElement
  9648. )
  9649. {
  9650. BOOL fResult;
  9651. BYTE *pbElement = NULL;
  9652. DWORD cbElement = 0;
  9653. WCHAR wszHashName[MAX_HASH_NAME_LEN];
  9654. if (0 == pKeyIdentifier->cbData || MAX_HASH_LEN < pKeyIdentifier->cbData)
  9655. goto InvalidArg;
  9656. ILS_BytesToWStr(pKeyIdentifier->cbData, pKeyIdentifier->pbData, wszHashName);
  9657. if (!fLocalMachine) {
  9658. LPWSTR pwszRoamingStoreDir;
  9659. if (pwszRoamingStoreDir = ILS_GetRoamingStoreDirectory(
  9660. ROAMING_MY_STORE_SUBDIR)) {
  9661. // Ignore BACKUP_RESTORE
  9662. fResult = ILS_ReadElementFromFile(
  9663. pwszRoamingStoreDir,
  9664. KEYID_CONTEXT_NAME,
  9665. wszHashName,
  9666. 0, // dwFlags
  9667. &pbElement,
  9668. &cbElement
  9669. );
  9670. PkiFree(pwszRoamingStoreDir);
  9671. if (!fResult) {
  9672. if (ERROR_FILE_NOT_FOUND != GetLastError())
  9673. goto ReadElementFromFileError;
  9674. } else
  9675. goto CommonReturn;
  9676. }
  9677. }
  9678. {
  9679. HKEY hKey;
  9680. DWORD dwOpenFlags;
  9681. if (fLocalMachine)
  9682. dwOpenFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
  9683. else
  9684. dwOpenFlags = CERT_SYSTEM_STORE_CURRENT_USER;
  9685. if (NULL == (hKey = OpenKeyIdStoreSubKey(
  9686. dwOpenFlags | CERT_STORE_READONLY_FLAG,
  9687. pwszComputerName
  9688. )))
  9689. goto OpenKeyIdStoreSubKeyError;
  9690. // Ignore BACKUP_RESTORE
  9691. fResult = ILS_ReadElementFromRegistry(
  9692. hKey,
  9693. KEYID_CONTEXT_NAME,
  9694. wszHashName,
  9695. 0, // dwFlags
  9696. &pbElement,
  9697. &cbElement
  9698. );
  9699. ILS_CloseRegistryKey(hKey);
  9700. if (!fResult)
  9701. goto ReadElementFromRegistryError;
  9702. }
  9703. fResult = TRUE;
  9704. CommonReturn:
  9705. *ppbElement = pbElement;
  9706. *pcbElement = cbElement;
  9707. return fResult;
  9708. ErrorReturn:
  9709. assert(NULL == pbElement && 0 == cbElement);
  9710. fResult = FALSE;
  9711. goto CommonReturn;
  9712. SET_ERROR(InvalidArg, E_INVALIDARG)
  9713. TRACE_ERROR(ReadElementFromFileError)
  9714. TRACE_ERROR(OpenKeyIdStoreSubKeyError)
  9715. TRACE_ERROR(ReadElementFromRegistryError)
  9716. }
  9717. BOOL
  9718. ILS_WriteKeyIdElement(
  9719. IN const CRYPT_HASH_BLOB *pKeyIdentifier,
  9720. IN BOOL fLocalMachine,
  9721. IN OPTIONAL LPCWSTR pwszComputerName,
  9722. IN const BYTE *pbElement,
  9723. IN DWORD cbElement
  9724. )
  9725. {
  9726. BOOL fResult;
  9727. WCHAR wszHashName[MAX_HASH_NAME_LEN];
  9728. if (0 == pKeyIdentifier->cbData || MAX_HASH_LEN < pKeyIdentifier->cbData)
  9729. goto InvalidArg;
  9730. ILS_BytesToWStr(pKeyIdentifier->cbData, pKeyIdentifier->pbData, wszHashName);
  9731. if (!fLocalMachine) {
  9732. LPWSTR pwszRoamingStoreDir;
  9733. if (pwszRoamingStoreDir = ILS_GetRoamingStoreDirectory(
  9734. ROAMING_MY_STORE_SUBDIR)) {
  9735. // Ignore BACKUP_RESTORE
  9736. fResult = ILS_WriteElementToFile(
  9737. pwszRoamingStoreDir,
  9738. KEYID_CONTEXT_NAME,
  9739. wszHashName,
  9740. 0, // dwFlags
  9741. pbElement,
  9742. cbElement
  9743. );
  9744. PkiFree(pwszRoamingStoreDir);
  9745. if (!fResult)
  9746. goto WriteElementToFileError;
  9747. else
  9748. goto CommonReturn;
  9749. }
  9750. }
  9751. {
  9752. HKEY hKey;
  9753. DWORD dwOpenFlags;
  9754. if (fLocalMachine)
  9755. dwOpenFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
  9756. else
  9757. dwOpenFlags = CERT_SYSTEM_STORE_CURRENT_USER;
  9758. if (NULL == (hKey = OpenKeyIdStoreSubKey(
  9759. dwOpenFlags,
  9760. pwszComputerName
  9761. )))
  9762. goto OpenKeyIdStoreSubKeyError;
  9763. // Ignore BACKUP_RESTORE
  9764. fResult = ILS_WriteElementToRegistry(
  9765. hKey,
  9766. KEYID_CONTEXT_NAME,
  9767. wszHashName,
  9768. 0, // dwFlags
  9769. pbElement,
  9770. cbElement
  9771. );
  9772. ILS_CloseRegistryKey(hKey);
  9773. if (!fResult)
  9774. goto WriteElementToRegistryError;
  9775. }
  9776. fResult = TRUE;
  9777. CommonReturn:
  9778. return fResult;
  9779. ErrorReturn:
  9780. fResult = FALSE;
  9781. goto CommonReturn;
  9782. SET_ERROR(InvalidArg, E_INVALIDARG)
  9783. TRACE_ERROR(WriteElementToFileError)
  9784. TRACE_ERROR(OpenKeyIdStoreSubKeyError)
  9785. TRACE_ERROR(WriteElementToRegistryError)
  9786. }
  9787. BOOL
  9788. ILS_DeleteKeyIdElement(
  9789. IN const CRYPT_HASH_BLOB *pKeyIdentifier,
  9790. IN BOOL fLocalMachine,
  9791. IN OPTIONAL LPCWSTR pwszComputerName
  9792. )
  9793. {
  9794. BOOL fResult;
  9795. WCHAR wszHashName[MAX_HASH_NAME_LEN];
  9796. if (0 == pKeyIdentifier->cbData || MAX_HASH_LEN < pKeyIdentifier->cbData)
  9797. goto InvalidArg;
  9798. ILS_BytesToWStr(pKeyIdentifier->cbData, pKeyIdentifier->pbData, wszHashName);
  9799. if (!fLocalMachine) {
  9800. LPWSTR pwszRoamingStoreDir;
  9801. if (pwszRoamingStoreDir = ILS_GetRoamingStoreDirectory(
  9802. ROAMING_MY_STORE_SUBDIR)) {
  9803. // Ignore BACKUP_RESTORE
  9804. fResult = ILS_DeleteElementFromDirectory(
  9805. pwszRoamingStoreDir,
  9806. KEYID_CONTEXT_NAME,
  9807. wszHashName,
  9808. 0 // dwFlags
  9809. );
  9810. PkiFree(pwszRoamingStoreDir);
  9811. if (!fResult)
  9812. goto DeleteElementFromDirectoryError;
  9813. else
  9814. goto CommonReturn;
  9815. }
  9816. }
  9817. {
  9818. HKEY hKey;
  9819. DWORD dwOpenFlags;
  9820. if (fLocalMachine)
  9821. dwOpenFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
  9822. else
  9823. dwOpenFlags = CERT_SYSTEM_STORE_CURRENT_USER;
  9824. if (NULL == (hKey = OpenKeyIdStoreSubKey(
  9825. dwOpenFlags,
  9826. pwszComputerName
  9827. )))
  9828. goto OpenKeyIdStoreSubKeyError;
  9829. // Ignore BACKUP_RESTORE
  9830. fResult = ILS_DeleteElementFromRegistry(
  9831. hKey,
  9832. KEYID_CONTEXT_NAME,
  9833. wszHashName,
  9834. 0 // dwFlags
  9835. );
  9836. ILS_CloseRegistryKey(hKey);
  9837. if (!fResult)
  9838. goto DeleteElementFromRegistryError;
  9839. }
  9840. fResult = TRUE;
  9841. CommonReturn:
  9842. return fResult;
  9843. ErrorReturn:
  9844. fResult = FALSE;
  9845. goto CommonReturn;
  9846. SET_ERROR(InvalidArg, E_INVALIDARG)
  9847. TRACE_ERROR(DeleteElementFromDirectoryError)
  9848. TRACE_ERROR(OpenKeyIdStoreSubKeyError)
  9849. TRACE_ERROR(DeleteElementFromRegistryError)
  9850. }
  9851. typedef struct _OPEN_KEYID_CALLBACK_ARG {
  9852. void *pvArg;
  9853. PFN_ILS_OPEN_KEYID_ELEMENT pfnOpenKeyId;
  9854. } OPEN_KEYID_CALLBACK_ARG, *POPEN_KEYID_CALLBACK_ARG;
  9855. STATIC BOOL OpenKeyIdElementCallback(
  9856. IN const WCHAR wszHashName[MAX_HASH_NAME_LEN],
  9857. IN const BYTE *pbElement,
  9858. IN DWORD cbElement,
  9859. IN void *pvArg
  9860. )
  9861. {
  9862. POPEN_KEYID_CALLBACK_ARG pKeyIdArg = (POPEN_KEYID_CALLBACK_ARG) pvArg;
  9863. DWORD cbHash;
  9864. BYTE rgbHash[MAX_HASH_LEN];
  9865. CRYPT_HASH_BLOB KeyIdentifier;
  9866. WStrToBytes(wszHashName, rgbHash, &cbHash);
  9867. KeyIdentifier.cbData = cbHash;
  9868. KeyIdentifier.pbData = rgbHash;
  9869. return pKeyIdArg->pfnOpenKeyId(
  9870. &KeyIdentifier,
  9871. pbElement,
  9872. cbElement,
  9873. pKeyIdArg->pvArg
  9874. );
  9875. }
  9876. BOOL
  9877. ILS_OpenAllKeyIdElements(
  9878. IN BOOL fLocalMachine,
  9879. IN OPTIONAL LPCWSTR pwszComputerName,
  9880. IN void *pvArg,
  9881. IN PFN_ILS_OPEN_KEYID_ELEMENT pfnOpenKeyId
  9882. )
  9883. {
  9884. BOOL fResult;
  9885. BOOL fOpenFile = FALSE;
  9886. OPEN_KEYID_CALLBACK_ARG KeyIdArg = { pvArg, pfnOpenKeyId };
  9887. if (!fLocalMachine) {
  9888. LPWSTR pwszRoamingStoreDir;
  9889. if (pwszRoamingStoreDir = ILS_GetRoamingStoreDirectory(
  9890. ROAMING_MY_STORE_SUBDIR)) {
  9891. // Ignore BACKUP_RESTORE
  9892. fResult = ILS_OpenAllElementsFromDirectory(
  9893. pwszRoamingStoreDir,
  9894. KEYID_CONTEXT_NAME,
  9895. 0, // dwFlags
  9896. (void *) &KeyIdArg,
  9897. OpenKeyIdElementCallback
  9898. );
  9899. PkiFree(pwszRoamingStoreDir);
  9900. if (!fResult)
  9901. goto ErrorReturn;
  9902. else
  9903. fOpenFile = TRUE;
  9904. }
  9905. }
  9906. {
  9907. HKEY hKey;
  9908. DWORD dwOpenFlags;
  9909. if (fLocalMachine)
  9910. dwOpenFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
  9911. else
  9912. dwOpenFlags = CERT_SYSTEM_STORE_CURRENT_USER;
  9913. if (NULL == (hKey = OpenKeyIdStoreSubKey(
  9914. dwOpenFlags | CERT_STORE_READONLY_FLAG,
  9915. pwszComputerName
  9916. )))
  9917. goto OpenKeyIdStoreSubKeyError;
  9918. // Ignore BACKUP_RESTORE
  9919. fResult = ILS_OpenAllElementsFromRegistry(
  9920. hKey,
  9921. KEYID_CONTEXT_NAME,
  9922. 0, // dwFlags
  9923. (void *) &KeyIdArg,
  9924. OpenKeyIdElementCallback
  9925. );
  9926. ILS_CloseRegistryKey(hKey);
  9927. }
  9928. CommonReturn:
  9929. if (fOpenFile)
  9930. // Ignore any registry errors
  9931. return TRUE;
  9932. else
  9933. return fResult;
  9934. ErrorReturn:
  9935. fResult = FALSE;
  9936. goto CommonReturn;
  9937. TRACE_ERROR(OpenKeyIdStoreSubKeyError)
  9938. }