windows-nt/Source/XPSP1/NT/net/rras/netsh/if/repair.c
2020-09-26 16:20:57 +08:00

895 lines
26 KiB
C

#include "precomp.h"
EXTERN_C
VOID
WINAPI
NetCfgDiagRepairRegistryBindings (
IN FILE* pLogFile);
#define REG_DELETE 100
typedef enum {
COND_NONE,
COND_VALUE,
COND_ADD,
COND_DELETE,
} CONDITIONAL;
typedef struct _TR_VALUE_DESCRIPTOR {
PCSTR SubKeyName;
PCSTR ValueName;
DWORD RegType;
union {
ULONG_PTR __asignany;
ULONG DataValue;
CONST BYTE *DataPointer;
};
DWORD DataSize;
//
// If Conditional is not COND_NONE, then the value is conditionally
// dependent on the presence of a key of the same name under the
// ConditionalParentKeyName. If the key is present, the values
// below are used. If not the values above are used.
//
// If Conditional is COND_ADD, then the value is added/set if
// if the conditional key is present, and deleted if it is not present.
//
// If Conditional is COND_DELETE, then the value is added/set if
// the conditional key is NOT present, and deleted if it is present.
//
CONDITIONAL Conditional;
union {
ULONG_PTR __asignany2;
ULONG ConditionalDataValue;
CONST BYTE *ConditionalDataPointer;
};
} TR_VALUE_DESCRIPTOR;
#define TRV_DW(_subkey, _valuename, _data) \
{ _subkey, _valuename, REG_DWORD, (ULONG_PTR)_data, sizeof(DWORD) },
#define TRV_DW_CV(_subkey, _valuename, _datafalse, _datatrue) \
{ _subkey, _valuename, REG_DWORD, (ULONG_PTR)_datafalse, sizeof(DWORD), \
COND_VALUE, (ULONG_PTR)_datatrue },
#define TRV_DW_CA(_subkey, _valuename, _data) \
{ _subkey, _valuename, REG_DWORD, 0, sizeof(DWORD), COND_ADD, \
(ULONG_PTR)_data },
#define TRV_DW_CD(_subkey, _valuename, _data) \
{ _subkey, _valuename, REG_DWORD, (ULONG_PTR)_data, sizeof(DWORD), \
COND_DELETE, 0 },
#define TRV_ESZ(_subkey, _valuename, _esz) \
{ _subkey, _valuename, REG_EXPAND_SZ, (ULONG_PTR)_esz, sizeof(_esz) },
#define TRV_MSZ(_subkey, _valuename, _msz) \
{ _subkey, _valuename, REG_MULTI_SZ, (ULONG_PTR)_msz, sizeof(_msz) },
#define TRV_MSZ_CA(_subkey, _valuename, _msz) \
{ _subkey, _valuename, REG_MULTI_SZ, 0, sizeof(_msz), COND_ADD, \
(ULONG_PTR)_msz },
#define TRV_SZ(_subkey, _valuename, _sz) \
{ _subkey, _valuename, REG_SZ, (ULONG_PTR)_sz, sizeof(_sz) },
#define TRV_SZ_CA(_subkey, _valuename, _sz) \
{ _subkey, _valuename, REG_SZ, 0, sizeof(_sz), COND_ADD, \
(ULONG_PTR)_sz },
#define TRV_DEL(_subkey, _valuename) \
{ _subkey, _valuename, REG_DELETE, 0, 0 },
#define TRV_END() \
{ NULL, NULL, REG_NONE, 0, 0 }
typedef struct _TR_KEY_DESCRIPTOR {
//
// RootKey is one of the HKEY_* values. (e.g. HKEY_LOCAL_MACHINE)
//
HKEY RootKey;
//
// ParentKey is the name of a subkey (under RootKey) where either the
// values reside or subkeys are to be enumerated and values found under
// each subkey.
//
PCSTR ParentKeyName;
//
// TRUE if all subkeys of Parentkey are to be enumerated and values
// found under each of those subkeys.
//
BOOL EnumKey;
//
// Pointer to an array of value descriptors. The array is terminated
// with an entry of all zeros.
//
CONST TR_VALUE_DESCRIPTOR *Value;
//
// ConditionalParentKeyName is the name of a subkey (under RootKey)
// where a value/subkey may reside, whose presence or lack thereof
// may affect the values set under subkeys of ParentKeyName.
//
PCSTR ConditionalParentKeyName;
} TR_KEY_DESCRIPTOR;
#define DHCP_OPT_TCPIP(_name) \
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\"_name"\0"
#define DHCP_OPT_TCPIP_INTERFACE(_name) \
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\?\\"_name"\0"
#define DHCP_OPT_LEGACY_TCPIP_INTERFACE(_name) \
"SYSTEM\\CurrentControlSet\\Services\\?\\Parameters\\Tcpip\\"_name"\0"
#define DHCP_OPT_NETBT(_name) \
"SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters\\"_name
#define DHCP_OPT_NETBT_INTERFACE(_name) \
"SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters\\Interfaces\\Tcpip_?\\"_name"\0"
#define DHCP_OPT_NETBT_ADAPTER(_name) \
"SYSTEM\\CurrentControlSet\\Services\\NetBT\\Adapters\\?\\"_name"\0"
CONST TR_VALUE_DESCRIPTOR DhcpParameterOptions_Values [] =
{
TRV_DW ("1", "KeyType", 7)
TRV_MSZ("1", "RegLocation", DHCP_OPT_TCPIP_INTERFACE ("DhcpSubnetMaskOpt")
DHCP_OPT_LEGACY_TCPIP_INTERFACE("DhcpSubnetMaskOpt"))
TRV_DW ("3", "KeyType", 7)
TRV_MSZ("3", "RegLocation", DHCP_OPT_TCPIP_INTERFACE ("DhcpDefaultGateway")
DHCP_OPT_LEGACY_TCPIP_INTERFACE("DhcpDefaultGateway"))
TRV_DW ("6", "KeyType", 1)
TRV_MSZ("6", "RegLocation", DHCP_OPT_TCPIP_INTERFACE("DhcpNameServer")
DHCP_OPT_TCPIP ("DhcpNameServer"))
TRV_DW ("15", "KeyType", 1)
TRV_MSZ("15", "RegLocation", DHCP_OPT_TCPIP_INTERFACE("DhcpDomain")
DHCP_OPT_TCPIP ("DhcpDomain"))
TRV_DW ("44", "KeyType", 1)
TRV_MSZ("44", "RegLocation", DHCP_OPT_NETBT_INTERFACE("DhcpNameServerList")
DHCP_OPT_NETBT_ADAPTER ("DhcpNameServer"))
TRV_DW ("46", "KeyType", 4)
TRV_SZ ("46", "RegLocation", DHCP_OPT_NETBT("DhcpNodeType"))
TRV_DW ("47", "KeyType", 1)
TRV_SZ ("47", "RegLocation", DHCP_OPT_NETBT("DhcpScopeID"))
TRV_DW ("DhcpNetbiosOptions", "KeyType", 4)
TRV_DW ("DhcpNetbiosOptions", "OptionId", 1)
TRV_DW ("DhcpNetbiosOptions", "VendorType", 1)
TRV_MSZ("DhcpNetbiosOptions", "RegLocation", DHCP_OPT_NETBT_INTERFACE("DhcpNetbiosOptions"))
TRV_END()
};
CONST TR_KEY_DESCRIPTOR DhcpParameterOptions =
{
HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\Dhcp\\Parameters\\Options",
FALSE,
DhcpParameterOptions_Values
};
CONST TR_VALUE_DESCRIPTOR DhcpParameter_Values [] =
{
TRV_ESZ(NULL, "ServiceDll", "%SystemRoot%\\System32\\dhcpcsvc.dll")
TRV_END()
};
CONST TR_KEY_DESCRIPTOR DhcpParameters =
{
HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\Dhcp\\Parameters",
FALSE,
DhcpParameter_Values
};
CONST TR_VALUE_DESCRIPTOR DnscacheParameter_Values [] =
{
TRV_ESZ(NULL, "ServiceDll", "%SystemRoot%\\System32\\dnsrslvr.dll")
TRV_DEL(NULL, "AdapterTimeoutCacheTime")
TRV_DEL(NULL, "CacheHashTableBucketSize")
TRV_DEL(NULL, "CacheHashTableSize")
TRV_DEL(NULL, "DefaultRegistrationRefreshInterval")
TRV_DEL(NULL, "MaxCacheEntryTtlLimit")
TRV_DEL(NULL, "MaxSoaCacheEntryTtlLimit")
TRV_DEL(NULL, "NegativeCacheTime")
TRV_DEL(NULL, "NegativeSoaCacheTime")
TRV_DEL(NULL, "NetFailureCacheTime")
TRV_DEL(NULL, "NetFailureErrorPopupLimit")
TRV_END()
};
CONST TR_KEY_DESCRIPTOR DnscacheParameters =
{
HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters",
FALSE,
DnscacheParameter_Values
};
CONST TR_VALUE_DESCRIPTOR LmHostsParameter_Values [] =
{
TRV_ESZ(NULL, "ServiceDll", "%SystemRoot%\\System32\\lmhsvc.dll")
TRV_END()
};
CONST TR_KEY_DESCRIPTOR LmHostsParameters =
{
HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\LmHosts\\Parameters",
FALSE,
LmHostsParameter_Values
};
CONST TR_VALUE_DESCRIPTOR NetbtInterface_Values [] =
{
TRV_DEL(NULL, "EnableAdapterDomainNameRegistration")
TRV_MSZ(NULL, "NameServerList", "")
TRV_DW (NULL, "NetbiosOptions", 0)
TRV_END()
};
CONST TR_KEY_DESCRIPTOR NetbtInterfaces =
{
HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\Netbt\\Parameters\\Interfaces",
TRUE,
NetbtInterface_Values
};
CONST TR_VALUE_DESCRIPTOR NetbtParameter_Values [] =
{
TRV_DEL(NULL, "BacklogIncrement")
TRV_DW (NULL, "BcastNameQueryCount", 3)
TRV_DW (NULL, "BcastQueryTimeout", 750)
TRV_DEL(NULL, "BroadcastAddress")
TRV_DEL(NULL, "CachePerAdapterEnabled")
TRV_DW (NULL, "CacheTimeout", 600000)
TRV_DEL(NULL, "ConnectOnRequestedInterfaceOnly")
TRV_DEL(NULL, "EnableDns")
TRV_DEL(NULL, "EnableLmhosts")
TRV_DEL(NULL, "EnableProxy")
TRV_DEL(NULL, "EnableProxyRegCheck")
TRV_DEL(NULL, "InitialRefreshT.O.")
TRV_DEL(NULL, "LmhostsTimeout")
TRV_DEL(NULL, "MaxConnBackLog")
TRV_DEL(NULL, "MaxDgramBuffering")
TRV_DEL(NULL, "MaxPreloadEntries")
TRV_DEL(NULL, "MinimumFreeLowerConnections")
TRV_DEL(NULL, "MinimumRefreshSleepTime")
TRV_DW (NULL, "NameServerPort", 137)
TRV_DW (NULL, "NameSrvQueryCount", 3)
TRV_DW (NULL, "NameSrvQueryTimeout", 1500)
TRV_SZ (NULL, "NbProvider", "_tcp")
TRV_DEL(NULL, "NodeType")
TRV_DEL(NULL, "NoNameReleaseOnDemand")
TRV_DEL(NULL, "RandomAdapter")
TRV_DEL(NULL, "RefreshOpCode")
TRV_DEL(NULL, "ScopeId")
TRV_DW (NULL, "SessionKeepAlive", 3600000)
TRV_DEL(NULL, "SingleResponse")
TRV_DW (NULL, "Size/Small/Medium/Large", 1)
TRV_DEL(NULL, "SmbDeviceEnabled")
TRV_SZ (NULL, "TransportBindName", "\\Device\\")
TRV_DEL(NULL, "TryAllIpAddrs")
TRV_DEL(NULL, "TryAllNameServers")
TRV_DEL(NULL, "UseDnsOnlyForNameResolutions")
TRV_DEL(NULL, "WinsDownTimeout")
TRV_END()
};
CONST TR_KEY_DESCRIPTOR NetbtParameters =
{
HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\Netbt\\Parameters",
FALSE,
NetbtParameter_Values
};
CONST TR_VALUE_DESCRIPTOR NlaParameter_Values [] =
{
TRV_ESZ(NULL, "ServiceDll", "%SystemRoot%\\System32\\mswsock.dll")
TRV_END()
};
CONST TR_KEY_DESCRIPTOR NlaParameters =
{
HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\Nla\\Parameters",
FALSE,
NlaParameter_Values
};
CONST TR_VALUE_DESCRIPTOR TcpipInterface_Values [] =
{
TRV_DW_CA (NULL, "AddressType", 0)
TRV_MSZ (NULL, "DefaultGateway", "")
TRV_MSZ_CA(NULL, "DefaultGatewayMetric", "")
TRV_DW_CA (NULL, "DisableDynamicUpdate", 0)
TRV_DEL (NULL, "DisableReverseAddressRegistrations")
TRV_DW_CD (NULL, "DontAddDefaultGateway", 0)
TRV_DW_CV (NULL, "EnableDhcp", 0, 1)
TRV_MSZ (NULL, "IpAddress", "0.0.0.0\0")
TRV_DEL (NULL, "IpAutoconfigurationAddress")
TRV_DEL (NULL, "IpAutoconfigurationEnabled")
TRV_DEL (NULL, "IpAutoconfigurationMask")
TRV_DEL (NULL, "IpAutoconfigurationSeed")
TRV_DEL (NULL, "IpAutoconfigurationSubnet")
TRV_DEL (NULL, "MaxForwardPending")
TRV_DEL (NULL, "Mtu")
TRV_SZ_CA (NULL, "NameServer", "")
TRV_DEL (NULL, "PerformRouterDiscovery")
TRV_DEL (NULL, "PerformRouterDiscoveryBackup")
TRV_DEL (NULL, "PptpFiltering")
TRV_MSZ_CA(NULL, "RawIpAllowedProtocols", "")
TRV_DEL (NULL, "SolicitationAddressBcast")
TRV_MSZ (NULL, "SubnetMask", "0.0.0.0\0")
TRV_MSZ_CA(NULL, "TcpAllowedPorts", "")
TRV_DEL (NULL, "TcpDelAckTicks")
TRV_DEL (NULL, "TcpInitialRtt")
TRV_DEL (NULL, "TcpWindowSize")
TRV_DEL (NULL, "TypeOfInterface")
TRV_MSZ_CA(NULL, "UdpAllowedPorts", "")
TRV_DW (NULL, "UseZeroBroadcast", 0)
TRV_END ()
};
CONST TR_KEY_DESCRIPTOR TcpipInterfaces =
{
HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces",
TRUE,
TcpipInterface_Values,
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Adapters",
};
CONST TR_VALUE_DESCRIPTOR TcpipParameter_Values [] =
{
TRV_DEL(NULL, "AllowUnqualifiedQuery")
TRV_DEL(NULL, "AllowUserRawAccess")
TRV_DEL(NULL, "ArpAlwaysSourceRoute")
TRV_DEL(NULL, "ArpCacheLife")
TRV_DEL(NULL, "ArpCacheMinReferencedLife")
TRV_DEL(NULL, "ArpRetryCount")
TRV_DEL(NULL, "ArpTrSingleRoute")
TRV_DEL(NULL, "ArpUseEtherSnap")
TRV_ESZ(NULL, "DatabasePath", "%SystemRoot%\\System32\\drivers\\etc")
TRV_DEL(NULL, "DefaultRegistrationTtl")
TRV_DEL(NULL, "DefaultTosValue")
TRV_DEL(NULL, "DefaultTtl")
TRV_DEL(NULL, "DisableDhcpMediaSense")
TRV_DEL(NULL, "DisableDynamicUpdate")
TRV_DEL(NULL, "DisableIpSourceRouting")
TRV_DEL(NULL, "DisableMediaSenseEventLog")
TRV_DEL(NULL, "DisableReplaceAddressesInConflicts")
TRV_DEL(NULL, "DisableTaskOffload")
TRV_DEL(NULL, "DisableUserTosSetting")
TRV_DEL(NULL, "DisjointNameSpace")
TRV_DEL(NULL, "DontAddDefaultGatewayDefault")
TRV_DEL(NULL, "DnsQueryTimeouts")
TRV_DEL(NULL, "EnableAddrMaskReply")
TRV_DEL(NULL, "EnableBcastArpReply")
TRV_DEL(NULL, "EnableDeadGwDetect")
TRV_DEL(NULL, "EnableFastRouteLookup")
TRV_DEL(NULL, "EnableIcmpRedirect")
TRV_DEL(NULL, "EnableMulticastForwarding")
TRV_DEL(NULL, "EnablePmtuBhDetect")
TRV_DEL(NULL, "EnablePmtuDiscovery")
TRV_DEL(NULL, "EnableSecurityFilters")
TRV_DEL(NULL, "FfpControlFlags")
TRV_DEL(NULL, "FfpFastForwardingCacheSize")
TRV_DW (NULL, "ForwardBroadcasts", 0)
TRV_DEL(NULL, "ForwardBufferMemory")
TRV_DEL(NULL, "GlobalMaxTcpWindowSize")
TRV_DEL(NULL, "IgmpLevel")
TRV_DEL(NULL, "IpAutoconfigurationEnabled")
TRV_DEL(NULL, "IpAutoconfigurationMask")
TRV_DEL(NULL, "IpAutoconfigurationSeed")
TRV_DW (NULL, "IpEnableRouter", 0)
TRV_DEL(NULL, "IpEnableRouterBackup")
TRV_DEL(NULL, "KeepAliveInterval")
TRV_DEL(NULL, "KeepAliveTime")
TRV_SZ (NULL, "NameServer", "")
TRV_DEL(NULL, "MaxForwardBufferMemory")
TRV_DEL(NULL, "MaxFreeTWTcbs")
TRV_DEL(NULL, "MaxFreeTcbs")
TRV_DEL(NULL, "MaxHashTableSize")
TRV_DEL(NULL, "MaxNormLookupMemory")
TRV_DEL(NULL, "MaxNumForwardPackets")
TRV_DEL(NULL, "MaxUserPort")
TRV_DEL(NULL, "NumForwardPackets")
TRV_DEL(NULL, "NumTcbTablePartitions")
TRV_DEL(NULL, "PptpTcpMaxDataRetransmissions")
TRV_DEL(NULL, "PrioritizeRecordData")
TRV_DEL(NULL, "QueryIpMatching")
TRV_DEL(NULL, "SackOpts")
TRV_DEL(NULL, "SearchList")
TRV_DEL(NULL, "SynAttackProtect")
TRV_DEL(NULL, "Tcp1323Opts")
TRV_DEL(NULL, "TcpMaxConnectResponseRetransmissions")
TRV_DEL(NULL, "TcpMaxConnectRetransmissions")
TRV_DEL(NULL, "TcpMaxDataRetransmissions")
TRV_DEL(NULL, "TcpMaxDupAcks")
TRV_DEL(NULL, "TcpMaxHalfOpen")
TRV_DEL(NULL, "TcpMaxHalfOpenRetried")
TRV_DEL(NULL, "TcpMaxPortsExhausted")
TRV_DEL(NULL, "TcpMaxSendFree")
TRV_DEL(NULL, "TcpNumConnections")
TRV_DEL(NULL, "TcpTimedWaitDelay")
TRV_DEL(NULL, "TcpUseRfc1122UrgentPointer")
TRV_DEL(NULL, "TcpWindowSize")
TRV_DEL(NULL, "TrFunctionalMcastAddress")
TRV_DEL(NULL, "UpdateSecurityLevel")
TRV_DEL(NULL, "UseDomainNameDevolution")
TRV_DW ("Winsock", "UseDelayedAcceptance", 0)
TRV_END()
};
CONST TR_KEY_DESCRIPTOR TcpipParameters =
{
HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
FALSE,
TcpipParameter_Values
};
CONST TR_VALUE_DESCRIPTOR TcpipPerformance_Values [] =
{
TRV_SZ (NULL, "Close", "CloseTcpIpPerformanceData")
TRV_SZ (NULL, "Collect", "CollectTcpIpPerformanceData")
TRV_SZ (NULL, "Library", "Perfctrs.dll")
TRV_SZ (NULL, "Open", "OpenTcpIpPerformanceData")
TRV_SZ (NULL, "Object List", "502 510 546 582 638 658")
TRV_END()
};
CONST TR_KEY_DESCRIPTOR TcpipPerformance =
{
HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Performance",
FALSE,
TcpipPerformance_Values
};
CONST TR_VALUE_DESCRIPTOR TcpipServiceProvider_Values [] =
{
TRV_DW (NULL, "Class", 8)
TRV_DW (NULL, "DnsPriority", 2000)
TRV_DW (NULL, "HostsPriority", 500)
TRV_DW (NULL, "LocalPriority", 499)
TRV_DW (NULL, "NetbtPriority", 2001)
TRV_SZ (NULL, "Name", "TCP/IP")
TRV_ESZ(NULL, "ProviderPath", "%SystemRoot%\\System32\\wsock32.dll")
TRV_END()
};
CONST TR_KEY_DESCRIPTOR TcpipServiceProvider =
{
HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\ServiceProvider",
FALSE,
TcpipServiceProvider_Values
};
CONST TR_KEY_DESCRIPTOR* TrRepairSet [] =
{
&DhcpParameterOptions,
&DhcpParameters,
&DnscacheParameters,
&LmHostsParameters,
&NetbtInterfaces,
&NetbtParameters,
&NlaParameters,
&TcpipInterfaces,
&TcpipParameters,
&TcpipPerformance,
&TcpipServiceProvider,
NULL
};
#define SAM_DESIRED KEY_READ | KEY_WRITE | DELETE
typedef enum _TR_LOG_ACTION {
TR_ADDED,
TR_DELETED,
TR_RESET,
} TR_LOG_ACTION;
CONST PCSTR LogActionPrefix [] = {
"added ",
"deleted",
"reset ",
};
typedef struct _TR_REPAIR_CONTEXT {
HANDLE Heap;
FILE *LogFile;
PBYTE RegData;
ULONG RegDataSize;
CHAR EnumKeyName [MAX_PATH];
} TR_REPAIR_CONTEXT, *PTR_REPAIR_CTX;
BOOL
TrInitializeRepairContext(
IN PTR_REPAIR_CTX Ctx,
IN FILE *LogFile
)
{
ZeroMemory(Ctx, sizeof(TR_REPAIR_CONTEXT));
Ctx->Heap = GetProcessHeap();
Ctx->LogFile = LogFile;
Ctx->RegDataSize = 1024;
Ctx->RegData = HeapAlloc(Ctx->Heap, 0, Ctx->RegDataSize);
*Ctx->EnumKeyName = 0;
return (Ctx->RegData != NULL);
}
VOID
TrCleanupRepairContext(
IN PTR_REPAIR_CTX Ctx
)
{
if (Ctx->RegData != NULL) {
HeapFree(Ctx->Heap, 0, Ctx->RegData);
Ctx->RegData = NULL;
}
}
VOID
TrLogAction(
IN TR_LOG_ACTION Action,
IN PTR_REPAIR_CTX Ctx,
IN CONST TR_KEY_DESCRIPTOR *Kd,
IN CONST TR_VALUE_DESCRIPTOR *Vd
)
{
fprintf(Ctx->LogFile, "%s %s\\",
LogActionPrefix[Action], Kd->ParentKeyName);
if (Vd->SubKeyName != NULL) {
fprintf(Ctx->LogFile, "%s\\", Vd->SubKeyName);
}
if (Kd->EnumKey) {
fprintf(Ctx->LogFile, "%s\\", Ctx->EnumKeyName);
}
fprintf(Ctx->LogFile, "%s\n", Vd->ValueName);
//
// Show the value we are replacing.
//
if (TR_RESET == Action) {
switch (Vd->RegType) {
case REG_DWORD:
fprintf(Ctx->LogFile, " old REG_DWORD = %d\n\n", *(PULONG)Ctx->RegData);
break;
case REG_EXPAND_SZ:
fprintf(Ctx->LogFile, " old REG_EXPAND_SZ = %s\n\n", (PCSTR)Ctx->RegData);
break;
case REG_MULTI_SZ:
{
PCSTR Msz = (PCSTR)Ctx->RegData;
fprintf(Ctx->LogFile, " old REG_MULTI_SZ =\n");
if (*Msz) {
while (*Msz) {
fprintf(Ctx->LogFile, " %s\n", Msz);
Msz += strlen(Msz) + 1;
}
} else {
fprintf(Ctx->LogFile, " <empty>\n");
}
fprintf(Ctx->LogFile, "\n");
break;
}
case REG_SZ:
fprintf(Ctx->LogFile, " old REG_SZ = %s\n\n", (PCSTR)Ctx->RegData);
break;
default:
break;
}
}
}
LONG
TrReadRegData(
IN PTR_REPAIR_CTX Ctx,
IN HKEY Key,
IN CONST TR_VALUE_DESCRIPTOR *Vd,
OUT PULONG ReturnedSize
)
{
LONG Error;
ULONG Type, Size;
*ReturnedSize = 0;
Size = Ctx->RegDataSize;
Error = RegQueryValueExA(Key, Vd->ValueName, NULL, &Type,
Ctx->RegData, &Size);
if (ERROR_MORE_DATA == Error) {
HeapFree(Ctx->Heap, 0, Ctx->RegData);
Ctx->RegDataSize = (Size + 63) & ~63;
Ctx->RegData = HeapAlloc(Ctx->Heap, 0, Ctx->RegDataSize);
if (Ctx->RegData != NULL) {
Size = Ctx->RegDataSize;
Error = RegQueryValueExA(Key, Vd->ValueName, NULL, &Type,
Ctx->RegData, &Size);
if (NOERROR != Error) {
fprintf(Ctx->LogFile,
" RegQueryValueEx still failed. error = %d\n",
Error);
} else {
*ReturnedSize = Size;
}
} else {
Error = ERROR_NOT_ENOUGH_MEMORY;
}
} else if (NOERROR == Error) {
*ReturnedSize = Size;
}
return Error;
}
VOID
TrSetRegData(
IN HKEY Key,
IN CONST TR_VALUE_DESCRIPTOR *Vd,
IN BOOLEAN ConditionalKeyPresent
)
{
CONST BYTE *Data;
ConditionalKeyPresent &= (Vd->Conditional != COND_NONE);
if (REG_DWORD == Vd->RegType) {
Data = (CONST BYTE*)((ConditionalKeyPresent)? &Vd->ConditionalDataValue : &Vd->DataValue);
} else {
Data = (ConditionalKeyPresent)? Vd->ConditionalDataPointer : Vd->DataPointer;
}
RegSetValueExA(Key, Vd->ValueName, 0, Vd->RegType, Data, Vd->DataSize);
}
BOOLEAN
TrKeyShouldExist(
IN CONST TR_VALUE_DESCRIPTOR *Vd,
IN BOOLEAN ConditionalKeyPresent
)
{
if (REG_DELETE == Vd->RegType) {
return FALSE;
}
if ((Vd->Conditional == COND_ADD) && !ConditionalKeyPresent) {
return FALSE;
}
if ((Vd->Conditional == COND_DELETE) && ConditionalKeyPresent) {
return FALSE;
}
return TRUE;
}
VOID
TrProcessOpenKey(
IN PTR_REPAIR_CTX Ctx,
IN HKEY ParentKey,
IN BOOLEAN ConditionalKeyPresent,
IN CONST TR_KEY_DESCRIPTOR *Kd
)
{
LONG Error;
ULONG i, Size;
CONST TR_VALUE_DESCRIPTOR *Vd, *PrevVd;
HKEY SubKey, UseKey;
PrevVd = NULL;
SubKey = INVALID_HANDLE_VALUE;
for (i = 0; Kd->Value[i].ValueName != NULL; i++) {
Vd = &Kd->Value[i];
if (Vd->SubKeyName == NULL) {
UseKey = ParentKey;
}
//
// Open a subkey if needed, and only if its not the same as
// the one already open.
//
else if (((PrevVd == NULL) || (Vd->SubKeyName != PrevVd->SubKeyName))) {
if (SubKey != INVALID_HANDLE_VALUE) {
RegCloseKey(SubKey);
}
Error = RegOpenKeyExA(ParentKey, Vd->SubKeyName, 0,
SAM_DESIRED, &SubKey);
if (NOERROR == Error) {
UseKey = SubKey;
} else {
SubKey = INVALID_HANDLE_VALUE;
}
}
Error = TrReadRegData(Ctx, UseKey, Vd, &Size);
if (ERROR_FILE_NOT_FOUND == Error) {
if (TrKeyShouldExist(Vd, ConditionalKeyPresent)) {
//
// The value should exist, so set its default value.
//
TrSetRegData(UseKey, Vd, ConditionalKeyPresent);
TrLogAction(TR_ADDED, Ctx, Kd, Vd);
}
} else if (NOERROR == Error) {
//
// The value exists and we read its data.
//
if (!TrKeyShouldExist(Vd, ConditionalKeyPresent)) {
//
// Need to delete the existing value.
//
RegDeleteValueA(UseKey, Vd->ValueName);
TrLogAction(TR_DELETED, Ctx, Kd, Vd);
} else {
BOOL MisCompare = TRUE;
//
// Compare the value we read with the default value and reset
// it if it is different.
//
if (Size == Vd->DataSize) {
if (REG_DWORD == Vd->RegType) {
MisCompare = (*(PULONG)Ctx->RegData != ((ConditionalKeyPresent && (Vd->Conditional != COND_NONE))? Vd->ConditionalDataValue : Vd->DataValue));
} else {
MisCompare = memcmp(Ctx->RegData, (ConditionalKeyPresent && (Vd->Conditional != COND_NONE))? Vd->ConditionalDataPointer : Vd->DataPointer, Size);
}
}
if (MisCompare) {
TrSetRegData(UseKey, Vd, ConditionalKeyPresent);
TrLogAction(TR_RESET, Ctx, Kd, Vd);
}
}
} else {
fprintf(Ctx->LogFile, "\nerror reading registry value (%s) (%d)\n", Vd->ValueName, Error);
}
PrevVd = Vd;
}
if (SubKey != INVALID_HANDLE_VALUE) {
RegCloseKey(SubKey);
}
}
VOID
TrProcessKey(
IN PTR_REPAIR_CTX Ctx,
IN CONST TR_KEY_DESCRIPTOR *Kd
)
{
LONG Error;
HKEY ParentKey, ConditionalParentKey;
BOOLEAN ConditionalKeyPresent;
Error = RegOpenKeyExA(Kd->RootKey, Kd->ConditionalParentKeyName, 0,
SAM_DESIRED, &ConditionalParentKey);
if (NOERROR != Error) {
ConditionalParentKey = NULL;
}
Error = RegOpenKeyExA(Kd->RootKey, Kd->ParentKeyName, 0,
SAM_DESIRED, &ParentKey);
if (NOERROR == Error) {
if (Kd->EnumKey) {
ULONG i;
ULONG EnumKeyNameLen;
FILETIME LastWriteTime;
HKEY SubKey, ConditionalSubKey;
for (i = 0; NOERROR == Error; i++) {
EnumKeyNameLen = sizeof(Ctx->EnumKeyName);
Error = RegEnumKeyExA(ParentKey, i, Ctx->EnumKeyName, &EnumKeyNameLen,
NULL, NULL, NULL, &LastWriteTime);
if (NOERROR != Error) {
if (ERROR_NO_MORE_ITEMS != Error) {
fprintf(Ctx->LogFile, "enum error = %d (index = %d)\n",
Error, i);
}
break;
}
ConditionalKeyPresent = FALSE;
if (ConditionalParentKey) {
Error = RegOpenKeyExA(ConditionalParentKey,
Ctx->EnumKeyName, 0,
SAM_DESIRED, &ConditionalSubKey);
if (NO_ERROR == Error) {
RegCloseKey(ConditionalSubKey);
ConditionalKeyPresent = TRUE;
}
}
Error = RegOpenKeyExA(ParentKey, Ctx->EnumKeyName, 0,
SAM_DESIRED, &SubKey);
if (NOERROR == Error) {
TrProcessOpenKey(Ctx, SubKey, ConditionalKeyPresent, Kd);
RegCloseKey(SubKey);
}
}
} else {
TrProcessOpenKey(Ctx, ParentKey, FALSE, Kd);
}
RegCloseKey(ParentKey);
}
if (ConditionalParentKey) {
RegCloseKey(ConditionalParentKey);
}
}
VOID
TrProcessSet(
IN PTR_REPAIR_CTX Ctx,
IN CONST TR_KEY_DESCRIPTOR *Set[]
)
{
ULONG i;
//
// Process each TR_KEY_DESCRIPTOR element in the set.
//
for (i = 0; Set[i] != NULL; i++) {
TrProcessKey(Ctx, Set[i]);
}
}
DWORD
TrRepair(
FILE* LogFile
)
{
TR_REPAIR_CONTEXT Ctx;
if (TrInitializeRepairContext(&Ctx, LogFile)) {
TrProcessSet(&Ctx, TrRepairSet);
NetCfgDiagRepairRegistryBindings(LogFile);
TrCleanupRepairContext(&Ctx);
}
return NOERROR;
}