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.

1291 lines
33 KiB

  1. /*++
  2. Copyright (C) 2000 Microsoft Corporation
  3. Module Name:
  4. mmfile.c
  5. Abstract;
  6. This file contains code to read/write MM data structures
  7. from/to internal file format.. code is nearly ripped off of
  8. server\dbconfig.c
  9. --*/
  10. #include <precomp.h>
  11. #include "server\uniqid.h"
  12. typedef struct _DB_CREATE_CONTEXT {
  13. IN ULONG Index;
  14. IN PM_SERVER Server;
  15. IN PM_CLASSDEF UserClass, VendorClass;
  16. IN PM_SUBNET Subnet;
  17. IN PM_RESERVATION Reservation;
  18. } DB_CREATE_CONTEXT, *PDB_CREATE_CONTEXT;
  19. //
  20. // types of records
  21. //
  22. enum {
  23. DBCFG_CLASS,
  24. DBCFG_OPT,
  25. DBCFG_OPTDEF,
  26. DBCFG_SCOPE,
  27. DBCFG_MSCOPE,
  28. DBCFG_RANGE,
  29. DBCFG_EXCL,
  30. DBCFG_RESERVATION,
  31. DBCFG_END
  32. };
  33. //
  34. // attributes/fields
  35. //
  36. enum {
  37. DBCFG_INDEX,
  38. DBCFG_TYPE,
  39. DBCFG_SUBTYPE,
  40. DBCFG_FLAGS,
  41. DBCFG_NAME,
  42. DBCFG_COMMENT,
  43. DBCFG_INFO,
  44. DBCFG_OPTION_ID,
  45. DBCFG_OPTION_USER,
  46. DBCFG_OPTION_VENDOR,
  47. DBCFG_IPADDRESS,
  48. DBCFG_MASK,
  49. DBCFG_SUPERSCOPE,
  50. DBCFG_MSCOPEID,
  51. DBCFG_MSCOPELANG,
  52. DBCFG_MSCOPETTL,
  53. DBCFG_MSCOPE_EXPIRY,
  54. DBCFG_RANGE_START,
  55. DBCFG_RANGE_END,
  56. DBCFG_RANGE_MASK,
  57. DBCFG_BOOTP_ALLOCATED,
  58. DBCFG_BOOTP_MAX,
  59. DBCFG_LAST_COLUMN
  60. };
  61. typedef struct _DBCFG_ENTRY {
  62. ULONG Bitmasks; // indicates which of the fields below is present
  63. ULONG Index;
  64. ULONG Type, SubType, Flags;
  65. LPWSTR Name, Comment;
  66. PUCHAR Info;
  67. ULONG OptionId;
  68. LPWSTR UserClass, VendorClass;
  69. ULONG IpAddress, Mask;
  70. LPWSTR SuperScope;
  71. ULONG MscopeId;
  72. LPWSTR MscopeLang;
  73. ULONG Ttl;
  74. FILETIME ExpiryTime;
  75. ULONG RangeStart, RangeEnd, RangeMask;
  76. ULONG BootpAllocated, BootpMax;
  77. ULONG InfoSize;
  78. PVOID Buf;
  79. } DBCFG_ENTRY, *PDBCFG_ENTRY;
  80. typedef struct _DBCFG_MAP {
  81. DWORD Offset, Size;
  82. } DBCFG_MAP;
  83. DBCFG_MAP EntryMap[] = {
  84. FIELD_OFFSET(DBCFG_ENTRY,Index), sizeof(DWORD),
  85. FIELD_OFFSET(DBCFG_ENTRY,Type), sizeof(DWORD),
  86. FIELD_OFFSET(DBCFG_ENTRY,SubType), sizeof(DWORD),
  87. FIELD_OFFSET(DBCFG_ENTRY,Flags), sizeof(DWORD),
  88. FIELD_OFFSET(DBCFG_ENTRY,Name), 0,
  89. FIELD_OFFSET(DBCFG_ENTRY,Comment), 0,
  90. FIELD_OFFSET(DBCFG_ENTRY,Info), 0,
  91. FIELD_OFFSET(DBCFG_ENTRY,OptionId), sizeof(DWORD),
  92. FIELD_OFFSET(DBCFG_ENTRY,UserClass), 0,
  93. FIELD_OFFSET(DBCFG_ENTRY,VendorClass), 0,
  94. FIELD_OFFSET(DBCFG_ENTRY,IpAddress), sizeof(DWORD),
  95. FIELD_OFFSET(DBCFG_ENTRY,Mask), sizeof(DWORD),
  96. FIELD_OFFSET(DBCFG_ENTRY,SuperScope), 0,
  97. FIELD_OFFSET(DBCFG_ENTRY,MscopeId), sizeof(DWORD),
  98. FIELD_OFFSET(DBCFG_ENTRY,MscopeLang), 0,
  99. FIELD_OFFSET(DBCFG_ENTRY,Ttl), sizeof(DWORD),
  100. FIELD_OFFSET(DBCFG_ENTRY,ExpiryTime), sizeof(FILETIME),
  101. FIELD_OFFSET(DBCFG_ENTRY,RangeStart), sizeof(DWORD),
  102. FIELD_OFFSET(DBCFG_ENTRY,RangeEnd), sizeof(DWORD),
  103. FIELD_OFFSET(DBCFG_ENTRY,RangeMask), sizeof(DWORD),
  104. FIELD_OFFSET(DBCFG_ENTRY,BootpAllocated), sizeof(DWORD),
  105. FIELD_OFFSET(DBCFG_ENTRY,BootpMax), sizeof(DWORD)
  106. };
  107. DWORD Bitmasks[] = {
  108. 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
  109. 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000,
  110. 0x010000, 0x020000, 0x040000, 0x080000, 0x100000, 0x200000,
  111. 0x400000, 0x80000,
  112. };
  113. DWORD
  114. CreateDbEntry(
  115. IN PDBCFG_ENTRY Entry
  116. )
  117. {
  118. DWORD Error, Size, i, Offset;
  119. PVOID Data;
  120. WORD Buffer[4096];
  121. Offset = 0;
  122. for( i = 0; i < DBCFG_LAST_COLUMN; i ++ ) {
  123. if( (Entry->Bitmasks & Bitmasks[i]) == 0 ) {
  124. continue;
  125. }
  126. Size = EntryMap[i].Size;
  127. Data = EntryMap[i].Offset + (LPBYTE)Entry;
  128. if( i == DBCFG_INFO ) {
  129. //
  130. // Skip info -- it is added at end
  131. //
  132. continue;
  133. } else if( 0 == Size ) {
  134. //
  135. // Calculate the size of the string
  136. //
  137. Data = *(LPWSTR *)Data;
  138. if( NULL != Data ) Size = sizeof(WCHAR)*(
  139. 1 + wcslen(Data));
  140. }
  141. if( 0 == Size ) continue;
  142. Buffer[Offset++] = (WORD)i;
  143. Buffer[Offset++] = (WORD)Size;
  144. memcpy(&Buffer[Offset], Data, Size);
  145. Offset += (Size + sizeof(WORD) - 1 )/sizeof(WORD);
  146. }
  147. //
  148. // add info at the end.
  149. //
  150. i = DBCFG_INFO;
  151. if( Entry->Bitmasks & Bitmasks[i]) {
  152. Size = EntryMap[i].Size;
  153. Data = EntryMap[i].Offset + (LPBYTE)Entry;
  154. Data = *(PUCHAR *)Data;
  155. if( NULL != Data ) Size = Entry->InfoSize;
  156. if( 0 != Size ) {
  157. Buffer[Offset++] = (WORD)i;
  158. Buffer[Offset++] = (WORD)Size;
  159. memcpy(&Buffer[Offset], Data, Size);
  160. Offset += (Size + sizeof(WORD) - 1 )/sizeof(WORD);
  161. }
  162. }
  163. Buffer[Offset++] = DBCFG_LAST_COLUMN+1;
  164. Buffer[Offset++] = 0;
  165. //
  166. // Write the record onto file
  167. //
  168. return AddRecordNoSize( (LPBYTE)Buffer, Offset*sizeof(WORD));
  169. }
  170. DWORD
  171. CreateClassEntry(
  172. IN ULONG Index,
  173. IN PM_CLASSDEF Class
  174. )
  175. {
  176. DBCFG_ENTRY Entry;
  177. //
  178. // IsVendor, Type, Name, Comment, nBytes, ActualBytes
  179. //
  180. ZeroMemory(&Entry, sizeof(Entry));
  181. Entry.Bitmasks = (
  182. Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] |
  183. Bitmasks[DBCFG_SUBTYPE] |
  184. Bitmasks[DBCFG_FLAGS] | Bitmasks[DBCFG_SUBTYPE] |
  185. Bitmasks[DBCFG_NAME] | Bitmasks[DBCFG_COMMENT] |
  186. Bitmasks[DBCFG_INFO] );
  187. Entry.Index = Index;
  188. Entry.Type = DBCFG_CLASS;
  189. Entry.Flags = Class->IsVendor;
  190. Entry.SubType = Class->Type;
  191. Entry.Name = Class->Name;
  192. Entry.Comment = Class->Comment;
  193. Entry.Info = Class->ActualBytes;
  194. Entry.InfoSize = Class->nBytes;
  195. return CreateDbEntry( &Entry );
  196. }
  197. DWORD
  198. CreateOptDefEntry(
  199. IN ULONG Index,
  200. IN PM_OPTDEF OptDef,
  201. IN PM_CLASSDEF UserClass,
  202. IN PM_CLASSDEF VendorClass
  203. )
  204. {
  205. DBCFG_ENTRY Entry;
  206. //
  207. // OptId, Type, OptName, OptComment, OptVal, OptValLen,
  208. // User, Vendor
  209. //
  210. ZeroMemory(&Entry, sizeof(Entry));
  211. Entry.Bitmasks = (
  212. Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] |
  213. Bitmasks[DBCFG_SUBTYPE] | Bitmasks[DBCFG_OPTION_ID] |
  214. Bitmasks[DBCFG_NAME] | Bitmasks[DBCFG_COMMENT] |
  215. Bitmasks[DBCFG_INFO] | Bitmasks[DBCFG_OPTION_USER] |
  216. Bitmasks[DBCFG_OPTION_VENDOR] );
  217. Entry.Index = Index;
  218. Entry.Type = DBCFG_OPTDEF;
  219. Entry.OptionId = OptDef->OptId;
  220. Entry.SubType = OptDef->Type;
  221. Entry.Name = OptDef->OptName;
  222. Entry.Comment = OptDef->OptComment;
  223. Entry.Info = OptDef->OptVal;
  224. Entry.InfoSize = OptDef->OptValLen;
  225. if( UserClass) Entry.UserClass = UserClass->Name;
  226. if( VendorClass) Entry.VendorClass = VendorClass->Name;
  227. return CreateDbEntry( &Entry );
  228. }
  229. DWORD
  230. CreateOptionEntry(
  231. IN ULONG Index,
  232. IN PM_OPTION Option,
  233. IN PM_CLASSDEF UserClass,
  234. IN PM_CLASSDEF VendorClass,
  235. IN PM_SUBNET Subnet,
  236. IN PM_RESERVATION Reservation
  237. )
  238. {
  239. DBCFG_ENTRY Entry;
  240. //
  241. // OptId, Len, Val, User, Vendor
  242. //
  243. ZeroMemory(&Entry, sizeof(Entry));
  244. Entry.Bitmasks = (
  245. Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] |
  246. Bitmasks[DBCFG_OPTION_ID] | Bitmasks[DBCFG_INFO] |
  247. Bitmasks[DBCFG_OPTION_USER] |
  248. Bitmasks[DBCFG_OPTION_VENDOR] );
  249. if( Reservation ) {
  250. Entry.Bitmasks |= Bitmasks[DBCFG_IPADDRESS];
  251. Entry.IpAddress = Reservation->Address;
  252. } else if( Subnet && Subnet->fSubnet ) {
  253. Entry.Bitmasks |= Bitmasks[DBCFG_IPADDRESS];
  254. Entry.IpAddress = Subnet->Address;
  255. } else if( Subnet && !Subnet->fSubnet ) {
  256. Entry.Bitmasks |= Bitmasks[DBCFG_MSCOPEID];
  257. Entry.MscopeId = Subnet->MScopeId;
  258. }
  259. Entry.Index = Index;
  260. Entry.Type = DBCFG_OPT;
  261. Entry.OptionId = Option->OptId;
  262. Entry.Info = Option->Val;
  263. Entry.InfoSize = Option->Len;
  264. if( UserClass) Entry.UserClass = UserClass->Name;
  265. if( VendorClass) Entry.VendorClass = VendorClass->Name;
  266. return CreateDbEntry( &Entry );
  267. }
  268. DWORD
  269. CreateScopeEntry(
  270. IN ULONG Index,
  271. IN PM_SUBNET Subnet,
  272. IN PM_SSCOPE SScope
  273. )
  274. {
  275. DBCFG_ENTRY Entry;
  276. //
  277. // State, Policy, ExpiryTime, Name, Description
  278. //
  279. ZeroMemory(&Entry, sizeof(Entry));
  280. Entry.Bitmasks = (
  281. Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] |
  282. Bitmasks[DBCFG_SUBTYPE] | Bitmasks[DBCFG_FLAGS] |
  283. Bitmasks[DBCFG_NAME] | Bitmasks[DBCFG_COMMENT] );
  284. if( Subnet->fSubnet ) {
  285. Entry.Bitmasks |= (
  286. Bitmasks[DBCFG_IPADDRESS] | Bitmasks[DBCFG_MASK] |
  287. Bitmasks[DBCFG_SUPERSCOPE] );
  288. Entry.IpAddress = Subnet->Address;
  289. Entry.Mask = Subnet->Mask;
  290. if( SScope ) Entry.SuperScope = SScope->Name;
  291. } else {
  292. Entry.Bitmasks |= (
  293. Bitmasks[DBCFG_MSCOPEID] | Bitmasks[DBCFG_MSCOPETTL] |
  294. Bitmasks[DBCFG_MSCOPELANG] |
  295. Bitmasks[DBCFG_MSCOPE_EXPIRY] );
  296. Entry.MscopeId = Subnet->MScopeId;
  297. Entry.Ttl = Subnet->TTL;
  298. Entry.MscopeLang = Subnet->LangTag;
  299. Entry.ExpiryTime = *(FILETIME *)&Subnet->ExpiryTime;
  300. }
  301. Entry.Index = Index;
  302. Entry.Type = Subnet->fSubnet ? DBCFG_SCOPE : DBCFG_MSCOPE ;
  303. Entry.SubType = Subnet->State;
  304. Entry.Flags = Subnet->Policy;
  305. Entry.Name = Subnet->Name;
  306. Entry.Comment = Subnet->Description;
  307. return CreateDbEntry( &Entry );
  308. }
  309. DWORD
  310. CreateRangeEntry(
  311. IN ULONG Index,
  312. IN PM_RANGE Range,
  313. IN PM_SUBNET Subnet
  314. )
  315. {
  316. DBCFG_ENTRY Entry;
  317. //
  318. // Start, End, Mask, State, BootpAllocated, MaxBootpAllowed
  319. //
  320. ZeroMemory(&Entry, sizeof(Entry));
  321. Entry.Bitmasks = (
  322. Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] |
  323. Bitmasks[DBCFG_RANGE_START] | Bitmasks[DBCFG_RANGE_END] |
  324. Bitmasks[DBCFG_RANGE_MASK] | Bitmasks[DBCFG_FLAGS] |
  325. Bitmasks[DBCFG_BOOTP_ALLOCATED] | Bitmasks[DBCFG_BOOTP_MAX] );
  326. if( Subnet->fSubnet ) {
  327. Entry.Bitmasks |= Bitmasks[DBCFG_IPADDRESS];
  328. Entry.IpAddress = Subnet->Address;
  329. } else {
  330. Entry.Bitmasks |= Bitmasks[DBCFG_MSCOPEID];
  331. Entry.MscopeId = Subnet->MScopeId;
  332. }
  333. Entry.Index = Index;
  334. Entry.Type = DBCFG_RANGE;
  335. Entry.RangeStart = Range->Start;
  336. Entry.RangeEnd = Range->End;
  337. Entry.RangeMask = Range->Mask;
  338. Entry.Flags = Range->State;
  339. Entry.BootpAllocated = Range->BootpAllocated;
  340. Entry.BootpMax = Range->MaxBootpAllowed;
  341. return CreateDbEntry( &Entry );
  342. }
  343. DWORD
  344. CreateExclEntry(
  345. IN ULONG Index,
  346. IN PM_EXCL Excl,
  347. IN PM_SUBNET Subnet
  348. )
  349. {
  350. DBCFG_ENTRY Entry;
  351. //
  352. // Start, End
  353. //
  354. ZeroMemory(&Entry, sizeof(Entry));
  355. Entry.Bitmasks = (
  356. Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] |
  357. Bitmasks[DBCFG_RANGE_START] | Bitmasks[DBCFG_RANGE_END] );
  358. if( Subnet->fSubnet ) {
  359. Entry.Bitmasks |= Bitmasks[DBCFG_IPADDRESS];
  360. Entry.IpAddress = Subnet->Address;
  361. } else {
  362. Entry.Bitmasks |= Bitmasks[DBCFG_MSCOPEID];
  363. Entry.MscopeId = Subnet->MScopeId;
  364. }
  365. Entry.Index = Index;
  366. Entry.Type = DBCFG_EXCL;
  367. Entry.RangeStart = Excl->Start;
  368. Entry.RangeEnd = Excl->End;
  369. return CreateDbEntry( &Entry );
  370. }
  371. DWORD
  372. CreateReservationEntry(
  373. IN ULONG Index,
  374. IN PM_RESERVATION Reservation
  375. )
  376. {
  377. DBCFG_ENTRY Entry;
  378. //
  379. // Address, Flags, nBytes, ClientUID
  380. //
  381. ZeroMemory(&Entry, sizeof(Entry));
  382. Entry.Bitmasks = (
  383. Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] |
  384. Bitmasks[DBCFG_IPADDRESS] | Bitmasks[DBCFG_INFO] |
  385. Bitmasks[DBCFG_FLAGS] );
  386. Entry.Index = Index;
  387. Entry.Type = DBCFG_RESERVATION;
  388. Entry.IpAddress = Reservation->Address;
  389. Entry.Flags = Reservation->Flags;
  390. Entry.Info = Reservation->ClientUID;
  391. Entry.InfoSize = Reservation->nBytes;
  392. return CreateDbEntry( &Entry );
  393. }
  394. DWORD
  395. IterateArrayWithDbCreateRoutine(
  396. IN PDB_CREATE_CONTEXT Ctxt,
  397. IN PARRAY Array,
  398. IN DWORD (*Routine)(
  399. IN PDB_CREATE_CONTEXT Ctxt,
  400. IN PVOID ArrayElement
  401. )
  402. )
  403. {
  404. ARRAY_LOCATION Loc;
  405. DWORD Error;
  406. PVOID Element;
  407. Error = MemArrayInitLoc( Array, &Loc );
  408. while( NO_ERROR == Error ) {
  409. Error = MemArrayGetElement(
  410. Array, &Loc, &Element );
  411. ASSERT( NO_ERROR == Error && NULL != Element );
  412. Ctxt->Index ++;
  413. Error = Routine( Ctxt, Element );
  414. if( NO_ERROR != Error ) return Error;
  415. Error = MemArrayNextLoc( Array, &Loc );
  416. }
  417. if( ERROR_FILE_NOT_FOUND == Error ) return NO_ERROR;
  418. return Error;
  419. }
  420. DWORD
  421. DbCreateClassRoutine(
  422. IN PDB_CREATE_CONTEXT Ctxt,
  423. IN PM_CLASSDEF Class
  424. )
  425. {
  426. return CreateClassEntry( Ctxt->Index, Class );
  427. }
  428. DWORD
  429. DbCreateOptDefRoutine(
  430. IN PDB_CREATE_CONTEXT Ctxt,
  431. IN PM_OPTDEF OptDef
  432. )
  433. {
  434. return CreateOptDefEntry(
  435. Ctxt->Index, OptDef, Ctxt->UserClass,
  436. Ctxt->VendorClass );
  437. }
  438. DWORD
  439. DbCreateOptClassDefRoutine(
  440. IN PDB_CREATE_CONTEXT Ctxt,
  441. IN PM_OPTCLASSDEFL_ONE OptClassDef
  442. )
  443. {
  444. DWORD Error;
  445. if( 0 == MemArraySize(&OptClassDef->OptDefList.OptDefArray) ) {
  446. return NO_ERROR;
  447. }
  448. if( 0 == OptClassDef->ClassId ) {
  449. Ctxt->UserClass = NULL;
  450. } else {
  451. Error = MemServerGetClassDef(
  452. Ctxt->Server, OptClassDef->ClassId, NULL, 0, NULL,
  453. &Ctxt->UserClass );
  454. ASSERT( NO_ERROR == Error );
  455. if( NO_ERROR != Error ) return Error;
  456. }
  457. if( 0 == OptClassDef->VendorId ) {
  458. Ctxt->VendorClass = NULL;
  459. } else {
  460. Error = MemServerGetClassDef(
  461. Ctxt->Server, OptClassDef->VendorId, NULL, 0, NULL,
  462. &Ctxt->VendorClass );
  463. ASSERT( NO_ERROR == Error );
  464. if( NO_ERROR != Error ) return Error;
  465. }
  466. Error = IterateArrayWithDbCreateRoutine(
  467. Ctxt, &OptClassDef->OptDefList.OptDefArray,
  468. DbCreateOptDefRoutine );
  469. return Error;
  470. }
  471. DWORD
  472. DbCreateOptionRoutine(
  473. IN PDB_CREATE_CONTEXT Ctxt,
  474. IN PM_OPTION Option
  475. )
  476. {
  477. return CreateOptionEntry(
  478. Ctxt->Index, Option, Ctxt->UserClass,
  479. Ctxt->VendorClass, Ctxt->Subnet, Ctxt->Reservation );
  480. }
  481. DWORD
  482. DbCreateOptListRoutine(
  483. IN PDB_CREATE_CONTEXT Ctxt,
  484. IN PM_ONECLASS_OPTLIST OptList
  485. )
  486. {
  487. DWORD Error;
  488. if( 0 == MemArraySize(&OptList->OptList) ) {
  489. return NO_ERROR;
  490. }
  491. if( 0 == OptList->ClassId ) {
  492. Ctxt->UserClass = NULL;
  493. } else {
  494. Error = MemServerGetClassDef(
  495. Ctxt->Server, OptList->ClassId, NULL, 0, NULL,
  496. &Ctxt->UserClass );
  497. ASSERT( NO_ERROR == Error );
  498. if( NO_ERROR != Error ) return Error;
  499. }
  500. if( 0 == OptList->VendorId ) {
  501. Ctxt->VendorClass = NULL;
  502. } else {
  503. Error = MemServerGetClassDef(
  504. Ctxt->Server, OptList->VendorId, NULL, 0, NULL,
  505. &Ctxt->VendorClass );
  506. ASSERT( NO_ERROR == Error );
  507. if( NO_ERROR != Error ) return Error;
  508. }
  509. Error = IterateArrayWithDbCreateRoutine(
  510. Ctxt, &OptList->OptList, DbCreateOptionRoutine );
  511. return Error;
  512. }
  513. DWORD
  514. DbCreateRangeRoutine(
  515. IN PDB_CREATE_CONTEXT Ctxt,
  516. IN PM_RANGE Range
  517. )
  518. {
  519. return CreateRangeEntry(
  520. Ctxt->Index, Range, Ctxt->Subnet );
  521. }
  522. DWORD
  523. DbCreateExclRoutine(
  524. IN PDB_CREATE_CONTEXT Ctxt,
  525. IN PM_EXCL Excl
  526. )
  527. {
  528. return CreateExclEntry(
  529. Ctxt->Index, Excl, Ctxt->Subnet );
  530. }
  531. DWORD
  532. DbCreateReservationRoutine(
  533. IN PDB_CREATE_CONTEXT Ctxt,
  534. IN PM_RESERVATION Reservation
  535. )
  536. {
  537. DWORD Error;
  538. Error = CreateReservationEntry(
  539. Ctxt->Index, Reservation );
  540. if( NO_ERROR != Error ) return Error;
  541. Ctxt->Reservation = Reservation;
  542. //
  543. // Now add the options for this reservation
  544. //
  545. return IterateArrayWithDbCreateRoutine(
  546. Ctxt, &Reservation->Options.Array,
  547. DbCreateOptListRoutine );
  548. }
  549. DWORD
  550. DbCreateScopeRoutine(
  551. IN PDB_CREATE_CONTEXT Ctxt,
  552. IN PM_SUBNET Subnet
  553. )
  554. {
  555. PM_SSCOPE SScope = NULL;
  556. DWORD Error;
  557. if( Subnet->fSubnet && Subnet->SuperScopeId ) {
  558. Error = MemServerFindSScope(
  559. Ctxt->Server, Subnet->SuperScopeId, NULL, &SScope );
  560. if( NO_ERROR != Error ) {
  561. SScope = NULL;
  562. }
  563. }
  564. Error = CreateScopeEntry(
  565. Ctxt->Index, Subnet, SScope );
  566. if( NO_ERROR != Error ) return Error;
  567. //
  568. // Initialize the two fields that will get used later
  569. //
  570. Ctxt->Subnet = Subnet;
  571. Ctxt->Reservation = NULL;
  572. //
  573. // Now add the options for this scope
  574. //
  575. Error = IterateArrayWithDbCreateRoutine(
  576. Ctxt, &Subnet->Options.Array,
  577. DbCreateOptListRoutine );
  578. if( NO_ERROR != Error ) return Error;
  579. //
  580. // Now add the ranges and exclusions
  581. //
  582. Error = IterateArrayWithDbCreateRoutine(
  583. Ctxt, &Subnet->Ranges, DbCreateRangeRoutine );
  584. if( NO_ERROR != Error ) return Error;
  585. Error = IterateArrayWithDbCreateRoutine(
  586. Ctxt, &Subnet->Exclusions, DbCreateExclRoutine );
  587. if( NO_ERROR != Error ) return Error;
  588. //
  589. // Finally, add the reservations
  590. //
  591. return IterateArrayWithDbCreateRoutine(
  592. Ctxt, &Subnet->Reservations,
  593. DbCreateReservationRoutine );
  594. }
  595. DWORD
  596. DbCreateServerRoutine(
  597. IN PDB_CREATE_CONTEXT Ctxt,
  598. IN PM_SERVER Server
  599. )
  600. {
  601. DWORD Error;
  602. Ctxt->Server = Server;
  603. //
  604. // First look through the classes
  605. //
  606. Error = IterateArrayWithDbCreateRoutine(
  607. Ctxt, &Server->ClassDefs.ClassDefArray,
  608. DbCreateClassRoutine );
  609. if( NO_ERROR != Error ) return Error;
  610. //
  611. // Next save the option defs
  612. //
  613. Error = IterateArrayWithDbCreateRoutine(
  614. Ctxt, &Server->OptDefs.Array,
  615. DbCreateOptClassDefRoutine );
  616. if( NO_ERROR != Error ) return Error;
  617. //
  618. // Next save the options
  619. //
  620. Error = IterateArrayWithDbCreateRoutine(
  621. Ctxt, &Server->Options.Array,
  622. DbCreateOptListRoutine );
  623. if( NO_ERROR != Error ) return Error;
  624. //
  625. // Next save the scopes and mcast scopes
  626. //
  627. Error = IterateArrayWithDbCreateRoutine(
  628. Ctxt, &Server->Subnets, DbCreateScopeRoutine );
  629. if( NO_ERROR != Error ) return Error;
  630. return NO_ERROR;
  631. }
  632. DWORD
  633. SaveConfigurationToFile(
  634. IN PM_SERVER Server
  635. )
  636. {
  637. DB_CREATE_CONTEXT Ctxt;
  638. DWORD Error;
  639. ZeroMemory( &Ctxt, sizeof(Ctxt) );
  640. Error = DbCreateServerRoutine(
  641. &Ctxt, Server );
  642. if( NO_ERROR != Error ) {
  643. Tr("DbCreateServerRoutine: %ld\n", Error);
  644. } else {
  645. //
  646. // Sentinel
  647. //
  648. DBCFG_ENTRY Entry;
  649. ZeroMemory( &Entry, sizeof(Entry) );
  650. Entry.Bitmasks = (
  651. Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] );
  652. Entry.Type = DBCFG_END;
  653. Error = CreateDbEntry( &Entry );
  654. if( NO_ERROR != Error ) {
  655. Tr("Create last entry: %ld\n", Error );
  656. }
  657. }
  658. Tr("SaveConfigurationToFile: %ld\n", Error);
  659. return Error;
  660. }
  661. DWORD
  662. GetColumnFromMemory(
  663. IN OUT LPBYTE *Mem,
  664. IN OUT ULONG *MemSize,
  665. IN ULONG Col,
  666. IN OUT PVOID Buffer,
  667. IN ULONG BufSize,
  668. IN OUT ULONG *CopiedSize
  669. )
  670. {
  671. WORD *WordMem = (WORD *)*Mem;
  672. DWORD Size;
  673. if( *MemSize < sizeof(WORD)*2 ) return ERROR_INVALID_DATA;
  674. if( Col != WordMem[0] ) return JET_wrnColumnNull;
  675. Size = sizeof(WORD)*(
  676. 2 + (WordMem[1]+sizeof(WORD)-1)/sizeof(WORD) );
  677. if( Size > *MemSize ) return ERROR_INVALID_DATA;
  678. if( WordMem[1] >= BufSize ) *CopiedSize = BufSize;
  679. else *CopiedSize = WordMem[1];
  680. memcpy(Buffer, &WordMem[2], *CopiedSize );
  681. (*Mem) += Size;
  682. (*MemSize) -= Size;
  683. if( WordMem[1] > BufSize ) return JET_wrnBufferTruncated;
  684. return NO_ERROR;
  685. }
  686. DWORD
  687. ReadDbEntry(
  688. IN OUT LPBYTE *Mem,
  689. IN OUT ULONG *MemSize,
  690. IN PDBCFG_ENTRY Entry,
  691. IN PVOID Buffer,
  692. IN ULONG BufSize
  693. )
  694. {
  695. DWORD Size, CopiedSize, i, OldMemSize, DummySize;
  696. JET_ERR JetError;
  697. LPVOID Data, Ptr;
  698. LPBYTE OldMem;
  699. OldMemSize = *MemSize;
  700. OldMem = *Mem;
  701. ZeroMemory( Entry, sizeof(*Entry) );
  702. ZeroMemory( Buffer, BufSize );
  703. for( i = 0; i < DBCFG_LAST_COLUMN; i ++ ) {
  704. //
  705. // Info should be read at the very end to avoid screwing
  706. // up alignment as info is binary while the rest of the
  707. // variable size columns are all WCHAR strings
  708. //
  709. if( i == DBCFG_INFO ) continue;
  710. Size = EntryMap[i].Size;
  711. Data = EntryMap[i].Offset + (LPBYTE)Entry;
  712. Ptr = Data;
  713. if( 0 == Size ) {
  714. //
  715. // Calculate the size of the string
  716. //
  717. Data = Buffer;
  718. Size = BufSize;
  719. }
  720. JetError = GetColumnFromMemory(
  721. Mem, MemSize, i, Data, Size, &CopiedSize );
  722. //
  723. // If the column doesn't exist, continue
  724. //
  725. if( JET_wrnColumnNull == JetError ) continue;
  726. if( JET_wrnBufferTruncated == JetError &&
  727. Data == Buffer ) {
  728. (*Mem) = OldMem;
  729. (*MemSize) = OldMemSize;
  730. return ERROR_INSUFFICIENT_BUFFER;
  731. }
  732. if( NO_ERROR != JetError ) {
  733. Tr( "GetColumnFromMemory: %ld\n", JetError );
  734. return JetError;
  735. }
  736. //
  737. // If it is any of the variable sized params, then
  738. // set the ptr to point to the buffer where the data is
  739. // copied, and also update the buffer.
  740. //
  741. if( Data == Buffer ) {
  742. (*(LPVOID *)Ptr) = Buffer;
  743. BufSize -= CopiedSize;
  744. Buffer = (PVOID)(((PUCHAR)Buffer) + CopiedSize);
  745. } else {
  746. ASSERT( CopiedSize == Size );
  747. }
  748. //
  749. // Indicate that the column was retrieved successfully
  750. //
  751. Entry->Bitmasks |= Bitmasks[i];
  752. }
  753. //
  754. // Read the info field
  755. //
  756. Size = BufSize;
  757. JetError = GetColumnFromMemory(
  758. Mem, MemSize, DBCFG_INFO, Buffer, Size, &CopiedSize );
  759. GetColumnFromMemory(
  760. Mem, MemSize, DBCFG_LAST_COLUMN+1,NULL, 0, &DummySize);
  761. if( JET_wrnColumnNull == JetError ) return NO_ERROR;
  762. if( JET_wrnBufferTruncated == JetError ) {
  763. (*Mem) = OldMem;
  764. (*MemSize) = OldMemSize;
  765. return ERROR_INSUFFICIENT_BUFFER;
  766. }
  767. if( NO_ERROR != JetError ) {
  768. Tr("GetColumnFromMemory: %ld\n", JetError );
  769. return JetError;
  770. }
  771. Entry->Info = Buffer;
  772. Entry->InfoSize = CopiedSize;
  773. Entry->Bitmasks |= Bitmasks[DBCFG_INFO];
  774. return NO_ERROR;
  775. }
  776. DWORD
  777. ReadDbEntryEx(
  778. IN OUT LPBYTE *Mem,
  779. IN OUT ULONG *MemSize,
  780. IN PDBCFG_ENTRY Entry
  781. )
  782. {
  783. PVOID Buffer;
  784. ULONG BufSize;
  785. DWORD Error;
  786. Buffer = NULL;
  787. BufSize = 512;
  788. do {
  789. if( NULL != Buffer ) LocalFree(Buffer);
  790. BufSize *= 2;
  791. Buffer = LocalAlloc( LPTR, BufSize );
  792. if( NULL == Buffer ) return ERROR_NOT_ENOUGH_MEMORY;
  793. Error = ReadDbEntry(Mem, MemSize, Entry, Buffer, BufSize);
  794. } while( ERROR_INSUFFICIENT_BUFFER == Error );
  795. if( !(Entry->Bitmasks & Bitmasks[DBCFG_INDEX]) ||
  796. !(Entry->Bitmasks & Bitmasks[DBCFG_TYPE]) ) {
  797. if( NO_ERROR == Error ) {
  798. ASSERT( FALSE );
  799. Error = ERROR_INTERNAL_ERROR;
  800. }
  801. }
  802. if( NO_ERROR != Error ) {
  803. LocalFree( Buffer );
  804. return Error;
  805. }
  806. Entry->Buf = Buffer;
  807. return NO_ERROR;
  808. }
  809. DWORD
  810. AddDbEntry(
  811. IN PM_SERVER Server,
  812. IN PDBCFG_ENTRY Entry
  813. )
  814. {
  815. DWORD UserId, VendorId, SScopeId, Error;
  816. PM_SUBNET Subnet;
  817. PM_OPTCLASS OptClass;
  818. PM_OPTION Option, DelOpt;
  819. PM_RANGE DelRange;
  820. PM_EXCL DelExcl;
  821. PM_RESERVATION Reservation;
  822. PM_CLASSDEF ClassDef;
  823. PM_SSCOPE SScope;
  824. Subnet = NULL;
  825. OptClass = NULL;
  826. Option = DelOpt = NULL;
  827. Reservation = NULL;
  828. DelRange = NULL;
  829. DelExcl = NULL;
  830. UserId = 0;
  831. VendorId = 0;
  832. SScopeId = 0;
  833. if( Entry->UserClass ) {
  834. Error = MemServerGetClassDef(
  835. Server, 0, Entry->UserClass, 0, NULL, &ClassDef );
  836. ASSERT( NO_ERROR == Error );
  837. if( NO_ERROR != Error ) return Error;
  838. ASSERT( ClassDef->IsVendor == FALSE );
  839. UserId = ClassDef->ClassId;
  840. }
  841. if( Entry->VendorClass ) {
  842. Error = MemServerGetClassDef(
  843. Server, 0, Entry->VendorClass, 0, NULL, &ClassDef );
  844. ASSERT( NO_ERROR == Error );
  845. if( NO_ERROR != Error ) return Error;
  846. ASSERT( ClassDef->IsVendor == TRUE);
  847. VendorId = ClassDef->ClassId;
  848. }
  849. if( Entry->SuperScope ) {
  850. Error = MemServerFindSScope(
  851. Server, INVALID_SSCOPE_ID, Entry->SuperScope, &SScope );
  852. if( NO_ERROR == Error ) {
  853. SScopeId = SScope->SScopeId;
  854. } else if( ERROR_FILE_NOT_FOUND != Error ) {
  855. return Error;
  856. } else {
  857. Error = MemSScopeInit( &SScope, 0, Entry->SuperScope );
  858. if( NO_ERROR != Error ) return Error;
  859. Error = MemServerAddSScope( Server, SScope );
  860. if( NO_ERROR != Error ) {
  861. MemSScopeCleanup( SScope );
  862. return Error;
  863. }
  864. SScopeId = SScope->SScopeId;
  865. }
  866. }
  867. switch( Entry->Type ) {
  868. case DBCFG_CLASS :
  869. //
  870. // Flags = IsVendor, SubType =Type, Info = ActualBytes
  871. //
  872. return MemServerAddClassDef(
  873. Server, MemNewClassId(), Entry->Flags, Entry->Name,
  874. Entry->Comment, Entry->InfoSize, Entry->Info, INVALID_UNIQ_ID );
  875. case DBCFG_OPTDEF :
  876. //
  877. // OptionId = OptId, SubType = Type, Info = OptVal
  878. //
  879. return MemServerAddOptDef(
  880. Server, UserId, VendorId, Entry->OptionId,
  881. Entry->Name, Entry->Comment, Entry->SubType,
  882. Entry->Info, Entry->InfoSize, INVALID_UNIQ_ID );
  883. case DBCFG_OPT:
  884. //
  885. // OptionId = OptId, Info = Val
  886. // If this is a reservation option, address is set to
  887. // reserved client address. If this is a subnet option,
  888. // address is set to subnet address. If this is a mscope
  889. // option, scopeid is set to mscope scopeid. If it is a
  890. // global option, neither address not scopeid is set.
  891. //
  892. if( Entry->Bitmasks & Bitmasks[DBCFG_MSCOPEID] ) {
  893. Error = MemServerFindMScope(
  894. Server, Entry->MscopeId, NULL, &Subnet );
  895. if( NO_ERROR != Error ) return Error;
  896. OptClass = &Subnet->Options;
  897. } else if( 0 == (Entry->Bitmasks & Bitmasks[DBCFG_IPADDRESS] )) {
  898. OptClass = &Server->Options;
  899. } else {
  900. Error = MemServerGetUAddressInfo(
  901. Server, Entry->IpAddress, &Subnet, NULL, NULL,
  902. &Reservation );
  903. ASSERT( NO_ERROR == Error );
  904. if( NO_ERROR != Error ) return Error;
  905. if( NULL != Reservation ) {
  906. OptClass = &Reservation->Options;
  907. } else OptClass = &Subnet->Options;
  908. }
  909. Error = MemOptInit(
  910. &Option, Entry->OptionId, Entry->InfoSize,
  911. Entry->Info );
  912. if( NO_ERROR != Error ) return Error;
  913. Error = MemOptClassAddOption(
  914. OptClass, Option, UserId, VendorId, &DelOpt, INVALID_UNIQ_ID );
  915. ASSERT( NULL == DelOpt );
  916. if( NO_ERROR != Error ) MemFree( Option );
  917. return Error;
  918. case DBCFG_SCOPE:
  919. //
  920. // IpAddress = Address, Mask = Mask, SubType = State,
  921. // Flags = Policy
  922. //
  923. Error = MemSubnetInit(
  924. &Subnet, Entry->IpAddress, Entry->Mask,
  925. Entry->SubType, SScopeId, Entry->Name, Entry->Comment );
  926. if( NO_ERROR != Error ) return Error;
  927. Error = MemServerAddSubnet( Server, Subnet, INVALID_UNIQ_ID );
  928. if( NO_ERROR != Error ) MemSubnetCleanup( Subnet );
  929. return Error;
  930. case DBCFG_MSCOPE :
  931. //
  932. // MscopeId = MScopeId, Ttl = TTL, MscopeLang = LangTag,
  933. // ExpiryTime = ExpiryTime, SubType = State, Flags =
  934. // Policy..
  935. //
  936. Error = MemMScopeInit(
  937. &Subnet, Entry->MscopeId, Entry->SubType,
  938. Entry->Flags, (BYTE)Entry->Ttl, Entry->Name,
  939. Entry->Comment, Entry->MscopeLang,
  940. *(DATE_TIME *)&Entry->ExpiryTime );
  941. if( NO_ERROR != Error ) return Error;
  942. Error = MemServerAddMScope( Server, Subnet, INVALID_UNIQ_ID );
  943. if( NO_ERROR != Error ) MemSubnetCleanup( Subnet );
  944. Subnet->ServerPtr = Server;
  945. return Error;
  946. case DBCFG_RANGE :
  947. //
  948. // RangeStart = Start, RangeEnd = End, RangeMask = Mask,
  949. // Flags = State, BootpAllocated, BootpMax =
  950. // MaxBootpAllowed... Also, IpAddress or MscopeId
  951. //
  952. if( Entry->Bitmasks & Bitmasks[DBCFG_IPADDRESS] ) {
  953. Error = MemServerGetUAddressInfo(
  954. Server, Entry->IpAddress, &Subnet, NULL, NULL,
  955. NULL );
  956. } else {
  957. Error = MemServerFindMScope(
  958. Server, Entry->MscopeId, NULL, &Subnet );
  959. }
  960. if( NO_ERROR != Error ) return Error;
  961. return MemSubnetAddRange(
  962. Subnet, Entry->RangeStart, Entry->RangeEnd,
  963. Entry->Flags, Entry->BootpAllocated, Entry->BootpMax,
  964. &DelRange, INVALID_UNIQ_ID );
  965. case DBCFG_EXCL:
  966. //
  967. // RangeStart = Start, RangeEnd = End
  968. //
  969. if( Entry->Bitmasks & Bitmasks[DBCFG_IPADDRESS] ) {
  970. Error = MemServerGetUAddressInfo(
  971. Server, Entry->IpAddress, &Subnet, NULL, NULL,
  972. NULL );
  973. } else {
  974. Error = MemServerFindMScope(
  975. Server, Entry->MscopeId, NULL, &Subnet );
  976. }
  977. if( NO_ERROR != Error ) return Error;
  978. return MemSubnetAddExcl(
  979. Subnet, Entry->RangeStart, Entry->RangeEnd, &DelExcl,
  980. INVALID_UNIQ_ID
  981. );
  982. case DBCFG_RESERVATION :
  983. //
  984. // IpAddress = Address, Flags = Flags, Info = ClientUID
  985. //
  986. Error = MemServerGetAddressInfo(
  987. Server, Entry->IpAddress, &Subnet, NULL, NULL, NULL );
  988. if( NO_ERROR != Error ) return Error;
  989. return MemReserveAdd(
  990. &Subnet->Reservations, Entry->IpAddress,
  991. Entry->Flags, Entry->Info, Entry->InfoSize,
  992. INVALID_UNIQ_ID );
  993. default:
  994. return ERROR_INTERNAL_ERROR;
  995. }
  996. }
  997. DWORD
  998. AddDbEntryEx(
  999. IN PM_SERVER Server,
  1000. IN PDBCFG_ENTRY Entry
  1001. )
  1002. {
  1003. DWORD Error;
  1004. LPSTR EntryTypes[] = {
  1005. "Class", "Opt", "OptDef", "Scope", "Mscope", "Range",
  1006. "Excl", "Reservation", "Unknown1", "Unknown2", "Unknown3"
  1007. };
  1008. Error = AddDbEntry( Server, Entry );
  1009. if( NO_ERROR != Error ) {
  1010. Tr("Error adding entry[%ld] %s: 0x%lx\n",
  1011. Entry->Index, EntryTypes[Entry->Type], Error );
  1012. }
  1013. return Error;
  1014. }
  1015. DWORD
  1016. ReadDbEntries(
  1017. IN OUT LPBYTE *Mem,
  1018. IN OUT ULONG *MemSize,
  1019. IN OUT PM_SERVER *Server
  1020. )
  1021. {
  1022. DBCFG_ENTRY Entry;
  1023. DWORD Error = NO_ERROR;
  1024. Error = MemServerInit(
  1025. Server, -1, 0, 0, NULL, NULL );
  1026. if( NO_ERROR != Error ) return Error;
  1027. while( Error == NO_ERROR ) {
  1028. Error = ReadDbEntryEx( Mem, MemSize, &Entry );
  1029. if( NO_ERROR != Error ) {
  1030. Tr( "ReadDbEntryEx: %ld\n", Error );
  1031. break;
  1032. }
  1033. if( Entry.Type == DBCFG_END ) {
  1034. Error = NO_ERROR;
  1035. break;
  1036. }
  1037. Error = AddDbEntryEx( *Server, &Entry );
  1038. if( NULL != Entry.Buf ) LocalFree( Entry.Buf );
  1039. if( NO_ERROR != Error ) {
  1040. Tr( "AddDbEntryEx: %ld\n", Error );
  1041. return Error;
  1042. }
  1043. }
  1044. Tr("ReadDbEntries: %ld\n", Error);
  1045. if( NO_ERROR != Error ) {
  1046. MemServerFree( *Server );
  1047. (*Server) = NULL;
  1048. }
  1049. return Error;
  1050. }