Source code of Windows XP (NT5)
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.

1789 lines
59 KiB

  1. //================================================================================
  2. // Copyright (C) 1997 Microsoft Corporation
  3. // Author: RameshV
  4. // Description: simple registry utilities
  5. //================================================================================
  6. #include <mmregpch.h>
  7. //BeginExport(typedef)
  8. typedef struct _REG_HANDLE {
  9. HKEY Key;
  10. HKEY SubKey;
  11. LPWSTR SubKeyLocation;
  12. } REG_HANDLE, *PREG_HANDLE, *LPREG_HANDLE;
  13. //EndExport(typedef)
  14. //BeginExport(constants)
  15. #define REG_THIS_SERVER L"Software\\Microsoft\\DHCPServer\\Configuration"
  16. #define REG_THIS_SERVER_DS L"Software\\Microsoft\\DHCPServer\\Config_DS"
  17. #define REG_THIS_SERVER_DS_VALUE L"Config_DS"
  18. #define REG_THIS_SERVER_DS_PARENT L"Software\\Microsoft\\DHCPServer"
  19. #define REG_SERVER_GLOBAL_OPTIONS L"GlobalOptionValues"
  20. #define REG_SERVER_OPTDEFS L"OptionInfo"
  21. #define REG_SERVER_SUBNETS L"Subnets"
  22. #define REG_SERVER_SSCOPES L"SuperScope"
  23. #define REG_SERVER_CLASSDEFS L"ClassDefs"
  24. #define REG_SERVER_MSCOPES L"MulticastScopes"
  25. #define REG_SUBNET_SERVERS L"DHCPServers"
  26. #define REG_SUBNET_RANGES L"IpRanges"
  27. #define REG_SUBNET_RESERVATIONS L"ReservedIps"
  28. #define REG_SUBNET_OPTIONS L"SubnetOptions"
  29. #define REG_SUBNET_EXCL L"ExcludedIpRanges"
  30. #define REG_SUBNET_ADDRESS L"SubnetAddress"
  31. #define REG_SUBNET_NAME L"SubnetName"
  32. #define REG_SUBNET_COMMENT L"SubnetComment"
  33. #define REG_SUBNET_MASK L"SubnetMask"
  34. #define REG_SUBNET_STATE L"SubnetState"
  35. #define REG_SUBNET_SWITCHED_FLAG L"SwitchedNetworkFlag"
  36. #define REG_MSCOPE_NAME L"MScopeName"
  37. #define REG_MSCOPE_COMMENT L"MScopeComment"
  38. //
  39. // Win2K Beta2 and Beta3 went out with scope id param value MScopeId.
  40. // Since their meaning is being changed, to avoid any costly upgrade
  41. // code, this value is being changed to MScopeIdValue: to automatically
  42. // chose a good scope id, TTL values. Note that the default value of
  43. // zero is treated specially for this scope id param. It implies that
  44. // this was probably a pre-RC1 upgrade. In this case, the Scope ID
  45. // defaults to first value in the range.
  46. //
  47. #define REG_MSCOPE_SCOPEID L"MScopeIdValue"
  48. #define REG_MSCOPE_STATE L"MScopeState"
  49. #define REG_MSCOPE_ADDR_POLICY L"MScopeAddressPolicy"
  50. #define REG_MSCOPE_TTL L"MScopeTTL"
  51. #define REG_MSCOPE_LANG_TAG L"MScopeLangTag"
  52. #define REG_MSCOPE_EXPIRY_TIME L"MScopeExpiryTime"
  53. #define REG_SUB_SERVER_NAME L"ServerHostName"
  54. #define REG_SUB_SERVER_COMMENT L"ServerComment"
  55. #define REG_SUB_SERVER_ADDRESS L"ServerAddress"
  56. #define REG_SUB_SERVER_ROLE L"Role"
  57. #define REG_RANGE_NAME L"RangeName"
  58. #define REG_RANGE_COMMENT L"RangeComment"
  59. #define REG_RANGE_START_ADDRESS L"StartAddress"
  60. #define REG_RANGE_END_ADDRESS L"EndAddress"
  61. #define REG_RANGE_INUSE_CLUSTERS L"InUseClusters"
  62. #define REG_RANGE_USED_CLUSTERS L"UsedClusters"
  63. #define REG_RANGE_BITS_PREFIX L"Bits "
  64. #define REG_RANGE_BITS_PREFIX_WCHAR_COUNT (5)
  65. #define REG_RANGE_FLAGS L"RangeFlags"
  66. #define REG_RANGE_ALLOC L"RangeBootpAllocated"
  67. #define REG_RANGE_MAX_ALLOC L"RangeBootpMaxAllowed"
  68. #define REG_OPTION_NAME L"OptionName"
  69. #define REG_OPTION_COMMENT L"OptionComment"
  70. #define REG_OPTION_TYPE L"OptionType"
  71. #define REG_OPTION_VALUE L"OptionValue"
  72. #define REG_OPTION_ID L"OptionId"
  73. #define REG_OPTION_CLASSNAME L"OptionClassName"
  74. #define REG_OPTION_VENDORNAME L"OptionVendorName"
  75. #define REG_CLASSDEF_NAME L"ClassName"
  76. #define REG_CLASSDEF_COMMENT L"ClassComment"
  77. #define REG_CLASSDEF_TYPE L"ClassType"
  78. #define REG_CLASSDEF_VALUE L"ClassValue"
  79. #define REG_RESERVATION_ADDRESS L"IpAddress"
  80. #define REG_RESERVATION_UID L"ClientUID"
  81. #define REG_RESERVATION_TYPE L"AllowedClientTypes"
  82. #define REG_RESERVATION_NAME L"ReservationName"
  83. #define REG_RESERVATION_COMMENT L"ReservationComment"
  84. #define REG_FLAGS L"Flags"
  85. #define REG_ACCESS KEY_ALL_ACCESS
  86. #define REG_DEFAULT_SUBNET_STATE 0
  87. #define REG_DEFAULT_SUBNET_MASK 0xFFFFFFFF
  88. #define REG_DEFAULT_SWITCHED_FLAG FALSE
  89. #define REG_CLASS L"DhcpClass"
  90. #define DHCP_LAST_DOWNLOAD_TIME_VALUE L"LastDownloadTime"
  91. #define DHCP_LAST_DOWNLOAD_TIME_TYPE REG_BINARY
  92. #define DEF_RANGE_ALLOC 0
  93. #define DEF_RANGE_MAX_ALLOC (~(ULONG)0)
  94. //EndExport(constants)
  95. const DWORD ZeroReserved = 0;
  96. const LPVOID NullReserved = 0;
  97. #define MAX_KEY_SIZE 512
  98. #define DEF_RANGE_FLAG_VAL (MM_FLAG_ALLOW_DHCP)
  99. #define DEF_RESERVATION_TYPE (MM_FLAG_ALLOW_DHCP|MM_FLAG_ALLOW_BOOTP)
  100. //BeginExport(comment)
  101. //================================================================================
  102. // The basic open/traverse/close functions are here
  103. //================================================================================
  104. //EndExport(comment)
  105. HKEY CurrentServerKey = NULL;
  106. //BeginExport(function)
  107. DWORD
  108. DhcpRegSetCurrentServer(
  109. IN OUT PREG_HANDLE Hdl
  110. ) //EndExport(function)
  111. {
  112. CurrentServerKey = Hdl? Hdl->Key : NULL;
  113. return ERROR_SUCCESS;
  114. }
  115. //BeginExport(function)
  116. DWORD
  117. DhcpRegGetThisServer(
  118. IN OUT PREG_HANDLE Hdl
  119. ) //EndExport(function)
  120. {
  121. DWORD Disposition;
  122. if( NULL != CurrentServerKey ) {
  123. return RegOpenKeyEx( // duplicate key
  124. CurrentServerKey,
  125. NULL,
  126. ZeroReserved,
  127. REG_ACCESS,
  128. &Hdl->Key
  129. );
  130. }
  131. return RegCreateKeyEx(
  132. HKEY_LOCAL_MACHINE,
  133. REG_THIS_SERVER,
  134. ZeroReserved,
  135. REG_CLASS,
  136. REG_OPTION_NON_VOLATILE,
  137. REG_ACCESS,
  138. NULL,
  139. &Hdl->Key,
  140. &Disposition
  141. );
  142. }
  143. //BeginExport(function)
  144. DWORD
  145. DhcpRegGetNextHdl(
  146. IN PREG_HANDLE Hdl,
  147. IN LPWSTR NextLoc,
  148. OUT PREG_HANDLE OutHdl
  149. ) //EndExport(function)
  150. {
  151. DWORD Disposition;
  152. DWORD Error;
  153. Error = RegCreateKeyEx(
  154. Hdl->Key,
  155. NextLoc,
  156. ZeroReserved,
  157. REG_CLASS,
  158. REG_OPTION_NON_VOLATILE,
  159. REG_ACCESS,
  160. NULL,
  161. &OutHdl->Key,
  162. &Disposition
  163. );
  164. return Error;
  165. }
  166. //BeginExport(function)
  167. DWORD
  168. DhcpRegCloseHdl(
  169. IN OUT PREG_HANDLE Hdl
  170. ) //EndExport(function)
  171. {
  172. DWORD Error;
  173. Error = RegCloseKey(Hdl->Key);
  174. Hdl->Key = NULL;
  175. return Error;
  176. }
  177. //BeginExport(comment)
  178. //================================================================================
  179. // MISC utilities for registry manipulation
  180. //================================================================================
  181. //EndExport(comment)
  182. //BeginExport(function)
  183. DWORD
  184. DhcpRegFillSubKeys(
  185. IN PREG_HANDLE Hdl,
  186. IN OUT PARRAY Array // fill in a list of key names
  187. ) //EndExport(function)
  188. {
  189. DWORD Error;
  190. DWORD Index;
  191. DWORD Size;
  192. WCHAR KeyName[MAX_KEY_SIZE];
  193. LPWSTR ThisKeyName;
  194. Index = 0;
  195. do {
  196. Size = sizeof(KeyName)/sizeof(KeyName[0]);
  197. Error = RegEnumKeyEx(
  198. Hdl->Key,
  199. Index++,
  200. KeyName,
  201. &Size,
  202. NullReserved,
  203. NULL,
  204. NULL,
  205. NULL
  206. );
  207. if( ERROR_NO_MORE_ITEMS == Error ) {
  208. Error = ERROR_SUCCESS;
  209. break;
  210. }
  211. if( ERROR_SUCCESS != Error ) break;
  212. Require(0 != Size);
  213. Size += 1; // for the terminating L'\0' char
  214. Size *= sizeof(WCHAR); // looks like the units are WCHAR!!
  215. ThisKeyName = MemAlloc(Size);
  216. if( NULL == ThisKeyName ) return ERROR_NOT_ENOUGH_MEMORY;
  217. wcscpy(ThisKeyName, KeyName);
  218. Error = MemArrayAddElement(Array, (LPVOID)ThisKeyName);
  219. if( ERROR_SUCCESS != Error ) {
  220. MemFree(ThisKeyName);
  221. }
  222. } while( ERROR_SUCCESS == Error );
  223. Require(ERROR_MORE_DATA != Error);
  224. return Index? ERROR_SUCCESS : Error; // if we added something, dont bother about reporting error
  225. }
  226. //BeginExport(function)
  227. LPVOID // DWORD or LPWSTR or LPBYTE
  228. DhcpRegRead( // read differnt values from registry and allocate if not DWORD
  229. IN PREG_HANDLE Hdl,
  230. IN DWORD Type, // if DWORD dont allocate memory
  231. IN LPWSTR ValueName,
  232. IN LPVOID RetValue // value to use if nothing found
  233. ) //EndExport(function)
  234. {
  235. DWORD Error;
  236. DWORD Size;
  237. DWORD Dword;
  238. LPVOID Ret;
  239. if( REG_DWORD == Type ) {
  240. Size = sizeof(DWORD);
  241. Ret = (LPVOID)&Dword;
  242. } else {
  243. Size = 0;
  244. Error = RegQueryValueEx(
  245. Hdl->Key,
  246. ValueName,
  247. NullReserved,
  248. NULL,
  249. NULL,
  250. &Size
  251. );
  252. if( ERROR_SUCCESS != Error ) return RetValue;
  253. if (Size == 0) return RetValue; // MemAlloc does not check the size!
  254. Ret = MemAlloc(Size);
  255. if( NULL == Ret ) return RetValue; // should not really happen
  256. }
  257. Error = RegQueryValueEx(
  258. Hdl->Key,
  259. ValueName,
  260. NullReserved,
  261. NULL,
  262. Ret,
  263. &Size
  264. );
  265. if( ERROR_SUCCESS != Error && Ret != (LPVOID)&Dword ) {
  266. MemFree(Ret);
  267. Ret = NULL;
  268. }
  269. if( ERROR_SUCCESS != Error) return RetValue;
  270. if( Ret == (LPVOID)&Dword ) {
  271. return ULongToPtr(Dword);
  272. } else {
  273. return Ret;
  274. }
  275. }
  276. //BeginExport(function)
  277. DWORD
  278. DhcpRegReadBinary( // read binary type
  279. IN PREG_HANDLE Hdl,
  280. IN LPWSTR ValueName,
  281. OUT LPBYTE *RetVal,
  282. OUT DWORD *RetValSize
  283. ) //EndExport(function)
  284. {
  285. DWORD Error;
  286. DWORD Size;
  287. LPVOID Ret;
  288. *RetVal = NULL;
  289. *RetValSize = 0;
  290. Size = 0;
  291. Error = RegQueryValueEx(
  292. Hdl->Key,
  293. ValueName,
  294. NullReserved,
  295. NULL,
  296. NULL,
  297. &Size
  298. );
  299. if( ERROR_SUCCESS != Error ) return Error;
  300. if( 0 == Size ) return ERROR_SUCCESS;
  301. Ret = MemAlloc(Size);
  302. if( NULL == Ret ) return ERROR_NOT_ENOUGH_MEMORY;
  303. Error = RegQueryValueEx(
  304. Hdl->Key,
  305. ValueName,
  306. NullReserved,
  307. NULL,
  308. Ret,
  309. &Size
  310. );
  311. if( ERROR_SUCCESS != Error ) {
  312. MemFree(Ret);
  313. return Error;
  314. }
  315. *RetVal = Ret;
  316. *RetValSize = Size;
  317. return ERROR_SUCCESS;
  318. }
  319. //BeginExport(function)
  320. LPWSTR
  321. DhcpRegCombineClassAndOption( // create string based on class name and option id
  322. IN LPWSTR ClassName,
  323. IN LPWSTR VendorName,
  324. IN DWORD OptionId
  325. ) //EndExport(function)
  326. {
  327. DWORD Size;
  328. LPWSTR Ptr;
  329. if( NULL == VendorName && NULL == ClassName ) {
  330. //
  331. // Special case usual options for downward compatability with older
  332. // options.. (NT4 options in registry don't have any "!" in them.
  333. //
  334. Ptr = MemAlloc( 4 * sizeof(WCHAR) );
  335. if( NULL == Ptr ) return NULL;
  336. Ptr [2] = L'0' + (BYTE)(OptionId %10); OptionId /= 10;
  337. Ptr [1] = L'0' + (BYTE)(OptionId %10); OptionId /= 10;
  338. Ptr [0] = L'0' + (BYTE)(OptionId %10);
  339. Ptr [3] = L'\0';
  340. return Ptr;
  341. }
  342. if( NULL == VendorName ) VendorName = L"";
  343. if( NULL == ClassName ) ClassName = L"";
  344. Size = (wcslen(ClassName) + 1 + 5)*sizeof(WCHAR);
  345. Size += wcslen(VendorName)*sizeof(WCHAR);
  346. Ptr = MemAlloc(Size);
  347. if( NULL == Ptr ) return NULL;
  348. Size = 0;
  349. Ptr[2+Size] = L'0' + (BYTE)(OptionId % 10); OptionId /= 10;
  350. Ptr[1+Size] = L'0' + (BYTE)(OptionId % 10); OptionId /= 10;
  351. Ptr[0+Size] = L'0' + (BYTE)(OptionId % 10);
  352. Ptr[3+Size] = L'\0';
  353. wcscat(Ptr, L"!");
  354. wcscat(Ptr, VendorName);
  355. wcscat(Ptr, L"!");
  356. wcscat(Ptr, ClassName);
  357. return Ptr;
  358. }
  359. //BeginExport(function)
  360. LPWSTR
  361. ConvertAddressToLPWSTR(
  362. IN DWORD Address,
  363. IN OUT LPWSTR BufferStr // input buffer to fill with dotted notation
  364. ) //EndExport(function)
  365. {
  366. LPSTR AddressStr;
  367. DWORD Count;
  368. Address = ntohl(Address);
  369. AddressStr = inet_ntoa(*(struct in_addr *)&Address);
  370. Count = mbstowcs(BufferStr, AddressStr, sizeof("000.000.000.000"));
  371. if( -1 == Count ) return NULL;
  372. return BufferStr;
  373. }
  374. //BeginExport(comment)
  375. //================================================================================
  376. // the following functions help traversing the registry
  377. //================================================================================
  378. //EndExport(comment)
  379. DWORD
  380. DhcpRegGetNextNextHdl(
  381. IN PREG_HANDLE Hdl,
  382. IN LPWSTR Loc1,
  383. IN LPWSTR Loc2,
  384. OUT PREG_HANDLE Hdl2
  385. )
  386. {
  387. WCHAR Loc[MAX_KEY_SIZE*2];
  388. Loc[ 0 ] = L'\0';
  389. if ( ( wcslen(Loc1) + wcslen(Loc2) + 1 ) < ( MAX_KEY_SIZE * 2 ) )
  390. {
  391. wcscpy(Loc,Loc1);
  392. wcscat(Loc, L"\\");
  393. wcscat(Loc,Loc2);
  394. }
  395. return DhcpRegGetNextHdl(Hdl, Loc, Hdl2);
  396. }
  397. //BeginExport(function)
  398. DWORD
  399. DhcpRegServerGetSubnetHdl(
  400. IN PREG_HANDLE Hdl,
  401. IN LPWSTR Subnet,
  402. OUT PREG_HANDLE Hdl2
  403. ) //EndExport(function)
  404. {
  405. return DhcpRegGetNextNextHdl(Hdl, REG_SERVER_SUBNETS, Subnet, Hdl2);
  406. }
  407. //BeginExport(function)
  408. DWORD
  409. DhcpRegServerGetSScopeHdl(
  410. IN PREG_HANDLE Hdl,
  411. IN LPWSTR SScope,
  412. OUT PREG_HANDLE Hdl2
  413. ) //EndExport(function)
  414. {
  415. return DhcpRegGetNextNextHdl(Hdl, REG_SERVER_SSCOPES, SScope, Hdl2);
  416. }
  417. //BeginExport(function)
  418. DWORD
  419. DhcpRegServerGetOptDefHdl(
  420. IN PREG_HANDLE Hdl,
  421. IN LPWSTR OptDef,
  422. OUT PREG_HANDLE Hdl2
  423. ) //EndExport(function)
  424. {
  425. return DhcpRegGetNextNextHdl(Hdl, REG_SERVER_OPTDEFS, OptDef, Hdl2);
  426. }
  427. //BeginExport(function)
  428. DWORD
  429. DhcpRegServerGetOptHdl(
  430. IN PREG_HANDLE Hdl,
  431. IN LPWSTR Opt,
  432. OUT PREG_HANDLE Hdl2
  433. ) //EndExport(function)
  434. {
  435. return DhcpRegGetNextNextHdl(Hdl, REG_SERVER_GLOBAL_OPTIONS, Opt, Hdl2);
  436. }
  437. //BeginExport(function)
  438. DWORD
  439. DhcpRegServerGetMScopeHdl(
  440. IN PREG_HANDLE Hdl,
  441. IN LPWSTR MScope,
  442. OUT PREG_HANDLE Hdl2
  443. ) //EndExport(function)
  444. {
  445. return DhcpRegGetNextNextHdl(Hdl, REG_SERVER_MSCOPES, MScope, Hdl2);
  446. }
  447. //BeginExport(function)
  448. DWORD
  449. DhcpRegServerGetClassDefHdl(
  450. IN PREG_HANDLE Hdl,
  451. IN LPWSTR ClassDef,
  452. OUT PREG_HANDLE Hdl2
  453. ) //EndExport(function)
  454. {
  455. return DhcpRegGetNextNextHdl(Hdl, REG_SERVER_CLASSDEFS, ClassDef, Hdl2);
  456. }
  457. //BeginExport(function)
  458. DWORD
  459. DhcpRegSubnetGetOptHdl(
  460. IN PREG_HANDLE Hdl,
  461. IN LPWSTR Opt,
  462. OUT PREG_HANDLE Hdl2
  463. ) //EndExport(function)
  464. {
  465. return DhcpRegGetNextNextHdl(Hdl, REG_SUBNET_OPTIONS, Opt, Hdl2);
  466. }
  467. //BeginExport(function)
  468. DWORD
  469. DhcpRegSubnetGetRangeHdl(
  470. IN PREG_HANDLE Hdl,
  471. IN LPWSTR Range,
  472. OUT PREG_HANDLE Hdl2
  473. ) //EndExport(function)
  474. {
  475. return DhcpRegGetNextNextHdl(Hdl, REG_SUBNET_RANGES, Range, Hdl2);
  476. }
  477. //BeginExport(function)
  478. DWORD
  479. DhcpRegSubnetGetReservationHdl(
  480. IN PREG_HANDLE Hdl,
  481. IN LPWSTR Reservation,
  482. OUT PREG_HANDLE Hdl2
  483. ) //EndExport(function)
  484. {
  485. return DhcpRegGetNextNextHdl(Hdl, REG_SUBNET_RESERVATIONS, Reservation, Hdl2);
  486. }
  487. //BeginExport(function)
  488. DWORD
  489. DhcpRegSubnetGetServerHdl(
  490. IN PREG_HANDLE Hdl,
  491. IN LPWSTR Server,
  492. OUT PREG_HANDLE Hdl2
  493. ) //EndExport(function)
  494. {
  495. return DhcpRegGetNextNextHdl(Hdl, REG_SUBNET_SERVERS, Server, Hdl2);
  496. }
  497. //BeginExport(function)
  498. DWORD
  499. DhcpRegReservationGetOptHdl(
  500. IN PREG_HANDLE Hdl,
  501. IN LPWSTR OptionName,
  502. OUT PREG_HANDLE Hdl2
  503. ) //EndExport(function)
  504. {
  505. return DhcpRegGetNextHdl(Hdl, OptionName, Hdl2);
  506. }
  507. //BeginExport(comment)
  508. //================================================================================
  509. // List retrieval functions.. for servers, subnets, ranges etc.
  510. //================================================================================
  511. //EndExport(comment)
  512. //BeginExport(function)
  513. DWORD
  514. DhcpRegServerGetList(
  515. IN PREG_HANDLE Hdl, // ptr to server location
  516. IN OUT PARRAY OptList, // list of LPWSTR options
  517. IN OUT PARRAY OptDefList, // list of LPWSTR optdefs
  518. IN OUT PARRAY Subnets, // list of LPWSTR subnets
  519. IN OUT PARRAY SScopes, // list of LPWSTR sscopes
  520. IN OUT PARRAY ClassDefs, // list of LPWSTR classes
  521. IN OUT PARRAY MScopes // list of LPWSTR mscopes
  522. ) //EndExport(function)
  523. {
  524. DWORD Error;
  525. DWORD LocalError;
  526. DWORD Index;
  527. REG_HANDLE Hdl2;
  528. struct {
  529. PARRAY Array;
  530. LPWSTR Location;
  531. } Table[] = {
  532. OptList, REG_SERVER_GLOBAL_OPTIONS,
  533. OptDefList, REG_SERVER_OPTDEFS,
  534. Subnets, REG_SERVER_SUBNETS,
  535. SScopes, REG_SERVER_SSCOPES,
  536. ClassDefs, REG_SERVER_CLASSDEFS,
  537. MScopes, REG_SERVER_MSCOPES
  538. };
  539. for( Index = 0; Index < sizeof(Table)/sizeof(Table[0]); Index ++ ) {
  540. if( NULL == Table[Index].Array ) continue;
  541. Error = DhcpRegGetNextHdl(Hdl, Table[Index].Location, &Hdl2);
  542. if( ERROR_SUCCESS != Error ) return Error;
  543. Error = DhcpRegFillSubKeys(&Hdl2, Table[Index].Array);
  544. LocalError = DhcpRegCloseHdl(&Hdl2);
  545. Require(ERROR_SUCCESS == LocalError);
  546. if( ERROR_SUCCESS != Error ) return Error;
  547. }
  548. return Error;
  549. }
  550. //BeginExport(function)
  551. DWORD
  552. DhcpRegSubnetGetExclusions(
  553. IN PREG_HANDLE Hdl,
  554. OUT LPBYTE *Excl,
  555. OUT DWORD *ExclSize
  556. ) //EndExport(function)
  557. {
  558. DWORD Error;
  559. DWORD Size;
  560. DWORD Type;
  561. if( NULL == Excl ) return ERROR_SUCCESS;
  562. Size = 0;
  563. Error = RegQueryValueEx(
  564. Hdl->Key,
  565. REG_SUBNET_EXCL,
  566. NullReserved,
  567. &Type,
  568. NULL,
  569. &Size
  570. );
  571. if( ERROR_SUCCESS != Error ) return Error;
  572. *Excl = NULL;
  573. *ExclSize = 0;
  574. if( 0 == Size ) return ERROR_SUCCESS;
  575. *Excl = MemAlloc(Size);
  576. if( NULL == *Excl ) return ERROR_NOT_ENOUGH_MEMORY;
  577. *ExclSize = Size;
  578. Error = RegQueryValueEx(
  579. Hdl->Key,
  580. REG_SUBNET_EXCL,
  581. NullReserved,
  582. &Type,
  583. *Excl,
  584. ExclSize
  585. );
  586. if( ERROR_SUCCESS != Error ) {
  587. MemFree(*Excl);
  588. *Excl = NULL;
  589. }
  590. return Error;
  591. }
  592. //BeginExport(function)
  593. DWORD
  594. DhcpRegSubnetGetList(
  595. IN PREG_HANDLE Hdl,
  596. IN OUT PARRAY Servers,
  597. IN OUT PARRAY IpRanges,
  598. IN OUT PARRAY Reservations,
  599. IN OUT PARRAY Options,
  600. OUT LPBYTE *Excl,
  601. OUT DWORD *ExclSizeInBytes
  602. ) //EndExport(function)
  603. {
  604. DWORD Error;
  605. DWORD LocalError;
  606. DWORD Index;
  607. REG_HANDLE Hdl2;
  608. struct {
  609. PARRAY Array;
  610. LPWSTR Location;
  611. } Table[] = {
  612. Servers, REG_SUBNET_SERVERS,
  613. IpRanges, REG_SUBNET_RANGES,
  614. Reservations, REG_SUBNET_RESERVATIONS,
  615. Options, REG_SUBNET_OPTIONS,
  616. // Exclusions are to be handled a bit differently
  617. };
  618. for( Index = 0; Index < sizeof(Table)/sizeof(Table[0]); Index ++ ) {
  619. if( NULL == Table[Index].Array ) continue;
  620. Error = DhcpRegGetNextHdl(Hdl, Table[Index].Location, &Hdl2);
  621. if( ERROR_SUCCESS != Error ) return Error;
  622. Error = DhcpRegFillSubKeys(&Hdl2, Table[Index].Array);
  623. LocalError = DhcpRegCloseHdl(&Hdl2);
  624. Require(ERROR_SUCCESS == LocalError);
  625. if( ERROR_SUCCESS != Error ) return Error;
  626. }
  627. // Now read the exclusions from off here
  628. return DhcpRegSubnetGetExclusions(Hdl, Excl, ExclSizeInBytes );
  629. }
  630. //BeginExport(function)
  631. DWORD
  632. DhcpRegSScopeGetList(
  633. IN PREG_HANDLE Hdl,
  634. IN OUT PARRAY Subnets
  635. ) //EndExport(function)
  636. {
  637. return DhcpRegFillSubKeys(Hdl, Subnets);
  638. }
  639. //BeginExport(function)
  640. DWORD
  641. DhcpRegReservationGetList(
  642. IN PREG_HANDLE Hdl,
  643. IN OUT PARRAY Options
  644. ) //EndExport(function)
  645. {
  646. return DhcpRegFillSubKeys(Hdl, Options);
  647. }
  648. //BeginExport(comment)
  649. //================================================================================
  650. // the separate stuff are here -- these are not list stuff, but just simple
  651. // single valued attributes
  652. // some of these actually, dont even go to the registry, but that's fine alright?
  653. //================================================================================
  654. //EndExport(comment)
  655. //BeginExport(function)
  656. DWORD
  657. DhcpRegServerGetAttributes(
  658. IN PREG_HANDLE Hdl,
  659. OUT LPWSTR *Name,
  660. OUT LPWSTR *Comment,
  661. OUT DWORD *Flags
  662. // more attributes will come here soon?
  663. ) //EndExport(function)
  664. {
  665. if( Name ) *Name = NULL;
  666. if( Comment ) *Comment = NULL;
  667. if( Flags ) *Flags = 0;
  668. return ERROR_SUCCESS;
  669. }
  670. //BeginExport(function)
  671. DWORD
  672. DhcpRegSubnetGetAttributes(
  673. IN PREG_HANDLE Hdl,
  674. OUT LPWSTR *Name,
  675. OUT LPWSTR *Comment,
  676. OUT DWORD *Flags,
  677. OUT DWORD *Address,
  678. OUT DWORD *Mask
  679. ) //EndExport(function)
  680. {
  681. DWORD fSwitched;
  682. if( Name ) *Name = DhcpRegRead(Hdl, REG_SZ, REG_SUBNET_NAME, NULL);
  683. if( Comment ) *Comment = DhcpRegRead(Hdl, REG_SZ, REG_SUBNET_COMMENT, NULL);
  684. if( Flags ) {
  685. *Flags = PtrToUlong(DhcpRegRead(Hdl, REG_DWORD, REG_SUBNET_STATE, (LPVOID)REG_DEFAULT_SUBNET_STATE));
  686. fSwitched = PtrToUlong(DhcpRegRead(Hdl, REG_DWORD, REG_SUBNET_SWITCHED_FLAG, (LPVOID)REG_DEFAULT_SWITCHED_FLAG));
  687. if(fSwitched) SWITCHED(*Flags);
  688. }
  689. if( Address )
  690. *Address = PtrToUlong(DhcpRegRead(Hdl, REG_DWORD, REG_SUBNET_ADDRESS, (LPVOID)0));
  691. if( Mask ) *Mask = PtrToUlong(DhcpRegRead(Hdl, REG_DWORD, REG_SUBNET_MASK, ULongToPtr(REG_DEFAULT_SUBNET_MASK)));
  692. return ERROR_SUCCESS;
  693. }
  694. typedef struct {
  695. LPVOID RetPtr;
  696. LPWSTR ValueName;
  697. DWORD ValueType;
  698. LPVOID Defaults;
  699. } ATTRIB_TBL, *PATTRIB_TBL, *LPATTRIB_TBL;
  700. VOID
  701. DhcpRegFillAttribTable(
  702. IN PREG_HANDLE Hdl,
  703. IN PATTRIB_TBL Table,
  704. IN DWORD TableSize
  705. ) {
  706. DWORD i;
  707. PVOID Tmp;
  708. for( i = 0; i < TableSize ; i ++ ) {
  709. if( NULL == Table[i].RetPtr) continue;
  710. Tmp = DhcpRegRead(
  711. Hdl,
  712. Table[i].ValueType,
  713. Table[i].ValueName,
  714. Table[i].Defaults
  715. );
  716. if( REG_DWORD == Table[i].ValueType ) {
  717. *((DWORD *)Table[i].RetPtr) = PtrToUlong(Tmp);
  718. } else {
  719. *((LPVOID *)Table[i].RetPtr) = Tmp;
  720. }
  721. }
  722. }
  723. //
  724. // Hack O Rama -- This routine returns ERROR_INVALID_DATA if
  725. // the registry has been upgraded from pre-win2k build to win2k.
  726. // So that defaults can be chosen for ScopeId etc.
  727. //
  728. //BeginExport(function)
  729. DWORD
  730. DhcpRegMScopeGetAttributes(
  731. IN PREG_HANDLE Hdl,
  732. OUT LPWSTR *Comments,
  733. OUT DWORD *State,
  734. OUT DWORD *ScopeId,
  735. OUT DWORD *Policy,
  736. OUT DWORD *TTL,
  737. OUT LPWSTR *LangTag,
  738. OUT PDATE_TIME *ExpiryTime
  739. ) //EndExport(function)
  740. {
  741. DATE_TIME DefaultExpiryTime = {DHCP_DATE_TIME_INFINIT_LOW, DHCP_DATE_TIME_INFINIT_HIGH};
  742. LPWSTR DefaultLangTag = L"en-US";
  743. DWORD ScopeIdFake1, ScopeIdFake2;
  744. ATTRIB_TBL Table[] = {
  745. Comments, REG_MSCOPE_COMMENT, REG_SZ, NULL,
  746. State, REG_MSCOPE_STATE, REG_DWORD, (LPVOID)0,
  747. ScopeId, REG_MSCOPE_SCOPEID, REG_DWORD, (LPVOID)0,
  748. &ScopeIdFake1, REG_MSCOPE_SCOPEID, REG_DWORD, (LPVOID)1,
  749. &ScopeIdFake2, REG_MSCOPE_SCOPEID, REG_DWORD, (LPVOID)2,
  750. Policy, REG_MSCOPE_ADDR_POLICY, REG_DWORD, (LPVOID)0,
  751. TTL, REG_MSCOPE_TTL, REG_DWORD, (LPVOID)DEFAULT_MCAST_TTL,
  752. LangTag, REG_MSCOPE_LANG_TAG, REG_SZ, (LPVOID)0,
  753. ExpiryTime, REG_MSCOPE_EXPIRY_TIME, REG_BINARY, (LPVOID)0
  754. };
  755. DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  756. if (*LangTag == 0) {
  757. *LangTag = MemAlloc(wcslen((DefaultLangTag)+1)*sizeof(WCHAR));
  758. if (*LangTag) {
  759. wcscpy(*LangTag, DefaultLangTag);
  760. } else {
  761. return ERROR_NOT_ENOUGH_MEMORY;
  762. }
  763. }
  764. if (*ExpiryTime == 0) {
  765. *ExpiryTime = MemAlloc(sizeof (DefaultExpiryTime));
  766. if (*ExpiryTime) {
  767. **ExpiryTime = DefaultExpiryTime;
  768. } else {
  769. return ERROR_NOT_ENOUGH_MEMORY;
  770. }
  771. }
  772. if( ScopeIdFake1 != ScopeIdFake2 ) {
  773. Require(ScopeIdFake1 == 1 && ScopeIdFake2 == 2);
  774. //
  775. // Basically no value for ScopeId in the registry. return a warning.
  776. // such as ERROR_INVALID_DATA.
  777. //
  778. return ERROR_INVALID_DATA;
  779. }
  780. return ERROR_SUCCESS;
  781. }
  782. //BeginExport(function)
  783. DWORD
  784. DhcpRegOptDefGetAttributes(
  785. IN PREG_HANDLE Hdl,
  786. OUT LPWSTR *Name,
  787. OUT LPWSTR *Comments,
  788. OUT DWORD *Flags,
  789. OUT DWORD *OptionId,
  790. OUT LPWSTR *ClassName,
  791. OUT LPWSTR *VendorName,
  792. OUT LPBYTE *Value,
  793. OUT DWORD *ValueSize
  794. ) //EndExport(function)
  795. {
  796. DWORD Error;
  797. ATTRIB_TBL Table[] = {
  798. Name, REG_OPTION_NAME, REG_SZ, NULL,
  799. Comments, REG_OPTION_COMMENT, REG_SZ, NULL,
  800. ClassName, REG_OPTION_CLASSNAME, REG_SZ, NULL,
  801. VendorName, REG_OPTION_VENDORNAME, REG_SZ, NULL,
  802. Flags, REG_OPTION_TYPE, REG_DWORD, (LPVOID)0,
  803. OptionId, REG_OPTION_ID, REG_DWORD, (LPVOID)0
  804. };
  805. DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  806. if( Value ) {
  807. Error = DhcpRegReadBinary(Hdl, REG_OPTION_VALUE, Value, ValueSize);
  808. Require(*Value);
  809. }
  810. return ERROR_SUCCESS;
  811. }
  812. //BeginExport(function)
  813. DWORD
  814. DhcpRegSScopeGetAttributes( // superscopes dont have any information stored.. dont use this
  815. IN PREG_HANDLE Hdl,
  816. OUT LPWSTR *Name,
  817. OUT LPWSTR *Comment,
  818. OUT DWORD *Flags
  819. ) //EndExport(function)
  820. {
  821. Require(FALSE);
  822. return ERROR_INVALID_PARAMETER;
  823. }
  824. //BeginExport(function)
  825. DWORD
  826. DhcpRegClassDefGetAttributes(
  827. IN PREG_HANDLE Hdl,
  828. OUT LPWSTR *Name,
  829. OUT LPWSTR *Comment,
  830. OUT DWORD *Flags,
  831. OUT LPBYTE *Value,
  832. OUT DWORD *ValueSize
  833. ) //EndExport(function)
  834. {
  835. DWORD Error;
  836. ATTRIB_TBL Table[] = {
  837. Name, REG_CLASSDEF_NAME, REG_SZ, NULL,
  838. Comment, REG_CLASSDEF_COMMENT, REG_SZ, NULL,
  839. Flags, REG_CLASSDEF_TYPE, REG_DWORD, (LPVOID)0
  840. };
  841. DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  842. if( Value ) {
  843. Error = DhcpRegReadBinary(Hdl, REG_CLASSDEF_VALUE, Value, ValueSize);
  844. Require(*Value);
  845. }
  846. return ERROR_SUCCESS;
  847. }
  848. //BeginExport(function)
  849. DWORD
  850. DhcpRegSubnetServerGetAttributes(
  851. IN PREG_HANDLE Hdl,
  852. OUT LPWSTR *Name,
  853. OUT LPWSTR *Comment,
  854. OUT DWORD *Flags,
  855. OUT DWORD *Address,
  856. OUT DWORD *Role
  857. ) //EndExport(function)
  858. {
  859. ATTRIB_TBL Table[] = {
  860. Name, REG_SUB_SERVER_NAME, REG_SZ, NULL,
  861. Comment, REG_SUB_SERVER_COMMENT,REG_SZ, NULL,
  862. Flags, REG_FLAGS, REG_DWORD, (LPVOID)0,
  863. Address, REG_SUB_SERVER_ADDRESS,REG_DWORD, (LPVOID)0,
  864. Role, REG_SUB_SERVER_ROLE, REG_DWORD, (LPVOID)0
  865. };
  866. DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  867. return ERROR_SUCCESS;
  868. }
  869. //BeginExport(function)
  870. DWORD
  871. DhcpRegRangeGetAttributes(
  872. IN PREG_HANDLE Hdl,
  873. OUT LPWSTR *Name,
  874. OUT LPWSTR *Comment,
  875. OUT DWORD *Flags,
  876. OUT ULONG *AllocCount,
  877. OUT ULONG *MaxAllocCount,
  878. OUT DWORD *StartAddress,
  879. OUT DWORD *EndAddress,
  880. OUT LPBYTE *InUseClusters,
  881. OUT DWORD *InUseClusterSize,
  882. OUT LPBYTE *UsedClusters,
  883. OUT DWORD *UsedClustersSize
  884. ) //EndExport(function)
  885. {
  886. DWORD Error;
  887. ATTRIB_TBL Table[] = {
  888. Name, REG_RANGE_NAME, REG_SZ, NULL,
  889. Comment, REG_RANGE_COMMENT, REG_SZ, NULL,
  890. Flags, REG_RANGE_FLAGS, REG_DWORD, (LPVOID)(DEF_RANGE_FLAG_VAL),
  891. AllocCount, REG_RANGE_ALLOC, REG_DWORD, (LPVOID)(DEF_RANGE_ALLOC),
  892. MaxAllocCount, REG_RANGE_MAX_ALLOC, REG_DWORD, (LPVOID)(ULONG_PTR)(DEF_RANGE_MAX_ALLOC),
  893. StartAddress, REG_RANGE_START_ADDRESS, REG_DWORD, (LPVOID)0,
  894. EndAddress, REG_RANGE_END_ADDRESS, REG_DWORD, (LPVOID)0
  895. };
  896. DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  897. if( InUseClusters ) {
  898. Error = DhcpRegReadBinary(Hdl, REG_RANGE_INUSE_CLUSTERS, InUseClusters, InUseClusterSize);
  899. //Require(ERROR_SUCCESS == Error); //-- after registry changed, NO_SUCH_FILE could come up here as well.
  900. }
  901. if( UsedClusters ) {
  902. Error = DhcpRegReadBinary(Hdl, REG_RANGE_USED_CLUSTERS, UsedClusters, UsedClustersSize);
  903. //Require(ERROR_SUCCESS == Error); //-- after registry changed, NO_SUCH_FILE could come up here as well.
  904. }
  905. return ERROR_SUCCESS;
  906. }
  907. //BeginExport(function)
  908. DWORD
  909. DhcpRegReservationGetAttributes(
  910. IN PREG_HANDLE Hdl,
  911. OUT LPWSTR *Name,
  912. OUT LPWSTR *Comment,
  913. OUT DWORD *Flags,
  914. OUT DWORD *Address,
  915. OUT LPBYTE *ClientUID,
  916. OUT DWORD *ClientUIDSize
  917. ) //EndExport(function)
  918. {
  919. DWORD Error;
  920. DWORD deftype = DEF_RESERVATION_TYPE;
  921. ATTRIB_TBL Table[] = {
  922. Name, REG_RESERVATION_NAME, REG_SZ, NULL,
  923. Comment, REG_RESERVATION_COMMENT, REG_SZ, NULL,
  924. Flags, REG_RESERVATION_TYPE, REG_DWORD, ULongToPtr(deftype),
  925. Address, REG_RESERVATION_ADDRESS, REG_DWORD, (LPVOID)0,
  926. };
  927. DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  928. if( ClientUID ) {
  929. Error = DhcpRegReadBinary(Hdl, REG_RESERVATION_UID, ClientUID, ClientUIDSize);
  930. Require(ERROR_SUCCESS == Error);
  931. }
  932. return ERROR_SUCCESS;
  933. }
  934. //BeginExport(function)
  935. DWORD
  936. DhcpRegOptGetAttributes(
  937. IN PREG_HANDLE Hdl,
  938. OUT DWORD *OptionId,
  939. OUT LPWSTR *ClassName,
  940. OUT LPWSTR *VendorName,
  941. OUT DWORD *Flags,
  942. OUT LPBYTE *Value,
  943. OUT DWORD *ValueSize
  944. ) //EndExport(function)
  945. {
  946. DWORD Error;
  947. ATTRIB_TBL Table[] = {
  948. OptionId, REG_OPTION_ID, REG_DWORD, (LPVOID)0,
  949. ClassName, REG_OPTION_CLASSNAME, REG_SZ, NULL,
  950. VendorName, REG_OPTION_VENDORNAME, REG_SZ, NULL,
  951. Flags, REG_OPTION_TYPE, REG_DWORD, (LPVOID)0,
  952. };
  953. DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  954. if( Value ) {
  955. Error = DhcpRegReadBinary(Hdl, REG_OPTION_VALUE, Value, ValueSize);
  956. }
  957. return ERROR_SUCCESS;
  958. }
  959. //BeginExport(comment)
  960. //================================================================================
  961. // the following functiosn help in writing to the registry
  962. //================================================================================
  963. //EndExport(comment)
  964. typedef struct {
  965. LPVOID Value;
  966. DWORD Size;
  967. DWORD Type;
  968. LPWSTR ValueName;
  969. } WATTRIB_TBL, *PWATTRIB_TBL, *LPWATTRIB_TBL;
  970. DWORD
  971. DhcpRegSaveAttribTable(
  972. IN PREG_HANDLE Hdl,
  973. IN PWATTRIB_TBL Table,
  974. IN DWORD Size
  975. )
  976. {
  977. DWORD i;
  978. DWORD Error;
  979. DWORD PtrSize;
  980. LPBYTE Ptr;
  981. for(i = 0; i < Size; i ++ ) {
  982. if( NULL == Table[i].Value ) continue;
  983. PtrSize = Table[i].Size;
  984. Ptr = *(LPBYTE *)Table[i].Value;
  985. switch(Table[i].Type) {
  986. case REG_SZ:
  987. if( NULL == *(LPWSTR *)Table[i].Value) { PtrSize = sizeof(WCHAR); Ptr = (LPBYTE)L""; break; }
  988. PtrSize = sizeof(WCHAR)*(wcslen(*((LPWSTR *)Table[i].Value))+1);
  989. Ptr = *(LPBYTE *)Table[i].Value;
  990. break;
  991. case REG_DWORD:
  992. PtrSize = sizeof(DWORD);
  993. Ptr = Table[i].Value; // This is because we deref this ptr down below..
  994. break;
  995. }
  996. Error = RegSetValueEx(
  997. Hdl->Key,
  998. Table[i].ValueName,
  999. ZeroReserved,
  1000. Table[i].Type,
  1001. Ptr,
  1002. PtrSize
  1003. );
  1004. if( ERROR_SUCCESS != Error ) {
  1005. return Error;
  1006. }
  1007. }
  1008. return ERROR_SUCCESS;
  1009. }
  1010. //BeginExport(functions)
  1011. DWORD
  1012. DhcpRegSaveSubKeys(
  1013. IN PREG_HANDLE Hdl,
  1014. IN OUT PARRAY Array
  1015. ) //EndExport(function)
  1016. {
  1017. ARRAY_LOCATION Loc;
  1018. DWORD Error;
  1019. REG_HANDLE Hdl2;
  1020. LPWSTR KeyName;
  1021. Error = MemArrayInitLoc(Array, &Loc);
  1022. while(ERROR_FILE_NOT_FOUND != Error ) {
  1023. Require(ERROR_SUCCESS == Error);
  1024. Error = MemArrayGetElement(Array, &Loc, (LPVOID *)&KeyName);
  1025. Require(ERROR_SUCCESS == Error && NULL != KeyName);
  1026. Error = DhcpRegGetNextHdl(Hdl, KeyName, &Hdl2);
  1027. if( ERROR_SUCCESS != Error ) return Error;
  1028. Error = DhcpRegCloseHdl(&Hdl2);
  1029. Require(ERROR_SUCCESS == Error);
  1030. Error = MemArrayNextLoc(Array, &Loc);
  1031. }
  1032. return ERROR_SUCCESS;
  1033. }
  1034. //BeginExport(functions)
  1035. DWORD
  1036. DhcpRegSaveSubKeysPrefixed(
  1037. IN PREG_HANDLE Hdl,
  1038. IN OUT PARRAY Array,
  1039. IN LPWSTR CommonPrefix
  1040. ) //EndExport(function)
  1041. {
  1042. ARRAY_LOCATION Loc;
  1043. DWORD Error;
  1044. REG_HANDLE Hdl2;
  1045. LPWSTR KeyName;
  1046. Error = MemArrayInitLoc(Array, &Loc);
  1047. while(ERROR_FILE_NOT_FOUND != Error ) {
  1048. Require(ERROR_SUCCESS == Error);
  1049. Error = MemArrayGetElement(Array, &Loc, (LPVOID *)&KeyName);
  1050. Require(ERROR_SUCCESS == Error && NULL != KeyName);
  1051. Error = DhcpRegGetNextNextHdl(Hdl, CommonPrefix, KeyName, &Hdl2);
  1052. if( ERROR_SUCCESS != Error ) return Error;
  1053. Error = DhcpRegCloseHdl(&Hdl2);
  1054. Require(ERROR_SUCCESS == Error);
  1055. Error = MemArrayNextLoc(Array, &Loc);
  1056. }
  1057. return ERROR_SUCCESS;
  1058. }
  1059. //BeginExport(function)
  1060. DWORD
  1061. DhcpRegServerSetList(
  1062. IN PREG_HANDLE Hdl,
  1063. IN PARRAY OptList, // list of LPWSTR options
  1064. IN PARRAY OptDefList, // list of LPWSTR optdefs
  1065. IN PARRAY Subnets, // list of LPWSTR subnets
  1066. IN PARRAY SScopes, // list of LPWSTR sscopes
  1067. IN PARRAY ClassDefs, // list of LPWSTR classes
  1068. IN PARRAY MScopes // list of LPWSTR mscopes
  1069. ) //EndExport(function)
  1070. {
  1071. DWORD Error;
  1072. DWORD LocalError;
  1073. DWORD Index;
  1074. REG_HANDLE Hdl2;
  1075. struct {
  1076. PARRAY Array;
  1077. LPWSTR Location;
  1078. } Table[] = {
  1079. OptList, REG_SERVER_GLOBAL_OPTIONS,
  1080. OptDefList, REG_SERVER_OPTDEFS,
  1081. Subnets, REG_SERVER_SUBNETS,
  1082. SScopes, REG_SERVER_SSCOPES,
  1083. ClassDefs, REG_SERVER_CLASSDEFS,
  1084. MScopes, REG_SERVER_MSCOPES
  1085. };
  1086. for( Index = 0; Index < sizeof(Table)/sizeof(Table[0]); Index ++ ) {
  1087. if( NULL == Table[Index].Array ) continue;
  1088. Error = DhcpRegGetNextHdl(Hdl, Table[Index].Location, &Hdl2);
  1089. if( ERROR_SUCCESS != Error ) return Error;
  1090. Error = DhcpRegSaveSubKeys(&Hdl2, Table[Index].Array);
  1091. LocalError = DhcpRegCloseHdl(&Hdl2);
  1092. Require(ERROR_SUCCESS == LocalError);
  1093. if( ERROR_SUCCESS != Error ) return Error;
  1094. }
  1095. return Error;
  1096. }
  1097. //BeginExport(function)
  1098. DWORD
  1099. DhcpRegSubnetSetExclusions(
  1100. IN PREG_HANDLE Hdl,
  1101. IN LPBYTE *Excl,
  1102. IN DWORD ExclSize
  1103. ) //EndExport(function)
  1104. {
  1105. DWORD Error;
  1106. WATTRIB_TBL Table[] = {
  1107. (LPVOID*)Excl, ExclSize, REG_BINARY, REG_SUBNET_EXCL,
  1108. };
  1109. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1110. }
  1111. //BeginExport(function)
  1112. DWORD
  1113. DhcpRegSubnetSetList(
  1114. IN PREG_HANDLE Hdl,
  1115. IN PARRAY Servers,
  1116. IN PARRAY IpRanges,
  1117. IN PARRAY Reservations,
  1118. IN PARRAY Options,
  1119. IN LPBYTE *Excl,
  1120. IN DWORD ExclSizeInBytes
  1121. ) //EndExport(function)
  1122. {
  1123. DWORD Error;
  1124. DWORD LocalError;
  1125. DWORD Index;
  1126. REG_HANDLE Hdl2;
  1127. struct {
  1128. PARRAY Array;
  1129. LPWSTR Location;
  1130. } Table[] = {
  1131. Servers, REG_SUBNET_SERVERS,
  1132. IpRanges, REG_SUBNET_RANGES,
  1133. Reservations, REG_SUBNET_RESERVATIONS,
  1134. Options, REG_SUBNET_OPTIONS,
  1135. // Exclusions are to be handled a bit differently
  1136. };
  1137. for( Index = 0; Index < sizeof(Table)/sizeof(Table[0]); Index ++ ) {
  1138. if( NULL == Table[Index].Array ) continue;
  1139. Error = DhcpRegGetNextHdl(Hdl, Table[Index].Location, &Hdl2);
  1140. if( ERROR_SUCCESS != Error ) return Error;
  1141. Error = DhcpRegSaveSubKeys(&Hdl2, Table[Index].Array);
  1142. LocalError = DhcpRegCloseHdl(&Hdl2);
  1143. Require(ERROR_SUCCESS == LocalError);
  1144. if( ERROR_SUCCESS != Error ) return Error;
  1145. }
  1146. // Now read the exclusions from off here
  1147. return DhcpRegSubnetSetExclusions(Hdl, Excl, ExclSizeInBytes );
  1148. }
  1149. //BeginExport(function)
  1150. DWORD
  1151. DhcpRegSScopeSetList(
  1152. IN PREG_HANDLE Hdl,
  1153. IN OUT PARRAY Subnets
  1154. ) //EndExport(function)
  1155. {
  1156. return DhcpRegSaveSubKeys(Hdl, Subnets);
  1157. }
  1158. //BeginExport(function)
  1159. DWORD
  1160. DhcpRegReservationSetList(
  1161. IN PREG_HANDLE Hdl,
  1162. IN PARRAY Subnets
  1163. ) //EndExport(function)
  1164. {
  1165. return DhcpRegSaveSubKeys(Hdl, Subnets);
  1166. }
  1167. //BeginExport(comment)
  1168. //================================================================================
  1169. // the single stuff are here -- these are not list stuff, but just simple
  1170. // single valued attributes
  1171. // some of these actually, dont even go to the registry, but that's fine alright?
  1172. //================================================================================
  1173. //EndExport(comment)
  1174. //BeginExport(function)
  1175. DWORD
  1176. DhcpRegServerSetAttributes(
  1177. IN PREG_HANDLE Hdl,
  1178. IN LPWSTR *Name,
  1179. IN LPWSTR *Comment,
  1180. IN DWORD *Flags
  1181. // more attributes will come here soon?
  1182. ) //EndExport(function)
  1183. {
  1184. #if 0
  1185. WATTRIB_TBL Table[] = {
  1186. Name, REG_SERVER_NAME
  1187. }
  1188. if( Name ) *Name = NULL;
  1189. if( Comment ) *Comment = NULL;
  1190. if( Flags ) *Flags = 0;
  1191. #endif
  1192. return ERROR_SUCCESS;
  1193. }
  1194. DWORD
  1195. DhcpRegSubnetSetAttributesInternal(
  1196. IN PREG_HANDLE Hdl,
  1197. IN LPWSTR *Name,
  1198. IN LPWSTR *Comment,
  1199. IN DWORD *Flags,
  1200. IN DWORD *Address,
  1201. IN DWORD *Mask,
  1202. IN DWORD *SwitchedNetwork
  1203. )
  1204. {
  1205. DWORD Error, SrvIpAddress, SrvRole;
  1206. LPWSTR EmptyString;
  1207. REG_HANDLE Hdl2;
  1208. WATTRIB_TBL Table[] = {
  1209. Name, 0, REG_SZ, REG_SUBNET_NAME,
  1210. Comment, 0, REG_SZ, REG_SUBNET_COMMENT,
  1211. Flags, 0, REG_DWORD, REG_SUBNET_STATE,
  1212. Address, 0, REG_DWORD, REG_SUBNET_ADDRESS,
  1213. Mask, 0, REG_DWORD, REG_SUBNET_MASK,
  1214. SwitchedNetwork, 0, REG_DWORD, REG_SUBNET_SWITCHED_FLAG
  1215. };
  1216. Error = DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1217. if( NO_ERROR != Error ) return Error;
  1218. //
  1219. // The following lines are for backward compat with NT4.
  1220. //
  1221. //
  1222. // Create the reservation key in any case
  1223. //
  1224. Error = DhcpRegGetNextHdl(
  1225. Hdl, REG_SUBNET_RESERVATIONS, &Hdl2 );
  1226. if( NO_ERROR != Error ) return Error;
  1227. DhcpRegCloseHdl( &Hdl2 );
  1228. //
  1229. // Create the servers key
  1230. //
  1231. Error = DhcpRegGetNextHdl(
  1232. Hdl, L"DHCPServers", &Hdl2 );
  1233. if( NO_ERROR != Error ) return Error;
  1234. DhcpRegCloseHdl( &Hdl2 );
  1235. Error = DhcpRegGetNextNextHdl(
  1236. Hdl, L"DHCPServers", L"127.0.0.1", &Hdl2 );
  1237. if( NO_ERROR != Error ) return Error;
  1238. //
  1239. // Now set the role of the newly created server as primary
  1240. //
  1241. SrvIpAddress = INADDR_LOOPBACK;
  1242. SrvRole = 1; // primary
  1243. EmptyString = L"";
  1244. {
  1245. WATTRIB_TBL SrvTable[] = {
  1246. &SrvRole, 0, REG_DWORD, L"Role",
  1247. &SrvIpAddress, 0, REG_DWORD, L"ServerIpAddress",
  1248. &EmptyString, 0, REG_SZ, L"ServerHostName",
  1249. &EmptyString, 0, REG_SZ, L"ServerNetBiosName"
  1250. };
  1251. Error = DhcpRegSaveAttribTable(
  1252. &Hdl2, SrvTable, sizeof(SrvTable)/sizeof(SrvTable[0]));
  1253. }
  1254. DhcpRegCloseHdl(&Hdl2);
  1255. return Error;
  1256. }
  1257. //BeginExport(function)
  1258. DWORD
  1259. DhcpRegSubnetSetAttributes(
  1260. IN PREG_HANDLE Hdl,
  1261. IN LPWSTR *Name,
  1262. IN LPWSTR *Comment,
  1263. IN DWORD *Flags,
  1264. IN DWORD *Address,
  1265. IN DWORD *Mask
  1266. ) //EndExport(function)
  1267. {
  1268. DWORD xFlags, SwitchedNetwork = FALSE;
  1269. OSVERSIONINFO Ver;
  1270. Ver.dwOSVersionInfoSize = sizeof(Ver);
  1271. if( FALSE == GetVersionEx(&Ver) ) return GetLastError();
  1272. if( Flags && Ver.dwMajorVersion < 5 ) {
  1273. SwitchedNetwork = IS_SWITCHED(*Flags);
  1274. xFlags = IS_DISABLED(*Flags);
  1275. Flags = &xFlags;
  1276. }
  1277. return DhcpRegSubnetSetAttributesInternal(
  1278. Hdl, Name, Comment, Flags, Address, Mask,
  1279. Flags ? &SwitchedNetwork : NULL );
  1280. }
  1281. //BeginExport(function)
  1282. DWORD
  1283. DhcpRegMScopeSetAttributes(
  1284. IN PREG_HANDLE Hdl,
  1285. IN LPWSTR *Comments,
  1286. IN DWORD *State,
  1287. IN DWORD *ScopeId,
  1288. IN DWORD *Policy,
  1289. IN DWORD *TTL,
  1290. IN LPWSTR *LangTag,
  1291. IN PDATE_TIME *ExpiryTime
  1292. ) //EndExport(function)
  1293. {
  1294. WATTRIB_TBL Table[] = {
  1295. Comments, 0, REG_SZ, REG_MSCOPE_COMMENT,
  1296. State, 0, REG_DWORD, REG_MSCOPE_STATE,
  1297. ScopeId, 0, REG_DWORD, REG_MSCOPE_SCOPEID,
  1298. Policy, 0, REG_DWORD, REG_MSCOPE_ADDR_POLICY,
  1299. TTL, 0, REG_DWORD, REG_MSCOPE_TTL,
  1300. LangTag, 0, REG_SZ, REG_MSCOPE_LANG_TAG,
  1301. ExpiryTime, sizeof(**ExpiryTime), REG_BINARY, REG_MSCOPE_EXPIRY_TIME
  1302. };
  1303. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1304. }
  1305. //BeginExport(function)
  1306. DWORD
  1307. DhcpRegOptDefSetAttributes(
  1308. IN PREG_HANDLE Hdl,
  1309. IN LPWSTR *Name,
  1310. IN LPWSTR *Comments,
  1311. IN DWORD *Flags,
  1312. IN DWORD *OptionId,
  1313. IN LPWSTR *ClassName,
  1314. IN LPWSTR *VendorName,
  1315. IN LPBYTE *Value,
  1316. IN DWORD ValueSize
  1317. ) //EndExport(function)
  1318. {
  1319. DWORD Error;
  1320. WATTRIB_TBL Table[] = {
  1321. Name, 0, REG_SZ, REG_OPTION_NAME,
  1322. Comments, 0, REG_SZ, REG_OPTION_COMMENT,
  1323. ClassName, 0, REG_SZ, REG_OPTION_CLASSNAME,
  1324. VendorName, 0, REG_SZ, REG_OPTION_VENDORNAME,
  1325. Flags, 0, REG_DWORD, REG_OPTION_TYPE,
  1326. OptionId, 0, REG_DWORD, REG_OPTION_ID,
  1327. Value, ValueSize,REG_BINARY, REG_OPTION_VALUE
  1328. };
  1329. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1330. }
  1331. //BeginExport(function)
  1332. DWORD
  1333. DhcpRegSScopeSetAttributes( // superscopes dont have any information stored.. dont use this
  1334. IN PREG_HANDLE Hdl,
  1335. IN LPWSTR *Name,
  1336. IN LPWSTR *Comment,
  1337. IN DWORD *Flags
  1338. ) //EndExport(function)
  1339. {
  1340. Require(FALSE);
  1341. return ERROR_INVALID_PARAMETER;
  1342. }
  1343. //BeginExport(function)
  1344. DWORD
  1345. DhcpRegClassDefSetAttributes(
  1346. IN PREG_HANDLE Hdl,
  1347. IN LPWSTR *Name,
  1348. IN LPWSTR *Comment,
  1349. IN DWORD *Flags,
  1350. IN LPBYTE *Value,
  1351. IN DWORD ValueSize
  1352. ) //EndExport(function)
  1353. {
  1354. DWORD Error;
  1355. WATTRIB_TBL Table[] = {
  1356. Name, 0, REG_SZ, REG_CLASSDEF_NAME,
  1357. Comment, 0, REG_SZ, REG_CLASSDEF_COMMENT,
  1358. Flags, 0, REG_DWORD, REG_CLASSDEF_TYPE,
  1359. Value, ValueSize,REG_BINARY, REG_CLASSDEF_VALUE
  1360. };
  1361. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1362. }
  1363. //BeginExport(function)
  1364. DWORD
  1365. DhcpRegSubnetServerSetAttributes(
  1366. IN PREG_HANDLE Hdl,
  1367. IN LPWSTR *Name,
  1368. IN LPWSTR *Comment,
  1369. IN DWORD *Flags,
  1370. IN DWORD *Address,
  1371. IN DWORD *Role
  1372. ) //EndExport(function)
  1373. {
  1374. WATTRIB_TBL Table[] = {
  1375. Name, 0, REG_SZ, REG_SUB_SERVER_NAME,
  1376. Comment, 0, REG_SZ, REG_SUB_SERVER_COMMENT,
  1377. Flags, 0, REG_DWORD, REG_FLAGS,
  1378. Address, 0, REG_DWORD, REG_SUB_SERVER_ADDRESS,
  1379. Role, 0, REG_DWORD, REG_SUB_SERVER_ROLE,
  1380. };
  1381. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1382. }
  1383. //BeginExport(function)
  1384. DWORD
  1385. DhcpRegRangeSetAttributes(
  1386. IN PREG_HANDLE Hdl,
  1387. IN LPWSTR *Name,
  1388. IN LPWSTR *Comment,
  1389. IN DWORD *Flags,
  1390. IN ULONG *AllocCount,
  1391. IN ULONG *MaxAllocCount,
  1392. IN DWORD *StartAddress,
  1393. IN DWORD *EndAddress,
  1394. IN LPBYTE *InUseClusters,
  1395. IN DWORD InUseClusterSize,
  1396. IN LPBYTE *UsedClusters,
  1397. IN DWORD UsedClustersSize
  1398. ) //EndExport(function)
  1399. {
  1400. DWORD Error;
  1401. WATTRIB_TBL Table[] = {
  1402. Name, 0, REG_SZ, REG_RANGE_NAME,
  1403. Comment, 0, REG_SZ, REG_RANGE_COMMENT,
  1404. Flags, 0, REG_DWORD, REG_RANGE_FLAGS,
  1405. AllocCount, 0, REG_DWORD, REG_RANGE_ALLOC,
  1406. MaxAllocCount, 0, REG_DWORD, REG_RANGE_MAX_ALLOC,
  1407. StartAddress, 0, REG_DWORD, REG_RANGE_START_ADDRESS,
  1408. EndAddress, 0, REG_DWORD, REG_RANGE_END_ADDRESS,
  1409. InUseClusters, InUseClusterSize, REG_BINARY, REG_RANGE_INUSE_CLUSTERS,
  1410. UsedClusters, UsedClustersSize, REG_BINARY, REG_RANGE_USED_CLUSTERS,
  1411. };
  1412. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1413. }
  1414. //BeginExport(function)
  1415. DWORD
  1416. DhcpRegReservationSetAttributes(
  1417. IN PREG_HANDLE Hdl,
  1418. IN LPWSTR *Name,
  1419. IN LPWSTR *Comment,
  1420. IN DWORD *Flags,
  1421. IN DWORD *Address,
  1422. IN LPBYTE *ClientUID,
  1423. IN DWORD ClientUIDSize
  1424. ) //EndExport(function)
  1425. {
  1426. DWORD Error;
  1427. WATTRIB_TBL Table[] = {
  1428. Name, 0, REG_SZ, REG_RESERVATION_NAME,
  1429. Comment, 0, REG_SZ, REG_RESERVATION_COMMENT,
  1430. Flags, 0, REG_DWORD, REG_RESERVATION_TYPE,
  1431. Address, 0, REG_DWORD, REG_RESERVATION_ADDRESS,
  1432. ClientUID, ClientUIDSize, REG_BINARY, REG_RESERVATION_UID,
  1433. };
  1434. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1435. }
  1436. //BeginExport(function)
  1437. DWORD
  1438. DhcpRegOptSetAttributes(
  1439. IN PREG_HANDLE Hdl,
  1440. IN DWORD *OptionId,
  1441. IN LPWSTR *ClassName,
  1442. IN LPWSTR *VendorName,
  1443. IN DWORD *Flags,
  1444. IN LPBYTE *Value,
  1445. IN DWORD ValueSize
  1446. ) //EndExport(function)
  1447. {
  1448. DWORD Error;
  1449. WATTRIB_TBL Table[] = {
  1450. OptionId, 0, REG_DWORD, REG_OPTION_ID,
  1451. ClassName, 0, REG_SZ, REG_OPTION_CLASSNAME,
  1452. VendorName, 0, REG_SZ, REG_OPTION_VENDORNAME,
  1453. Flags, 0, REG_DWORD, REG_OPTION_TYPE,
  1454. Value, ValueSize,REG_BINARY, REG_OPTION_VALUE,
  1455. };
  1456. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1457. }
  1458. //================================================================================
  1459. // recursive deleting of keys...
  1460. //================================================================================
  1461. //BeginExport(function)
  1462. DWORD
  1463. DhcpRegRecurseDelete(
  1464. IN PREG_HANDLE Hdl,
  1465. IN LPWSTR KeyName
  1466. ) //EndExport(function)
  1467. {
  1468. REG_HANDLE Hdl2;
  1469. DWORD Error;
  1470. DWORD LocalError, RetError;
  1471. ARRAY Array; // sub keys
  1472. ARRAY_LOCATION Loc;
  1473. LPWSTR SubKey;
  1474. RetError = ERROR_SUCCESS;
  1475. Error = DhcpRegGetNextHdl(Hdl, KeyName, &Hdl2);
  1476. if( ERROR_SUCCESS != Error ) return Error;
  1477. Error = MemArrayInit(&Array);
  1478. if( ERROR_SUCCESS != Error ) {
  1479. LocalError = DhcpRegCloseHdl(&Hdl2);
  1480. Require(ERROR_SUCCESS == LocalError);
  1481. return Error;
  1482. }
  1483. Error = DhcpRegFillSubKeys(&Hdl2, &Array);
  1484. Require( ERROR_SUCCESS == Error );
  1485. Error = MemArrayInitLoc(&Array, &Loc);
  1486. while(ERROR_FILE_NOT_FOUND != Error) {
  1487. Require(ERROR_SUCCESS == Error);
  1488. Error = MemArrayGetElement(&Array, &Loc, (LPVOID *)&SubKey);
  1489. Require(ERROR_SUCCESS == Error && SubKey);
  1490. Error = DhcpRegRecurseDelete(&Hdl2, SubKey);
  1491. if( ERROR_SUCCESS != Error ) RetError = Error;
  1492. if( SubKey ) MemFree(SubKey);
  1493. Error = MemArrayNextLoc(&Array, &Loc);
  1494. }
  1495. Error = MemArrayCleanup(&Array);
  1496. Require(ERROR_SUCCESS == Error);
  1497. Error = DhcpRegCloseHdl(&Hdl2);
  1498. Require(ERROR_SUCCESS == Error);
  1499. Error = RegDeleteKey(Hdl->Key, KeyName);
  1500. if( ERROR_SUCCESS != Error ) RetError = Error;
  1501. return RetError;
  1502. }
  1503. //BeginExport(function)
  1504. DWORD
  1505. DhcpRegRecurseDeleteBunch(
  1506. IN PREG_HANDLE Hdl,
  1507. IN PARRAY KeysArray
  1508. ) //EndExport(function)
  1509. {
  1510. ARRAY_LOCATION Loc;
  1511. LPWSTR ThisKeyName;
  1512. DWORD Error;
  1513. Error = MemArrayInitLoc(KeysArray, &Loc);
  1514. while( ERROR_FILE_NOT_FOUND != Error ) {
  1515. Require(ERROR_SUCCESS == Error);
  1516. Error = MemArrayGetElement(KeysArray, &Loc, &ThisKeyName);
  1517. Require(ERROR_SUCCESS == Error && NULL != ThisKeyName);
  1518. Error = DhcpRegRecurseDelete(Hdl, ThisKeyName);
  1519. if( ERROR_SUCCESS != Error ) return Error;
  1520. Error = MemArrayNextLoc(KeysArray, &Loc);
  1521. }
  1522. return ERROR_SUCCESS;
  1523. }
  1524. static
  1525. VOID
  1526. GetLocalFileTime( // fill in filetime struct w/ current local time
  1527. IN OUT LPFILETIME Time // struct to fill in
  1528. )
  1529. {
  1530. BOOL Status;
  1531. SYSTEMTIME SysTime;
  1532. GetSystemTime(&SysTime); // get sys time as UTC time.
  1533. Status = SystemTimeToFileTime(&SysTime,Time); // conver system time to file time
  1534. if( FALSE == Status ) { // convert failed?
  1535. Time->dwLowDateTime = 0xFFFFFFFF; // set time to weird value in case of failiure
  1536. Time->dwHighDateTime = 0xFFFFFFFF;
  1537. }
  1538. }
  1539. //BeginExport(function)
  1540. DWORD
  1541. DhcpRegUpdateTime( // update the last modified time
  1542. VOID
  1543. ) //EndExport(function)
  1544. {
  1545. FILETIME Time;
  1546. DWORD Err, Size;
  1547. HKEY hKey;
  1548. GetLocalFileTime(&Time); // first get current time
  1549. (*(LONGLONG *)&Time) += 10*1000*60*2; // 2 minutes (Filetime is in 100-nano seconds)
  1550. // HACK! the previous line is there as the DS takes a little while to update the
  1551. // last changed time..
  1552. Time.dwLowDateTime =Time.dwHighDateTime =0; // set time to "long back" initially
  1553. Err = RegOpenKeyEx // try to open the config key.
  1554. (
  1555. /* hKey */ HKEY_LOCAL_MACHINE,
  1556. /* lpSubKey */ REG_THIS_SERVER,
  1557. /* ulOptions */ 0 /* Reserved */ ,
  1558. /* samDesired */ KEY_ALL_ACCESS,
  1559. /* phkResult */ &hKey
  1560. );
  1561. if( ERROR_SUCCESS != Err ) return Err; // time is still set to ages back
  1562. Err = RegSetValueEx // now save the time value
  1563. (
  1564. /* hKey */ hKey,
  1565. /* lpValueName */ DHCP_LAST_DOWNLOAD_TIME_VALUE,
  1566. /* lpReserved */ 0,
  1567. /* lpType */ REG_BINARY,
  1568. /* lpData */ (LPBYTE)&Time,
  1569. /* lpcData */ sizeof(Time)
  1570. );
  1571. RegCloseKey(hKey); // close key before we forget
  1572. return Err;
  1573. }
  1574. //================================================================================
  1575. // end of file
  1576. //================================================================================