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
2085 lines
46 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1995 - 1999
|
|
//
|
|
// File: reg.cpp
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <pch.cpp>
|
|
|
|
#pragma hdrstop
|
|
|
|
#include <xenroll.h>
|
|
#include "polreg.h"
|
|
#include "certtype.h"
|
|
|
|
#define __dwFILE__ __dwFILE_CERTUTIL_REG_CPP__
|
|
|
|
|
|
// add two WCHAR L'\0's after the registry value, in case of a poorly
|
|
// formed REG_MULTI_SZ. Add another to handle possible odd sizes.
|
|
|
|
#define cbVALUEZEROPAD (3 * sizeof(WCHAR))
|
|
|
|
|
|
typedef struct _DUMPFLAGS
|
|
{
|
|
DWORD Mask;
|
|
DWORD Value;
|
|
WCHAR const *pwszDescription;
|
|
} DUMPFLAGS;
|
|
|
|
|
|
#define _DFBIT(def) { (def), (def), L#def }
|
|
#define _DFBIT2(mask, def) { (mask), (def), L#def }
|
|
|
|
|
|
DUMPFLAGS g_adfEditFlags[] =
|
|
{
|
|
_DFBIT(EDITF_ENABLEREQUESTEXTENSIONS),
|
|
_DFBIT(EDITF_REQUESTEXTENSIONLIST),
|
|
_DFBIT(EDITF_DISABLEEXTENSIONLIST),
|
|
_DFBIT(EDITF_ADDOLDKEYUSAGE),
|
|
_DFBIT(EDITF_ADDOLDCERTTYPE),
|
|
_DFBIT(EDITF_ATTRIBUTEENDDATE),
|
|
_DFBIT(EDITF_BASICCONSTRAINTSCRITICAL),
|
|
_DFBIT(EDITF_BASICCONSTRAINTSCA),
|
|
_DFBIT(EDITF_ENABLEAKIKEYID),
|
|
_DFBIT(EDITF_ATTRIBUTECA),
|
|
_DFBIT(EDITF_IGNOREREQUESTERGROUP),
|
|
_DFBIT(EDITF_ENABLEAKIISSUERNAME),
|
|
_DFBIT(EDITF_ENABLEAKIISSUERSERIAL),
|
|
_DFBIT(EDITF_ENABLEAKICRITICAL),
|
|
_DFBIT(EDITF_SERVERUPGRADED),
|
|
_DFBIT(EDITF_ATTRIBUTEEKU),
|
|
_DFBIT(EDITF_ENABLEDEFAULTSMIME),
|
|
_DFBIT(EDITF_EMAILOPTIONAL),
|
|
_DFBIT(EDITF_ATTRIBUTESUBJECTALTNAME2),
|
|
_DFBIT(EDITF_ENABLELDAPREFERRALS),
|
|
_DFBIT(EDITF_ENABLECHASECLIENTDC),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
DUMPFLAGS g_adfCRLFlags[] =
|
|
{
|
|
_DFBIT(CRLF_DELTA_USE_OLDEST_UNEXPIRED_BASE),
|
|
_DFBIT(CRLF_DELETE_EXPIRED_CRLS),
|
|
_DFBIT(CRLF_CRLNUMBER_CRITICAL),
|
|
_DFBIT(CRLF_REVCHECK_IGNORE_OFFLINE),
|
|
_DFBIT(CRLF_IGNORE_INVALID_POLICIES),
|
|
_DFBIT(CRLF_REBUILD_MODIFIED_SUBJECT_ONLY),
|
|
_DFBIT(CRLF_SAVE_FAILED_CERTS),
|
|
_DFBIT(CRLF_IGNORE_UNKNOWN_CMC_ATTRIBUTES),
|
|
_DFBIT(CRLF_IGNORE_CROSS_CERT_TRUST_ERROR),
|
|
_DFBIT(CRLF_PUBLISH_EXPIRED_CERT_CRLS),
|
|
_DFBIT(CRLF_ENFORCE_ENROLLMENT_AGENT),
|
|
_DFBIT(CRLF_DISABLE_RDN_REORDER),
|
|
_DFBIT(CRLF_DISABLE_ROOT_CROSS_CERTS),
|
|
_DFBIT(CRLF_LOG_FULL_RESPONSE),
|
|
_DFBIT(CRLF_USE_XCHG_CERT_TEMPLATE),
|
|
_DFBIT(CRLF_USE_CROSS_CERT_TEMPLATE),
|
|
_DFBIT(CRLF_ALLOW_REQUEST_ATTRIBUTE_SUBJECT),
|
|
_DFBIT(CRLF_REVCHECK_IGNORE_NOREVCHECK),
|
|
_DFBIT(CRLF_PRESERVE_EXPIRED_CA_CERTS),
|
|
_DFBIT(CRLF_PRESERVE_REVOKED_CA_CERTS),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
DUMPFLAGS g_adfInterfaceFlags[] =
|
|
{
|
|
_DFBIT(IF_LOCKICERTREQUEST),
|
|
_DFBIT(IF_NOREMOTEICERTREQUEST),
|
|
_DFBIT(IF_NOLOCALICERTREQUEST),
|
|
_DFBIT(IF_NORPCICERTREQUEST),
|
|
_DFBIT(IF_NOREMOTEICERTADMIN),
|
|
_DFBIT(IF_NOLOCALICERTADMIN),
|
|
_DFBIT(IF_NOREMOTEICERTADMINBACKUP),
|
|
_DFBIT(IF_NOLOCALICERTADMINBACKUP),
|
|
_DFBIT(IF_NOSNAPSHOTBACKUP),
|
|
_DFBIT(IF_ENFORCEENCRYPTICERTREQUEST),
|
|
_DFBIT(IF_ENFORCEENCRYPTICERTADMIN),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
DUMPFLAGS g_adfKRAFlags[] =
|
|
{
|
|
_DFBIT(KRAF_ENABLEFOREIGN),
|
|
_DFBIT(KRAF_SAVEBADREQUESTKEY),
|
|
_DFBIT(KRAF_ENABLEARCHIVEALL),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
DUMPFLAGS g_adfDBFlags[] =
|
|
{
|
|
_DFBIT(DBFLAGS_READONLY),
|
|
_DFBIT(DBFLAGS_CREATEIFNEEDED),
|
|
_DFBIT(DBFLAGS_CIRCULARLOGGING),
|
|
_DFBIT(DBFLAGS_LAZYFLUSH),
|
|
_DFBIT(DBFLAGS_MAXCACHESIZEX100),
|
|
_DFBIT(DBFLAGS_CHECKPOINTDEPTH60MB),
|
|
_DFBIT(DBFLAGS_LOGBUFFERSLARGE),
|
|
_DFBIT(DBFLAGS_LOGBUFFERSHUGE),
|
|
_DFBIT(DBFLAGS_LOGFILESIZE16MB),
|
|
_DFBIT(DBFLAGS_MULTITHREADTRANSACTIONS),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
DUMPFLAGS g_adfLDAPFlags[] =
|
|
{
|
|
_DFBIT(LDAPF_SSLENABLE),
|
|
_DFBIT(LDAPF_SIGNDISABLE),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
#define ISSCERT_LDAPURL ISSCERT_LDAPURL_OLD
|
|
#define ISSCERT_HTTPURL ISSCERT_HTTPURL_OLD
|
|
#define ISSCERT_FTPURL ISSCERT_FTPURL_OLD
|
|
#define ISSCERT_FILEURL ISSCERT_FILEURL_OLD
|
|
|
|
DUMPFLAGS g_adfIssuercertFlags[] =
|
|
{
|
|
_DFBIT(ISSCERT_LDAPURL),
|
|
_DFBIT(ISSCERT_HTTPURL),
|
|
_DFBIT(ISSCERT_FTPURL),
|
|
_DFBIT(ISSCERT_FILEURL),
|
|
_DFBIT(ISSCERT_ENABLE),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
|
|
DUMPFLAGS g_adfRequestDispositionFlags[] =
|
|
{
|
|
_DFBIT2(REQDISP_MASK, REQDISP_PENDING),
|
|
_DFBIT2(REQDISP_MASK, REQDISP_ISSUE),
|
|
_DFBIT2(REQDISP_MASK, REQDISP_DENY),
|
|
_DFBIT2(REQDISP_MASK, REQDISP_USEREQUESTATTRIBUTE),
|
|
_DFBIT(REQDISP_PENDINGFIRST),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
|
|
#define REVEXT_CDPLDAPURL REVEXT_CDPLDAPURL_OLD
|
|
#define REVEXT_CDPHTTPURL REVEXT_CDPHTTPURL_OLD
|
|
#define REVEXT_CDPFTPURL REVEXT_CDPFTPURL_OLD
|
|
#define REVEXT_CDPFILEURL REVEXT_CDPFILEURL_OLD
|
|
|
|
DUMPFLAGS g_adfRevocationTypeFlags[] =
|
|
{
|
|
_DFBIT(REVEXT_CDPLDAPURL),
|
|
_DFBIT(REVEXT_CDPHTTPURL),
|
|
_DFBIT(REVEXT_CDPFTPURL),
|
|
_DFBIT(REVEXT_CDPFILEURL),
|
|
_DFBIT(REVEXT_CDPENABLE),
|
|
_DFBIT(REVEXT_ASPENABLE),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
|
|
DUMPFLAGS g_adfSetupStatus[] =
|
|
{
|
|
_DFBIT(SETUP_SERVER_FLAG),
|
|
_DFBIT(SETUP_CLIENT_FLAG),
|
|
_DFBIT(SETUP_SUSPEND_FLAG),
|
|
_DFBIT(SETUP_REQUEST_FLAG),
|
|
_DFBIT(SETUP_ONLINE_FLAG),
|
|
_DFBIT(SETUP_DENIED_FLAG),
|
|
_DFBIT(SETUP_CREATEDB_FLAG),
|
|
_DFBIT(SETUP_ATTEMPT_VROOT_CREATE),
|
|
_DFBIT(SETUP_FORCECRL_FLAG),
|
|
_DFBIT(SETUP_UPDATE_CAOBJECT_SVRTYPE),
|
|
_DFBIT(SETUP_SERVER_UPGRADED_FLAG),
|
|
_DFBIT(SETUP_SECURITY_CHANGED),
|
|
_DFBIT(SETUP_W2K_SECURITY_NOT_UPGRADED_FLAG),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
|
|
DUMPFLAGS g_adfCertPublishFlags[] =
|
|
{
|
|
_DFBIT(EXITPUB_FILE),
|
|
_DFBIT(EXITPUB_ACTIVEDIRECTORY),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
|
|
DUMPFLAGS g_adfCAType[] =
|
|
{
|
|
_DFBIT2(MAXDWORD, ENUM_ENTERPRISE_ROOTCA),
|
|
_DFBIT2(MAXDWORD, ENUM_ENTERPRISE_SUBCA),
|
|
_DFBIT2(MAXDWORD, ENUM_STANDALONE_ROOTCA),
|
|
_DFBIT2(MAXDWORD, ENUM_STANDALONE_SUBCA),
|
|
_DFBIT2(MAXDWORD, ENUM_UNKNOWN_CA),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
|
|
DUMPFLAGS g_adfForceTeletex[] =
|
|
{
|
|
_DFBIT2(ENUM_TELETEX_MASK, ENUM_TELETEX_OFF),
|
|
_DFBIT2(ENUM_TELETEX_MASK, ENUM_TELETEX_ON),
|
|
_DFBIT2(ENUM_TELETEX_MASK, ENUM_TELETEX_AUTO),
|
|
_DFBIT2(ENUM_TELETEX_UTF8, ENUM_TELETEX_UTF8),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
|
|
DUMPFLAGS g_adfCSURL[] =
|
|
{
|
|
_DFBIT(CSURL_SERVERPUBLISH),
|
|
_DFBIT(CSURL_ADDTOCERTCDP),
|
|
_DFBIT(CSURL_ADDTOFRESHESTCRL),
|
|
_DFBIT(CSURL_ADDTOCRLCDP),
|
|
_DFBIT(CSURL_PUBLISHRETRY),
|
|
_DFBIT(CSURL_ADDTOCERTOCSP),
|
|
_DFBIT(CSURL_SERVERPUBLISHDELTA),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
|
|
// Enrollment Flags:
|
|
|
|
DUMPFLAGS g_adfTemplateEnroll[] =
|
|
{
|
|
_DFBIT(CT_FLAG_INCLUDE_SYMMETRIC_ALGORITHMS),
|
|
_DFBIT(CT_FLAG_PEND_ALL_REQUESTS),
|
|
_DFBIT(CT_FLAG_PUBLISH_TO_KRA_CONTAINER),
|
|
_DFBIT(CT_FLAG_PUBLISH_TO_DS),
|
|
_DFBIT(CT_FLAG_AUTO_ENROLLMENT_CHECK_USER_DS_CERTIFICATE),
|
|
_DFBIT(CT_FLAG_AUTO_ENROLLMENT),
|
|
_DFBIT(CT_FLAG_PREVIOUS_APPROVAL_VALIDATE_REENROLLMENT),
|
|
_DFBIT(CT_FLAG_DOMAIN_AUTHENTICATION_NOT_REQUIRED),
|
|
_DFBIT(CT_FLAG_USER_INTERACTION_REQUIRED),
|
|
_DFBIT(CT_FLAG_ADD_TEMPLATE_NAME),
|
|
_DFBIT(CT_FLAG_REMOVE_INVALID_CERTIFICATE_FROM_PERSONAL_STORE),
|
|
_DFBIT(CT_FLAG_ALLOW_ENROLL_ON_BEHALF_OF),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
|
|
// Certificate Subject Name Flags:
|
|
|
|
DUMPFLAGS g_adfTemplateName[] =
|
|
{
|
|
_DFBIT(CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT),
|
|
_DFBIT(CT_FLAG_ADD_EMAIL),
|
|
_DFBIT(CT_FLAG_ADD_OBJ_GUID),
|
|
_DFBIT(CT_FLAG_ADD_DIRECTORY_PATH),
|
|
_DFBIT(CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT_ALT_NAME),
|
|
_DFBIT(CT_FLAG_SUBJECT_ALT_REQUIRE_SPN),
|
|
_DFBIT(CT_FLAG_SUBJECT_ALT_REQUIRE_DIRECTORY_GUID),
|
|
_DFBIT(CT_FLAG_SUBJECT_ALT_REQUIRE_UPN),
|
|
_DFBIT(CT_FLAG_SUBJECT_ALT_REQUIRE_EMAIL),
|
|
_DFBIT(CT_FLAG_SUBJECT_ALT_REQUIRE_DNS),
|
|
_DFBIT(CT_FLAG_SUBJECT_REQUIRE_DNS_AS_CN),
|
|
_DFBIT(CT_FLAG_SUBJECT_REQUIRE_EMAIL),
|
|
_DFBIT(CT_FLAG_SUBJECT_REQUIRE_COMMON_NAME),
|
|
_DFBIT(CT_FLAG_SUBJECT_REQUIRE_DIRECTORY_PATH),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
DUMPFLAGS g_adfTemplatePrivateKey[] =
|
|
{
|
|
// Private Key Flags:
|
|
_DFBIT(CT_FLAG_REQUIRE_PRIVATE_KEY_ARCHIVAL),
|
|
_DFBIT(CT_FLAG_EXPORTABLE_KEY),
|
|
_DFBIT(CT_FLAG_STRONG_KEY_PROTECTION_REQUIRED),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
|
|
// Old V1 template flags definitions:
|
|
//efine CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT 0x00000001
|
|
//efine CT_FLAG_ADD_EMAIL 0x00000002
|
|
//efine CT_FLAG_ADD_OBJ_GUID 0x00000004
|
|
//efine CT_FLAG_PUBLISH_TO_DS 0x00000008
|
|
//efine CT_FLAG_EXPORTABLE_KEY 0x00000010
|
|
//efine CT_FLAG_AUTO_ENROLLMENT 0x00000020
|
|
//efine CT_FLAG_MACHINE_TYPE 0x00000040
|
|
//efine CT_FLAG_IS_CA 0x00000080
|
|
//efine CT_FLAG_ADD_DIRECTORY_PATH 0x00000100
|
|
//efine CT_FLAG_ADD_TEMPLATE_NAME 0x00000200
|
|
#define CT_FLAG_ADD_SUBJECT_DIRECTORY_PATH 0x00000400
|
|
//efine CT_FLAG_IS_CROSS_CA 0x00000800
|
|
//efine CT_FLAG_IS_DEFAULT 0x00010000
|
|
//efine CT_FLAG_IS_MODIFIED 0x00020000
|
|
#define CT_FLAG_IS_DELETED 0x00040000
|
|
#define CT_FLAG_POLICY_MISMATCH 0x00080000
|
|
|
|
|
|
// General Flags
|
|
|
|
DUMPFLAGS g_adfTemplateGeneral[] =
|
|
{
|
|
_DFBIT(CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT),
|
|
_DFBIT(CT_FLAG_ADD_EMAIL),
|
|
_DFBIT(CT_FLAG_ADD_OBJ_GUID),
|
|
_DFBIT(CT_FLAG_PUBLISH_TO_DS),
|
|
_DFBIT(CT_FLAG_EXPORTABLE_KEY),
|
|
_DFBIT(CT_FLAG_AUTO_ENROLLMENT),
|
|
_DFBIT(CT_FLAG_MACHINE_TYPE),
|
|
_DFBIT(CT_FLAG_IS_CA),
|
|
_DFBIT(CT_FLAG_ADD_DIRECTORY_PATH),
|
|
_DFBIT(CT_FLAG_ADD_TEMPLATE_NAME),
|
|
_DFBIT(CT_FLAG_ADD_SUBJECT_DIRECTORY_PATH),
|
|
_DFBIT(CT_FLAG_IS_CROSS_CA),
|
|
_DFBIT(CT_FLAG_IS_DEFAULT),
|
|
_DFBIT(CT_FLAG_IS_MODIFIED),
|
|
_DFBIT(CT_FLAG_IS_DELETED),
|
|
_DFBIT(CT_FLAG_POLICY_MISMATCH),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
|
|
DUMPFLAGS g_adfKMSCertStatus[] =
|
|
{
|
|
_DFBIT(CERTFLAGS_REVOKED),
|
|
_DFBIT(CERTFLAGS_NOT_EXPIRED),
|
|
_DFBIT(CERTFLAGS_SIGNING),
|
|
_DFBIT(CERTFLAGS_SEALING),
|
|
_DFBIT(CERTFLAGS_CURRENT),
|
|
_DFBIT(CERTFLAGS_IMPORTED),
|
|
_DFBIT2(CERTFLAGS_VERSION_3, CERTFLAGS_VERSION_1),
|
|
_DFBIT2(CERTFLAGS_VERSION_3, CERTFLAGS_VERSION_3),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
|
|
DUMPFLAGS g_adfCRLPublishFlags[] =
|
|
{
|
|
_DFBIT(CPF_BASE),
|
|
_DFBIT(CPF_DELTA),
|
|
_DFBIT(CPF_COMPLETE),
|
|
_DFBIT(CPF_SHADOW),
|
|
_DFBIT(CPF_CASTORE_ERROR),
|
|
_DFBIT(CPF_BADURL_ERROR),
|
|
_DFBIT(CPF_MANUAL),
|
|
_DFBIT(CPF_SIGNATURE_ERROR),
|
|
_DFBIT(CPF_LDAP_ERROR),
|
|
_DFBIT(CPF_FILE_ERROR),
|
|
_DFBIT(CPF_FTP_ERROR),
|
|
_DFBIT(CPF_HTTP_ERROR),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
DUMPFLAGS g_adfCAFlags[] =
|
|
{
|
|
_DFBIT(CA_FLAG_NO_TEMPLATE_SUPPORT),
|
|
_DFBIT(CA_FLAG_SUPPORTS_NT_AUTHENTICATION),
|
|
_DFBIT(CA_FLAG_CA_SUPPORTS_MANUAL_AUTHENTICATION),
|
|
_DFBIT(CA_FLAG_CA_SERVERTYPE_ADVANCED),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
|
|
DUMPFLAGS g_adfOIDFlags[] =
|
|
{
|
|
_DFBIT2(MAXDWORD, CERT_OID_TYPE_TEMPLATE),
|
|
_DFBIT2(MAXDWORD, CERT_OID_TYPE_ISSUER_POLICY),
|
|
_DFBIT2(MAXDWORD, CERT_OID_TYPE_APPLICATION_POLICY),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
|
|
DUMPFLAGS g_adfRequestClientId[] =
|
|
{
|
|
_DFBIT2(MAXDWORD, XECI_DISABLE),
|
|
_DFBIT2(MAXDWORD, XECI_XENROLL),
|
|
_DFBIT2(MAXDWORD, XECI_AUTOENROLL),
|
|
_DFBIT2(MAXDWORD, XECI_REQWIZARD),
|
|
_DFBIT2(MAXDWORD, XECI_CERTREQ),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
DUMPFLAGS g_adfSMTPEventFilter[] =
|
|
{
|
|
#ifndef EXITEVENT_CERTUNREVOKED
|
|
#define EXITEVENT_CERTUNREVOKED 0x100
|
|
#endif
|
|
_DFBIT(EXITEVENT_CERTISSUED),
|
|
_DFBIT(EXITEVENT_CERTPENDING),
|
|
_DFBIT(EXITEVENT_CERTDENIED),
|
|
_DFBIT(EXITEVENT_CERTREVOKED),
|
|
_DFBIT(EXITEVENT_CERTRETRIEVEPENDING),
|
|
_DFBIT(EXITEVENT_CRLISSUED),
|
|
_DFBIT(EXITEVENT_SHUTDOWN),
|
|
_DFBIT(EXITEVENT_STARTUP),
|
|
_DFBIT(EXITEVENT_CERTUNREVOKED),
|
|
{ 0, 0, NULL }
|
|
};
|
|
|
|
|
|
typedef struct _DUMPFLAGSREGMAP
|
|
{
|
|
WCHAR const *pwszRegName;
|
|
DUMPFLAGS const *adf;
|
|
} DUMPFLAGSREGMAP;
|
|
|
|
|
|
DUMPFLAGSREGMAP g_adfrm[] = {
|
|
{ wszREGEDITFLAGS, g_adfEditFlags },
|
|
{ wszREGISSUERCERTURLFLAGS, g_adfIssuercertFlags },
|
|
{ wszREGREQUESTDISPOSITION, g_adfRequestDispositionFlags },
|
|
{ wszREGREVOCATIONTYPE, g_adfRevocationTypeFlags },
|
|
{ wszREGSETUPSTATUS, g_adfSetupStatus },
|
|
{ wszREGCERTPUBLISHFLAGS, g_adfCertPublishFlags },
|
|
{ wszREGCRLEDITFLAGS, g_adfEditFlags },
|
|
{ wszREGCRLFLAGS, g_adfCRLFlags },
|
|
{ wszREGKRAFLAGS, g_adfKRAFlags },
|
|
{ wszREGINTERFACEFLAGS, g_adfInterfaceFlags },
|
|
{ wszREGLDAPFLAGS, g_adfLDAPFlags },
|
|
{ wszREGDBFLAGS, g_adfDBFlags },
|
|
{ wszREGCATYPE, g_adfCAType},
|
|
{ wszREGWEBCLIENTCATYPE, g_adfCAType},
|
|
{ wszREGFORCETELETEX, g_adfForceTeletex},
|
|
{ CERTTYPE_RPOP_ENROLLMENT_FLAG, g_adfTemplateEnroll },
|
|
{ CERTTYPE_PROP_NAME_FLAG, g_adfTemplateName },
|
|
{ CERTTYPE_PROP_PRIVATE_KEY_FLAG, g_adfTemplatePrivateKey },
|
|
//{ CERTTYPE_PROP_FLAGS, g_adfTemplateGeneral },
|
|
{ wszCUREGDSTEMPLATEFLAGS, g_adfTemplateGeneral },
|
|
{ wszCUREGDSCAFLAGS, g_adfCAFlags },
|
|
//{ OID_PROP_TYPE, g_adfOIDFlags },
|
|
{ wszCUREGDSOIDFLAGS, g_adfOIDFlags },
|
|
{ wszPROPCERTIFICATEENROLLMENTFLAGS, g_adfTemplateEnroll },
|
|
{ wszPROPCERTIFICATEGENERALFLAGS, g_adfTemplateGeneral },
|
|
{ wszKMSCERTSTATUS, g_adfKMSCertStatus },
|
|
{ wszPROPCRLPUBLISHFLAGS, g_adfCRLPublishFlags },
|
|
{ wszREQUESTCLIENTID, g_adfRequestClientId },
|
|
{ wszREGCRLPUBLICATIONURLS, g_adfCSURL },
|
|
{ wszREGCACERTPUBLICATIONURLS, g_adfCSURL },
|
|
{ wszREGEXITSMTPEVENTFILTER, g_adfSMTPEventFilter },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
|
|
VOID
|
|
cuPrintFlags(
|
|
IN DWORD Flags,
|
|
IN DUMPFLAGS const *pdf)
|
|
{
|
|
DWORD ExtraFlags = Flags;
|
|
|
|
for ( ; NULL != pdf->pwszDescription; pdf++)
|
|
{
|
|
BOOL fSet = (Flags & pdf->Mask) == pdf->Value;
|
|
|
|
if (fSet || g_fVerbose)
|
|
{
|
|
wprintf(
|
|
L" %ws%ws -- %x",
|
|
fSet? g_wszEmpty : L" " wszLPAREN,
|
|
pdf->pwszDescription,
|
|
pdf->Value);
|
|
if (9 < pdf->Value)
|
|
{
|
|
wprintf(L" (%d)", pdf->Value);
|
|
}
|
|
if (!fSet)
|
|
{
|
|
wprintf(wszRPAREN);
|
|
}
|
|
wprintf(wszNewLine);
|
|
}
|
|
ExtraFlags &= ~pdf->Mask;
|
|
}
|
|
if (0 != ExtraFlags)
|
|
{
|
|
wprintf(L" 0x%x (%u)\n", ExtraFlags, ExtraFlags);
|
|
}
|
|
}
|
|
|
|
|
|
WCHAR const *
|
|
regTail(
|
|
IN WCHAR const *pwszRegName)
|
|
{
|
|
WCHAR const *pwsz = wcsrchr(pwszRegName, L'\\');
|
|
|
|
if (NULL != pwsz)
|
|
{
|
|
pwsz++;
|
|
}
|
|
else
|
|
{
|
|
pwsz = pwszRegName;
|
|
}
|
|
return(pwsz);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuLookupRegFlags(
|
|
IN WCHAR const *pwszRegName,
|
|
OUT DUMPFLAGS const **ppdf)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
DUMPFLAGSREGMAP const *pdfrm;
|
|
|
|
*ppdf = NULL;
|
|
pwszRegName = regTail(pwszRegName);
|
|
for (pdfrm = g_adfrm; NULL != pdfrm->pwszRegName; pdfrm++)
|
|
{
|
|
if (0 == mylstrcmpiS(pwszRegName, pdfrm->pwszRegName))
|
|
{
|
|
*ppdf = pdfrm->adf;
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
VOID
|
|
cuPrintRegDWord(
|
|
IN DWORD Value,
|
|
IN WCHAR const *pwszRegName)
|
|
{
|
|
HRESULT hr;
|
|
|
|
pwszRegName = regTail(pwszRegName);
|
|
if (0 == LSTRCMPIS(pwszRegName, wszREGVERSION))
|
|
{
|
|
wprintf(L" -- %u.%u", Value >> 16, Value & ((1 << 16) - 1));
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
cuPrintRegFlags(
|
|
IN BOOL fNewLine,
|
|
IN DWORD Flags,
|
|
IN WCHAR const *pwszRegName)
|
|
{
|
|
HRESULT hr;
|
|
DUMPFLAGS const *pdf;
|
|
|
|
pwszRegName = regTail(pwszRegName);
|
|
if (0 == LSTRCMPIS(pwszRegName, wszHASHALGORITHM) ||
|
|
0 == LSTRCMPIS(pwszRegName, wszENCRYPTIONALGORITHM))
|
|
{
|
|
cuDumpAlgid(Flags);
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = cuLookupRegFlags(pwszRegName, &pdf);
|
|
_JumpIfError2(hr, error, "cuLookupRegFlags", hr);
|
|
|
|
if (fNewLine)
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
cuPrintFlags(Flags, pdf);
|
|
}
|
|
|
|
error:
|
|
return(S_OK == hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuMapRegFlags(
|
|
IN WCHAR const *pwszRegName,
|
|
IN WCHAR const *pwszRegValue,
|
|
IN BOOL fClearField,
|
|
IN OUT DWORD *pFlags)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR const *pwsz;
|
|
DUMPFLAGS const *pdf;
|
|
|
|
hr = cuLookupRegFlags(pwszRegName, &pdf);
|
|
_JumpIfErrorStr2(hr, error, "cuLookupRegFlags", pwszRegName, hr);
|
|
|
|
for ( ; NULL != pdf->pwszDescription; pdf++)
|
|
{
|
|
if (0 == mylstrcmpiS(pwszRegValue, pdf->pwszDescription))
|
|
{
|
|
break;
|
|
}
|
|
pwsz = wcschr(pdf->pwszDescription, L'_');
|
|
if (NULL == pwsz)
|
|
{
|
|
continue;
|
|
}
|
|
if (0 == mylstrcmpiS(pwszRegValue, &pwsz[1]))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (NULL == pdf->pwszDescription)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpErrorStr2(hr, error, "no match", pwszRegValue, hr);
|
|
}
|
|
|
|
*pFlags &= ~pdf->Mask;
|
|
if (!fClearField)
|
|
{
|
|
*pFlags |= pdf->Value;
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
OpenSubKey(
|
|
IN HKEY hkey,
|
|
IN WCHAR const *pwszName,
|
|
IN BOOL fCreateSubKey,
|
|
OUT HKEY *phkeySub,
|
|
OUT WCHAR **ppwszSubKeyName,
|
|
OUT WCHAR **ppwszValueName)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hkeySub = NULL;
|
|
WCHAR *pwszSubKeyName = NULL;
|
|
WCHAR *pwszT;
|
|
DWORD cwcSkip;
|
|
DWORD i;
|
|
WCHAR awc[MAX_PATH];
|
|
|
|
*phkeySub = NULL;
|
|
hr = myDupString(pwszName, &pwszSubKeyName);
|
|
_JumpIfError(hr, error, "myDupString");
|
|
|
|
cwcSkip = wcslen(pwszName);
|
|
|
|
hr = RegOpenKeyEx(
|
|
hkey,
|
|
pwszSubKeyName,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hkeySub);
|
|
if (S_OK != hr)
|
|
{
|
|
//_PrintErrorStr(hr, "RegOpenKeyEx", pwszName);
|
|
|
|
hkeySub = NULL;
|
|
pwszT = wcsrchr(pwszSubKeyName, L'\\');
|
|
if (NULL != pwszT)
|
|
{
|
|
*pwszT = L'\0';
|
|
cwcSkip = SAFE_SUBTRACT_POINTERS(pwszT, pwszSubKeyName) + 1;
|
|
|
|
hr = RegOpenKeyEx(
|
|
hkey,
|
|
pwszSubKeyName,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hkeySub);
|
|
if ((HRESULT) ERROR_FILE_NOT_FOUND == hr && fCreateSubKey)
|
|
{
|
|
hr = RegCreateKey(hkey, pwszSubKeyName, &hkeySub);
|
|
_JumpIfErrorStr(hr, error, "RegCreateKey", pwszSubKeyName);
|
|
}
|
|
_JumpIfErrorStr(hr, error, "RegOpenKeyEx", pwszSubKeyName);
|
|
}
|
|
}
|
|
|
|
if (NULL != hkeySub)
|
|
{
|
|
pwszName += cwcSkip;
|
|
|
|
if (L'\0' != *pwszName)
|
|
{
|
|
// Look for case-ignore registry value name, & use the value's
|
|
// correct upper/lower case spelling if an existing registry value:
|
|
|
|
for (i = 0; ; i++)
|
|
{
|
|
DWORD cwc = ARRAYSIZE(awc);
|
|
hr = RegEnumValue(hkeySub, i, awc, &cwc, NULL, NULL, NULL, NULL);
|
|
if (S_OK != hr)
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
if (0 == mylstrcmpiL(awc, pwszName))
|
|
{
|
|
pwszName = awc;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = myDupString(pwszName, ppwszValueName);
|
|
_JumpIfError(hr, error, "myDupString");
|
|
|
|
if (NULL != hkeySub)
|
|
{
|
|
*phkeySub = hkeySub;
|
|
hkeySub = NULL;
|
|
}
|
|
*ppwszSubKeyName = pwszSubKeyName;
|
|
pwszSubKeyName = NULL;
|
|
|
|
error:
|
|
if (NULL != pwszSubKeyName)
|
|
{
|
|
LocalFree(pwszSubKeyName);
|
|
}
|
|
if (NULL != hkeySub)
|
|
{
|
|
RegCloseKey(hkeySub);
|
|
}
|
|
return(myHError(hr));
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintRegStringValue(
|
|
IN WCHAR const *pwszLookupName,
|
|
IN WCHAR const *pwszValue)
|
|
{
|
|
DWORD Flags;
|
|
WCHAR *pwszDup = NULL;
|
|
|
|
wprintf(L"%ws", pwszValue);
|
|
if (iswdigit(*pwszValue))
|
|
{
|
|
BOOL fParmValid = FALSE;
|
|
DWORD dwParm;
|
|
WCHAR const *pwszObjId = pwszValue;
|
|
WCHAR *pwszParm = wcschr(pwszValue, L',');
|
|
|
|
if (NULL != pwszParm)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = myDupString(pwszValue, &pwszDup);
|
|
_PrintIfError(hr, "myDupString");
|
|
|
|
pwszParm = wcschr(pwszDup, L',');
|
|
if (NULL != pwszParm)
|
|
{
|
|
*pwszParm++ = L'\0';
|
|
dwParm = myWtoI(pwszParm, &fParmValid);
|
|
pwszObjId = fParmValid? pwszDup : NULL;
|
|
}
|
|
}
|
|
if (NULL != pwszObjId)
|
|
{
|
|
cuPrintPossibleObjectIdName(pwszObjId);
|
|
if (fParmValid)
|
|
{
|
|
wprintf(L" %x", dwParm);
|
|
if (9 < dwParm)
|
|
{
|
|
wprintf(L" (%d)", dwParm);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
cuPrintRegFlags(TRUE, _wtoi(pwszValue), pwszLookupName);
|
|
if (NULL != pwszDup)
|
|
{
|
|
LocalFree(pwszDup);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintRegValue(
|
|
IN WCHAR const *pwszLookupName,
|
|
IN WCHAR const *pwszDisplayName,
|
|
IN DWORD dwType,
|
|
IN BOOL fPrintDwordNameAndValue,
|
|
IN BOOL fPrintType,
|
|
IN DWORD cwcSeparator,
|
|
IN DWORD cbValue,
|
|
OPTIONAL IN BYTE const *pbValue,
|
|
OPTIONAL OUT BOOL *pfLongValue)
|
|
{
|
|
HRESULT hr;
|
|
DWORD i;
|
|
WCHAR const *pwsz;
|
|
BOOL fLongValue = FALSE;
|
|
char const *pszEqual = NULL != pbValue? " =" : "";
|
|
|
|
if (0 == cwcSeparator && fPrintType)
|
|
{
|
|
cwcSeparator = 1;
|
|
}
|
|
if (fPrintDwordNameAndValue)
|
|
{
|
|
wprintf(L" %ws%*ws", pwszDisplayName, cwcSeparator, L"");
|
|
}
|
|
switch (dwType)
|
|
{
|
|
case REG_DWORD:
|
|
if (fPrintDwordNameAndValue)
|
|
{
|
|
wprintf(
|
|
L"%ws%hs",
|
|
fPrintType? L"REG_DWORD" : L"",
|
|
pszEqual);
|
|
}
|
|
if (NULL != pbValue)
|
|
{
|
|
CSASSERT(sizeof(DWORD) == cbValue);
|
|
if (fPrintDwordNameAndValue)
|
|
{
|
|
wprintf(L" %x", *(DWORD *) pbValue);
|
|
if (9 < *(DWORD *) pbValue)
|
|
{
|
|
wprintf(L" (%d)", *(DWORD *) pbValue);
|
|
}
|
|
cuPrintRegDWord(*(DWORD *) pbValue, pwszLookupName);
|
|
wprintf(wszNewLine);
|
|
}
|
|
if (cuPrintRegFlags(FALSE, *(DWORD *) pbValue, pwszLookupName))
|
|
{
|
|
fLongValue = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (fPrintDwordNameAndValue)
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case REG_SZ:
|
|
if (fPrintType)
|
|
{
|
|
wprintf(L"REG_SZ");
|
|
}
|
|
if (NULL != pbValue && 0 != cbValue)
|
|
{
|
|
CSASSERT((wcslen((WCHAR const *) pbValue) + 1) * sizeof(WCHAR) == cbValue);
|
|
wprintf(L" = ");
|
|
PrintRegStringValue(pwszLookupName, (WCHAR const *) pbValue);
|
|
if (44 < wcslen((WCHAR const *) pbValue))
|
|
{
|
|
fLongValue = TRUE;
|
|
}
|
|
}
|
|
wprintf(wszNewLine);
|
|
break;
|
|
|
|
case REG_MULTI_SZ:
|
|
wprintf(
|
|
L"%ws%hs",
|
|
fPrintType? L"REG_MULTI_SZ" : L"",
|
|
pszEqual);
|
|
if (NULL != pbValue && 0 != cbValue)
|
|
{
|
|
pwsz = (WCHAR const *) pbValue;
|
|
if (L'\0' == *pwsz)
|
|
{
|
|
// empty value
|
|
}
|
|
else if (!fPrintType && L'\0' == pwsz[wcslen(pwsz) + 1])
|
|
{
|
|
// single value
|
|
|
|
wprintf(L" ");
|
|
PrintRegStringValue(pwszLookupName, (WCHAR const *) pbValue);
|
|
pwsz += wcslen(pwsz) + 1;
|
|
}
|
|
else
|
|
{
|
|
wprintf(wszNewLine);
|
|
i = 0;
|
|
for ( ; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
|
|
{
|
|
wprintf(L" %u: ", i);
|
|
PrintRegStringValue(pwszLookupName, pwsz);
|
|
wprintf(wszNewLine);
|
|
i++;
|
|
}
|
|
fLongValue = TRUE;
|
|
}
|
|
CSASSERT(
|
|
(pwsz == (WCHAR *) pbValue && 2 * sizeof(WCHAR) == cbValue) ||
|
|
(SAFE_SUBTRACT_POINTERS((BYTE *) pwsz, pbValue) +
|
|
sizeof(WCHAR) ==
|
|
cbValue));
|
|
}
|
|
if (!fLongValue)
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
case REG_BINARY:
|
|
if (fPrintType)
|
|
{
|
|
if (REG_BINARY == dwType)
|
|
{
|
|
wprintf(L"REG_BINARY");
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"???=%x%", dwType);
|
|
}
|
|
}
|
|
wprintf(L"%hs", pszEqual);
|
|
if (NULL != pbValue && 0 != cbValue)
|
|
{
|
|
BOOL fDump = TRUE;
|
|
WCHAR const *pwszNL = wszNewLine;
|
|
|
|
if (REG_BINARY == dwType && sizeof(FILETIME) == cbValue)
|
|
{
|
|
hr = cuDumpFileTimeOrPeriod(
|
|
0,
|
|
NULL,
|
|
(FILETIME const *) pbValue);
|
|
if (S_OK == hr)
|
|
{
|
|
if (g_fVerbose)
|
|
{
|
|
pwszNL = NULL;
|
|
}
|
|
else
|
|
{
|
|
fDump = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if (fDump)
|
|
{
|
|
if (NULL != pwszNL)
|
|
{
|
|
wprintf(pwszNL);
|
|
}
|
|
DumpHex(0, pbValue, cbValue);
|
|
fLongValue = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
if (NULL != pfLongValue)
|
|
{
|
|
*pfLongValue = fLongValue;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
cuRegPrintDwordValue(
|
|
IN BOOL fPrintNameAndValue,
|
|
IN WCHAR const *pwszLookupName,
|
|
IN WCHAR const *pwszDisplayName,
|
|
IN DWORD dwValue)
|
|
{
|
|
BOOL fDisplayed = FALSE;
|
|
|
|
PrintRegValue(
|
|
pwszLookupName,
|
|
pwszDisplayName,
|
|
REG_DWORD,
|
|
fPrintNameAndValue,
|
|
FALSE,
|
|
0, // cwcSeparator
|
|
sizeof(dwValue),
|
|
(BYTE const *) &dwValue,
|
|
&fDisplayed);
|
|
return(fDisplayed);
|
|
}
|
|
|
|
|
|
VOID
|
|
cuRegPrintAwszValue(
|
|
IN WCHAR const *pwszName,
|
|
OPTIONAL IN WCHAR const * const *prgpwszValues)
|
|
{
|
|
WCHAR *pwszzValues = NULL;
|
|
WCHAR *pwsz;
|
|
DWORD cwcAlloc;
|
|
DWORD i;
|
|
|
|
cwcAlloc = 1;
|
|
if (NULL == prgpwszValues || NULL == prgpwszValues[0])
|
|
{
|
|
cwcAlloc++;
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; NULL != prgpwszValues[i]; i++)
|
|
{
|
|
cwcAlloc += wcslen(prgpwszValues[i]) + 1;
|
|
}
|
|
}
|
|
pwszzValues = (WCHAR *) LocalAlloc(LMEM_FIXED, cwcAlloc * sizeof(WCHAR));
|
|
if (NULL == pwszzValues)
|
|
{
|
|
_JumpError(E_OUTOFMEMORY, error, "LocalAlloc");
|
|
}
|
|
pwsz = pwszzValues;
|
|
if (NULL == prgpwszValues || NULL == prgpwszValues[0])
|
|
{
|
|
*pwsz++ = L'\0';
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; NULL != prgpwszValues[i]; i++)
|
|
{
|
|
wcscpy(pwsz, prgpwszValues[i]);
|
|
pwsz += wcslen(pwsz) + 1;
|
|
}
|
|
}
|
|
*pwsz = L'\0';
|
|
CSASSERT(SAFE_SUBTRACT_POINTERS(pwsz, pwszzValues) + 1 == cwcAlloc);
|
|
|
|
PrintRegValue(
|
|
pwszName,
|
|
pwszName,
|
|
REG_MULTI_SZ,
|
|
TRUE,
|
|
FALSE,
|
|
0, // cwcSeparator
|
|
cwcAlloc * sizeof(WCHAR),
|
|
(BYTE const *) pwszzValues,
|
|
NULL); // pfLongValue
|
|
|
|
error:
|
|
if (NULL != pwszzValues)
|
|
{
|
|
LocalFree(pwszzValues);
|
|
}
|
|
}
|
|
|
|
|
|
#define REGOP_NONE 0
|
|
#define REGOP_SET 1
|
|
#define REGOP_CLEAR 2
|
|
|
|
|
|
BOOL
|
|
IsInList(
|
|
IN WCHAR const *pwsz,
|
|
OPTIONAL IN WCHAR const *pwszzList)
|
|
{
|
|
BOOL fFound = FALSE;
|
|
WCHAR *pwszT;
|
|
|
|
if (NULL != pwszzList)
|
|
{
|
|
for ( ; L'\0' != *pwszzList; pwszzList += wcslen(pwszzList) + 1)
|
|
{
|
|
if (0 == mylstrcmpiL(pwszzList, pwsz))
|
|
{
|
|
fFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return(fFound);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CombineMultiSzRegValues(
|
|
IN DWORD RegOp,
|
|
IN WCHAR const *pwszRegValue,
|
|
IN DWORD dwTypeOld,
|
|
IN DWORD cbValueOld,
|
|
OPTIONAL IN BYTE const *pbValueOld,
|
|
OUT BYTE **ppbValue,
|
|
OUT DWORD *pcbValue)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszDst;
|
|
WCHAR const *pwsz;
|
|
DWORD cpwsz;
|
|
WCHAR const **apwsz = NULL;
|
|
DWORD cOld = 0;
|
|
DWORD cNew = 0;
|
|
DWORD cCombined;
|
|
WCHAR *pwszzNew = NULL;
|
|
DWORD cwc;
|
|
DWORD i;
|
|
|
|
if (REGOP_NONE != RegOp)
|
|
{
|
|
pwsz = (WCHAR *) pbValueOld;
|
|
if (NULL != pwsz && 0 != cbValueOld)
|
|
{
|
|
for ( ; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
|
|
{
|
|
cOld++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Convert backslash-n sequences to L'\0' and move data up.
|
|
|
|
cwc = wcslen(pwszRegValue) + 1 + 1;
|
|
pwszzNew = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
|
|
if (NULL == pwszzNew)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
pwszDst = pwszzNew;
|
|
pwsz = pwszRegValue;
|
|
|
|
if (L'\0' != *pwsz && REGOP_CLEAR != RegOp)
|
|
{
|
|
cNew++;
|
|
}
|
|
while (L'\0' != *pwsz)
|
|
{
|
|
WCHAR wc;
|
|
|
|
wc = *pwsz++;
|
|
if (L'\\' == wc && L'n' == *pwsz)
|
|
{
|
|
if (0 != cNew)
|
|
{
|
|
cNew++;
|
|
}
|
|
wc = L'\0';
|
|
pwsz++;
|
|
while (L'\\' == pwsz[0] && L'n' == pwsz[1])
|
|
{
|
|
pwsz += 2;
|
|
}
|
|
}
|
|
*pwszDst++ = wc;
|
|
}
|
|
*pwszDst++ = L'\0';
|
|
*pwszDst = L'\0';
|
|
|
|
|
|
apwsz = (WCHAR const **) LocalAlloc(LMEM_FIXED, (cOld + cNew) * sizeof(apwsz[0]));
|
|
if (NULL == apwsz)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
cCombined = 0;
|
|
if (cOld)
|
|
{
|
|
for (pwsz = (WCHAR *) pbValueOld; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
|
|
{
|
|
if (REGOP_SET == RegOp || !IsInList(pwsz, pwszzNew))
|
|
{
|
|
apwsz[cCombined++] = pwsz;
|
|
}
|
|
}
|
|
}
|
|
if (cNew)
|
|
{
|
|
for (pwsz = pwszzNew; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
|
|
{
|
|
if (REGOP_NONE == RegOp || !IsInList(pwsz, (WCHAR *) pbValueOld))
|
|
{
|
|
apwsz[cCombined++] = pwsz;
|
|
}
|
|
}
|
|
}
|
|
CSASSERT(cOld + cNew >= cCombined);
|
|
|
|
cwc = 1;
|
|
for (i = 0; i < cCombined; i++)
|
|
{
|
|
cwc += wcslen(apwsz[i]) + 1;
|
|
}
|
|
if (0 == cCombined)
|
|
{
|
|
cwc++;
|
|
}
|
|
|
|
*pcbValue = cwc * sizeof(WCHAR);
|
|
*ppbValue = (BYTE *) LocalAlloc(LMEM_FIXED, *pcbValue);
|
|
if (NULL == *ppbValue)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
pwszDst = (WCHAR *) *ppbValue;
|
|
for (i = 0; i < cCombined; i++)
|
|
{
|
|
wcscpy(pwszDst, apwsz[i]);
|
|
pwszDst += wcslen(pwszDst) + 1;
|
|
}
|
|
if (0 == cCombined)
|
|
{
|
|
*pwszDst++ = L'\0';
|
|
}
|
|
*pwszDst = L'\0';
|
|
|
|
CSASSERT(SAFE_SUBTRACT_POINTERS(pwszDst, (WCHAR *) *ppbValue) + 1 == cwc);
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != apwsz)
|
|
{
|
|
LocalFree(apwsz);
|
|
}
|
|
if (NULL != pwszzNew)
|
|
{
|
|
LocalFree(pwszzNew);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
ParseRegValue(
|
|
IN WCHAR const *pwszRegName,
|
|
IN DWORD cbValueOld,
|
|
IN BYTE const *pbValueOld,
|
|
IN OUT DWORD *pdwType,
|
|
IN WCHAR const *pwszRegValue,
|
|
OUT DWORD *pcbValue,
|
|
OUT BYTE **ppbValue)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR const *pwsz;
|
|
DWORD cb;
|
|
DWORD dw;
|
|
DWORD dwValue;
|
|
DWORD dwType;
|
|
DWORD cNewLine;
|
|
DWORD RegOp;
|
|
BOOL fNumber;
|
|
|
|
// A leading '-' or '+' character is used as a REGOP_* operator.
|
|
// To include it as part of the string, add leading whitespace,
|
|
// or separate the operator from the string by one or more spaces.
|
|
//
|
|
// "-foo" -- remove "foo" from registry value
|
|
// "- foo" -- remove "foo" from registry value
|
|
// " -foo" -- overwrite registry value with "-foo"
|
|
// "--foo" -- remove "-foo" from registry value
|
|
// "- -foo" -- remove "-foo" from registry value
|
|
|
|
dwValue = 0;
|
|
cNewLine = 0;
|
|
if (REG_DWORD == *pdwType)
|
|
{
|
|
CSASSERT(sizeof(dw) == cbValueOld);
|
|
dwValue = *(DWORD *) pbValueOld;
|
|
}
|
|
if (L'+' == *pwszRegValue)
|
|
{
|
|
RegOp = REGOP_SET; // set bits in existing value
|
|
pwszRegValue++;
|
|
}
|
|
else if (myIsMinusSign(*pwszRegValue))
|
|
{
|
|
RegOp = REGOP_CLEAR; // clear bits in existing value
|
|
pwszRegValue++;
|
|
}
|
|
else
|
|
{
|
|
RegOp = REGOP_NONE; // overwrite value
|
|
dwValue = 0;
|
|
}
|
|
while (L' ' == *pwszRegValue || L'\t' == *pwszRegValue)
|
|
{
|
|
pwszRegValue++;
|
|
}
|
|
|
|
cb = sizeof(dwValue); // assume REG_DWORD
|
|
dwType = REG_DWORD;
|
|
|
|
fNumber = FALSE;
|
|
|
|
if (L'+' == *pwszRegValue ||
|
|
myIsMinusSign(*pwszRegValue) ||
|
|
iswdigit(*pwszRegValue))
|
|
{
|
|
hr = myGetSignedLong(pwszRegValue, (LONG *) &dw);
|
|
if (S_OK == hr)
|
|
{
|
|
fNumber = TRUE;
|
|
switch (RegOp)
|
|
{
|
|
default:
|
|
case REGOP_NONE:
|
|
dwValue = dw;
|
|
break;
|
|
|
|
case REGOP_SET:
|
|
dwValue |= dw;
|
|
break;
|
|
|
|
case REGOP_CLEAR:
|
|
dwValue &= ~dw;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!fNumber)
|
|
{
|
|
hr = cuMapRegFlags(
|
|
pwszRegName,
|
|
pwszRegValue,
|
|
REGOP_CLEAR == RegOp,
|
|
&dwValue);
|
|
if (S_OK != hr)
|
|
{
|
|
pwsz = pwszRegValue;
|
|
while (TRUE)
|
|
{
|
|
pwsz = wcschr(pwsz, L'\\');
|
|
if (NULL == pwsz)
|
|
{
|
|
break;
|
|
}
|
|
if (L'n' == *++pwsz)
|
|
{
|
|
cNewLine++;
|
|
}
|
|
}
|
|
if (REGOP_SET == RegOp || 0 != cNewLine)
|
|
{
|
|
dwType = REG_MULTI_SZ;
|
|
}
|
|
else
|
|
{
|
|
dwType = REG_SZ;
|
|
}
|
|
cb = (wcslen(pwszRegValue) + 1) * sizeof(WCHAR);
|
|
}
|
|
}
|
|
|
|
if (REG_NONE != *pdwType && dwType != *pdwType)
|
|
{
|
|
if (REG_SZ == dwType && REG_MULTI_SZ == *pdwType)
|
|
{
|
|
dwType = REG_MULTI_SZ;
|
|
if (0 == cNewLine)
|
|
{
|
|
cb += sizeof(WCHAR);
|
|
}
|
|
}
|
|
else if (REG_MULTI_SZ != dwType || REG_SZ != *pdwType)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
_JumpError(hr, error, "bad registry value type");
|
|
}
|
|
}
|
|
|
|
if (REG_MULTI_SZ == dwType)
|
|
{
|
|
hr = CombineMultiSzRegValues(
|
|
RegOp,
|
|
pwszRegValue,
|
|
*pdwType,
|
|
cbValueOld,
|
|
pbValueOld,
|
|
ppbValue,
|
|
pcbValue);
|
|
_JumpIfError(hr, error, "CombineMultiSzRegValues");
|
|
}
|
|
else
|
|
{
|
|
*ppbValue = (BYTE *) LocalAlloc(LMEM_FIXED, cb);
|
|
if (NULL == *ppbValue)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
*pcbValue = cb;
|
|
|
|
if (REG_DWORD == dwType)
|
|
{
|
|
CSASSERT(sizeof(dwValue) == cb);
|
|
CopyMemory(*ppbValue, &dwValue, sizeof(dwValue));
|
|
}
|
|
else
|
|
{
|
|
if (REGOP_NONE != RegOp)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
_JumpErrorStr(hr, error, "bad registry value string", pwszRegValue);
|
|
}
|
|
CSASSERT((wcslen(pwszRegValue) + 1) * sizeof(WCHAR) <= cb);
|
|
wcscpy((WCHAR *) *ppbValue, pwszRegValue);
|
|
}
|
|
}
|
|
*pdwType = dwType;
|
|
if (g_fVerbose)
|
|
{
|
|
DumpHex(0, *ppbValue, *pcbValue);
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
WriteRegValue(
|
|
IN HKEY hkey,
|
|
IN WCHAR const *pwszName,
|
|
IN DWORD dwType,
|
|
IN DWORD cbValue,
|
|
IN BYTE const *pbValue)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = RegSetValueEx(hkey, pwszName, 0, dwType, pbValue, cbValue);
|
|
_JumpIfErrorStr(hr, error, "RegSetValueEx", pwszName);
|
|
|
|
error:
|
|
return(myHError(hr));
|
|
}
|
|
|
|
|
|
HRESULT
|
|
ReadRegValue(
|
|
IN HKEY hkey,
|
|
IN WCHAR const *pwszName,
|
|
OUT DWORD *pdwType,
|
|
OUT DWORD *pcbValue,
|
|
OUT BYTE **ppbValue)
|
|
{
|
|
HRESULT hr;
|
|
DWORD cb;
|
|
|
|
*ppbValue = NULL;
|
|
cb = 0;
|
|
hr = RegQueryValueEx(
|
|
hkey,
|
|
pwszName,
|
|
NULL,
|
|
pdwType,
|
|
NULL,
|
|
&cb);
|
|
_JumpIfErrorStr2(hr, error, "RegQueryValueEx", pwszName, ERROR_FILE_NOT_FOUND);
|
|
|
|
// add two WCHAR L'\0's after the registry value, in case of a poorly
|
|
// formed REG_MULTI_SZ. Add another to handle possible odd sizes.
|
|
|
|
*ppbValue = (BYTE *) LocalAlloc(LMEM_FIXED, cb + cbVALUEZEROPAD);
|
|
if (NULL == *ppbValue)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
hr = RegQueryValueEx(
|
|
hkey,
|
|
pwszName,
|
|
NULL,
|
|
pdwType,
|
|
*ppbValue,
|
|
&cb);
|
|
_JumpIfErrorStr(hr, error, "RegQueryValueEx", pwszName);
|
|
|
|
if (REG_SZ == *pdwType || REG_MULTI_SZ == *pdwType)
|
|
{
|
|
WCHAR *pwszStart;
|
|
WCHAR *pwsz;
|
|
DWORD cbT;
|
|
|
|
CSASSERT(0 == ((sizeof(WCHAR) - 1) & cb));
|
|
pwszStart = (WCHAR *) *ppbValue;
|
|
cbT = ~(sizeof(WCHAR) - 1) & cb;
|
|
pwsz = &pwszStart[cbT / sizeof(WCHAR)];
|
|
|
|
ZeroMemory(pwsz, cbVALUEZEROPAD);
|
|
pwsz = pwszStart;
|
|
while (L'\0' != pwsz[0] || L'\0' != pwsz[1])
|
|
{
|
|
pwsz++;
|
|
}
|
|
cbT = (SAFE_SUBTRACT_POINTERS(pwsz, pwszStart) +
|
|
(REG_SZ == *pdwType? 1 : 2)) * sizeof(WCHAR);
|
|
CSASSERT(cb == cbT);
|
|
cb = cbT;
|
|
}
|
|
*pcbValue = cb;
|
|
|
|
error:
|
|
if (S_OK != hr)
|
|
{
|
|
if (NULL != *ppbValue)
|
|
{
|
|
LocalFree(*ppbValue);
|
|
*ppbValue = NULL;
|
|
}
|
|
}
|
|
return(myHError(hr));
|
|
}
|
|
|
|
|
|
#define cwcVALUENAME 25 // Nominal registry value name length
|
|
|
|
HRESULT
|
|
DumpRegKeysAndValues(
|
|
IN HKEY hkey,
|
|
OPTIONAL WCHAR *pwszValueNamePrefix)
|
|
{
|
|
HRESULT hr;
|
|
DWORD i;
|
|
DWORD j;
|
|
DWORD cwc;
|
|
DWORD dwType;
|
|
WCHAR awc[MAX_PATH + 1];
|
|
DWORD cb;
|
|
BYTE *pb;
|
|
BYTE ab[8 + cbVALUEZEROPAD]; // enough for small registry values
|
|
DWORD cbAlloc;
|
|
BYTE *pbAlloc = ab;
|
|
BOOL fLongValue;
|
|
WCHAR *pwszPrefix = NULL;
|
|
DWORD cwcPrefix;
|
|
|
|
if (NULL != pwszValueNamePrefix)
|
|
{
|
|
cwcPrefix = wcslen(pwszValueNamePrefix);
|
|
pwszPrefix = (WCHAR *) LocalAlloc(
|
|
LMEM_FIXED,
|
|
(cwcPrefix + 1) * sizeof(WCHAR));
|
|
if (NULL == pwszPrefix)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
}
|
|
for (i = j = 0; ; i++)
|
|
{
|
|
cwc = ARRAYSIZE(awc);
|
|
hr = RegEnumKey(hkey, i, awc, cwc);
|
|
if (S_OK != hr)
|
|
{
|
|
if ((HRESULT) ERROR_NO_MORE_ITEMS != hr)
|
|
{
|
|
_PrintError(hr, "RegEnumKey");
|
|
}
|
|
break;
|
|
}
|
|
if (NULL != pwszPrefix)
|
|
{
|
|
wcsncpy(pwszPrefix, awc, cwcPrefix);
|
|
pwszPrefix[cwcPrefix] = L'\0';
|
|
if (0 != mylstrcmpiL(pwszValueNamePrefix, pwszPrefix))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (0 == j)
|
|
{
|
|
wprintf(wszNewLine);
|
|
wprintf(myLoadResourceString(IDS_KEYS)); // "Keys:"
|
|
wprintf(wszNewLine);
|
|
}
|
|
else if (0 == (j % 5))
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
wprintf(L" %ws\n", awc);
|
|
j++;
|
|
}
|
|
|
|
cbAlloc = sizeof(ab) - cbVALUEZEROPAD;
|
|
fLongValue = FALSE;
|
|
for (i = j = 0; ; i++)
|
|
{
|
|
DWORD cwcSep;
|
|
|
|
cwc = ARRAYSIZE(awc);
|
|
cb = cbAlloc;
|
|
pb = pbAlloc;
|
|
hr = RegEnumValue(hkey, i, awc, &cwc, NULL, &dwType, pb, &cb);
|
|
if (S_OK != hr)
|
|
{
|
|
if ((HRESULT) ERROR_MORE_DATA != hr)
|
|
{
|
|
if ((HRESULT) ERROR_NO_MORE_ITEMS != hr)
|
|
{
|
|
_PrintError(hr, "RegEnumValue");
|
|
}
|
|
break;
|
|
}
|
|
CSASSERT(NULL != pb);
|
|
pb = (BYTE *) LocalAlloc(LMEM_FIXED, cb + cbVALUEZEROPAD);
|
|
if (NULL == pb)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
if (ab != pbAlloc)
|
|
{
|
|
LocalFree(pbAlloc);
|
|
}
|
|
pbAlloc = pb;
|
|
cbAlloc = cb;
|
|
cwc = ARRAYSIZE(awc);
|
|
hr = RegEnumValue(hkey, i, awc, &cwc, NULL, &dwType, pb, &cb);
|
|
_JumpIfError(hr, error, "RegEnumValue");
|
|
}
|
|
if (NULL != pb)
|
|
{
|
|
ZeroMemory(&pb[cb], cbVALUEZEROPAD);
|
|
}
|
|
if (NULL != pwszPrefix)
|
|
{
|
|
wcsncpy(pwszPrefix, awc, cwcPrefix);
|
|
pwszPrefix[cwcPrefix] = L'\0';
|
|
if (0 != mylstrcmpiL(pwszValueNamePrefix, pwszPrefix))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
if (0 == j)
|
|
{
|
|
wprintf(wszNewLine);
|
|
wprintf(myLoadResourceString(IDS_VALUES)); // "Values:"
|
|
wprintf(wszNewLine);
|
|
}
|
|
else if (fLongValue || 0 == (j % 5))
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
cwcSep = wcslen(awc);
|
|
cwcSep = cwcVALUENAME < cwcSep? 0 : cwcVALUENAME - cwcSep;
|
|
PrintRegValue(awc, awc, dwType, TRUE, TRUE, cwcSep, cb, pb, &fLongValue);
|
|
j++;
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pbAlloc && ab != pbAlloc)
|
|
{
|
|
LocalFree(pbAlloc);
|
|
}
|
|
if (NULL != pwszPrefix)
|
|
{
|
|
LocalFree(pwszPrefix);
|
|
}
|
|
return(myHError(hr));
|
|
}
|
|
|
|
|
|
WCHAR const *
|
|
wszHKEY(
|
|
IN WCHAR const *pwszPath)
|
|
{
|
|
WCHAR const *pwszKey = L"HKEY_LOCAL_MACHINE\\";
|
|
|
|
if (g_fUserRegistry && 0 == _wcsnicmp(
|
|
pwszPath,
|
|
wszCERTTYPECACHE,
|
|
WSZARRAYSIZE(wszCERTTYPECACHE)))
|
|
{
|
|
pwszKey = L"HKEY_CURRENT_USER\\";
|
|
}
|
|
return(pwszKey);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
verbGetReg(
|
|
IN WCHAR const *pwszOption,
|
|
OPTIONAL IN WCHAR const *pwszRegName,
|
|
IN WCHAR const *pwszArg2,
|
|
IN WCHAR const *pwszArg3,
|
|
IN WCHAR const *pwszArg4)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszPath = NULL;
|
|
WCHAR *pwszName = NULL;
|
|
WCHAR *pwszValueName = NULL;
|
|
WCHAR *pwszSubKeyName = NULL;
|
|
DWORD dwType;
|
|
DWORD cbValue;
|
|
BYTE *pbValue = NULL;
|
|
HKEY hkey = NULL;
|
|
HKEY hkeySub = NULL;
|
|
HKEY hkeyT;
|
|
|
|
if (NULL == pwszRegName)
|
|
{
|
|
pwszRegName = L"";
|
|
}
|
|
hr = myRegOpenRelativeKey(
|
|
g_pwszConfig,
|
|
pwszRegName,
|
|
RORKF_FULLPATH | (g_fUserRegistry? RORKF_USERKEY : 0),
|
|
&pwszPath,
|
|
&pwszName,
|
|
&hkey);
|
|
_JumpIfErrorStr(hr, error, "myRegOpenRelativeKey", pwszRegName);
|
|
|
|
hr = OpenSubKey(
|
|
hkey,
|
|
pwszName,
|
|
FALSE,
|
|
&hkeySub,
|
|
&pwszSubKeyName,
|
|
&pwszValueName);
|
|
_JumpIfError(hr, error, "OpenSubKey");
|
|
|
|
hkeyT = NULL != hkeySub? hkeySub : hkey;
|
|
wprintf(
|
|
L"%ws%ws%ws%ws:\n",
|
|
wszHKEY(pwszPath),
|
|
L'\0' != *pwszPath? pwszPath : wszREGKEYCONFIG,
|
|
L'\0' != *pwszSubKeyName? L"\\" : L"",
|
|
pwszSubKeyName);
|
|
|
|
if (NULL == pwszValueName ||
|
|
L'\0' == *pwszValueName ||
|
|
NULL != wcschr(pwszValueName, L'*'))
|
|
{
|
|
if (NULL != pwszValueName)
|
|
{
|
|
WCHAR *pwsz = wcschr(pwszValueName, L'*');
|
|
|
|
if (NULL != pwsz)
|
|
{
|
|
*pwsz = L'\0';
|
|
}
|
|
}
|
|
|
|
hr = DumpRegKeysAndValues(hkeyT, pwszValueName);
|
|
_JumpIfError(hr, error, "DumpRegKeysAndValues");
|
|
}
|
|
else
|
|
{
|
|
hr = ReadRegValue(hkeyT, pwszValueName, &dwType, &cbValue, &pbValue);
|
|
_JumpIfErrorStr(hr, error, "ReadRegValue", pwszValueName);
|
|
|
|
wprintf(wszNewLine);
|
|
PrintRegValue(
|
|
pwszValueName,
|
|
pwszValueName,
|
|
dwType,
|
|
TRUE,
|
|
TRUE,
|
|
0,
|
|
cbValue,
|
|
pbValue,
|
|
NULL);
|
|
}
|
|
|
|
error:
|
|
if (NULL != hkey)
|
|
{
|
|
RegCloseKey(hkey);
|
|
}
|
|
if (NULL != hkeySub)
|
|
{
|
|
RegCloseKey(hkeySub);
|
|
}
|
|
if (NULL != pwszPath)
|
|
{
|
|
LocalFree(pwszPath);
|
|
}
|
|
if (NULL != pwszName)
|
|
{
|
|
LocalFree(pwszName);
|
|
}
|
|
if (NULL != pwszSubKeyName)
|
|
{
|
|
LocalFree(pwszSubKeyName);
|
|
}
|
|
if (NULL != pwszValueName)
|
|
{
|
|
LocalFree(pwszValueName);
|
|
}
|
|
if (NULL != pbValue)
|
|
{
|
|
LocalFree(pbValue);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
verbSetReg(
|
|
IN WCHAR const *pwszOption,
|
|
IN WCHAR const *pwszRegName,
|
|
IN WCHAR const *pwszRegValue,
|
|
IN WCHAR const *pwszArg3,
|
|
IN WCHAR const *pwszArg4)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszPath = NULL;
|
|
WCHAR *pwszName = NULL;
|
|
WCHAR *pwszValueName = NULL;
|
|
WCHAR *pwszSubKeyName = NULL;
|
|
DWORD dwType;
|
|
DWORD cbValue;
|
|
DWORD cbValueArg;
|
|
BYTE *pbValueOld = NULL;
|
|
BYTE *pbValueNew = NULL;
|
|
BYTE *pbValueArg = NULL;
|
|
HKEY hkey = NULL;
|
|
HKEY hkeySub = NULL;
|
|
HKEY hkeyT;
|
|
DWORD dw;
|
|
|
|
hr = myRegOpenRelativeKey(
|
|
g_pwszConfig,
|
|
pwszRegName,
|
|
RORKF_FULLPATH |
|
|
RORKF_CREATESUBKEYS |
|
|
(g_fUserRegistry? RORKF_USERKEY : 0) |
|
|
(g_fForce? RORKF_CREATEKEY : 0),
|
|
&pwszPath,
|
|
&pwszName,
|
|
&hkey);
|
|
_JumpIfErrorStr(hr, error, "myRegOpenRelativeKey", pwszRegName);
|
|
|
|
hr = OpenSubKey(
|
|
hkey,
|
|
pwszName,
|
|
g_fForce,
|
|
&hkeySub,
|
|
&pwszSubKeyName,
|
|
&pwszValueName);
|
|
_JumpIfError(hr, error, "OpenSubKey");
|
|
|
|
hkeyT = NULL != hkeySub? hkeySub : hkey;
|
|
wprintf(
|
|
L"%ws%ws%ws%ws:\n",
|
|
g_fVerbose? wszHKEY(pwszPath) : L"",
|
|
L'\0' != *pwszPath? pwszPath : wszREGKEYCONFIG,
|
|
L'\0' != *pwszSubKeyName? L"\\" : L"",
|
|
pwszSubKeyName);
|
|
|
|
hr = ReadRegValue(hkeyT, pwszValueName, &dwType, &cbValue, &pbValueOld);
|
|
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
|
|
{
|
|
_JumpIfErrorStr(hr, error, "ReadRegValue", pwszValueName);
|
|
}
|
|
|
|
if (NULL != pbValueOld)
|
|
{
|
|
wprintf(wszNewLine);
|
|
wprintf(myLoadResourceString(IDS_OLD_REG_VALUE)); // "Old Value:"
|
|
wprintf(wszNewLine);
|
|
PrintRegValue(
|
|
pwszValueName,
|
|
pwszValueName,
|
|
dwType,
|
|
TRUE,
|
|
TRUE,
|
|
0,
|
|
cbValue,
|
|
pbValueOld,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
dwType = REG_NONE;
|
|
}
|
|
|
|
hr = ParseRegValue(
|
|
pwszRegName,
|
|
cbValue,
|
|
pbValueOld,
|
|
&dwType,
|
|
pwszRegValue,
|
|
&cbValueArg,
|
|
&pbValueArg);
|
|
_JumpIfErrorStr(hr, error, "ParseRegValue", pwszRegValue);
|
|
|
|
hr = WriteRegValue(hkeyT, pwszValueName, dwType, cbValueArg, pbValueArg);
|
|
_JumpIfErrorStr(hr, error, "WriteRegValue", pwszValueName);
|
|
|
|
hr = ReadRegValue(hkeyT, pwszValueName, &dwType, &cbValue, &pbValueNew);
|
|
_JumpIfErrorStr(hr, error, "ReadRegValue", pwszValueName);
|
|
|
|
wprintf(wszNewLine);
|
|
wprintf(myLoadResourceString(IDS_NEW_REG_VALUE)); // "New Value:"
|
|
wprintf(wszNewLine);
|
|
PrintRegValue(
|
|
pwszValueName,
|
|
pwszValueName,
|
|
dwType,
|
|
TRUE,
|
|
TRUE,
|
|
0,
|
|
cbValue,
|
|
pbValueNew,
|
|
NULL);
|
|
|
|
error:
|
|
if (NULL != hkey)
|
|
{
|
|
RegCloseKey(hkey);
|
|
}
|
|
if (NULL != hkeySub)
|
|
{
|
|
RegCloseKey(hkeySub);
|
|
}
|
|
if (NULL != pwszPath)
|
|
{
|
|
LocalFree(pwszPath);
|
|
}
|
|
if (NULL != pwszName)
|
|
{
|
|
LocalFree(pwszName);
|
|
}
|
|
if (NULL != pwszSubKeyName)
|
|
{
|
|
LocalFree(pwszSubKeyName);
|
|
}
|
|
if (NULL != pwszValueName)
|
|
{
|
|
LocalFree(pwszValueName);
|
|
}
|
|
if (NULL != pbValueOld)
|
|
{
|
|
LocalFree(pbValueOld);
|
|
}
|
|
if (NULL != pbValueArg)
|
|
{
|
|
LocalFree(pbValueArg);
|
|
}
|
|
if (NULL != pbValueNew)
|
|
{
|
|
LocalFree(pbValueNew);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
verbDelReg(
|
|
IN WCHAR const *pwszOption,
|
|
IN WCHAR const *pwszRegName,
|
|
IN WCHAR const *pwszArg2,
|
|
IN WCHAR const *pwszArg3,
|
|
IN WCHAR const *pwszArg4)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszPath = NULL;
|
|
WCHAR *pwszName = NULL;
|
|
WCHAR *pwszValueName = NULL;
|
|
WCHAR *pwszSubKeyName = NULL;
|
|
DWORD dwType;
|
|
DWORD cbValue;
|
|
BYTE *pbValueOld = NULL;
|
|
HKEY hkey = NULL;
|
|
HKEY hkeySub = NULL;
|
|
HKEY hkeyT;
|
|
DWORD dw;
|
|
|
|
hr = myRegOpenRelativeKey(
|
|
g_pwszConfig,
|
|
pwszRegName,
|
|
RORKF_FULLPATH |
|
|
RORKF_CREATESUBKEYS |
|
|
(g_fUserRegistry? RORKF_USERKEY : 0),
|
|
&pwszPath,
|
|
&pwszName,
|
|
&hkey);
|
|
_JumpIfErrorStr(hr, error, "myRegOpenRelativeKey", pwszRegName);
|
|
|
|
hr = OpenSubKey(
|
|
hkey,
|
|
pwszName,
|
|
FALSE,
|
|
&hkeySub,
|
|
&pwszSubKeyName,
|
|
&pwszValueName);
|
|
_JumpIfError(hr, error, "OpenSubKey");
|
|
|
|
hkeyT = NULL != hkeySub? hkeySub : hkey;
|
|
wprintf(
|
|
L"%ws%ws%ws%ws:\n",
|
|
wszHKEY(pwszPath),
|
|
L'\0' != *pwszPath? pwszPath : wszREGKEYCONFIG,
|
|
L'\0' != *pwszSubKeyName? L"\\" : L"",
|
|
pwszSubKeyName);
|
|
|
|
hr = ReadRegValue(hkeyT, pwszValueName, &dwType, &cbValue, &pbValueOld);
|
|
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
|
|
{
|
|
_JumpIfErrorStr(hr, error, "ReadRegValue", pwszValueName);
|
|
}
|
|
|
|
if (NULL != pbValueOld)
|
|
{
|
|
wprintf(wszNewLine);
|
|
wprintf(myLoadResourceString(IDS_OLD_REG_VALUE)); // "Old Value:"
|
|
wprintf(wszNewLine);
|
|
PrintRegValue(
|
|
pwszValueName,
|
|
pwszValueName,
|
|
dwType,
|
|
TRUE,
|
|
TRUE,
|
|
0,
|
|
cbValue,
|
|
pbValueOld,
|
|
NULL);
|
|
}
|
|
if (NULL == pwszValueName || L'\0' == *pwszValueName)
|
|
{
|
|
if (!g_fForce)
|
|
{
|
|
hr = E_ACCESSDENIED;
|
|
_JumpErrorStr(hr, error, "use -f", pwszSubKeyName);
|
|
}
|
|
if (NULL != hkeySub)
|
|
{
|
|
RegCloseKey(hkeySub);
|
|
hkeySub = NULL;
|
|
}
|
|
hr = RegDeleteKey(hkey, pwszSubKeyName);
|
|
if (S_OK != hr)
|
|
{
|
|
hr = myHError(hr);
|
|
_JumpErrorStr(hr, error, "RegDeleteKey", pwszSubKeyName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = RegDeleteValue(hkeyT, pwszValueName);
|
|
if (S_OK != hr)
|
|
{
|
|
hr = myHError(hr);
|
|
_JumpErrorStr(hr, error, "RegDeleteValue", pwszValueName);
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != hkey)
|
|
{
|
|
RegCloseKey(hkey);
|
|
}
|
|
if (NULL != hkeySub)
|
|
{
|
|
RegCloseKey(hkeySub);
|
|
}
|
|
if (NULL != pwszPath)
|
|
{
|
|
LocalFree(pwszPath);
|
|
}
|
|
if (NULL != pwszName)
|
|
{
|
|
LocalFree(pwszName);
|
|
}
|
|
if (NULL != pwszSubKeyName)
|
|
{
|
|
LocalFree(pwszSubKeyName);
|
|
}
|
|
if (NULL != pwszValueName)
|
|
{
|
|
LocalFree(pwszValueName);
|
|
}
|
|
if (NULL != pbValueOld)
|
|
{
|
|
LocalFree(pbValueOld);
|
|
}
|
|
return(hr);
|
|
}
|