//================================================================================ // Copyright (C) 1997 Microsoft Corporation // Author: RameshV // Description: simple registry utilities //================================================================================ #include //BeginExport(typedef) typedef struct _REG_HANDLE { HKEY Key; HKEY SubKey; LPWSTR SubKeyLocation; } REG_HANDLE, *PREG_HANDLE, *LPREG_HANDLE; //EndExport(typedef) //BeginExport(constants) #define REG_THIS_SERVER L"Software\\Microsoft\\DHCPServer\\Configuration" #define REG_THIS_SERVER_DS L"Software\\Microsoft\\DHCPServer\\Config_DS" #define REG_THIS_SERVER_DS_VALUE L"Config_DS" #define REG_THIS_SERVER_DS_PARENT L"Software\\Microsoft\\DHCPServer" #define REG_SERVER_GLOBAL_OPTIONS L"GlobalOptionValues" #define REG_SERVER_OPTDEFS L"OptionInfo" #define REG_SERVER_SUBNETS L"Subnets" #define REG_SERVER_SSCOPES L"SuperScope" #define REG_SERVER_CLASSDEFS L"ClassDefs" #define REG_SERVER_MSCOPES L"MulticastScopes" #define REG_SUBNET_SERVERS L"DHCPServers" #define REG_SUBNET_RANGES L"IpRanges" #define REG_SUBNET_RESERVATIONS L"ReservedIps" #define REG_SUBNET_OPTIONS L"SubnetOptions" #define REG_SUBNET_EXCL L"ExcludedIpRanges" #define REG_SUBNET_ADDRESS L"SubnetAddress" #define REG_SUBNET_NAME L"SubnetName" #define REG_SUBNET_COMMENT L"SubnetComment" #define REG_SUBNET_MASK L"SubnetMask" #define REG_SUBNET_STATE L"SubnetState" #define REG_SUBNET_SWITCHED_FLAG L"SwitchedNetworkFlag" #define REG_MSCOPE_NAME L"MScopeName" #define REG_MSCOPE_COMMENT L"MScopeComment" // // Win2K Beta2 and Beta3 went out with scope id param value MScopeId. // Since their meaning is being changed, to avoid any costly upgrade // code, this value is being changed to MScopeIdValue: to automatically // chose a good scope id, TTL values. Note that the default value of // zero is treated specially for this scope id param. It implies that // this was probably a pre-RC1 upgrade. In this case, the Scope ID // defaults to first value in the range. // #define REG_MSCOPE_SCOPEID L"MScopeIdValue" #define REG_MSCOPE_STATE L"MScopeState" #define REG_MSCOPE_ADDR_POLICY L"MScopeAddressPolicy" #define REG_MSCOPE_TTL L"MScopeTTL" #define REG_MSCOPE_LANG_TAG L"MScopeLangTag" #define REG_MSCOPE_EXPIRY_TIME L"MScopeExpiryTime" #define REG_SUB_SERVER_NAME L"ServerHostName" #define REG_SUB_SERVER_COMMENT L"ServerComment" #define REG_SUB_SERVER_ADDRESS L"ServerAddress" #define REG_SUB_SERVER_ROLE L"Role" #define REG_RANGE_NAME L"RangeName" #define REG_RANGE_COMMENT L"RangeComment" #define REG_RANGE_START_ADDRESS L"StartAddress" #define REG_RANGE_END_ADDRESS L"EndAddress" #define REG_RANGE_INUSE_CLUSTERS L"InUseClusters" #define REG_RANGE_USED_CLUSTERS L"UsedClusters" #define REG_RANGE_BITS_PREFIX L"Bits " #define REG_RANGE_BITS_PREFIX_WCHAR_COUNT (5) #define REG_RANGE_FLAGS L"RangeFlags" #define REG_RANGE_ALLOC L"RangeBootpAllocated" #define REG_RANGE_MAX_ALLOC L"RangeBootpMaxAllowed" #define REG_OPTION_NAME L"OptionName" #define REG_OPTION_COMMENT L"OptionComment" #define REG_OPTION_TYPE L"OptionType" #define REG_OPTION_VALUE L"OptionValue" #define REG_OPTION_ID L"OptionId" #define REG_OPTION_CLASSNAME L"OptionClassName" #define REG_OPTION_VENDORNAME L"OptionVendorName" #define REG_CLASSDEF_NAME L"ClassName" #define REG_CLASSDEF_COMMENT L"ClassComment" #define REG_CLASSDEF_TYPE L"ClassType" #define REG_CLASSDEF_VALUE L"ClassValue" #define REG_RESERVATION_ADDRESS L"IpAddress" #define REG_RESERVATION_UID L"ClientUID" #define REG_RESERVATION_TYPE L"AllowedClientTypes" #define REG_RESERVATION_NAME L"ReservationName" #define REG_RESERVATION_COMMENT L"ReservationComment" #define REG_FLAGS L"Flags" #define REG_ACCESS KEY_ALL_ACCESS #define REG_DEFAULT_SUBNET_STATE 0 #define REG_DEFAULT_SUBNET_MASK 0xFFFFFFFF #define REG_DEFAULT_SWITCHED_FLAG FALSE #define REG_CLASS L"DhcpClass" #define DHCP_LAST_DOWNLOAD_TIME_VALUE L"LastDownloadTime" #define DHCP_LAST_DOWNLOAD_TIME_TYPE REG_BINARY #define DEF_RANGE_ALLOC 0 #define DEF_RANGE_MAX_ALLOC (~(ULONG)0) //EndExport(constants) const DWORD ZeroReserved = 0; const LPVOID NullReserved = 0; #define MAX_KEY_SIZE 512 #define DEF_RANGE_FLAG_VAL (MM_FLAG_ALLOW_DHCP) #define DEF_RESERVATION_TYPE (MM_FLAG_ALLOW_DHCP|MM_FLAG_ALLOW_BOOTP) //BeginExport(comment) //================================================================================ // The basic open/traverse/close functions are here //================================================================================ //EndExport(comment) HKEY CurrentServerKey = NULL; //BeginExport(function) DWORD DhcpRegSetCurrentServer( IN OUT PREG_HANDLE Hdl ) //EndExport(function) { CurrentServerKey = Hdl? Hdl->Key : NULL; return ERROR_SUCCESS; } //BeginExport(function) DWORD DhcpRegGetThisServer( IN OUT PREG_HANDLE Hdl ) //EndExport(function) { DWORD Disposition; if( NULL != CurrentServerKey ) { return RegOpenKeyEx( // duplicate key CurrentServerKey, NULL, ZeroReserved, REG_ACCESS, &Hdl->Key ); } return RegCreateKeyEx( HKEY_LOCAL_MACHINE, REG_THIS_SERVER, ZeroReserved, REG_CLASS, REG_OPTION_NON_VOLATILE, REG_ACCESS, NULL, &Hdl->Key, &Disposition ); } //BeginExport(function) DWORD DhcpRegGetNextHdl( IN PREG_HANDLE Hdl, IN LPWSTR NextLoc, OUT PREG_HANDLE OutHdl ) //EndExport(function) { DWORD Disposition; DWORD Error; Error = RegCreateKeyEx( Hdl->Key, NextLoc, ZeroReserved, REG_CLASS, REG_OPTION_NON_VOLATILE, REG_ACCESS, NULL, &OutHdl->Key, &Disposition ); return Error; } //BeginExport(function) DWORD DhcpRegCloseHdl( IN OUT PREG_HANDLE Hdl ) //EndExport(function) { DWORD Error; Error = RegCloseKey(Hdl->Key); Hdl->Key = NULL; return Error; } //BeginExport(comment) //================================================================================ // MISC utilities for registry manipulation //================================================================================ //EndExport(comment) //BeginExport(function) DWORD DhcpRegFillSubKeys( IN PREG_HANDLE Hdl, IN OUT PARRAY Array // fill in a list of key names ) //EndExport(function) { DWORD Error; DWORD Index; DWORD Size; WCHAR KeyName[MAX_KEY_SIZE]; LPWSTR ThisKeyName; Index = 0; do { Size = sizeof(KeyName)/sizeof(KeyName[0]); Error = RegEnumKeyEx( Hdl->Key, Index++, KeyName, &Size, NullReserved, NULL, NULL, NULL ); if( ERROR_NO_MORE_ITEMS == Error ) { Error = ERROR_SUCCESS; break; } if( ERROR_SUCCESS != Error ) break; Require(0 != Size); Size += 1; // for the terminating L'\0' char Size *= sizeof(WCHAR); // looks like the units are WCHAR!! ThisKeyName = MemAlloc(Size); if( NULL == ThisKeyName ) return ERROR_NOT_ENOUGH_MEMORY; wcscpy(ThisKeyName, KeyName); Error = MemArrayAddElement(Array, (LPVOID)ThisKeyName); if( ERROR_SUCCESS != Error ) { MemFree(ThisKeyName); } } while( ERROR_SUCCESS == Error ); Require(ERROR_MORE_DATA != Error); return Index? ERROR_SUCCESS : Error; // if we added something, dont bother about reporting error } //BeginExport(function) LPVOID // DWORD or LPWSTR or LPBYTE DhcpRegRead( // read differnt values from registry and allocate if not DWORD IN PREG_HANDLE Hdl, IN DWORD Type, // if DWORD dont allocate memory IN LPWSTR ValueName, IN LPVOID RetValue // value to use if nothing found ) //EndExport(function) { DWORD Error; DWORD Size; DWORD Dword; LPVOID Ret; if( REG_DWORD == Type ) { Size = sizeof(DWORD); Ret = (LPVOID)&Dword; } else { Size = 0; Error = RegQueryValueEx( Hdl->Key, ValueName, NullReserved, NULL, NULL, &Size ); if( ERROR_SUCCESS != Error ) return RetValue; if (Size == 0) return RetValue; // MemAlloc does not check the size! Ret = MemAlloc(Size); if( NULL == Ret ) return RetValue; // should not really happen } Error = RegQueryValueEx( Hdl->Key, ValueName, NullReserved, NULL, Ret, &Size ); if( ERROR_SUCCESS != Error && Ret != (LPVOID)&Dword ) { MemFree(Ret); Ret = NULL; } if( ERROR_SUCCESS != Error) return RetValue; if( Ret == (LPVOID)&Dword ) { return ULongToPtr(Dword); } else { return Ret; } } //BeginExport(function) DWORD DhcpRegReadBinary( // read binary type IN PREG_HANDLE Hdl, IN LPWSTR ValueName, OUT LPBYTE *RetVal, OUT DWORD *RetValSize ) //EndExport(function) { DWORD Error; DWORD Size; LPVOID Ret; *RetVal = NULL; *RetValSize = 0; Size = 0; Error = RegQueryValueEx( Hdl->Key, ValueName, NullReserved, NULL, NULL, &Size ); if( ERROR_SUCCESS != Error ) return Error; if( 0 == Size ) return ERROR_SUCCESS; Ret = MemAlloc(Size); if( NULL == Ret ) return ERROR_NOT_ENOUGH_MEMORY; Error = RegQueryValueEx( Hdl->Key, ValueName, NullReserved, NULL, Ret, &Size ); if( ERROR_SUCCESS != Error ) { MemFree(Ret); return Error; } *RetVal = Ret; *RetValSize = Size; return ERROR_SUCCESS; } //BeginExport(function) LPWSTR DhcpRegCombineClassAndOption( // create string based on class name and option id IN LPWSTR ClassName, IN LPWSTR VendorName, IN DWORD OptionId ) //EndExport(function) { DWORD Size; LPWSTR Ptr; if( NULL == VendorName && NULL == ClassName ) { // // Special case usual options for downward compatability with older // options.. (NT4 options in registry don't have any "!" in them. // Ptr = MemAlloc( 4 * sizeof(WCHAR) ); if( NULL == Ptr ) return NULL; Ptr [2] = L'0' + (BYTE)(OptionId %10); OptionId /= 10; Ptr [1] = L'0' + (BYTE)(OptionId %10); OptionId /= 10; Ptr [0] = L'0' + (BYTE)(OptionId %10); Ptr [3] = L'\0'; return Ptr; } if( NULL == VendorName ) VendorName = L""; if( NULL == ClassName ) ClassName = L""; Size = (wcslen(ClassName) + 1 + 5)*sizeof(WCHAR); Size += wcslen(VendorName)*sizeof(WCHAR); Ptr = MemAlloc(Size); if( NULL == Ptr ) return NULL; Size = 0; Ptr[2+Size] = L'0' + (BYTE)(OptionId % 10); OptionId /= 10; Ptr[1+Size] = L'0' + (BYTE)(OptionId % 10); OptionId /= 10; Ptr[0+Size] = L'0' + (BYTE)(OptionId % 10); Ptr[3+Size] = L'\0'; wcscat(Ptr, L"!"); wcscat(Ptr, VendorName); wcscat(Ptr, L"!"); wcscat(Ptr, ClassName); return Ptr; } //BeginExport(function) LPWSTR ConvertAddressToLPWSTR( IN DWORD Address, IN OUT LPWSTR BufferStr // input buffer to fill with dotted notation ) //EndExport(function) { LPSTR AddressStr; DWORD Count; Address = ntohl(Address); AddressStr = inet_ntoa(*(struct in_addr *)&Address); Count = mbstowcs(BufferStr, AddressStr, sizeof("000.000.000.000")); if( -1 == Count ) return NULL; return BufferStr; } //BeginExport(comment) //================================================================================ // the following functions help traversing the registry //================================================================================ //EndExport(comment) DWORD DhcpRegGetNextNextHdl( IN PREG_HANDLE Hdl, IN LPWSTR Loc1, IN LPWSTR Loc2, OUT PREG_HANDLE Hdl2 ) { WCHAR Loc[MAX_KEY_SIZE*2]; Loc[ 0 ] = L'\0'; if ( ( wcslen(Loc1) + wcslen(Loc2) + 1 ) < ( MAX_KEY_SIZE * 2 ) ) { wcscpy(Loc,Loc1); wcscat(Loc, L"\\"); wcscat(Loc,Loc2); } return DhcpRegGetNextHdl(Hdl, Loc, Hdl2); } //BeginExport(function) DWORD DhcpRegServerGetSubnetHdl( IN PREG_HANDLE Hdl, IN LPWSTR Subnet, OUT PREG_HANDLE Hdl2 ) //EndExport(function) { return DhcpRegGetNextNextHdl(Hdl, REG_SERVER_SUBNETS, Subnet, Hdl2); } //BeginExport(function) DWORD DhcpRegServerGetSScopeHdl( IN PREG_HANDLE Hdl, IN LPWSTR SScope, OUT PREG_HANDLE Hdl2 ) //EndExport(function) { return DhcpRegGetNextNextHdl(Hdl, REG_SERVER_SSCOPES, SScope, Hdl2); } //BeginExport(function) DWORD DhcpRegServerGetOptDefHdl( IN PREG_HANDLE Hdl, IN LPWSTR OptDef, OUT PREG_HANDLE Hdl2 ) //EndExport(function) { return DhcpRegGetNextNextHdl(Hdl, REG_SERVER_OPTDEFS, OptDef, Hdl2); } //BeginExport(function) DWORD DhcpRegServerGetOptHdl( IN PREG_HANDLE Hdl, IN LPWSTR Opt, OUT PREG_HANDLE Hdl2 ) //EndExport(function) { return DhcpRegGetNextNextHdl(Hdl, REG_SERVER_GLOBAL_OPTIONS, Opt, Hdl2); } //BeginExport(function) DWORD DhcpRegServerGetMScopeHdl( IN PREG_HANDLE Hdl, IN LPWSTR MScope, OUT PREG_HANDLE Hdl2 ) //EndExport(function) { return DhcpRegGetNextNextHdl(Hdl, REG_SERVER_MSCOPES, MScope, Hdl2); } //BeginExport(function) DWORD DhcpRegServerGetClassDefHdl( IN PREG_HANDLE Hdl, IN LPWSTR ClassDef, OUT PREG_HANDLE Hdl2 ) //EndExport(function) { return DhcpRegGetNextNextHdl(Hdl, REG_SERVER_CLASSDEFS, ClassDef, Hdl2); } //BeginExport(function) DWORD DhcpRegSubnetGetOptHdl( IN PREG_HANDLE Hdl, IN LPWSTR Opt, OUT PREG_HANDLE Hdl2 ) //EndExport(function) { return DhcpRegGetNextNextHdl(Hdl, REG_SUBNET_OPTIONS, Opt, Hdl2); } //BeginExport(function) DWORD DhcpRegSubnetGetRangeHdl( IN PREG_HANDLE Hdl, IN LPWSTR Range, OUT PREG_HANDLE Hdl2 ) //EndExport(function) { return DhcpRegGetNextNextHdl(Hdl, REG_SUBNET_RANGES, Range, Hdl2); } //BeginExport(function) DWORD DhcpRegSubnetGetReservationHdl( IN PREG_HANDLE Hdl, IN LPWSTR Reservation, OUT PREG_HANDLE Hdl2 ) //EndExport(function) { return DhcpRegGetNextNextHdl(Hdl, REG_SUBNET_RESERVATIONS, Reservation, Hdl2); } //BeginExport(function) DWORD DhcpRegSubnetGetServerHdl( IN PREG_HANDLE Hdl, IN LPWSTR Server, OUT PREG_HANDLE Hdl2 ) //EndExport(function) { return DhcpRegGetNextNextHdl(Hdl, REG_SUBNET_SERVERS, Server, Hdl2); } //BeginExport(function) DWORD DhcpRegReservationGetOptHdl( IN PREG_HANDLE Hdl, IN LPWSTR OptionName, OUT PREG_HANDLE Hdl2 ) //EndExport(function) { return DhcpRegGetNextHdl(Hdl, OptionName, Hdl2); } //BeginExport(comment) //================================================================================ // List retrieval functions.. for servers, subnets, ranges etc. //================================================================================ //EndExport(comment) //BeginExport(function) DWORD DhcpRegServerGetList( IN PREG_HANDLE Hdl, // ptr to server location IN OUT PARRAY OptList, // list of LPWSTR options IN OUT PARRAY OptDefList, // list of LPWSTR optdefs IN OUT PARRAY Subnets, // list of LPWSTR subnets IN OUT PARRAY SScopes, // list of LPWSTR sscopes IN OUT PARRAY ClassDefs, // list of LPWSTR classes IN OUT PARRAY MScopes // list of LPWSTR mscopes ) //EndExport(function) { DWORD Error; DWORD LocalError; DWORD Index; REG_HANDLE Hdl2; struct { PARRAY Array; LPWSTR Location; } Table[] = { OptList, REG_SERVER_GLOBAL_OPTIONS, OptDefList, REG_SERVER_OPTDEFS, Subnets, REG_SERVER_SUBNETS, SScopes, REG_SERVER_SSCOPES, ClassDefs, REG_SERVER_CLASSDEFS, MScopes, REG_SERVER_MSCOPES }; for( Index = 0; Index < sizeof(Table)/sizeof(Table[0]); Index ++ ) { if( NULL == Table[Index].Array ) continue; Error = DhcpRegGetNextHdl(Hdl, Table[Index].Location, &Hdl2); if( ERROR_SUCCESS != Error ) return Error; Error = DhcpRegFillSubKeys(&Hdl2, Table[Index].Array); LocalError = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == LocalError); if( ERROR_SUCCESS != Error ) return Error; } return Error; } //BeginExport(function) DWORD DhcpRegSubnetGetExclusions( IN PREG_HANDLE Hdl, OUT LPBYTE *Excl, OUT DWORD *ExclSize ) //EndExport(function) { DWORD Error; DWORD Size; DWORD Type; if( NULL == Excl ) return ERROR_SUCCESS; Size = 0; Error = RegQueryValueEx( Hdl->Key, REG_SUBNET_EXCL, NullReserved, &Type, NULL, &Size ); if( ERROR_SUCCESS != Error ) return Error; *Excl = NULL; *ExclSize = 0; if( 0 == Size ) return ERROR_SUCCESS; *Excl = MemAlloc(Size); if( NULL == *Excl ) return ERROR_NOT_ENOUGH_MEMORY; *ExclSize = Size; Error = RegQueryValueEx( Hdl->Key, REG_SUBNET_EXCL, NullReserved, &Type, *Excl, ExclSize ); if( ERROR_SUCCESS != Error ) { MemFree(*Excl); *Excl = NULL; } return Error; } //BeginExport(function) DWORD DhcpRegSubnetGetList( IN PREG_HANDLE Hdl, IN OUT PARRAY Servers, IN OUT PARRAY IpRanges, IN OUT PARRAY Reservations, IN OUT PARRAY Options, OUT LPBYTE *Excl, OUT DWORD *ExclSizeInBytes ) //EndExport(function) { DWORD Error; DWORD LocalError; DWORD Index; REG_HANDLE Hdl2; struct { PARRAY Array; LPWSTR Location; } Table[] = { Servers, REG_SUBNET_SERVERS, IpRanges, REG_SUBNET_RANGES, Reservations, REG_SUBNET_RESERVATIONS, Options, REG_SUBNET_OPTIONS, // Exclusions are to be handled a bit differently }; for( Index = 0; Index < sizeof(Table)/sizeof(Table[0]); Index ++ ) { if( NULL == Table[Index].Array ) continue; Error = DhcpRegGetNextHdl(Hdl, Table[Index].Location, &Hdl2); if( ERROR_SUCCESS != Error ) return Error; Error = DhcpRegFillSubKeys(&Hdl2, Table[Index].Array); LocalError = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == LocalError); if( ERROR_SUCCESS != Error ) return Error; } // Now read the exclusions from off here return DhcpRegSubnetGetExclusions(Hdl, Excl, ExclSizeInBytes ); } //BeginExport(function) DWORD DhcpRegSScopeGetList( IN PREG_HANDLE Hdl, IN OUT PARRAY Subnets ) //EndExport(function) { return DhcpRegFillSubKeys(Hdl, Subnets); } //BeginExport(function) DWORD DhcpRegReservationGetList( IN PREG_HANDLE Hdl, IN OUT PARRAY Options ) //EndExport(function) { return DhcpRegFillSubKeys(Hdl, Options); } //BeginExport(comment) //================================================================================ // the separate stuff are here -- these are not list stuff, but just simple // single valued attributes // some of these actually, dont even go to the registry, but that's fine alright? //================================================================================ //EndExport(comment) //BeginExport(function) DWORD DhcpRegServerGetAttributes( IN PREG_HANDLE Hdl, OUT LPWSTR *Name, OUT LPWSTR *Comment, OUT DWORD *Flags // more attributes will come here soon? ) //EndExport(function) { if( Name ) *Name = NULL; if( Comment ) *Comment = NULL; if( Flags ) *Flags = 0; return ERROR_SUCCESS; } //BeginExport(function) DWORD DhcpRegSubnetGetAttributes( IN PREG_HANDLE Hdl, OUT LPWSTR *Name, OUT LPWSTR *Comment, OUT DWORD *Flags, OUT DWORD *Address, OUT DWORD *Mask ) //EndExport(function) { DWORD fSwitched; if( Name ) *Name = DhcpRegRead(Hdl, REG_SZ, REG_SUBNET_NAME, NULL); if( Comment ) *Comment = DhcpRegRead(Hdl, REG_SZ, REG_SUBNET_COMMENT, NULL); if( Flags ) { *Flags = PtrToUlong(DhcpRegRead(Hdl, REG_DWORD, REG_SUBNET_STATE, (LPVOID)REG_DEFAULT_SUBNET_STATE)); fSwitched = PtrToUlong(DhcpRegRead(Hdl, REG_DWORD, REG_SUBNET_SWITCHED_FLAG, (LPVOID)REG_DEFAULT_SWITCHED_FLAG)); if(fSwitched) SWITCHED(*Flags); } if( Address ) *Address = PtrToUlong(DhcpRegRead(Hdl, REG_DWORD, REG_SUBNET_ADDRESS, (LPVOID)0)); if( Mask ) *Mask = PtrToUlong(DhcpRegRead(Hdl, REG_DWORD, REG_SUBNET_MASK, ULongToPtr(REG_DEFAULT_SUBNET_MASK))); return ERROR_SUCCESS; } typedef struct { LPVOID RetPtr; LPWSTR ValueName; DWORD ValueType; LPVOID Defaults; } ATTRIB_TBL, *PATTRIB_TBL, *LPATTRIB_TBL; VOID DhcpRegFillAttribTable( IN PREG_HANDLE Hdl, IN PATTRIB_TBL Table, IN DWORD TableSize ) { DWORD i; PVOID Tmp; for( i = 0; i < TableSize ; i ++ ) { if( NULL == Table[i].RetPtr) continue; Tmp = DhcpRegRead( Hdl, Table[i].ValueType, Table[i].ValueName, Table[i].Defaults ); if( REG_DWORD == Table[i].ValueType ) { *((DWORD *)Table[i].RetPtr) = PtrToUlong(Tmp); } else { *((LPVOID *)Table[i].RetPtr) = Tmp; } } } // // Hack O Rama -- This routine returns ERROR_INVALID_DATA if // the registry has been upgraded from pre-win2k build to win2k. // So that defaults can be chosen for ScopeId etc. // //BeginExport(function) DWORD DhcpRegMScopeGetAttributes( IN PREG_HANDLE Hdl, OUT LPWSTR *Comments, OUT DWORD *State, OUT DWORD *ScopeId, OUT DWORD *Policy, OUT DWORD *TTL, OUT LPWSTR *LangTag, OUT PDATE_TIME *ExpiryTime ) //EndExport(function) { DATE_TIME DefaultExpiryTime = {DHCP_DATE_TIME_INFINIT_LOW, DHCP_DATE_TIME_INFINIT_HIGH}; LPWSTR DefaultLangTag = L"en-US"; DWORD ScopeIdFake1, ScopeIdFake2; ATTRIB_TBL Table[] = { Comments, REG_MSCOPE_COMMENT, REG_SZ, NULL, State, REG_MSCOPE_STATE, REG_DWORD, (LPVOID)0, ScopeId, REG_MSCOPE_SCOPEID, REG_DWORD, (LPVOID)0, &ScopeIdFake1, REG_MSCOPE_SCOPEID, REG_DWORD, (LPVOID)1, &ScopeIdFake2, REG_MSCOPE_SCOPEID, REG_DWORD, (LPVOID)2, Policy, REG_MSCOPE_ADDR_POLICY, REG_DWORD, (LPVOID)0, TTL, REG_MSCOPE_TTL, REG_DWORD, (LPVOID)DEFAULT_MCAST_TTL, LangTag, REG_MSCOPE_LANG_TAG, REG_SZ, (LPVOID)0, ExpiryTime, REG_MSCOPE_EXPIRY_TIME, REG_BINARY, (LPVOID)0 }; DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); if (*LangTag == 0) { *LangTag = MemAlloc(wcslen((DefaultLangTag)+1)*sizeof(WCHAR)); if (*LangTag) { wcscpy(*LangTag, DefaultLangTag); } else { return ERROR_NOT_ENOUGH_MEMORY; } } if (*ExpiryTime == 0) { *ExpiryTime = MemAlloc(sizeof (DefaultExpiryTime)); if (*ExpiryTime) { **ExpiryTime = DefaultExpiryTime; } else { return ERROR_NOT_ENOUGH_MEMORY; } } if( ScopeIdFake1 != ScopeIdFake2 ) { Require(ScopeIdFake1 == 1 && ScopeIdFake2 == 2); // // Basically no value for ScopeId in the registry. return a warning. // such as ERROR_INVALID_DATA. // return ERROR_INVALID_DATA; } return ERROR_SUCCESS; } //BeginExport(function) DWORD DhcpRegOptDefGetAttributes( IN PREG_HANDLE Hdl, OUT LPWSTR *Name, OUT LPWSTR *Comments, OUT DWORD *Flags, OUT DWORD *OptionId, OUT LPWSTR *ClassName, OUT LPWSTR *VendorName, OUT LPBYTE *Value, OUT DWORD *ValueSize ) //EndExport(function) { DWORD Error; ATTRIB_TBL Table[] = { Name, REG_OPTION_NAME, REG_SZ, NULL, Comments, REG_OPTION_COMMENT, REG_SZ, NULL, ClassName, REG_OPTION_CLASSNAME, REG_SZ, NULL, VendorName, REG_OPTION_VENDORNAME, REG_SZ, NULL, Flags, REG_OPTION_TYPE, REG_DWORD, (LPVOID)0, OptionId, REG_OPTION_ID, REG_DWORD, (LPVOID)0 }; DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); if( Value ) { Error = DhcpRegReadBinary(Hdl, REG_OPTION_VALUE, Value, ValueSize); Require(*Value); } return ERROR_SUCCESS; } //BeginExport(function) DWORD DhcpRegSScopeGetAttributes( // superscopes dont have any information stored.. dont use this IN PREG_HANDLE Hdl, OUT LPWSTR *Name, OUT LPWSTR *Comment, OUT DWORD *Flags ) //EndExport(function) { Require(FALSE); return ERROR_INVALID_PARAMETER; } //BeginExport(function) DWORD DhcpRegClassDefGetAttributes( IN PREG_HANDLE Hdl, OUT LPWSTR *Name, OUT LPWSTR *Comment, OUT DWORD *Flags, OUT LPBYTE *Value, OUT DWORD *ValueSize ) //EndExport(function) { DWORD Error; ATTRIB_TBL Table[] = { Name, REG_CLASSDEF_NAME, REG_SZ, NULL, Comment, REG_CLASSDEF_COMMENT, REG_SZ, NULL, Flags, REG_CLASSDEF_TYPE, REG_DWORD, (LPVOID)0 }; DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); if( Value ) { Error = DhcpRegReadBinary(Hdl, REG_CLASSDEF_VALUE, Value, ValueSize); Require(*Value); } return ERROR_SUCCESS; } //BeginExport(function) DWORD DhcpRegSubnetServerGetAttributes( IN PREG_HANDLE Hdl, OUT LPWSTR *Name, OUT LPWSTR *Comment, OUT DWORD *Flags, OUT DWORD *Address, OUT DWORD *Role ) //EndExport(function) { ATTRIB_TBL Table[] = { Name, REG_SUB_SERVER_NAME, REG_SZ, NULL, Comment, REG_SUB_SERVER_COMMENT,REG_SZ, NULL, Flags, REG_FLAGS, REG_DWORD, (LPVOID)0, Address, REG_SUB_SERVER_ADDRESS,REG_DWORD, (LPVOID)0, Role, REG_SUB_SERVER_ROLE, REG_DWORD, (LPVOID)0 }; DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); return ERROR_SUCCESS; } //BeginExport(function) DWORD DhcpRegRangeGetAttributes( IN PREG_HANDLE Hdl, OUT LPWSTR *Name, OUT LPWSTR *Comment, OUT DWORD *Flags, OUT ULONG *AllocCount, OUT ULONG *MaxAllocCount, OUT DWORD *StartAddress, OUT DWORD *EndAddress, OUT LPBYTE *InUseClusters, OUT DWORD *InUseClusterSize, OUT LPBYTE *UsedClusters, OUT DWORD *UsedClustersSize ) //EndExport(function) { DWORD Error; ATTRIB_TBL Table[] = { Name, REG_RANGE_NAME, REG_SZ, NULL, Comment, REG_RANGE_COMMENT, REG_SZ, NULL, Flags, REG_RANGE_FLAGS, REG_DWORD, (LPVOID)(DEF_RANGE_FLAG_VAL), AllocCount, REG_RANGE_ALLOC, REG_DWORD, (LPVOID)(DEF_RANGE_ALLOC), MaxAllocCount, REG_RANGE_MAX_ALLOC, REG_DWORD, (LPVOID)(ULONG_PTR)(DEF_RANGE_MAX_ALLOC), StartAddress, REG_RANGE_START_ADDRESS, REG_DWORD, (LPVOID)0, EndAddress, REG_RANGE_END_ADDRESS, REG_DWORD, (LPVOID)0 }; DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); if( InUseClusters ) { Error = DhcpRegReadBinary(Hdl, REG_RANGE_INUSE_CLUSTERS, InUseClusters, InUseClusterSize); //Require(ERROR_SUCCESS == Error); //-- after registry changed, NO_SUCH_FILE could come up here as well. } if( UsedClusters ) { Error = DhcpRegReadBinary(Hdl, REG_RANGE_USED_CLUSTERS, UsedClusters, UsedClustersSize); //Require(ERROR_SUCCESS == Error); //-- after registry changed, NO_SUCH_FILE could come up here as well. } return ERROR_SUCCESS; } //BeginExport(function) DWORD DhcpRegReservationGetAttributes( IN PREG_HANDLE Hdl, OUT LPWSTR *Name, OUT LPWSTR *Comment, OUT DWORD *Flags, OUT DWORD *Address, OUT LPBYTE *ClientUID, OUT DWORD *ClientUIDSize ) //EndExport(function) { DWORD Error; DWORD deftype = DEF_RESERVATION_TYPE; ATTRIB_TBL Table[] = { Name, REG_RESERVATION_NAME, REG_SZ, NULL, Comment, REG_RESERVATION_COMMENT, REG_SZ, NULL, Flags, REG_RESERVATION_TYPE, REG_DWORD, ULongToPtr(deftype), Address, REG_RESERVATION_ADDRESS, REG_DWORD, (LPVOID)0, }; DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); if( ClientUID ) { Error = DhcpRegReadBinary(Hdl, REG_RESERVATION_UID, ClientUID, ClientUIDSize); Require(ERROR_SUCCESS == Error); } return ERROR_SUCCESS; } //BeginExport(function) DWORD DhcpRegOptGetAttributes( IN PREG_HANDLE Hdl, OUT DWORD *OptionId, OUT LPWSTR *ClassName, OUT LPWSTR *VendorName, OUT DWORD *Flags, OUT LPBYTE *Value, OUT DWORD *ValueSize ) //EndExport(function) { DWORD Error; ATTRIB_TBL Table[] = { OptionId, REG_OPTION_ID, REG_DWORD, (LPVOID)0, ClassName, REG_OPTION_CLASSNAME, REG_SZ, NULL, VendorName, REG_OPTION_VENDORNAME, REG_SZ, NULL, Flags, REG_OPTION_TYPE, REG_DWORD, (LPVOID)0, }; DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); if( Value ) { Error = DhcpRegReadBinary(Hdl, REG_OPTION_VALUE, Value, ValueSize); } return ERROR_SUCCESS; } //BeginExport(comment) //================================================================================ // the following functiosn help in writing to the registry //================================================================================ //EndExport(comment) typedef struct { LPVOID Value; DWORD Size; DWORD Type; LPWSTR ValueName; } WATTRIB_TBL, *PWATTRIB_TBL, *LPWATTRIB_TBL; DWORD DhcpRegSaveAttribTable( IN PREG_HANDLE Hdl, IN PWATTRIB_TBL Table, IN DWORD Size ) { DWORD i; DWORD Error; DWORD PtrSize; LPBYTE Ptr; for(i = 0; i < Size; i ++ ) { if( NULL == Table[i].Value ) continue; PtrSize = Table[i].Size; Ptr = *(LPBYTE *)Table[i].Value; switch(Table[i].Type) { case REG_SZ: if( NULL == *(LPWSTR *)Table[i].Value) { PtrSize = sizeof(WCHAR); Ptr = (LPBYTE)L""; break; } PtrSize = sizeof(WCHAR)*(wcslen(*((LPWSTR *)Table[i].Value))+1); Ptr = *(LPBYTE *)Table[i].Value; break; case REG_DWORD: PtrSize = sizeof(DWORD); Ptr = Table[i].Value; // This is because we deref this ptr down below.. break; } Error = RegSetValueEx( Hdl->Key, Table[i].ValueName, ZeroReserved, Table[i].Type, Ptr, PtrSize ); if( ERROR_SUCCESS != Error ) { return Error; } } return ERROR_SUCCESS; } //BeginExport(functions) DWORD DhcpRegSaveSubKeys( IN PREG_HANDLE Hdl, IN OUT PARRAY Array ) //EndExport(function) { ARRAY_LOCATION Loc; DWORD Error; REG_HANDLE Hdl2; LPWSTR KeyName; Error = MemArrayInitLoc(Array, &Loc); while(ERROR_FILE_NOT_FOUND != Error ) { Require(ERROR_SUCCESS == Error); Error = MemArrayGetElement(Array, &Loc, (LPVOID *)&KeyName); Require(ERROR_SUCCESS == Error && NULL != KeyName); Error = DhcpRegGetNextHdl(Hdl, KeyName, &Hdl2); if( ERROR_SUCCESS != Error ) return Error; Error = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == Error); Error = MemArrayNextLoc(Array, &Loc); } return ERROR_SUCCESS; } //BeginExport(functions) DWORD DhcpRegSaveSubKeysPrefixed( IN PREG_HANDLE Hdl, IN OUT PARRAY Array, IN LPWSTR CommonPrefix ) //EndExport(function) { ARRAY_LOCATION Loc; DWORD Error; REG_HANDLE Hdl2; LPWSTR KeyName; Error = MemArrayInitLoc(Array, &Loc); while(ERROR_FILE_NOT_FOUND != Error ) { Require(ERROR_SUCCESS == Error); Error = MemArrayGetElement(Array, &Loc, (LPVOID *)&KeyName); Require(ERROR_SUCCESS == Error && NULL != KeyName); Error = DhcpRegGetNextNextHdl(Hdl, CommonPrefix, KeyName, &Hdl2); if( ERROR_SUCCESS != Error ) return Error; Error = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == Error); Error = MemArrayNextLoc(Array, &Loc); } return ERROR_SUCCESS; } //BeginExport(function) DWORD DhcpRegServerSetList( IN PREG_HANDLE Hdl, IN PARRAY OptList, // list of LPWSTR options IN PARRAY OptDefList, // list of LPWSTR optdefs IN PARRAY Subnets, // list of LPWSTR subnets IN PARRAY SScopes, // list of LPWSTR sscopes IN PARRAY ClassDefs, // list of LPWSTR classes IN PARRAY MScopes // list of LPWSTR mscopes ) //EndExport(function) { DWORD Error; DWORD LocalError; DWORD Index; REG_HANDLE Hdl2; struct { PARRAY Array; LPWSTR Location; } Table[] = { OptList, REG_SERVER_GLOBAL_OPTIONS, OptDefList, REG_SERVER_OPTDEFS, Subnets, REG_SERVER_SUBNETS, SScopes, REG_SERVER_SSCOPES, ClassDefs, REG_SERVER_CLASSDEFS, MScopes, REG_SERVER_MSCOPES }; for( Index = 0; Index < sizeof(Table)/sizeof(Table[0]); Index ++ ) { if( NULL == Table[Index].Array ) continue; Error = DhcpRegGetNextHdl(Hdl, Table[Index].Location, &Hdl2); if( ERROR_SUCCESS != Error ) return Error; Error = DhcpRegSaveSubKeys(&Hdl2, Table[Index].Array); LocalError = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == LocalError); if( ERROR_SUCCESS != Error ) return Error; } return Error; } //BeginExport(function) DWORD DhcpRegSubnetSetExclusions( IN PREG_HANDLE Hdl, IN LPBYTE *Excl, IN DWORD ExclSize ) //EndExport(function) { DWORD Error; WATTRIB_TBL Table[] = { (LPVOID*)Excl, ExclSize, REG_BINARY, REG_SUBNET_EXCL, }; return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); } //BeginExport(function) DWORD DhcpRegSubnetSetList( IN PREG_HANDLE Hdl, IN PARRAY Servers, IN PARRAY IpRanges, IN PARRAY Reservations, IN PARRAY Options, IN LPBYTE *Excl, IN DWORD ExclSizeInBytes ) //EndExport(function) { DWORD Error; DWORD LocalError; DWORD Index; REG_HANDLE Hdl2; struct { PARRAY Array; LPWSTR Location; } Table[] = { Servers, REG_SUBNET_SERVERS, IpRanges, REG_SUBNET_RANGES, Reservations, REG_SUBNET_RESERVATIONS, Options, REG_SUBNET_OPTIONS, // Exclusions are to be handled a bit differently }; for( Index = 0; Index < sizeof(Table)/sizeof(Table[0]); Index ++ ) { if( NULL == Table[Index].Array ) continue; Error = DhcpRegGetNextHdl(Hdl, Table[Index].Location, &Hdl2); if( ERROR_SUCCESS != Error ) return Error; Error = DhcpRegSaveSubKeys(&Hdl2, Table[Index].Array); LocalError = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == LocalError); if( ERROR_SUCCESS != Error ) return Error; } // Now read the exclusions from off here return DhcpRegSubnetSetExclusions(Hdl, Excl, ExclSizeInBytes ); } //BeginExport(function) DWORD DhcpRegSScopeSetList( IN PREG_HANDLE Hdl, IN OUT PARRAY Subnets ) //EndExport(function) { return DhcpRegSaveSubKeys(Hdl, Subnets); } //BeginExport(function) DWORD DhcpRegReservationSetList( IN PREG_HANDLE Hdl, IN PARRAY Subnets ) //EndExport(function) { return DhcpRegSaveSubKeys(Hdl, Subnets); } //BeginExport(comment) //================================================================================ // the single stuff are here -- these are not list stuff, but just simple // single valued attributes // some of these actually, dont even go to the registry, but that's fine alright? //================================================================================ //EndExport(comment) //BeginExport(function) DWORD DhcpRegServerSetAttributes( IN PREG_HANDLE Hdl, IN LPWSTR *Name, IN LPWSTR *Comment, IN DWORD *Flags // more attributes will come here soon? ) //EndExport(function) { #if 0 WATTRIB_TBL Table[] = { Name, REG_SERVER_NAME } if( Name ) *Name = NULL; if( Comment ) *Comment = NULL; if( Flags ) *Flags = 0; #endif return ERROR_SUCCESS; } DWORD DhcpRegSubnetSetAttributesInternal( IN PREG_HANDLE Hdl, IN LPWSTR *Name, IN LPWSTR *Comment, IN DWORD *Flags, IN DWORD *Address, IN DWORD *Mask, IN DWORD *SwitchedNetwork ) { DWORD Error, SrvIpAddress, SrvRole; LPWSTR EmptyString; REG_HANDLE Hdl2; WATTRIB_TBL Table[] = { Name, 0, REG_SZ, REG_SUBNET_NAME, Comment, 0, REG_SZ, REG_SUBNET_COMMENT, Flags, 0, REG_DWORD, REG_SUBNET_STATE, Address, 0, REG_DWORD, REG_SUBNET_ADDRESS, Mask, 0, REG_DWORD, REG_SUBNET_MASK, SwitchedNetwork, 0, REG_DWORD, REG_SUBNET_SWITCHED_FLAG }; Error = DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); if( NO_ERROR != Error ) return Error; // // The following lines are for backward compat with NT4. // // // Create the reservation key in any case // Error = DhcpRegGetNextHdl( Hdl, REG_SUBNET_RESERVATIONS, &Hdl2 ); if( NO_ERROR != Error ) return Error; DhcpRegCloseHdl( &Hdl2 ); // // Create the servers key // Error = DhcpRegGetNextHdl( Hdl, L"DHCPServers", &Hdl2 ); if( NO_ERROR != Error ) return Error; DhcpRegCloseHdl( &Hdl2 ); Error = DhcpRegGetNextNextHdl( Hdl, L"DHCPServers", L"127.0.0.1", &Hdl2 ); if( NO_ERROR != Error ) return Error; // // Now set the role of the newly created server as primary // SrvIpAddress = INADDR_LOOPBACK; SrvRole = 1; // primary EmptyString = L""; { WATTRIB_TBL SrvTable[] = { &SrvRole, 0, REG_DWORD, L"Role", &SrvIpAddress, 0, REG_DWORD, L"ServerIpAddress", &EmptyString, 0, REG_SZ, L"ServerHostName", &EmptyString, 0, REG_SZ, L"ServerNetBiosName" }; Error = DhcpRegSaveAttribTable( &Hdl2, SrvTable, sizeof(SrvTable)/sizeof(SrvTable[0])); } DhcpRegCloseHdl(&Hdl2); return Error; } //BeginExport(function) DWORD DhcpRegSubnetSetAttributes( IN PREG_HANDLE Hdl, IN LPWSTR *Name, IN LPWSTR *Comment, IN DWORD *Flags, IN DWORD *Address, IN DWORD *Mask ) //EndExport(function) { DWORD xFlags, SwitchedNetwork = FALSE; OSVERSIONINFO Ver; Ver.dwOSVersionInfoSize = sizeof(Ver); if( FALSE == GetVersionEx(&Ver) ) return GetLastError(); if( Flags && Ver.dwMajorVersion < 5 ) { SwitchedNetwork = IS_SWITCHED(*Flags); xFlags = IS_DISABLED(*Flags); Flags = &xFlags; } return DhcpRegSubnetSetAttributesInternal( Hdl, Name, Comment, Flags, Address, Mask, Flags ? &SwitchedNetwork : NULL ); } //BeginExport(function) DWORD DhcpRegMScopeSetAttributes( IN PREG_HANDLE Hdl, IN LPWSTR *Comments, IN DWORD *State, IN DWORD *ScopeId, IN DWORD *Policy, IN DWORD *TTL, IN LPWSTR *LangTag, IN PDATE_TIME *ExpiryTime ) //EndExport(function) { WATTRIB_TBL Table[] = { Comments, 0, REG_SZ, REG_MSCOPE_COMMENT, State, 0, REG_DWORD, REG_MSCOPE_STATE, ScopeId, 0, REG_DWORD, REG_MSCOPE_SCOPEID, Policy, 0, REG_DWORD, REG_MSCOPE_ADDR_POLICY, TTL, 0, REG_DWORD, REG_MSCOPE_TTL, LangTag, 0, REG_SZ, REG_MSCOPE_LANG_TAG, ExpiryTime, sizeof(**ExpiryTime), REG_BINARY, REG_MSCOPE_EXPIRY_TIME }; return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); } //BeginExport(function) DWORD DhcpRegOptDefSetAttributes( IN PREG_HANDLE Hdl, IN LPWSTR *Name, IN LPWSTR *Comments, IN DWORD *Flags, IN DWORD *OptionId, IN LPWSTR *ClassName, IN LPWSTR *VendorName, IN LPBYTE *Value, IN DWORD ValueSize ) //EndExport(function) { DWORD Error; WATTRIB_TBL Table[] = { Name, 0, REG_SZ, REG_OPTION_NAME, Comments, 0, REG_SZ, REG_OPTION_COMMENT, ClassName, 0, REG_SZ, REG_OPTION_CLASSNAME, VendorName, 0, REG_SZ, REG_OPTION_VENDORNAME, Flags, 0, REG_DWORD, REG_OPTION_TYPE, OptionId, 0, REG_DWORD, REG_OPTION_ID, Value, ValueSize,REG_BINARY, REG_OPTION_VALUE }; return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); } //BeginExport(function) DWORD DhcpRegSScopeSetAttributes( // superscopes dont have any information stored.. dont use this IN PREG_HANDLE Hdl, IN LPWSTR *Name, IN LPWSTR *Comment, IN DWORD *Flags ) //EndExport(function) { Require(FALSE); return ERROR_INVALID_PARAMETER; } //BeginExport(function) DWORD DhcpRegClassDefSetAttributes( IN PREG_HANDLE Hdl, IN LPWSTR *Name, IN LPWSTR *Comment, IN DWORD *Flags, IN LPBYTE *Value, IN DWORD ValueSize ) //EndExport(function) { DWORD Error; WATTRIB_TBL Table[] = { Name, 0, REG_SZ, REG_CLASSDEF_NAME, Comment, 0, REG_SZ, REG_CLASSDEF_COMMENT, Flags, 0, REG_DWORD, REG_CLASSDEF_TYPE, Value, ValueSize,REG_BINARY, REG_CLASSDEF_VALUE }; return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); } //BeginExport(function) DWORD DhcpRegSubnetServerSetAttributes( IN PREG_HANDLE Hdl, IN LPWSTR *Name, IN LPWSTR *Comment, IN DWORD *Flags, IN DWORD *Address, IN DWORD *Role ) //EndExport(function) { WATTRIB_TBL Table[] = { Name, 0, REG_SZ, REG_SUB_SERVER_NAME, Comment, 0, REG_SZ, REG_SUB_SERVER_COMMENT, Flags, 0, REG_DWORD, REG_FLAGS, Address, 0, REG_DWORD, REG_SUB_SERVER_ADDRESS, Role, 0, REG_DWORD, REG_SUB_SERVER_ROLE, }; return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); } //BeginExport(function) DWORD DhcpRegRangeSetAttributes( IN PREG_HANDLE Hdl, IN LPWSTR *Name, IN LPWSTR *Comment, IN DWORD *Flags, IN ULONG *AllocCount, IN ULONG *MaxAllocCount, IN DWORD *StartAddress, IN DWORD *EndAddress, IN LPBYTE *InUseClusters, IN DWORD InUseClusterSize, IN LPBYTE *UsedClusters, IN DWORD UsedClustersSize ) //EndExport(function) { DWORD Error; WATTRIB_TBL Table[] = { Name, 0, REG_SZ, REG_RANGE_NAME, Comment, 0, REG_SZ, REG_RANGE_COMMENT, Flags, 0, REG_DWORD, REG_RANGE_FLAGS, AllocCount, 0, REG_DWORD, REG_RANGE_ALLOC, MaxAllocCount, 0, REG_DWORD, REG_RANGE_MAX_ALLOC, StartAddress, 0, REG_DWORD, REG_RANGE_START_ADDRESS, EndAddress, 0, REG_DWORD, REG_RANGE_END_ADDRESS, InUseClusters, InUseClusterSize, REG_BINARY, REG_RANGE_INUSE_CLUSTERS, UsedClusters, UsedClustersSize, REG_BINARY, REG_RANGE_USED_CLUSTERS, }; return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); } //BeginExport(function) DWORD DhcpRegReservationSetAttributes( IN PREG_HANDLE Hdl, IN LPWSTR *Name, IN LPWSTR *Comment, IN DWORD *Flags, IN DWORD *Address, IN LPBYTE *ClientUID, IN DWORD ClientUIDSize ) //EndExport(function) { DWORD Error; WATTRIB_TBL Table[] = { Name, 0, REG_SZ, REG_RESERVATION_NAME, Comment, 0, REG_SZ, REG_RESERVATION_COMMENT, Flags, 0, REG_DWORD, REG_RESERVATION_TYPE, Address, 0, REG_DWORD, REG_RESERVATION_ADDRESS, ClientUID, ClientUIDSize, REG_BINARY, REG_RESERVATION_UID, }; return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); } //BeginExport(function) DWORD DhcpRegOptSetAttributes( IN PREG_HANDLE Hdl, IN DWORD *OptionId, IN LPWSTR *ClassName, IN LPWSTR *VendorName, IN DWORD *Flags, IN LPBYTE *Value, IN DWORD ValueSize ) //EndExport(function) { DWORD Error; WATTRIB_TBL Table[] = { OptionId, 0, REG_DWORD, REG_OPTION_ID, ClassName, 0, REG_SZ, REG_OPTION_CLASSNAME, VendorName, 0, REG_SZ, REG_OPTION_VENDORNAME, Flags, 0, REG_DWORD, REG_OPTION_TYPE, Value, ValueSize,REG_BINARY, REG_OPTION_VALUE, }; return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0])); } //================================================================================ // recursive deleting of keys... //================================================================================ //BeginExport(function) DWORD DhcpRegRecurseDelete( IN PREG_HANDLE Hdl, IN LPWSTR KeyName ) //EndExport(function) { REG_HANDLE Hdl2; DWORD Error; DWORD LocalError, RetError; ARRAY Array; // sub keys ARRAY_LOCATION Loc; LPWSTR SubKey; RetError = ERROR_SUCCESS; Error = DhcpRegGetNextHdl(Hdl, KeyName, &Hdl2); if( ERROR_SUCCESS != Error ) return Error; Error = MemArrayInit(&Array); if( ERROR_SUCCESS != Error ) { LocalError = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == LocalError); return Error; } Error = DhcpRegFillSubKeys(&Hdl2, &Array); Require( ERROR_SUCCESS == Error ); Error = MemArrayInitLoc(&Array, &Loc); while(ERROR_FILE_NOT_FOUND != Error) { Require(ERROR_SUCCESS == Error); Error = MemArrayGetElement(&Array, &Loc, (LPVOID *)&SubKey); Require(ERROR_SUCCESS == Error && SubKey); Error = DhcpRegRecurseDelete(&Hdl2, SubKey); if( ERROR_SUCCESS != Error ) RetError = Error; if( SubKey ) MemFree(SubKey); Error = MemArrayNextLoc(&Array, &Loc); } Error = MemArrayCleanup(&Array); Require(ERROR_SUCCESS == Error); Error = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == Error); Error = RegDeleteKey(Hdl->Key, KeyName); if( ERROR_SUCCESS != Error ) RetError = Error; return RetError; } //BeginExport(function) DWORD DhcpRegRecurseDeleteBunch( IN PREG_HANDLE Hdl, IN PARRAY KeysArray ) //EndExport(function) { ARRAY_LOCATION Loc; LPWSTR ThisKeyName; DWORD Error; Error = MemArrayInitLoc(KeysArray, &Loc); while( ERROR_FILE_NOT_FOUND != Error ) { Require(ERROR_SUCCESS == Error); Error = MemArrayGetElement(KeysArray, &Loc, &ThisKeyName); Require(ERROR_SUCCESS == Error && NULL != ThisKeyName); Error = DhcpRegRecurseDelete(Hdl, ThisKeyName); if( ERROR_SUCCESS != Error ) return Error; Error = MemArrayNextLoc(KeysArray, &Loc); } return ERROR_SUCCESS; } static VOID GetLocalFileTime( // fill in filetime struct w/ current local time IN OUT LPFILETIME Time // struct to fill in ) { BOOL Status; SYSTEMTIME SysTime; GetSystemTime(&SysTime); // get sys time as UTC time. Status = SystemTimeToFileTime(&SysTime,Time); // conver system time to file time if( FALSE == Status ) { // convert failed? Time->dwLowDateTime = 0xFFFFFFFF; // set time to weird value in case of failiure Time->dwHighDateTime = 0xFFFFFFFF; } } //BeginExport(function) DWORD DhcpRegUpdateTime( // update the last modified time VOID ) //EndExport(function) { FILETIME Time; DWORD Err, Size; HKEY hKey; GetLocalFileTime(&Time); // first get current time (*(LONGLONG *)&Time) += 10*1000*60*2; // 2 minutes (Filetime is in 100-nano seconds) // HACK! the previous line is there as the DS takes a little while to update the // last changed time.. Time.dwLowDateTime =Time.dwHighDateTime =0; // set time to "long back" initially Err = RegOpenKeyEx // try to open the config key. ( /* hKey */ HKEY_LOCAL_MACHINE, /* lpSubKey */ REG_THIS_SERVER, /* ulOptions */ 0 /* Reserved */ , /* samDesired */ KEY_ALL_ACCESS, /* phkResult */ &hKey ); if( ERROR_SUCCESS != Err ) return Err; // time is still set to ages back Err = RegSetValueEx // now save the time value ( /* hKey */ hKey, /* lpValueName */ DHCP_LAST_DOWNLOAD_TIME_VALUE, /* lpReserved */ 0, /* lpType */ REG_BINARY, /* lpData */ (LPBYTE)&Time, /* lpcData */ sizeof(Time) ); RegCloseKey(hKey); // close key before we forget return Err; } //================================================================================ // end of file //================================================================================