#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, " \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; }