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.

1290 lines
31 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. typedef struct _DB_CREATE_CONTEXT {
  12. IN ULONG Index;
  13. IN PM_SERVER Server;
  14. IN PM_CLASSDEF UserClass, VendorClass;
  15. IN PM_SUBNET Subnet;
  16. IN PM_RESERVATION Reservation;
  17. } DB_CREATE_CONTEXT, *PDB_CREATE_CONTEXT;
  18. //
  19. // types of records
  20. //
  21. enum {
  22. DBCFG_CLASS,
  23. DBCFG_OPT,
  24. DBCFG_OPTDEF,
  25. DBCFG_SCOPE,
  26. DBCFG_MSCOPE,
  27. DBCFG_RANGE,
  28. DBCFG_EXCL,
  29. DBCFG_RESERVATION,
  30. DBCFG_END
  31. };
  32. //
  33. // attributes/fields
  34. //
  35. enum {
  36. DBCFG_INDEX,
  37. DBCFG_TYPE,
  38. DBCFG_SUBTYPE,
  39. DBCFG_FLAGS,
  40. DBCFG_NAME,
  41. DBCFG_COMMENT,
  42. DBCFG_INFO,
  43. DBCFG_OPTION_ID,
  44. DBCFG_OPTION_USER,
  45. DBCFG_OPTION_VENDOR,
  46. DBCFG_IPADDRESS,
  47. DBCFG_MASK,
  48. DBCFG_SUPERSCOPE,
  49. DBCFG_MSCOPEID,
  50. DBCFG_MSCOPELANG,
  51. DBCFG_MSCOPETTL,
  52. DBCFG_MSCOPE_EXPIRY,
  53. DBCFG_RANGE_START,
  54. DBCFG_RANGE_END,
  55. DBCFG_RANGE_MASK,
  56. DBCFG_BOOTP_ALLOCATED,
  57. DBCFG_BOOTP_MAX,
  58. DBCFG_LAST_COLUMN
  59. };
  60. typedef struct _DBCFG_ENTRY {
  61. ULONG Bitmasks; // indicates which of the fields below is present
  62. ULONG Index;
  63. ULONG Type, SubType, Flags;
  64. LPWSTR Name, Comment;
  65. PUCHAR Info;
  66. ULONG OptionId;
  67. LPWSTR UserClass, VendorClass;
  68. ULONG IpAddress, Mask;
  69. LPWSTR SuperScope;
  70. ULONG MscopeId;
  71. LPWSTR MscopeLang;
  72. ULONG Ttl;
  73. FILETIME ExpiryTime;
  74. ULONG RangeStart, RangeEnd, RangeMask;
  75. ULONG BootpAllocated, BootpMax;
  76. ULONG InfoSize;
  77. PVOID Buf;
  78. } DBCFG_ENTRY, *PDBCFG_ENTRY;
  79. typedef struct _DBCFG_MAP {
  80. DWORD Offset, Size;
  81. } DBCFG_MAP;
  82. DBCFG_MAP EntryMap[] = {
  83. FIELD_OFFSET(DBCFG_ENTRY,Index), sizeof(DWORD),
  84. FIELD_OFFSET(DBCFG_ENTRY,Type), sizeof(DWORD),
  85. FIELD_OFFSET(DBCFG_ENTRY,SubType), sizeof(DWORD),
  86. FIELD_OFFSET(DBCFG_ENTRY,Flags), sizeof(DWORD),
  87. FIELD_OFFSET(DBCFG_ENTRY,Name), 0,
  88. FIELD_OFFSET(DBCFG_ENTRY,Comment), 0,
  89. FIELD_OFFSET(DBCFG_ENTRY,Info), 0,
  90. FIELD_OFFSET(DBCFG_ENTRY,OptionId), sizeof(DWORD),
  91. FIELD_OFFSET(DBCFG_ENTRY,UserClass), 0,
  92. FIELD_OFFSET(DBCFG_ENTRY,VendorClass), 0,
  93. FIELD_OFFSET(DBCFG_ENTRY,IpAddress), sizeof(DWORD),
  94. FIELD_OFFSET(DBCFG_ENTRY,Mask), sizeof(DWORD),
  95. FIELD_OFFSET(DBCFG_ENTRY,SuperScope), 0,
  96. FIELD_OFFSET(DBCFG_ENTRY,MscopeId), sizeof(DWORD),
  97. FIELD_OFFSET(DBCFG_ENTRY,MscopeLang), 0,
  98. FIELD_OFFSET(DBCFG_ENTRY,Ttl), sizeof(DWORD),
  99. FIELD_OFFSET(DBCFG_ENTRY,ExpiryTime), sizeof(FILETIME),
  100. FIELD_OFFSET(DBCFG_ENTRY,RangeStart), sizeof(DWORD),
  101. FIELD_OFFSET(DBCFG_ENTRY,RangeEnd), sizeof(DWORD),
  102. FIELD_OFFSET(DBCFG_ENTRY,RangeMask), sizeof(DWORD),
  103. FIELD_OFFSET(DBCFG_ENTRY,BootpAllocated), sizeof(DWORD),
  104. FIELD_OFFSET(DBCFG_ENTRY,BootpMax), sizeof(DWORD)
  105. };
  106. DWORD Bitmasks[] = {
  107. 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
  108. 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000,
  109. 0x010000, 0x020000, 0x040000, 0x080000, 0x100000, 0x200000,
  110. 0x400000, 0x80000,
  111. };
  112. DWORD
  113. CreateDbEntry(
  114. IN PDBCFG_ENTRY Entry
  115. )
  116. {
  117. DWORD Error, Size, i, Offset;
  118. PVOID Data;
  119. WORD Buffer[4096];
  120. Offset = 0;
  121. for( i = 0; i < DBCFG_LAST_COLUMN; i ++ ) {
  122. if( (Entry->Bitmasks & Bitmasks[i]) == 0 ) {
  123. continue;
  124. }
  125. Size = EntryMap[i].Size;
  126. Data = EntryMap[i].Offset + (LPBYTE)Entry;
  127. if( i == DBCFG_INFO ) {
  128. //
  129. // Skip info -- it is added at end
  130. //
  131. continue;
  132. } else if( 0 == Size ) {
  133. //
  134. // Calculate the size of the string
  135. //
  136. Data = *(LPWSTR *)Data;
  137. if( NULL != Data ) Size = sizeof(WCHAR)*(
  138. 1 + wcslen(Data));
  139. }
  140. if( 0 == Size ) continue;
  141. Buffer[Offset++] = (WORD)i;
  142. Buffer[Offset++] = (WORD)Size;
  143. memcpy(&Buffer[Offset], Data, Size);
  144. Offset += (Size + sizeof(WORD) - 1 )/sizeof(WORD);
  145. }
  146. //
  147. // add info at the end.
  148. //
  149. i = DBCFG_INFO;
  150. if( Entry->Bitmasks & Bitmasks[i]) {
  151. Size = EntryMap[i].Size;
  152. Data = EntryMap[i].Offset + (LPBYTE)Entry;
  153. Data = *(PUCHAR *)Data;
  154. if( NULL != Data ) Size = Entry->InfoSize;
  155. if( 0 != Size ) {
  156. Buffer[Offset++] = (WORD)i;
  157. Buffer[Offset++] = (WORD)Size;
  158. memcpy(&Buffer[Offset], Data, Size);
  159. Offset += (Size + sizeof(WORD) - 1 )/sizeof(WORD);
  160. }
  161. }
  162. Buffer[Offset++] = DBCFG_LAST_COLUMN+1;
  163. Buffer[Offset++] = 0;
  164. //
  165. // Write the record onto file
  166. //
  167. return AddRecordNoSize( (LPBYTE)Buffer, Offset*sizeof(WORD));
  168. }
  169. DWORD
  170. CreateClassEntry(
  171. IN ULONG Index,
  172. IN PM_CLASSDEF Class
  173. )
  174. {
  175. DBCFG_ENTRY Entry;
  176. //
  177. // IsVendor, Type, Name, Comment, nBytes, ActualBytes
  178. //
  179. ZeroMemory(&Entry, sizeof(Entry));
  180. Entry.Bitmasks = (
  181. Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] |
  182. Bitmasks[DBCFG_SUBTYPE] |
  183. Bitmasks[DBCFG_FLAGS] | Bitmasks[DBCFG_SUBTYPE] |
  184. Bitmasks[DBCFG_NAME] | Bitmasks[DBCFG_COMMENT] |
  185. Bitmasks[DBCFG_INFO] );
  186. Entry.Index = Index;
  187. Entry.Type = DBCFG_CLASS;
  188. Entry.Flags = Class->IsVendor;
  189. Entry.SubType = Class->Type;
  190. Entry.Name = Class->Name;
  191. Entry.Comment = Class->Comment;
  192. Entry.Info = Class->ActualBytes;
  193. Entry.InfoSize = Class->nBytes;
  194. return CreateDbEntry( &Entry );
  195. }
  196. DWORD
  197. CreateOptDefEntry(
  198. IN ULONG Index,
  199. IN PM_OPTDEF OptDef,
  200. IN PM_CLASSDEF UserClass,
  201. IN PM_CLASSDEF VendorClass
  202. )
  203. {
  204. DBCFG_ENTRY Entry;
  205. //
  206. // OptId, Type, OptName, OptComment, OptVal, OptValLen,
  207. // User, Vendor
  208. //
  209. ZeroMemory(&Entry, sizeof(Entry));
  210. Entry.Bitmasks = (
  211. Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] |
  212. Bitmasks[DBCFG_SUBTYPE] | Bitmasks[DBCFG_OPTION_ID] |
  213. Bitmasks[DBCFG_NAME] | Bitmasks[DBCFG_COMMENT] |
  214. Bitmasks[DBCFG_INFO] | Bitmasks[DBCFG_OPTION_USER] |
  215. Bitmasks[DBCFG_OPTION_VENDOR] );
  216. Entry.Index = Index;
  217. Entry.Type = DBCFG_OPTDEF;
  218. Entry.OptionId = OptDef->OptId;
  219. Entry.SubType = OptDef->Type;
  220. Entry.Name = OptDef->OptName;
  221. Entry.Comment = OptDef->OptComment;
  222. Entry.Info = OptDef->OptVal;
  223. Entry.InfoSize = OptDef->OptValLen;
  224. if( UserClass) Entry.UserClass = UserClass->Name;
  225. if( VendorClass) Entry.VendorClass = VendorClass->Name;
  226. return CreateDbEntry( &Entry );
  227. }
  228. DWORD
  229. CreateOptionEntry(
  230. IN ULONG Index,
  231. IN PM_OPTION Option,
  232. IN PM_CLASSDEF UserClass,
  233. IN PM_CLASSDEF VendorClass,
  234. IN PM_SUBNET Subnet,
  235. IN PM_RESERVATION Reservation
  236. )
  237. {
  238. DBCFG_ENTRY Entry;
  239. //
  240. // OptId, Len, Val, User, Vendor
  241. //
  242. ZeroMemory(&Entry, sizeof(Entry));
  243. Entry.Bitmasks = (
  244. Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] |
  245. Bitmasks[DBCFG_OPTION_ID] | Bitmasks[DBCFG_INFO] |
  246. Bitmasks[DBCFG_OPTION_USER] |
  247. Bitmasks[DBCFG_OPTION_VENDOR] );
  248. if( Reservation ) {
  249. Entry.Bitmasks |= Bitmasks[DBCFG_IPADDRESS];
  250. Entry.IpAddress = Reservation->Address;
  251. } else if( Subnet && Subnet->fSubnet ) {
  252. Entry.Bitmasks |= Bitmasks[DBCFG_IPADDRESS];
  253. Entry.IpAddress = Subnet->Address;
  254. } else if( Subnet && !Subnet->fSubnet ) {
  255. Entry.Bitmasks |= Bitmasks[DBCFG_MSCOPEID];
  256. Entry.MscopeId = Subnet->MScopeId;
  257. }
  258. Entry.Index = Index;
  259. Entry.Type = DBCFG_OPT;
  260. Entry.OptionId = Option->OptId;
  261. Entry.Info = Option->Val;
  262. Entry.InfoSize = Option->Len;
  263. if( UserClass) Entry.UserClass = UserClass->Name;
  264. if( VendorClass) Entry.VendorClass = VendorClass->Name;
  265. return CreateDbEntry( &Entry );
  266. }
  267. DWORD
  268. CreateScopeEntry(
  269. IN ULONG Index,
  270. IN PM_SUBNET Subnet,
  271. IN PM_SSCOPE SScope
  272. )
  273. {
  274. DBCFG_ENTRY Entry;
  275. //
  276. // State, Policy, ExpiryTime, Name, Description
  277. //
  278. ZeroMemory(&Entry, sizeof(Entry));
  279. Entry.Bitmasks = (
  280. Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] |
  281. Bitmasks[DBCFG_SUBTYPE] | Bitmasks[DBCFG_FLAGS] |
  282. Bitmasks[DBCFG_NAME] | Bitmasks[DBCFG_COMMENT] );
  283. if( Subnet->fSubnet ) {
  284. Entry.Bitmasks |= (
  285. Bitmasks[DBCFG_IPADDRESS] | Bitmasks[DBCFG_MASK] |
  286. Bitmasks[DBCFG_SUPERSCOPE] );
  287. Entry.IpAddress = Subnet->Address;
  288. Entry.Mask = Subnet->Mask;
  289. if( SScope ) Entry.SuperScope = SScope->Name;
  290. } else {
  291. Entry.Bitmasks |= (
  292. Bitmasks[DBCFG_MSCOPEID] | Bitmasks[DBCFG_MSCOPETTL] |
  293. Bitmasks[DBCFG_MSCOPELANG] |
  294. Bitmasks[DBCFG_MSCOPE_EXPIRY] );
  295. Entry.MscopeId = Subnet->MScopeId;
  296. Entry.Ttl = Subnet->TTL;
  297. Entry.MscopeLang = Subnet->LangTag;
  298. Entry.ExpiryTime = *(FILETIME *)&Subnet->ExpiryTime;
  299. }
  300. Entry.Index = Index;
  301. Entry.Type = Subnet->fSubnet ? DBCFG_SCOPE : DBCFG_MSCOPE ;
  302. Entry.SubType = Subnet->State;
  303. Entry.Flags = Subnet->Policy;
  304. Entry.Name = Subnet->Name;
  305. Entry.Comment = Subnet->Description;
  306. return CreateDbEntry( &Entry );
  307. }
  308. DWORD
  309. CreateRangeEntry(
  310. IN ULONG Index,
  311. IN PM_RANGE Range,
  312. IN PM_SUBNET Subnet
  313. )
  314. {
  315. DBCFG_ENTRY Entry;
  316. //
  317. // Start, End, Mask, State, BootpAllocated, MaxBootpAllowed
  318. //
  319. ZeroMemory(&Entry, sizeof(Entry));
  320. Entry.Bitmasks = (
  321. Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] |
  322. Bitmasks[DBCFG_RANGE_START] | Bitmasks[DBCFG_RANGE_END] |
  323. Bitmasks[DBCFG_RANGE_MASK] | Bitmasks[DBCFG_FLAGS] |
  324. Bitmasks[DBCFG_BOOTP_ALLOCATED] | Bitmasks[DBCFG_BOOTP_MAX] );
  325. if( Subnet->fSubnet ) {
  326. Entry.Bitmasks |= Bitmasks[DBCFG_IPADDRESS];
  327. Entry.IpAddress = Subnet->Address;
  328. } else {
  329. Entry.Bitmasks |= Bitmasks[DBCFG_MSCOPEID];
  330. Entry.MscopeId = Subnet->MScopeId;
  331. }
  332. Entry.Index = Index;
  333. Entry.Type = DBCFG_RANGE;
  334. Entry.RangeStart = Range->Start;
  335. Entry.RangeEnd = Range->End;
  336. Entry.RangeMask = Range->Mask;
  337. Entry.Flags = Range->State;
  338. Entry.BootpAllocated = Range->BootpAllocated;
  339. Entry.BootpMax = Range->MaxBootpAllowed;
  340. return CreateDbEntry( &Entry );
  341. }
  342. DWORD
  343. CreateExclEntry(
  344. IN ULONG Index,
  345. IN PM_EXCL Excl,
  346. IN PM_SUBNET Subnet
  347. )
  348. {
  349. DBCFG_ENTRY Entry;
  350. //
  351. // Start, End
  352. //
  353. ZeroMemory(&Entry, sizeof(Entry));
  354. Entry.Bitmasks = (
  355. Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] |
  356. Bitmasks[DBCFG_RANGE_START] | Bitmasks[DBCFG_RANGE_END] );
  357. if( Subnet->fSubnet ) {
  358. Entry.Bitmasks |= Bitmasks[DBCFG_IPADDRESS];
  359. Entry.IpAddress = Subnet->Address;
  360. } else {
  361. Entry.Bitmasks |= Bitmasks[DBCFG_MSCOPEID];
  362. Entry.MscopeId = Subnet->MScopeId;
  363. }
  364. Entry.Index = Index;
  365. Entry.Type = DBCFG_EXCL;
  366. Entry.RangeStart = Excl->Start;
  367. Entry.RangeEnd = Excl->End;
  368. return CreateDbEntry( &Entry );
  369. }
  370. DWORD
  371. CreateReservationEntry(
  372. IN ULONG Index,
  373. IN PM_RESERVATION Reservation
  374. )
  375. {
  376. DBCFG_ENTRY Entry;
  377. //
  378. // Address, Flags, nBytes, ClientUID
  379. //
  380. ZeroMemory(&Entry, sizeof(Entry));
  381. Entry.Bitmasks = (
  382. Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] |
  383. Bitmasks[DBCFG_IPADDRESS] | Bitmasks[DBCFG_INFO] |
  384. Bitmasks[DBCFG_FLAGS] );
  385. Entry.Index = Index;
  386. Entry.Type = DBCFG_RESERVATION;
  387. Entry.IpAddress = Reservation->Address;
  388. Entry.Flags = Reservation->Flags;
  389. Entry.Info = Reservation->ClientUID;
  390. Entry.InfoSize = Reservation->nBytes;
  391. return CreateDbEntry( &Entry );
  392. }
  393. DWORD
  394. IterateArrayWithDbCreateRoutine(
  395. IN PDB_CREATE_CONTEXT Ctxt,
  396. IN PARRAY Array,
  397. IN DWORD (*Routine)(
  398. IN PDB_CREATE_CONTEXT Ctxt,
  399. IN PVOID ArrayElement
  400. )
  401. )
  402. {
  403. ARRAY_LOCATION Loc;
  404. DWORD Error;
  405. PVOID Element;
  406. Error = MemArrayInitLoc( Array, &Loc );
  407. while( NO_ERROR == Error ) {
  408. Error = MemArrayGetElement(
  409. Array, &Loc, &Element );
  410. ASSERT( NO_ERROR == Error && NULL != Element );
  411. Ctxt->Index ++;
  412. Error = Routine( Ctxt, Element );
  413. if( NO_ERROR != Error ) return Error;
  414. Error = MemArrayNextLoc( Array, &Loc );
  415. }
  416. if( ERROR_FILE_NOT_FOUND == Error ) return NO_ERROR;
  417. return Error;
  418. }
  419. DWORD
  420. DbCreateClassRoutine(
  421. IN PDB_CREATE_CONTEXT Ctxt,
  422. IN PM_CLASSDEF Class
  423. )
  424. {
  425. return CreateClassEntry( Ctxt->Index, Class );
  426. }
  427. DWORD
  428. DbCreateOptDefRoutine(
  429. IN PDB_CREATE_CONTEXT Ctxt,
  430. IN PM_OPTDEF OptDef
  431. )
  432. {
  433. return CreateOptDefEntry(
  434. Ctxt->Index, OptDef, Ctxt->UserClass,
  435. Ctxt->VendorClass );
  436. }
  437. DWORD
  438. DbCreateOptClassDefRoutine(
  439. IN PDB_CREATE_CONTEXT Ctxt,
  440. IN PM_OPTCLASSDEFL_ONE OptClassDef
  441. )
  442. {
  443. DWORD Error;
  444. if( 0 == MemArraySize(&OptClassDef->OptDefList.OptDefArray) ) {
  445. return NO_ERROR;
  446. }
  447. if( 0 == OptClassDef->ClassId ) {
  448. Ctxt->UserClass = NULL;
  449. } else {
  450. Error = MemServerGetClassDef(
  451. Ctxt->Server, OptClassDef->ClassId, NULL, 0, NULL,
  452. &Ctxt->UserClass );
  453. ASSERT( NO_ERROR == Error );
  454. if( NO_ERROR != Error ) return Error;
  455. }
  456. if( 0 == OptClassDef->VendorId ) {
  457. Ctxt->VendorClass = NULL;
  458. } else {
  459. Error = MemServerGetClassDef(
  460. Ctxt->Server, OptClassDef->VendorId, NULL, 0, NULL,
  461. &Ctxt->VendorClass );
  462. ASSERT( NO_ERROR == Error );
  463. if( NO_ERROR != Error ) return Error;
  464. }
  465. Error = IterateArrayWithDbCreateRoutine(
  466. Ctxt, &OptClassDef->OptDefList.OptDefArray,
  467. DbCreateOptDefRoutine );
  468. return Error;
  469. }
  470. DWORD
  471. DbCreateOptionRoutine(
  472. IN PDB_CREATE_CONTEXT Ctxt,
  473. IN PM_OPTION Option
  474. )
  475. {
  476. return CreateOptionEntry(
  477. Ctxt->Index, Option, Ctxt->UserClass,
  478. Ctxt->VendorClass, Ctxt->Subnet, Ctxt->Reservation );
  479. }
  480. DWORD
  481. DbCreateOptListRoutine(
  482. IN PDB_CREATE_CONTEXT Ctxt,
  483. IN PM_ONECLASS_OPTLIST OptList
  484. )
  485. {
  486. DWORD Error;
  487. if( 0 == MemArraySize(&OptList->OptList) ) {
  488. return NO_ERROR;
  489. }
  490. if( 0 == OptList->ClassId ) {
  491. Ctxt->UserClass = NULL;
  492. } else {
  493. Error = MemServerGetClassDef(
  494. Ctxt->Server, OptList->ClassId, NULL, 0, NULL,
  495. &Ctxt->UserClass );
  496. ASSERT( NO_ERROR == Error );
  497. if( NO_ERROR != Error ) return Error;
  498. }
  499. if( 0 == OptList->VendorId ) {
  500. Ctxt->VendorClass = NULL;
  501. } else {
  502. Error = MemServerGetClassDef(
  503. Ctxt->Server, OptList->VendorId, NULL, 0, NULL,
  504. &Ctxt->VendorClass );
  505. ASSERT( NO_ERROR == Error );
  506. if( NO_ERROR != Error ) return Error;
  507. }
  508. Error = IterateArrayWithDbCreateRoutine(
  509. Ctxt, &OptList->OptList, DbCreateOptionRoutine );
  510. return Error;
  511. }
  512. DWORD
  513. DbCreateRangeRoutine(
  514. IN PDB_CREATE_CONTEXT Ctxt,
  515. IN PM_RANGE Range
  516. )
  517. {
  518. return CreateRangeEntry(
  519. Ctxt->Index, Range, Ctxt->Subnet );
  520. }
  521. DWORD
  522. DbCreateExclRoutine(
  523. IN PDB_CREATE_CONTEXT Ctxt,
  524. IN PM_EXCL Excl
  525. )
  526. {
  527. return CreateExclEntry(
  528. Ctxt->Index, Excl, Ctxt->Subnet );
  529. }
  530. DWORD
  531. DbCreateReservationRoutine(
  532. IN PDB_CREATE_CONTEXT Ctxt,
  533. IN PM_RESERVATION Reservation
  534. )
  535. {
  536. DWORD Error;
  537. Error = CreateReservationEntry(
  538. Ctxt->Index, Reservation );
  539. if( NO_ERROR != Error ) return Error;
  540. Ctxt->Reservation = Reservation;
  541. //
  542. // Now add the options for this reservation
  543. //
  544. return IterateArrayWithDbCreateRoutine(
  545. Ctxt, &Reservation->Options.Array,
  546. DbCreateOptListRoutine );
  547. }
  548. DWORD
  549. DbCreateScopeRoutine(
  550. IN PDB_CREATE_CONTEXT Ctxt,
  551. IN PM_SUBNET Subnet
  552. )
  553. {
  554. PM_SSCOPE SScope = NULL;
  555. DWORD Error;
  556. if( Subnet->fSubnet && Subnet->SuperScopeId ) {
  557. DWORD Error;
  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 );
  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 );
  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 );
  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 );
  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 );
  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 );
  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. );
  981. case DBCFG_RESERVATION :
  982. //
  983. // IpAddress = Address, Flags = Flags, Info = ClientUID
  984. //
  985. Error = MemServerGetAddressInfo(
  986. Server, Entry->IpAddress, &Subnet, NULL, NULL, NULL );
  987. if( NO_ERROR != Error ) return Error;
  988. return MemReserveAdd(
  989. &Subnet->Reservations, Entry->IpAddress,
  990. Entry->Flags, Entry->Info, Entry->InfoSize );
  991. default:
  992. return ERROR_INTERNAL_ERROR;
  993. }
  994. }
  995. DWORD
  996. AddDbEntryEx(
  997. IN PM_SERVER Server,
  998. IN PDBCFG_ENTRY Entry
  999. )
  1000. {
  1001. DWORD Error;
  1002. LPSTR EntryTypes[] = {
  1003. "Class", "Opt", "OptDef", "Scope", "Mscope", "Range",
  1004. "Excl", "Reservation", "Unknown1", "Unknown2", "Unknown3"
  1005. };
  1006. Error = AddDbEntry( Server, Entry );
  1007. if( NO_ERROR != Error ) {
  1008. Tr("Error adding entry[%ld] %s: 0x%lx\n",
  1009. Entry->Index, EntryTypes[Entry->Type], Error );
  1010. }
  1011. return Error;
  1012. }
  1013. DWORD
  1014. ReadDbEntries(
  1015. IN OUT LPBYTE *Mem,
  1016. IN OUT ULONG *MemSize,
  1017. IN OUT PM_SERVER *Server
  1018. )
  1019. {
  1020. DBCFG_ENTRY Entry;
  1021. DWORD Error = NO_ERROR;
  1022. Error = MemServerInit(
  1023. Server, -1, 0, 0, NULL, NULL );
  1024. if( NO_ERROR != Error ) return Error;
  1025. while( Error == NO_ERROR ) {
  1026. Error = ReadDbEntryEx( Mem, MemSize, &Entry );
  1027. if( NO_ERROR != Error ) {
  1028. Tr( "ReadDbEntryEx: %ld\n", Error );
  1029. break;
  1030. }
  1031. if( Entry.Type == DBCFG_END ) {
  1032. Error = NO_ERROR;
  1033. break;
  1034. }
  1035. Error = AddDbEntryEx( *Server, &Entry );
  1036. if( NULL != Entry.Buf ) LocalFree( Entry.Buf );
  1037. if( NO_ERROR != Error ) {
  1038. Tr( "AddDbEntryEx: %ld\n", Error );
  1039. return Error;
  1040. }
  1041. }
  1042. Tr("ReadDbEntries: %ld\n", Error);
  1043. if( NO_ERROR != Error ) {
  1044. MemServerFree( *Server );
  1045. (*Server) = NULL;
  1046. }
  1047. return Error;
  1048. }