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

//+-------------------------------------------------------------------------
//
// 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);
}