Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1781 lines
61 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. Error = ERROR_SUCCESS;
  540. for( Index = 0; Index < sizeof(Table)/sizeof(Table[0]); Index ++ ) {
  541. if( NULL == Table[Index].Array ) continue;
  542. Error = DhcpRegGetNextHdl(Hdl, Table[Index].Location, &Hdl2);
  543. if( ERROR_SUCCESS != Error ) return Error;
  544. Error = DhcpRegFillSubKeys(&Hdl2, Table[Index].Array);
  545. LocalError = DhcpRegCloseHdl(&Hdl2);
  546. Require(ERROR_SUCCESS == LocalError);
  547. if( ERROR_SUCCESS != Error ) return Error;
  548. }
  549. return Error;
  550. }
  551. //BeginExport(function)
  552. DWORD
  553. DhcpRegSubnetGetExclusions(
  554. IN PREG_HANDLE Hdl,
  555. OUT LPBYTE *Excl,
  556. OUT DWORD *ExclSize
  557. ) //EndExport(function)
  558. {
  559. DWORD Error;
  560. DWORD Size;
  561. DWORD Type;
  562. if( NULL == Excl ) return ERROR_SUCCESS;
  563. Size = 0;
  564. Error = RegQueryValueEx(
  565. Hdl->Key,
  566. REG_SUBNET_EXCL,
  567. NullReserved,
  568. &Type,
  569. NULL,
  570. &Size
  571. );
  572. if( ERROR_SUCCESS != Error ) return Error;
  573. *Excl = NULL;
  574. *ExclSize = 0;
  575. if( 0 == Size ) return ERROR_SUCCESS;
  576. *Excl = MemAlloc(Size);
  577. if( NULL == *Excl ) return ERROR_NOT_ENOUGH_MEMORY;
  578. *ExclSize = Size;
  579. Error = RegQueryValueEx(
  580. Hdl->Key,
  581. REG_SUBNET_EXCL,
  582. NullReserved,
  583. &Type,
  584. *Excl,
  585. ExclSize
  586. );
  587. if( ERROR_SUCCESS != Error ) {
  588. MemFree(*Excl);
  589. *Excl = NULL;
  590. }
  591. return Error;
  592. }
  593. //BeginExport(function)
  594. DWORD
  595. DhcpRegSubnetGetList(
  596. IN PREG_HANDLE Hdl,
  597. IN OUT PARRAY Servers,
  598. IN OUT PARRAY IpRanges,
  599. IN OUT PARRAY Reservations,
  600. IN OUT PARRAY Options,
  601. OUT LPBYTE *Excl,
  602. OUT DWORD *ExclSizeInBytes
  603. ) //EndExport(function)
  604. {
  605. DWORD Error;
  606. DWORD LocalError;
  607. DWORD Index;
  608. REG_HANDLE Hdl2;
  609. struct {
  610. PARRAY Array;
  611. LPWSTR Location;
  612. } Table[] = {
  613. Servers, REG_SUBNET_SERVERS,
  614. IpRanges, REG_SUBNET_RANGES,
  615. Reservations, REG_SUBNET_RESERVATIONS,
  616. Options, REG_SUBNET_OPTIONS,
  617. // Exclusions are to be handled a bit differently
  618. };
  619. for( Index = 0; Index < sizeof(Table)/sizeof(Table[0]); Index ++ ) {
  620. if( NULL == Table[Index].Array ) continue;
  621. Error = DhcpRegGetNextHdl(Hdl, Table[Index].Location, &Hdl2);
  622. if( ERROR_SUCCESS != Error ) return Error;
  623. Error = DhcpRegFillSubKeys(&Hdl2, Table[Index].Array);
  624. LocalError = DhcpRegCloseHdl(&Hdl2);
  625. Require(ERROR_SUCCESS == LocalError);
  626. if( ERROR_SUCCESS != Error ) return Error;
  627. }
  628. // Now read the exclusions from off here
  629. return DhcpRegSubnetGetExclusions(Hdl, Excl, ExclSizeInBytes );
  630. }
  631. //BeginExport(function)
  632. DWORD
  633. DhcpRegSScopeGetList(
  634. IN PREG_HANDLE Hdl,
  635. IN OUT PARRAY Subnets
  636. ) //EndExport(function)
  637. {
  638. return DhcpRegFillSubKeys(Hdl, Subnets);
  639. }
  640. //BeginExport(function)
  641. DWORD
  642. DhcpRegReservationGetList(
  643. IN PREG_HANDLE Hdl,
  644. IN OUT PARRAY Options
  645. ) //EndExport(function)
  646. {
  647. return DhcpRegFillSubKeys(Hdl, Options);
  648. }
  649. //BeginExport(comment)
  650. //================================================================================
  651. // the separate stuff are here -- these are not list stuff, but just simple
  652. // single valued attributes
  653. // some of these actually, dont even go to the registry, but that's fine alright?
  654. //================================================================================
  655. //EndExport(comment)
  656. //BeginExport(function)
  657. DWORD
  658. DhcpRegServerGetAttributes(
  659. IN PREG_HANDLE Hdl,
  660. OUT LPWSTR *Name,
  661. OUT LPWSTR *Comment,
  662. OUT DWORD *Flags
  663. // more attributes will come here soon?
  664. ) //EndExport(function)
  665. {
  666. if( Name ) *Name = NULL;
  667. if( Comment ) *Comment = NULL;
  668. if( Flags ) *Flags = 0;
  669. return ERROR_SUCCESS;
  670. }
  671. //BeginExport(function)
  672. DWORD
  673. DhcpRegSubnetGetAttributes(
  674. IN PREG_HANDLE Hdl,
  675. OUT LPWSTR *Name,
  676. OUT LPWSTR *Comment,
  677. OUT DWORD *Flags,
  678. OUT DWORD *Address,
  679. OUT DWORD *Mask
  680. ) //EndExport(function)
  681. {
  682. DWORD fSwitched;
  683. if( Name ) *Name = DhcpRegRead(Hdl, REG_SZ, REG_SUBNET_NAME, NULL);
  684. if( Comment ) *Comment = DhcpRegRead(Hdl, REG_SZ, REG_SUBNET_COMMENT, NULL);
  685. if( Flags ) {
  686. *Flags = PtrToUlong(DhcpRegRead(Hdl, REG_DWORD, REG_SUBNET_STATE, (LPVOID)REG_DEFAULT_SUBNET_STATE));
  687. fSwitched = PtrToUlong(DhcpRegRead(Hdl, REG_DWORD, REG_SUBNET_SWITCHED_FLAG, (LPVOID)REG_DEFAULT_SWITCHED_FLAG));
  688. if(fSwitched) SWITCHED(( DHCP_SUBNET_STATE * ) Flags);
  689. }
  690. if( Address )
  691. *Address = PtrToUlong(DhcpRegRead(Hdl, REG_DWORD, REG_SUBNET_ADDRESS, (LPVOID)0));
  692. if( Mask ) *Mask = PtrToUlong(DhcpRegRead(Hdl, REG_DWORD, REG_SUBNET_MASK, ULongToPtr(REG_DEFAULT_SUBNET_MASK)));
  693. return ERROR_SUCCESS;
  694. }
  695. typedef struct {
  696. LPVOID RetPtr;
  697. LPWSTR ValueName;
  698. DWORD ValueType;
  699. LPVOID Defaults;
  700. } ATTRIB_TBL, *PATTRIB_TBL, *LPATTRIB_TBL;
  701. VOID
  702. DhcpRegFillAttribTable(
  703. IN PREG_HANDLE Hdl,
  704. IN PATTRIB_TBL Table,
  705. IN DWORD TableSize
  706. ) {
  707. DWORD i;
  708. PVOID Tmp;
  709. for( i = 0; i < TableSize ; i ++ ) {
  710. if( NULL == Table[i].RetPtr) continue;
  711. Tmp = DhcpRegRead(
  712. Hdl,
  713. Table[i].ValueType,
  714. Table[i].ValueName,
  715. Table[i].Defaults
  716. );
  717. if( REG_DWORD == Table[i].ValueType ) {
  718. *((DWORD *)Table[i].RetPtr) = PtrToUlong(Tmp);
  719. } else {
  720. *((LPVOID *)Table[i].RetPtr) = Tmp;
  721. }
  722. }
  723. }
  724. //
  725. // Hack O Rama -- This routine returns ERROR_INVALID_DATA if
  726. // the registry has been upgraded from pre-win2k build to win2k.
  727. // So that defaults can be chosen for ScopeId etc.
  728. //
  729. //BeginExport(function)
  730. DWORD
  731. DhcpRegMScopeGetAttributes(
  732. IN PREG_HANDLE Hdl,
  733. OUT LPWSTR *Comments,
  734. OUT DWORD *State,
  735. OUT DWORD *ScopeId,
  736. OUT DWORD *Policy,
  737. OUT DWORD *TTL,
  738. OUT LPWSTR *LangTag,
  739. OUT PDATE_TIME *ExpiryTime
  740. ) //EndExport(function)
  741. {
  742. DATE_TIME DefaultExpiryTime = {DHCP_DATE_TIME_INFINIT_LOW, DHCP_DATE_TIME_INFINIT_HIGH};
  743. LPWSTR DefaultLangTag = L"en-US";
  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. Policy, REG_MSCOPE_ADDR_POLICY, REG_DWORD, (LPVOID)0,
  749. TTL, REG_MSCOPE_TTL, REG_DWORD, (LPVOID)DEFAULT_MCAST_TTL,
  750. LangTag, REG_MSCOPE_LANG_TAG, REG_SZ, (LPVOID)0,
  751. ExpiryTime, REG_MSCOPE_EXPIRY_TIME, REG_BINARY, (LPVOID)0
  752. };
  753. DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  754. if (*LangTag == 0) {
  755. *LangTag = MemAlloc(wcslen((DefaultLangTag)+1)*sizeof(WCHAR));
  756. if (*LangTag) {
  757. wcscpy(*LangTag, DefaultLangTag);
  758. } else {
  759. return ERROR_NOT_ENOUGH_MEMORY;
  760. }
  761. }
  762. if (*ExpiryTime == 0) {
  763. *ExpiryTime = MemAlloc(sizeof (DefaultExpiryTime));
  764. if (*ExpiryTime) {
  765. **ExpiryTime = DefaultExpiryTime;
  766. } else {
  767. return ERROR_NOT_ENOUGH_MEMORY;
  768. }
  769. }
  770. return ERROR_SUCCESS;
  771. }
  772. //BeginExport(function)
  773. DWORD
  774. DhcpRegOptDefGetAttributes(
  775. IN PREG_HANDLE Hdl,
  776. OUT LPWSTR *Name,
  777. OUT LPWSTR *Comments,
  778. OUT DWORD *Flags,
  779. OUT DWORD *OptionId,
  780. OUT LPWSTR *ClassName,
  781. OUT LPWSTR *VendorName,
  782. OUT LPBYTE *Value,
  783. OUT DWORD *ValueSize
  784. ) //EndExport(function)
  785. {
  786. DWORD Error;
  787. ATTRIB_TBL Table[] = {
  788. Name, REG_OPTION_NAME, REG_SZ, NULL,
  789. Comments, REG_OPTION_COMMENT, REG_SZ, NULL,
  790. ClassName, REG_OPTION_CLASSNAME, REG_SZ, NULL,
  791. VendorName, REG_OPTION_VENDORNAME, REG_SZ, NULL,
  792. Flags, REG_OPTION_TYPE, REG_DWORD, (LPVOID)0,
  793. OptionId, REG_OPTION_ID, REG_DWORD, (LPVOID)0
  794. };
  795. DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  796. if( Value ) {
  797. Error = DhcpRegReadBinary(Hdl, REG_OPTION_VALUE, Value, ValueSize);
  798. Require(*Value);
  799. }
  800. return ERROR_SUCCESS;
  801. }
  802. //BeginExport(function)
  803. DWORD
  804. DhcpRegSScopeGetAttributes( // superscopes dont have any information stored.. dont use this
  805. IN PREG_HANDLE Hdl,
  806. OUT LPWSTR *Name,
  807. OUT LPWSTR *Comment,
  808. OUT DWORD *Flags
  809. ) //EndExport(function)
  810. {
  811. Require(FALSE);
  812. return ERROR_INVALID_PARAMETER;
  813. }
  814. //BeginExport(function)
  815. DWORD
  816. DhcpRegClassDefGetAttributes(
  817. IN PREG_HANDLE Hdl,
  818. OUT LPWSTR *Name,
  819. OUT LPWSTR *Comment,
  820. OUT DWORD *Flags,
  821. OUT LPBYTE *Value,
  822. OUT DWORD *ValueSize
  823. ) //EndExport(function)
  824. {
  825. DWORD Error;
  826. ATTRIB_TBL Table[] = {
  827. Name, REG_CLASSDEF_NAME, REG_SZ, NULL,
  828. Comment, REG_CLASSDEF_COMMENT, REG_SZ, NULL,
  829. Flags, REG_CLASSDEF_TYPE, REG_DWORD, (LPVOID)0
  830. };
  831. DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  832. if( Value ) {
  833. Error = DhcpRegReadBinary(Hdl, REG_CLASSDEF_VALUE, Value, ValueSize);
  834. Require(*Value);
  835. }
  836. return ERROR_SUCCESS;
  837. }
  838. //BeginExport(function)
  839. DWORD
  840. DhcpRegSubnetServerGetAttributes(
  841. IN PREG_HANDLE Hdl,
  842. OUT LPWSTR *Name,
  843. OUT LPWSTR *Comment,
  844. OUT DWORD *Flags,
  845. OUT DWORD *Address,
  846. OUT DWORD *Role
  847. ) //EndExport(function)
  848. {
  849. ATTRIB_TBL Table[] = {
  850. Name, REG_SUB_SERVER_NAME, REG_SZ, NULL,
  851. Comment, REG_SUB_SERVER_COMMENT,REG_SZ, NULL,
  852. Flags, REG_FLAGS, REG_DWORD, (LPVOID)0,
  853. Address, REG_SUB_SERVER_ADDRESS,REG_DWORD, (LPVOID)0,
  854. Role, REG_SUB_SERVER_ROLE, REG_DWORD, (LPVOID)0
  855. };
  856. DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  857. return ERROR_SUCCESS;
  858. }
  859. //BeginExport(function)
  860. DWORD
  861. DhcpRegRangeGetAttributes(
  862. IN PREG_HANDLE Hdl,
  863. OUT LPWSTR *Name,
  864. OUT LPWSTR *Comment,
  865. OUT DWORD *Flags,
  866. OUT ULONG *AllocCount,
  867. OUT ULONG *MaxAllocCount,
  868. OUT DWORD *StartAddress,
  869. OUT DWORD *EndAddress,
  870. OUT LPBYTE *InUseClusters,
  871. OUT DWORD *InUseClusterSize,
  872. OUT LPBYTE *UsedClusters,
  873. OUT DWORD *UsedClustersSize
  874. ) //EndExport(function)
  875. {
  876. DWORD Error;
  877. ATTRIB_TBL Table[] = {
  878. Name, REG_RANGE_NAME, REG_SZ, NULL,
  879. Comment, REG_RANGE_COMMENT, REG_SZ, NULL,
  880. Flags, REG_RANGE_FLAGS, REG_DWORD, (LPVOID)(DEF_RANGE_FLAG_VAL),
  881. AllocCount, REG_RANGE_ALLOC, REG_DWORD, (LPVOID)(DEF_RANGE_ALLOC),
  882. MaxAllocCount, REG_RANGE_MAX_ALLOC, REG_DWORD, (LPVOID)(ULONG_PTR)(DEF_RANGE_MAX_ALLOC),
  883. StartAddress, REG_RANGE_START_ADDRESS, REG_DWORD, (LPVOID)0,
  884. EndAddress, REG_RANGE_END_ADDRESS, REG_DWORD, (LPVOID)0
  885. };
  886. DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  887. if( InUseClusters ) {
  888. Error = DhcpRegReadBinary(Hdl, REG_RANGE_INUSE_CLUSTERS, InUseClusters, InUseClusterSize);
  889. //Require(ERROR_SUCCESS == Error); //-- after registry changed, NO_SUCH_FILE could come up here as well.
  890. }
  891. if( UsedClusters ) {
  892. Error = DhcpRegReadBinary(Hdl, REG_RANGE_USED_CLUSTERS, UsedClusters, UsedClustersSize);
  893. //Require(ERROR_SUCCESS == Error); //-- after registry changed, NO_SUCH_FILE could come up here as well.
  894. }
  895. return ERROR_SUCCESS;
  896. }
  897. //BeginExport(function)
  898. DWORD
  899. DhcpRegReservationGetAttributes(
  900. IN PREG_HANDLE Hdl,
  901. OUT LPWSTR *Name,
  902. OUT LPWSTR *Comment,
  903. OUT DWORD *Flags,
  904. OUT DWORD *Address,
  905. OUT LPBYTE *ClientUID,
  906. OUT DWORD *ClientUIDSize
  907. ) //EndExport(function)
  908. {
  909. DWORD Error;
  910. DWORD deftype = DEF_RESERVATION_TYPE;
  911. ATTRIB_TBL Table[] = {
  912. Name, REG_RESERVATION_NAME, REG_SZ, NULL,
  913. Comment, REG_RESERVATION_COMMENT, REG_SZ, NULL,
  914. Flags, REG_RESERVATION_TYPE, REG_DWORD, ULongToPtr(deftype),
  915. Address, REG_RESERVATION_ADDRESS, REG_DWORD, (LPVOID)0,
  916. };
  917. DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  918. if( ClientUID ) {
  919. Error = DhcpRegReadBinary(Hdl, REG_RESERVATION_UID, ClientUID, ClientUIDSize);
  920. Require(ERROR_SUCCESS == Error);
  921. }
  922. return ERROR_SUCCESS;
  923. }
  924. //BeginExport(function)
  925. DWORD
  926. DhcpRegOptGetAttributes(
  927. IN PREG_HANDLE Hdl,
  928. OUT DWORD *OptionId,
  929. OUT LPWSTR *ClassName,
  930. OUT LPWSTR *VendorName,
  931. OUT DWORD *Flags,
  932. OUT LPBYTE *Value,
  933. OUT DWORD *ValueSize
  934. ) //EndExport(function)
  935. {
  936. DWORD Error;
  937. ATTRIB_TBL Table[] = {
  938. OptionId, REG_OPTION_ID, REG_DWORD, (LPVOID)0,
  939. ClassName, REG_OPTION_CLASSNAME, REG_SZ, NULL,
  940. VendorName, REG_OPTION_VENDORNAME, REG_SZ, NULL,
  941. Flags, REG_OPTION_TYPE, REG_DWORD, (LPVOID)0,
  942. };
  943. DhcpRegFillAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  944. if( Value ) {
  945. Error = DhcpRegReadBinary(Hdl, REG_OPTION_VALUE, Value, ValueSize);
  946. }
  947. return ERROR_SUCCESS;
  948. }
  949. //BeginExport(comment)
  950. //================================================================================
  951. // the following functiosn help in writing to the registry
  952. //================================================================================
  953. //EndExport(comment)
  954. typedef struct {
  955. LPVOID Value;
  956. DWORD Size;
  957. DWORD Type;
  958. LPWSTR ValueName;
  959. } WATTRIB_TBL, *PWATTRIB_TBL, *LPWATTRIB_TBL;
  960. DWORD
  961. DhcpRegSaveAttribTable(
  962. IN PREG_HANDLE Hdl,
  963. IN PWATTRIB_TBL Table,
  964. IN DWORD Size
  965. )
  966. {
  967. DWORD i;
  968. DWORD Error;
  969. DWORD PtrSize;
  970. LPBYTE Ptr;
  971. for(i = 0; i < Size; i ++ ) {
  972. if( NULL == Table[i].Value ) continue;
  973. PtrSize = Table[i].Size;
  974. Ptr = *(LPBYTE *)Table[i].Value;
  975. switch(Table[i].Type) {
  976. case REG_SZ:
  977. if( NULL == *(LPWSTR *)Table[i].Value) { PtrSize = sizeof(WCHAR); Ptr = (LPBYTE)L""; break; }
  978. PtrSize = sizeof(WCHAR)*(wcslen(*((LPWSTR *)Table[i].Value))+1);
  979. Ptr = *(LPBYTE *)Table[i].Value;
  980. break;
  981. case REG_DWORD:
  982. PtrSize = sizeof(DWORD);
  983. Ptr = Table[i].Value; // This is because we deref this ptr down below..
  984. break;
  985. }
  986. Error = RegSetValueEx(
  987. Hdl->Key,
  988. Table[i].ValueName,
  989. ZeroReserved,
  990. Table[i].Type,
  991. Ptr,
  992. PtrSize
  993. );
  994. if( ERROR_SUCCESS != Error ) {
  995. return Error;
  996. }
  997. }
  998. return ERROR_SUCCESS;
  999. }
  1000. //BeginExport(functions)
  1001. DWORD
  1002. DhcpRegSaveSubKeys(
  1003. IN PREG_HANDLE Hdl,
  1004. IN OUT PARRAY Array
  1005. ) //EndExport(function)
  1006. {
  1007. ARRAY_LOCATION Loc;
  1008. DWORD Error;
  1009. REG_HANDLE Hdl2;
  1010. LPWSTR KeyName;
  1011. Error = MemArrayInitLoc(Array, &Loc);
  1012. while(ERROR_FILE_NOT_FOUND != Error ) {
  1013. Require(ERROR_SUCCESS == Error);
  1014. Error = MemArrayGetElement(Array, &Loc, (LPVOID *)&KeyName);
  1015. Require(ERROR_SUCCESS == Error && NULL != KeyName);
  1016. Error = DhcpRegGetNextHdl(Hdl, KeyName, &Hdl2);
  1017. if( ERROR_SUCCESS != Error ) return Error;
  1018. Error = DhcpRegCloseHdl(&Hdl2);
  1019. Require(ERROR_SUCCESS == Error);
  1020. Error = MemArrayNextLoc(Array, &Loc);
  1021. }
  1022. return ERROR_SUCCESS;
  1023. }
  1024. //BeginExport(functions)
  1025. DWORD
  1026. DhcpRegSaveSubKeysPrefixed(
  1027. IN PREG_HANDLE Hdl,
  1028. IN OUT PARRAY Array,
  1029. IN LPWSTR CommonPrefix
  1030. ) //EndExport(function)
  1031. {
  1032. ARRAY_LOCATION Loc;
  1033. DWORD Error;
  1034. REG_HANDLE Hdl2;
  1035. LPWSTR KeyName;
  1036. Error = MemArrayInitLoc(Array, &Loc);
  1037. while(ERROR_FILE_NOT_FOUND != Error ) {
  1038. Require(ERROR_SUCCESS == Error);
  1039. Error = MemArrayGetElement(Array, &Loc, (LPVOID *)&KeyName);
  1040. Require(ERROR_SUCCESS == Error && NULL != KeyName);
  1041. Error = DhcpRegGetNextNextHdl(Hdl, CommonPrefix, KeyName, &Hdl2);
  1042. if( ERROR_SUCCESS != Error ) return Error;
  1043. Error = DhcpRegCloseHdl(&Hdl2);
  1044. Require(ERROR_SUCCESS == Error);
  1045. Error = MemArrayNextLoc(Array, &Loc);
  1046. }
  1047. return ERROR_SUCCESS;
  1048. }
  1049. //BeginExport(function)
  1050. DWORD
  1051. DhcpRegServerSetList(
  1052. IN PREG_HANDLE Hdl,
  1053. IN PARRAY OptList, // list of LPWSTR options
  1054. IN PARRAY OptDefList, // list of LPWSTR optdefs
  1055. IN PARRAY Subnets, // list of LPWSTR subnets
  1056. IN PARRAY SScopes, // list of LPWSTR sscopes
  1057. IN PARRAY ClassDefs, // list of LPWSTR classes
  1058. IN PARRAY MScopes // list of LPWSTR mscopes
  1059. ) //EndExport(function)
  1060. {
  1061. DWORD Error;
  1062. DWORD LocalError;
  1063. DWORD Index;
  1064. REG_HANDLE Hdl2;
  1065. struct {
  1066. PARRAY Array;
  1067. LPWSTR Location;
  1068. } Table[] = {
  1069. OptList, REG_SERVER_GLOBAL_OPTIONS,
  1070. OptDefList, REG_SERVER_OPTDEFS,
  1071. Subnets, REG_SERVER_SUBNETS,
  1072. SScopes, REG_SERVER_SSCOPES,
  1073. ClassDefs, REG_SERVER_CLASSDEFS,
  1074. MScopes, REG_SERVER_MSCOPES
  1075. };
  1076. Error = ERROR_SUCCESS;
  1077. for( Index = 0; Index < sizeof(Table)/sizeof(Table[0]); Index ++ ) {
  1078. if( NULL == Table[Index].Array ) continue;
  1079. Error = DhcpRegGetNextHdl(Hdl, Table[Index].Location, &Hdl2);
  1080. if( ERROR_SUCCESS != Error ) return Error;
  1081. Error = DhcpRegSaveSubKeys(&Hdl2, Table[Index].Array);
  1082. LocalError = DhcpRegCloseHdl(&Hdl2);
  1083. Require(ERROR_SUCCESS == LocalError);
  1084. if( ERROR_SUCCESS != Error ) return Error;
  1085. }
  1086. return Error;
  1087. }
  1088. //BeginExport(function)
  1089. DWORD
  1090. DhcpRegSubnetSetExclusions(
  1091. IN PREG_HANDLE Hdl,
  1092. IN LPBYTE *Excl,
  1093. IN DWORD ExclSize
  1094. ) //EndExport(function)
  1095. {
  1096. DWORD Error;
  1097. WATTRIB_TBL Table[] = {
  1098. (LPVOID*)Excl, ExclSize, REG_BINARY, REG_SUBNET_EXCL,
  1099. };
  1100. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1101. }
  1102. //BeginExport(function)
  1103. DWORD
  1104. DhcpRegSubnetSetList(
  1105. IN PREG_HANDLE Hdl,
  1106. IN PARRAY Servers,
  1107. IN PARRAY IpRanges,
  1108. IN PARRAY Reservations,
  1109. IN PARRAY Options,
  1110. IN LPBYTE *Excl,
  1111. IN DWORD ExclSizeInBytes
  1112. ) //EndExport(function)
  1113. {
  1114. DWORD Error;
  1115. DWORD LocalError;
  1116. DWORD Index;
  1117. REG_HANDLE Hdl2;
  1118. struct {
  1119. PARRAY Array;
  1120. LPWSTR Location;
  1121. } Table[] = {
  1122. Servers, REG_SUBNET_SERVERS,
  1123. IpRanges, REG_SUBNET_RANGES,
  1124. Reservations, REG_SUBNET_RESERVATIONS,
  1125. Options, REG_SUBNET_OPTIONS,
  1126. // Exclusions are to be handled a bit differently
  1127. };
  1128. for( Index = 0; Index < sizeof(Table)/sizeof(Table[0]); Index ++ ) {
  1129. if( NULL == Table[Index].Array ) continue;
  1130. Error = DhcpRegGetNextHdl(Hdl, Table[Index].Location, &Hdl2);
  1131. if( ERROR_SUCCESS != Error ) return Error;
  1132. Error = DhcpRegSaveSubKeys(&Hdl2, Table[Index].Array);
  1133. LocalError = DhcpRegCloseHdl(&Hdl2);
  1134. Require(ERROR_SUCCESS == LocalError);
  1135. if( ERROR_SUCCESS != Error ) return Error;
  1136. }
  1137. // Now read the exclusions from off here
  1138. return DhcpRegSubnetSetExclusions(Hdl, Excl, ExclSizeInBytes );
  1139. }
  1140. //BeginExport(function)
  1141. DWORD
  1142. DhcpRegSScopeSetList(
  1143. IN PREG_HANDLE Hdl,
  1144. IN OUT PARRAY Subnets
  1145. ) //EndExport(function)
  1146. {
  1147. return DhcpRegSaveSubKeys(Hdl, Subnets);
  1148. }
  1149. //BeginExport(function)
  1150. DWORD
  1151. DhcpRegReservationSetList(
  1152. IN PREG_HANDLE Hdl,
  1153. IN PARRAY Subnets
  1154. ) //EndExport(function)
  1155. {
  1156. return DhcpRegSaveSubKeys(Hdl, Subnets);
  1157. }
  1158. //BeginExport(comment)
  1159. //================================================================================
  1160. // the single stuff are here -- these are not list stuff, but just simple
  1161. // single valued attributes
  1162. // some of these actually, dont even go to the registry, but that's fine alright?
  1163. //================================================================================
  1164. //EndExport(comment)
  1165. //BeginExport(function)
  1166. DWORD
  1167. DhcpRegServerSetAttributes(
  1168. IN PREG_HANDLE Hdl,
  1169. IN LPWSTR *Name,
  1170. IN LPWSTR *Comment,
  1171. IN DWORD *Flags
  1172. // more attributes will come here soon?
  1173. ) //EndExport(function)
  1174. {
  1175. #if 0
  1176. WATTRIB_TBL Table[] = {
  1177. Name, REG_SERVER_NAME
  1178. }
  1179. if( Name ) *Name = NULL;
  1180. if( Comment ) *Comment = NULL;
  1181. if( Flags ) *Flags = 0;
  1182. #endif
  1183. return ERROR_SUCCESS;
  1184. }
  1185. DWORD
  1186. DhcpRegSubnetSetAttributesInternal(
  1187. IN PREG_HANDLE Hdl,
  1188. IN LPWSTR *Name,
  1189. IN LPWSTR *Comment,
  1190. IN DWORD *Flags,
  1191. IN DWORD *Address,
  1192. IN DWORD *Mask,
  1193. IN DWORD *SwitchedNetwork
  1194. )
  1195. {
  1196. DWORD Error, SrvIpAddress, SrvRole;
  1197. LPWSTR EmptyString;
  1198. REG_HANDLE Hdl2;
  1199. WATTRIB_TBL Table[] = {
  1200. Name, 0, REG_SZ, REG_SUBNET_NAME,
  1201. Comment, 0, REG_SZ, REG_SUBNET_COMMENT,
  1202. Flags, 0, REG_DWORD, REG_SUBNET_STATE,
  1203. Address, 0, REG_DWORD, REG_SUBNET_ADDRESS,
  1204. Mask, 0, REG_DWORD, REG_SUBNET_MASK,
  1205. SwitchedNetwork, 0, REG_DWORD, REG_SUBNET_SWITCHED_FLAG
  1206. };
  1207. Error = DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1208. if( NO_ERROR != Error ) return Error;
  1209. //
  1210. // The following lines are for backward compat with NT4.
  1211. //
  1212. //
  1213. // Create the reservation key in any case
  1214. //
  1215. Error = DhcpRegGetNextHdl(
  1216. Hdl, REG_SUBNET_RESERVATIONS, &Hdl2 );
  1217. if( NO_ERROR != Error ) return Error;
  1218. DhcpRegCloseHdl( &Hdl2 );
  1219. //
  1220. // Create the servers key
  1221. //
  1222. Error = DhcpRegGetNextHdl(
  1223. Hdl, L"DHCPServers", &Hdl2 );
  1224. if( NO_ERROR != Error ) return Error;
  1225. DhcpRegCloseHdl( &Hdl2 );
  1226. Error = DhcpRegGetNextNextHdl(
  1227. Hdl, L"DHCPServers", L"127.0.0.1", &Hdl2 );
  1228. if( NO_ERROR != Error ) return Error;
  1229. //
  1230. // Now set the role of the newly created server as primary
  1231. //
  1232. SrvIpAddress = INADDR_LOOPBACK;
  1233. SrvRole = 1; // primary
  1234. EmptyString = L"";
  1235. {
  1236. WATTRIB_TBL SrvTable[] = {
  1237. &SrvRole, 0, REG_DWORD, L"Role",
  1238. &SrvIpAddress, 0, REG_DWORD, L"ServerIpAddress",
  1239. &EmptyString, 0, REG_SZ, L"ServerHostName",
  1240. &EmptyString, 0, REG_SZ, L"ServerNetBiosName"
  1241. };
  1242. Error = DhcpRegSaveAttribTable(
  1243. &Hdl2, SrvTable, sizeof(SrvTable)/sizeof(SrvTable[0]));
  1244. }
  1245. DhcpRegCloseHdl(&Hdl2);
  1246. return Error;
  1247. }
  1248. //BeginExport(function)
  1249. DWORD
  1250. DhcpRegSubnetSetAttributes(
  1251. IN PREG_HANDLE Hdl,
  1252. IN LPWSTR *Name,
  1253. IN LPWSTR *Comment,
  1254. IN DWORD *Flags,
  1255. IN DWORD *Address,
  1256. IN DWORD *Mask
  1257. ) //EndExport(function)
  1258. {
  1259. DWORD xFlags, SwitchedNetwork = FALSE;
  1260. OSVERSIONINFO Ver;
  1261. Ver.dwOSVersionInfoSize = sizeof(Ver);
  1262. if( FALSE == GetVersionEx(&Ver) ) return GetLastError();
  1263. if( Flags && Ver.dwMajorVersion < 5 ) {
  1264. SwitchedNetwork = IS_SWITCHED(*Flags);
  1265. xFlags = IS_DISABLED(*Flags);
  1266. Flags = &xFlags;
  1267. }
  1268. return DhcpRegSubnetSetAttributesInternal(
  1269. Hdl, Name, Comment, Flags, Address, Mask,
  1270. Flags ? &SwitchedNetwork : NULL );
  1271. }
  1272. //BeginExport(function)
  1273. DWORD
  1274. DhcpRegMScopeSetAttributes(
  1275. IN PREG_HANDLE Hdl,
  1276. IN LPWSTR *Comments,
  1277. IN DWORD *State,
  1278. IN DWORD *ScopeId,
  1279. IN DWORD *Policy,
  1280. IN DWORD *TTL,
  1281. IN LPWSTR *LangTag,
  1282. IN PDATE_TIME *ExpiryTime
  1283. ) //EndExport(function)
  1284. {
  1285. WATTRIB_TBL Table[] = {
  1286. Comments, 0, REG_SZ, REG_MSCOPE_COMMENT,
  1287. State, 0, REG_DWORD, REG_MSCOPE_STATE,
  1288. ScopeId, 0, REG_DWORD, REG_MSCOPE_SCOPEID,
  1289. Policy, 0, REG_DWORD, REG_MSCOPE_ADDR_POLICY,
  1290. TTL, 0, REG_DWORD, REG_MSCOPE_TTL,
  1291. LangTag, 0, REG_SZ, REG_MSCOPE_LANG_TAG,
  1292. ExpiryTime, sizeof(**ExpiryTime), REG_BINARY, REG_MSCOPE_EXPIRY_TIME
  1293. };
  1294. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1295. }
  1296. //BeginExport(function)
  1297. DWORD
  1298. DhcpRegOptDefSetAttributes(
  1299. IN PREG_HANDLE Hdl,
  1300. IN LPWSTR *Name,
  1301. IN LPWSTR *Comments,
  1302. IN DWORD *Flags,
  1303. IN DWORD *OptionId,
  1304. IN LPWSTR *ClassName,
  1305. IN LPWSTR *VendorName,
  1306. IN LPBYTE *Value,
  1307. IN DWORD ValueSize
  1308. ) //EndExport(function)
  1309. {
  1310. DWORD Error;
  1311. WATTRIB_TBL Table[] = {
  1312. Name, 0, REG_SZ, REG_OPTION_NAME,
  1313. Comments, 0, REG_SZ, REG_OPTION_COMMENT,
  1314. ClassName, 0, REG_SZ, REG_OPTION_CLASSNAME,
  1315. VendorName, 0, REG_SZ, REG_OPTION_VENDORNAME,
  1316. Flags, 0, REG_DWORD, REG_OPTION_TYPE,
  1317. OptionId, 0, REG_DWORD, REG_OPTION_ID,
  1318. Value, ValueSize,REG_BINARY, REG_OPTION_VALUE
  1319. };
  1320. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1321. }
  1322. //BeginExport(function)
  1323. DWORD
  1324. DhcpRegSScopeSetAttributes( // superscopes dont have any information stored.. dont use this
  1325. IN PREG_HANDLE Hdl,
  1326. IN LPWSTR *Name,
  1327. IN LPWSTR *Comment,
  1328. IN DWORD *Flags
  1329. ) //EndExport(function)
  1330. {
  1331. Require(FALSE);
  1332. return ERROR_INVALID_PARAMETER;
  1333. }
  1334. //BeginExport(function)
  1335. DWORD
  1336. DhcpRegClassDefSetAttributes(
  1337. IN PREG_HANDLE Hdl,
  1338. IN LPWSTR *Name,
  1339. IN LPWSTR *Comment,
  1340. IN DWORD *Flags,
  1341. IN LPBYTE *Value,
  1342. IN DWORD ValueSize
  1343. ) //EndExport(function)
  1344. {
  1345. DWORD Error;
  1346. WATTRIB_TBL Table[] = {
  1347. Name, 0, REG_SZ, REG_CLASSDEF_NAME,
  1348. Comment, 0, REG_SZ, REG_CLASSDEF_COMMENT,
  1349. Flags, 0, REG_DWORD, REG_CLASSDEF_TYPE,
  1350. Value, ValueSize,REG_BINARY, REG_CLASSDEF_VALUE
  1351. };
  1352. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1353. }
  1354. //BeginExport(function)
  1355. DWORD
  1356. DhcpRegSubnetServerSetAttributes(
  1357. IN PREG_HANDLE Hdl,
  1358. IN LPWSTR *Name,
  1359. IN LPWSTR *Comment,
  1360. IN DWORD *Flags,
  1361. IN DWORD *Address,
  1362. IN DWORD *Role
  1363. ) //EndExport(function)
  1364. {
  1365. WATTRIB_TBL Table[] = {
  1366. Name, 0, REG_SZ, REG_SUB_SERVER_NAME,
  1367. Comment, 0, REG_SZ, REG_SUB_SERVER_COMMENT,
  1368. Flags, 0, REG_DWORD, REG_FLAGS,
  1369. Address, 0, REG_DWORD, REG_SUB_SERVER_ADDRESS,
  1370. Role, 0, REG_DWORD, REG_SUB_SERVER_ROLE,
  1371. };
  1372. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1373. }
  1374. //BeginExport(function)
  1375. DWORD
  1376. DhcpRegRangeSetAttributes(
  1377. IN PREG_HANDLE Hdl,
  1378. IN LPWSTR *Name,
  1379. IN LPWSTR *Comment,
  1380. IN DWORD *Flags,
  1381. IN ULONG *AllocCount,
  1382. IN ULONG *MaxAllocCount,
  1383. IN DWORD *StartAddress,
  1384. IN DWORD *EndAddress,
  1385. IN LPBYTE *InUseClusters,
  1386. IN DWORD InUseClusterSize,
  1387. IN LPBYTE *UsedClusters,
  1388. IN DWORD UsedClustersSize
  1389. ) //EndExport(function)
  1390. {
  1391. DWORD Error;
  1392. WATTRIB_TBL Table[] = {
  1393. Name, 0, REG_SZ, REG_RANGE_NAME,
  1394. Comment, 0, REG_SZ, REG_RANGE_COMMENT,
  1395. Flags, 0, REG_DWORD, REG_RANGE_FLAGS,
  1396. AllocCount, 0, REG_DWORD, REG_RANGE_ALLOC,
  1397. MaxAllocCount, 0, REG_DWORD, REG_RANGE_MAX_ALLOC,
  1398. StartAddress, 0, REG_DWORD, REG_RANGE_START_ADDRESS,
  1399. EndAddress, 0, REG_DWORD, REG_RANGE_END_ADDRESS,
  1400. InUseClusters, InUseClusterSize, REG_BINARY, REG_RANGE_INUSE_CLUSTERS,
  1401. UsedClusters, UsedClustersSize, REG_BINARY, REG_RANGE_USED_CLUSTERS,
  1402. };
  1403. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1404. }
  1405. //BeginExport(function)
  1406. DWORD
  1407. DhcpRegReservationSetAttributes(
  1408. IN PREG_HANDLE Hdl,
  1409. IN LPWSTR *Name,
  1410. IN LPWSTR *Comment,
  1411. IN DWORD *Flags,
  1412. IN DWORD *Address,
  1413. IN LPBYTE *ClientUID,
  1414. IN DWORD ClientUIDSize
  1415. ) //EndExport(function)
  1416. {
  1417. DWORD Error;
  1418. WATTRIB_TBL Table[] = {
  1419. Name, 0, REG_SZ, REG_RESERVATION_NAME,
  1420. Comment, 0, REG_SZ, REG_RESERVATION_COMMENT,
  1421. Flags, 0, REG_DWORD, REG_RESERVATION_TYPE,
  1422. Address, 0, REG_DWORD, REG_RESERVATION_ADDRESS,
  1423. ClientUID, ClientUIDSize, REG_BINARY, REG_RESERVATION_UID,
  1424. };
  1425. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1426. }
  1427. //BeginExport(function)
  1428. DWORD
  1429. DhcpRegOptSetAttributes(
  1430. IN PREG_HANDLE Hdl,
  1431. IN DWORD *OptionId,
  1432. IN LPWSTR *ClassName,
  1433. IN LPWSTR *VendorName,
  1434. IN DWORD *Flags,
  1435. IN LPBYTE *Value,
  1436. IN DWORD ValueSize
  1437. ) //EndExport(function)
  1438. {
  1439. DWORD Error;
  1440. WATTRIB_TBL Table[] = {
  1441. OptionId, 0, REG_DWORD, REG_OPTION_ID,
  1442. ClassName, 0, REG_SZ, REG_OPTION_CLASSNAME,
  1443. VendorName, 0, REG_SZ, REG_OPTION_VENDORNAME,
  1444. Flags, 0, REG_DWORD, REG_OPTION_TYPE,
  1445. Value, ValueSize,REG_BINARY, REG_OPTION_VALUE,
  1446. };
  1447. return DhcpRegSaveAttribTable(Hdl, Table, sizeof(Table)/sizeof(Table[0]));
  1448. }
  1449. //================================================================================
  1450. // recursive deleting of keys...
  1451. //================================================================================
  1452. //BeginExport(function)
  1453. DWORD
  1454. DhcpRegRecurseDelete(
  1455. IN PREG_HANDLE Hdl,
  1456. IN LPWSTR KeyName
  1457. ) //EndExport(function)
  1458. {
  1459. REG_HANDLE Hdl2;
  1460. DWORD Error;
  1461. DWORD LocalError, RetError;
  1462. ARRAY Array; // sub keys
  1463. ARRAY_LOCATION Loc;
  1464. LPWSTR SubKey;
  1465. RetError = ERROR_SUCCESS;
  1466. Error = DhcpRegGetNextHdl(Hdl, KeyName, &Hdl2);
  1467. if( ERROR_SUCCESS != Error ) return Error;
  1468. Error = MemArrayInit(&Array);
  1469. if( ERROR_SUCCESS != Error ) {
  1470. LocalError = DhcpRegCloseHdl(&Hdl2);
  1471. Require(ERROR_SUCCESS == LocalError);
  1472. return Error;
  1473. }
  1474. Error = DhcpRegFillSubKeys(&Hdl2, &Array);
  1475. Require( ERROR_SUCCESS == Error );
  1476. Error = MemArrayInitLoc(&Array, &Loc);
  1477. while(ERROR_FILE_NOT_FOUND != Error) {
  1478. Require(ERROR_SUCCESS == Error);
  1479. Error = MemArrayGetElement(&Array, &Loc, (LPVOID *)&SubKey);
  1480. Require(ERROR_SUCCESS == Error && SubKey);
  1481. Error = DhcpRegRecurseDelete(&Hdl2, SubKey);
  1482. if( ERROR_SUCCESS != Error ) RetError = Error;
  1483. if( SubKey ) MemFree(SubKey);
  1484. Error = MemArrayNextLoc(&Array, &Loc);
  1485. }
  1486. Error = MemArrayCleanup(&Array);
  1487. Require(ERROR_SUCCESS == Error);
  1488. Error = DhcpRegCloseHdl(&Hdl2);
  1489. Require(ERROR_SUCCESS == Error);
  1490. Error = RegDeleteKey(Hdl->Key, KeyName);
  1491. if( ERROR_SUCCESS != Error ) RetError = Error;
  1492. return RetError;
  1493. }
  1494. //BeginExport(function)
  1495. DWORD
  1496. DhcpRegRecurseDeleteBunch(
  1497. IN PREG_HANDLE Hdl,
  1498. IN PARRAY KeysArray
  1499. ) //EndExport(function)
  1500. {
  1501. ARRAY_LOCATION Loc;
  1502. LPWSTR ThisKeyName;
  1503. DWORD Error;
  1504. Error = MemArrayInitLoc(KeysArray, &Loc);
  1505. while( ERROR_FILE_NOT_FOUND != Error ) {
  1506. Require(ERROR_SUCCESS == Error);
  1507. Error = MemArrayGetElement(KeysArray, &Loc, &ThisKeyName);
  1508. Require(ERROR_SUCCESS == Error && NULL != ThisKeyName);
  1509. Error = DhcpRegRecurseDelete(Hdl, ThisKeyName);
  1510. if( ERROR_SUCCESS != Error ) return Error;
  1511. Error = MemArrayNextLoc(KeysArray, &Loc);
  1512. }
  1513. return ERROR_SUCCESS;
  1514. }
  1515. static
  1516. VOID
  1517. GetLocalFileTime( // fill in filetime struct w/ current local time
  1518. IN OUT LPFILETIME Time // struct to fill in
  1519. )
  1520. {
  1521. BOOL Status;
  1522. SYSTEMTIME SysTime;
  1523. GetSystemTime(&SysTime); // get sys time as UTC time.
  1524. Status = SystemTimeToFileTime(&SysTime,Time); // conver system time to file time
  1525. if( FALSE == Status ) { // convert failed?
  1526. Time->dwLowDateTime = 0xFFFFFFFF; // set time to weird value in case of failiure
  1527. Time->dwHighDateTime = 0xFFFFFFFF;
  1528. }
  1529. }
  1530. //BeginExport(function)
  1531. DWORD
  1532. DhcpRegUpdateTime( // update the last modified time
  1533. VOID
  1534. ) //EndExport(function)
  1535. {
  1536. FILETIME Time;
  1537. DWORD Err, Size;
  1538. HKEY hKey;
  1539. GetLocalFileTime(&Time); // first get current time
  1540. (*(LONGLONG *)&Time) += 10*1000*60*2; // 2 minutes (Filetime is in 100-nano seconds)
  1541. // HACK! the previous line is there as the DS takes a little while to update the
  1542. // last changed time..
  1543. Time.dwLowDateTime =Time.dwHighDateTime =0; // set time to "long back" initially
  1544. Err = RegOpenKeyEx // try to open the config key.
  1545. (
  1546. /* hKey */ HKEY_LOCAL_MACHINE,
  1547. /* lpSubKey */ REG_THIS_SERVER,
  1548. /* ulOptions */ 0 /* Reserved */ ,
  1549. /* samDesired */ KEY_ALL_ACCESS,
  1550. /* phkResult */ &hKey
  1551. );
  1552. if( ERROR_SUCCESS != Err ) return Err; // time is still set to ages back
  1553. Err = RegSetValueEx // now save the time value
  1554. (
  1555. /* hKey */ hKey,
  1556. /* lpValueName */ DHCP_LAST_DOWNLOAD_TIME_VALUE,
  1557. /* lpReserved */ 0,
  1558. /* lpType */ REG_BINARY,
  1559. /* lpData */ (LPBYTE)&Time,
  1560. /* lpcData */ sizeof(Time)
  1561. );
  1562. RegCloseKey(hKey); // close key before we forget
  1563. return Err;
  1564. }
  1565. //================================================================================
  1566. // end of file
  1567. //================================================================================