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.

2085 lines
46 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: reg.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <pch.cpp>
  11. #pragma hdrstop
  12. #include <xenroll.h>
  13. #include "polreg.h"
  14. #include "certtype.h"
  15. #define __dwFILE__ __dwFILE_CERTUTIL_REG_CPP__
  16. // add two WCHAR L'\0's after the registry value, in case of a poorly
  17. // formed REG_MULTI_SZ. Add another to handle possible odd sizes.
  18. #define cbVALUEZEROPAD (3 * sizeof(WCHAR))
  19. typedef struct _DUMPFLAGS
  20. {
  21. DWORD Mask;
  22. DWORD Value;
  23. WCHAR const *pwszDescription;
  24. } DUMPFLAGS;
  25. #define _DFBIT(def) { (def), (def), L#def }
  26. #define _DFBIT2(mask, def) { (mask), (def), L#def }
  27. DUMPFLAGS g_adfEditFlags[] =
  28. {
  29. _DFBIT(EDITF_ENABLEREQUESTEXTENSIONS),
  30. _DFBIT(EDITF_REQUESTEXTENSIONLIST),
  31. _DFBIT(EDITF_DISABLEEXTENSIONLIST),
  32. _DFBIT(EDITF_ADDOLDKEYUSAGE),
  33. _DFBIT(EDITF_ADDOLDCERTTYPE),
  34. _DFBIT(EDITF_ATTRIBUTEENDDATE),
  35. _DFBIT(EDITF_BASICCONSTRAINTSCRITICAL),
  36. _DFBIT(EDITF_BASICCONSTRAINTSCA),
  37. _DFBIT(EDITF_ENABLEAKIKEYID),
  38. _DFBIT(EDITF_ATTRIBUTECA),
  39. _DFBIT(EDITF_IGNOREREQUESTERGROUP),
  40. _DFBIT(EDITF_ENABLEAKIISSUERNAME),
  41. _DFBIT(EDITF_ENABLEAKIISSUERSERIAL),
  42. _DFBIT(EDITF_ENABLEAKICRITICAL),
  43. _DFBIT(EDITF_SERVERUPGRADED),
  44. _DFBIT(EDITF_ATTRIBUTEEKU),
  45. _DFBIT(EDITF_ENABLEDEFAULTSMIME),
  46. _DFBIT(EDITF_EMAILOPTIONAL),
  47. _DFBIT(EDITF_ATTRIBUTESUBJECTALTNAME2),
  48. _DFBIT(EDITF_ENABLELDAPREFERRALS),
  49. _DFBIT(EDITF_ENABLECHASECLIENTDC),
  50. { 0, 0, NULL }
  51. };
  52. DUMPFLAGS g_adfCRLFlags[] =
  53. {
  54. _DFBIT(CRLF_DELTA_USE_OLDEST_UNEXPIRED_BASE),
  55. _DFBIT(CRLF_DELETE_EXPIRED_CRLS),
  56. _DFBIT(CRLF_CRLNUMBER_CRITICAL),
  57. _DFBIT(CRLF_REVCHECK_IGNORE_OFFLINE),
  58. _DFBIT(CRLF_IGNORE_INVALID_POLICIES),
  59. _DFBIT(CRLF_REBUILD_MODIFIED_SUBJECT_ONLY),
  60. _DFBIT(CRLF_SAVE_FAILED_CERTS),
  61. _DFBIT(CRLF_IGNORE_UNKNOWN_CMC_ATTRIBUTES),
  62. _DFBIT(CRLF_IGNORE_CROSS_CERT_TRUST_ERROR),
  63. _DFBIT(CRLF_PUBLISH_EXPIRED_CERT_CRLS),
  64. _DFBIT(CRLF_ENFORCE_ENROLLMENT_AGENT),
  65. _DFBIT(CRLF_DISABLE_RDN_REORDER),
  66. _DFBIT(CRLF_DISABLE_ROOT_CROSS_CERTS),
  67. _DFBIT(CRLF_LOG_FULL_RESPONSE),
  68. _DFBIT(CRLF_USE_XCHG_CERT_TEMPLATE),
  69. _DFBIT(CRLF_USE_CROSS_CERT_TEMPLATE),
  70. _DFBIT(CRLF_ALLOW_REQUEST_ATTRIBUTE_SUBJECT),
  71. _DFBIT(CRLF_REVCHECK_IGNORE_NOREVCHECK),
  72. _DFBIT(CRLF_PRESERVE_EXPIRED_CA_CERTS),
  73. _DFBIT(CRLF_PRESERVE_REVOKED_CA_CERTS),
  74. { 0, 0, NULL }
  75. };
  76. DUMPFLAGS g_adfInterfaceFlags[] =
  77. {
  78. _DFBIT(IF_LOCKICERTREQUEST),
  79. _DFBIT(IF_NOREMOTEICERTREQUEST),
  80. _DFBIT(IF_NOLOCALICERTREQUEST),
  81. _DFBIT(IF_NORPCICERTREQUEST),
  82. _DFBIT(IF_NOREMOTEICERTADMIN),
  83. _DFBIT(IF_NOLOCALICERTADMIN),
  84. _DFBIT(IF_NOREMOTEICERTADMINBACKUP),
  85. _DFBIT(IF_NOLOCALICERTADMINBACKUP),
  86. _DFBIT(IF_NOSNAPSHOTBACKUP),
  87. _DFBIT(IF_ENFORCEENCRYPTICERTREQUEST),
  88. _DFBIT(IF_ENFORCEENCRYPTICERTADMIN),
  89. { 0, 0, NULL }
  90. };
  91. DUMPFLAGS g_adfKRAFlags[] =
  92. {
  93. _DFBIT(KRAF_ENABLEFOREIGN),
  94. _DFBIT(KRAF_SAVEBADREQUESTKEY),
  95. _DFBIT(KRAF_ENABLEARCHIVEALL),
  96. { 0, 0, NULL }
  97. };
  98. DUMPFLAGS g_adfDBFlags[] =
  99. {
  100. _DFBIT(DBFLAGS_READONLY),
  101. _DFBIT(DBFLAGS_CREATEIFNEEDED),
  102. _DFBIT(DBFLAGS_CIRCULARLOGGING),
  103. _DFBIT(DBFLAGS_LAZYFLUSH),
  104. _DFBIT(DBFLAGS_MAXCACHESIZEX100),
  105. _DFBIT(DBFLAGS_CHECKPOINTDEPTH60MB),
  106. _DFBIT(DBFLAGS_LOGBUFFERSLARGE),
  107. _DFBIT(DBFLAGS_LOGBUFFERSHUGE),
  108. _DFBIT(DBFLAGS_LOGFILESIZE16MB),
  109. _DFBIT(DBFLAGS_MULTITHREADTRANSACTIONS),
  110. { 0, 0, NULL }
  111. };
  112. DUMPFLAGS g_adfLDAPFlags[] =
  113. {
  114. _DFBIT(LDAPF_SSLENABLE),
  115. _DFBIT(LDAPF_SIGNDISABLE),
  116. { 0, 0, NULL }
  117. };
  118. #define ISSCERT_LDAPURL ISSCERT_LDAPURL_OLD
  119. #define ISSCERT_HTTPURL ISSCERT_HTTPURL_OLD
  120. #define ISSCERT_FTPURL ISSCERT_FTPURL_OLD
  121. #define ISSCERT_FILEURL ISSCERT_FILEURL_OLD
  122. DUMPFLAGS g_adfIssuercertFlags[] =
  123. {
  124. _DFBIT(ISSCERT_LDAPURL),
  125. _DFBIT(ISSCERT_HTTPURL),
  126. _DFBIT(ISSCERT_FTPURL),
  127. _DFBIT(ISSCERT_FILEURL),
  128. _DFBIT(ISSCERT_ENABLE),
  129. { 0, 0, NULL }
  130. };
  131. DUMPFLAGS g_adfRequestDispositionFlags[] =
  132. {
  133. _DFBIT2(REQDISP_MASK, REQDISP_PENDING),
  134. _DFBIT2(REQDISP_MASK, REQDISP_ISSUE),
  135. _DFBIT2(REQDISP_MASK, REQDISP_DENY),
  136. _DFBIT2(REQDISP_MASK, REQDISP_USEREQUESTATTRIBUTE),
  137. _DFBIT(REQDISP_PENDINGFIRST),
  138. { 0, 0, NULL }
  139. };
  140. #define REVEXT_CDPLDAPURL REVEXT_CDPLDAPURL_OLD
  141. #define REVEXT_CDPHTTPURL REVEXT_CDPHTTPURL_OLD
  142. #define REVEXT_CDPFTPURL REVEXT_CDPFTPURL_OLD
  143. #define REVEXT_CDPFILEURL REVEXT_CDPFILEURL_OLD
  144. DUMPFLAGS g_adfRevocationTypeFlags[] =
  145. {
  146. _DFBIT(REVEXT_CDPLDAPURL),
  147. _DFBIT(REVEXT_CDPHTTPURL),
  148. _DFBIT(REVEXT_CDPFTPURL),
  149. _DFBIT(REVEXT_CDPFILEURL),
  150. _DFBIT(REVEXT_CDPENABLE),
  151. _DFBIT(REVEXT_ASPENABLE),
  152. { 0, 0, NULL }
  153. };
  154. DUMPFLAGS g_adfSetupStatus[] =
  155. {
  156. _DFBIT(SETUP_SERVER_FLAG),
  157. _DFBIT(SETUP_CLIENT_FLAG),
  158. _DFBIT(SETUP_SUSPEND_FLAG),
  159. _DFBIT(SETUP_REQUEST_FLAG),
  160. _DFBIT(SETUP_ONLINE_FLAG),
  161. _DFBIT(SETUP_DENIED_FLAG),
  162. _DFBIT(SETUP_CREATEDB_FLAG),
  163. _DFBIT(SETUP_ATTEMPT_VROOT_CREATE),
  164. _DFBIT(SETUP_FORCECRL_FLAG),
  165. _DFBIT(SETUP_UPDATE_CAOBJECT_SVRTYPE),
  166. _DFBIT(SETUP_SERVER_UPGRADED_FLAG),
  167. _DFBIT(SETUP_SECURITY_CHANGED),
  168. _DFBIT(SETUP_W2K_SECURITY_NOT_UPGRADED_FLAG),
  169. { 0, 0, NULL }
  170. };
  171. DUMPFLAGS g_adfCertPublishFlags[] =
  172. {
  173. _DFBIT(EXITPUB_FILE),
  174. _DFBIT(EXITPUB_ACTIVEDIRECTORY),
  175. { 0, 0, NULL }
  176. };
  177. DUMPFLAGS g_adfCAType[] =
  178. {
  179. _DFBIT2(MAXDWORD, ENUM_ENTERPRISE_ROOTCA),
  180. _DFBIT2(MAXDWORD, ENUM_ENTERPRISE_SUBCA),
  181. _DFBIT2(MAXDWORD, ENUM_STANDALONE_ROOTCA),
  182. _DFBIT2(MAXDWORD, ENUM_STANDALONE_SUBCA),
  183. _DFBIT2(MAXDWORD, ENUM_UNKNOWN_CA),
  184. { 0, 0, NULL }
  185. };
  186. DUMPFLAGS g_adfForceTeletex[] =
  187. {
  188. _DFBIT2(ENUM_TELETEX_MASK, ENUM_TELETEX_OFF),
  189. _DFBIT2(ENUM_TELETEX_MASK, ENUM_TELETEX_ON),
  190. _DFBIT2(ENUM_TELETEX_MASK, ENUM_TELETEX_AUTO),
  191. _DFBIT2(ENUM_TELETEX_UTF8, ENUM_TELETEX_UTF8),
  192. { 0, 0, NULL }
  193. };
  194. DUMPFLAGS g_adfCSURL[] =
  195. {
  196. _DFBIT(CSURL_SERVERPUBLISH),
  197. _DFBIT(CSURL_ADDTOCERTCDP),
  198. _DFBIT(CSURL_ADDTOFRESHESTCRL),
  199. _DFBIT(CSURL_ADDTOCRLCDP),
  200. _DFBIT(CSURL_PUBLISHRETRY),
  201. _DFBIT(CSURL_ADDTOCERTOCSP),
  202. _DFBIT(CSURL_SERVERPUBLISHDELTA),
  203. { 0, 0, NULL }
  204. };
  205. // Enrollment Flags:
  206. DUMPFLAGS g_adfTemplateEnroll[] =
  207. {
  208. _DFBIT(CT_FLAG_INCLUDE_SYMMETRIC_ALGORITHMS),
  209. _DFBIT(CT_FLAG_PEND_ALL_REQUESTS),
  210. _DFBIT(CT_FLAG_PUBLISH_TO_KRA_CONTAINER),
  211. _DFBIT(CT_FLAG_PUBLISH_TO_DS),
  212. _DFBIT(CT_FLAG_AUTO_ENROLLMENT_CHECK_USER_DS_CERTIFICATE),
  213. _DFBIT(CT_FLAG_AUTO_ENROLLMENT),
  214. _DFBIT(CT_FLAG_PREVIOUS_APPROVAL_VALIDATE_REENROLLMENT),
  215. _DFBIT(CT_FLAG_DOMAIN_AUTHENTICATION_NOT_REQUIRED),
  216. _DFBIT(CT_FLAG_USER_INTERACTION_REQUIRED),
  217. _DFBIT(CT_FLAG_ADD_TEMPLATE_NAME),
  218. _DFBIT(CT_FLAG_REMOVE_INVALID_CERTIFICATE_FROM_PERSONAL_STORE),
  219. _DFBIT(CT_FLAG_ALLOW_ENROLL_ON_BEHALF_OF),
  220. { 0, 0, NULL }
  221. };
  222. // Certificate Subject Name Flags:
  223. DUMPFLAGS g_adfTemplateName[] =
  224. {
  225. _DFBIT(CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT),
  226. _DFBIT(CT_FLAG_ADD_EMAIL),
  227. _DFBIT(CT_FLAG_ADD_OBJ_GUID),
  228. _DFBIT(CT_FLAG_ADD_DIRECTORY_PATH),
  229. _DFBIT(CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT_ALT_NAME),
  230. _DFBIT(CT_FLAG_SUBJECT_ALT_REQUIRE_SPN),
  231. _DFBIT(CT_FLAG_SUBJECT_ALT_REQUIRE_DIRECTORY_GUID),
  232. _DFBIT(CT_FLAG_SUBJECT_ALT_REQUIRE_UPN),
  233. _DFBIT(CT_FLAG_SUBJECT_ALT_REQUIRE_EMAIL),
  234. _DFBIT(CT_FLAG_SUBJECT_ALT_REQUIRE_DNS),
  235. _DFBIT(CT_FLAG_SUBJECT_REQUIRE_DNS_AS_CN),
  236. _DFBIT(CT_FLAG_SUBJECT_REQUIRE_EMAIL),
  237. _DFBIT(CT_FLAG_SUBJECT_REQUIRE_COMMON_NAME),
  238. _DFBIT(CT_FLAG_SUBJECT_REQUIRE_DIRECTORY_PATH),
  239. { 0, 0, NULL }
  240. };
  241. DUMPFLAGS g_adfTemplatePrivateKey[] =
  242. {
  243. // Private Key Flags:
  244. _DFBIT(CT_FLAG_REQUIRE_PRIVATE_KEY_ARCHIVAL),
  245. _DFBIT(CT_FLAG_EXPORTABLE_KEY),
  246. _DFBIT(CT_FLAG_STRONG_KEY_PROTECTION_REQUIRED),
  247. { 0, 0, NULL }
  248. };
  249. // Old V1 template flags definitions:
  250. //efine CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT 0x00000001
  251. //efine CT_FLAG_ADD_EMAIL 0x00000002
  252. //efine CT_FLAG_ADD_OBJ_GUID 0x00000004
  253. //efine CT_FLAG_PUBLISH_TO_DS 0x00000008
  254. //efine CT_FLAG_EXPORTABLE_KEY 0x00000010
  255. //efine CT_FLAG_AUTO_ENROLLMENT 0x00000020
  256. //efine CT_FLAG_MACHINE_TYPE 0x00000040
  257. //efine CT_FLAG_IS_CA 0x00000080
  258. //efine CT_FLAG_ADD_DIRECTORY_PATH 0x00000100
  259. //efine CT_FLAG_ADD_TEMPLATE_NAME 0x00000200
  260. #define CT_FLAG_ADD_SUBJECT_DIRECTORY_PATH 0x00000400
  261. //efine CT_FLAG_IS_CROSS_CA 0x00000800
  262. //efine CT_FLAG_IS_DEFAULT 0x00010000
  263. //efine CT_FLAG_IS_MODIFIED 0x00020000
  264. #define CT_FLAG_IS_DELETED 0x00040000
  265. #define CT_FLAG_POLICY_MISMATCH 0x00080000
  266. // General Flags
  267. DUMPFLAGS g_adfTemplateGeneral[] =
  268. {
  269. _DFBIT(CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT),
  270. _DFBIT(CT_FLAG_ADD_EMAIL),
  271. _DFBIT(CT_FLAG_ADD_OBJ_GUID),
  272. _DFBIT(CT_FLAG_PUBLISH_TO_DS),
  273. _DFBIT(CT_FLAG_EXPORTABLE_KEY),
  274. _DFBIT(CT_FLAG_AUTO_ENROLLMENT),
  275. _DFBIT(CT_FLAG_MACHINE_TYPE),
  276. _DFBIT(CT_FLAG_IS_CA),
  277. _DFBIT(CT_FLAG_ADD_DIRECTORY_PATH),
  278. _DFBIT(CT_FLAG_ADD_TEMPLATE_NAME),
  279. _DFBIT(CT_FLAG_ADD_SUBJECT_DIRECTORY_PATH),
  280. _DFBIT(CT_FLAG_IS_CROSS_CA),
  281. _DFBIT(CT_FLAG_IS_DEFAULT),
  282. _DFBIT(CT_FLAG_IS_MODIFIED),
  283. _DFBIT(CT_FLAG_IS_DELETED),
  284. _DFBIT(CT_FLAG_POLICY_MISMATCH),
  285. { 0, 0, NULL }
  286. };
  287. DUMPFLAGS g_adfKMSCertStatus[] =
  288. {
  289. _DFBIT(CERTFLAGS_REVOKED),
  290. _DFBIT(CERTFLAGS_NOT_EXPIRED),
  291. _DFBIT(CERTFLAGS_SIGNING),
  292. _DFBIT(CERTFLAGS_SEALING),
  293. _DFBIT(CERTFLAGS_CURRENT),
  294. _DFBIT(CERTFLAGS_IMPORTED),
  295. _DFBIT2(CERTFLAGS_VERSION_3, CERTFLAGS_VERSION_1),
  296. _DFBIT2(CERTFLAGS_VERSION_3, CERTFLAGS_VERSION_3),
  297. { 0, 0, NULL }
  298. };
  299. DUMPFLAGS g_adfCRLPublishFlags[] =
  300. {
  301. _DFBIT(CPF_BASE),
  302. _DFBIT(CPF_DELTA),
  303. _DFBIT(CPF_COMPLETE),
  304. _DFBIT(CPF_SHADOW),
  305. _DFBIT(CPF_CASTORE_ERROR),
  306. _DFBIT(CPF_BADURL_ERROR),
  307. _DFBIT(CPF_MANUAL),
  308. _DFBIT(CPF_SIGNATURE_ERROR),
  309. _DFBIT(CPF_LDAP_ERROR),
  310. _DFBIT(CPF_FILE_ERROR),
  311. _DFBIT(CPF_FTP_ERROR),
  312. _DFBIT(CPF_HTTP_ERROR),
  313. { 0, 0, NULL }
  314. };
  315. DUMPFLAGS g_adfCAFlags[] =
  316. {
  317. _DFBIT(CA_FLAG_NO_TEMPLATE_SUPPORT),
  318. _DFBIT(CA_FLAG_SUPPORTS_NT_AUTHENTICATION),
  319. _DFBIT(CA_FLAG_CA_SUPPORTS_MANUAL_AUTHENTICATION),
  320. _DFBIT(CA_FLAG_CA_SERVERTYPE_ADVANCED),
  321. { 0, 0, NULL }
  322. };
  323. DUMPFLAGS g_adfOIDFlags[] =
  324. {
  325. _DFBIT2(MAXDWORD, CERT_OID_TYPE_TEMPLATE),
  326. _DFBIT2(MAXDWORD, CERT_OID_TYPE_ISSUER_POLICY),
  327. _DFBIT2(MAXDWORD, CERT_OID_TYPE_APPLICATION_POLICY),
  328. { 0, 0, NULL }
  329. };
  330. DUMPFLAGS g_adfRequestClientId[] =
  331. {
  332. _DFBIT2(MAXDWORD, XECI_DISABLE),
  333. _DFBIT2(MAXDWORD, XECI_XENROLL),
  334. _DFBIT2(MAXDWORD, XECI_AUTOENROLL),
  335. _DFBIT2(MAXDWORD, XECI_REQWIZARD),
  336. _DFBIT2(MAXDWORD, XECI_CERTREQ),
  337. { 0, 0, NULL }
  338. };
  339. DUMPFLAGS g_adfSMTPEventFilter[] =
  340. {
  341. #ifndef EXITEVENT_CERTUNREVOKED
  342. #define EXITEVENT_CERTUNREVOKED 0x100
  343. #endif
  344. _DFBIT(EXITEVENT_CERTISSUED),
  345. _DFBIT(EXITEVENT_CERTPENDING),
  346. _DFBIT(EXITEVENT_CERTDENIED),
  347. _DFBIT(EXITEVENT_CERTREVOKED),
  348. _DFBIT(EXITEVENT_CERTRETRIEVEPENDING),
  349. _DFBIT(EXITEVENT_CRLISSUED),
  350. _DFBIT(EXITEVENT_SHUTDOWN),
  351. _DFBIT(EXITEVENT_STARTUP),
  352. _DFBIT(EXITEVENT_CERTUNREVOKED),
  353. { 0, 0, NULL }
  354. };
  355. typedef struct _DUMPFLAGSREGMAP
  356. {
  357. WCHAR const *pwszRegName;
  358. DUMPFLAGS const *adf;
  359. } DUMPFLAGSREGMAP;
  360. DUMPFLAGSREGMAP g_adfrm[] = {
  361. { wszREGEDITFLAGS, g_adfEditFlags },
  362. { wszREGISSUERCERTURLFLAGS, g_adfIssuercertFlags },
  363. { wszREGREQUESTDISPOSITION, g_adfRequestDispositionFlags },
  364. { wszREGREVOCATIONTYPE, g_adfRevocationTypeFlags },
  365. { wszREGSETUPSTATUS, g_adfSetupStatus },
  366. { wszREGCERTPUBLISHFLAGS, g_adfCertPublishFlags },
  367. { wszREGCRLEDITFLAGS, g_adfEditFlags },
  368. { wszREGCRLFLAGS, g_adfCRLFlags },
  369. { wszREGKRAFLAGS, g_adfKRAFlags },
  370. { wszREGINTERFACEFLAGS, g_adfInterfaceFlags },
  371. { wszREGLDAPFLAGS, g_adfLDAPFlags },
  372. { wszREGDBFLAGS, g_adfDBFlags },
  373. { wszREGCATYPE, g_adfCAType},
  374. { wszREGWEBCLIENTCATYPE, g_adfCAType},
  375. { wszREGFORCETELETEX, g_adfForceTeletex},
  376. { CERTTYPE_RPOP_ENROLLMENT_FLAG, g_adfTemplateEnroll },
  377. { CERTTYPE_PROP_NAME_FLAG, g_adfTemplateName },
  378. { CERTTYPE_PROP_PRIVATE_KEY_FLAG, g_adfTemplatePrivateKey },
  379. //{ CERTTYPE_PROP_FLAGS, g_adfTemplateGeneral },
  380. { wszCUREGDSTEMPLATEFLAGS, g_adfTemplateGeneral },
  381. { wszCUREGDSCAFLAGS, g_adfCAFlags },
  382. //{ OID_PROP_TYPE, g_adfOIDFlags },
  383. { wszCUREGDSOIDFLAGS, g_adfOIDFlags },
  384. { wszPROPCERTIFICATEENROLLMENTFLAGS, g_adfTemplateEnroll },
  385. { wszPROPCERTIFICATEGENERALFLAGS, g_adfTemplateGeneral },
  386. { wszKMSCERTSTATUS, g_adfKMSCertStatus },
  387. { wszPROPCRLPUBLISHFLAGS, g_adfCRLPublishFlags },
  388. { wszREQUESTCLIENTID, g_adfRequestClientId },
  389. { wszREGCRLPUBLICATIONURLS, g_adfCSURL },
  390. { wszREGCACERTPUBLICATIONURLS, g_adfCSURL },
  391. { wszREGEXITSMTPEVENTFILTER, g_adfSMTPEventFilter },
  392. { NULL, NULL }
  393. };
  394. VOID
  395. cuPrintFlags(
  396. IN DWORD Flags,
  397. IN DUMPFLAGS const *pdf)
  398. {
  399. DWORD ExtraFlags = Flags;
  400. for ( ; NULL != pdf->pwszDescription; pdf++)
  401. {
  402. BOOL fSet = (Flags & pdf->Mask) == pdf->Value;
  403. if (fSet || g_fVerbose)
  404. {
  405. wprintf(
  406. L" %ws%ws -- %x",
  407. fSet? g_wszEmpty : L" " wszLPAREN,
  408. pdf->pwszDescription,
  409. pdf->Value);
  410. if (9 < pdf->Value)
  411. {
  412. wprintf(L" (%d)", pdf->Value);
  413. }
  414. if (!fSet)
  415. {
  416. wprintf(wszRPAREN);
  417. }
  418. wprintf(wszNewLine);
  419. }
  420. ExtraFlags &= ~pdf->Mask;
  421. }
  422. if (0 != ExtraFlags)
  423. {
  424. wprintf(L" 0x%x (%u)\n", ExtraFlags, ExtraFlags);
  425. }
  426. }
  427. WCHAR const *
  428. regTail(
  429. IN WCHAR const *pwszRegName)
  430. {
  431. WCHAR const *pwsz = wcsrchr(pwszRegName, L'\\');
  432. if (NULL != pwsz)
  433. {
  434. pwsz++;
  435. }
  436. else
  437. {
  438. pwsz = pwszRegName;
  439. }
  440. return(pwsz);
  441. }
  442. HRESULT
  443. cuLookupRegFlags(
  444. IN WCHAR const *pwszRegName,
  445. OUT DUMPFLAGS const **ppdf)
  446. {
  447. HRESULT hr = E_INVALIDARG;
  448. DUMPFLAGSREGMAP const *pdfrm;
  449. *ppdf = NULL;
  450. pwszRegName = regTail(pwszRegName);
  451. for (pdfrm = g_adfrm; NULL != pdfrm->pwszRegName; pdfrm++)
  452. {
  453. if (0 == mylstrcmpiS(pwszRegName, pdfrm->pwszRegName))
  454. {
  455. *ppdf = pdfrm->adf;
  456. hr = S_OK;
  457. break;
  458. }
  459. }
  460. return(hr);
  461. }
  462. VOID
  463. cuPrintRegDWord(
  464. IN DWORD Value,
  465. IN WCHAR const *pwszRegName)
  466. {
  467. HRESULT hr;
  468. pwszRegName = regTail(pwszRegName);
  469. if (0 == LSTRCMPIS(pwszRegName, wszREGVERSION))
  470. {
  471. wprintf(L" -- %u.%u", Value >> 16, Value & ((1 << 16) - 1));
  472. }
  473. }
  474. BOOL
  475. cuPrintRegFlags(
  476. IN BOOL fNewLine,
  477. IN DWORD Flags,
  478. IN WCHAR const *pwszRegName)
  479. {
  480. HRESULT hr;
  481. DUMPFLAGS const *pdf;
  482. pwszRegName = regTail(pwszRegName);
  483. if (0 == LSTRCMPIS(pwszRegName, wszHASHALGORITHM) ||
  484. 0 == LSTRCMPIS(pwszRegName, wszENCRYPTIONALGORITHM))
  485. {
  486. cuDumpAlgid(Flags);
  487. hr = S_OK;
  488. }
  489. else
  490. {
  491. hr = cuLookupRegFlags(pwszRegName, &pdf);
  492. _JumpIfError2(hr, error, "cuLookupRegFlags", hr);
  493. if (fNewLine)
  494. {
  495. wprintf(wszNewLine);
  496. }
  497. cuPrintFlags(Flags, pdf);
  498. }
  499. error:
  500. return(S_OK == hr);
  501. }
  502. HRESULT
  503. cuMapRegFlags(
  504. IN WCHAR const *pwszRegName,
  505. IN WCHAR const *pwszRegValue,
  506. IN BOOL fClearField,
  507. IN OUT DWORD *pFlags)
  508. {
  509. HRESULT hr;
  510. WCHAR const *pwsz;
  511. DUMPFLAGS const *pdf;
  512. hr = cuLookupRegFlags(pwszRegName, &pdf);
  513. _JumpIfErrorStr2(hr, error, "cuLookupRegFlags", pwszRegName, hr);
  514. for ( ; NULL != pdf->pwszDescription; pdf++)
  515. {
  516. if (0 == mylstrcmpiS(pwszRegValue, pdf->pwszDescription))
  517. {
  518. break;
  519. }
  520. pwsz = wcschr(pdf->pwszDescription, L'_');
  521. if (NULL == pwsz)
  522. {
  523. continue;
  524. }
  525. if (0 == mylstrcmpiS(pwszRegValue, &pwsz[1]))
  526. {
  527. break;
  528. }
  529. }
  530. if (NULL == pdf->pwszDescription)
  531. {
  532. hr = E_INVALIDARG;
  533. _JumpErrorStr2(hr, error, "no match", pwszRegValue, hr);
  534. }
  535. *pFlags &= ~pdf->Mask;
  536. if (!fClearField)
  537. {
  538. *pFlags |= pdf->Value;
  539. }
  540. hr = S_OK;
  541. error:
  542. return(hr);
  543. }
  544. HRESULT
  545. OpenSubKey(
  546. IN HKEY hkey,
  547. IN WCHAR const *pwszName,
  548. IN BOOL fCreateSubKey,
  549. OUT HKEY *phkeySub,
  550. OUT WCHAR **ppwszSubKeyName,
  551. OUT WCHAR **ppwszValueName)
  552. {
  553. HRESULT hr;
  554. HKEY hkeySub = NULL;
  555. WCHAR *pwszSubKeyName = NULL;
  556. WCHAR *pwszT;
  557. DWORD cwcSkip;
  558. DWORD i;
  559. WCHAR awc[MAX_PATH];
  560. *phkeySub = NULL;
  561. hr = myDupString(pwszName, &pwszSubKeyName);
  562. _JumpIfError(hr, error, "myDupString");
  563. cwcSkip = wcslen(pwszName);
  564. hr = RegOpenKeyEx(
  565. hkey,
  566. pwszSubKeyName,
  567. 0,
  568. KEY_ALL_ACCESS,
  569. &hkeySub);
  570. if (S_OK != hr)
  571. {
  572. //_PrintErrorStr(hr, "RegOpenKeyEx", pwszName);
  573. hkeySub = NULL;
  574. pwszT = wcsrchr(pwszSubKeyName, L'\\');
  575. if (NULL != pwszT)
  576. {
  577. *pwszT = L'\0';
  578. cwcSkip = SAFE_SUBTRACT_POINTERS(pwszT, pwszSubKeyName) + 1;
  579. hr = RegOpenKeyEx(
  580. hkey,
  581. pwszSubKeyName,
  582. 0,
  583. KEY_ALL_ACCESS,
  584. &hkeySub);
  585. if ((HRESULT) ERROR_FILE_NOT_FOUND == hr && fCreateSubKey)
  586. {
  587. hr = RegCreateKey(hkey, pwszSubKeyName, &hkeySub);
  588. _JumpIfErrorStr(hr, error, "RegCreateKey", pwszSubKeyName);
  589. }
  590. _JumpIfErrorStr(hr, error, "RegOpenKeyEx", pwszSubKeyName);
  591. }
  592. }
  593. if (NULL != hkeySub)
  594. {
  595. pwszName += cwcSkip;
  596. if (L'\0' != *pwszName)
  597. {
  598. // Look for case-ignore registry value name, & use the value's
  599. // correct upper/lower case spelling if an existing registry value:
  600. for (i = 0; ; i++)
  601. {
  602. DWORD cwc = ARRAYSIZE(awc);
  603. hr = RegEnumValue(hkeySub, i, awc, &cwc, NULL, NULL, NULL, NULL);
  604. if (S_OK != hr)
  605. {
  606. hr = S_OK;
  607. break;
  608. }
  609. if (0 == mylstrcmpiL(awc, pwszName))
  610. {
  611. pwszName = awc;
  612. break;
  613. }
  614. }
  615. }
  616. }
  617. hr = myDupString(pwszName, ppwszValueName);
  618. _JumpIfError(hr, error, "myDupString");
  619. if (NULL != hkeySub)
  620. {
  621. *phkeySub = hkeySub;
  622. hkeySub = NULL;
  623. }
  624. *ppwszSubKeyName = pwszSubKeyName;
  625. pwszSubKeyName = NULL;
  626. error:
  627. if (NULL != pwszSubKeyName)
  628. {
  629. LocalFree(pwszSubKeyName);
  630. }
  631. if (NULL != hkeySub)
  632. {
  633. RegCloseKey(hkeySub);
  634. }
  635. return(myHError(hr));
  636. }
  637. VOID
  638. PrintRegStringValue(
  639. IN WCHAR const *pwszLookupName,
  640. IN WCHAR const *pwszValue)
  641. {
  642. DWORD Flags;
  643. WCHAR *pwszDup = NULL;
  644. wprintf(L"%ws", pwszValue);
  645. if (iswdigit(*pwszValue))
  646. {
  647. BOOL fParmValid = FALSE;
  648. DWORD dwParm;
  649. WCHAR const *pwszObjId = pwszValue;
  650. WCHAR *pwszParm = wcschr(pwszValue, L',');
  651. if (NULL != pwszParm)
  652. {
  653. HRESULT hr;
  654. hr = myDupString(pwszValue, &pwszDup);
  655. _PrintIfError(hr, "myDupString");
  656. pwszParm = wcschr(pwszDup, L',');
  657. if (NULL != pwszParm)
  658. {
  659. *pwszParm++ = L'\0';
  660. dwParm = myWtoI(pwszParm, &fParmValid);
  661. pwszObjId = fParmValid? pwszDup : NULL;
  662. }
  663. }
  664. if (NULL != pwszObjId)
  665. {
  666. cuPrintPossibleObjectIdName(pwszObjId);
  667. if (fParmValid)
  668. {
  669. wprintf(L" %x", dwParm);
  670. if (9 < dwParm)
  671. {
  672. wprintf(L" (%d)", dwParm);
  673. }
  674. }
  675. }
  676. }
  677. cuPrintRegFlags(TRUE, _wtoi(pwszValue), pwszLookupName);
  678. if (NULL != pwszDup)
  679. {
  680. LocalFree(pwszDup);
  681. }
  682. }
  683. VOID
  684. PrintRegValue(
  685. IN WCHAR const *pwszLookupName,
  686. IN WCHAR const *pwszDisplayName,
  687. IN DWORD dwType,
  688. IN BOOL fPrintDwordNameAndValue,
  689. IN BOOL fPrintType,
  690. IN DWORD cwcSeparator,
  691. IN DWORD cbValue,
  692. OPTIONAL IN BYTE const *pbValue,
  693. OPTIONAL OUT BOOL *pfLongValue)
  694. {
  695. HRESULT hr;
  696. DWORD i;
  697. WCHAR const *pwsz;
  698. BOOL fLongValue = FALSE;
  699. char const *pszEqual = NULL != pbValue? " =" : "";
  700. if (0 == cwcSeparator && fPrintType)
  701. {
  702. cwcSeparator = 1;
  703. }
  704. if (fPrintDwordNameAndValue)
  705. {
  706. wprintf(L" %ws%*ws", pwszDisplayName, cwcSeparator, L"");
  707. }
  708. switch (dwType)
  709. {
  710. case REG_DWORD:
  711. if (fPrintDwordNameAndValue)
  712. {
  713. wprintf(
  714. L"%ws%hs",
  715. fPrintType? L"REG_DWORD" : L"",
  716. pszEqual);
  717. }
  718. if (NULL != pbValue)
  719. {
  720. CSASSERT(sizeof(DWORD) == cbValue);
  721. if (fPrintDwordNameAndValue)
  722. {
  723. wprintf(L" %x", *(DWORD *) pbValue);
  724. if (9 < *(DWORD *) pbValue)
  725. {
  726. wprintf(L" (%d)", *(DWORD *) pbValue);
  727. }
  728. cuPrintRegDWord(*(DWORD *) pbValue, pwszLookupName);
  729. wprintf(wszNewLine);
  730. }
  731. if (cuPrintRegFlags(FALSE, *(DWORD *) pbValue, pwszLookupName))
  732. {
  733. fLongValue = TRUE;
  734. }
  735. }
  736. else
  737. {
  738. if (fPrintDwordNameAndValue)
  739. {
  740. wprintf(wszNewLine);
  741. }
  742. }
  743. break;
  744. case REG_SZ:
  745. if (fPrintType)
  746. {
  747. wprintf(L"REG_SZ");
  748. }
  749. if (NULL != pbValue && 0 != cbValue)
  750. {
  751. CSASSERT((wcslen((WCHAR const *) pbValue) + 1) * sizeof(WCHAR) == cbValue);
  752. wprintf(L" = ");
  753. PrintRegStringValue(pwszLookupName, (WCHAR const *) pbValue);
  754. if (44 < wcslen((WCHAR const *) pbValue))
  755. {
  756. fLongValue = TRUE;
  757. }
  758. }
  759. wprintf(wszNewLine);
  760. break;
  761. case REG_MULTI_SZ:
  762. wprintf(
  763. L"%ws%hs",
  764. fPrintType? L"REG_MULTI_SZ" : L"",
  765. pszEqual);
  766. if (NULL != pbValue && 0 != cbValue)
  767. {
  768. pwsz = (WCHAR const *) pbValue;
  769. if (L'\0' == *pwsz)
  770. {
  771. // empty value
  772. }
  773. else if (!fPrintType && L'\0' == pwsz[wcslen(pwsz) + 1])
  774. {
  775. // single value
  776. wprintf(L" ");
  777. PrintRegStringValue(pwszLookupName, (WCHAR const *) pbValue);
  778. pwsz += wcslen(pwsz) + 1;
  779. }
  780. else
  781. {
  782. wprintf(wszNewLine);
  783. i = 0;
  784. for ( ; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  785. {
  786. wprintf(L" %u: ", i);
  787. PrintRegStringValue(pwszLookupName, pwsz);
  788. wprintf(wszNewLine);
  789. i++;
  790. }
  791. fLongValue = TRUE;
  792. }
  793. CSASSERT(
  794. (pwsz == (WCHAR *) pbValue && 2 * sizeof(WCHAR) == cbValue) ||
  795. (SAFE_SUBTRACT_POINTERS((BYTE *) pwsz, pbValue) +
  796. sizeof(WCHAR) ==
  797. cbValue));
  798. }
  799. if (!fLongValue)
  800. {
  801. wprintf(wszNewLine);
  802. }
  803. break;
  804. default:
  805. case REG_BINARY:
  806. if (fPrintType)
  807. {
  808. if (REG_BINARY == dwType)
  809. {
  810. wprintf(L"REG_BINARY");
  811. }
  812. else
  813. {
  814. wprintf(L"???=%x%", dwType);
  815. }
  816. }
  817. wprintf(L"%hs", pszEqual);
  818. if (NULL != pbValue && 0 != cbValue)
  819. {
  820. BOOL fDump = TRUE;
  821. WCHAR const *pwszNL = wszNewLine;
  822. if (REG_BINARY == dwType && sizeof(FILETIME) == cbValue)
  823. {
  824. hr = cuDumpFileTimeOrPeriod(
  825. 0,
  826. NULL,
  827. (FILETIME const *) pbValue);
  828. if (S_OK == hr)
  829. {
  830. if (g_fVerbose)
  831. {
  832. pwszNL = NULL;
  833. }
  834. else
  835. {
  836. fDump = FALSE;
  837. }
  838. }
  839. }
  840. if (fDump)
  841. {
  842. if (NULL != pwszNL)
  843. {
  844. wprintf(pwszNL);
  845. }
  846. DumpHex(0, pbValue, cbValue);
  847. fLongValue = TRUE;
  848. }
  849. }
  850. break;
  851. }
  852. if (NULL != pfLongValue)
  853. {
  854. *pfLongValue = fLongValue;
  855. }
  856. }
  857. BOOL
  858. cuRegPrintDwordValue(
  859. IN BOOL fPrintNameAndValue,
  860. IN WCHAR const *pwszLookupName,
  861. IN WCHAR const *pwszDisplayName,
  862. IN DWORD dwValue)
  863. {
  864. BOOL fDisplayed = FALSE;
  865. PrintRegValue(
  866. pwszLookupName,
  867. pwszDisplayName,
  868. REG_DWORD,
  869. fPrintNameAndValue,
  870. FALSE,
  871. 0, // cwcSeparator
  872. sizeof(dwValue),
  873. (BYTE const *) &dwValue,
  874. &fDisplayed);
  875. return(fDisplayed);
  876. }
  877. VOID
  878. cuRegPrintAwszValue(
  879. IN WCHAR const *pwszName,
  880. OPTIONAL IN WCHAR const * const *prgpwszValues)
  881. {
  882. WCHAR *pwszzValues = NULL;
  883. WCHAR *pwsz;
  884. DWORD cwcAlloc;
  885. DWORD i;
  886. cwcAlloc = 1;
  887. if (NULL == prgpwszValues || NULL == prgpwszValues[0])
  888. {
  889. cwcAlloc++;
  890. }
  891. else
  892. {
  893. for (i = 0; NULL != prgpwszValues[i]; i++)
  894. {
  895. cwcAlloc += wcslen(prgpwszValues[i]) + 1;
  896. }
  897. }
  898. pwszzValues = (WCHAR *) LocalAlloc(LMEM_FIXED, cwcAlloc * sizeof(WCHAR));
  899. if (NULL == pwszzValues)
  900. {
  901. _JumpError(E_OUTOFMEMORY, error, "LocalAlloc");
  902. }
  903. pwsz = pwszzValues;
  904. if (NULL == prgpwszValues || NULL == prgpwszValues[0])
  905. {
  906. *pwsz++ = L'\0';
  907. }
  908. else
  909. {
  910. for (i = 0; NULL != prgpwszValues[i]; i++)
  911. {
  912. wcscpy(pwsz, prgpwszValues[i]);
  913. pwsz += wcslen(pwsz) + 1;
  914. }
  915. }
  916. *pwsz = L'\0';
  917. CSASSERT(SAFE_SUBTRACT_POINTERS(pwsz, pwszzValues) + 1 == cwcAlloc);
  918. PrintRegValue(
  919. pwszName,
  920. pwszName,
  921. REG_MULTI_SZ,
  922. TRUE,
  923. FALSE,
  924. 0, // cwcSeparator
  925. cwcAlloc * sizeof(WCHAR),
  926. (BYTE const *) pwszzValues,
  927. NULL); // pfLongValue
  928. error:
  929. if (NULL != pwszzValues)
  930. {
  931. LocalFree(pwszzValues);
  932. }
  933. }
  934. #define REGOP_NONE 0
  935. #define REGOP_SET 1
  936. #define REGOP_CLEAR 2
  937. BOOL
  938. IsInList(
  939. IN WCHAR const *pwsz,
  940. OPTIONAL IN WCHAR const *pwszzList)
  941. {
  942. BOOL fFound = FALSE;
  943. WCHAR *pwszT;
  944. if (NULL != pwszzList)
  945. {
  946. for ( ; L'\0' != *pwszzList; pwszzList += wcslen(pwszzList) + 1)
  947. {
  948. if (0 == mylstrcmpiL(pwszzList, pwsz))
  949. {
  950. fFound = TRUE;
  951. break;
  952. }
  953. }
  954. }
  955. return(fFound);
  956. }
  957. HRESULT
  958. CombineMultiSzRegValues(
  959. IN DWORD RegOp,
  960. IN WCHAR const *pwszRegValue,
  961. IN DWORD dwTypeOld,
  962. IN DWORD cbValueOld,
  963. OPTIONAL IN BYTE const *pbValueOld,
  964. OUT BYTE **ppbValue,
  965. OUT DWORD *pcbValue)
  966. {
  967. HRESULT hr;
  968. WCHAR *pwszDst;
  969. WCHAR const *pwsz;
  970. DWORD cpwsz;
  971. WCHAR const **apwsz = NULL;
  972. DWORD cOld = 0;
  973. DWORD cNew = 0;
  974. DWORD cCombined;
  975. WCHAR *pwszzNew = NULL;
  976. DWORD cwc;
  977. DWORD i;
  978. if (REGOP_NONE != RegOp)
  979. {
  980. pwsz = (WCHAR *) pbValueOld;
  981. if (NULL != pwsz && 0 != cbValueOld)
  982. {
  983. for ( ; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  984. {
  985. cOld++;
  986. }
  987. }
  988. }
  989. // Convert backslash-n sequences to L'\0' and move data up.
  990. cwc = wcslen(pwszRegValue) + 1 + 1;
  991. pwszzNew = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  992. if (NULL == pwszzNew)
  993. {
  994. hr = E_OUTOFMEMORY;
  995. _JumpError(hr, error, "LocalAlloc");
  996. }
  997. pwszDst = pwszzNew;
  998. pwsz = pwszRegValue;
  999. if (L'\0' != *pwsz && REGOP_CLEAR != RegOp)
  1000. {
  1001. cNew++;
  1002. }
  1003. while (L'\0' != *pwsz)
  1004. {
  1005. WCHAR wc;
  1006. wc = *pwsz++;
  1007. if (L'\\' == wc && L'n' == *pwsz)
  1008. {
  1009. if (0 != cNew)
  1010. {
  1011. cNew++;
  1012. }
  1013. wc = L'\0';
  1014. pwsz++;
  1015. while (L'\\' == pwsz[0] && L'n' == pwsz[1])
  1016. {
  1017. pwsz += 2;
  1018. }
  1019. }
  1020. *pwszDst++ = wc;
  1021. }
  1022. *pwszDst++ = L'\0';
  1023. *pwszDst = L'\0';
  1024. apwsz = (WCHAR const **) LocalAlloc(LMEM_FIXED, (cOld + cNew) * sizeof(apwsz[0]));
  1025. if (NULL == apwsz)
  1026. {
  1027. hr = E_OUTOFMEMORY;
  1028. _JumpError(hr, error, "LocalAlloc");
  1029. }
  1030. cCombined = 0;
  1031. if (cOld)
  1032. {
  1033. for (pwsz = (WCHAR *) pbValueOld; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  1034. {
  1035. if (REGOP_SET == RegOp || !IsInList(pwsz, pwszzNew))
  1036. {
  1037. apwsz[cCombined++] = pwsz;
  1038. }
  1039. }
  1040. }
  1041. if (cNew)
  1042. {
  1043. for (pwsz = pwszzNew; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  1044. {
  1045. if (REGOP_NONE == RegOp || !IsInList(pwsz, (WCHAR *) pbValueOld))
  1046. {
  1047. apwsz[cCombined++] = pwsz;
  1048. }
  1049. }
  1050. }
  1051. CSASSERT(cOld + cNew >= cCombined);
  1052. cwc = 1;
  1053. for (i = 0; i < cCombined; i++)
  1054. {
  1055. cwc += wcslen(apwsz[i]) + 1;
  1056. }
  1057. if (0 == cCombined)
  1058. {
  1059. cwc++;
  1060. }
  1061. *pcbValue = cwc * sizeof(WCHAR);
  1062. *ppbValue = (BYTE *) LocalAlloc(LMEM_FIXED, *pcbValue);
  1063. if (NULL == *ppbValue)
  1064. {
  1065. hr = E_OUTOFMEMORY;
  1066. _JumpError(hr, error, "LocalAlloc");
  1067. }
  1068. pwszDst = (WCHAR *) *ppbValue;
  1069. for (i = 0; i < cCombined; i++)
  1070. {
  1071. wcscpy(pwszDst, apwsz[i]);
  1072. pwszDst += wcslen(pwszDst) + 1;
  1073. }
  1074. if (0 == cCombined)
  1075. {
  1076. *pwszDst++ = L'\0';
  1077. }
  1078. *pwszDst = L'\0';
  1079. CSASSERT(SAFE_SUBTRACT_POINTERS(pwszDst, (WCHAR *) *ppbValue) + 1 == cwc);
  1080. hr = S_OK;
  1081. error:
  1082. if (NULL != apwsz)
  1083. {
  1084. LocalFree(apwsz);
  1085. }
  1086. if (NULL != pwszzNew)
  1087. {
  1088. LocalFree(pwszzNew);
  1089. }
  1090. return(hr);
  1091. }
  1092. HRESULT
  1093. ParseRegValue(
  1094. IN WCHAR const *pwszRegName,
  1095. IN DWORD cbValueOld,
  1096. IN BYTE const *pbValueOld,
  1097. IN OUT DWORD *pdwType,
  1098. IN WCHAR const *pwszRegValue,
  1099. OUT DWORD *pcbValue,
  1100. OUT BYTE **ppbValue)
  1101. {
  1102. HRESULT hr;
  1103. WCHAR const *pwsz;
  1104. DWORD cb;
  1105. DWORD dw;
  1106. DWORD dwValue;
  1107. DWORD dwType;
  1108. DWORD cNewLine;
  1109. DWORD RegOp;
  1110. BOOL fNumber;
  1111. // A leading '-' or '+' character is used as a REGOP_* operator.
  1112. // To include it as part of the string, add leading whitespace,
  1113. // or separate the operator from the string by one or more spaces.
  1114. //
  1115. // "-foo" -- remove "foo" from registry value
  1116. // "- foo" -- remove "foo" from registry value
  1117. // " -foo" -- overwrite registry value with "-foo"
  1118. // "--foo" -- remove "-foo" from registry value
  1119. // "- -foo" -- remove "-foo" from registry value
  1120. dwValue = 0;
  1121. cNewLine = 0;
  1122. if (REG_DWORD == *pdwType)
  1123. {
  1124. CSASSERT(sizeof(dw) == cbValueOld);
  1125. dwValue = *(DWORD *) pbValueOld;
  1126. }
  1127. if (L'+' == *pwszRegValue)
  1128. {
  1129. RegOp = REGOP_SET; // set bits in existing value
  1130. pwszRegValue++;
  1131. }
  1132. else if (myIsMinusSign(*pwszRegValue))
  1133. {
  1134. RegOp = REGOP_CLEAR; // clear bits in existing value
  1135. pwszRegValue++;
  1136. }
  1137. else
  1138. {
  1139. RegOp = REGOP_NONE; // overwrite value
  1140. dwValue = 0;
  1141. }
  1142. while (L' ' == *pwszRegValue || L'\t' == *pwszRegValue)
  1143. {
  1144. pwszRegValue++;
  1145. }
  1146. cb = sizeof(dwValue); // assume REG_DWORD
  1147. dwType = REG_DWORD;
  1148. fNumber = FALSE;
  1149. if (L'+' == *pwszRegValue ||
  1150. myIsMinusSign(*pwszRegValue) ||
  1151. iswdigit(*pwszRegValue))
  1152. {
  1153. hr = myGetSignedLong(pwszRegValue, (LONG *) &dw);
  1154. if (S_OK == hr)
  1155. {
  1156. fNumber = TRUE;
  1157. switch (RegOp)
  1158. {
  1159. default:
  1160. case REGOP_NONE:
  1161. dwValue = dw;
  1162. break;
  1163. case REGOP_SET:
  1164. dwValue |= dw;
  1165. break;
  1166. case REGOP_CLEAR:
  1167. dwValue &= ~dw;
  1168. break;
  1169. }
  1170. }
  1171. }
  1172. if (!fNumber)
  1173. {
  1174. hr = cuMapRegFlags(
  1175. pwszRegName,
  1176. pwszRegValue,
  1177. REGOP_CLEAR == RegOp,
  1178. &dwValue);
  1179. if (S_OK != hr)
  1180. {
  1181. pwsz = pwszRegValue;
  1182. while (TRUE)
  1183. {
  1184. pwsz = wcschr(pwsz, L'\\');
  1185. if (NULL == pwsz)
  1186. {
  1187. break;
  1188. }
  1189. if (L'n' == *++pwsz)
  1190. {
  1191. cNewLine++;
  1192. }
  1193. }
  1194. if (REGOP_SET == RegOp || 0 != cNewLine)
  1195. {
  1196. dwType = REG_MULTI_SZ;
  1197. }
  1198. else
  1199. {
  1200. dwType = REG_SZ;
  1201. }
  1202. cb = (wcslen(pwszRegValue) + 1) * sizeof(WCHAR);
  1203. }
  1204. }
  1205. if (REG_NONE != *pdwType && dwType != *pdwType)
  1206. {
  1207. if (REG_SZ == dwType && REG_MULTI_SZ == *pdwType)
  1208. {
  1209. dwType = REG_MULTI_SZ;
  1210. if (0 == cNewLine)
  1211. {
  1212. cb += sizeof(WCHAR);
  1213. }
  1214. }
  1215. else if (REG_MULTI_SZ != dwType || REG_SZ != *pdwType)
  1216. {
  1217. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1218. _JumpError(hr, error, "bad registry value type");
  1219. }
  1220. }
  1221. if (REG_MULTI_SZ == dwType)
  1222. {
  1223. hr = CombineMultiSzRegValues(
  1224. RegOp,
  1225. pwszRegValue,
  1226. *pdwType,
  1227. cbValueOld,
  1228. pbValueOld,
  1229. ppbValue,
  1230. pcbValue);
  1231. _JumpIfError(hr, error, "CombineMultiSzRegValues");
  1232. }
  1233. else
  1234. {
  1235. *ppbValue = (BYTE *) LocalAlloc(LMEM_FIXED, cb);
  1236. if (NULL == *ppbValue)
  1237. {
  1238. hr = E_OUTOFMEMORY;
  1239. _JumpError(hr, error, "LocalAlloc");
  1240. }
  1241. *pcbValue = cb;
  1242. if (REG_DWORD == dwType)
  1243. {
  1244. CSASSERT(sizeof(dwValue) == cb);
  1245. CopyMemory(*ppbValue, &dwValue, sizeof(dwValue));
  1246. }
  1247. else
  1248. {
  1249. if (REGOP_NONE != RegOp)
  1250. {
  1251. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1252. _JumpErrorStr(hr, error, "bad registry value string", pwszRegValue);
  1253. }
  1254. CSASSERT((wcslen(pwszRegValue) + 1) * sizeof(WCHAR) <= cb);
  1255. wcscpy((WCHAR *) *ppbValue, pwszRegValue);
  1256. }
  1257. }
  1258. *pdwType = dwType;
  1259. if (g_fVerbose)
  1260. {
  1261. DumpHex(0, *ppbValue, *pcbValue);
  1262. }
  1263. hr = S_OK;
  1264. error:
  1265. return(hr);
  1266. }
  1267. HRESULT
  1268. WriteRegValue(
  1269. IN HKEY hkey,
  1270. IN WCHAR const *pwszName,
  1271. IN DWORD dwType,
  1272. IN DWORD cbValue,
  1273. IN BYTE const *pbValue)
  1274. {
  1275. HRESULT hr;
  1276. hr = RegSetValueEx(hkey, pwszName, 0, dwType, pbValue, cbValue);
  1277. _JumpIfErrorStr(hr, error, "RegSetValueEx", pwszName);
  1278. error:
  1279. return(myHError(hr));
  1280. }
  1281. HRESULT
  1282. ReadRegValue(
  1283. IN HKEY hkey,
  1284. IN WCHAR const *pwszName,
  1285. OUT DWORD *pdwType,
  1286. OUT DWORD *pcbValue,
  1287. OUT BYTE **ppbValue)
  1288. {
  1289. HRESULT hr;
  1290. DWORD cb;
  1291. *ppbValue = NULL;
  1292. cb = 0;
  1293. hr = RegQueryValueEx(
  1294. hkey,
  1295. pwszName,
  1296. NULL,
  1297. pdwType,
  1298. NULL,
  1299. &cb);
  1300. _JumpIfErrorStr2(hr, error, "RegQueryValueEx", pwszName, ERROR_FILE_NOT_FOUND);
  1301. // add two WCHAR L'\0's after the registry value, in case of a poorly
  1302. // formed REG_MULTI_SZ. Add another to handle possible odd sizes.
  1303. *ppbValue = (BYTE *) LocalAlloc(LMEM_FIXED, cb + cbVALUEZEROPAD);
  1304. if (NULL == *ppbValue)
  1305. {
  1306. hr = E_OUTOFMEMORY;
  1307. _JumpError(hr, error, "LocalAlloc");
  1308. }
  1309. hr = RegQueryValueEx(
  1310. hkey,
  1311. pwszName,
  1312. NULL,
  1313. pdwType,
  1314. *ppbValue,
  1315. &cb);
  1316. _JumpIfErrorStr(hr, error, "RegQueryValueEx", pwszName);
  1317. if (REG_SZ == *pdwType || REG_MULTI_SZ == *pdwType)
  1318. {
  1319. WCHAR *pwszStart;
  1320. WCHAR *pwsz;
  1321. DWORD cbT;
  1322. CSASSERT(0 == ((sizeof(WCHAR) - 1) & cb));
  1323. pwszStart = (WCHAR *) *ppbValue;
  1324. cbT = ~(sizeof(WCHAR) - 1) & cb;
  1325. pwsz = &pwszStart[cbT / sizeof(WCHAR)];
  1326. ZeroMemory(pwsz, cbVALUEZEROPAD);
  1327. pwsz = pwszStart;
  1328. while (L'\0' != pwsz[0] || L'\0' != pwsz[1])
  1329. {
  1330. pwsz++;
  1331. }
  1332. cbT = (SAFE_SUBTRACT_POINTERS(pwsz, pwszStart) +
  1333. (REG_SZ == *pdwType? 1 : 2)) * sizeof(WCHAR);
  1334. CSASSERT(cb == cbT);
  1335. cb = cbT;
  1336. }
  1337. *pcbValue = cb;
  1338. error:
  1339. if (S_OK != hr)
  1340. {
  1341. if (NULL != *ppbValue)
  1342. {
  1343. LocalFree(*ppbValue);
  1344. *ppbValue = NULL;
  1345. }
  1346. }
  1347. return(myHError(hr));
  1348. }
  1349. #define cwcVALUENAME 25 // Nominal registry value name length
  1350. HRESULT
  1351. DumpRegKeysAndValues(
  1352. IN HKEY hkey,
  1353. OPTIONAL WCHAR *pwszValueNamePrefix)
  1354. {
  1355. HRESULT hr;
  1356. DWORD i;
  1357. DWORD j;
  1358. DWORD cwc;
  1359. DWORD dwType;
  1360. WCHAR awc[MAX_PATH + 1];
  1361. DWORD cb;
  1362. BYTE *pb;
  1363. BYTE ab[8 + cbVALUEZEROPAD]; // enough for small registry values
  1364. DWORD cbAlloc;
  1365. BYTE *pbAlloc = ab;
  1366. BOOL fLongValue;
  1367. WCHAR *pwszPrefix = NULL;
  1368. DWORD cwcPrefix;
  1369. if (NULL != pwszValueNamePrefix)
  1370. {
  1371. cwcPrefix = wcslen(pwszValueNamePrefix);
  1372. pwszPrefix = (WCHAR *) LocalAlloc(
  1373. LMEM_FIXED,
  1374. (cwcPrefix + 1) * sizeof(WCHAR));
  1375. if (NULL == pwszPrefix)
  1376. {
  1377. hr = E_OUTOFMEMORY;
  1378. _JumpError(hr, error, "LocalAlloc");
  1379. }
  1380. }
  1381. for (i = j = 0; ; i++)
  1382. {
  1383. cwc = ARRAYSIZE(awc);
  1384. hr = RegEnumKey(hkey, i, awc, cwc);
  1385. if (S_OK != hr)
  1386. {
  1387. if ((HRESULT) ERROR_NO_MORE_ITEMS != hr)
  1388. {
  1389. _PrintError(hr, "RegEnumKey");
  1390. }
  1391. break;
  1392. }
  1393. if (NULL != pwszPrefix)
  1394. {
  1395. wcsncpy(pwszPrefix, awc, cwcPrefix);
  1396. pwszPrefix[cwcPrefix] = L'\0';
  1397. if (0 != mylstrcmpiL(pwszValueNamePrefix, pwszPrefix))
  1398. {
  1399. continue;
  1400. }
  1401. }
  1402. if (0 == j)
  1403. {
  1404. wprintf(wszNewLine);
  1405. wprintf(myLoadResourceString(IDS_KEYS)); // "Keys:"
  1406. wprintf(wszNewLine);
  1407. }
  1408. else if (0 == (j % 5))
  1409. {
  1410. wprintf(wszNewLine);
  1411. }
  1412. wprintf(L" %ws\n", awc);
  1413. j++;
  1414. }
  1415. cbAlloc = sizeof(ab) - cbVALUEZEROPAD;
  1416. fLongValue = FALSE;
  1417. for (i = j = 0; ; i++)
  1418. {
  1419. DWORD cwcSep;
  1420. cwc = ARRAYSIZE(awc);
  1421. cb = cbAlloc;
  1422. pb = pbAlloc;
  1423. hr = RegEnumValue(hkey, i, awc, &cwc, NULL, &dwType, pb, &cb);
  1424. if (S_OK != hr)
  1425. {
  1426. if ((HRESULT) ERROR_MORE_DATA != hr)
  1427. {
  1428. if ((HRESULT) ERROR_NO_MORE_ITEMS != hr)
  1429. {
  1430. _PrintError(hr, "RegEnumValue");
  1431. }
  1432. break;
  1433. }
  1434. CSASSERT(NULL != pb);
  1435. pb = (BYTE *) LocalAlloc(LMEM_FIXED, cb + cbVALUEZEROPAD);
  1436. if (NULL == pb)
  1437. {
  1438. hr = E_OUTOFMEMORY;
  1439. _JumpError(hr, error, "LocalAlloc");
  1440. }
  1441. if (ab != pbAlloc)
  1442. {
  1443. LocalFree(pbAlloc);
  1444. }
  1445. pbAlloc = pb;
  1446. cbAlloc = cb;
  1447. cwc = ARRAYSIZE(awc);
  1448. hr = RegEnumValue(hkey, i, awc, &cwc, NULL, &dwType, pb, &cb);
  1449. _JumpIfError(hr, error, "RegEnumValue");
  1450. }
  1451. if (NULL != pb)
  1452. {
  1453. ZeroMemory(&pb[cb], cbVALUEZEROPAD);
  1454. }
  1455. if (NULL != pwszPrefix)
  1456. {
  1457. wcsncpy(pwszPrefix, awc, cwcPrefix);
  1458. pwszPrefix[cwcPrefix] = L'\0';
  1459. if (0 != mylstrcmpiL(pwszValueNamePrefix, pwszPrefix))
  1460. {
  1461. continue;
  1462. }
  1463. }
  1464. if (0 == j)
  1465. {
  1466. wprintf(wszNewLine);
  1467. wprintf(myLoadResourceString(IDS_VALUES)); // "Values:"
  1468. wprintf(wszNewLine);
  1469. }
  1470. else if (fLongValue || 0 == (j % 5))
  1471. {
  1472. wprintf(wszNewLine);
  1473. }
  1474. cwcSep = wcslen(awc);
  1475. cwcSep = cwcVALUENAME < cwcSep? 0 : cwcVALUENAME - cwcSep;
  1476. PrintRegValue(awc, awc, dwType, TRUE, TRUE, cwcSep, cb, pb, &fLongValue);
  1477. j++;
  1478. }
  1479. hr = S_OK;
  1480. error:
  1481. if (NULL != pbAlloc && ab != pbAlloc)
  1482. {
  1483. LocalFree(pbAlloc);
  1484. }
  1485. if (NULL != pwszPrefix)
  1486. {
  1487. LocalFree(pwszPrefix);
  1488. }
  1489. return(myHError(hr));
  1490. }
  1491. WCHAR const *
  1492. wszHKEY(
  1493. IN WCHAR const *pwszPath)
  1494. {
  1495. WCHAR const *pwszKey = L"HKEY_LOCAL_MACHINE\\";
  1496. if (g_fUserRegistry && 0 == _wcsnicmp(
  1497. pwszPath,
  1498. wszCERTTYPECACHE,
  1499. WSZARRAYSIZE(wszCERTTYPECACHE)))
  1500. {
  1501. pwszKey = L"HKEY_CURRENT_USER\\";
  1502. }
  1503. return(pwszKey);
  1504. }
  1505. HRESULT
  1506. verbGetReg(
  1507. IN WCHAR const *pwszOption,
  1508. OPTIONAL IN WCHAR const *pwszRegName,
  1509. IN WCHAR const *pwszArg2,
  1510. IN WCHAR const *pwszArg3,
  1511. IN WCHAR const *pwszArg4)
  1512. {
  1513. HRESULT hr;
  1514. WCHAR *pwszPath = NULL;
  1515. WCHAR *pwszName = NULL;
  1516. WCHAR *pwszValueName = NULL;
  1517. WCHAR *pwszSubKeyName = NULL;
  1518. DWORD dwType;
  1519. DWORD cbValue;
  1520. BYTE *pbValue = NULL;
  1521. HKEY hkey = NULL;
  1522. HKEY hkeySub = NULL;
  1523. HKEY hkeyT;
  1524. if (NULL == pwszRegName)
  1525. {
  1526. pwszRegName = L"";
  1527. }
  1528. hr = myRegOpenRelativeKey(
  1529. g_pwszConfig,
  1530. pwszRegName,
  1531. RORKF_FULLPATH | (g_fUserRegistry? RORKF_USERKEY : 0),
  1532. &pwszPath,
  1533. &pwszName,
  1534. &hkey);
  1535. _JumpIfErrorStr(hr, error, "myRegOpenRelativeKey", pwszRegName);
  1536. hr = OpenSubKey(
  1537. hkey,
  1538. pwszName,
  1539. FALSE,
  1540. &hkeySub,
  1541. &pwszSubKeyName,
  1542. &pwszValueName);
  1543. _JumpIfError(hr, error, "OpenSubKey");
  1544. hkeyT = NULL != hkeySub? hkeySub : hkey;
  1545. wprintf(
  1546. L"%ws%ws%ws%ws:\n",
  1547. wszHKEY(pwszPath),
  1548. L'\0' != *pwszPath? pwszPath : wszREGKEYCONFIG,
  1549. L'\0' != *pwszSubKeyName? L"\\" : L"",
  1550. pwszSubKeyName);
  1551. if (NULL == pwszValueName ||
  1552. L'\0' == *pwszValueName ||
  1553. NULL != wcschr(pwszValueName, L'*'))
  1554. {
  1555. if (NULL != pwszValueName)
  1556. {
  1557. WCHAR *pwsz = wcschr(pwszValueName, L'*');
  1558. if (NULL != pwsz)
  1559. {
  1560. *pwsz = L'\0';
  1561. }
  1562. }
  1563. hr = DumpRegKeysAndValues(hkeyT, pwszValueName);
  1564. _JumpIfError(hr, error, "DumpRegKeysAndValues");
  1565. }
  1566. else
  1567. {
  1568. hr = ReadRegValue(hkeyT, pwszValueName, &dwType, &cbValue, &pbValue);
  1569. _JumpIfErrorStr(hr, error, "ReadRegValue", pwszValueName);
  1570. wprintf(wszNewLine);
  1571. PrintRegValue(
  1572. pwszValueName,
  1573. pwszValueName,
  1574. dwType,
  1575. TRUE,
  1576. TRUE,
  1577. 0,
  1578. cbValue,
  1579. pbValue,
  1580. NULL);
  1581. }
  1582. error:
  1583. if (NULL != hkey)
  1584. {
  1585. RegCloseKey(hkey);
  1586. }
  1587. if (NULL != hkeySub)
  1588. {
  1589. RegCloseKey(hkeySub);
  1590. }
  1591. if (NULL != pwszPath)
  1592. {
  1593. LocalFree(pwszPath);
  1594. }
  1595. if (NULL != pwszName)
  1596. {
  1597. LocalFree(pwszName);
  1598. }
  1599. if (NULL != pwszSubKeyName)
  1600. {
  1601. LocalFree(pwszSubKeyName);
  1602. }
  1603. if (NULL != pwszValueName)
  1604. {
  1605. LocalFree(pwszValueName);
  1606. }
  1607. if (NULL != pbValue)
  1608. {
  1609. LocalFree(pbValue);
  1610. }
  1611. return(hr);
  1612. }
  1613. HRESULT
  1614. verbSetReg(
  1615. IN WCHAR const *pwszOption,
  1616. IN WCHAR const *pwszRegName,
  1617. IN WCHAR const *pwszRegValue,
  1618. IN WCHAR const *pwszArg3,
  1619. IN WCHAR const *pwszArg4)
  1620. {
  1621. HRESULT hr;
  1622. WCHAR *pwszPath = NULL;
  1623. WCHAR *pwszName = NULL;
  1624. WCHAR *pwszValueName = NULL;
  1625. WCHAR *pwszSubKeyName = NULL;
  1626. DWORD dwType;
  1627. DWORD cbValue;
  1628. DWORD cbValueArg;
  1629. BYTE *pbValueOld = NULL;
  1630. BYTE *pbValueNew = NULL;
  1631. BYTE *pbValueArg = NULL;
  1632. HKEY hkey = NULL;
  1633. HKEY hkeySub = NULL;
  1634. HKEY hkeyT;
  1635. DWORD dw;
  1636. hr = myRegOpenRelativeKey(
  1637. g_pwszConfig,
  1638. pwszRegName,
  1639. RORKF_FULLPATH |
  1640. RORKF_CREATESUBKEYS |
  1641. (g_fUserRegistry? RORKF_USERKEY : 0) |
  1642. (g_fForce? RORKF_CREATEKEY : 0),
  1643. &pwszPath,
  1644. &pwszName,
  1645. &hkey);
  1646. _JumpIfErrorStr(hr, error, "myRegOpenRelativeKey", pwszRegName);
  1647. hr = OpenSubKey(
  1648. hkey,
  1649. pwszName,
  1650. g_fForce,
  1651. &hkeySub,
  1652. &pwszSubKeyName,
  1653. &pwszValueName);
  1654. _JumpIfError(hr, error, "OpenSubKey");
  1655. hkeyT = NULL != hkeySub? hkeySub : hkey;
  1656. wprintf(
  1657. L"%ws%ws%ws%ws:\n",
  1658. g_fVerbose? wszHKEY(pwszPath) : L"",
  1659. L'\0' != *pwszPath? pwszPath : wszREGKEYCONFIG,
  1660. L'\0' != *pwszSubKeyName? L"\\" : L"",
  1661. pwszSubKeyName);
  1662. hr = ReadRegValue(hkeyT, pwszValueName, &dwType, &cbValue, &pbValueOld);
  1663. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  1664. {
  1665. _JumpIfErrorStr(hr, error, "ReadRegValue", pwszValueName);
  1666. }
  1667. if (NULL != pbValueOld)
  1668. {
  1669. wprintf(wszNewLine);
  1670. wprintf(myLoadResourceString(IDS_OLD_REG_VALUE)); // "Old Value:"
  1671. wprintf(wszNewLine);
  1672. PrintRegValue(
  1673. pwszValueName,
  1674. pwszValueName,
  1675. dwType,
  1676. TRUE,
  1677. TRUE,
  1678. 0,
  1679. cbValue,
  1680. pbValueOld,
  1681. NULL);
  1682. }
  1683. else
  1684. {
  1685. dwType = REG_NONE;
  1686. }
  1687. hr = ParseRegValue(
  1688. pwszRegName,
  1689. cbValue,
  1690. pbValueOld,
  1691. &dwType,
  1692. pwszRegValue,
  1693. &cbValueArg,
  1694. &pbValueArg);
  1695. _JumpIfErrorStr(hr, error, "ParseRegValue", pwszRegValue);
  1696. hr = WriteRegValue(hkeyT, pwszValueName, dwType, cbValueArg, pbValueArg);
  1697. _JumpIfErrorStr(hr, error, "WriteRegValue", pwszValueName);
  1698. hr = ReadRegValue(hkeyT, pwszValueName, &dwType, &cbValue, &pbValueNew);
  1699. _JumpIfErrorStr(hr, error, "ReadRegValue", pwszValueName);
  1700. wprintf(wszNewLine);
  1701. wprintf(myLoadResourceString(IDS_NEW_REG_VALUE)); // "New Value:"
  1702. wprintf(wszNewLine);
  1703. PrintRegValue(
  1704. pwszValueName,
  1705. pwszValueName,
  1706. dwType,
  1707. TRUE,
  1708. TRUE,
  1709. 0,
  1710. cbValue,
  1711. pbValueNew,
  1712. NULL);
  1713. error:
  1714. if (NULL != hkey)
  1715. {
  1716. RegCloseKey(hkey);
  1717. }
  1718. if (NULL != hkeySub)
  1719. {
  1720. RegCloseKey(hkeySub);
  1721. }
  1722. if (NULL != pwszPath)
  1723. {
  1724. LocalFree(pwszPath);
  1725. }
  1726. if (NULL != pwszName)
  1727. {
  1728. LocalFree(pwszName);
  1729. }
  1730. if (NULL != pwszSubKeyName)
  1731. {
  1732. LocalFree(pwszSubKeyName);
  1733. }
  1734. if (NULL != pwszValueName)
  1735. {
  1736. LocalFree(pwszValueName);
  1737. }
  1738. if (NULL != pbValueOld)
  1739. {
  1740. LocalFree(pbValueOld);
  1741. }
  1742. if (NULL != pbValueArg)
  1743. {
  1744. LocalFree(pbValueArg);
  1745. }
  1746. if (NULL != pbValueNew)
  1747. {
  1748. LocalFree(pbValueNew);
  1749. }
  1750. return(hr);
  1751. }
  1752. HRESULT
  1753. verbDelReg(
  1754. IN WCHAR const *pwszOption,
  1755. IN WCHAR const *pwszRegName,
  1756. IN WCHAR const *pwszArg2,
  1757. IN WCHAR const *pwszArg3,
  1758. IN WCHAR const *pwszArg4)
  1759. {
  1760. HRESULT hr;
  1761. WCHAR *pwszPath = NULL;
  1762. WCHAR *pwszName = NULL;
  1763. WCHAR *pwszValueName = NULL;
  1764. WCHAR *pwszSubKeyName = NULL;
  1765. DWORD dwType;
  1766. DWORD cbValue;
  1767. BYTE *pbValueOld = NULL;
  1768. HKEY hkey = NULL;
  1769. HKEY hkeySub = NULL;
  1770. HKEY hkeyT;
  1771. DWORD dw;
  1772. hr = myRegOpenRelativeKey(
  1773. g_pwszConfig,
  1774. pwszRegName,
  1775. RORKF_FULLPATH |
  1776. RORKF_CREATESUBKEYS |
  1777. (g_fUserRegistry? RORKF_USERKEY : 0),
  1778. &pwszPath,
  1779. &pwszName,
  1780. &hkey);
  1781. _JumpIfErrorStr(hr, error, "myRegOpenRelativeKey", pwszRegName);
  1782. hr = OpenSubKey(
  1783. hkey,
  1784. pwszName,
  1785. FALSE,
  1786. &hkeySub,
  1787. &pwszSubKeyName,
  1788. &pwszValueName);
  1789. _JumpIfError(hr, error, "OpenSubKey");
  1790. hkeyT = NULL != hkeySub? hkeySub : hkey;
  1791. wprintf(
  1792. L"%ws%ws%ws%ws:\n",
  1793. wszHKEY(pwszPath),
  1794. L'\0' != *pwszPath? pwszPath : wszREGKEYCONFIG,
  1795. L'\0' != *pwszSubKeyName? L"\\" : L"",
  1796. pwszSubKeyName);
  1797. hr = ReadRegValue(hkeyT, pwszValueName, &dwType, &cbValue, &pbValueOld);
  1798. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  1799. {
  1800. _JumpIfErrorStr(hr, error, "ReadRegValue", pwszValueName);
  1801. }
  1802. if (NULL != pbValueOld)
  1803. {
  1804. wprintf(wszNewLine);
  1805. wprintf(myLoadResourceString(IDS_OLD_REG_VALUE)); // "Old Value:"
  1806. wprintf(wszNewLine);
  1807. PrintRegValue(
  1808. pwszValueName,
  1809. pwszValueName,
  1810. dwType,
  1811. TRUE,
  1812. TRUE,
  1813. 0,
  1814. cbValue,
  1815. pbValueOld,
  1816. NULL);
  1817. }
  1818. if (NULL == pwszValueName || L'\0' == *pwszValueName)
  1819. {
  1820. if (!g_fForce)
  1821. {
  1822. hr = E_ACCESSDENIED;
  1823. _JumpErrorStr(hr, error, "use -f", pwszSubKeyName);
  1824. }
  1825. if (NULL != hkeySub)
  1826. {
  1827. RegCloseKey(hkeySub);
  1828. hkeySub = NULL;
  1829. }
  1830. hr = RegDeleteKey(hkey, pwszSubKeyName);
  1831. if (S_OK != hr)
  1832. {
  1833. hr = myHError(hr);
  1834. _JumpErrorStr(hr, error, "RegDeleteKey", pwszSubKeyName);
  1835. }
  1836. }
  1837. else
  1838. {
  1839. hr = RegDeleteValue(hkeyT, pwszValueName);
  1840. if (S_OK != hr)
  1841. {
  1842. hr = myHError(hr);
  1843. _JumpErrorStr(hr, error, "RegDeleteValue", pwszValueName);
  1844. }
  1845. }
  1846. hr = S_OK;
  1847. error:
  1848. if (NULL != hkey)
  1849. {
  1850. RegCloseKey(hkey);
  1851. }
  1852. if (NULL != hkeySub)
  1853. {
  1854. RegCloseKey(hkeySub);
  1855. }
  1856. if (NULL != pwszPath)
  1857. {
  1858. LocalFree(pwszPath);
  1859. }
  1860. if (NULL != pwszName)
  1861. {
  1862. LocalFree(pwszName);
  1863. }
  1864. if (NULL != pwszSubKeyName)
  1865. {
  1866. LocalFree(pwszSubKeyName);
  1867. }
  1868. if (NULL != pwszValueName)
  1869. {
  1870. LocalFree(pwszValueName);
  1871. }
  1872. if (NULL != pbValueOld)
  1873. {
  1874. LocalFree(pbValueOld);
  1875. }
  1876. return(hr);
  1877. }