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.

3022 lines
74 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. memdb.c
  5. Abstract:
  6. A simple memory-based database for associating flags
  7. with a string.
  8. Author:
  9. Jim Schmidt (jimschm) 8-Aug-1996
  10. Revision History:
  11. jimschm 23-Sep-1998 Expanded user flags to 24 bits (from 12 bits)
  12. calinn 12-Dec-1997 Extended MemDbMakePrintableKey and MemDbMakeNonPrintableKey
  13. jimschm 03-Dec-1997 Added multi-thread synchronization
  14. jimschm 22-Oct-1997 Split into multiple source files,
  15. added multiple memory block capability
  16. jimschm 16-Sep-1997 Hashing: delete fix
  17. jimschm 29-Jul-1997 Hashing, user flags added
  18. jimschm 07-Mar-1997 Signature changes
  19. jimschm 03-Mar-1997 PrivateBuildKeyFromOffset changes
  20. jimschm 18-Dec-1996 Fixed deltree bug
  21. --*/
  22. #include "pch.h"
  23. #include "memdbp.h"
  24. #ifndef UNICODE
  25. #error UNICODE required
  26. #endif
  27. //
  28. // Global delcaration
  29. //
  30. PDATABASE g_db;
  31. GROWLIST g_DatabaseList = GROWLIST_INIT;
  32. BYTE g_SelectedDatabase;
  33. PHIVE g_HeadHive;
  34. CRITICAL_SECTION g_MemDbCs;
  35. #ifdef DEBUG
  36. #define FILE_SIGNATURE DEBUG_FILE_SIGNATURE
  37. BOOL g_UseDebugStructs = TRUE;
  38. #else
  39. #define FILE_SIGNATURE RETAIL_FILE_SIGNATURE
  40. #endif
  41. //
  42. // Private prototypes
  43. //
  44. INT
  45. pCreateDatabase (
  46. PCWSTR Name
  47. );
  48. BOOL
  49. pInitializeDatabase (
  50. OUT PDATABASE Database,
  51. IN PCWSTR Name
  52. );
  53. BOOL
  54. pFreeDatabase (
  55. IN OUT PDATABASE Database
  56. );
  57. VOID
  58. pFreeSelectedDatabase (
  59. VOID
  60. );
  61. VOID
  62. pFreeAllDatabases (
  63. VOID
  64. );
  65. BOOL
  66. pPrivateMemDbGetValueW (
  67. IN PCWSTR KeyStr,
  68. OUT PDWORD Value, OPTIONAL
  69. OUT PDWORD UserFlagsPtr OPTIONAL
  70. );
  71. BOOL
  72. pInitializeMemDb (
  73. VOID
  74. );
  75. //
  76. // Implementation
  77. //
  78. BOOL
  79. MemDb_Entry (
  80. IN HINSTANCE hinstDLL,
  81. IN DWORD Reason,
  82. IN PVOID lpv
  83. )
  84. /*++
  85. Routine Description:
  86. DllMain is called after the C runtime is initialized, and its purpose
  87. is to initialize the globals for this process.
  88. Arguments:
  89. hinstDLL - (OS-supplied) Instance handle for the DLL
  90. Reason - (OS-supplied) Type of initialization or termination
  91. lpv - (OS-supplied) Unused
  92. Return Value:
  93. TRUE because DLL always initializes properly.
  94. --*/
  95. {
  96. switch (Reason) {
  97. case DLL_PROCESS_ATTACH:
  98. if (!pInitializeMemDb()) {
  99. return FALSE;
  100. }
  101. InitializeCriticalSection (&g_MemDbCs);
  102. InitOperationTable();
  103. break;
  104. case DLL_PROCESS_DETACH:
  105. pFreeAllDatabases();
  106. FreeGrowList (&g_DatabaseList);
  107. DeleteCriticalSection (&g_MemDbCs);
  108. DumpBinTreeStats();
  109. break;
  110. }
  111. return TRUE;
  112. }
  113. BOOL
  114. pInitializeMemDb (
  115. VOID
  116. )
  117. {
  118. FreeGrowList (&g_DatabaseList);
  119. ZeroMemory (&g_DatabaseList, sizeof (g_DatabaseList));
  120. g_db = NULL;
  121. if (!InitializeHashBlock()) {
  122. return FALSE;
  123. }
  124. if (pCreateDatabase (L"") != 0) {
  125. return FALSE;
  126. }
  127. g_SelectedDatabase = 1;
  128. SelectDatabase (0);
  129. return TRUE;
  130. }
  131. BOOL
  132. pInitializeDatabase (
  133. OUT PDATABASE Database,
  134. IN PCWSTR Name
  135. )
  136. {
  137. UINT u;
  138. Database->AllocSize = BLOCK_SIZE;
  139. Database->Buf = (PBYTE) MemAlloc (g_hHeap, 0, Database->AllocSize);
  140. Database->End = 0;
  141. Database->FirstLevelRoot = INVALID_OFFSET;
  142. Database->FirstDeleted = INVALID_OFFSET;
  143. MYASSERT (INVALID_OFFSET == 0xFFFFFFFF);
  144. FillMemory (Database->TokenBuckets, sizeof (Database->TokenBuckets), 0xFF);
  145. _wcssafecpy (Database->Hive, Name, MAX_HIVE_NAME);
  146. return TRUE;
  147. }
  148. BOOL
  149. pFreeDatabase (
  150. IN OUT PDATABASE Database
  151. )
  152. {
  153. if (Database->Buf) {
  154. MemFree (g_hHeap, 0, Database->Buf);
  155. Database->Buf = NULL;
  156. }
  157. Database->End = 0;
  158. Database->FirstLevelRoot = INVALID_OFFSET;
  159. Database->FirstDeleted = INVALID_OFFSET;
  160. Database->Hive[0] = 0;
  161. return TRUE;
  162. }
  163. INT
  164. pCreateDatabase (
  165. PCWSTR Name
  166. )
  167. {
  168. DATABASE Database;
  169. BYTE Index;
  170. UINT Count;
  171. UINT u;
  172. //
  173. // Does key exist already?
  174. //
  175. if (g_db) {
  176. SelectDatabase (0);
  177. if (INVALID_OFFSET != FindKeyStruct (g_db->FirstLevelRoot, Name)) {
  178. DEBUGMSG ((DBG_WHOOPS, "Cannot create %ls because it already exists!", Name));
  179. SetLastError (ERROR_ALREADY_EXISTS);
  180. return -1;
  181. }
  182. }
  183. //
  184. // Scan list for a blank spot
  185. //
  186. Count = GrowListGetSize (&g_DatabaseList);
  187. for (u = 0 ; u < Count ; u++) {
  188. if (!GrowListGetItem (&g_DatabaseList, u)) {
  189. break;
  190. }
  191. }
  192. if (u < Count) {
  193. //
  194. // Use empty slot
  195. //
  196. Index = (BYTE) u;
  197. } else if (Count < 256) {
  198. //
  199. // No empty slot; grow the list
  200. //
  201. Index = (BYTE) Count;
  202. if (!GrowListAppend (&g_DatabaseList, NULL, 0)) {
  203. DEBUGMSG ((DBG_WARNING, "Could not create database because GrowListAppend failed"));
  204. return -1;
  205. }
  206. } else {
  207. DEBUGMSG ((DBG_ERROR, "Cannot have more than 256 databases in memdb!"));
  208. return -1;
  209. }
  210. //
  211. // Create the database memory block
  212. //
  213. pInitializeDatabase (&Database, Name);
  214. if (!GrowListSetItem (&g_DatabaseList, (UINT) Index, (PBYTE) &Database, sizeof (Database))) {
  215. DEBUGMSG ((DBG_WARNING, "Could not create database because GrowListSetItem failed"));
  216. pFreeDatabase (&Database);
  217. return -1;
  218. }
  219. return (INT) Index;
  220. }
  221. VOID
  222. pDestroySelectedDatabase (
  223. VOID
  224. )
  225. {
  226. //
  227. // Free all resources for the database
  228. //
  229. pFreeSelectedDatabase ();
  230. //
  231. // For all databases except for the root, free the DATABASE
  232. // structure in g_DatabaseList.
  233. //
  234. if (g_SelectedDatabase) {
  235. GrowListResetItem (&g_DatabaseList, (UINT) g_SelectedDatabase);
  236. }
  237. }
  238. VOID
  239. pFreeSelectedDatabase (
  240. VOID
  241. )
  242. {
  243. //
  244. // Free all resources used by a single database
  245. //
  246. if (g_db->Buf) {
  247. MemFree (g_hHeap, 0, g_db->Buf);
  248. }
  249. FreeAllBinaryBlocks();
  250. ZeroMemory (g_db, sizeof (DATABASE));
  251. }
  252. VOID
  253. pFreeAllDatabases (
  254. VOID
  255. )
  256. {
  257. UINT Count;
  258. UINT Index;
  259. //
  260. // Free all database blocks
  261. //
  262. Count = GrowListGetSize (&g_DatabaseList);
  263. for (Index = 0 ; Index < Count ; Index++) {
  264. if (SelectDatabase ((BYTE) Index)) {
  265. pDestroySelectedDatabase();
  266. }
  267. }
  268. //
  269. // Free global hash table
  270. //
  271. FreeHashBlock();
  272. SelectDatabase(0);
  273. }
  274. BOOL
  275. SelectDatabase (
  276. BYTE DatabaseId
  277. )
  278. {
  279. PDATABASE Database;
  280. if (g_SelectedDatabase == DatabaseId) {
  281. return TRUE;
  282. }
  283. Database = (PDATABASE) GrowListGetItem (&g_DatabaseList, (UINT) DatabaseId);
  284. if (!Database) {
  285. DEBUGMSG ((DBG_WHOOPS, "MemDb: Invalid database selection!"));
  286. return FALSE;
  287. }
  288. g_db = Database;
  289. g_SelectedDatabase = DatabaseId;
  290. return TRUE;
  291. }
  292. PCWSTR
  293. SelectHive (
  294. PCWSTR FullKeyStr
  295. )
  296. {
  297. UINT Count;
  298. UINT Index;
  299. PDATABASE Database;
  300. PCWSTR End;
  301. //
  302. // Determine if root of FullKeyStr is part of a hive
  303. //
  304. End = wcschr (FullKeyStr, L'\\');
  305. if (End) {
  306. Count = GrowListGetSize (&g_DatabaseList);
  307. for (Index = 1 ; Index < Count ; Index++) {
  308. Database = (PDATABASE) GrowListGetItem (&g_DatabaseList, Index);
  309. if (Database && StringIMatchABW (Database->Hive, FullKeyStr, End)) {
  310. //
  311. // Match found; select the database and return the subkey
  312. //
  313. SelectDatabase ((BYTE) Index);
  314. End = _wcsinc (End);
  315. return End;
  316. }
  317. }
  318. }
  319. SelectDatabase (0);
  320. return FullKeyStr;
  321. }
  322. BOOL
  323. IsTemporaryKey (
  324. PCWSTR FullKeyStr
  325. )
  326. {
  327. UINT Count;
  328. UINT Index;
  329. PDATABASE Database;
  330. PCWSTR End;
  331. End = wcschr (FullKeyStr, L'\\');
  332. if (!End) {
  333. End = GetEndOfStringW (FullKeyStr);
  334. }
  335. Count = GrowListGetSize (&g_DatabaseList);
  336. for (Index = 1 ; Index < Count ; Index++) {
  337. Database = (PDATABASE) GrowListGetItem (&g_DatabaseList, Index);
  338. if (Database && StringIMatchABW (Database->Hive, FullKeyStr, End)) {
  339. //
  340. // Match found; return true
  341. //
  342. return TRUE;
  343. }
  344. }
  345. return FALSE;
  346. }
  347. //
  348. // MemDbSetValue creates or modifies KeyStr. The value of the key is changed
  349. // when the return value is TRUE.
  350. //
  351. BOOL
  352. PrivateMemDbSetValueA (
  353. PCSTR Key,
  354. DWORD Val,
  355. DWORD SetFlags,
  356. DWORD ClearFlags,
  357. PDWORD Offset
  358. )
  359. {
  360. PCWSTR p;
  361. BOOL b = FALSE;
  362. p = ConvertAtoW (Key);
  363. if (p) {
  364. b = PrivateMemDbSetValueW (p, Val, SetFlags, ClearFlags, Offset);
  365. FreeConvertedStr (p);
  366. }
  367. return b;
  368. }
  369. BOOL
  370. PrivateMemDbSetValueW (
  371. PCWSTR Key,
  372. DWORD Val,
  373. DWORD SetFlags,
  374. DWORD ClearFlags,
  375. PDWORD Offset
  376. )
  377. {
  378. DWORD KeyOffset;
  379. PKEYSTRUCT KeyStruct;
  380. PCWSTR SubKey;
  381. BOOL b = FALSE;
  382. EnterCriticalSection (&g_MemDbCs);
  383. __try {
  384. SubKey = SelectHive (Key);
  385. KeyOffset = FindKey (SubKey);
  386. if (KeyOffset == INVALID_OFFSET) {
  387. KeyOffset = NewKey (SubKey, Key);
  388. if (KeyOffset == INVALID_OFFSET) {
  389. __leave;
  390. }
  391. }
  392. KeyStruct = GetKeyStruct (KeyOffset);
  393. FreeKeyStructBinaryBlock (KeyStruct);
  394. KeyStruct->dwValue = Val;
  395. if (Offset) {
  396. *Offset = KeyOffset | (g_SelectedDatabase << RESERVED_BITS);
  397. }
  398. KeyStruct->Flags = KeyStruct->Flags & ~(ClearFlags & KSF_USERFLAG_MASK);
  399. KeyStruct->Flags = KeyStruct->Flags | (SetFlags & KSF_USERFLAG_MASK);
  400. b = TRUE;
  401. }
  402. __finally {
  403. LeaveCriticalSection (&g_MemDbCs);
  404. }
  405. return b;
  406. }
  407. BOOL
  408. PrivateMemDbSetBinaryValueA (
  409. IN PCSTR Key,
  410. IN PCBYTE Data,
  411. IN DWORD SizeOfData,
  412. OUT PDWORD Offset OPTIONAL
  413. )
  414. {
  415. PCWSTR p;
  416. BOOL b = FALSE;
  417. p = ConvertAtoW (Key);
  418. if (p) {
  419. b = PrivateMemDbSetBinaryValueW (p, Data, SizeOfData, Offset);
  420. FreeConvertedStr (p);
  421. }
  422. return b;
  423. }
  424. BOOL
  425. PrivateMemDbSetBinaryValueW (
  426. IN PCWSTR Key,
  427. IN PCBYTE Data,
  428. IN DWORD SizeOfData,
  429. OUT PDWORD Offset OPTIONAL
  430. )
  431. {
  432. DWORD KeyOffset;
  433. PKEYSTRUCT KeyStruct;
  434. PCWSTR SubKey;
  435. BOOL b = FALSE;
  436. EnterCriticalSection (&g_MemDbCs);
  437. __try {
  438. SubKey = SelectHive (Key);
  439. KeyOffset = FindKey (SubKey);
  440. if (KeyOffset == INVALID_OFFSET) {
  441. KeyOffset = NewKey (SubKey, Key);
  442. if (KeyOffset == INVALID_OFFSET) {
  443. __leave;
  444. }
  445. }
  446. KeyStruct = GetKeyStruct (KeyOffset);
  447. // Free existing buffer
  448. FreeKeyStructBinaryBlock (KeyStruct);
  449. // Alloc new buffer
  450. KeyStruct->BinaryPtr = AllocBinaryBlock (Data, SizeOfData, KeyOffset);
  451. if (!KeyStruct->BinaryPtr) {
  452. __leave;
  453. }
  454. KeyStruct->Flags |= KSF_BINARY;
  455. if (Offset) {
  456. *Offset = KeyOffset | (g_SelectedDatabase << RESERVED_BITS);
  457. }
  458. b = TRUE;
  459. }
  460. __finally {
  461. LeaveCriticalSection (&g_MemDbCs);
  462. }
  463. return b;
  464. }
  465. BOOL
  466. MemDbSetValueA (
  467. IN PCSTR KeyStr,
  468. IN DWORD dwValue
  469. )
  470. {
  471. return PrivateMemDbSetValueA (KeyStr, dwValue, 0, 0, NULL);
  472. }
  473. BOOL
  474. MemDbSetValueW (
  475. IN PCWSTR KeyStr,
  476. IN DWORD dwValue
  477. )
  478. {
  479. return PrivateMemDbSetValueW (KeyStr, dwValue, 0, 0, NULL);
  480. }
  481. BOOL
  482. MemDbSetValueAndFlagsA (
  483. IN PCSTR KeyStr,
  484. IN DWORD dwValue,
  485. IN DWORD SetUserFlags,
  486. IN DWORD ClearUserFlags
  487. )
  488. {
  489. return PrivateMemDbSetValueA (KeyStr, dwValue, SetUserFlags, ClearUserFlags, NULL);
  490. }
  491. BOOL
  492. MemDbSetValueAndFlagsW (
  493. IN PCWSTR KeyStr,
  494. IN DWORD dwValue,
  495. IN DWORD SetUserFlags,
  496. IN DWORD ClearUserFlags
  497. )
  498. {
  499. return PrivateMemDbSetValueW (KeyStr, dwValue, SetUserFlags, ClearUserFlags, NULL);
  500. }
  501. BOOL
  502. MemDbSetBinaryValueA (
  503. IN PCSTR KeyStr,
  504. IN PCBYTE Data,
  505. IN DWORD DataSize
  506. )
  507. {
  508. return PrivateMemDbSetBinaryValueA (KeyStr, Data, DataSize, NULL);
  509. }
  510. BOOL
  511. MemDbSetBinaryValueW (
  512. IN PCWSTR KeyStr,
  513. IN PCBYTE Data,
  514. IN DWORD DataSize
  515. )
  516. {
  517. return PrivateMemDbSetBinaryValueW (KeyStr, Data, DataSize, NULL);
  518. }
  519. //
  520. // GetValue takes a full key string and returns the
  521. // value to the caller-supplied DWORD. Value
  522. // may be NULL to check only for existance of the
  523. // value.
  524. //
  525. BOOL
  526. pPrivateMemDbGetValueA (
  527. IN PCSTR KeyStr,
  528. OUT PDWORD Value, OPTIONAL
  529. OUT PDWORD UserFlagsPtr OPTIONAL
  530. )
  531. {
  532. PCWSTR p;
  533. BOOL b = FALSE;
  534. p = ConvertAtoW (KeyStr);
  535. if (p) {
  536. b = pPrivateMemDbGetValueW (p, Value, UserFlagsPtr);
  537. FreeConvertedStr (p);
  538. }
  539. return b;
  540. }
  541. BOOL
  542. pPrivateMemDbGetValueW (
  543. IN PCWSTR KeyStr,
  544. OUT PDWORD Value, OPTIONAL
  545. OUT PDWORD UserFlagsPtr OPTIONAL
  546. )
  547. {
  548. DWORD KeyOffset;
  549. PCWSTR SubKey;
  550. BOOL b = FALSE;
  551. EnterCriticalSection (&g_MemDbCs);
  552. __try {
  553. SubKey = SelectHive (KeyStr);
  554. KeyOffset = FindKey (SubKey);
  555. if (KeyOffset == INVALID_OFFSET) {
  556. __leave;
  557. }
  558. CopyValToPtr (GetKeyStruct (KeyOffset), Value);
  559. CopyFlagsToPtr (GetKeyStruct (KeyOffset), UserFlagsPtr);
  560. b = TRUE;
  561. }
  562. __finally {
  563. LeaveCriticalSection (&g_MemDbCs);
  564. }
  565. return b;
  566. }
  567. BOOL
  568. MemDbGetValueA (
  569. IN PCSTR Key,
  570. OUT PDWORD ValuePtr OPTIONAL
  571. )
  572. {
  573. return pPrivateMemDbGetValueA (Key, ValuePtr, NULL);
  574. }
  575. BOOL
  576. MemDbGetValueW (
  577. IN PCWSTR Key,
  578. OUT PDWORD ValuePtr OPTIONAL
  579. )
  580. {
  581. return pPrivateMemDbGetValueW (Key, ValuePtr, NULL);
  582. }
  583. BOOL
  584. MemDbGetValueAndFlagsA (
  585. IN PCSTR Key,
  586. OUT PDWORD ValuePtr, OPTIONAL
  587. OUT PDWORD UserFlagsPtr
  588. )
  589. {
  590. return pPrivateMemDbGetValueA (Key, ValuePtr, UserFlagsPtr);
  591. }
  592. BOOL
  593. MemDbGetValueAndFlagsW (
  594. IN PCWSTR Key,
  595. OUT PDWORD ValuePtr, OPTIONAL
  596. OUT PDWORD UserFlagsPtr
  597. )
  598. {
  599. return pPrivateMemDbGetValueW (Key, ValuePtr, UserFlagsPtr);
  600. }
  601. PCBYTE
  602. MemDbGetBinaryValueA (
  603. IN PCSTR KeyStr,
  604. OUT PDWORD DataSize OPTIONAL
  605. )
  606. {
  607. PCWSTR p;
  608. BYTE const * b = NULL;
  609. p = ConvertAtoW (KeyStr);
  610. if (p) {
  611. b = MemDbGetBinaryValueW (p, DataSize);
  612. FreeConvertedStr (p);
  613. }
  614. return b;
  615. }
  616. PCBYTE
  617. MemDbGetBinaryValueW (
  618. IN PCWSTR KeyStr,
  619. OUT PDWORD DataSize OPTIONAL
  620. )
  621. {
  622. DWORD KeyOffset;
  623. PKEYSTRUCT KeyStruct;
  624. PCWSTR SubKey;
  625. PCBYTE Result = NULL;
  626. EnterCriticalSection (&g_MemDbCs);
  627. __try {
  628. SubKey = SelectHive (KeyStr);
  629. KeyOffset = FindKey (SubKey);
  630. if (KeyOffset == INVALID_OFFSET) {
  631. __leave;
  632. }
  633. KeyStruct = GetKeyStruct (KeyOffset);
  634. if (DataSize) {
  635. *DataSize = GetKeyStructBinarySize (KeyStruct);
  636. }
  637. Result = GetKeyStructBinaryData (KeyStruct);
  638. }
  639. __finally {
  640. LeaveCriticalSection (&g_MemDbCs);
  641. }
  642. return Result;
  643. }
  644. //
  645. // GetPatternValue takes a full key string and returns the
  646. // value to the caller-supplied DWORD. The stored value string
  647. // is treated as a pattern, but KeyStr is not a pattern.
  648. // The return value represents the first match found.
  649. //
  650. BOOL
  651. MemDbGetPatternValueA (
  652. IN PCSTR KeyStr,
  653. OUT PDWORD Value
  654. )
  655. {
  656. PCWSTR p;
  657. BOOL b = FALSE;
  658. p = ConvertAtoW (KeyStr);
  659. if (p) {
  660. b = MemDbGetPatternValueW (p, Value);
  661. FreeConvertedStr (p);
  662. }
  663. return b;
  664. }
  665. BOOL
  666. MemDbGetPatternValueW (
  667. IN PCWSTR KeyStr,
  668. OUT PDWORD Value
  669. )
  670. {
  671. DWORD KeyOffset;
  672. PCWSTR SubKey;
  673. BOOL b = FALSE;
  674. EnterCriticalSection (&g_MemDbCs);
  675. __try {
  676. SubKey = SelectHive (KeyStr);
  677. KeyOffset = FindPatternKey (g_db->FirstLevelRoot, SubKey, FALSE);
  678. if (KeyOffset == INVALID_OFFSET) {
  679. __leave;
  680. }
  681. CopyValToPtr (GetKeyStruct (KeyOffset), Value);
  682. b = TRUE;
  683. }
  684. __finally {
  685. LeaveCriticalSection (&g_MemDbCs);
  686. }
  687. return b;
  688. }
  689. //
  690. // MemDbGetStoredEndPatternValue takes a full key string and returns the
  691. // value to the caller-supplied DWORD. The stored value string
  692. // is treated as a pattern, but KeyStr is not a pattern.
  693. // The return value represents the first match found.
  694. //
  695. // If the last stored key segment is an asterisk, then the pattern
  696. // is considered to match.
  697. //
  698. BOOL
  699. MemDbGetStoredEndPatternValueA (
  700. IN PCSTR KeyStr,
  701. OUT PDWORD Value
  702. )
  703. {
  704. PCWSTR p;
  705. BOOL b = FALSE;
  706. p = ConvertAtoW (KeyStr);
  707. if (p) {
  708. b = MemDbGetStoredEndPatternValueW (p, Value);
  709. FreeConvertedStr (p);
  710. }
  711. return b;
  712. }
  713. BOOL
  714. MemDbGetStoredEndPatternValueW (
  715. IN PCWSTR KeyStr,
  716. OUT PDWORD Value
  717. )
  718. {
  719. DWORD KeyOffset;
  720. PCWSTR SubKey;
  721. BOOL b = FALSE;
  722. EnterCriticalSection (&g_MemDbCs);
  723. __try {
  724. SubKey = SelectHive (KeyStr);
  725. KeyOffset = FindPatternKey (g_db->FirstLevelRoot, SubKey, TRUE);
  726. if (KeyOffset == INVALID_OFFSET) {
  727. __leave;
  728. }
  729. CopyValToPtr (GetKeyStruct (KeyOffset), Value);
  730. b = TRUE;
  731. }
  732. __finally {
  733. LeaveCriticalSection (&g_MemDbCs);
  734. }
  735. return b;
  736. }
  737. //
  738. // GetValueWithPattern takes a full key string that may contain
  739. // wildcards between the backslashes, and returns the value
  740. // to the caller-supplied DWORD. The stored value string
  741. // is not treated as a pattern. The return value represents
  742. // the first match found.
  743. //
  744. BOOL
  745. MemDbGetValueWithPatternA (
  746. IN PCSTR KeyPattern,
  747. OUT PDWORD Value
  748. )
  749. {
  750. PCWSTR p;
  751. BOOL b = FALSE;
  752. p = ConvertAtoW (KeyPattern);
  753. if (p) {
  754. b = MemDbGetValueWithPatternW (p, Value);
  755. FreeConvertedStr (p);
  756. }
  757. return b;
  758. }
  759. BOOL
  760. MemDbGetValueWithPatternW (
  761. IN PCWSTR KeyPattern,
  762. OUT PDWORD Value
  763. )
  764. {
  765. DWORD KeyOffset;
  766. PCWSTR SubKey;
  767. BOOL b = FALSE;
  768. EnterCriticalSection (&g_MemDbCs);
  769. __try {
  770. SubKey = SelectHive (KeyPattern);
  771. KeyOffset = FindKeyUsingPattern (g_db->FirstLevelRoot, SubKey);
  772. if (KeyOffset == INVALID_OFFSET) {
  773. __leave;
  774. }
  775. CopyValToPtr (GetKeyStruct (KeyOffset), Value);
  776. b = TRUE;
  777. }
  778. __finally {
  779. LeaveCriticalSection (&g_MemDbCs);
  780. }
  781. return b;
  782. }
  783. BOOL
  784. MemDbGetPatternValueWithPatternA (
  785. IN PCSTR KeyPattern,
  786. OUT PDWORD Value
  787. )
  788. {
  789. PCWSTR p;
  790. BOOL b = FALSE;
  791. p = ConvertAtoW (KeyPattern);
  792. if (p) {
  793. b = MemDbGetPatternValueWithPatternW (p, Value);
  794. FreeConvertedStr (p);
  795. }
  796. return b;
  797. }
  798. BOOL
  799. MemDbGetPatternValueWithPatternW (
  800. IN PCWSTR KeyPattern,
  801. OUT PDWORD Value
  802. )
  803. {
  804. DWORD KeyOffset;
  805. PCWSTR SubKey;
  806. BOOL b = FALSE;
  807. EnterCriticalSection (&g_MemDbCs);
  808. __try {
  809. SubKey = SelectHive (KeyPattern);
  810. KeyOffset = FindPatternKeyUsingPattern (g_db->FirstLevelRoot, SubKey);
  811. if (KeyOffset == INVALID_OFFSET) {
  812. __leave;
  813. }
  814. CopyValToPtr (GetKeyStruct (KeyOffset), Value);
  815. b = TRUE;
  816. }
  817. __finally {
  818. LeaveCriticalSection (&g_MemDbCs);
  819. }
  820. return b;
  821. }
  822. VOID
  823. MemDbDeleteValueA (
  824. IN PCSTR KeyStr
  825. )
  826. {
  827. PCWSTR p;
  828. p = ConvertAtoW (KeyStr);
  829. if (p) {
  830. MemDbDeleteValueW (p);
  831. FreeConvertedStr (p);
  832. }
  833. }
  834. VOID
  835. MemDbDeleteValueW (
  836. IN PCWSTR KeyStr
  837. )
  838. {
  839. PCWSTR SubKey;
  840. EnterCriticalSection (&g_MemDbCs);
  841. SubKey = SelectHive (KeyStr);
  842. DeleteKey (SubKey, &g_db->FirstLevelRoot, TRUE);
  843. LeaveCriticalSection (&g_MemDbCs);
  844. }
  845. VOID
  846. MemDbDeleteTreeA (
  847. IN PCSTR KeyStr
  848. )
  849. {
  850. PCWSTR p;
  851. p = ConvertAtoW (KeyStr);
  852. if (p) {
  853. MemDbDeleteTreeW (p);
  854. FreeConvertedStr (p);
  855. }
  856. }
  857. VOID
  858. MemDbDeleteTreeW (
  859. IN PCWSTR KeyStr
  860. )
  861. {
  862. PCWSTR SubKey;
  863. EnterCriticalSection (&g_MemDbCs);
  864. SubKey = SelectHive (KeyStr);
  865. DeleteKey (SubKey, &g_db->FirstLevelRoot, FALSE);
  866. LeaveCriticalSection (&g_MemDbCs);
  867. }
  868. //
  869. // Enum functions
  870. //
  871. BOOL
  872. MemDbEnumFirstValueA (
  873. OUT PMEMDB_ENUMA EnumPtr,
  874. IN PCSTR PatternStr,
  875. IN INT Depth,
  876. IN DWORD Flags
  877. )
  878. {
  879. BOOL b = FALSE;
  880. PCWSTR p;
  881. PCSTR str;
  882. MEMDB_ENUMW enumw;
  883. p = ConvertAtoW (PatternStr);
  884. if (p) {
  885. b = MemDbEnumFirstValueW (&enumw, p, Depth, Flags);
  886. FreeConvertedStr (p);
  887. } else {
  888. b = FALSE;
  889. }
  890. if (b) {
  891. str = ConvertWtoA (enumw.szName);
  892. if (str) {
  893. // ANSI struct is padded to match UNICODE
  894. MYASSERT (sizeof (MEMDB_ENUMW) == sizeof (MEMDB_ENUMA));
  895. CopyMemory (EnumPtr, &enumw, sizeof (MEMDB_ENUMW));
  896. // Only the output key name needs to be converted
  897. StringCopyA (EnumPtr->szName, str);
  898. FreeConvertedStr (str);
  899. } else {
  900. b = FALSE;
  901. }
  902. }
  903. return b;
  904. }
  905. BOOL
  906. MemDbEnumFirstValueW (
  907. OUT PMEMDB_ENUMW EnumPtr,
  908. IN PCWSTR PatternStr,
  909. IN INT Depth,
  910. IN DWORD Flags
  911. )
  912. {
  913. PCWSTR Start;
  914. PCWSTR wstrLastWack;
  915. PCWSTR SubPatternStr;
  916. SubPatternStr = SelectHive (PatternStr);
  917. //
  918. // Init the EnumPtr struct
  919. //
  920. ZeroMemory (EnumPtr, sizeof (MEMDB_ENUM));
  921. if (!Depth) {
  922. Depth = MAX_ENUM_POS;
  923. }
  924. EnumPtr->Depth = Depth;
  925. EnumPtr->Flags = Flags;
  926. //
  927. // If pattern has wack, locate the starting level by
  928. // counting the number of parts that do not have
  929. // wildcard characters.
  930. //
  931. Start = SubPatternStr;
  932. while (wstrLastWack = wcschr (Start, L'\\')) {
  933. // See if part has a wildcard character
  934. while (Start < wstrLastWack) {
  935. if (*Start == L'*' || *Start == L'?')
  936. break;
  937. Start++;
  938. }
  939. // If a wildcard character was found, we have to stop here
  940. if (Start < wstrLastWack)
  941. break;
  942. // Otherwise, look at next part of the pattern
  943. Start = wstrLastWack + 1;
  944. EnumPtr->Start++;
  945. }
  946. EnumPtr->PosCount = 1;
  947. EnumPtr->LastPos[0] = INVALID_OFFSET;
  948. StringCopyW (EnumPtr->PatternStr, PatternStr);
  949. return MemDbEnumNextValueW (EnumPtr);
  950. }
  951. BOOL
  952. MemDbEnumNextValueA (
  953. IN OUT PMEMDB_ENUMA EnumPtr
  954. )
  955. {
  956. BOOL b = FALSE;
  957. PCSTR str;
  958. MEMDB_ENUMW enumw;
  959. // ANSI struct is padded to match UNICODE
  960. MYASSERT (sizeof (MEMDB_ENUMW) == sizeof (MEMDB_ENUMA));
  961. CopyMemory (&enumw, EnumPtr, sizeof (MEMDB_ENUMW));
  962. // ANSI output members are ignored (i.e. EnumPtr->szName)
  963. b = MemDbEnumNextValueW (&enumw);
  964. if (b) {
  965. str = ConvertWtoA (enumw.szName);
  966. if (str) {
  967. // ANSI struct is padded to match UNICODE
  968. MYASSERT (sizeof (MEMDB_ENUMW) == sizeof (MEMDB_ENUMA));
  969. CopyMemory (EnumPtr, &enumw, sizeof (MEMDB_ENUMW));
  970. // Only the output key name needs to be converted
  971. StringCopyA (EnumPtr->szName, str);
  972. FreeConvertedStr (str);
  973. } else {
  974. b = FALSE;
  975. }
  976. }
  977. return b;
  978. }
  979. BOOL
  980. MemDbEnumNextValueW (
  981. IN OUT PMEMDB_ENUMW EnumPtr
  982. )
  983. {
  984. // no init allowed in declarations
  985. PKEYSTRUCT KeyStruct = NULL;
  986. int Count;
  987. int Level;
  988. WCHAR PartBuf[MEMDB_MAX];
  989. PWSTR PartStr;
  990. PWSTR Src, Dest;
  991. int Pos;
  992. BOOL Wildcard;
  993. BOOL MatchNotFound;
  994. PCWSTR SubPatternStr;
  995. EnterCriticalSection (&g_MemDbCs);
  996. SubPatternStr = SelectHive (EnumPtr->PatternStr);
  997. MatchNotFound = TRUE;
  998. do {
  999. Wildcard = FALSE;
  1000. //
  1001. // The following states exist upon entry:
  1002. //
  1003. // STATE DESCRIPTION
  1004. // First time through PosCount == 1, LastPos[0] == INVALID_OFFSET
  1005. //
  1006. // Not first time LastPos[PosCount - 1] == INVALID_OFFSET
  1007. // through
  1008. //
  1009. // Not first time LastPos[PosCount - 1] != INVALID_OFFSET
  1010. // through, last match
  1011. // hit the depth
  1012. // ceiling
  1013. //
  1014. // PosCount points to the current unprocessed level, or when the
  1015. // depth ceiling is reached, it points to the level of the last
  1016. // match.
  1017. //
  1018. do {
  1019. //
  1020. // Build PartStr
  1021. //
  1022. Pos = EnumPtr->PosCount - 1;
  1023. Count = Pos + 1;
  1024. // Locate start of pattern part (if it is long enough)
  1025. PartStr = PartBuf;
  1026. for (Src = (PWSTR) SubPatternStr ; Count > 1 ; Count--) {
  1027. Src = wcschr (Src, L'\\');
  1028. if (!Src) {
  1029. break;
  1030. }
  1031. Src++;
  1032. }
  1033. // Copy part from pattern to buffer
  1034. if (Src) {
  1035. Dest = PartStr;
  1036. while (*Src && *Src != L'\\') {
  1037. *Dest = *Src;
  1038. Wildcard = Wildcard || (*Dest == L'*') || (*Dest == L'?');
  1039. Dest++;
  1040. Src++;
  1041. }
  1042. // Truncate
  1043. *Dest = 0;
  1044. }
  1045. // Use asterisk when pattern is shorter than current level
  1046. else {
  1047. PartStr = L"*";
  1048. Wildcard = TRUE;
  1049. }
  1050. //
  1051. // If current level is set to invalid offset, we have not yet
  1052. // tried it.
  1053. //
  1054. if (EnumPtr->LastPos[Pos] == INVALID_OFFSET) {
  1055. //
  1056. // Initialize the level
  1057. //
  1058. if (Pos == 0) {
  1059. EnumPtr->LastPos[0] = g_db->FirstLevelRoot;
  1060. } else {
  1061. KeyStruct = GetKeyStruct (EnumPtr->LastPos[Pos - 1]);
  1062. EnumPtr->LastPos[Pos] = KeyStruct->NextLevelRoot;
  1063. }
  1064. //
  1065. // If still invalid, the level is complete, and we need to
  1066. // go back.
  1067. //
  1068. if (EnumPtr->LastPos[Pos] == INVALID_OFFSET) {
  1069. EnumPtr->PosCount--;
  1070. continue;
  1071. }
  1072. //
  1073. // Level ready to be processed
  1074. //
  1075. if (!Wildcard) {
  1076. //
  1077. // Use binary tree to locate this item. If no match, the pattern
  1078. // will not match anything. Otherwise, we found something to
  1079. // return.
  1080. //
  1081. EnumPtr->LastPos[Pos] = FindKeyStruct (EnumPtr->LastPos[Pos], PartStr);
  1082. if (EnumPtr->LastPos[Pos] == INVALID_OFFSET) {
  1083. //
  1084. // Non-wildcard ot found. We can try going back because
  1085. // there might be a pattern at a higher level.
  1086. //
  1087. if (Pos > 0) {
  1088. PCWSTR p;
  1089. INT ParentLevel = 0;
  1090. INT LastParentLevel;
  1091. LastParentLevel = 0;
  1092. // Locate the previous pattern level
  1093. p = SubPatternStr;
  1094. while (*p && ParentLevel < Pos) {
  1095. // Locate wack, pattern or nul
  1096. while (*p && *p != L'\\') {
  1097. if (*p == L'?' || *p == L'*') {
  1098. break;
  1099. }
  1100. p++;
  1101. }
  1102. // If pattern or nul, set last pattern level
  1103. if (*p != L'\\') {
  1104. LastParentLevel = ParentLevel + 1;
  1105. // Jump to wack if not at nul
  1106. while (*p && *p != L'\\') {
  1107. p++;
  1108. }
  1109. }
  1110. // If more pattern exists, skip wack
  1111. if (p[0] && p[1]) {
  1112. MYASSERT (p[0] == L'\\');
  1113. p++;
  1114. }
  1115. ParentLevel++;
  1116. }
  1117. // Default: when no pattern, last pattern level is parent
  1118. // (Pos is zero-based while LastParentLevel is one-based)
  1119. if (!(*p)) {
  1120. LastParentLevel = Pos;
  1121. }
  1122. if (LastParentLevel) {
  1123. // Yes, a pattern does exist at a higher level
  1124. EnumPtr->PosCount = LastParentLevel;
  1125. continue;
  1126. }
  1127. }
  1128. // Pattern not found, we have exhausted all possibilities
  1129. LeaveCriticalSection (&g_MemDbCs);
  1130. return FALSE;
  1131. }
  1132. // If level is before start, keep searching forward instead
  1133. // of reporting a result.
  1134. if (EnumPtr->PosCount <= EnumPtr->Start) {
  1135. EnumPtr->PosCount++;
  1136. EnumPtr->LastPos[Pos + 1] = INVALID_OFFSET;
  1137. continue;
  1138. }
  1139. // Break out of last nested loop
  1140. break;
  1141. } else {
  1142. //
  1143. // Because of pattern, each item in the level must be examined.
  1144. // Set the pos to the first item and fall through to the pattern
  1145. // search code.
  1146. //
  1147. EnumPtr->LastPos[Pos] = GetFirstOffset (EnumPtr->LastPos[Pos]);
  1148. }
  1149. //
  1150. // Else if current level is not invalid, last time through we had a
  1151. // match and we need to increment the offset (wildcard patterns only).
  1152. //
  1153. } else {
  1154. if (Wildcard) {
  1155. EnumPtr->LastPos[Pos] = GetNextOffset (EnumPtr->LastPos[Pos]);
  1156. // If there are no more items, go back a level
  1157. if (EnumPtr->LastPos[Pos] == INVALID_OFFSET) {
  1158. EnumPtr->PosCount--;
  1159. continue;
  1160. }
  1161. }
  1162. }
  1163. //
  1164. // If we are here, it is because we are looking at a level, trying
  1165. // to find a pattern match. Loop until either a match is found,
  1166. // or we run out of items.
  1167. //
  1168. // The only exception is when the last match hit the depth ceiling
  1169. // and PartStr does not have a wildcard. In this case, we must
  1170. // reset the last pos and go back one level.
  1171. //
  1172. if (Wildcard) {
  1173. do {
  1174. // Get current key, advance, then check current key against pattern
  1175. KeyStruct = GetKeyStruct (EnumPtr->LastPos[Pos]);
  1176. if (IsPatternMatch (PartStr, GetKeyToken (KeyStruct->KeyToken)))
  1177. break;
  1178. EnumPtr->LastPos[Pos] = GetNextOffset (EnumPtr->LastPos[Pos]);
  1179. } while (EnumPtr->LastPos[Pos] != INVALID_OFFSET);
  1180. // Match found so break out of last nested loop
  1181. if (EnumPtr->LastPos[Pos] != INVALID_OFFSET)
  1182. break;
  1183. } else {
  1184. EnumPtr->LastPos[Pos] = INVALID_OFFSET;
  1185. }
  1186. //
  1187. // We ran out of items before finding a match, so it is time to
  1188. // go back up a level.
  1189. //
  1190. EnumPtr->PosCount--;
  1191. } while (EnumPtr->PosCount);
  1192. // Return if no items found
  1193. if (!EnumPtr->PosCount) {
  1194. LeaveCriticalSection (&g_MemDbCs);
  1195. return FALSE;
  1196. }
  1197. //
  1198. // A match was found. Build output string and prepare position for
  1199. // next level.
  1200. //
  1201. // Build the name of the item and get the value
  1202. EnumPtr->szName[0] = 0;
  1203. for (Level = EnumPtr->Start ; Level < EnumPtr->PosCount ; Level++) {
  1204. PWSTR namePointer = EnumPtr->szName;
  1205. KeyStruct = GetKeyStruct (EnumPtr->LastPos[Level]);
  1206. if (Level > EnumPtr -> Start) {
  1207. namePointer = _wcsappend(namePointer,L"\\");
  1208. }
  1209. _wcsappend (namePointer, GetKeyToken (KeyStruct->KeyToken));
  1210. }
  1211. MYASSERT (KeyStruct);
  1212. EnumPtr->bEndpoint = (KeyStruct->Flags & KSF_ENDPOINT) != 0;
  1213. EnumPtr->bBinary = (KeyStruct->Flags & KSF_BINARY) != 0;
  1214. EnumPtr->bProxy = (KeyStruct->Flags & KSF_PROXY_NODE) != 0;
  1215. EnumPtr->UserFlags = (KeyStruct->Flags & KSF_USERFLAG_MASK);
  1216. EnumPtr->BinaryPtr = GetKeyStructBinaryData (KeyStruct);
  1217. EnumPtr->BinarySize = GetKeyStructBinarySize (KeyStruct);
  1218. if (EnumPtr->bBinary) {
  1219. EnumPtr->dwValue = 0;
  1220. } else {
  1221. EnumPtr->dwValue = KeyStruct->dwValue;
  1222. }
  1223. EnumPtr->Offset = EnumPtr->LastPos[Pos] | (g_SelectedDatabase << RESERVED_BITS);
  1224. // Prepare position for next level
  1225. if ((EnumPtr->PosCount + 1) <= (EnumPtr->Depth + EnumPtr->Start)) {
  1226. EnumPtr->LastPos[Pos + 1] = INVALID_OFFSET;
  1227. EnumPtr->PosCount++;
  1228. }
  1229. switch (EnumPtr->Flags) {
  1230. case MEMDB_ALL_MATCHES:
  1231. MatchNotFound = FALSE;
  1232. break;
  1233. case MEMDB_ENDPOINTS_ONLY:
  1234. MatchNotFound = (KeyStruct->Flags & (KSF_ENDPOINT|KSF_PROXY_NODE)) != KSF_ENDPOINT;
  1235. break;
  1236. case MEMDB_BINARY_NODES_ONLY:
  1237. MatchNotFound = (KeyStruct->Flags & KSF_BINARY) == 0;
  1238. break;
  1239. case MEMDB_PROXY_NODES_ONLY:
  1240. MatchNotFound = (KeyStruct->Flags & KSF_PROXY_NODE) == 0;
  1241. break;
  1242. case MEMDB_ALL_BUT_PROXY:
  1243. MatchNotFound = (KeyStruct->Flags & KSF_PROXY_NODE) != 0;
  1244. break;
  1245. }
  1246. // Loop until flag match is found
  1247. } while (MatchNotFound);
  1248. LeaveCriticalSection (&g_MemDbCs);
  1249. return TRUE;
  1250. }
  1251. //
  1252. // Save and restore functions
  1253. //
  1254. BOOL
  1255. pPrivateMemDbSave (
  1256. PCWSTR FileName,
  1257. BOOL bUnicode
  1258. )
  1259. {
  1260. HANDLE FileHandle;
  1261. BOOL b = FALSE;
  1262. DWORD BytesWritten;
  1263. EnterCriticalSection (&g_MemDbCs);
  1264. __try {
  1265. SelectDatabase(0);
  1266. if (bUnicode) {
  1267. FileHandle = CreateFileW (FileName, GENERIC_WRITE, 0, NULL,
  1268. CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1269. } else {
  1270. FileHandle = CreateFileA ((PCSTR) FileName, GENERIC_WRITE, 0, NULL,
  1271. CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1272. }
  1273. if (FileHandle == INVALID_HANDLE_VALUE) {
  1274. if (bUnicode) {
  1275. DEBUGMSGW ((DBG_ERROR, "Can't open %s", FileName));
  1276. } else {
  1277. DEBUGMSGA ((DBG_ERROR, "Can't open %s", FileName));
  1278. }
  1279. __leave;
  1280. }
  1281. // entire file written in UNICODE char set
  1282. b = WriteFile (FileHandle, FILE_SIGNATURE, sizeof(FILE_SIGNATURE), &BytesWritten, NULL);
  1283. if (b) {
  1284. b = WriteFile (FileHandle, g_db, sizeof (DATABASE), &BytesWritten, NULL);
  1285. }
  1286. if (b) {
  1287. b = WriteFile (FileHandle, g_db->Buf, g_db->AllocSize, &BytesWritten, NULL);
  1288. if (BytesWritten != g_db->AllocSize)
  1289. b = FALSE;
  1290. }
  1291. if (b) {
  1292. b = SaveHashBlock (FileHandle);
  1293. }
  1294. if (b) {
  1295. b = SaveBinaryBlocks (FileHandle);
  1296. }
  1297. PushError();
  1298. CloseHandle (FileHandle);
  1299. PopError();
  1300. if (!b) {
  1301. if (bUnicode) {
  1302. DEBUGMSGW ((DBG_ERROR, "Error writing %s", FileName));
  1303. DeleteFileW (FileName);
  1304. } else {
  1305. DEBUGMSGA ((DBG_ERROR, "Error writing %s", FileName));
  1306. DeleteFileA ((PCSTR) FileName);
  1307. }
  1308. __leave;
  1309. }
  1310. MYASSERT (b == TRUE);
  1311. }
  1312. __finally {
  1313. PushError();
  1314. LeaveCriticalSection (&g_MemDbCs);
  1315. PopError();
  1316. }
  1317. return b;
  1318. }
  1319. BOOL
  1320. MemDbSaveA (
  1321. PCSTR FileName
  1322. )
  1323. {
  1324. return pPrivateMemDbSave ((PCWSTR) FileName, FALSE); // FALSE=ANSI
  1325. }
  1326. BOOL
  1327. MemDbSaveW (
  1328. PCWSTR FileName
  1329. )
  1330. {
  1331. return pPrivateMemDbSave (FileName, TRUE); // TRUE=UNICODE
  1332. }
  1333. BOOL
  1334. pPrivateMemDbLoad (
  1335. IN PCWSTR FileName,
  1336. IN BOOL bUnicode,
  1337. OUT PMEMDB_VERSION Version, OPTIONAL
  1338. IN BOOL QueryVersionOnly
  1339. )
  1340. {
  1341. HANDLE FileHandle;
  1342. BOOL b;
  1343. DWORD BytesRead;
  1344. WCHAR Buf[sizeof(FILE_SIGNATURE)];
  1345. PBYTE TempBuf = NULL;
  1346. PCWSTR VerPtr;
  1347. EnterCriticalSection (&g_MemDbCs);
  1348. if (Version) {
  1349. ZeroMemory (Version, sizeof (MEMDB_VERSION));
  1350. }
  1351. //
  1352. // Blow away existing resources
  1353. //
  1354. if (!QueryVersionOnly) {
  1355. pFreeAllDatabases();
  1356. }
  1357. //
  1358. // Load in file
  1359. //
  1360. if (*FileName && FileName) {
  1361. if (bUnicode) {
  1362. FileHandle = CreateFileW (FileName, GENERIC_READ, 0, NULL,
  1363. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1364. } else {
  1365. FileHandle = CreateFileA ((PCSTR) FileName, GENERIC_READ, 0, NULL,
  1366. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1367. }
  1368. } else {
  1369. FileHandle = INVALID_HANDLE_VALUE;
  1370. }
  1371. b = (FileHandle != INVALID_HANDLE_VALUE);
  1372. __try {
  1373. //
  1374. // Obtain the file signature
  1375. //
  1376. // NOTE: Entire file read is in UNICODE char set
  1377. //
  1378. if (b) {
  1379. b = ReadFile (FileHandle, Buf, sizeof(FILE_SIGNATURE), &BytesRead, NULL);
  1380. if (Version) {
  1381. if (StringMatchByteCountW (
  1382. VERSION_BASE_SIGNATURE,
  1383. Buf,
  1384. sizeof (VERSION_BASE_SIGNATURE) - sizeof (WCHAR)
  1385. )) {
  1386. Version->Valid = TRUE;
  1387. //
  1388. // Identify version number
  1389. //
  1390. VerPtr = (PCWSTR) ((PBYTE) Buf + sizeof (VERSION_BASE_SIGNATURE) - sizeof (WCHAR));
  1391. if (StringMatchByteCountW (
  1392. MEMDB_VERSION,
  1393. VerPtr,
  1394. sizeof (MEMDB_VERSION) - sizeof (WCHAR)
  1395. )) {
  1396. Version->CurrentVersion = TRUE;
  1397. }
  1398. Version->Version = (UINT) _wtoi (VerPtr + 1);
  1399. //
  1400. // Identify checked or free build
  1401. //
  1402. VerPtr += (sizeof (MEMDB_VERSION) / sizeof (WCHAR)) - 1;
  1403. if (StringMatchByteCountW (
  1404. MEMDB_DEBUG_SIGNATURE,
  1405. VerPtr,
  1406. sizeof (MEMDB_DEBUG_SIGNATURE) - sizeof (WCHAR)
  1407. )) {
  1408. Version->Debug = TRUE;
  1409. } else if (!StringMatchByteCountW (
  1410. VerPtr,
  1411. MEMDB_NODBG_SIGNATURE,
  1412. sizeof (MEMDB_NODBG_SIGNATURE) - sizeof (WCHAR)
  1413. )) {
  1414. Version->Valid = FALSE;
  1415. }
  1416. }
  1417. }
  1418. }
  1419. if (QueryVersionOnly) {
  1420. b = FALSE;
  1421. }
  1422. if (b) {
  1423. b = StringMatchW (Buf, FILE_SIGNATURE);
  1424. #ifdef DEBUG
  1425. //
  1426. // This code allows a debug build of memdb to work with both
  1427. // debug and retail versions of the DAT file
  1428. //
  1429. if (!b) {
  1430. if (StringMatchW (Buf, DEBUG_FILE_SIGNATURE)) {
  1431. g_UseDebugStructs = TRUE;
  1432. b = TRUE;
  1433. } else if (StringMatchW (Buf, RETAIL_FILE_SIGNATURE)) {
  1434. DEBUGMSG ((DBG_ERROR, "memdb dat file is from free build; checked version expected"));
  1435. g_UseDebugStructs = FALSE;
  1436. b = TRUE;
  1437. }
  1438. }
  1439. #else
  1440. if (!b) {
  1441. SetLastError (ERROR_BAD_FORMAT);
  1442. LOG ((LOG_WARNING, "Warning: data file could be from checked build; free version expected"));
  1443. }
  1444. #endif
  1445. }
  1446. //
  1447. // Obtain the database struct
  1448. //
  1449. if (b) {
  1450. b = ReadFile (FileHandle, (PBYTE) g_db, sizeof (DATABASE), &BytesRead, NULL);
  1451. if (BytesRead != sizeof (DATABASE)) {
  1452. b = FALSE;
  1453. SetLastError (ERROR_BAD_FORMAT);
  1454. }
  1455. }
  1456. //
  1457. // Allocate the memory block
  1458. //
  1459. if (b) {
  1460. TempBuf = (PBYTE) MemAlloc (g_hHeap, 0, g_db->AllocSize);
  1461. if (TempBuf) {
  1462. g_db->Buf = TempBuf;
  1463. TempBuf = NULL;
  1464. } else {
  1465. b = FALSE;
  1466. }
  1467. }
  1468. //
  1469. // Read the memory block
  1470. //
  1471. if (b) {
  1472. b = ReadFile (FileHandle, g_db->Buf, g_db->AllocSize, &BytesRead, NULL);
  1473. if (BytesRead != g_db->AllocSize) {
  1474. b = FALSE;
  1475. SetLastError (ERROR_BAD_FORMAT);
  1476. }
  1477. }
  1478. //
  1479. // Read the hash table
  1480. //
  1481. if (b) {
  1482. b = LoadHashBlock (FileHandle);
  1483. }
  1484. //
  1485. // Read binary blocks
  1486. //
  1487. if (b) {
  1488. b = LoadBinaryBlocks (FileHandle);
  1489. }
  1490. }
  1491. __except (TRUE) {
  1492. b = FALSE;
  1493. PushError();
  1494. LOG ((LOG_ERROR, "MemDb dat file %s could not be loaded because of an exception", FileName));
  1495. FreeAllBinaryBlocks();
  1496. PopError();
  1497. }
  1498. PushError();
  1499. if (FileHandle != INVALID_HANDLE_VALUE) {
  1500. CloseHandle (FileHandle);
  1501. }
  1502. if (!b && !QueryVersionOnly) {
  1503. pFreeAllDatabases();
  1504. pInitializeMemDb();
  1505. }
  1506. LeaveCriticalSection (&g_MemDbCs);
  1507. PopError();
  1508. if (QueryVersionOnly) {
  1509. return TRUE;
  1510. }
  1511. return b;
  1512. }
  1513. BOOL
  1514. MemDbLoadA (
  1515. IN PCSTR FileName
  1516. )
  1517. {
  1518. return pPrivateMemDbLoad ((PCWSTR) FileName, FALSE, NULL, FALSE);
  1519. }
  1520. BOOL
  1521. MemDbLoadW (
  1522. IN PCWSTR FileName
  1523. )
  1524. {
  1525. return pPrivateMemDbLoad (FileName, TRUE, NULL, FALSE);
  1526. }
  1527. BOOL
  1528. MemDbValidateDatabase (
  1529. VOID
  1530. )
  1531. {
  1532. MEMDB_ENUMW e;
  1533. if (MemDbEnumFirstValueW (&e, L"*", 0, MEMDB_ENDPOINTS_ONLY)) {
  1534. do {
  1535. if (!pPrivateMemDbGetValueW (e.szName, NULL, NULL)) {
  1536. return FALSE;
  1537. }
  1538. } while (MemDbEnumNextValueW (&e));
  1539. }
  1540. return TRUE;
  1541. }
  1542. BOOL
  1543. MemDbCreateTemporaryKeyA (
  1544. IN PCSTR KeyName
  1545. )
  1546. {
  1547. PCWSTR KeyNameW;
  1548. BOOL b = FALSE;
  1549. KeyNameW = ConvertAtoW (KeyName);
  1550. if (KeyNameW) {
  1551. b = MemDbCreateTemporaryKeyW (KeyNameW);
  1552. FreeConvertedStr (KeyNameW);
  1553. }
  1554. return b;
  1555. }
  1556. BOOL
  1557. MemDbCreateTemporaryKeyW (
  1558. IN PCWSTR KeyName
  1559. )
  1560. {
  1561. UINT Count;
  1562. UINT Index;
  1563. PDATABASE Database;
  1564. DWORD KeyOffset;
  1565. PCWSTR SubKey;
  1566. BOOL b = FALSE;
  1567. EnterCriticalSection (&g_MemDbCs);
  1568. __try {
  1569. if (wcslen (KeyName) >= MAX_HIVE_NAME) {
  1570. SetLastError (ERROR_INVALID_PARAMETER);
  1571. __leave;
  1572. }
  1573. SubKey = SelectHive (KeyName);
  1574. KeyOffset = FindKey (SubKey);
  1575. if (KeyOffset != INVALID_OFFSET) {
  1576. SetLastError (ERROR_ALREADY_EXISTS);
  1577. __leave;
  1578. }
  1579. Count = GrowListGetSize (&g_DatabaseList);
  1580. for (Index = 1 ; Index < Count ; Index++) {
  1581. Database = (PDATABASE) GrowListGetItem (&g_DatabaseList, Index);
  1582. if (Database && StringIMatchW (Database->Hive, KeyName)) {
  1583. SetLastError (ERROR_ALREADY_EXISTS);
  1584. __leave;
  1585. }
  1586. }
  1587. b = pCreateDatabase (KeyName);
  1588. }
  1589. __finally {
  1590. LeaveCriticalSection (&g_MemDbCs);
  1591. }
  1592. return b;
  1593. }
  1594. /*++
  1595. Routine Description:
  1596. MemDbMakeNonPrintableKey converts the double-backslashe pairs in a string
  1597. to ASCII 1, a non-printable character. This allows the caller to store
  1598. properly escaped strings in MemDb.
  1599. This routine is desinged to be expanded for other types of escape
  1600. processing.
  1601. Arguments:
  1602. KeyName - Specifies the key text; receives the converted text. The DBCS
  1603. version may grow the text buffer, so the text buffer must be twice
  1604. the length of the inbound string.
  1605. Flags - Specifies the type of conversion. Currently only
  1606. MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1 is supported.
  1607. Return Value:
  1608. none
  1609. --*/
  1610. VOID
  1611. MemDbMakeNonPrintableKeyA (
  1612. IN OUT PSTR KeyName,
  1613. IN DWORD Flags
  1614. )
  1615. {
  1616. while (*KeyName) {
  1617. if (Flags & MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1) {
  1618. if (_mbsnextc (KeyName) == '\\' &&
  1619. _mbsnextc (_mbsinc (KeyName)) == '\\'
  1620. ) {
  1621. _setmbchar (KeyName, 1);
  1622. KeyName = _mbsinc (KeyName);
  1623. MYASSERT (_mbsnextc (KeyName) == '\\');
  1624. _setmbchar (KeyName, 1);
  1625. }
  1626. DEBUGMSG_IF ((
  1627. _mbsnextc (KeyName) == 1,
  1628. DBG_WHOOPS,
  1629. "MemDbMakeNonPrintableKeyA: Non-printable character "
  1630. "collision detected; key was damaged"
  1631. ));
  1632. }
  1633. if (Flags & MEMDB_CONVERT_WILD_STAR_TO_ASCII_2) {
  1634. if (_mbsnextc (KeyName) == '*') {
  1635. _setmbchar (KeyName, 2);
  1636. }
  1637. DEBUGMSG_IF ((
  1638. _mbsnextc (_mbsinc (KeyName)) == 2,
  1639. DBG_WHOOPS,
  1640. "MemDbMakeNonPrintableKeyA: Non-printable character "
  1641. "collision detected; key was damaged"
  1642. ));
  1643. }
  1644. if (Flags & MEMDB_CONVERT_WILD_QMARK_TO_ASCII_3) {
  1645. if (_mbsnextc (KeyName) == '?') {
  1646. _setmbchar (KeyName, 3);
  1647. }
  1648. DEBUGMSG_IF ((
  1649. _mbsnextc (_mbsinc (KeyName)) == 3,
  1650. DBG_WHOOPS,
  1651. "MemDbMakeNonPrintableKeyA: Non-printable character "
  1652. "collision detected; key was damaged"
  1653. ));
  1654. }
  1655. KeyName = _mbsinc (KeyName);
  1656. }
  1657. }
  1658. VOID
  1659. MemDbMakeNonPrintableKeyW (
  1660. IN OUT PWSTR KeyName,
  1661. IN DWORD Flags
  1662. )
  1663. {
  1664. while (*KeyName) {
  1665. if (Flags & MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1) {
  1666. if (KeyName[0] == L'\\' && KeyName[1] == L'\\') {
  1667. KeyName[0] = 1;
  1668. KeyName[1] = 1;
  1669. KeyName++;
  1670. }
  1671. DEBUGMSG_IF ((
  1672. KeyName[0] == 1,
  1673. DBG_WHOOPS,
  1674. "MemDbMakeNonPrintableKeyW: Non-printable character "
  1675. "collision detected; key was damaged"
  1676. ));
  1677. }
  1678. if (Flags & MEMDB_CONVERT_WILD_STAR_TO_ASCII_2) {
  1679. if (KeyName[0] == L'*') {
  1680. KeyName[0] = 2;
  1681. }
  1682. DEBUGMSG_IF ((
  1683. KeyName[1] == 2,
  1684. DBG_WHOOPS,
  1685. "MemDbMakeNonPrintableKeyW: Non-printable character "
  1686. "collision detected; key was damaged"
  1687. ));
  1688. }
  1689. if (Flags & MEMDB_CONVERT_WILD_QMARK_TO_ASCII_3) {
  1690. if (KeyName[0] == L'*') {
  1691. KeyName[0] = 3;
  1692. }
  1693. DEBUGMSG_IF ((
  1694. KeyName[1] == 3,
  1695. DBG_WHOOPS,
  1696. "MemDbMakeNonPrintableKeyW: Non-printable character "
  1697. "collision detected; key was damaged"
  1698. ));
  1699. }
  1700. KeyName++;
  1701. }
  1702. }
  1703. /*++
  1704. Routine Description:
  1705. MemDbMakePrintableKey converts the ASCII 1 characters to backslashes,
  1706. restoring the string converted by MemDbMakeNonPrintableKey.
  1707. This routine is desinged to be expanded for other types of escape
  1708. processing.
  1709. Arguments:
  1710. KeyName - Specifies the key text; receives the converted text. The DBCS
  1711. version may grow the text buffer, so the text buffer must be twice
  1712. the length of the inbound string.
  1713. Flags - Specifies the type of conversion. Currently only
  1714. MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1 is supported.
  1715. Return Value:
  1716. none
  1717. --*/
  1718. VOID
  1719. MemDbMakePrintableKeyA (
  1720. IN OUT PSTR KeyName,
  1721. IN DWORD Flags
  1722. )
  1723. {
  1724. while (*KeyName) {
  1725. if (Flags & MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1) {
  1726. if (_mbsnextc (KeyName) == 1) {
  1727. _setmbchar (KeyName, '\\');
  1728. }
  1729. }
  1730. if (Flags & MEMDB_CONVERT_WILD_STAR_TO_ASCII_2) {
  1731. if (_mbsnextc (KeyName) == 2) {
  1732. _setmbchar (KeyName, '*');
  1733. }
  1734. }
  1735. if (Flags & MEMDB_CONVERT_WILD_QMARK_TO_ASCII_3) {
  1736. if (_mbsnextc (KeyName) == 3) {
  1737. _setmbchar (KeyName, '?');
  1738. }
  1739. }
  1740. KeyName = _mbsinc (KeyName);
  1741. }
  1742. }
  1743. VOID
  1744. MemDbMakePrintableKeyW (
  1745. IN OUT PWSTR KeyName,
  1746. IN DWORD Flags
  1747. )
  1748. {
  1749. while (*KeyName) {
  1750. if (Flags & MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1) {
  1751. if (KeyName[0] == 1) {
  1752. KeyName[0] = L'\\';
  1753. }
  1754. }
  1755. if (Flags & MEMDB_CONVERT_WILD_STAR_TO_ASCII_2) {
  1756. if (KeyName[0] == 2) {
  1757. KeyName[0] = L'*';
  1758. }
  1759. }
  1760. if (Flags & MEMDB_CONVERT_WILD_QMARK_TO_ASCII_3) {
  1761. if (KeyName[0] == 3) {
  1762. KeyName[0] = L'?';
  1763. }
  1764. }
  1765. KeyName++;
  1766. }
  1767. }
  1768. VOID
  1769. GetFixedUserNameA (
  1770. IN OUT PSTR SrcUserBuf
  1771. )
  1772. /*++
  1773. Routine Description:
  1774. GetFixedUserName looks in memdb for the user specified in SrcUserBuf,
  1775. and if found, returns the changed name.
  1776. Arguments:
  1777. SrcUserBuf - Specifies the user to look up as returned from the Win9x
  1778. registry. Receives the user name to create on NT.
  1779. Return Value:
  1780. None.
  1781. --*/
  1782. {
  1783. CHAR EncodedName[MEMDB_MAX];
  1784. CHAR FixedName[MEMDB_MAX];
  1785. StackStringCopyA (EncodedName, SrcUserBuf);
  1786. MemDbMakeNonPrintableKeyA (
  1787. EncodedName,
  1788. MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1|
  1789. MEMDB_CONVERT_WILD_STAR_TO_ASCII_2|
  1790. MEMDB_CONVERT_WILD_QMARK_TO_ASCII_3
  1791. );
  1792. if (MemDbGetEndpointValueExA (
  1793. MEMDB_CATEGORY_FIXEDUSERNAMESA,
  1794. EncodedName,
  1795. NULL,
  1796. FixedName
  1797. )) {
  1798. StringCopyA (SrcUserBuf, FixedName);
  1799. }
  1800. }
  1801. VOID
  1802. GetFixedUserNameW (
  1803. IN OUT PWSTR SrcUserBuf
  1804. )
  1805. /*++
  1806. Routine Description:
  1807. GetFixedUserName looks in memdb for the user specified in SrcUserBuf,
  1808. and if found, returns the changed name.
  1809. Arguments:
  1810. SrcUserBuf - Specifies the user to look up as returned from the Win9x
  1811. registry. Receives the user name to create on NT.
  1812. Return Value:
  1813. None.
  1814. --*/
  1815. {
  1816. WCHAR EncodedName[MEMDB_MAX];
  1817. WCHAR FixedName[MEMDB_MAX];
  1818. StackStringCopyW (EncodedName, SrcUserBuf);
  1819. MemDbMakeNonPrintableKeyW (
  1820. EncodedName,
  1821. MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1|
  1822. MEMDB_CONVERT_WILD_STAR_TO_ASCII_2|
  1823. MEMDB_CONVERT_WILD_QMARK_TO_ASCII_3
  1824. );
  1825. if (MemDbGetEndpointValueExW (
  1826. MEMDB_CATEGORY_FIXEDUSERNAMESW,
  1827. EncodedName,
  1828. NULL,
  1829. FixedName
  1830. )) {
  1831. StringCopyW (SrcUserBuf, FixedName);
  1832. }
  1833. }
  1834. /*
  1835. The format of the binary file for MemDb export
  1836. DWORD Signature
  1837. DWORD Version
  1838. DWORD GlobalFlags// 0x00000001 mask for Ansi format
  1839. // 0x00000002 mask for Temporary key
  1840. BYTE Root[]; // The root of the tree (zero terminated).
  1841. struct _KEY {
  1842. WORD Flags; // 0xF000 mask for accessing the entry flags
  1843. // - 0x1000 - Mask for Key name (0 - root relative, 1 - previous key relative)
  1844. // - 0x2000 - Mask for existing data (0 - no data, 1 - some data)
  1845. // - 0x4000 - Mast for data type (0 - DWORD, 1 - binary data)
  1846. // - 0x8000 - Mast for key flags (0 - nonexistent, 1 - existent)
  1847. // 0x0FFF mask for accessing size of the entry (except the data)
  1848. BYTE Key[]; // Should be PCSTR or PCWSTR (not zero terminated)
  1849. DWORD KeyFlags; //optional (dependant on Flags).
  1850. BYTE Data[]; // optional (dependant on Flags).
  1851. // if BLOB first DWORD is the size of the BLOB
  1852. // if DWORD then has exactly 4 bytes
  1853. }
  1854. ...
  1855. */
  1856. #define MEMDB_EXPORT_SIGNATURE 0x42444D4D
  1857. #define MEMDB_EXPORT_VERSION 0x00000001
  1858. #define MEMDB_EXPORT_FLAGS_ANSI 0x00000001
  1859. #define MEMDB_EXPORT_FLAGS_TEMP_KEY 0x00000002
  1860. #define MEMDB_EXPORT_FLAGS_PREV_RELATIVE 0x1000
  1861. #define MEMDB_EXPORT_FLAGS_DATA_PRESENT 0x2000
  1862. #define MEMDB_EXPORT_FLAGS_BINARY_DATA 0x4000
  1863. #define MEMDB_EXPORT_FLAGS_FLAGS_PRESENT 0x8000
  1864. #define MEMDB_EXPORT_FLAGS_SIZE_MASK 0x0FFF
  1865. BOOL
  1866. pMemDbExportWorkerA (
  1867. IN PCSTR RootTree,
  1868. IN PCSTR FileName
  1869. )
  1870. {
  1871. HANDLE fileHandle = INVALID_HANDLE_VALUE;
  1872. PCWSTR uRootTree;
  1873. PCSTR lastWackPtr;
  1874. DWORD globalFlags;
  1875. WORD localFlags;
  1876. CHAR key[MEMDB_MAX];
  1877. DWORD keySize;
  1878. DWORD copySize;
  1879. MEMDB_ENUMA e;
  1880. WORD blobSize;
  1881. DWORD written;
  1882. fileHandle = CreateFileA (FileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1883. if (fileHandle == INVALID_HANDLE_VALUE) {
  1884. return FALSE;
  1885. }
  1886. globalFlags = MEMDB_EXPORT_SIGNATURE;
  1887. WriteFile (fileHandle, &globalFlags, sizeof (DWORD), &written, NULL);
  1888. globalFlags = MEMDB_EXPORT_VERSION;
  1889. WriteFile (fileHandle, &globalFlags, sizeof (DWORD), &written, NULL);
  1890. globalFlags = MEMDB_EXPORT_FLAGS_ANSI;
  1891. // get the information if this key is a temporary key and set the flags if true
  1892. uRootTree = ConvertAtoW (RootTree);
  1893. if (IsTemporaryKey (uRootTree)) {
  1894. globalFlags |= MEMDB_EXPORT_FLAGS_TEMP_KEY;
  1895. }
  1896. FreeConvertedStr (uRootTree);
  1897. WriteFile (fileHandle, &globalFlags, sizeof (DWORD), &written, NULL);
  1898. // now write the root tree
  1899. WriteFile (fileHandle, RootTree, SizeOfStringA (RootTree), &written, NULL);
  1900. MemDbBuildKeyA (key, RootTree, "*", NULL, NULL);
  1901. if (MemDbEnumFirstValueA (&e, key, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
  1902. key [0] = 0;
  1903. keySize = 0;
  1904. do {
  1905. // initialize the flags
  1906. localFlags = 0;
  1907. if (e.bBinary) {
  1908. localFlags |= MEMDB_EXPORT_FLAGS_DATA_PRESENT;
  1909. localFlags |= MEMDB_EXPORT_FLAGS_BINARY_DATA;
  1910. } else {
  1911. if (e.dwValue) {
  1912. localFlags |= MEMDB_EXPORT_FLAGS_DATA_PRESENT;
  1913. }
  1914. }
  1915. if (e.UserFlags) {
  1916. localFlags |= MEMDB_EXPORT_FLAGS_FLAGS_PRESENT;
  1917. }
  1918. // let's compute the size for this blob
  1919. blobSize = sizeof (WORD); // Flags
  1920. if (keySize &&
  1921. StringIMatchByteCountA (key, e.szName, keySize - sizeof (CHAR)) &&
  1922. (e.szName [keySize - 1] == '\\')
  1923. ) {
  1924. localFlags |= MEMDB_EXPORT_FLAGS_PREV_RELATIVE;
  1925. copySize = SizeOfStringA (e.szName) - keySize - sizeof (CHAR);
  1926. } else {
  1927. copySize = SizeOfStringA (e.szName) - sizeof (CHAR);
  1928. keySize = 0;
  1929. }
  1930. MYASSERT (copySize < 4096);
  1931. blobSize += (WORD) copySize;
  1932. localFlags |= blobSize;
  1933. // write the flags
  1934. WriteFile (fileHandle, &localFlags, sizeof (WORD), &written, NULL);
  1935. // write the key
  1936. WriteFile (fileHandle, ((PBYTE) e.szName) + keySize, copySize, &written, NULL);
  1937. // write the key flags if appropriate
  1938. if (localFlags & MEMDB_EXPORT_FLAGS_FLAGS_PRESENT) {
  1939. WriteFile (fileHandle, &e.UserFlags, sizeof (DWORD), &written, NULL);
  1940. }
  1941. // write the data if appropriate
  1942. if (localFlags & MEMDB_EXPORT_FLAGS_DATA_PRESENT) {
  1943. if (localFlags & MEMDB_EXPORT_FLAGS_BINARY_DATA) {
  1944. WriteFile (fileHandle, &e.BinarySize, sizeof (DWORD), &written, NULL);
  1945. WriteFile (fileHandle, e.BinaryPtr, e.BinarySize, &written, NULL);
  1946. } else {
  1947. WriteFile (fileHandle, &e.dwValue, sizeof (DWORD), &written, NULL);
  1948. }
  1949. }
  1950. lastWackPtr = _mbsrchr (e.szName, '\\');
  1951. if (lastWackPtr) {
  1952. keySize = ByteCountABA (e.szName, lastWackPtr) + sizeof (CHAR);
  1953. StringCopyByteCountA (key, e.szName, keySize);
  1954. } else {
  1955. keySize = 0;
  1956. }
  1957. } while (MemDbEnumNextValueA (&e));
  1958. }
  1959. localFlags = 0;
  1960. // finally write the zero terminator
  1961. WriteFile (fileHandle, &localFlags, sizeof (WORD), &written, NULL);
  1962. CloseHandle (fileHandle);
  1963. return TRUE;
  1964. }
  1965. BOOL
  1966. pMemDbExportWorkerW (
  1967. IN PCWSTR RootTree,
  1968. IN PCWSTR FileName
  1969. )
  1970. {
  1971. HANDLE fileHandle = INVALID_HANDLE_VALUE;
  1972. PCWSTR lastWackPtr;
  1973. DWORD globalFlags;
  1974. WORD localFlags;
  1975. WCHAR key[MEMDB_MAX];
  1976. DWORD keySize;
  1977. DWORD copySize;
  1978. MEMDB_ENUMW e;
  1979. WORD blobSize;
  1980. DWORD written;
  1981. fileHandle = CreateFileW (FileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1982. if (fileHandle == INVALID_HANDLE_VALUE) {
  1983. return FALSE;
  1984. }
  1985. globalFlags = MEMDB_EXPORT_SIGNATURE;
  1986. WriteFile (fileHandle, &globalFlags, sizeof (DWORD), &written, NULL);
  1987. globalFlags = MEMDB_EXPORT_VERSION;
  1988. WriteFile (fileHandle, &globalFlags, sizeof (DWORD), &written, NULL);
  1989. // get the information if this key is a temporary key and set the flags if true
  1990. if (IsTemporaryKey (RootTree)) {
  1991. globalFlags |= MEMDB_EXPORT_FLAGS_TEMP_KEY;
  1992. }
  1993. WriteFile (fileHandle, &globalFlags, sizeof (DWORD), &written, NULL);
  1994. // now write the root tree
  1995. WriteFile (fileHandle, RootTree, SizeOfStringW (RootTree), &written, NULL);
  1996. MemDbBuildKeyW (key, RootTree, L"*", NULL, NULL);
  1997. if (MemDbEnumFirstValueW (&e, key, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
  1998. key [0] = 0;
  1999. keySize = 0;
  2000. do {
  2001. // initialize the flags
  2002. localFlags = 0;
  2003. if (e.bBinary) {
  2004. localFlags |= MEMDB_EXPORT_FLAGS_DATA_PRESENT;
  2005. localFlags |= MEMDB_EXPORT_FLAGS_BINARY_DATA;
  2006. } else {
  2007. if (e.dwValue) {
  2008. localFlags |= MEMDB_EXPORT_FLAGS_DATA_PRESENT;
  2009. }
  2010. }
  2011. if (e.UserFlags) {
  2012. localFlags |= MEMDB_EXPORT_FLAGS_FLAGS_PRESENT;
  2013. }
  2014. // let's compute the size for this blob
  2015. blobSize = sizeof (WORD); // Flags
  2016. if (keySize &&
  2017. StringIMatchByteCountW (key, e.szName, keySize - sizeof (WCHAR)) &&
  2018. (e.szName [keySize - 1] == L'\\')
  2019. ) {
  2020. localFlags |= MEMDB_EXPORT_FLAGS_PREV_RELATIVE;
  2021. copySize = SizeOfStringW (e.szName) - keySize - sizeof (WCHAR);
  2022. } else {
  2023. copySize = SizeOfStringW (e.szName) - sizeof (WCHAR);
  2024. keySize = 0;
  2025. }
  2026. MYASSERT (copySize < 4096);
  2027. blobSize += (WORD) copySize;
  2028. localFlags |= blobSize;
  2029. // write the flags
  2030. WriteFile (fileHandle, &localFlags, sizeof (WORD), &written, NULL);
  2031. // write the key
  2032. WriteFile (fileHandle, ((PBYTE) e.szName) + keySize, copySize, &written, NULL);
  2033. // write the key flags if appropriate
  2034. if (localFlags & MEMDB_EXPORT_FLAGS_FLAGS_PRESENT) {
  2035. WriteFile (fileHandle, &e.UserFlags, sizeof (DWORD), &written, NULL);
  2036. }
  2037. // write the data if appropriate
  2038. if (localFlags & MEMDB_EXPORT_FLAGS_DATA_PRESENT) {
  2039. if (localFlags & MEMDB_EXPORT_FLAGS_BINARY_DATA) {
  2040. WriteFile (fileHandle, &e.BinarySize, sizeof (DWORD), &written, NULL);
  2041. WriteFile (fileHandle, e.BinaryPtr, e.BinarySize, &written, NULL);
  2042. } else {
  2043. WriteFile (fileHandle, &e.dwValue, sizeof (DWORD), &written, NULL);
  2044. }
  2045. }
  2046. lastWackPtr = wcsrchr (e.szName, L'\\');
  2047. if (lastWackPtr) {
  2048. keySize = ByteCountABW (e.szName, lastWackPtr) + sizeof (WCHAR);
  2049. StringCopyByteCountW (key, e.szName, keySize);
  2050. } else {
  2051. keySize = 0;
  2052. }
  2053. } while (MemDbEnumNextValueW (&e));
  2054. }
  2055. localFlags = 0;
  2056. // finally write the zero terminator
  2057. WriteFile (fileHandle, &localFlags, sizeof (WORD), &written, NULL);
  2058. CloseHandle (fileHandle);
  2059. return TRUE;
  2060. }
  2061. BOOL
  2062. MemDbExportA (
  2063. IN PCSTR RootTree,
  2064. IN PCSTR FileName,
  2065. IN BOOL AnsiFormat
  2066. )
  2067. /*++
  2068. Routine Description:
  2069. MemDbExportA exports a tree in a private binary format. The format is described above.
  2070. Arguments:
  2071. RootTree - Specifies the tree to be exported
  2072. FileName - Name of the binary format file to export to.
  2073. AnsiFormat - Keys should be written in ANSI rather than in Unicode.
  2074. Return Value:
  2075. TRUE is successfull, FALSE if not.
  2076. --*/
  2077. {
  2078. PCWSTR uRootTree, uFileName;
  2079. BOOL result = TRUE;
  2080. if (AnsiFormat) {
  2081. result = pMemDbExportWorkerA (RootTree, FileName);
  2082. } else {
  2083. uRootTree = ConvertAtoW (RootTree);
  2084. uFileName = ConvertAtoW (FileName);
  2085. result = pMemDbExportWorkerW (uRootTree, uFileName);
  2086. FreeConvertedStr (uFileName);
  2087. FreeConvertedStr (uRootTree);
  2088. }
  2089. return result;
  2090. }
  2091. BOOL
  2092. MemDbExportW (
  2093. IN PCWSTR RootTree,
  2094. IN PCWSTR FileName,
  2095. IN BOOL AnsiFormat
  2096. )
  2097. /*++
  2098. Routine Description:
  2099. MemDbExportW exports a tree in a private binary format. The format is described above.
  2100. Arguments:
  2101. RootTree - Specifies the tree to be exported
  2102. FileName - Name of the binary format file to export to.
  2103. AnsiFormat - Keys should be written in ANSI rather than in Unicode.
  2104. Return Value:
  2105. TRUE is successfull, FALSE if not.
  2106. --*/
  2107. {
  2108. PCSTR aRootTree, aFileName;
  2109. BOOL result = TRUE;
  2110. if (!AnsiFormat) {
  2111. result = pMemDbExportWorkerW (RootTree, FileName);
  2112. } else {
  2113. aRootTree = ConvertWtoA (RootTree);
  2114. aFileName = ConvertWtoA (FileName);
  2115. result = pMemDbExportWorkerA (aRootTree, aFileName);
  2116. FreeConvertedStr (aFileName);
  2117. FreeConvertedStr (aRootTree);
  2118. }
  2119. return result;
  2120. }
  2121. BOOL
  2122. pMemDbImportWorkerA (
  2123. IN PBYTE FileBuffer
  2124. )
  2125. {
  2126. DWORD globalFlags;
  2127. WORD localFlags;
  2128. PCSTR rootTree;
  2129. CHAR lastKey [MEMDB_MAX];
  2130. PSTR lastKeyPtr;
  2131. CHAR node [MEMDB_MAX];
  2132. CHAR localKey [MEMDB_MAX];
  2133. DWORD flags = 0;
  2134. globalFlags = *((PDWORD) FileBuffer);
  2135. // FileBuffer will point to the tree that's imported
  2136. FileBuffer += sizeof (DWORD);
  2137. rootTree = (PCSTR) FileBuffer;
  2138. if (globalFlags & MEMDB_EXPORT_FLAGS_TEMP_KEY) {
  2139. // a temporary key was exported
  2140. MemDbCreateTemporaryKeyA ((PCSTR) FileBuffer);
  2141. }
  2142. // let's pass the string
  2143. FileBuffer = GetEndOfStringA ((PCSTR) FileBuffer) + sizeof (CHAR);
  2144. // ok from this point on we read and add all keys
  2145. lastKey [0] = 0;
  2146. localFlags = *((PWORD) FileBuffer);
  2147. while (localFlags) {
  2148. localKey [0] = 0;
  2149. StringCopyByteCountA (localKey, (PSTR)(FileBuffer + sizeof (WORD)), (localFlags & MEMDB_EXPORT_FLAGS_SIZE_MASK) - sizeof (WORD) + sizeof (CHAR));
  2150. MemDbBuildKeyA (node, rootTree, (localFlags & MEMDB_EXPORT_FLAGS_PREV_RELATIVE)?lastKey:NULL, localKey, NULL);
  2151. FileBuffer += (localFlags & MEMDB_EXPORT_FLAGS_SIZE_MASK);
  2152. MYASSERT (!((localFlags & MEMDB_EXPORT_FLAGS_BINARY_DATA) && (localFlags & MEMDB_EXPORT_FLAGS_FLAGS_PRESENT)));
  2153. if (localFlags & MEMDB_EXPORT_FLAGS_FLAGS_PRESENT) {
  2154. flags = *(PDWORD)FileBuffer;
  2155. FileBuffer += sizeof (DWORD);
  2156. }
  2157. if (localFlags & MEMDB_EXPORT_FLAGS_DATA_PRESENT) {
  2158. if (localFlags & MEMDB_EXPORT_FLAGS_BINARY_DATA) {
  2159. MemDbSetBinaryValueA (node, FileBuffer + sizeof (DWORD), *(PDWORD)FileBuffer);
  2160. FileBuffer += (*(PDWORD)FileBuffer + sizeof (DWORD));
  2161. } else {
  2162. MemDbSetValueAndFlagsA (node, *(PDWORD)FileBuffer, flags, 0);
  2163. FileBuffer += sizeof (DWORD);
  2164. }
  2165. } else {
  2166. MemDbSetValueA (node, 0);
  2167. }
  2168. if (localFlags & MEMDB_EXPORT_FLAGS_PREV_RELATIVE) {
  2169. StringCatA (lastKey, "\\");
  2170. StringCatA (lastKey, localKey);
  2171. lastKeyPtr = _mbsrchr (lastKey, '\\');
  2172. if (lastKeyPtr) {
  2173. *lastKeyPtr = 0;
  2174. } else {
  2175. lastKey [0] = 0;
  2176. }
  2177. } else {
  2178. StringCopyA (lastKey, localKey);
  2179. lastKeyPtr = _mbsrchr (lastKey, '\\');
  2180. if (lastKeyPtr) {
  2181. *lastKeyPtr = 0;
  2182. } else {
  2183. lastKey [0] = 0;
  2184. }
  2185. }
  2186. localFlags = *((PWORD) FileBuffer);
  2187. }
  2188. return TRUE;
  2189. }
  2190. BOOL
  2191. pMemDbImportWorkerW (
  2192. IN PBYTE FileBuffer
  2193. )
  2194. {
  2195. DWORD globalFlags;
  2196. WORD localFlags;
  2197. PCWSTR rootTree;
  2198. WCHAR lastKey [MEMDB_MAX];
  2199. PWSTR lastKeyPtr;
  2200. WCHAR node [MEMDB_MAX];
  2201. WCHAR localKey [MEMDB_MAX];
  2202. DWORD flags = 0;
  2203. globalFlags = *((PDWORD) FileBuffer);
  2204. // FileBuffer will point to the tree that's imported
  2205. FileBuffer += sizeof (DWORD);
  2206. rootTree = (PCWSTR) FileBuffer;
  2207. if (globalFlags & MEMDB_EXPORT_FLAGS_TEMP_KEY) {
  2208. // a temporary key was exported
  2209. MemDbCreateTemporaryKeyW ((PCWSTR) FileBuffer);
  2210. }
  2211. // let's pass the string
  2212. FileBuffer = (PBYTE)GetEndOfStringW ((PCWSTR) FileBuffer) + sizeof (WCHAR);
  2213. // ok from this point on we read and add all keys
  2214. lastKey [0] = 0;
  2215. localFlags = *((PWORD) FileBuffer);
  2216. while (localFlags) {
  2217. localKey [0] = 0;
  2218. StringCopyByteCountW (localKey, (PWSTR)(FileBuffer + sizeof (WORD)), (localFlags & MEMDB_EXPORT_FLAGS_SIZE_MASK) - sizeof (WORD) + sizeof (WCHAR));
  2219. MemDbBuildKeyW (node, rootTree, (localFlags & MEMDB_EXPORT_FLAGS_PREV_RELATIVE)?lastKey:NULL, localKey, NULL);
  2220. FileBuffer += (localFlags & MEMDB_EXPORT_FLAGS_SIZE_MASK);
  2221. MYASSERT (!((localFlags & MEMDB_EXPORT_FLAGS_BINARY_DATA) && (localFlags & MEMDB_EXPORT_FLAGS_FLAGS_PRESENT)));
  2222. if (localFlags & MEMDB_EXPORT_FLAGS_FLAGS_PRESENT) {
  2223. flags = *(PDWORD)FileBuffer;
  2224. FileBuffer += sizeof (DWORD);
  2225. }
  2226. if (localFlags & MEMDB_EXPORT_FLAGS_DATA_PRESENT) {
  2227. if (localFlags & MEMDB_EXPORT_FLAGS_BINARY_DATA) {
  2228. MemDbSetBinaryValueW (node, FileBuffer + sizeof (DWORD), *(PDWORD)FileBuffer);
  2229. FileBuffer += (*(PDWORD)FileBuffer + sizeof (DWORD));
  2230. } else {
  2231. MemDbSetValueAndFlagsW (node, *(PDWORD)FileBuffer, flags, 0);
  2232. FileBuffer += sizeof (DWORD);
  2233. }
  2234. } else {
  2235. MemDbSetValueW (node, 0);
  2236. }
  2237. if (localFlags & MEMDB_EXPORT_FLAGS_PREV_RELATIVE) {
  2238. StringCatW (lastKey, L"\\");
  2239. StringCatW (lastKey, localKey);
  2240. lastKeyPtr = wcsrchr (lastKey, L'\\');
  2241. if (lastKeyPtr) {
  2242. *lastKeyPtr = 0;
  2243. } else {
  2244. lastKey [0] = 0;
  2245. }
  2246. } else {
  2247. StringCopyW (lastKey, localKey);
  2248. lastKeyPtr = wcsrchr (lastKey, L'\\');
  2249. if (lastKeyPtr) {
  2250. *lastKeyPtr = 0;
  2251. } else {
  2252. lastKey [0] = 0;
  2253. }
  2254. }
  2255. localFlags = *((PWORD) FileBuffer);
  2256. }
  2257. return TRUE;
  2258. }
  2259. BOOL
  2260. MemDbImportA (
  2261. IN PCSTR FileName
  2262. )
  2263. /*++
  2264. Routine Description:
  2265. MemDbImportA imports a tree from a private binary format. The format is described above.
  2266. Arguments:
  2267. FileName - Name of the binary format file to import from.
  2268. Return Value:
  2269. TRUE is successfull, FALSE if not.
  2270. --*/
  2271. {
  2272. PBYTE fileBuff;
  2273. HANDLE fileHandle;
  2274. HANDLE mapHandle;
  2275. BOOL result = TRUE;
  2276. fileBuff = MapFileIntoMemoryA (FileName, &fileHandle, &mapHandle);
  2277. if (fileBuff == NULL) {
  2278. DEBUGMSGA ((DBG_ERROR, "Could not execute MemDbImport for %s", FileName));
  2279. return FALSE;
  2280. }
  2281. __try {
  2282. if (*((PDWORD) fileBuff) != MEMDB_EXPORT_SIGNATURE) {
  2283. DEBUGMSGA ((DBG_ERROR, "Unknown signature for file to import: %s", FileName));
  2284. result = FALSE;
  2285. } else {
  2286. fileBuff += sizeof (DWORD);
  2287. if (*((PDWORD) fileBuff) != MEMDB_EXPORT_VERSION) {
  2288. DEBUGMSGA ((DBG_ERROR, "Unknown version for file to import: %s", FileName));
  2289. result = FALSE;
  2290. } else {
  2291. fileBuff += sizeof (DWORD);
  2292. if (*((PDWORD) fileBuff) & MEMDB_EXPORT_FLAGS_ANSI) {
  2293. result = pMemDbImportWorkerA (fileBuff);
  2294. } else {
  2295. result = pMemDbImportWorkerW (fileBuff);
  2296. }
  2297. }
  2298. }
  2299. }
  2300. __except (1) {
  2301. DEBUGMSGA ((DBG_ERROR, "Access violation while importing: %s", FileName));
  2302. }
  2303. UnmapFile (fileBuff, mapHandle, fileHandle);
  2304. return result;
  2305. }
  2306. BOOL
  2307. MemDbImportW (
  2308. IN PCWSTR FileName
  2309. )
  2310. /*++
  2311. Routine Description:
  2312. MemDbImportW imports a tree from a private binary format. The format is described above.
  2313. Arguments:
  2314. FileName - Name of the binary format file to import from.
  2315. Return Value:
  2316. TRUE is successfull, FALSE if not.
  2317. --*/
  2318. {
  2319. PBYTE fileBuff;
  2320. HANDLE fileHandle;
  2321. HANDLE mapHandle;
  2322. BOOL result;
  2323. fileBuff = MapFileIntoMemoryW (FileName, &fileHandle, &mapHandle);
  2324. if (fileBuff == NULL) {
  2325. DEBUGMSGW ((DBG_ERROR, "Could not execute MemDbImport for %s", FileName));
  2326. return FALSE;
  2327. }
  2328. __try {
  2329. if (*((PDWORD) fileBuff) != MEMDB_EXPORT_SIGNATURE) {
  2330. DEBUGMSGW ((DBG_ERROR, "Unknown signature for file to import: %s", FileName));
  2331. result = FALSE;
  2332. } else {
  2333. fileBuff += sizeof (DWORD);
  2334. if (*((PDWORD) fileBuff) != MEMDB_EXPORT_VERSION) {
  2335. DEBUGMSGW ((DBG_ERROR, "Unknown version for file to import: %s", FileName));
  2336. result = FALSE;
  2337. } else {
  2338. fileBuff += sizeof (DWORD);
  2339. if (*((PDWORD) fileBuff) & MEMDB_EXPORT_FLAGS_ANSI) {
  2340. result = pMemDbImportWorkerA (fileBuff);
  2341. } else {
  2342. result = pMemDbImportWorkerW (fileBuff);
  2343. }
  2344. }
  2345. }
  2346. }
  2347. __except (1) {
  2348. DEBUGMSGW ((DBG_ERROR, "Access violation while importing: %s", FileName));
  2349. }
  2350. UnmapFile (fileBuff, mapHandle, fileHandle);
  2351. return result;
  2352. }
  2353. BOOL
  2354. MemDbQueryVersionA (
  2355. PCSTR FileName,
  2356. PMEMDB_VERSION Version
  2357. )
  2358. {
  2359. pPrivateMemDbLoad ((PCWSTR) FileName, FALSE, Version, TRUE);
  2360. return Version->Valid;
  2361. }
  2362. BOOL
  2363. MemDbQueryVersionW (
  2364. PCWSTR FileName,
  2365. PMEMDB_VERSION Version
  2366. )
  2367. {
  2368. pPrivateMemDbLoad (FileName, TRUE, Version, TRUE);
  2369. return Version->Valid;
  2370. }