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.
 
 
 
 
 
 

1075 lines
32 KiB

#include "precomp.h"
EXTERN_C
VOID
WINAPI
NetCfgDiagRepairRegistryBindings (
IN FILE* pLogFile);
#define REG_DELETE 100
CONST CHAR Empty[] = "";
typedef union _TR_VALUE_DATA {
ULONG_PTR __asignany;
ULONG Value;
CONST BYTE* Pointer;
} TR_VALUE_DATA;
typedef
VOID
(TR_CONDITIONAL_ROUTINE)(
IN CONST struct _TR_REPAIR_CONTEXT *Ctx,
IN CONST struct _TR_KEY_DESCRIPTOR *Kd,
IN CONST struct _TR_VALUE_DESCRIPTOR *Vd,
OUT DWORD *RegType,
OUT TR_VALUE_DATA *Data,
OUT DWORD *DataSize
);
typedef TR_CONDITIONAL_ROUTINE *PTR_CONDITIONAL_ROUTINE;
typedef struct _TR_VALUE_DESCRIPTOR {
PCSTR SubKeyName;
PCSTR ValueName;
DWORD RegType;
TR_VALUE_DATA Data;
DWORD DataSize;
//
// If Conditional is TRUE, then Data and DataSize are obtained at run-time
// by invoking the routine whose address is in ConditionalRoutine.
// ConditionalData may be used to hold arbitrary information for use by
// ConditionalRoutine.
//
BOOLEAN Conditional;
PTR_CONDITIONAL_ROUTINE ConditionalRoutine;
TR_VALUE_DATA ConditionalData;
} TR_VALUE_DESCRIPTOR;
#define TRV_DW(_subkey, _valuename, _data) \
{ _subkey, _valuename, REG_DWORD, (ULONG_PTR)_data, sizeof(DWORD) },
#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_SZ(_subkey, _valuename, _sz) \
{ _subkey, _valuename, REG_SZ, (ULONG_PTR)_sz, sizeof(_sz) },
#define TRV_DEL(_subkey, _valuename) \
{ _subkey, _valuename, REG_DELETE, 0, 0 },
#define TRV_COND(_subkey, _valuename, _routine, _cdata) \
{ _subkey, _valuename, REG_NONE, 0, 0, TRUE, _routine, _cdata },
#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;
} 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
};
typedef enum {
TrAddressTypeTcpipValue,
TrDefaultGatewayMetricTcpipValue,
TrDisableDynamicUpdateTcpipValue,
TrDontAddDefaultGatewayTcpipValue,
TrEnableDhcpTcpipValue,
TrNameServerTcpipValue,
TrRawIpAllowedProtocolsTcpipValue,
TrTcpAllowedPortsTcpipValue,
TrUdpAllowedPortsTcpipValue,
TrEnableDeadGwDetectTcpipValue,
} TR_TCPIP_VALUE;
TR_CONDITIONAL_ROUTINE TrTcpipWanConditionalRoutine;
TR_CONDITIONAL_ROUTINE TrTcpipRrasConditionalRoutine;
CONST TR_VALUE_DESCRIPTOR TcpipInterface_Values [] =
{
TRV_COND(NULL, "AddressType",
TrTcpipWanConditionalRoutine,
TrAddressTypeTcpipValue)
TRV_MSZ (NULL, "DefaultGateway", "")
TRV_COND(NULL, "DefaultGatewayMetric",
TrTcpipWanConditionalRoutine,
TrDefaultGatewayMetricTcpipValue)
TRV_COND(NULL, "DisableDynamicUpdate",
TrTcpipWanConditionalRoutine,
TrDisableDynamicUpdateTcpipValue)
TRV_DEL (NULL, "DisableReverseAddressRegistrations")
TRV_COND(NULL, "DontAddDefaultGateway",
TrTcpipRrasConditionalRoutine,
TrDontAddDefaultGatewayTcpipValue)
TRV_COND(NULL, "EnableDhcp",
TrTcpipWanConditionalRoutine,
TrEnableDhcpTcpipValue)
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_COND(NULL, "NameServer",
TrTcpipWanConditionalRoutine,
TrNameServerTcpipValue)
TRV_DEL (NULL, "PerformRouterDiscovery")
TRV_DEL (NULL, "PerformRouterDiscoveryBackup")
TRV_DEL (NULL, "PptpFiltering")
TRV_COND(NULL, "RawIpAllowedProtocols",
TrTcpipWanConditionalRoutine,
TrRawIpAllowedProtocolsTcpipValue)
TRV_DEL (NULL, "SolicitationAddressBcast")
TRV_MSZ (NULL, "SubnetMask", "0.0.0.0\0")
TRV_COND(NULL, "TcpAllowedPorts",
TrTcpipWanConditionalRoutine,
TrTcpAllowedPortsTcpipValue)
TRV_DEL (NULL, "TcpDelAckTicks")
TRV_DEL (NULL, "TcpInitialRtt")
TRV_DEL (NULL, "TcpWindowSize")
TRV_DEL (NULL, "TypeOfInterface")
TRV_COND(NULL, "UdpAllowedPorts",
TrTcpipWanConditionalRoutine,
TrUdpAllowedPortsTcpipValue)
TRV_DW (NULL, "UseZeroBroadcast", 0)
TRV_END ()
};
CONST TR_KEY_DESCRIPTOR TcpipInterfaces =
{
HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces",
TRUE,
TcpipInterface_Values
};
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_COND(NULL, "EnableDeadGwDetect",
TrTcpipRrasConditionalRoutine,
TrEnableDeadGwDetectTcpipValue)
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,
IN DWORD RegType
)
{
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 (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 DWORD RegType,
IN TR_VALUE_DATA* Data,
IN DWORD DataSize
)
{
RegSetValueExA(Key, Vd->ValueName, 0, RegType,
(REG_DWORD == RegType) ? (CONST BYTE*)&Data->Value
: Data->Pointer,
DataSize);
}
VOID
TrProcessOpenKey(
IN PTR_REPAIR_CTX Ctx,
IN HKEY ParentKey,
IN CONST TR_KEY_DESCRIPTOR *Kd
)
{
LONG Error = NOERROR;
ULONG i, Size;
CONST TR_VALUE_DESCRIPTOR *Vd, *PrevVd;
HKEY SubKey, UseKey;
DWORD RegType;
TR_VALUE_DATA Data;
DWORD DataSize;
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;
Error = NOERROR;
}
//
// 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;
}
}
if (NOERROR == Error) {
Error = TrReadRegData(Ctx, UseKey, Vd, &Size);
}
//
// If the key is handled specially, consult its conditional-routine
// to obtain the settings to be used below. From here onwards,
// all processing for this value must use the local variables
// 'RegType', 'Data', and 'DataSize' rather than the corresponding
// fields of 'Vd'.
//
// (Also see 'TrSetRegData' and 'TrLogAction'.)
//
if (Vd->Conditional) {
Vd->ConditionalRoutine(Ctx, Kd, Vd, &RegType, &Data, &DataSize);
} else {
RegType = Vd->RegType;
Data = Vd->Data;
DataSize = Vd->DataSize;
}
if (ERROR_FILE_NOT_FOUND == Error) {
if (REG_DELETE != RegType) {
//
// The value should exist, so set its default value.
//
TrSetRegData(UseKey, Vd, RegType, &Data, DataSize);
TrLogAction(TR_ADDED, Ctx, Kd, Vd, RegType);
}
} else if (NOERROR == Error) {
//
// The value exists and we read its data.
//
if (REG_DELETE == RegType) {
//
// Need to delete the existing value.
//
RegDeleteValueA(UseKey, Vd->ValueName);
TrLogAction(TR_DELETED, Ctx, Kd, Vd, RegType);
} else {
BOOL MisCompare = TRUE;
//
// Compare the value we read with the default value and reset
// it if it is different.
//
if (Size == DataSize) {
if (REG_DWORD == RegType) {
MisCompare = (*(PULONG)Ctx->RegData != Data.Value);
} else {
MisCompare = memcmp(Ctx->RegData, Data.Pointer,
Size);
}
}
if (MisCompare) {
TrSetRegData(UseKey, Vd, RegType, &Data, DataSize);
TrLogAction(TR_RESET, Ctx, Kd, Vd, RegType);
}
}
} 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;
Error = RegOpenKeyExA(Kd->RootKey, Kd->ParentKeyName, 0,
SAM_DESIRED, &ParentKey);
if (NOERROR == Error) {
if (Kd->EnumKey) {
ULONG i;
ULONG EnumKeyNameLen;
FILETIME LastWriteTime;
HKEY SubKey;
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;
}
Error = RegOpenKeyExA(ParentKey, Ctx->EnumKeyName, 0,
SAM_DESIRED, &SubKey);
if (NOERROR == Error) {
TrProcessOpenKey(Ctx, SubKey, Kd);
RegCloseKey(SubKey);
}
}
} else {
TrProcessOpenKey(Ctx, ParentKey, Kd);
}
RegCloseKey(ParentKey);
}
}
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;
}
BOOLEAN
IsRrasInstalled(
IN CONST struct _TR_REPAIR_CONTEXT *Ctx,
IN CONST struct _TR_KEY_DESCRIPTOR *Kd
)
{
ULONG Error;
BOOLEAN RrasInstalled;
HKEY RrasKey;
CONST CHAR RrasKeyName[] =
"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess";
Error = RegOpenKeyExA(Kd->RootKey, RrasKeyName, 0, SAM_DESIRED, &RrasKey);
if (NOERROR != Error) {
RrasInstalled = FALSE;
} else {
DWORD ConfigurationFlags;
DWORD Size;
DWORD Type;
Size = sizeof(DWORD);
Error = RegQueryValueExA(RrasKey, "ConfigurationFlags", NULL, &Type,
(LPBYTE)&ConfigurationFlags, &Size);
if (NOERROR != Error) {
RrasInstalled = FALSE;
} else {
RrasInstalled = (ConfigurationFlags != 0);
}
RegCloseKey(RrasKey);
}
return RrasInstalled;
}
BOOLEAN
IsWanInterface(
IN CONST struct _TR_REPAIR_CONTEXT *Ctx,
IN CONST struct _TR_KEY_DESCRIPTOR *Kd
)
{
HKEY AdaptersKey;
CONST CHAR AdaptersKeyName[] =
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Adapters";
LONG Error;
BOOLEAN IsWan;
HKEY Key;
//
// Open the TCP/IP adapters key.
// If successful, look for a subkey with the same name
// as the one in 'Kd'. If present, this is not a LAN interface.
//
Error = RegOpenKeyExA(Kd->RootKey, AdaptersKeyName, 0, SAM_DESIRED,
&AdaptersKey);
if (NOERROR != Error) {
//
// Assume this is a LAN interface.
//
IsWan = FALSE;
} else {
Error = RegOpenKeyExA(AdaptersKey, Ctx->EnumKeyName, 0, SAM_DESIRED,
&Key);
if (NOERROR != Error) {
IsWan = TRUE;
} else {
IsWan = FALSE;
RegCloseKey(Key);
}
RegCloseKey(AdaptersKey);
}
return IsWan;
}
VOID
TrTcpipWanConditionalRoutine(
IN CONST struct _TR_REPAIR_CONTEXT *Ctx,
IN CONST struct _TR_KEY_DESCRIPTOR *Kd,
IN CONST struct _TR_VALUE_DESCRIPTOR *Vd,
OUT DWORD *RegType,
OUT TR_VALUE_DATA *Data,
OUT DWORD *DataSize
)
{
//
// Return the appropriate setting for the given registry value,
// based on whether its key is for a WAN or LAN interface.
//
if (IsWanInterface(Ctx, Kd)) {
switch((TR_TCPIP_VALUE)Vd->ConditionalData.Value) {
case TrAddressTypeTcpipValue:
case TrDefaultGatewayMetricTcpipValue:
case TrDisableDynamicUpdateTcpipValue:
case TrNameServerTcpipValue:
case TrRawIpAllowedProtocolsTcpipValue:
case TrTcpAllowedPortsTcpipValue:
case TrUdpAllowedPortsTcpipValue:
default:
*RegType = REG_DELETE;
break;
case TrEnableDhcpTcpipValue:
case TrDontAddDefaultGatewayTcpipValue:
*RegType = REG_DWORD;
Data->Value = 0;
*DataSize = sizeof(DWORD);
break;
}
} else {
switch((TR_TCPIP_VALUE)Vd->ConditionalData.Value) {
case TrDontAddDefaultGatewayTcpipValue:
default:
*RegType = REG_DELETE;
break;
case TrAddressTypeTcpipValue:
case TrDisableDynamicUpdateTcpipValue:
*RegType = REG_DWORD;
Data->Value = 0;
*DataSize = sizeof(DWORD);
break;
case TrEnableDhcpTcpipValue:
*RegType = REG_DWORD;
Data->Value = 1;
*DataSize = sizeof(DWORD);
break;
case TrNameServerTcpipValue:
*RegType = REG_SZ;
Data->Pointer = Empty;
*DataSize = sizeof(Empty);
break;
case TrDefaultGatewayMetricTcpipValue:
case TrRawIpAllowedProtocolsTcpipValue:
case TrTcpAllowedPortsTcpipValue:
case TrUdpAllowedPortsTcpipValue:
*RegType = REG_MULTI_SZ;
Data->Pointer = Empty;
*DataSize = sizeof(Empty);
break;
}
}
}
VOID
TrTcpipRrasConditionalRoutine(
IN CONST struct _TR_REPAIR_CONTEXT *Ctx,
IN CONST struct _TR_KEY_DESCRIPTOR *Kd,
IN CONST struct _TR_VALUE_DESCRIPTOR *Vd,
OUT DWORD *RegType,
OUT TR_VALUE_DATA *Data,
OUT DWORD *DataSize
)
{
//
// Return the appropriate setting for the given registry value,
// based on whether RRAS is installed.
//
// N.B. The setting for 'DontAddDefaultGateway' is further dependent
// on whether the key is for a WAN or LAN interface.
//
if (IsRrasInstalled(Ctx, Kd)) {
switch((TR_TCPIP_VALUE)Vd->ConditionalData.Value) {
case TrDontAddDefaultGatewayTcpipValue:
if (IsWanInterface(Ctx, Kd)) {
*RegType = REG_DWORD;
Data->Value = 1;
*DataSize = sizeof(DWORD);
} else {
*RegType = REG_DELETE;
}
break;
case TrEnableDeadGwDetectTcpipValue:
*RegType = REG_DWORD;
Data->Value = 0;
*DataSize = sizeof(DWORD);
break;
default:
*RegType = REG_DELETE;
break;
}
} else {
switch((TR_TCPIP_VALUE)Vd->ConditionalData.Value) {
case TrDontAddDefaultGatewayTcpipValue:
case TrEnableDeadGwDetectTcpipValue:
default:
*RegType = REG_DELETE;
break;
}
}
}