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.

5628 lines
121 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. memdb.c
  5. Abstract:
  6. A memory-based database for managing all kinds of data relationships.
  7. Author:
  8. Jim Schmidt (jimschm) 8-Aug-1996
  9. Revision History:
  10. jimschm 05-Oct-1999 Documentation
  11. mvander 13-Aug-1999 many changes
  12. jimschm 23-Sep-1998 Expanded user flags to 24 bits (from 12 bits)
  13. calinn 12-Dec-1997 Extended MemDbMakePrintableKey and MemDbMakeNonPrintableKey
  14. jimschm 03-Dec-1997 Added multi-thread synchronization
  15. jimschm 22-Oct-1997 Split into multiple source files,
  16. added multiple memory block capability
  17. jimschm 16-Sep-1997 Hashing: delete fix
  18. jimschm 29-Jul-1997 Hashing, user flags added
  19. jimschm 07-Mar-1997 Signature changes
  20. jimschm 03-Mar-1997 PrivateBuildKeyFromOffset changes
  21. jimschm 18-Dec-1996 Fixed deltree bug
  22. --*/
  23. #include "pch.h"
  24. // PORTBUG: Make sure to pick up latest fixes in win9xupg project
  25. //
  26. // Includes
  27. //
  28. #include "memdbp.h"
  29. #include "bintree.h"
  30. //
  31. // Strings
  32. //
  33. // None
  34. //
  35. // Constants
  36. //
  37. // None
  38. //
  39. // Macros
  40. //
  41. // None
  42. //
  43. // Types
  44. //
  45. // None
  46. //
  47. // Globals
  48. //
  49. CRITICAL_SECTION g_MemDbCs;
  50. PMHANDLE g_MemDbPool = NULL;
  51. static INT g_Initialized;
  52. //
  53. // Macro expansion list
  54. //
  55. // None
  56. //
  57. // Macro expansion definition
  58. //
  59. // None
  60. //
  61. // Code
  62. //
  63. /*++
  64. Routine Description:
  65. MemDbInitializeEx creates data structures for an initial database. Calling
  66. this routine is required.
  67. Arguments:
  68. None.
  69. Return Value:
  70. TRUE if successful, FALSE otherwise.
  71. --*/
  72. BOOL
  73. MemDbInitializeExA (
  74. IN PCSTR DatabasePath OPTIONAL
  75. )
  76. {
  77. BOOL result = TRUE;
  78. MYASSERT (g_Initialized >= 0);
  79. g_Initialized++;
  80. if (g_Initialized == 1) {
  81. g_MemDbPool = PmCreateNamedPool ("MemDb");
  82. if (g_MemDbPool == NULL) {
  83. return FALSE;
  84. }
  85. __try {
  86. InitializeCriticalSection (&g_MemDbCs);
  87. } __except (EXCEPTION_CONTINUE_EXECUTION) {
  88. // Might raise an out of memory exception, but we don't check for that in this function.
  89. // Ignores
  90. }
  91. //
  92. // If we fail, we don't automatically call MemDbTerminate, because
  93. // there is an option to MemDbTerminate which we don't know.
  94. //
  95. if (!DatabasesInitializeA (DatabasePath)) {
  96. return FALSE;
  97. }
  98. result = FileEnumInitialize ();
  99. }
  100. return result;
  101. }
  102. BOOL
  103. MemDbInitializeExW (
  104. IN PCWSTR DatabasePath OPTIONAL
  105. )
  106. {
  107. BOOL result = TRUE;
  108. MYASSERT (g_Initialized >= 0);
  109. g_Initialized++;
  110. if (g_Initialized == 1) {
  111. g_MemDbPool = PmCreateNamedPool ("MemDb");
  112. if (g_MemDbPool == NULL) {
  113. return FALSE;
  114. }
  115. __try {
  116. InitializeCriticalSection (&g_MemDbCs);
  117. } __except (EXCEPTION_CONTINUE_EXECUTION) {
  118. // Might raise an out of memory exception, but we don't check for that in this function.
  119. // Ignores
  120. }
  121. //
  122. // If we fail, we don't automatically call MemDbTerminate, because
  123. // there is an option to MemDbTerminate which we don't know.
  124. //
  125. if (!DatabasesInitializeW (DatabasePath)) {
  126. return FALSE;
  127. }
  128. result = FileEnumInitialize ();
  129. }
  130. return result;
  131. }
  132. VOID
  133. MemDbTerminateEx (
  134. IN BOOL EraseDatabasePath
  135. )
  136. /*++
  137. Routine Description:
  138. MemDbTerminateEx frees all resources associated with MemDb
  139. and, optionally, removes the database directory.
  140. This routine should be called at process termination.
  141. Arguments:
  142. None.
  143. Return Value:
  144. None.
  145. --*/
  146. {
  147. MYASSERT (g_Initialized > 0);
  148. g_Initialized--;
  149. if (!g_Initialized) {
  150. if (g_MemDbPool) {
  151. PmDestroyPool (g_MemDbPool);
  152. g_MemDbPool = NULL;
  153. }
  154. DatabasesTerminate (EraseDatabasePath);
  155. DeleteCriticalSection (&g_MemDbCs);
  156. FileEnumTerminate ();
  157. } else if (g_Initialized < 0) {
  158. //
  159. // Since we call ourselves, protect callers from over-termination
  160. //
  161. g_Initialized = 0;
  162. }
  163. }
  164. PVOID
  165. MemDbGetMemory (
  166. IN UINT Size
  167. )
  168. {
  169. MYASSERT (g_MemDbPool);
  170. return PmGetMemory (g_MemDbPool, Size);
  171. }
  172. VOID
  173. MemDbReleaseMemory (
  174. IN PCVOID Memory
  175. )
  176. {
  177. if (Memory) {
  178. MYASSERT (g_MemDbPool);
  179. PmReleaseMemory (g_MemDbPool, Memory);
  180. }
  181. }
  182. KEYHANDLE
  183. MemDbAddKeyA (
  184. IN PCSTR KeyName
  185. )
  186. /*++
  187. Routine Description:
  188. MemDbAddKey creates a memdb key that has no values, flags or any
  189. other data. This is used to reduce the size of the database.
  190. Arguments:
  191. KeyName - Specifies the key to create.
  192. Return Value:
  193. Returns the HANDLE to the newly created key or NULL if
  194. not successful.
  195. --*/
  196. {
  197. PCWSTR keyNameW;
  198. KEYHANDLE result = 0;
  199. keyNameW = ConvertAtoW (KeyName);
  200. if (keyNameW) {
  201. result = MemDbAddKeyW (keyNameW);
  202. FreeConvertedStr (keyNameW);
  203. }
  204. return result;
  205. }
  206. KEYHANDLE
  207. MemDbAddKeyW (
  208. IN PCWSTR KeyName
  209. )
  210. /*++
  211. Routine Description:
  212. MemDbAddKey creates a memdb key that has no values, flags or any
  213. other data. This is used to reduce the size of the database.
  214. Arguments:
  215. KeyName - Specifies the key to create.
  216. Return Value:
  217. Returns the HANDLE to the newly created key or NULL if not successful.
  218. --*/
  219. {
  220. UINT keyIndex;
  221. PCWSTR subKey;
  222. KEYHANDLE result = 0;
  223. if (!g_Initialized) {
  224. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  225. return result;
  226. }
  227. MYASSERT (g_MemDbPool);
  228. EnterCriticalSection (&g_MemDbCs);
  229. __try {
  230. //
  231. // first make sure there is no key
  232. // with this name.
  233. //
  234. subKey = SelectHiveW (KeyName);
  235. if (!subKey) {
  236. __leave;
  237. }
  238. keyIndex = FindKey (subKey);
  239. if (keyIndex != INVALID_OFFSET) {
  240. SetLastError (ERROR_ALREADY_EXISTS);
  241. __leave;
  242. }
  243. keyIndex = NewEmptyKey (subKey);
  244. if (keyIndex != INVALID_OFFSET) {
  245. result = GET_EXTERNAL_INDEX (keyIndex);
  246. SetLastError (ERROR_SUCCESS);
  247. }
  248. }
  249. __finally {
  250. #ifdef DEBUG
  251. if (g_DatabaseCheckLevel) {
  252. CheckDatabase (g_DatabaseCheckLevel);
  253. }
  254. #endif
  255. LeaveCriticalSection (&g_MemDbCs);
  256. }
  257. return result;
  258. }
  259. KEYHANDLE
  260. MemDbSetKeyA (
  261. IN PCSTR KeyName
  262. )
  263. /*++
  264. Routine Description:
  265. MemDbSetKey creates a memdb key that has no values, flags or any other data.
  266. This is used to reduce the size of the database. If the key exists it will
  267. return the handle of the existing key.
  268. Arguments:
  269. KeyName - Specifies the key to create.
  270. Return Value:
  271. Returns the HANDLE to the newly created or existent key or NULL if some error
  272. occurs.
  273. --*/
  274. {
  275. PCWSTR keyNameW;
  276. KEYHANDLE result = 0;
  277. keyNameW = ConvertAtoW (KeyName);
  278. if (keyNameW) {
  279. result = MemDbSetKeyW (keyNameW);
  280. FreeConvertedStr (keyNameW);
  281. }
  282. return result;
  283. }
  284. KEYHANDLE
  285. MemDbSetKeyW (
  286. IN PCWSTR KeyName
  287. )
  288. /*++
  289. Routine Description:
  290. MemDbSetKey creates a memdb key that has no values, flags or any other data.
  291. This is used to reduce the size of the database. If the key exists it will
  292. return the handle of the existing key.
  293. Arguments:
  294. KeyName - Specifies the key to create.
  295. Return Value:
  296. Returns the HANDLE to the newly created or existent key or NULL if some error
  297. occurs.
  298. --*/
  299. {
  300. UINT keyIndex;
  301. PCWSTR subKey;
  302. KEYHANDLE result = 0;
  303. if (!g_Initialized) {
  304. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  305. return result;
  306. }
  307. MYASSERT (g_MemDbPool);
  308. EnterCriticalSection (&g_MemDbCs);
  309. __try {
  310. //
  311. // first make sure there is no key
  312. // with this name.
  313. //
  314. subKey = SelectHiveW (KeyName);
  315. if (!subKey) {
  316. __leave;
  317. }
  318. keyIndex = FindKey (subKey);
  319. if (keyIndex != INVALID_OFFSET) {
  320. SetLastError (ERROR_ALREADY_EXISTS);
  321. result = GET_EXTERNAL_INDEX (keyIndex);;
  322. __leave;
  323. }
  324. keyIndex = NewEmptyKey (subKey);
  325. if (keyIndex != INVALID_OFFSET) {
  326. result = GET_EXTERNAL_INDEX (keyIndex);;
  327. SetLastError (ERROR_SUCCESS);
  328. }
  329. }
  330. __finally {
  331. #ifdef DEBUG
  332. if (g_DatabaseCheckLevel) {
  333. CheckDatabase (g_DatabaseCheckLevel);
  334. }
  335. #endif
  336. LeaveCriticalSection (&g_MemDbCs);
  337. }
  338. return result;
  339. }
  340. BOOL
  341. MemDbDeleteKeyA (
  342. IN PCSTR KeyStr
  343. )
  344. /*++
  345. Routine Description:
  346. MemDbDeleteKey deletes a specific string from the database (along with all
  347. data associated with it)
  348. Arguments:
  349. KeyStr - Specifies the key string to delete (i.e., foo\bar\cat)
  350. Return Value:
  351. TRUE if successful, FALSE otherwise
  352. --*/
  353. {
  354. PCWSTR p;
  355. BOOL result = FALSE;
  356. p = ConvertAtoW (KeyStr);
  357. if (p) {
  358. result = MemDbDeleteKeyW (p);
  359. FreeConvertedStr (p);
  360. }
  361. return result;
  362. }
  363. BOOL
  364. MemDbDeleteKeyW (
  365. IN PCWSTR KeyStr
  366. )
  367. /*++
  368. Routine Description:
  369. MemDbDeleteKey deletes a specific string from the database (along with all
  370. data associated with it)
  371. Arguments:
  372. KeyStr - Specifies the key string to delete (i.e., foo\bar\cat)
  373. Return Value:
  374. TRUE if successful, FALSE otherwise
  375. --*/
  376. {
  377. PCWSTR subKey;
  378. BOOL result = FALSE;
  379. if (!g_Initialized) {
  380. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  381. return result;
  382. }
  383. MYASSERT (g_MemDbPool);
  384. EnterCriticalSection (&g_MemDbCs);
  385. subKey = SelectHiveW (KeyStr);
  386. if (subKey) {
  387. result = DeleteKey (subKey, g_CurrentDatabase->FirstLevelTree, TRUE);
  388. #ifdef DEBUG
  389. if (g_DatabaseCheckLevel) {
  390. CheckDatabase (g_DatabaseCheckLevel);
  391. }
  392. #endif
  393. }
  394. LeaveCriticalSection (&g_MemDbCs);
  395. return result;
  396. }
  397. BOOL
  398. MemDbDeleteKeyByHandle (
  399. IN KEYHANDLE KeyHandle
  400. )
  401. /*++
  402. Routine Description:
  403. MemDbDeleteKeyByHandle deletes a specific key from the database
  404. identified by the key handle. It also removes all data associated
  405. with it.
  406. Arguments:
  407. KeyHandle - Key Handle identifying the key
  408. Return Value:
  409. TRUE if successful, FALSE otherwise
  410. --*/
  411. {
  412. BYTE dbIndex;
  413. BOOL result = FALSE;
  414. if (!g_Initialized) {
  415. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  416. return result;
  417. }
  418. MYASSERT (g_MemDbPool);
  419. if (!KeyHandle) {
  420. return FALSE;
  421. }
  422. EnterCriticalSection (&g_MemDbCs);
  423. dbIndex = GET_DATABASE (KeyHandle);
  424. if (SelectDatabase (dbIndex)) {
  425. result = PrivateDeleteKeyByIndex (GET_INDEX (KeyHandle));
  426. #ifdef DEBUG
  427. if (g_DatabaseCheckLevel) {
  428. CheckDatabase (g_DatabaseCheckLevel);
  429. }
  430. #endif
  431. }
  432. LeaveCriticalSection (&g_MemDbCs);
  433. return result;
  434. }
  435. BOOL
  436. MemDbDeleteTreeA (
  437. IN PCSTR KeyName
  438. )
  439. /*++
  440. Routine Description:
  441. MemDbDeleteTree removes an entire tree branch from the database, including
  442. all data associated. The specified key string does not need to be
  443. an endpoint (i.e., specifying foo\bar will cause deletion of foo\bar\cat).
  444. Arguments:
  445. KeyName - Specifies the key string to delete. This string cannot be empty.
  446. Return Value:
  447. TRUE if successful, FALSE otherwise
  448. --*/
  449. {
  450. PCWSTR p;
  451. BOOL result = FALSE;
  452. p = ConvertAtoW (KeyName);
  453. if (p) {
  454. result = MemDbDeleteTreeW (p);
  455. FreeConvertedStr (p);
  456. }
  457. return result;
  458. }
  459. BOOL
  460. MemDbDeleteTreeW (
  461. IN PCWSTR KeyName
  462. )
  463. /*++
  464. Routine Description:
  465. MemDbDeleteTree removes an entire tree branch from the database, including
  466. all data associated. The specified key string does not need to be
  467. an endpoint (i.e., specifying foo\bar will cause deletion of foo\bar\cat).
  468. Arguments:
  469. KeyName - Specifies the key string to delete. This string cannot be empty.
  470. Return Value:
  471. TRUE if successful, FALSE otherwise
  472. --*/
  473. {
  474. PCWSTR subKey;
  475. BOOL result = FALSE;
  476. if (!g_Initialized) {
  477. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  478. return result;
  479. }
  480. MYASSERT (g_MemDbPool);
  481. EnterCriticalSection (&g_MemDbCs);
  482. subKey = SelectHiveW (KeyName);
  483. if (subKey) {
  484. result = DeleteKey (subKey, g_CurrentDatabase->FirstLevelTree, FALSE);
  485. #ifdef DEBUG
  486. if (g_DatabaseCheckLevel) {
  487. CheckDatabase (g_DatabaseCheckLevel);
  488. }
  489. #endif
  490. }
  491. LeaveCriticalSection (&g_MemDbCs);
  492. return result;
  493. }
  494. PCSTR
  495. MemDbGetKeyFromHandleA (
  496. IN KEYHANDLE KeyHandle,
  497. IN UINT StartLevel
  498. )
  499. /*++
  500. Routine Description:
  501. MemDbGetKeyFromHandle will create a key string given the key handle.
  502. It will allocate memory from memdb's private pool to store the result.
  503. Caller is responsible for calling MemDbReleaseMemory on the result.
  504. This function also allow trimming from the beginning of the string.
  505. By specifying a start level, the function will skip a number of
  506. levels before building the string. For example, if a key handle points
  507. to the string mycat\foo\bar, and StartLevel is 1, the function will
  508. return foo\bar.
  509. Arguments:
  510. KeyHandle - Specifies the key handle that identifies the key.
  511. StartLevel - Specifies a zero-based starting level, where zero represents
  512. the complete string, one represents the string starting after
  513. the first backslash, and so on.
  514. Return Value:
  515. A valid string (using memory allocated from memdb's private pool) if
  516. successful, NULL otherwise.
  517. --*/
  518. {
  519. PSTR result = NULL;
  520. WCHAR wideBuffer[MEMDB_MAX];
  521. PWSTR bufferIndex = wideBuffer;
  522. BYTE dbIndex;
  523. UINT chars;
  524. PKEYSTRUCT keyStruct;
  525. PSTR p;
  526. if (!g_Initialized) {
  527. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  528. return result;
  529. }
  530. MYASSERT (g_MemDbPool);
  531. if (!KeyHandle) {
  532. return NULL;
  533. }
  534. EnterCriticalSection (&g_MemDbCs);
  535. __try {
  536. dbIndex = GET_DATABASE (KeyHandle);
  537. if (!SelectDatabase (dbIndex)) {
  538. __leave;
  539. }
  540. if (StartLevel == MEMDB_LAST_LEVEL) {
  541. //
  542. // Special case -- get the last level string
  543. //
  544. keyStruct = GetKeyStruct (GET_INDEX (KeyHandle));
  545. if (!keyStruct) {
  546. __leave;
  547. }
  548. result = MemDbGetMemory (keyStruct->KeyName[0] * 2 + 1);
  549. p = DirectUnicodeToDbcsN (
  550. result,
  551. keyStruct->KeyName + 1,
  552. keyStruct->KeyName[0] * sizeof (WCHAR)
  553. );
  554. *p = 0;
  555. __leave;
  556. }
  557. switch (dbIndex) {
  558. case DB_PERMANENT:
  559. break;
  560. case DB_TEMPORARY:
  561. if (StartLevel == 0) {
  562. bufferIndex [0] = L'~';
  563. bufferIndex++;
  564. } else {
  565. StartLevel --;
  566. }
  567. break;
  568. default:
  569. __leave;
  570. }
  571. if (PrivateBuildKeyFromIndex (
  572. StartLevel,
  573. GET_INDEX (KeyHandle),
  574. bufferIndex,
  575. NULL,
  576. NULL,
  577. &chars
  578. )) {
  579. result = MemDbGetMemory (chars*2+1);
  580. KnownSizeWtoA (result, wideBuffer);
  581. __leave;
  582. }
  583. }
  584. __finally {
  585. LeaveCriticalSection (&g_MemDbCs);
  586. }
  587. return result;
  588. }
  589. PCWSTR
  590. MemDbGetKeyFromHandleW (
  591. IN KEYHANDLE KeyHandle,
  592. IN UINT StartLevel
  593. )
  594. /*++
  595. Routine Description:
  596. MemDbGetKeyFromHandle will create a key string given the key handle.
  597. It will allocate memory from memdb's private pool to store the result.
  598. Caller is responsible for calling MemDbReleaseMemory on the result.
  599. This function also allow trimming from the beginning of the string.
  600. By specifying a start level, the function will skip a number of
  601. levels before building the string. For example, if a key handle points
  602. to the string mycat\foo\bar, and StartLevel is 1, the function will
  603. return foo\bar.
  604. Arguments:
  605. KeyHandle - Specifies the key handle that identifies the key.
  606. StartLevel - Specifies a zero-based starting level, where zero represents
  607. the complete string, one represents the string starting after
  608. the first backslash, and so on.
  609. Return Value:
  610. A valid string (using memory allocated from memdb's private pool) if
  611. successful, NULL otherwise.
  612. --*/
  613. {
  614. PWSTR result = NULL;
  615. WCHAR wideBuffer[MEMDB_MAX];
  616. PWSTR bufferIndex = wideBuffer;
  617. BYTE dbIndex;
  618. UINT chars;
  619. PKEYSTRUCT keyStruct;
  620. if (!g_Initialized) {
  621. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  622. return result;
  623. }
  624. MYASSERT (g_MemDbPool);
  625. if (!KeyHandle) {
  626. return NULL;
  627. }
  628. EnterCriticalSection (&g_MemDbCs);
  629. __try {
  630. dbIndex = GET_DATABASE (KeyHandle);
  631. if (!SelectDatabase (dbIndex)) {
  632. __leave;
  633. }
  634. if (StartLevel == MEMDB_LAST_LEVEL) {
  635. //
  636. // Special case -- get the last level string
  637. //
  638. keyStruct = GetKeyStruct (GET_INDEX (KeyHandle));
  639. if (!keyStruct) {
  640. __leave;
  641. }
  642. chars = keyStruct->KeyName[0];
  643. result = MemDbGetMemory ((chars + 1) * sizeof (WCHAR));
  644. CopyMemory (result, keyStruct->KeyName + 1, chars * sizeof (WCHAR));
  645. result[chars] = 0;
  646. __leave;
  647. }
  648. switch (dbIndex) {
  649. case DB_PERMANENT:
  650. break;
  651. case DB_TEMPORARY:
  652. if (StartLevel == 0) {
  653. bufferIndex [0] = L'~';
  654. bufferIndex++;
  655. } else {
  656. StartLevel --;
  657. }
  658. break;
  659. default:
  660. __leave;
  661. }
  662. if (PrivateBuildKeyFromIndex (
  663. StartLevel,
  664. GET_INDEX (KeyHandle),
  665. bufferIndex,
  666. NULL,
  667. NULL,
  668. &chars
  669. )) {
  670. if (chars) {
  671. result = MemDbGetMemory ((chars + 1) * sizeof (WCHAR));
  672. StringCopyW (result, wideBuffer);
  673. __leave;
  674. }
  675. }
  676. }
  677. __finally {
  678. LeaveCriticalSection (&g_MemDbCs);
  679. }
  680. return result;
  681. }
  682. BOOL
  683. MemDbGetKeyFromHandleExA (
  684. IN KEYHANDLE KeyHandle,
  685. IN UINT StartLevel,
  686. IN OUT PGROWBUFFER Buffer OPTIONAL
  687. )
  688. /*++
  689. Routine Description:
  690. MemDbGetKeyFromHandleEx will create a key string given the key handle.
  691. It will use caller's grow buffer to store the result.
  692. This function also allow trimming from the beginning of the string.
  693. By specifying a start level, the function will skip a number of
  694. levels before building the string. For example, if a key handle points
  695. to the string mycat\foo\bar, and StartLevel is 1, the function will
  696. return foo\bar.
  697. Arguments:
  698. KeyHandle - Specifies the key handle that identifies the key.
  699. StartLevel - Specifies a zero-based starting level, where zero represents
  700. the complete string, one represents the string starting after
  701. the first backslash, and so on.
  702. Buffer - Specifies an intialized grow buffer that may contain data.
  703. Receives the key string, appended to data in the buffer (if
  704. any)
  705. Return Value:
  706. TRUE if successful, FALSE otherwise.
  707. --*/
  708. {
  709. WCHAR wideBuffer[MEMDB_MAX];
  710. CHAR ansiBuffer[MEMDB_MAX*2];
  711. PWSTR bufferIndex = wideBuffer;
  712. BYTE dbIndex;
  713. UINT chars;
  714. BOOL result = FALSE;
  715. if (!g_Initialized) {
  716. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  717. return result;
  718. }
  719. MYASSERT (g_MemDbPool);
  720. if (!KeyHandle) {
  721. return FALSE;
  722. }
  723. EnterCriticalSection (&g_MemDbCs);
  724. __try {
  725. dbIndex = GET_DATABASE (KeyHandle);
  726. if (!SelectDatabase (dbIndex)) {
  727. __leave;
  728. }
  729. switch (dbIndex) {
  730. case DB_PERMANENT:
  731. break;
  732. case DB_TEMPORARY:
  733. if (StartLevel == 0) {
  734. bufferIndex [0] = L'~';
  735. bufferIndex++;
  736. } else {
  737. StartLevel --;
  738. }
  739. break;
  740. default:
  741. __leave;
  742. }
  743. if (PrivateBuildKeyFromIndex (
  744. StartLevel,
  745. GET_INDEX (KeyHandle),
  746. bufferIndex,
  747. NULL,
  748. NULL,
  749. &chars
  750. )) {
  751. if (chars) {
  752. KnownSizeWtoA (ansiBuffer, wideBuffer);
  753. if (Buffer) {
  754. (void)GbCopyStringA (Buffer, ansiBuffer);
  755. }
  756. result = TRUE;
  757. __leave;
  758. }
  759. }
  760. }
  761. __finally {
  762. LeaveCriticalSection (&g_MemDbCs);
  763. }
  764. return result;
  765. }
  766. BOOL
  767. MemDbGetKeyFromHandleExW (
  768. IN KEYHANDLE KeyHandle,
  769. IN UINT StartLevel,
  770. IN PGROWBUFFER Buffer OPTIONAL
  771. )
  772. /*++
  773. Routine Description:
  774. MemDbGetKeyFromHandleEx will create a key string given the key handle.
  775. It will use caller's grow buffer to store the result.
  776. This function also allow trimming from the beginning of the string.
  777. By specifying a start level, the function will skip a number of
  778. levels before building the string. For example, if a key handle points
  779. to the string mycat\foo\bar, and StartLevel is 1, the function will
  780. return foo\bar.
  781. Arguments:
  782. KeyHandle - Specifies the key handle that identifies the key.
  783. StartLevel - Specifies a zero-based starting level, where zero represents
  784. the complete string, one represents the string starting after
  785. the first backslash, and so on.
  786. Buffer - Specifies an intialized grow buffer that may contain data.
  787. Receives the key string, appended to data in the buffer (if
  788. any)
  789. Return Value:
  790. TRUE if successful, FALSE otherwise.
  791. --*/
  792. {
  793. WCHAR wideBuffer[MEMDB_MAX];
  794. PWSTR bufferIndex = wideBuffer;
  795. BYTE dbIndex;
  796. UINT chars;
  797. BOOL result = FALSE;
  798. if (!g_Initialized) {
  799. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  800. return result;
  801. }
  802. MYASSERT (g_MemDbPool);
  803. if (!KeyHandle) {
  804. return FALSE;
  805. }
  806. EnterCriticalSection (&g_MemDbCs);
  807. __try {
  808. dbIndex = GET_DATABASE (KeyHandle);
  809. if (!SelectDatabase (dbIndex)) {
  810. __leave;
  811. }
  812. switch (dbIndex) {
  813. case DB_PERMANENT:
  814. break;
  815. case DB_TEMPORARY:
  816. if (StartLevel == 0) {
  817. bufferIndex [0] = L'~';
  818. bufferIndex++;
  819. } else {
  820. StartLevel --;
  821. }
  822. break;
  823. default:
  824. __leave;
  825. }
  826. if (PrivateBuildKeyFromIndex (
  827. StartLevel,
  828. GET_INDEX (KeyHandle),
  829. bufferIndex,
  830. NULL,
  831. NULL,
  832. &chars
  833. )) {
  834. if (chars) {
  835. if (Buffer) {
  836. (void)GbCopyStringW (Buffer, wideBuffer);
  837. }
  838. result = TRUE;
  839. __leave;
  840. }
  841. }
  842. }
  843. __finally {
  844. LeaveCriticalSection (&g_MemDbCs);
  845. }
  846. return result;
  847. }
  848. KEYHANDLE
  849. MemDbGetHandleFromKeyA (
  850. IN PCSTR KeyName
  851. )
  852. /*++
  853. Routine Description:
  854. MemDbGetHandleFromKey will return the key handle associated with KeyName,
  855. if it's already added in memdb.
  856. Arguments:
  857. KeyName - Specifies the key to search.
  858. Return Value:
  859. Returns the key handle of the requested key or NULL if the key is not present.
  860. --*/
  861. {
  862. PCWSTR keyNameW;
  863. KEYHANDLE result = 0;
  864. keyNameW = ConvertAtoW (KeyName);
  865. if (keyNameW) {
  866. result = MemDbGetHandleFromKeyW (keyNameW);
  867. FreeConvertedStr (keyNameW);
  868. }
  869. return result;
  870. }
  871. KEYHANDLE
  872. MemDbGetHandleFromKeyW (
  873. IN PCWSTR KeyName
  874. )
  875. /*++
  876. Routine Description:
  877. MemDbGetHandleFromKey will return the key handle associated with KeyName,
  878. if it's already added in memdb.
  879. Arguments:
  880. KeyName - Specifies the key to search.
  881. Return Value:
  882. Returns the key handle of the requested key or NULL if the key is not present.
  883. --*/
  884. {
  885. UINT keyIndex;
  886. PCWSTR subKey;
  887. KEYHANDLE result = 0;
  888. if (!g_Initialized) {
  889. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  890. return result;
  891. }
  892. MYASSERT (g_MemDbPool);
  893. EnterCriticalSection (&g_MemDbCs);
  894. __try {
  895. //
  896. // first make sure there is a key
  897. // with this name.
  898. //
  899. subKey = SelectHiveW (KeyName);
  900. if (!subKey) {
  901. __leave;
  902. }
  903. keyIndex = FindKey (subKey);
  904. if (keyIndex == INVALID_OFFSET) {
  905. __leave;
  906. }
  907. result = GET_EXTERNAL_INDEX (keyIndex);
  908. }
  909. __finally {
  910. LeaveCriticalSection (&g_MemDbCs);
  911. }
  912. return result;
  913. }
  914. KEYHANDLE
  915. MemDbSetValueAndFlagsExA (
  916. IN PCSTR KeyName,
  917. IN BOOL AlterValue,
  918. IN UINT Value,
  919. IN BOOL ReplaceFlags,
  920. IN UINT SetFlags,
  921. IN UINT ClearFlags
  922. )
  923. /*++
  924. Routine Description:
  925. MemDbSetValueAndFlagsEx creates the key if it doesn't exist and then
  926. it sets it's value and it's flags based on the arguments.
  927. Arguments:
  928. KeyName - Specifies the key string (i.e., foo\bar\cat)
  929. AlterValue - Specifies if the existing value is to be altered
  930. Value - Specifies the 32-bit value associated with KeyName (only needed if AlterValue is TRUE)
  931. ReplaceFlags - Specifies if the existing flags are to be replaced. If TRUE then we only
  932. consider SetFlags as the replacing flags, ClearFlags will be ignored
  933. SetFlags - Specifies the bit flags that need to be set (if ReplaceFlags is FALSE) or the
  934. replacement flags (if ReplaceFlags is TRUE).
  935. ClearFlags - Specifies the bit flags that should be cleared (ignored if ReplaceFlags is TRUE).
  936. Return Value:
  937. the key handle for the existent or newly added key if successful, NULL
  938. otherwise.
  939. --*/
  940. {
  941. PCWSTR keyNameW;
  942. KEYHANDLE result = 0;
  943. keyNameW = ConvertAtoW (KeyName);
  944. if (keyNameW) {
  945. result = MemDbSetValueAndFlagsExW (
  946. keyNameW,
  947. AlterValue,
  948. Value,
  949. ReplaceFlags,
  950. SetFlags,
  951. ClearFlags
  952. );
  953. FreeConvertedStr (keyNameW);
  954. }
  955. return result;
  956. }
  957. KEYHANDLE
  958. MemDbSetValueAndFlagsExW (
  959. IN PCWSTR KeyName,
  960. IN BOOL AlterValue,
  961. IN UINT Value,
  962. IN BOOL ReplaceFlags,
  963. IN UINT SetFlags,
  964. IN UINT ClearFlags
  965. )
  966. /*++
  967. Routine Description:
  968. MemDbSetValueAndFlagsEx creates the key if it doesn't exist and then
  969. it sets it's value and it's flags based on the arguments.
  970. Arguments:
  971. KeyName - Specifies the key string (i.e., foo\bar\cat)
  972. AlterValue - Specifies if the existing value is to be altered
  973. Value - Specifies the 32-bit value associated with KeyName (only needed if AlterValue is TRUE)
  974. ReplaceFlags - Specifies if the existing flags are to be replaced. If TRUE then we only
  975. consider SetFlags as the replacing flags, ClearFlags will be ignored
  976. SetFlags - Specifies the bit flags that need to be set (if ReplaceFlags is FALSE) or the
  977. replacement flags (if ReplaceFlags is TRUE).
  978. ClearFlags - Specifies the bit flags that should be cleared (ignored if ReplaceFlags is TRUE).
  979. Return Value:
  980. the key handle for the existent or newly added key if successful, NULL
  981. otherwise.
  982. --*/
  983. {
  984. PCWSTR subKey;
  985. KEYHANDLE result = 0;
  986. UINT keyIndex;
  987. if (!g_Initialized) {
  988. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  989. return result;
  990. }
  991. MYASSERT (g_MemDbPool);
  992. EnterCriticalSection (&g_MemDbCs);
  993. __try {
  994. subKey = SelectHiveW (KeyName);
  995. if (!subKey) {
  996. __leave;
  997. }
  998. keyIndex = FindKey (subKey);
  999. if (keyIndex == INVALID_OFFSET) {
  1000. keyIndex = NewKey (subKey);
  1001. if (keyIndex == INVALID_OFFSET) {
  1002. __leave;
  1003. }
  1004. }
  1005. if (AlterValue) {
  1006. if (!KeyStructSetValue (keyIndex, Value)) {
  1007. __leave;
  1008. }
  1009. }
  1010. if ((ReplaceFlags && SetFlags) ||
  1011. (!ReplaceFlags && (SetFlags || ClearFlags))
  1012. ) {
  1013. if (!KeyStructSetFlags (keyIndex, ReplaceFlags, SetFlags, ClearFlags)) {
  1014. __leave;
  1015. }
  1016. }
  1017. MYASSERT (keyIndex != INVALID_OFFSET);
  1018. result = GET_EXTERNAL_INDEX (keyIndex);
  1019. }
  1020. __finally {
  1021. #ifdef DEBUG
  1022. if (g_DatabaseCheckLevel) {
  1023. CheckDatabase (g_DatabaseCheckLevel);
  1024. }
  1025. #endif
  1026. LeaveCriticalSection (&g_MemDbCs);
  1027. }
  1028. return result;
  1029. }
  1030. BOOL
  1031. MemDbSetValueAndFlagsByHandleEx (
  1032. IN KEYHANDLE KeyHandle,
  1033. IN BOOL AlterValue,
  1034. IN UINT Value,
  1035. IN BOOL ReplaceFlags,
  1036. IN UINT SetFlags,
  1037. IN UINT ClearFlags
  1038. )
  1039. /*++
  1040. Routine Description:
  1041. MemDbSetValueAndFlagsEx modifies value and/or flags for an existing key
  1042. identified by KeyHandle.
  1043. Arguments:
  1044. KeyHandle - Identifies an existing key
  1045. AlterValue - Specifies if the existing value is to be altered
  1046. Value - Specifies the 32-bit value associated with KeyName (only needed if AlterValue is TRUE)
  1047. ReplaceFlags - Specifies if the existing flags are to be replaced. If TRUE then we only
  1048. consider SetFlags as the replacing flags, ClearFlags will be ignored
  1049. SetFlags - Specifies the bit flags that need to be set (if ReplaceFlags is FALSE) or the
  1050. replacement flags (if ReplaceFlags is TRUE).
  1051. ClearFlags - Specifies the bit flags that should be cleared (ignored if ReplaceFlags is TRUE).
  1052. Return Value:
  1053. the key handle for the existent or newly added key if successful, NULL
  1054. otherwise.
  1055. --*/
  1056. {
  1057. BYTE dbIndex;
  1058. BOOL result = FALSE;
  1059. if (!g_Initialized) {
  1060. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  1061. return result;
  1062. }
  1063. MYASSERT (g_MemDbPool);
  1064. if (!KeyHandle) {
  1065. return FALSE;
  1066. }
  1067. EnterCriticalSection (&g_MemDbCs);
  1068. __try {
  1069. dbIndex = GET_DATABASE (KeyHandle);
  1070. if (!SelectDatabase (dbIndex)) {
  1071. __leave;
  1072. }
  1073. if (AlterValue) {
  1074. if (!KeyStructSetValue (GET_INDEX (KeyHandle), Value)) {
  1075. __leave;
  1076. }
  1077. }
  1078. if ((ReplaceFlags && SetFlags) ||
  1079. (!ReplaceFlags && (SetFlags || ClearFlags))
  1080. ) {
  1081. if (!KeyStructSetFlags (GET_INDEX (KeyHandle), ReplaceFlags, SetFlags, ClearFlags)) {
  1082. __leave;
  1083. }
  1084. }
  1085. result = TRUE;
  1086. }
  1087. __finally {
  1088. #ifdef DEBUG
  1089. if (g_DatabaseCheckLevel) {
  1090. CheckDatabase (g_DatabaseCheckLevel);
  1091. }
  1092. #endif
  1093. LeaveCriticalSection (&g_MemDbCs);
  1094. }
  1095. return result;
  1096. }
  1097. BOOL
  1098. MemDbGetValueAndFlagsA (
  1099. IN PCSTR KeyName,
  1100. OUT PUINT Value, OPTIONAL
  1101. OUT PUINT Flags OPTIONAL
  1102. )
  1103. /*++
  1104. Routine Description:
  1105. MemDbGetValueAndFlagsA is the external entry point for querying the database
  1106. for a value and flags.
  1107. Arguments:
  1108. KeyName - Specifies the key to query (i.e., foo\bar\cat)
  1109. Value - Recieves the value associated with Key, if Key exists.
  1110. Flags - Receives the flags associated with Key, if Key exists.
  1111. Return Value:
  1112. TRUE if Key exists in the database, FALSE otherwise.
  1113. --*/
  1114. {
  1115. PCWSTR p;
  1116. BOOL result = FALSE;
  1117. p = ConvertAtoW (KeyName);
  1118. if (p) {
  1119. result = MemDbGetValueAndFlagsW (p, Value, Flags);
  1120. FreeConvertedStr (p);
  1121. }
  1122. return result;
  1123. }
  1124. BOOL
  1125. MemDbGetValueAndFlagsW (
  1126. IN PCWSTR KeyName,
  1127. OUT PUINT Value, OPTIONAL
  1128. OUT PUINT Flags OPTIONAL
  1129. )
  1130. /*++
  1131. Routine Description:
  1132. MemDbGetValueAndFlagsW is the external entry point for querying the database
  1133. for a value and flags.
  1134. Arguments:
  1135. KeyName - Specifies the key to query (i.e., foo\bar\cat)
  1136. Value - Recieves the value associated with Key, if Key exists.
  1137. Flags - Receives the flags associated with Key, if Key exists.
  1138. Return Value:
  1139. TRUE if Key exists in the database, FALSE otherwise.
  1140. --*/
  1141. {
  1142. UINT keyIndex;
  1143. PCWSTR subKey;
  1144. BOOL result = FALSE;
  1145. if (!g_Initialized) {
  1146. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  1147. return result;
  1148. }
  1149. MYASSERT (g_MemDbPool);
  1150. EnterCriticalSection (&g_MemDbCs);
  1151. __try {
  1152. subKey = SelectHiveW (KeyName);
  1153. if (!subKey) {
  1154. __leave;
  1155. }
  1156. keyIndex = FindKey (subKey);
  1157. if (keyIndex == INVALID_OFFSET) {
  1158. __leave;
  1159. }
  1160. result = TRUE;
  1161. result = result && KeyStructGetValue (GetKeyStruct (keyIndex), Value);
  1162. result = result && KeyStructGetFlags (GetKeyStruct (keyIndex), Flags);
  1163. }
  1164. __finally {
  1165. LeaveCriticalSection (&g_MemDbCs);
  1166. }
  1167. return result;
  1168. }
  1169. BOOL
  1170. MemDbGetValueAndFlagsByHandle (
  1171. IN KEYHANDLE KeyHandle,
  1172. OUT PUINT Value, OPTIONAL
  1173. OUT PUINT Flags OPTIONAL
  1174. )
  1175. /*++
  1176. Routine Description:
  1177. MemDbGetValueAndFlagsByHandle is the external entry point for querying the database
  1178. for a value and flags based on a key handle.
  1179. Arguments:
  1180. KeyHandle - Specifies the key handle to query
  1181. Value - Recieves the value associated with Key, if KeyHandle exists.
  1182. Flags - Receives the flags associated with Key, if KeyHandle exists.
  1183. Return Value:
  1184. TRUE if KeyHandle exists in the database, FALSE otherwise.
  1185. --*/
  1186. {
  1187. BYTE dbIndex;
  1188. PKEYSTRUCT keyStruct;
  1189. BOOL result = FALSE;
  1190. if (!g_Initialized) {
  1191. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  1192. return result;
  1193. }
  1194. MYASSERT (g_MemDbPool);
  1195. if (!KeyHandle) {
  1196. return FALSE;
  1197. }
  1198. EnterCriticalSection (&g_MemDbCs);
  1199. __try {
  1200. dbIndex = GET_DATABASE (KeyHandle);
  1201. if (!SelectDatabase (dbIndex)) {
  1202. __leave;
  1203. }
  1204. keyStruct = GetKeyStruct (GET_INDEX (KeyHandle));
  1205. if (!keyStruct) {
  1206. __leave;
  1207. }
  1208. result = TRUE;
  1209. result = result && KeyStructGetValue (keyStruct, Value);
  1210. result = result && KeyStructGetFlags (keyStruct, Flags);
  1211. }
  1212. __finally {
  1213. LeaveCriticalSection (&g_MemDbCs);
  1214. }
  1215. return result;
  1216. }
  1217. DATAHANDLE
  1218. MemDbAddDataA (
  1219. IN PCSTR KeyName,
  1220. IN BYTE Type,
  1221. IN BYTE Instance,
  1222. IN PCBYTE Data,
  1223. IN UINT DataSize
  1224. )
  1225. /*++
  1226. Routine Description:
  1227. MemDbAddData is the a general purpose routine for adding binary data for a key.
  1228. Arguments:
  1229. KeyName - Specifies the key string to add (i.e., foo\bar\cat)
  1230. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  1231. Instance - Specifies data instance (0-3)
  1232. Data - Specifies the address of the data to be added.
  1233. DataSize - Specifies the size of the data.
  1234. Return Value:
  1235. A valid data handle if function was successful, NULL otherwise.
  1236. --*/
  1237. {
  1238. PCWSTR p;
  1239. DATAHANDLE result = 0;
  1240. p = ConvertAtoW (KeyName);
  1241. if (p) {
  1242. result = MemDbAddDataW (p, Type, Instance, Data, DataSize);
  1243. FreeConvertedStr (p);
  1244. }
  1245. return result;
  1246. }
  1247. DATAHANDLE
  1248. MemDbAddDataW (
  1249. IN PCWSTR KeyName,
  1250. IN BYTE Type,
  1251. IN BYTE Instance,
  1252. IN PCBYTE Data,
  1253. IN UINT DataSize
  1254. )
  1255. /*++
  1256. Routine Description:
  1257. MemDbAddData is the a general purpose routine for adding binary data for a key.
  1258. Arguments:
  1259. KeyName - Specifies the key string to add (i.e., foo\bar\cat)
  1260. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  1261. Instance - Specifies data instance (0-3)
  1262. Data - Specifies the address of the data to be added.
  1263. DataSize - Specifies the size of the data.
  1264. Return Value:
  1265. A valid data handle if function was successful, NULL otherwise.
  1266. --*/
  1267. {
  1268. UINT keyIndex;
  1269. UINT dataIndex;
  1270. PCWSTR subKey;
  1271. DATAHANDLE result = 0;
  1272. if (!g_Initialized) {
  1273. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  1274. return result;
  1275. }
  1276. MYASSERT (g_MemDbPool);
  1277. if ((Type != DATAFLAG_UNORDERED) &&
  1278. (Type != DATAFLAG_SINGLELINK) &&
  1279. (Type != DATAFLAG_DOUBLELINK)
  1280. ) {
  1281. return result;
  1282. }
  1283. if (Instance > 3) {
  1284. return result;
  1285. }
  1286. EnterCriticalSection (&g_MemDbCs);
  1287. __try {
  1288. subKey = SelectHiveW (KeyName);
  1289. if (!subKey) {
  1290. __leave;
  1291. }
  1292. keyIndex = FindKey (subKey);
  1293. if (keyIndex == INVALID_OFFSET) {
  1294. keyIndex = NewKey (subKey);
  1295. if (keyIndex == INVALID_OFFSET) {
  1296. __leave;
  1297. }
  1298. }
  1299. dataIndex = KeyStructAddBinaryData (keyIndex, Type, Instance, Data, DataSize);
  1300. if (dataIndex == INVALID_OFFSET) {
  1301. __leave;
  1302. }
  1303. result = GET_EXTERNAL_INDEX (dataIndex);
  1304. }
  1305. __finally {
  1306. #ifdef DEBUG
  1307. if (g_DatabaseCheckLevel) {
  1308. CheckDatabase (g_DatabaseCheckLevel);
  1309. }
  1310. #endif
  1311. LeaveCriticalSection (&g_MemDbCs);
  1312. }
  1313. return result;
  1314. }
  1315. DATAHANDLE
  1316. MemDbAddDataByKeyHandle (
  1317. IN KEYHANDLE KeyHandle,
  1318. IN BYTE Type,
  1319. IN BYTE Instance,
  1320. IN PCBYTE Data,
  1321. IN UINT DataSize
  1322. )
  1323. /*++
  1324. Routine Description:
  1325. MemDbAddData is the a general purpose routine for adding binary data for a key.
  1326. Arguments:
  1327. KeyHandle - Specifies the key using the key handle
  1328. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  1329. Instance - Specifies data instance (0-3)
  1330. Data - Specifies the address of the data to be added.
  1331. DataSize - Specifies the size of the data.
  1332. Return Value:
  1333. A valid data handle if function was successful, NULL otherwise.
  1334. --*/
  1335. {
  1336. BYTE dbIndex;
  1337. UINT dataIndex;
  1338. DATAHANDLE result = 0;
  1339. if (!g_Initialized) {
  1340. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  1341. return result;
  1342. }
  1343. MYASSERT (g_MemDbPool);
  1344. if ((Type != DATAFLAG_UNORDERED) &&
  1345. (Type != DATAFLAG_SINGLELINK) &&
  1346. (Type != DATAFLAG_DOUBLELINK)
  1347. ) {
  1348. return result;
  1349. }
  1350. if (Instance > 3) {
  1351. return result;
  1352. }
  1353. EnterCriticalSection (&g_MemDbCs);
  1354. __try {
  1355. dbIndex = GET_DATABASE (KeyHandle);
  1356. if (!SelectDatabase (dbIndex)) {
  1357. __leave;
  1358. }
  1359. dataIndex = KeyStructAddBinaryData (GET_INDEX (KeyHandle), Type, Instance, Data, DataSize);
  1360. if (dataIndex == INVALID_OFFSET) {
  1361. __leave;
  1362. }
  1363. result = GET_EXTERNAL_INDEX (dataIndex);
  1364. }
  1365. __finally {
  1366. #ifdef DEBUG
  1367. if (g_DatabaseCheckLevel) {
  1368. CheckDatabase (g_DatabaseCheckLevel);
  1369. }
  1370. #endif
  1371. LeaveCriticalSection (&g_MemDbCs);
  1372. }
  1373. return result;
  1374. }
  1375. DATAHANDLE
  1376. MemDbGetDataHandleA (
  1377. IN PCSTR KeyName,
  1378. IN BYTE Type,
  1379. IN BYTE Instance
  1380. )
  1381. {
  1382. PCWSTR p;
  1383. DATAHANDLE result = 0;
  1384. p = ConvertAtoW (KeyName);
  1385. if (p) {
  1386. result = MemDbGetDataHandleW (p, Type, Instance);
  1387. FreeConvertedStr (p);
  1388. }
  1389. return result;
  1390. }
  1391. DATAHANDLE
  1392. MemDbGetDataHandleW (
  1393. IN PCWSTR KeyName,
  1394. IN BYTE Type,
  1395. IN BYTE Instance
  1396. )
  1397. {
  1398. UINT keyIndex;
  1399. UINT dataIndex;
  1400. PCWSTR subKey;
  1401. DATAHANDLE result = 0;
  1402. if (!g_Initialized) {
  1403. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  1404. return result;
  1405. }
  1406. MYASSERT (g_MemDbPool);
  1407. if ((Type != DATAFLAG_UNORDERED) &&
  1408. (Type != DATAFLAG_SINGLELINK) &&
  1409. (Type != DATAFLAG_DOUBLELINK)
  1410. ) {
  1411. return result;
  1412. }
  1413. if (Instance > 3) {
  1414. return result;
  1415. }
  1416. EnterCriticalSection (&g_MemDbCs);
  1417. __try {
  1418. subKey = SelectHiveW (KeyName);
  1419. if (!subKey) {
  1420. __leave;
  1421. }
  1422. keyIndex = FindKey (subKey);
  1423. if (keyIndex == INVALID_OFFSET) {
  1424. __leave;
  1425. }
  1426. dataIndex = KeyStructGetDataIndex (keyIndex, Type, Instance);
  1427. if (dataIndex == INVALID_OFFSET) {
  1428. __leave;
  1429. }
  1430. result = GET_EXTERNAL_INDEX (dataIndex);
  1431. }
  1432. __finally {
  1433. LeaveCriticalSection (&g_MemDbCs);
  1434. }
  1435. return result;
  1436. }
  1437. DATAHANDLE
  1438. MemDbSetDataA (
  1439. IN PCSTR KeyName,
  1440. IN BYTE Type,
  1441. IN BYTE Instance,
  1442. IN PCBYTE Data,
  1443. IN UINT DataSize
  1444. )
  1445. /*++
  1446. Routine Description:
  1447. MemDbSetData is the a general purpose routine for setting binary data for a key.
  1448. If the key does not exist, it is created. If this type of data already exists, it
  1449. is replaced
  1450. Arguments:
  1451. KeyName - Specifies the key string to add (i.e., foo\bar\cat)
  1452. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  1453. Instance - Specifies data instance (0-3)
  1454. Data - Specifies the address of the data to be added.
  1455. DataSize - Specifies the size of the data.
  1456. Return Value:
  1457. A valid data handle if function was successful, NULL otherwise.
  1458. --*/
  1459. {
  1460. PCWSTR p;
  1461. DATAHANDLE result = 0;
  1462. p = ConvertAtoW (KeyName);
  1463. if (p) {
  1464. result = MemDbSetDataW (p, Type, Instance, Data, DataSize);
  1465. FreeConvertedStr (p);
  1466. }
  1467. return result;
  1468. }
  1469. DATAHANDLE
  1470. MemDbSetDataW (
  1471. IN PCWSTR KeyName,
  1472. IN BYTE Type,
  1473. IN BYTE Instance,
  1474. IN PCBYTE Data,
  1475. IN UINT DataSize
  1476. )
  1477. /*++
  1478. Routine Description:
  1479. MemDbSetData is the a general purpose routine for setting binary data for a key.
  1480. If the key does not exist, it is created. If this type of data already exists, it
  1481. is replaced, if it doesn't, it is created.
  1482. Arguments:
  1483. KeyName - Specifies the key string to add (i.e., foo\bar\cat)
  1484. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  1485. Instance - Specifies data instance (0-3)
  1486. Data - Specifies the address of the data to be added.
  1487. DataSize - Specifies the size of the data.
  1488. Return Value:
  1489. A valid data handle if function was successful, NULL otherwise.
  1490. --*/
  1491. {
  1492. UINT keyIndex;
  1493. UINT dataIndex;
  1494. PCWSTR subKey;
  1495. DATAHANDLE result = 0;
  1496. if (!g_Initialized) {
  1497. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  1498. return result;
  1499. }
  1500. MYASSERT (g_MemDbPool);
  1501. if ((Type != DATAFLAG_UNORDERED) &&
  1502. (Type != DATAFLAG_SINGLELINK) &&
  1503. (Type != DATAFLAG_DOUBLELINK)
  1504. ) {
  1505. return result;
  1506. }
  1507. if (Instance > 3) {
  1508. return result;
  1509. }
  1510. EnterCriticalSection (&g_MemDbCs);
  1511. __try {
  1512. subKey = SelectHiveW (KeyName);
  1513. if (!subKey) {
  1514. __leave;
  1515. }
  1516. keyIndex = FindKey (subKey);
  1517. if (keyIndex == INVALID_OFFSET) {
  1518. keyIndex = NewKey (subKey);
  1519. if (keyIndex == INVALID_OFFSET) {
  1520. __leave;
  1521. }
  1522. }
  1523. KeyStructDeleteBinaryData (keyIndex, Type, Instance);
  1524. dataIndex = KeyStructAddBinaryData (keyIndex, Type, Instance, Data, DataSize);
  1525. if (dataIndex == INVALID_OFFSET) {
  1526. __leave;
  1527. }
  1528. result = GET_EXTERNAL_INDEX (dataIndex);
  1529. }
  1530. __finally {
  1531. #ifdef DEBUG
  1532. if (g_DatabaseCheckLevel) {
  1533. CheckDatabase (g_DatabaseCheckLevel);
  1534. }
  1535. #endif
  1536. LeaveCriticalSection (&g_MemDbCs);
  1537. }
  1538. return result;
  1539. }
  1540. DATAHANDLE
  1541. MemDbSetDataByDataHandle (
  1542. IN DATAHANDLE DataHandle,
  1543. IN PCBYTE Data,
  1544. IN UINT DataSize
  1545. )
  1546. /*++
  1547. Routine Description:
  1548. MemDbSetData is the a general purpose routine for replacing an existing binary data.
  1549. Arguments:
  1550. DataHandle - Specifies an existing data handle
  1551. Data - Specifies the address of the data to be added.
  1552. DataSize - Specifies the size of the data.
  1553. Return Value:
  1554. A valid data handle if function was successful, NULL otherwise.
  1555. --*/
  1556. {
  1557. BYTE dbIndex;
  1558. UINT dataIndex;
  1559. DATAHANDLE result = 0;
  1560. if (!g_Initialized) {
  1561. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  1562. return result;
  1563. }
  1564. MYASSERT (g_MemDbPool);
  1565. if (!DataHandle) {
  1566. return result;
  1567. }
  1568. EnterCriticalSection (&g_MemDbCs);
  1569. __try {
  1570. dbIndex = GET_DATABASE (DataHandle);
  1571. if (!SelectDatabase (dbIndex)) {
  1572. __leave;
  1573. }
  1574. dataIndex = KeyStructReplaceBinaryDataByIndex (GET_INDEX (DataHandle), Data, DataSize);
  1575. if (dataIndex == INVALID_OFFSET) {
  1576. __leave;
  1577. }
  1578. result = GET_EXTERNAL_INDEX (dataIndex);
  1579. }
  1580. __finally {
  1581. #ifdef DEBUG
  1582. if (g_DatabaseCheckLevel) {
  1583. CheckDatabase (g_DatabaseCheckLevel);
  1584. }
  1585. #endif
  1586. LeaveCriticalSection (&g_MemDbCs);
  1587. }
  1588. return result;
  1589. }
  1590. DATAHANDLE
  1591. MemDbSetDataByKeyHandle (
  1592. IN KEYHANDLE KeyHandle,
  1593. IN BYTE Type,
  1594. IN BYTE Instance,
  1595. IN PCBYTE Data,
  1596. IN UINT DataSize
  1597. )
  1598. /*++
  1599. Routine Description:
  1600. MemDbSetDataByKeyHandle is the a general purpose routine for setting binary data for a key.
  1601. If this type of data already exists, it is replaced, if it doesn't, it is created.
  1602. Arguments:
  1603. KeyHandle - Specifies the key using the key handle
  1604. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  1605. Instance - Specifies data instance (0-3)
  1606. Data - Specifies the address of the data to be added.
  1607. DataSize - Specifies the size of the data.
  1608. Return Value:
  1609. A valid data handle if function was successful, NULL otherwise.
  1610. --*/
  1611. {
  1612. BYTE dbIndex;
  1613. UINT dataIndex;
  1614. DATAHANDLE result = 0;
  1615. if (!g_Initialized) {
  1616. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  1617. return result;
  1618. }
  1619. MYASSERT (g_MemDbPool);
  1620. if ((Type != DATAFLAG_UNORDERED) &&
  1621. (Type != DATAFLAG_SINGLELINK) &&
  1622. (Type != DATAFLAG_DOUBLELINK)
  1623. ) {
  1624. return result;
  1625. }
  1626. if (Instance > 3) {
  1627. return result;
  1628. }
  1629. EnterCriticalSection (&g_MemDbCs);
  1630. __try {
  1631. dbIndex = GET_DATABASE (KeyHandle);
  1632. if (!SelectDatabase (dbIndex)) {
  1633. __leave;
  1634. }
  1635. KeyStructDeleteBinaryData (GET_INDEX (KeyHandle), Type, Instance);
  1636. dataIndex = KeyStructAddBinaryData (GET_INDEX (KeyHandle), Type, Instance, Data, DataSize);
  1637. if (dataIndex == INVALID_OFFSET) {
  1638. __leave;
  1639. }
  1640. result = GET_EXTERNAL_INDEX (dataIndex);
  1641. }
  1642. __finally {
  1643. #ifdef DEBUG
  1644. if (g_DatabaseCheckLevel) {
  1645. CheckDatabase (g_DatabaseCheckLevel);
  1646. }
  1647. #endif
  1648. LeaveCriticalSection (&g_MemDbCs);
  1649. }
  1650. return result;
  1651. }
  1652. DATAHANDLE
  1653. MemDbGrowDataA (
  1654. IN PCSTR KeyName,
  1655. IN BYTE Type,
  1656. IN BYTE Instance,
  1657. IN PCBYTE Data,
  1658. IN UINT DataSize
  1659. )
  1660. /*++
  1661. Routine Description:
  1662. MemDbGrowData is the a general purpose routine for growing binary data for a key.
  1663. If the key does not exist, it is created. If this type of data already exists, it
  1664. is growed by appending the new data, if not, it is created by adding the new data
  1665. Arguments:
  1666. KeyName - Specifies the key string to add (i.e., foo\bar\cat)
  1667. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  1668. Instance - Specifies data instance (0-3)
  1669. Data - Specifies the address of the data to be added.
  1670. DataSize - Specifies the size of the data.
  1671. Return Value:
  1672. A valid data handle if function was successful, NULL otherwise.
  1673. --*/
  1674. {
  1675. PCWSTR p;
  1676. DATAHANDLE result = 0;
  1677. p = ConvertAtoW (KeyName);
  1678. if (p) {
  1679. result = MemDbGrowDataW (p, Type, Instance, Data, DataSize);
  1680. FreeConvertedStr (p);
  1681. }
  1682. return result;
  1683. }
  1684. DATAHANDLE
  1685. MemDbGrowDataW (
  1686. IN PCWSTR KeyName,
  1687. IN BYTE Type,
  1688. IN BYTE Instance,
  1689. IN PCBYTE Data,
  1690. IN UINT DataSize
  1691. )
  1692. /*++
  1693. Routine Description:
  1694. MemDbGrowData is the a general purpose routine for growing binary data for a key.
  1695. If the key does not exist, it is created. If this type of data already exists, it
  1696. is growed by appending the new data, if not, it is created by adding the new data
  1697. Arguments:
  1698. KeyName - Specifies the key string to add (i.e., foo\bar\cat)
  1699. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  1700. Instance - Specifies data instance (0-3)
  1701. Data - Specifies the address of the data to be added.
  1702. DataSize - Specifies the size of the data.
  1703. Return Value:
  1704. A valid data handle if function was successful, NULL otherwise.
  1705. --*/
  1706. {
  1707. UINT keyIndex;
  1708. UINT dataIndex;
  1709. PCWSTR subKey;
  1710. DATAHANDLE result = 0;
  1711. if (!g_Initialized) {
  1712. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  1713. return result;
  1714. }
  1715. MYASSERT (g_MemDbPool);
  1716. if ((Type != DATAFLAG_UNORDERED) &&
  1717. (Type != DATAFLAG_SINGLELINK) &&
  1718. (Type != DATAFLAG_DOUBLELINK)
  1719. ) {
  1720. return result;
  1721. }
  1722. if (Instance > 3) {
  1723. return result;
  1724. }
  1725. EnterCriticalSection (&g_MemDbCs);
  1726. __try {
  1727. subKey = SelectHiveW (KeyName);
  1728. if (!subKey) {
  1729. __leave;
  1730. }
  1731. keyIndex = FindKey (subKey);
  1732. if (keyIndex == INVALID_OFFSET) {
  1733. keyIndex = NewKey (subKey);
  1734. if (keyIndex == INVALID_OFFSET) {
  1735. __leave;
  1736. }
  1737. }
  1738. dataIndex = KeyStructGrowBinaryData (keyIndex, Type, Instance, Data, DataSize);
  1739. if (dataIndex == INVALID_OFFSET) {
  1740. __leave;
  1741. }
  1742. result = GET_EXTERNAL_INDEX (dataIndex);
  1743. }
  1744. __finally {
  1745. #ifdef DEBUG
  1746. if (g_DatabaseCheckLevel) {
  1747. CheckDatabase (g_DatabaseCheckLevel);
  1748. }
  1749. #endif
  1750. LeaveCriticalSection (&g_MemDbCs);
  1751. }
  1752. return result;
  1753. }
  1754. DATAHANDLE
  1755. MemDbGrowDataByDataHandle (
  1756. IN DATAHANDLE DataHandle,
  1757. IN PCBYTE Data,
  1758. IN UINT DataSize
  1759. )
  1760. /*++
  1761. Routine Description:
  1762. MemDbGrowDataByDataHandle is the a general purpose routine for growing binary data for a key.
  1763. Arguments:
  1764. DataHandle - Specifies the existing binary data handle
  1765. Data - Specifies the address of the data to be added.
  1766. DataSize - Specifies the size of the data.
  1767. Return Value:
  1768. A valid data handle if function was successful, NULL otherwise.
  1769. --*/
  1770. {
  1771. BYTE dbIndex;
  1772. UINT dataIndex;
  1773. DATAHANDLE result = 0;
  1774. if (!g_Initialized) {
  1775. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  1776. return result;
  1777. }
  1778. MYASSERT (g_MemDbPool);
  1779. EnterCriticalSection (&g_MemDbCs);
  1780. __try {
  1781. dbIndex = GET_DATABASE (DataHandle);
  1782. if (!SelectDatabase (dbIndex)) {
  1783. __leave;
  1784. }
  1785. dataIndex = KeyStructGrowBinaryDataByIndex (GET_INDEX (DataHandle), Data, DataSize);
  1786. if (dataIndex == INVALID_OFFSET) {
  1787. __leave;
  1788. }
  1789. result = GET_EXTERNAL_INDEX (dataIndex);
  1790. }
  1791. __finally {
  1792. #ifdef DEBUG
  1793. if (g_DatabaseCheckLevel) {
  1794. CheckDatabase (g_DatabaseCheckLevel);
  1795. }
  1796. #endif
  1797. LeaveCriticalSection (&g_MemDbCs);
  1798. }
  1799. return result;
  1800. }
  1801. DATAHANDLE
  1802. MemDbGrowDataByKeyHandle (
  1803. IN KEYHANDLE KeyHandle,
  1804. IN BYTE Type,
  1805. IN BYTE Instance,
  1806. IN PCBYTE Data,
  1807. IN UINT DataSize
  1808. )
  1809. /*++
  1810. Routine Description:
  1811. MemDbGrowDataByDataHandle is the a general purpose routine for growing binary
  1812. data for a key. If the data is not present it is added, if it's present, the
  1813. new data is appended.
  1814. Arguments:
  1815. KeyHandle - Specifies the key we want by it's handle
  1816. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  1817. Instance - Specifies data instance (0-3)
  1818. Data - Specifies the address of the data to be added.
  1819. DataSize - Specifies the size of the data.
  1820. Return Value:
  1821. A valid data handle if function was successful, NULL otherwise.
  1822. --*/
  1823. {
  1824. BYTE dbIndex;
  1825. UINT dataIndex;
  1826. DATAHANDLE result = 0;
  1827. if (!g_Initialized) {
  1828. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  1829. return result;
  1830. }
  1831. MYASSERT (g_MemDbPool);
  1832. if (!KeyHandle) {
  1833. return result;
  1834. }
  1835. EnterCriticalSection (&g_MemDbCs);
  1836. __try {
  1837. dbIndex = GET_DATABASE (KeyHandle);
  1838. if (!SelectDatabase (dbIndex)) {
  1839. __leave;
  1840. }
  1841. dataIndex = KeyStructGrowBinaryData (GET_INDEX (KeyHandle), Type, Instance, Data, DataSize);
  1842. if (dataIndex == INVALID_OFFSET) {
  1843. __leave;
  1844. }
  1845. result = GET_EXTERNAL_INDEX (dataIndex);
  1846. }
  1847. __finally {
  1848. #ifdef DEBUG
  1849. if (g_DatabaseCheckLevel) {
  1850. CheckDatabase (g_DatabaseCheckLevel);
  1851. }
  1852. #endif
  1853. LeaveCriticalSection (&g_MemDbCs);
  1854. }
  1855. return result;
  1856. }
  1857. PBYTE
  1858. MemDbGetDataA (
  1859. IN PCSTR KeyName,
  1860. IN BYTE Type,
  1861. IN BYTE Instance,
  1862. OUT PUINT DataSize OPTIONAL
  1863. )
  1864. /*++
  1865. Routine Description:
  1866. MemDbGetData is the a general purpose routine for retrieving existing binary
  1867. data for a key. if the key or binary data do not exist, will return NULL. The
  1868. function will allocate memory from memdb's private pool. Caller is responsible
  1869. for releasing the memory.
  1870. Arguments:
  1871. KeyName - Specifies the key string to add (i.e., foo\bar\cat)
  1872. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  1873. Instance - Specifies data instance (0-3)
  1874. DataSize - Receives the size of the data.
  1875. Return Value:
  1876. A valid memory address if function was successful, NULL otherwise. Caller must
  1877. free non-NULL return values by calling MemDbReleaseMemory.
  1878. --*/
  1879. {
  1880. PCWSTR p;
  1881. PBYTE result = NULL;
  1882. p = ConvertAtoW (KeyName);
  1883. if (p) {
  1884. result = MemDbGetDataW (p, Type, Instance, DataSize);
  1885. FreeConvertedStr (p);
  1886. }
  1887. return result;
  1888. }
  1889. PBYTE
  1890. MemDbGetDataW (
  1891. IN PCWSTR KeyName,
  1892. IN BYTE Type,
  1893. IN BYTE Instance,
  1894. OUT PUINT DataSize OPTIONAL
  1895. )
  1896. /*++
  1897. Routine Description:
  1898. MemDbGetData is the a general purpose routine for retrieving existing binary
  1899. data for a key. if the key or binary data do not exist, will return NULL. The
  1900. function will allocate memory from memdb's private pool. Caller is responsible
  1901. for releasing the memory.
  1902. Arguments:
  1903. KeyName - Specifies the key string to add (i.e., foo\bar\cat)
  1904. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  1905. Instance - Specifies data instance (0-3)
  1906. DataSize - Receives the size of the data.
  1907. Return Value:
  1908. A valid memory address if function was successful, NULL otherwise. Caller must
  1909. free non-NULL return values by calling MemDbReleaseMemory.
  1910. --*/
  1911. {
  1912. UINT keyIndex;
  1913. PCWSTR subKey;
  1914. PBYTE tempResult = NULL;
  1915. PBYTE result = NULL;
  1916. UINT localSize;
  1917. if (!g_Initialized) {
  1918. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  1919. return result;
  1920. }
  1921. MYASSERT (g_MemDbPool);
  1922. if ((Type != DATAFLAG_UNORDERED) &&
  1923. (Type != DATAFLAG_SINGLELINK) &&
  1924. (Type != DATAFLAG_DOUBLELINK)
  1925. ) {
  1926. return NULL;
  1927. }
  1928. if (Instance > 3) {
  1929. return NULL;
  1930. }
  1931. EnterCriticalSection (&g_MemDbCs);
  1932. __try {
  1933. subKey = SelectHiveW (KeyName);
  1934. if (!subKey) {
  1935. __leave;
  1936. }
  1937. keyIndex = FindKey (subKey);
  1938. if (keyIndex == INVALID_OFFSET) {
  1939. __leave;
  1940. }
  1941. tempResult = KeyStructGetBinaryData (keyIndex, Type, Instance, &localSize, NULL);
  1942. if (tempResult) {
  1943. result = MemDbGetMemory (localSize);
  1944. if (result) {
  1945. CopyMemory (result, tempResult, localSize);
  1946. if (DataSize) {
  1947. *DataSize = localSize;
  1948. }
  1949. }
  1950. }
  1951. }
  1952. __finally {
  1953. LeaveCriticalSection (&g_MemDbCs);
  1954. }
  1955. return result;
  1956. }
  1957. PBYTE
  1958. MemDbGetDataByDataHandle (
  1959. IN DATAHANDLE DataHandle,
  1960. OUT PUINT DataSize OPTIONAL
  1961. )
  1962. /*++
  1963. Routine Description:
  1964. MemDbGetDataByDataHandle is the a general purpose routine for retrieving
  1965. existing binary data for a key.
  1966. Arguments:
  1967. DataHandle - Specifies the data that's needed identified by the data handle
  1968. DataSize - Receives the size of the data.
  1969. Return Value:
  1970. A valid memory address if function was successful, NULL otherwise.
  1971. --*/
  1972. {
  1973. BYTE dbIndex;
  1974. PBYTE tempResult = NULL;
  1975. PBYTE result = NULL;
  1976. UINT localSize;
  1977. if (!g_Initialized) {
  1978. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  1979. return result;
  1980. }
  1981. MYASSERT (g_MemDbPool);
  1982. EnterCriticalSection (&g_MemDbCs);
  1983. __try {
  1984. dbIndex = GET_DATABASE (DataHandle);
  1985. if (!SelectDatabase (dbIndex)) {
  1986. __leave;
  1987. }
  1988. tempResult = KeyStructGetBinaryDataByIndex (GET_INDEX (DataHandle), &localSize);
  1989. if (tempResult) {
  1990. result = MemDbGetMemory (localSize);
  1991. if (result) {
  1992. CopyMemory (result, tempResult, localSize);
  1993. if (DataSize) {
  1994. *DataSize = localSize;
  1995. }
  1996. }
  1997. }
  1998. }
  1999. __finally {
  2000. LeaveCriticalSection (&g_MemDbCs);
  2001. }
  2002. return result;
  2003. }
  2004. PBYTE
  2005. MemDbGetDataByKeyHandle (
  2006. IN KEYHANDLE KeyHandle,
  2007. IN BYTE Type,
  2008. IN BYTE Instance,
  2009. OUT PUINT DataSize OPTIONAL
  2010. )
  2011. /*++
  2012. Routine Description:
  2013. MemDbGetDataByKeyHandle is the a general purpose routine for retrieving existing binary data for a key.
  2014. Arguments:
  2015. KeyHandle - Specifies the key by it's hey handle
  2016. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  2017. Instance - Specifies data instance (0-3)
  2018. DataSize - Receives the size of the data.
  2019. Return Value:
  2020. A valid memory address if function was successful, NULL otherwise. Caller must
  2021. free non-NULL return values by calling MemDbReleaseMemory.
  2022. --*/
  2023. {
  2024. BYTE dbIndex;
  2025. PBYTE tempResult = NULL;
  2026. PBYTE result = NULL;
  2027. UINT localSize;
  2028. if (!g_Initialized) {
  2029. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2030. return result;
  2031. }
  2032. MYASSERT (g_MemDbPool);
  2033. if ((Type != DATAFLAG_UNORDERED) &&
  2034. (Type != DATAFLAG_SINGLELINK) &&
  2035. (Type != DATAFLAG_DOUBLELINK)
  2036. ) {
  2037. return NULL;
  2038. }
  2039. if (Instance > 3) {
  2040. return NULL;
  2041. }
  2042. EnterCriticalSection (&g_MemDbCs);
  2043. __try {
  2044. dbIndex = GET_DATABASE (KeyHandle);
  2045. if (!SelectDatabase (dbIndex)) {
  2046. __leave;
  2047. }
  2048. tempResult = KeyStructGetBinaryData (GET_INDEX (KeyHandle), Type, Instance, &localSize, NULL);
  2049. if (tempResult) {
  2050. result = MemDbGetMemory (localSize);
  2051. if (result) {
  2052. CopyMemory (result, tempResult, localSize);
  2053. if (DataSize) {
  2054. *DataSize = localSize;
  2055. }
  2056. }
  2057. }
  2058. }
  2059. __finally {
  2060. LeaveCriticalSection (&g_MemDbCs);
  2061. }
  2062. return result;
  2063. }
  2064. BOOL
  2065. MemDbGetDataExA (
  2066. IN PCSTR KeyName,
  2067. IN BYTE Type,
  2068. IN BYTE Instance,
  2069. OUT PGROWBUFFER Buffer, OPTIONAL
  2070. OUT PUINT DataSize OPTIONAL
  2071. )
  2072. /*++
  2073. Routine Description:
  2074. MemDbGetDataEx is the a general purpose routine for retrieving existing binary
  2075. data for a key. if the key or binary data do not exist, will return FALSE. The
  2076. function will use the caller supplied growbuffer to store the data.
  2077. Arguments:
  2078. KeyName - Specifies the key string to add (i.e., foo\bar\cat)
  2079. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  2080. Instance - Specifies data instance (0-3)
  2081. Buffer - Specifies a grow buffer that may contain data. Receives the
  2082. stored data (appended to existing data).
  2083. DataSize - Receives the size of the data.
  2084. Return Value:
  2085. TRUE if binary data exists for the key, and was successfully stored in
  2086. Buffer, FALSE otherwise.
  2087. --*/
  2088. {
  2089. PCWSTR p;
  2090. BOOL result = FALSE;
  2091. p = ConvertAtoW (KeyName);
  2092. if (p) {
  2093. result = MemDbGetDataExW (p, Type, Instance, Buffer, DataSize);
  2094. FreeConvertedStr (p);
  2095. }
  2096. return result;
  2097. }
  2098. BOOL
  2099. MemDbGetDataExW (
  2100. IN PCWSTR KeyName,
  2101. IN BYTE Type,
  2102. IN BYTE Instance,
  2103. OUT PGROWBUFFER Buffer, OPTIONAL
  2104. OUT PUINT DataSize OPTIONAL
  2105. )
  2106. /*++
  2107. Routine Description:
  2108. MemDbGetData is the a general purpose routine for retrieving existing binary
  2109. data for a key. if the key or binary data do not exist, will return FALSE. The
  2110. function will use the caller supplied growbuffer to store the data.
  2111. Arguments:
  2112. KeyName - Specifies the key string to add (i.e., foo\bar\cat)
  2113. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  2114. Instance - Specifies data instance (0-3)
  2115. Buffer - Specifies a grow buffer that may contain data. Receives the
  2116. stored data (appended to existing data).
  2117. DataSize - Receives the size of the data.
  2118. Return Value:
  2119. TRUE if binary data exists for the key, and was successfully stored in
  2120. Buffer, FALSE otherwise.
  2121. --*/
  2122. {
  2123. UINT keyIndex;
  2124. PCWSTR subKey;
  2125. PBYTE tempResult = NULL;
  2126. PBYTE destResult = NULL;
  2127. BOOL result = FALSE;
  2128. UINT localSize;
  2129. if (!g_Initialized) {
  2130. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2131. return result;
  2132. }
  2133. MYASSERT (g_MemDbPool);
  2134. if ((Type != DATAFLAG_UNORDERED) &&
  2135. (Type != DATAFLAG_SINGLELINK) &&
  2136. (Type != DATAFLAG_DOUBLELINK)
  2137. ) {
  2138. return FALSE;
  2139. }
  2140. if (Instance > 3) {
  2141. return FALSE;
  2142. }
  2143. EnterCriticalSection (&g_MemDbCs);
  2144. __try {
  2145. subKey = SelectHiveW (KeyName);
  2146. if (!subKey) {
  2147. __leave;
  2148. }
  2149. keyIndex = FindKey (subKey);
  2150. if (keyIndex == INVALID_OFFSET) {
  2151. __leave;
  2152. }
  2153. tempResult = KeyStructGetBinaryData (keyIndex, Type, Instance, &localSize, NULL);
  2154. if (tempResult) {
  2155. if (Buffer) {
  2156. destResult = GbGrow (Buffer, localSize);
  2157. if (destResult) {
  2158. CopyMemory (destResult, tempResult, localSize);
  2159. result = TRUE;
  2160. }
  2161. } else {
  2162. result = TRUE;
  2163. }
  2164. if (result && DataSize) {
  2165. *DataSize = localSize;
  2166. }
  2167. }
  2168. }
  2169. __finally {
  2170. LeaveCriticalSection (&g_MemDbCs);
  2171. }
  2172. return result;
  2173. }
  2174. BOOL
  2175. MemDbGetDataByDataHandleEx (
  2176. IN DATAHANDLE DataHandle,
  2177. OUT PGROWBUFFER Buffer, OPTIONAL
  2178. OUT PUINT DataSize OPTIONAL
  2179. )
  2180. /*++
  2181. Routine Description:
  2182. MemDbGetDataByDataHandleEx is the a general purpose routine for retrieving
  2183. existing binary data for a key. The function will use the caller supplied
  2184. growbuffer to store the data.
  2185. Arguments:
  2186. DataHandle - Specifies the data that's needed identified by the data handle
  2187. Buffer - Specifies a grow buffer that may contain data. Receives the
  2188. stored data (appended to existing data).
  2189. DataSize - Receives the size of the data.
  2190. Return Value:
  2191. TRUE if binary data exists for the key, and was successfully stored in
  2192. Buffer, FALSE otherwise.
  2193. --*/
  2194. {
  2195. BYTE dbIndex;
  2196. PBYTE tempResult = NULL;
  2197. PBYTE destResult = NULL;
  2198. BOOL result = FALSE;
  2199. UINT localSize;
  2200. if (!g_Initialized) {
  2201. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2202. return result;
  2203. }
  2204. MYASSERT (g_MemDbPool);
  2205. EnterCriticalSection (&g_MemDbCs);
  2206. __try {
  2207. dbIndex = GET_DATABASE (DataHandle);
  2208. if (!SelectDatabase (dbIndex)) {
  2209. __leave;
  2210. }
  2211. tempResult = KeyStructGetBinaryDataByIndex (GET_INDEX (DataHandle), &localSize);
  2212. if (tempResult) {
  2213. if (Buffer) {
  2214. destResult = GbGrow (Buffer, localSize);
  2215. if (destResult) {
  2216. CopyMemory (destResult, tempResult, localSize);
  2217. result = TRUE;
  2218. }
  2219. } else {
  2220. result = TRUE;
  2221. }
  2222. if (result && DataSize) {
  2223. *DataSize = localSize;
  2224. }
  2225. }
  2226. }
  2227. __finally {
  2228. LeaveCriticalSection (&g_MemDbCs);
  2229. }
  2230. return result;
  2231. }
  2232. BOOL
  2233. MemDbGetDataByKeyHandleEx (
  2234. IN KEYHANDLE KeyHandle,
  2235. IN BYTE Type,
  2236. IN BYTE Instance,
  2237. OUT PGROWBUFFER Buffer, OPTIONAL
  2238. OUT PUINT DataSize OPTIONAL
  2239. )
  2240. /*++
  2241. Routine Description:
  2242. MemDbGetDataByKeyHandle is the a general purpose routine for retrieving
  2243. existing binary data for a key. The function will use the caller supplied
  2244. growbuffer to store the data.
  2245. Arguments:
  2246. KeyHandle - Specifies the key by it's hey handle
  2247. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  2248. Instance - Specifies data instance (0-3)
  2249. Buffer - Specifies a grow buffer that may contain data. Receives the
  2250. stored data (appended to existing data).
  2251. DataSize - Receives the size of the data.
  2252. Return Value:
  2253. TRUE if binary data exists for the key, and was successfully stored in
  2254. Buffer, FALSE otherwise.
  2255. --*/
  2256. {
  2257. BYTE dbIndex;
  2258. PBYTE tempResult = NULL;
  2259. PBYTE destResult = NULL;
  2260. BOOL result = FALSE;
  2261. UINT localSize;
  2262. if (!g_Initialized) {
  2263. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2264. return result;
  2265. }
  2266. MYASSERT (g_MemDbPool);
  2267. if ((Type != DATAFLAG_UNORDERED) &&
  2268. (Type != DATAFLAG_SINGLELINK) &&
  2269. (Type != DATAFLAG_DOUBLELINK)
  2270. ) {
  2271. return FALSE;
  2272. }
  2273. if (Instance > 3) {
  2274. return FALSE;
  2275. }
  2276. EnterCriticalSection (&g_MemDbCs);
  2277. __try {
  2278. dbIndex = GET_DATABASE (KeyHandle);
  2279. if (!SelectDatabase (dbIndex)) {
  2280. __leave;
  2281. }
  2282. tempResult = KeyStructGetBinaryData (GET_INDEX (KeyHandle), Type, Instance, &localSize, NULL);
  2283. if (tempResult) {
  2284. if (Buffer) {
  2285. destResult = GbGrow (Buffer, localSize);
  2286. if (destResult) {
  2287. CopyMemory (destResult, tempResult, localSize);
  2288. result = TRUE;
  2289. }
  2290. } else {
  2291. result = TRUE;
  2292. }
  2293. if (result && DataSize) {
  2294. *DataSize = localSize;
  2295. }
  2296. }
  2297. }
  2298. __finally {
  2299. LeaveCriticalSection (&g_MemDbCs);
  2300. }
  2301. return result;
  2302. }
  2303. BOOL
  2304. MemDbDeleteDataA (
  2305. IN PCSTR KeyName,
  2306. IN BYTE Type,
  2307. IN BYTE Instance
  2308. )
  2309. /*++
  2310. Routine Description:
  2311. MemDbGetData is the a general purpose routine for removing existing data for a
  2312. key. If the data does not exist the function will return TRUE anyway.
  2313. Arguments:
  2314. KeyName - Specifies the key string to add (i.e., foo\bar\cat)
  2315. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  2316. Instance - Specifies data instance (0-3)
  2317. Return Value:
  2318. TRUE if function was successful, FALSE otherwise.
  2319. --*/
  2320. {
  2321. PCWSTR p;
  2322. BOOL result = FALSE;
  2323. p = ConvertAtoW (KeyName);
  2324. if (p) {
  2325. result = MemDbDeleteDataW (p, Type, Instance);
  2326. FreeConvertedStr (p);
  2327. }
  2328. return result;
  2329. }
  2330. BOOL
  2331. MemDbDeleteDataW (
  2332. IN PCWSTR KeyName,
  2333. IN BYTE Type,
  2334. IN BYTE Instance
  2335. )
  2336. /*++
  2337. Routine Description:
  2338. MemDbDeleteData is the a general purpose routine for removing existing binary
  2339. data for a key. If the data does not exist the function will return TRUE
  2340. anyway.
  2341. Arguments:
  2342. KeyName - Specifies the key string to add (i.e., foo\bar\cat)
  2343. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  2344. Instance - Specifies data instance (0-3)
  2345. Return Value:
  2346. TRUE if function was successful, FALSE otherwise.
  2347. --*/
  2348. {
  2349. UINT keyIndex;
  2350. PCWSTR subKey;
  2351. BOOL result = FALSE;
  2352. if (!g_Initialized) {
  2353. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2354. return result;
  2355. }
  2356. MYASSERT (g_MemDbPool);
  2357. if ((Type != DATAFLAG_UNORDERED) &&
  2358. (Type != DATAFLAG_SINGLELINK) &&
  2359. (Type != DATAFLAG_DOUBLELINK)
  2360. ) {
  2361. return FALSE;
  2362. }
  2363. if (Instance > 3) {
  2364. return FALSE;
  2365. }
  2366. EnterCriticalSection (&g_MemDbCs);
  2367. __try {
  2368. subKey = SelectHiveW (KeyName);
  2369. if (!subKey) {
  2370. __leave;
  2371. }
  2372. keyIndex = FindKey (subKey);
  2373. if (keyIndex == INVALID_OFFSET) {
  2374. __leave;
  2375. }
  2376. result = KeyStructDeleteBinaryData (keyIndex, Type, Instance);
  2377. }
  2378. __finally {
  2379. #ifdef DEBUG
  2380. if (g_DatabaseCheckLevel) {
  2381. CheckDatabase (g_DatabaseCheckLevel);
  2382. }
  2383. #endif
  2384. LeaveCriticalSection (&g_MemDbCs);
  2385. }
  2386. return result;
  2387. }
  2388. BOOL
  2389. MemDbDeleteDataByDataHandle (
  2390. IN DATAHANDLE DataHandle
  2391. )
  2392. /*++
  2393. Routine Description:
  2394. MemDbGetDataByDataHandleEx is the a general purpose routine for removing
  2395. existing binary data for a key.
  2396. Arguments:
  2397. DataHandle - Specifies the data that's needed identified by the data handle
  2398. Return Value:
  2399. TRUE if successful, FALSE if not.
  2400. --*/
  2401. {
  2402. BYTE dbIndex;
  2403. BOOL result = FALSE;
  2404. if (!g_Initialized) {
  2405. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2406. return result;
  2407. }
  2408. MYASSERT (g_MemDbPool);
  2409. EnterCriticalSection (&g_MemDbCs);
  2410. __try {
  2411. dbIndex = GET_DATABASE (DataHandle);
  2412. if (!SelectDatabase (dbIndex)) {
  2413. __leave;
  2414. }
  2415. result = KeyStructDeleteBinaryDataByIndex (GET_INDEX (DataHandle));
  2416. }
  2417. __finally {
  2418. #ifdef DEBUG
  2419. if (g_DatabaseCheckLevel) {
  2420. CheckDatabase (g_DatabaseCheckLevel);
  2421. }
  2422. #endif
  2423. LeaveCriticalSection (&g_MemDbCs);
  2424. }
  2425. return result;
  2426. }
  2427. BOOL
  2428. MemDbDeleteDataByKeyHandle (
  2429. IN KEYHANDLE KeyHandle,
  2430. IN BYTE Type,
  2431. IN BYTE Instance
  2432. )
  2433. /*++
  2434. Routine Description:
  2435. MemDbGetDataByDataHandleEx is the a general purpose routine for removing
  2436. existing binary data for a key.
  2437. Arguments:
  2438. KeyHandle - Specifies the key by it's hey handle
  2439. Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
  2440. Instance - Specifies data instance (0-3)
  2441. Return Value:
  2442. TRUE if successful, FALSE if not.
  2443. --*/
  2444. {
  2445. BYTE dbIndex;
  2446. BOOL result = FALSE;
  2447. if (!g_Initialized) {
  2448. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2449. return result;
  2450. }
  2451. MYASSERT (g_MemDbPool);
  2452. EnterCriticalSection (&g_MemDbCs);
  2453. __try {
  2454. dbIndex = GET_DATABASE (KeyHandle);
  2455. if (!SelectDatabase (dbIndex)) {
  2456. __leave;
  2457. }
  2458. result = KeyStructDeleteBinaryData (GET_INDEX (KeyHandle), Type, Instance);
  2459. }
  2460. __finally {
  2461. #ifdef DEBUG
  2462. if (g_DatabaseCheckLevel) {
  2463. CheckDatabase (g_DatabaseCheckLevel);
  2464. }
  2465. #endif
  2466. LeaveCriticalSection (&g_MemDbCs);
  2467. }
  2468. return result;
  2469. }
  2470. DATAHANDLE
  2471. MemDbAddLinkageValueA (
  2472. IN PCSTR KeyName,
  2473. IN BYTE Type,
  2474. IN BYTE Instance,
  2475. IN UINT Linkage,
  2476. IN BOOL AllowDuplicates
  2477. )
  2478. {
  2479. PCWSTR p;
  2480. DATAHANDLE result = 0;
  2481. p = ConvertAtoW (KeyName);
  2482. if (p) {
  2483. result = MemDbAddLinkageValueW (p, Type, Instance, Linkage, AllowDuplicates);
  2484. FreeConvertedStr (p);
  2485. }
  2486. return result;
  2487. }
  2488. DATAHANDLE
  2489. MemDbAddLinkageValueW (
  2490. IN PCWSTR KeyName,
  2491. IN BYTE Type,
  2492. IN BYTE Instance,
  2493. IN UINT Linkage,
  2494. IN BOOL AllowDuplicates
  2495. )
  2496. {
  2497. UINT keyIndex;
  2498. UINT dataIndex;
  2499. PCWSTR subKey;
  2500. DATAHANDLE result = 0;
  2501. if (!g_Initialized) {
  2502. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2503. return result;
  2504. }
  2505. MYASSERT (g_MemDbPool);
  2506. if ((Type != DATAFLAG_SINGLELINK) &&
  2507. (Type != DATAFLAG_DOUBLELINK)
  2508. ) {
  2509. return result;
  2510. }
  2511. if (Instance > 3) {
  2512. return result;
  2513. }
  2514. EnterCriticalSection (&g_MemDbCs);
  2515. __try {
  2516. subKey = SelectHiveW (KeyName);
  2517. if (!subKey) {
  2518. __leave;
  2519. }
  2520. keyIndex = FindKey (subKey);
  2521. if (keyIndex == INVALID_OFFSET) {
  2522. keyIndex = NewKey (subKey);
  2523. if (keyIndex == INVALID_OFFSET) {
  2524. __leave;
  2525. }
  2526. }
  2527. dataIndex = KeyStructAddLinkage (keyIndex, Type, Instance, Linkage, AllowDuplicates);
  2528. if (dataIndex == INVALID_OFFSET) {
  2529. __leave;
  2530. }
  2531. result = GET_EXTERNAL_INDEX (dataIndex);
  2532. }
  2533. __finally {
  2534. #ifdef DEBUG
  2535. if (g_DatabaseCheckLevel) {
  2536. CheckDatabase (g_DatabaseCheckLevel);
  2537. }
  2538. #endif
  2539. LeaveCriticalSection (&g_MemDbCs);
  2540. }
  2541. return result;
  2542. }
  2543. DATAHANDLE
  2544. MemDbAddLinkageValueByDataHandle (
  2545. IN DATAHANDLE DataHandle,
  2546. IN UINT Linkage,
  2547. IN BOOL AllowDuplicates
  2548. )
  2549. {
  2550. BYTE dbIndex;
  2551. UINT dataIndex;
  2552. DATAHANDLE result = 0;
  2553. if (!g_Initialized) {
  2554. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2555. return result;
  2556. }
  2557. MYASSERT (g_MemDbPool);
  2558. EnterCriticalSection (&g_MemDbCs);
  2559. __try {
  2560. dbIndex = GET_DATABASE (DataHandle);
  2561. if (!SelectDatabase (dbIndex)) {
  2562. __leave;
  2563. }
  2564. dataIndex = KeyStructAddLinkageByIndex (GET_INDEX (DataHandle), Linkage, AllowDuplicates);
  2565. if (dataIndex == INVALID_OFFSET) {
  2566. __leave;
  2567. }
  2568. result = GET_EXTERNAL_INDEX (dataIndex);
  2569. }
  2570. __finally {
  2571. #ifdef DEBUG
  2572. if (g_DatabaseCheckLevel) {
  2573. CheckDatabase (g_DatabaseCheckLevel);
  2574. }
  2575. #endif
  2576. LeaveCriticalSection (&g_MemDbCs);
  2577. }
  2578. return result;
  2579. }
  2580. DATAHANDLE
  2581. MemDbAddLinkageValueByKeyHandle (
  2582. IN KEYHANDLE KeyHandle,
  2583. IN BYTE Type,
  2584. IN BYTE Instance,
  2585. IN UINT Linkage,
  2586. IN BOOL AllowDuplicates
  2587. )
  2588. {
  2589. BYTE dbIndex;
  2590. UINT dataIndex;
  2591. DATAHANDLE result = 0;
  2592. if (!g_Initialized) {
  2593. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2594. return result;
  2595. }
  2596. MYASSERT (g_MemDbPool);
  2597. if ((Type != DATAFLAG_SINGLELINK) &&
  2598. (Type != DATAFLAG_DOUBLELINK)
  2599. ) {
  2600. return result;
  2601. }
  2602. if (Instance > 3) {
  2603. return result;
  2604. }
  2605. EnterCriticalSection (&g_MemDbCs);
  2606. __try {
  2607. dbIndex = GET_DATABASE (KeyHandle);
  2608. if (!SelectDatabase (dbIndex)) {
  2609. __leave;
  2610. }
  2611. dataIndex = KeyStructAddLinkage (GET_INDEX (KeyHandle), Type, Instance, Linkage, AllowDuplicates);
  2612. if (dataIndex == INVALID_OFFSET) {
  2613. __leave;
  2614. }
  2615. result = GET_EXTERNAL_INDEX (dataIndex);
  2616. }
  2617. __finally {
  2618. #ifdef DEBUG
  2619. if (g_DatabaseCheckLevel) {
  2620. CheckDatabase (g_DatabaseCheckLevel);
  2621. }
  2622. #endif
  2623. LeaveCriticalSection (&g_MemDbCs);
  2624. }
  2625. return result;
  2626. }
  2627. BOOL
  2628. MemDbDeleteLinkageValueA (
  2629. IN PCSTR KeyName,
  2630. IN BYTE Type,
  2631. IN BYTE Instance,
  2632. IN UINT Linkage,
  2633. IN BOOL FirstOnly
  2634. )
  2635. {
  2636. PCWSTR p;
  2637. BOOL result = FALSE;
  2638. p = ConvertAtoW (KeyName);
  2639. if (p) {
  2640. result = MemDbDeleteLinkageValueW (p, Type, Instance, Linkage, FirstOnly);
  2641. FreeConvertedStr (p);
  2642. }
  2643. return result;
  2644. }
  2645. BOOL
  2646. MemDbDeleteLinkageValueW (
  2647. IN PCWSTR KeyName,
  2648. IN BYTE Type,
  2649. IN BYTE Instance,
  2650. IN UINT Linkage,
  2651. IN BOOL FirstOnly
  2652. )
  2653. {
  2654. UINT keyIndex;
  2655. PCWSTR subKey;
  2656. BOOL result = FALSE;
  2657. if (!g_Initialized) {
  2658. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2659. return result;
  2660. }
  2661. MYASSERT (g_MemDbPool);
  2662. if ((Type != DATAFLAG_SINGLELINK) &&
  2663. (Type != DATAFLAG_DOUBLELINK)
  2664. ) {
  2665. return FALSE;
  2666. }
  2667. if (Instance > 3) {
  2668. return FALSE;
  2669. }
  2670. EnterCriticalSection (&g_MemDbCs);
  2671. __try {
  2672. subKey = SelectHiveW (KeyName);
  2673. if (!subKey) {
  2674. __leave;
  2675. }
  2676. keyIndex = FindKey (subKey);
  2677. if (keyIndex == INVALID_OFFSET) {
  2678. __leave;
  2679. }
  2680. result = KeyStructDeleteLinkage (keyIndex, Type, Instance, Linkage, FirstOnly);
  2681. }
  2682. __finally {
  2683. #ifdef DEBUG
  2684. if (g_DatabaseCheckLevel) {
  2685. CheckDatabase (g_DatabaseCheckLevel);
  2686. }
  2687. #endif
  2688. LeaveCriticalSection (&g_MemDbCs);
  2689. }
  2690. return result;
  2691. }
  2692. BOOL
  2693. MemDbDeleteLinkageValueByDataHandle (
  2694. IN DATAHANDLE DataHandle,
  2695. IN UINT Linkage,
  2696. IN BOOL FirstOnly
  2697. )
  2698. {
  2699. BYTE dbIndex;
  2700. BOOL result = FALSE;
  2701. if (!g_Initialized) {
  2702. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2703. return result;
  2704. }
  2705. MYASSERT (g_MemDbPool);
  2706. EnterCriticalSection (&g_MemDbCs);
  2707. __try {
  2708. dbIndex = GET_DATABASE (DataHandle);
  2709. if (!SelectDatabase (dbIndex)) {
  2710. __leave;
  2711. }
  2712. result = KeyStructDeleteLinkageByIndex (GET_INDEX (DataHandle), Linkage, FirstOnly);
  2713. }
  2714. __finally {
  2715. #ifdef DEBUG
  2716. if (g_DatabaseCheckLevel) {
  2717. CheckDatabase (g_DatabaseCheckLevel);
  2718. }
  2719. #endif
  2720. LeaveCriticalSection (&g_MemDbCs);
  2721. }
  2722. return result;
  2723. }
  2724. BOOL
  2725. MemDbDeleteLinkageValueByKeyHandle (
  2726. IN KEYHANDLE KeyHandle,
  2727. IN BYTE Type,
  2728. IN BYTE Instance,
  2729. IN UINT Linkage,
  2730. IN BOOL FirstOnly
  2731. )
  2732. {
  2733. BYTE dbIndex;
  2734. BOOL result = FALSE;
  2735. if (!g_Initialized) {
  2736. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2737. return result;
  2738. }
  2739. MYASSERT (g_MemDbPool);
  2740. if ((Type != DATAFLAG_SINGLELINK) &&
  2741. (Type != DATAFLAG_DOUBLELINK)
  2742. ) {
  2743. return FALSE;
  2744. }
  2745. if (Instance > 3) {
  2746. return FALSE;
  2747. }
  2748. EnterCriticalSection (&g_MemDbCs);
  2749. __try {
  2750. dbIndex = GET_DATABASE (KeyHandle);
  2751. if (!SelectDatabase (dbIndex)) {
  2752. __leave;
  2753. }
  2754. result = KeyStructDeleteLinkage (GET_INDEX (KeyHandle), Type, Instance, Linkage, FirstOnly);
  2755. }
  2756. __finally {
  2757. #ifdef DEBUG
  2758. if (g_DatabaseCheckLevel) {
  2759. CheckDatabase (g_DatabaseCheckLevel);
  2760. }
  2761. #endif
  2762. LeaveCriticalSection (&g_MemDbCs);
  2763. }
  2764. return result;
  2765. }
  2766. BOOL
  2767. MemDbTestLinkageValueA (
  2768. IN PCSTR KeyName,
  2769. IN BYTE Type,
  2770. IN BYTE Instance,
  2771. IN UINT Linkage
  2772. )
  2773. {
  2774. PCWSTR p;
  2775. BOOL result = FALSE;
  2776. p = ConvertAtoW (KeyName);
  2777. if (p) {
  2778. result = MemDbTestLinkageValueW (p, Type, Instance, Linkage);
  2779. FreeConvertedStr (p);
  2780. }
  2781. return result;
  2782. }
  2783. BOOL
  2784. MemDbTestLinkageValueW (
  2785. IN PCWSTR KeyName,
  2786. IN BYTE Type,
  2787. IN BYTE Instance,
  2788. IN KEYHANDLE Linkage
  2789. )
  2790. {
  2791. UINT keyIndex;
  2792. PCWSTR subKey;
  2793. BOOL result = FALSE;
  2794. if (!g_Initialized) {
  2795. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2796. return result;
  2797. }
  2798. MYASSERT (g_MemDbPool);
  2799. if ((Type != DATAFLAG_SINGLELINK) &&
  2800. (Type != DATAFLAG_DOUBLELINK)
  2801. ) {
  2802. return FALSE;
  2803. }
  2804. if (Instance > 3) {
  2805. return FALSE;
  2806. }
  2807. EnterCriticalSection (&g_MemDbCs);
  2808. __try {
  2809. subKey = SelectHiveW (KeyName);
  2810. if (!subKey) {
  2811. __leave;
  2812. }
  2813. keyIndex = FindKey (subKey);
  2814. if (keyIndex == INVALID_OFFSET) {
  2815. __leave;
  2816. }
  2817. result = KeyStructTestLinkage (keyIndex, Type, Instance, Linkage);
  2818. }
  2819. __finally {
  2820. LeaveCriticalSection (&g_MemDbCs);
  2821. }
  2822. return result;
  2823. }
  2824. BOOL
  2825. MemDbTestLinkageValueByDataHandle (
  2826. IN DATAHANDLE DataHandle,
  2827. IN KEYHANDLE Linkage
  2828. )
  2829. {
  2830. BYTE dbIndex;
  2831. BOOL result = FALSE;
  2832. if (!g_Initialized) {
  2833. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2834. return result;
  2835. }
  2836. MYASSERT (g_MemDbPool);
  2837. EnterCriticalSection (&g_MemDbCs);
  2838. __try {
  2839. dbIndex = GET_DATABASE (DataHandle);
  2840. if (!SelectDatabase (dbIndex)) {
  2841. __leave;
  2842. }
  2843. result = KeyStructTestLinkageByIndex (GET_INDEX (DataHandle), Linkage);
  2844. }
  2845. __finally {
  2846. LeaveCriticalSection (&g_MemDbCs);
  2847. }
  2848. return result;
  2849. }
  2850. BOOL
  2851. MemDbTestLinkageValueByKeyHandle (
  2852. IN KEYHANDLE KeyHandle,
  2853. IN BYTE Type,
  2854. IN BYTE Instance,
  2855. IN KEYHANDLE Linkage
  2856. )
  2857. {
  2858. BYTE dbIndex;
  2859. BOOL result = FALSE;
  2860. if (!g_Initialized) {
  2861. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2862. return result;
  2863. }
  2864. MYASSERT (g_MemDbPool);
  2865. if ((Type != DATAFLAG_SINGLELINK) &&
  2866. (Type != DATAFLAG_DOUBLELINK)
  2867. ) {
  2868. return FALSE;
  2869. }
  2870. if (Instance > 3) {
  2871. return FALSE;
  2872. }
  2873. EnterCriticalSection (&g_MemDbCs);
  2874. __try {
  2875. dbIndex = GET_DATABASE (KeyHandle);
  2876. if (!SelectDatabase (dbIndex)) {
  2877. __leave;
  2878. }
  2879. result = KeyStructTestLinkage (GET_INDEX (KeyHandle), Type, Instance, Linkage);
  2880. }
  2881. __finally {
  2882. LeaveCriticalSection (&g_MemDbCs);
  2883. }
  2884. return result;
  2885. }
  2886. BOOL
  2887. MemDbAddLinkageA (
  2888. IN PCSTR KeyName1,
  2889. IN PCSTR KeyName2,
  2890. IN BYTE Type,
  2891. IN BYTE Instance
  2892. )
  2893. {
  2894. PCWSTR p1 = NULL;
  2895. PCWSTR p2 = NULL;
  2896. BOOL result = FALSE;
  2897. p1 = ConvertAtoW (KeyName1);
  2898. p2 = ConvertAtoW (KeyName2);
  2899. if (p1 && p2) {
  2900. result = MemDbAddLinkageW (p1, p2, Type, Instance);
  2901. }
  2902. if (p1) {
  2903. FreeConvertedStr (p1);
  2904. }
  2905. if (p2) {
  2906. FreeConvertedStr (p2);
  2907. }
  2908. return result;
  2909. }
  2910. BOOL
  2911. MemDbAddLinkageW (
  2912. IN PCWSTR KeyName1,
  2913. IN PCWSTR KeyName2,
  2914. IN BYTE Type,
  2915. IN BYTE Instance
  2916. )
  2917. {
  2918. UINT keyIndex1;
  2919. UINT keyIndex2;
  2920. UINT dataIndex;
  2921. PCWSTR subKey1;
  2922. PCWSTR subKey2;
  2923. BOOL result = FALSE;
  2924. if (!g_Initialized) {
  2925. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  2926. return result;
  2927. }
  2928. MYASSERT (g_MemDbPool);
  2929. if ((Type != DATAFLAG_SINGLELINK) &&
  2930. (Type != DATAFLAG_DOUBLELINK)
  2931. ) {
  2932. return FALSE;
  2933. }
  2934. if (Instance > 3) {
  2935. return FALSE;
  2936. }
  2937. EnterCriticalSection (&g_MemDbCs);
  2938. __try {
  2939. subKey1 = SelectHiveW (KeyName1);
  2940. if (!subKey1) {
  2941. __leave;
  2942. }
  2943. keyIndex1 = FindKey (subKey1);
  2944. if (keyIndex1 == INVALID_OFFSET) {
  2945. keyIndex1 = NewKey (subKey1);
  2946. if (keyIndex1 == INVALID_OFFSET) {
  2947. __leave;
  2948. }
  2949. }
  2950. subKey2 = SelectHiveW (KeyName2);
  2951. if (!subKey2) {
  2952. __leave;
  2953. }
  2954. keyIndex2 = FindKey (subKey2);
  2955. if (keyIndex2 == INVALID_OFFSET) {
  2956. keyIndex2 = NewKey (subKey2);
  2957. if (keyIndex2 == INVALID_OFFSET) {
  2958. __leave;
  2959. }
  2960. }
  2961. subKey1 = SelectHiveW (KeyName1);
  2962. if (!subKey1) {
  2963. __leave;
  2964. }
  2965. MYASSERT (keyIndex2 != INVALID_OFFSET);
  2966. dataIndex = KeyStructAddLinkage (keyIndex1, Type, Instance, GET_EXTERNAL_INDEX (keyIndex2), FALSE);
  2967. if (dataIndex == INVALID_OFFSET) {
  2968. __leave;
  2969. }
  2970. if (Type == DATAFLAG_DOUBLELINK) {
  2971. subKey2 = SelectHiveW (KeyName2);
  2972. if (!subKey2) {
  2973. __leave;
  2974. }
  2975. MYASSERT (keyIndex1 != INVALID_OFFSET);
  2976. dataIndex = KeyStructAddLinkage (keyIndex2, Type, Instance, GET_EXTERNAL_INDEX (keyIndex1), FALSE);
  2977. if (dataIndex == INVALID_OFFSET) {
  2978. __leave;
  2979. }
  2980. }
  2981. result = TRUE;
  2982. }
  2983. __finally {
  2984. #ifdef DEBUG
  2985. if (g_DatabaseCheckLevel) {
  2986. CheckDatabase (g_DatabaseCheckLevel);
  2987. }
  2988. #endif
  2989. LeaveCriticalSection (&g_MemDbCs);
  2990. }
  2991. return result;
  2992. }
  2993. BOOL
  2994. MemDbAddLinkageByKeyHandle (
  2995. IN KEYHANDLE KeyHandle1,
  2996. IN KEYHANDLE KeyHandle2,
  2997. IN BYTE Type,
  2998. IN BYTE Instance
  2999. )
  3000. {
  3001. UINT keyIndex1;
  3002. UINT keyIndex2;
  3003. UINT dataIndex;
  3004. BYTE dbIndex1;
  3005. BYTE dbIndex2;
  3006. BOOL result = FALSE;
  3007. if (!g_Initialized) {
  3008. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  3009. return result;
  3010. }
  3011. MYASSERT (g_MemDbPool);
  3012. if ((Type != DATAFLAG_SINGLELINK) &&
  3013. (Type != DATAFLAG_DOUBLELINK)
  3014. ) {
  3015. return FALSE;
  3016. }
  3017. if (Instance > 3) {
  3018. return FALSE;
  3019. }
  3020. EnterCriticalSection (&g_MemDbCs);
  3021. __try {
  3022. dbIndex1 = GET_DATABASE (KeyHandle1);
  3023. if (!SelectDatabase (dbIndex1)) {
  3024. __leave;
  3025. }
  3026. keyIndex1 = GET_INDEX (KeyHandle1);
  3027. if (keyIndex1 == INVALID_OFFSET) {
  3028. __leave;
  3029. }
  3030. dbIndex2 = GET_DATABASE (KeyHandle2);
  3031. if (!SelectDatabase (dbIndex2)) {
  3032. __leave;
  3033. }
  3034. keyIndex2 = GET_INDEX (KeyHandle2);
  3035. if (keyIndex2 == INVALID_OFFSET) {
  3036. __leave;
  3037. }
  3038. SelectDatabase (dbIndex1);
  3039. dataIndex = KeyStructAddLinkage (keyIndex1, Type, Instance, KeyHandle2, FALSE);
  3040. if (dataIndex == INVALID_OFFSET) {
  3041. __leave;
  3042. }
  3043. if (Type == DATAFLAG_DOUBLELINK) {
  3044. SelectDatabase (dbIndex2);
  3045. dataIndex = KeyStructAddLinkage (keyIndex2, Type, Instance, KeyHandle1, FALSE);
  3046. if (dataIndex == INVALID_OFFSET) {
  3047. __leave;
  3048. }
  3049. }
  3050. result = TRUE;
  3051. }
  3052. __finally {
  3053. #ifdef DEBUG
  3054. if (g_DatabaseCheckLevel) {
  3055. CheckDatabase (g_DatabaseCheckLevel);
  3056. }
  3057. #endif
  3058. LeaveCriticalSection (&g_MemDbCs);
  3059. }
  3060. return result;
  3061. }
  3062. BOOL
  3063. MemDbDeleteLinkageA (
  3064. IN PCSTR KeyName1,
  3065. IN PCSTR KeyName2,
  3066. IN BYTE Type,
  3067. IN BYTE Instance
  3068. )
  3069. {
  3070. PCWSTR p1 = NULL;
  3071. PCWSTR p2 = NULL;
  3072. BOOL result = FALSE;
  3073. p1 = ConvertAtoW (KeyName1);
  3074. p2 = ConvertAtoW (KeyName2);
  3075. if (p1 && p2) {
  3076. result = MemDbDeleteLinkageW (p1, p2, Type, Instance);
  3077. }
  3078. if (p1) {
  3079. FreeConvertedStr (p1);
  3080. }
  3081. if (p2) {
  3082. FreeConvertedStr (p2);
  3083. }
  3084. return result;
  3085. }
  3086. BOOL
  3087. MemDbDeleteLinkageW (
  3088. IN PCWSTR KeyName1,
  3089. IN PCWSTR KeyName2,
  3090. IN BYTE Type,
  3091. IN BYTE Instance
  3092. )
  3093. {
  3094. UINT keyIndex1;
  3095. UINT keyIndex2;
  3096. PCWSTR subKey1;
  3097. PCWSTR subKey2;
  3098. BOOL result = FALSE;
  3099. if (!g_Initialized) {
  3100. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  3101. return result;
  3102. }
  3103. MYASSERT (g_MemDbPool);
  3104. if ((Type != DATAFLAG_SINGLELINK) &&
  3105. (Type != DATAFLAG_DOUBLELINK)
  3106. ) {
  3107. return FALSE;
  3108. }
  3109. if (Instance > 3) {
  3110. return FALSE;
  3111. }
  3112. EnterCriticalSection (&g_MemDbCs);
  3113. __try {
  3114. subKey1 = SelectHiveW (KeyName1);
  3115. if (!subKey1) {
  3116. __leave;
  3117. }
  3118. keyIndex1 = FindKey (subKey1);
  3119. if (keyIndex1 == INVALID_OFFSET) {
  3120. __leave;
  3121. }
  3122. subKey2 = SelectHiveW (KeyName2);
  3123. if (!subKey2) {
  3124. __leave;
  3125. }
  3126. keyIndex2 = FindKey (subKey2);
  3127. if (keyIndex2 == INVALID_OFFSET) {
  3128. __leave;
  3129. }
  3130. subKey1 = SelectHiveW (KeyName1);
  3131. if (!subKey1) {
  3132. __leave;
  3133. }
  3134. MYASSERT (keyIndex2 != INVALID_OFFSET);
  3135. result = KeyStructDeleteLinkage (keyIndex1, Type, Instance, GET_EXTERNAL_INDEX (keyIndex2), FALSE);
  3136. if (result && (Type == DATAFLAG_DOUBLELINK)) {
  3137. subKey2 = SelectHiveW (KeyName2);
  3138. if (!subKey2) {
  3139. __leave;
  3140. }
  3141. MYASSERT (keyIndex1 != INVALID_OFFSET);
  3142. result = KeyStructDeleteLinkage (keyIndex2, Type, Instance, GET_EXTERNAL_INDEX (keyIndex1), FALSE);
  3143. }
  3144. }
  3145. __finally {
  3146. LeaveCriticalSection (&g_MemDbCs);
  3147. }
  3148. return result;
  3149. }
  3150. BOOL
  3151. MemDbDeleteLinkageByKeyHandle (
  3152. IN KEYHANDLE KeyHandle1,
  3153. IN KEYHANDLE KeyHandle2,
  3154. IN BYTE Type,
  3155. IN BYTE Instance
  3156. )
  3157. {
  3158. UINT keyIndex1;
  3159. UINT keyIndex2;
  3160. BYTE dbIndex1;
  3161. BYTE dbIndex2;
  3162. BOOL result = FALSE;
  3163. if (!g_Initialized) {
  3164. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  3165. return result;
  3166. }
  3167. MYASSERT (g_MemDbPool);
  3168. if ((Type != DATAFLAG_SINGLELINK) &&
  3169. (Type != DATAFLAG_DOUBLELINK)
  3170. ) {
  3171. return FALSE;
  3172. }
  3173. if (Instance > 3) {
  3174. return FALSE;
  3175. }
  3176. EnterCriticalSection (&g_MemDbCs);
  3177. __try {
  3178. dbIndex1 = GET_DATABASE (KeyHandle1);
  3179. if (!SelectDatabase (dbIndex1)) {
  3180. __leave;
  3181. }
  3182. keyIndex1 = GET_INDEX (KeyHandle1);
  3183. if (keyIndex1 == INVALID_OFFSET) {
  3184. __leave;
  3185. }
  3186. dbIndex2 = GET_DATABASE (KeyHandle2);
  3187. if (!SelectDatabase (dbIndex2)) {
  3188. __leave;
  3189. }
  3190. keyIndex2 = GET_INDEX (KeyHandle2);
  3191. if (keyIndex2 == INVALID_OFFSET) {
  3192. __leave;
  3193. }
  3194. SelectDatabase (dbIndex1);
  3195. result = KeyStructDeleteLinkage (keyIndex1, Type, Instance, KeyHandle2, FALSE);
  3196. if (result && (Type == DATAFLAG_DOUBLELINK)) {
  3197. SelectDatabase (dbIndex2);
  3198. result = KeyStructDeleteLinkage (keyIndex2, Type, Instance, KeyHandle1, FALSE);
  3199. }
  3200. }
  3201. __finally {
  3202. LeaveCriticalSection (&g_MemDbCs);
  3203. }
  3204. return result;
  3205. }
  3206. BOOL
  3207. MemDbTestLinkageA (
  3208. IN PCSTR KeyName1,
  3209. IN PCSTR KeyName2,
  3210. IN BYTE Type,
  3211. IN BYTE Instance
  3212. )
  3213. {
  3214. PCWSTR p1 = NULL;
  3215. PCWSTR p2 = NULL;
  3216. BOOL result = FALSE;
  3217. p1 = ConvertAtoW (KeyName1);
  3218. p2 = ConvertAtoW (KeyName2);
  3219. if (p1 && p2) {
  3220. result = MemDbTestLinkageW (p1, p2, Type, Instance);
  3221. }
  3222. if (p1) {
  3223. FreeConvertedStr (p1);
  3224. }
  3225. if (p2) {
  3226. FreeConvertedStr (p2);
  3227. }
  3228. return result;
  3229. }
  3230. BOOL
  3231. MemDbTestLinkageW (
  3232. IN PCWSTR KeyName1,
  3233. IN PCWSTR KeyName2,
  3234. IN BYTE Type,
  3235. IN BYTE Instance
  3236. )
  3237. {
  3238. UINT keyIndex1;
  3239. UINT keyIndex2;
  3240. PCWSTR subKey1;
  3241. PCWSTR subKey2;
  3242. BOOL result = FALSE;
  3243. if (!g_Initialized) {
  3244. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  3245. return result;
  3246. }
  3247. MYASSERT (g_MemDbPool);
  3248. if ((Type != DATAFLAG_SINGLELINK) &&
  3249. (Type != DATAFLAG_DOUBLELINK)
  3250. ) {
  3251. return FALSE;
  3252. }
  3253. if (Instance > 3) {
  3254. return FALSE;
  3255. }
  3256. EnterCriticalSection (&g_MemDbCs);
  3257. __try {
  3258. subKey1 = SelectHiveW (KeyName1);
  3259. if (!subKey1) {
  3260. __leave;
  3261. }
  3262. keyIndex1 = FindKey (subKey1);
  3263. if (keyIndex1 == INVALID_OFFSET) {
  3264. __leave;
  3265. }
  3266. subKey2 = SelectHiveW (KeyName2);
  3267. if (!subKey2) {
  3268. __leave;
  3269. }
  3270. keyIndex2 = FindKey (subKey2);
  3271. if (keyIndex2 == INVALID_OFFSET) {
  3272. __leave;
  3273. }
  3274. subKey1 = SelectHiveW (KeyName1);
  3275. if (!subKey1) {
  3276. __leave;
  3277. }
  3278. MYASSERT (keyIndex2 != INVALID_OFFSET);
  3279. result = KeyStructTestLinkage (keyIndex1, Type, Instance, GET_EXTERNAL_INDEX (keyIndex2));
  3280. if (result && (Type == DATAFLAG_DOUBLELINK)) {
  3281. subKey2 = SelectHiveW (KeyName2);
  3282. if (!subKey2) {
  3283. __leave;
  3284. }
  3285. MYASSERT (keyIndex1 != INVALID_OFFSET);
  3286. result = KeyStructTestLinkage (keyIndex2, Type, Instance, GET_EXTERNAL_INDEX (keyIndex1));
  3287. }
  3288. }
  3289. __finally {
  3290. LeaveCriticalSection (&g_MemDbCs);
  3291. }
  3292. return result;
  3293. }
  3294. BOOL
  3295. MemDbTestLinkageByKeyHandle (
  3296. IN KEYHANDLE KeyHandle1,
  3297. IN KEYHANDLE KeyHandle2,
  3298. IN BYTE Type,
  3299. IN BYTE Instance
  3300. )
  3301. {
  3302. UINT keyIndex1;
  3303. UINT keyIndex2;
  3304. BYTE dbIndex1;
  3305. BYTE dbIndex2;
  3306. BOOL result = FALSE;
  3307. if (!g_Initialized) {
  3308. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  3309. return result;
  3310. }
  3311. MYASSERT (g_MemDbPool);
  3312. if ((Type != DATAFLAG_SINGLELINK) &&
  3313. (Type != DATAFLAG_DOUBLELINK)
  3314. ) {
  3315. return FALSE;
  3316. }
  3317. if (Instance > 3) {
  3318. return FALSE;
  3319. }
  3320. EnterCriticalSection (&g_MemDbCs);
  3321. __try {
  3322. dbIndex1 = GET_DATABASE (KeyHandle1);
  3323. if (!SelectDatabase (dbIndex1)) {
  3324. __leave;
  3325. }
  3326. keyIndex1 = GET_INDEX (KeyHandle1);
  3327. if (keyIndex1 == INVALID_OFFSET) {
  3328. __leave;
  3329. }
  3330. dbIndex2 = GET_DATABASE (KeyHandle2);
  3331. if (!SelectDatabase (dbIndex2)) {
  3332. __leave;
  3333. }
  3334. keyIndex2 = GET_INDEX (KeyHandle2);
  3335. if (keyIndex2 == INVALID_OFFSET) {
  3336. __leave;
  3337. }
  3338. SelectDatabase (dbIndex1);
  3339. result = KeyStructTestLinkage (keyIndex1, Type, Instance, KeyHandle2);
  3340. if (result && (Type == DATAFLAG_DOUBLELINK)) {
  3341. SelectDatabase (dbIndex2);
  3342. result = KeyStructTestLinkage (keyIndex2, Type, Instance, KeyHandle1);
  3343. }
  3344. }
  3345. __finally {
  3346. LeaveCriticalSection (&g_MemDbCs);
  3347. }
  3348. return result;
  3349. }
  3350. KEYHANDLE
  3351. MemDbGetLinkageA (
  3352. IN PCSTR KeyName,
  3353. IN BYTE Type,
  3354. IN BYTE Instance,
  3355. IN UINT LinkageIndex
  3356. )
  3357. {
  3358. PCWSTR p = NULL;
  3359. KEYHANDLE result = 0;
  3360. p = ConvertAtoW (KeyName);
  3361. if (p) {
  3362. result = MemDbGetLinkageW (p, Type, Instance, LinkageIndex);
  3363. FreeConvertedStr (p);
  3364. }
  3365. return result;
  3366. }
  3367. KEYHANDLE
  3368. MemDbGetLinkageW (
  3369. IN PCWSTR KeyName,
  3370. IN BYTE Type,
  3371. IN BYTE Instance,
  3372. IN UINT LinkageIndex
  3373. )
  3374. {
  3375. UINT keyIndex;
  3376. PCWSTR subKey;
  3377. KEYHANDLE result = 0;
  3378. PUINT linkArray;
  3379. UINT linkArraySize;
  3380. if (!g_Initialized) {
  3381. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  3382. return result;
  3383. }
  3384. MYASSERT (g_MemDbPool);
  3385. if ((Type != DATAFLAG_SINGLELINK) &&
  3386. (Type != DATAFLAG_DOUBLELINK)
  3387. ) {
  3388. return result;
  3389. }
  3390. if (Instance > 3) {
  3391. return result;
  3392. }
  3393. EnterCriticalSection (&g_MemDbCs);
  3394. __try {
  3395. subKey = SelectHiveW (KeyName);
  3396. if (!subKey) {
  3397. __leave;
  3398. }
  3399. keyIndex = FindKey (subKey);
  3400. if (keyIndex == INVALID_OFFSET) {
  3401. __leave;
  3402. }
  3403. linkArraySize = 0;
  3404. linkArray = (PUINT)KeyStructGetBinaryData (keyIndex, Type, Instance, &linkArraySize, NULL);
  3405. linkArraySize = linkArraySize / SIZEOF(UINT);
  3406. if (linkArraySize <= LinkageIndex) {
  3407. __leave;
  3408. }
  3409. result = linkArray [LinkageIndex];
  3410. }
  3411. __finally {
  3412. LeaveCriticalSection (&g_MemDbCs);
  3413. }
  3414. return result;
  3415. }
  3416. KEYHANDLE
  3417. MemDbGetLinkageByKeyHandle (
  3418. IN KEYHANDLE KeyHandle,
  3419. IN BYTE Type,
  3420. IN BYTE Instance,
  3421. IN UINT LinkageIndex
  3422. )
  3423. {
  3424. UINT keyIndex;
  3425. BYTE dbIndex;
  3426. KEYHANDLE result = 0;
  3427. PUINT linkArray;
  3428. UINT linkArraySize;
  3429. if (!g_Initialized) {
  3430. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  3431. return result;
  3432. }
  3433. MYASSERT (g_MemDbPool);
  3434. if ((Type != DATAFLAG_SINGLELINK) &&
  3435. (Type != DATAFLAG_DOUBLELINK)
  3436. ) {
  3437. return result;
  3438. }
  3439. if (Instance > 3) {
  3440. return result;
  3441. }
  3442. EnterCriticalSection (&g_MemDbCs);
  3443. __try {
  3444. dbIndex = GET_DATABASE (KeyHandle);
  3445. if (!SelectDatabase (dbIndex)) {
  3446. __leave;
  3447. }
  3448. keyIndex = GET_INDEX (KeyHandle);
  3449. if (keyIndex == INVALID_OFFSET) {
  3450. __leave;
  3451. }
  3452. linkArray = (PUINT)KeyStructGetBinaryData (keyIndex, Type, Instance, &linkArraySize, NULL);
  3453. linkArraySize = linkArraySize / SIZEOF(UINT);
  3454. if (linkArraySize <= LinkageIndex) {
  3455. __leave;
  3456. }
  3457. result = linkArray [LinkageIndex];
  3458. }
  3459. __finally {
  3460. LeaveCriticalSection (&g_MemDbCs);
  3461. }
  3462. return result;
  3463. }
  3464. BOOL
  3465. pCheckEnumConditions (
  3466. IN UINT KeyIndex,
  3467. IN PMEMDB_ENUMW MemDbEnum
  3468. )
  3469. {
  3470. PKEYSTRUCT keyStruct;
  3471. UINT index;
  3472. PWSTR segPtr, segEndPtr;
  3473. keyStruct = GetKeyStruct (KeyIndex);
  3474. MYASSERT (keyStruct);
  3475. if (keyStruct->KeyFlags & KSF_ENDPOINT) {
  3476. if (!(MemDbEnum->EnumFlags & ENUMFLAG_ENDPOINTS)) {
  3477. return FALSE;
  3478. }
  3479. MemDbEnum->EndPoint = TRUE;
  3480. } else {
  3481. if (!(MemDbEnum->EnumFlags & ENUMFLAG_NONENDPOINTS)) {
  3482. return FALSE;
  3483. }
  3484. MemDbEnum->EndPoint = FALSE;
  3485. }
  3486. if (keyStruct->DataFlags & DATAFLAG_UNORDERED) {
  3487. if (!(MemDbEnum->EnumFlags & ENUMFLAG_UNORDERED)) {
  3488. return FALSE;
  3489. }
  3490. }
  3491. if (keyStruct->DataFlags & DATAFLAG_SINGLELINK) {
  3492. if (!(MemDbEnum->EnumFlags & ENUMFLAG_SINGLELINK)) {
  3493. return FALSE;
  3494. }
  3495. }
  3496. if (keyStruct->DataFlags & DATAFLAG_DOUBLELINK) {
  3497. if (!(MemDbEnum->EnumFlags & ENUMFLAG_DOUBLELINK)) {
  3498. return FALSE;
  3499. }
  3500. }
  3501. if (keyStruct->DataFlags & DATAFLAG_VALUE) {
  3502. if (!(MemDbEnum->EnumFlags & ENUMFLAG_VALUE)) {
  3503. return FALSE;
  3504. }
  3505. MemDbEnum->Value = keyStruct->Value;
  3506. } else {
  3507. MemDbEnum->Value = 0;
  3508. }
  3509. if (keyStruct->DataFlags & DATAFLAG_FLAGS) {
  3510. if (!(MemDbEnum->EnumFlags & ENUMFLAG_FLAGS)) {
  3511. return FALSE;
  3512. }
  3513. MemDbEnum->Flags = keyStruct->Flags;
  3514. } else {
  3515. MemDbEnum->Flags = 0;
  3516. }
  3517. if (!keyStruct->DataFlags) {
  3518. if (!(MemDbEnum->EnumFlags & ENUMFLAG_EMPTY)) {
  3519. return FALSE;
  3520. }
  3521. }
  3522. if (MemDbEnum->BeginLevel != ENUMLEVEL_LASTLEVEL) {
  3523. if (MemDbEnum->CurrentLevel - 1 < MemDbEnum->BeginLevel) {
  3524. return FALSE;
  3525. }
  3526. if (MemDbEnum->CurrentLevel - 1 > MemDbEnum->EndLevel) {
  3527. return FALSE;
  3528. }
  3529. }
  3530. MYASSERT (KeyIndex != INVALID_OFFSET);
  3531. MemDbEnum->KeyHandle = GET_EXTERNAL_INDEX (KeyIndex);
  3532. index = 0;
  3533. segPtr = MemDbEnum->KeyNameCopy;
  3534. MemDbEnum->FullKeyName[0] = 0;
  3535. MemDbEnum->KeyName[0] = 0;
  3536. while (segPtr) {
  3537. segEndPtr = wcschr (segPtr, L'\\');
  3538. if (segEndPtr) {
  3539. *segEndPtr = 0;
  3540. }
  3541. index ++;
  3542. if (index > 1) {
  3543. StringCatW (MemDbEnum->FullKeyName, L"\\");
  3544. StringCatW (MemDbEnum->FullKeyName, segPtr);
  3545. } else {
  3546. switch (g_CurrentDatabaseIndex) {
  3547. case DB_PERMANENT:
  3548. StringCopyW (MemDbEnum->FullKeyName, segPtr);
  3549. break;
  3550. case DB_TEMPORARY:
  3551. StringCopyW (MemDbEnum->FullKeyName, L"~");
  3552. StringCatW (MemDbEnum->FullKeyName, segPtr);
  3553. break;
  3554. default:
  3555. StringCopyW (MemDbEnum->FullKeyName, segPtr);
  3556. }
  3557. }
  3558. if (MemDbEnum->BeginLevel == ENUMLEVEL_LASTLEVEL) {
  3559. if (index >= MemDbEnum->CurrentLevel) {
  3560. //this is the last segment, copy it to the
  3561. //partial key
  3562. StringCopyW (MemDbEnum->KeyName, segPtr);
  3563. }
  3564. } else {
  3565. if (index > MemDbEnum->BeginLevel) {
  3566. //copy the current segment in partial key
  3567. if ((index - 1) == MemDbEnum->BeginLevel) {
  3568. if (index == 1) {
  3569. switch (g_CurrentDatabaseIndex) {
  3570. case DB_PERMANENT:
  3571. StringCopyW (MemDbEnum->KeyName, segPtr);
  3572. break;
  3573. case DB_TEMPORARY:
  3574. StringCopyW (MemDbEnum->KeyName, L"~");
  3575. StringCatW (MemDbEnum->KeyName, segPtr);
  3576. break;
  3577. default:
  3578. StringCopyW (MemDbEnum->KeyName, segPtr);
  3579. }
  3580. } else {
  3581. StringCopyW (MemDbEnum->KeyName, segPtr);
  3582. }
  3583. } else {
  3584. StringCatW (MemDbEnum->KeyName, L"\\");
  3585. StringCatW (MemDbEnum->KeyName, segPtr);
  3586. }
  3587. }
  3588. }
  3589. if (segEndPtr) {
  3590. segPtr = segEndPtr + 1;
  3591. *segEndPtr = L'\\';
  3592. } else {
  3593. segPtr = NULL;
  3594. }
  3595. if (index >= MemDbEnum->CurrentLevel) {
  3596. // no more segments to copy
  3597. break;
  3598. }
  3599. }
  3600. return TRUE;
  3601. }
  3602. VOID
  3603. pAddKeyToEnumStruct (
  3604. IN OUT PMEMDB_ENUMW MemDbEnum,
  3605. IN PCWSTR KeyName
  3606. )
  3607. {
  3608. PCWSTR lastName;
  3609. PWSTR endPtr;
  3610. lastName = MemDbEnum->KeyNameCopy;
  3611. if (lastName) {
  3612. MemDbEnum->KeyNameCopy = JoinTextExW (g_MemDbPool, lastName, L"\\", NULL, KeyName[0] + 1, &endPtr);
  3613. StringPasCopyConvertFrom (endPtr, KeyName);
  3614. MemDbReleaseMemory ((PBYTE)lastName);
  3615. } else {
  3616. MemDbEnum->KeyNameCopy = (PWSTR)MemDbGetMemory ((KeyName[0] + 1) * SIZEOF(WCHAR));
  3617. StringPasCopyConvertFrom ((PWSTR)MemDbEnum->KeyNameCopy, KeyName);
  3618. }
  3619. // NTRAID#NTBUG9-153308-2000/08/01-jimschm this way of doing it will fill out the pool very fast.
  3620. // need to find a way to release first and allocate after that.
  3621. }
  3622. VOID
  3623. pDeleteLastKeyFromEnumStruct (
  3624. IN OUT PMEMDB_ENUMW MemDbEnum
  3625. )
  3626. {
  3627. PWSTR lastWackPtr;
  3628. lastWackPtr = wcsrchr (MemDbEnum->KeyNameCopy, L'\\');
  3629. if (lastWackPtr) {
  3630. *lastWackPtr = 0;
  3631. } else {
  3632. MemDbReleaseMemory (MemDbEnum->KeyNameCopy);
  3633. MemDbEnum->KeyNameCopy = NULL;
  3634. }
  3635. }
  3636. BOOL
  3637. pMemDbEnumNextW (
  3638. IN OUT PMEMDB_ENUMW MemDbEnum
  3639. )
  3640. {
  3641. BOOL shouldReturn = FALSE;
  3642. BOOL result = FALSE;
  3643. BOOL patternMatch = TRUE;
  3644. BOOL goOn = TRUE;
  3645. BOOL patternFound;
  3646. UINT treeEnumContext;
  3647. UINT treeEnumNode;
  3648. UINT tempKeyIndex;
  3649. PKEYSTRUCT tempKeyStruct;
  3650. PBYTE gbAddress;
  3651. UINT minLevel;
  3652. UINT internalLevel;
  3653. while (!shouldReturn) {
  3654. if (MemDbEnum->EnumerationMode) {
  3655. result = FALSE;
  3656. minLevel = MemDbEnum->CurrentLevel;
  3657. internalLevel = MemDbEnum->CurrentLevel;
  3658. if (MemDbEnum->TreeEnumLevel == MemDbEnum->TreeEnumBuffer.End) {
  3659. patternMatch = FALSE;
  3660. while (!patternMatch) {
  3661. if (MemDbEnum->TreeEnumBuffer.End) {
  3662. goOn = TRUE;
  3663. while (goOn) {
  3664. // we are in the middle of some tree enumeration
  3665. // let's get back the context and continue
  3666. if (MemDbEnum->TreeEnumBuffer.End == 0) {
  3667. // we can't back out any more, we're done
  3668. break;
  3669. }
  3670. MemDbEnum->TreeEnumBuffer.End -= (SIZEOF(UINT)+SIZEOF(UINT));
  3671. if (MemDbEnum->TreeEnumLevel > MemDbEnum->TreeEnumBuffer.End) {
  3672. MemDbEnum->TreeEnumLevel = MemDbEnum->TreeEnumBuffer.End;
  3673. }
  3674. minLevel --;
  3675. if (MemDbEnum->CurrentLevel > minLevel) {
  3676. MemDbEnum->CurrentLevel = minLevel;
  3677. }
  3678. if (internalLevel > minLevel) {
  3679. internalLevel = minLevel;
  3680. }
  3681. pDeleteLastKeyFromEnumStruct (MemDbEnum);
  3682. treeEnumContext = *((PUINT) (MemDbEnum->TreeEnumBuffer.Buf+MemDbEnum->TreeEnumBuffer.End + SIZEOF(UINT)));
  3683. tempKeyIndex = BinTreeEnumNext (&treeEnumContext);
  3684. if (tempKeyIndex != INVALID_OFFSET) {
  3685. minLevel ++;
  3686. internalLevel ++;
  3687. goOn = FALSE;
  3688. // put them in the grow buffer
  3689. gbAddress = GbGrow (&(MemDbEnum->TreeEnumBuffer), SIZEOF(UINT)+SIZEOF(UINT));
  3690. if (gbAddress) {
  3691. *((PUINT) (gbAddress)) = tempKeyIndex;
  3692. *((PUINT) (gbAddress+SIZEOF(UINT))) = treeEnumContext;
  3693. }
  3694. tempKeyStruct = GetKeyStruct (tempKeyIndex);
  3695. MYASSERT (tempKeyStruct);
  3696. pAddKeyToEnumStruct (MemDbEnum, tempKeyStruct->KeyName);
  3697. treeEnumNode = tempKeyStruct->NextLevelTree;
  3698. while ((treeEnumNode != INVALID_OFFSET) &&
  3699. (internalLevel - 1 <= MemDbEnum->EndLevel)
  3700. ) {
  3701. tempKeyIndex = BinTreeEnumFirst (treeEnumNode, &treeEnumContext);
  3702. if (tempKeyIndex != INVALID_OFFSET) {
  3703. minLevel ++;
  3704. internalLevel ++;
  3705. // put them in the grow buffer
  3706. gbAddress = GbGrow (&(MemDbEnum->TreeEnumBuffer), SIZEOF(UINT)+SIZEOF(UINT));
  3707. if (gbAddress) {
  3708. *((PUINT) (gbAddress)) = tempKeyIndex;
  3709. *((PUINT) (gbAddress+SIZEOF(UINT))) = treeEnumContext;
  3710. }
  3711. tempKeyStruct = GetKeyStruct (tempKeyIndex);
  3712. MYASSERT (tempKeyStruct);
  3713. pAddKeyToEnumStruct (MemDbEnum, tempKeyStruct->KeyName);
  3714. treeEnumNode = tempKeyStruct->NextLevelTree;
  3715. } else {
  3716. treeEnumNode = INVALID_OFFSET;
  3717. }
  3718. }
  3719. }
  3720. }
  3721. } else {
  3722. // we are about to start the tree enumeration
  3723. // let's start the enumeration and push the
  3724. // context data in our buffer
  3725. treeEnumNode = MemDbEnum->CurrentIndex;
  3726. while ((treeEnumNode != INVALID_OFFSET) &&
  3727. (internalLevel <= MemDbEnum->EndLevel)
  3728. ) {
  3729. tempKeyIndex = BinTreeEnumFirst (treeEnumNode, &treeEnumContext);
  3730. if (tempKeyIndex != INVALID_OFFSET) {
  3731. minLevel ++;
  3732. internalLevel ++;
  3733. // put them in the grow buffer
  3734. gbAddress = GbGrow (&(MemDbEnum->TreeEnumBuffer), SIZEOF(UINT)+SIZEOF(UINT));
  3735. if (gbAddress) {
  3736. *((PUINT) (gbAddress)) = tempKeyIndex;
  3737. *((PUINT) (gbAddress+SIZEOF(UINT))) = treeEnumContext;
  3738. }
  3739. tempKeyStruct = GetKeyStruct (tempKeyIndex);
  3740. MYASSERT (tempKeyStruct);
  3741. pAddKeyToEnumStruct (MemDbEnum, tempKeyStruct->KeyName);
  3742. treeEnumNode = tempKeyStruct->NextLevelTree;
  3743. } else {
  3744. treeEnumNode = INVALID_OFFSET;
  3745. }
  3746. }
  3747. }
  3748. if (MemDbEnum->TreeEnumBuffer.End == 0) {
  3749. // we can't back out any more, we're done
  3750. break;
  3751. }
  3752. if (MemDbEnum->PatternStruct.PatternMatch) {
  3753. MYASSERT (MemDbEnum->PatternStruct.Data);
  3754. patternMatch =
  3755. MemDbEnum->PatternStruct.PatternMatch (
  3756. MemDbEnum->PatternStruct.Data,
  3757. MemDbEnum->KeyNameCopy
  3758. );
  3759. } else {
  3760. patternMatch = IsPatternMatchW (
  3761. MemDbEnum->PatternCopy,
  3762. MemDbEnum->KeyNameCopy
  3763. );
  3764. }
  3765. }
  3766. }
  3767. if (MemDbEnum->TreeEnumLevel == MemDbEnum->TreeEnumBuffer.End) {
  3768. break;
  3769. }
  3770. MYASSERT (MemDbEnum->TreeEnumLevel < MemDbEnum->TreeEnumBuffer.End);
  3771. // now implement segment by segment enumeration because we
  3772. // just created a full key that matches the pattern
  3773. MemDbEnum->CurrentLevel ++;
  3774. shouldReturn = pCheckEnumConditions (
  3775. *((PUINT) (MemDbEnum->TreeEnumBuffer.Buf+MemDbEnum->TreeEnumLevel)),
  3776. MemDbEnum
  3777. );
  3778. MemDbEnum->TreeEnumLevel += (SIZEOF(UINT)+SIZEOF(UINT));
  3779. result = TRUE;
  3780. } else {
  3781. result = FALSE;
  3782. if (!MemDbEnum->PatternEndPtr) {
  3783. //we are done, no more segments
  3784. break;
  3785. }
  3786. MemDbEnum->PatternPtr = MemDbEnum->PatternEndPtr;
  3787. MemDbEnum->PatternEndPtr = wcschr (MemDbEnum->PatternPtr, L'\\');
  3788. if (MemDbEnum->PatternEndPtr) {
  3789. *MemDbEnum->PatternEndPtr = 0;
  3790. }
  3791. if (MemDbEnum->PatternStruct.PatternFind) {
  3792. patternFound =
  3793. MemDbEnum->PatternStruct.PatternFind (
  3794. MemDbEnum->PatternPtr
  3795. );
  3796. } else {
  3797. patternFound = (wcschr (MemDbEnum->PatternPtr, L'*') ||
  3798. wcschr (MemDbEnum->PatternPtr, L'?')
  3799. );
  3800. }
  3801. if (patternFound) {
  3802. MemDbEnum->EnumerationMode = TRUE;
  3803. if (MemDbEnum->PatternEndPtr) {
  3804. *MemDbEnum->PatternEndPtr = L'\\';
  3805. MemDbEnum->PatternEndPtr++;
  3806. }
  3807. } else {
  3808. tempKeyIndex = FindKeyStructInTree (
  3809. MemDbEnum->CurrentIndex,
  3810. MemDbEnum->PatternPtr,
  3811. FALSE
  3812. );
  3813. if (tempKeyIndex == INVALID_OFFSET) {
  3814. // we are done, the segment we look for does not exist
  3815. break;
  3816. }
  3817. tempKeyStruct = GetKeyStruct (tempKeyIndex);
  3818. MYASSERT (tempKeyStruct);
  3819. pAddKeyToEnumStruct (MemDbEnum, tempKeyStruct->KeyName);
  3820. MemDbEnum->CurrentIndex = tempKeyStruct->NextLevelTree;
  3821. MemDbEnum->CurrentLevel ++;
  3822. if (MemDbEnum->PatternEndPtr) {
  3823. *MemDbEnum->PatternEndPtr = L'\\';
  3824. MemDbEnum->PatternEndPtr++;
  3825. }
  3826. patternMatch = IsPatternMatchW (
  3827. MemDbEnum->PatternCopy,
  3828. MemDbEnum->KeyNameCopy
  3829. );
  3830. shouldReturn = patternMatch && pCheckEnumConditions (
  3831. tempKeyIndex,
  3832. MemDbEnum
  3833. );
  3834. result = TRUE;
  3835. }
  3836. }
  3837. }
  3838. return result;
  3839. }
  3840. BOOL
  3841. RealMemDbEnumFirstExW (
  3842. IN OUT PMEMDB_ENUMW MemDbEnum,
  3843. IN PCWSTR EnumPattern,
  3844. IN UINT EnumFlags,
  3845. IN UINT BeginLevel,
  3846. IN UINT EndLevel,
  3847. IN PMEMDB_PATTERNSTRUCTW PatternStruct OPTIONAL
  3848. )
  3849. {
  3850. BOOL result = FALSE;
  3851. PCWSTR subPattern;
  3852. if (!g_Initialized) {
  3853. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  3854. return result;
  3855. }
  3856. MYASSERT (g_MemDbPool);
  3857. EnterCriticalSection (&g_MemDbCs);
  3858. __try {
  3859. subPattern = SelectHiveW (EnumPattern);
  3860. if (!subPattern) {
  3861. __leave;
  3862. }
  3863. ZeroMemory (MemDbEnum, SIZEOF (MEMDB_ENUMW));
  3864. MemDbEnum->CurrentDatabaseIndex = GetCurrentDatabaseIndex ();
  3865. MemDbEnum->EnumFlags = EnumFlags;
  3866. MemDbEnum->PatternCopy = DuplicateTextExW (g_MemDbPool, subPattern, 0, NULL);
  3867. if (!MemDbEnum->PatternCopy) {
  3868. __leave;
  3869. }
  3870. MemDbEnum->PatternPtr = MemDbEnum->PatternCopy;
  3871. MemDbEnum->PatternEndPtr = MemDbEnum->PatternPtr;
  3872. MemDbEnum->CurrentIndex = g_CurrentDatabase->FirstLevelTree;
  3873. MemDbEnum->BeginLevel = BeginLevel;
  3874. if (MemDbEnum->BeginLevel == ENUMLEVEL_LASTLEVEL) {
  3875. MemDbEnum->EndLevel = ENUMLEVEL_ALLLEVELS;
  3876. } else {
  3877. MemDbEnum->EndLevel = EndLevel;
  3878. if (MemDbEnum->EndLevel < MemDbEnum->BeginLevel) {
  3879. MemDbEnum->EndLevel = MemDbEnum->BeginLevel;
  3880. }
  3881. }
  3882. MemDbEnum->CurrentLevel = 0;
  3883. if (PatternStruct) {
  3884. MemDbEnum->PatternStruct.PatternFind = PatternStruct->PatternFind;
  3885. MemDbEnum->PatternStruct.PatternMatch = PatternStruct->PatternMatch;
  3886. MemDbEnum->PatternStruct.Data = PatternStruct->Data;
  3887. }
  3888. result = pMemDbEnumNextW (MemDbEnum);
  3889. if (!result) {
  3890. MemDbAbortEnumW (MemDbEnum);
  3891. }
  3892. }
  3893. __finally {
  3894. LeaveCriticalSection (&g_MemDbCs);
  3895. }
  3896. return result;
  3897. }
  3898. BOOL
  3899. RealMemDbEnumFirstExA (
  3900. IN OUT PMEMDB_ENUMA MemDbEnum,
  3901. IN PCSTR EnumPattern,
  3902. IN UINT EnumFlags,
  3903. IN UINT BeginLevel,
  3904. IN UINT EndLevel,
  3905. IN PMEMDB_PATTERNSTRUCTW PatternStruct OPTIONAL
  3906. )
  3907. {
  3908. BOOL result = FALSE;
  3909. PCWSTR unicodeStr;
  3910. unicodeStr = ConvertAtoW (EnumPattern);
  3911. if (!unicodeStr) {
  3912. return FALSE;
  3913. }
  3914. result = RealMemDbEnumFirstExW (
  3915. &(MemDbEnum->UnicodeEnum),
  3916. unicodeStr,
  3917. EnumFlags,
  3918. BeginLevel,
  3919. EndLevel,
  3920. PatternStruct
  3921. );
  3922. if (result) {
  3923. KnownSizeWtoA (MemDbEnum->FullKeyName, MemDbEnum->UnicodeEnum.FullKeyName);
  3924. KnownSizeWtoA (MemDbEnum->KeyName, MemDbEnum->UnicodeEnum.KeyName);
  3925. MemDbEnum->Value = MemDbEnum->UnicodeEnum.Value;
  3926. MemDbEnum->Flags = MemDbEnum->UnicodeEnum.Flags;
  3927. MemDbEnum->KeyHandle = MemDbEnum->UnicodeEnum.KeyHandle;
  3928. MemDbEnum->EndPoint = MemDbEnum->UnicodeEnum.EndPoint;
  3929. }
  3930. FreeConvertedStr (unicodeStr);
  3931. return result;
  3932. }
  3933. BOOL
  3934. RealMemDbEnumNextW (
  3935. IN OUT PMEMDB_ENUMW MemDbEnum
  3936. )
  3937. {
  3938. BOOL result = FALSE;
  3939. if (!g_Initialized) {
  3940. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  3941. return result;
  3942. }
  3943. MYASSERT (g_MemDbPool);
  3944. EnterCriticalSection (&g_MemDbCs);
  3945. __try {
  3946. if (!SelectDatabase (MemDbEnum->CurrentDatabaseIndex)) {
  3947. __leave;
  3948. }
  3949. result = pMemDbEnumNextW (MemDbEnum);
  3950. if (!result) {
  3951. MemDbAbortEnumW (MemDbEnum);
  3952. }
  3953. }
  3954. __finally {
  3955. LeaveCriticalSection (&g_MemDbCs);
  3956. }
  3957. return result;
  3958. }
  3959. BOOL
  3960. RealMemDbEnumNextA (
  3961. IN OUT PMEMDB_ENUMA MemDbEnum
  3962. )
  3963. {
  3964. BOOL result = FALSE;
  3965. result = RealMemDbEnumNextW (&(MemDbEnum->UnicodeEnum));
  3966. if (result) {
  3967. KnownSizeWtoA (MemDbEnum->FullKeyName, MemDbEnum->UnicodeEnum.FullKeyName);
  3968. KnownSizeWtoA (MemDbEnum->KeyName, MemDbEnum->UnicodeEnum.KeyName);
  3969. MemDbEnum->Value = MemDbEnum->UnicodeEnum.Value;
  3970. MemDbEnum->Flags = MemDbEnum->UnicodeEnum.Flags;
  3971. MemDbEnum->KeyHandle = MemDbEnum->UnicodeEnum.KeyHandle;
  3972. MemDbEnum->EndPoint = MemDbEnum->UnicodeEnum.EndPoint;
  3973. }
  3974. return result;
  3975. }
  3976. BOOL
  3977. MemDbAbortEnumW (
  3978. IN OUT PMEMDB_ENUMW MemDbEnum
  3979. )
  3980. {
  3981. if (MemDbEnum->KeyNameCopy) {
  3982. MemDbReleaseMemory (MemDbEnum->KeyNameCopy);
  3983. }
  3984. if (MemDbEnum->PatternCopy) {
  3985. MemDbReleaseMemory (MemDbEnum->PatternCopy);
  3986. }
  3987. GbFree (&(MemDbEnum->TreeEnumBuffer));
  3988. ZeroMemory (MemDbEnum, SIZEOF (MEMDB_ENUMW));
  3989. return TRUE;
  3990. }
  3991. BOOL
  3992. MemDbAbortEnumA (
  3993. IN OUT PMEMDB_ENUMA MemDbEnum
  3994. )
  3995. {
  3996. MemDbAbortEnumW (&(MemDbEnum->UnicodeEnum));
  3997. ZeroMemory (MemDbEnum, SIZEOF (MEMDB_ENUMA));
  3998. return TRUE;
  3999. }
  4000. BOOL
  4001. MemDbSetInsertionOrderedA (
  4002. IN PCSTR Key
  4003. )
  4004. /*++
  4005. Routine Description:
  4006. MemDbSetInsertionOrderedA sets the enumeration order of the children of Key
  4007. to be in the order they were inserted.
  4008. Arguments:
  4009. Key - key to make insertion ordered
  4010. Return Value:
  4011. TRUE if successful, FALSE otherwise.
  4012. --*/
  4013. {
  4014. PCWSTR unicodeKey;
  4015. BOOL b = FALSE;
  4016. unicodeKey = ConvertAtoW (Key);
  4017. if (unicodeKey) {
  4018. b = MemDbSetInsertionOrderedW (unicodeKey);
  4019. FreeConvertedStr (unicodeKey);
  4020. }
  4021. return b;
  4022. }
  4023. BOOL
  4024. MemDbSetInsertionOrderedW (
  4025. IN PCWSTR Key
  4026. )
  4027. /*++
  4028. Routine Description:
  4029. MemDbSetInsertionOrderedW sets the enumeration order of the children of Key
  4030. to be in the order they were inserted.
  4031. Arguments:
  4032. Key - key to make insertion ordered
  4033. Return Value:
  4034. TRUE if successful, FALSE otherwise.
  4035. --*/
  4036. {
  4037. UINT keyIndex;
  4038. PCWSTR subKey;
  4039. BOOL b = FALSE;
  4040. if (!g_Initialized) {
  4041. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  4042. return b;
  4043. }
  4044. MYASSERT (g_MemDbPool);
  4045. EnterCriticalSection (&g_MemDbCs);
  4046. __try {
  4047. subKey = SelectHiveW (Key);
  4048. if (!subKey) {
  4049. __leave;
  4050. }
  4051. keyIndex = FindKeyStruct (subKey);
  4052. if (keyIndex == INVALID_OFFSET) {
  4053. __leave;
  4054. }
  4055. b = KeyStructSetInsertionOrdered(GetKeyStruct(keyIndex));
  4056. }
  4057. __finally {
  4058. #ifdef DEBUG
  4059. if (g_DatabaseCheckLevel) {
  4060. CheckDatabase (g_DatabaseCheckLevel);
  4061. }
  4062. #endif
  4063. LeaveCriticalSection (&g_MemDbCs);
  4064. }
  4065. return b;
  4066. }
  4067. BOOL
  4068. MemDbSetInsertionOrderedByKeyHandle (
  4069. IN KEYHANDLE KeyHandle
  4070. )
  4071. /*++
  4072. Routine Description:
  4073. MemDbSetInsertionOrderedByKeyHandle sets the enumeration order of the children of
  4074. KeyHandle to be in the order they were inserted.
  4075. Arguments:
  4076. KeyHandle - Specifies the key using the key handle
  4077. Return Value:
  4078. TRUE if successful, FALSE otherwise.
  4079. --*/
  4080. {
  4081. BYTE dbIndex;
  4082. BOOL b = FALSE;
  4083. if (!g_Initialized) {
  4084. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  4085. return b;
  4086. }
  4087. MYASSERT (g_MemDbPool);
  4088. EnterCriticalSection (&g_MemDbCs);
  4089. __try {
  4090. dbIndex = GET_DATABASE (KeyHandle);
  4091. if (!SelectDatabase (dbIndex)) {
  4092. __leave;
  4093. }
  4094. b = KeyStructSetInsertionOrdered (GetKeyStruct(GET_INDEX (KeyHandle)));
  4095. }
  4096. __finally {
  4097. #ifdef DEBUG
  4098. if (g_DatabaseCheckLevel) {
  4099. CheckDatabase (g_DatabaseCheckLevel);
  4100. }
  4101. #endif
  4102. LeaveCriticalSection (&g_MemDbCs);
  4103. }
  4104. return b;
  4105. }
  4106. BOOL
  4107. MemDbMoveKeyHandleToEnd (
  4108. IN KEYHANDLE KeyHandle
  4109. )
  4110. {
  4111. BYTE dbIndex;
  4112. UINT keyIndex;
  4113. PKEYSTRUCT keyStruct;
  4114. UINT parentIndex;
  4115. PKEYSTRUCT parentKeyStruct;
  4116. UINT treeOffset;
  4117. BOOL b = FALSE;
  4118. if (!g_Initialized) {
  4119. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  4120. return b;
  4121. }
  4122. MYASSERT (g_MemDbPool);
  4123. EnterCriticalSection (&g_MemDbCs);
  4124. __try {
  4125. dbIndex = GET_DATABASE (KeyHandle);
  4126. if (!SelectDatabase (dbIndex)) {
  4127. __leave;
  4128. }
  4129. keyIndex = GET_INDEX (KeyHandle);
  4130. if (keyIndex == INVALID_OFFSET) {
  4131. __leave;
  4132. }
  4133. keyStruct = GetKeyStruct (keyIndex);
  4134. if (!keyStruct) {
  4135. __leave;
  4136. }
  4137. parentIndex = keyStruct->PrevLevelIndex;
  4138. if (parentIndex == INVALID_OFFSET) {
  4139. __leave;
  4140. }
  4141. parentKeyStruct = GetKeyStruct (parentIndex);
  4142. if (!parentKeyStruct) {
  4143. __leave;
  4144. }
  4145. if (!KeyStructSetInsertionOrdered (parentKeyStruct)) {
  4146. __leave;
  4147. }
  4148. // reloading key struct and parent key struct
  4149. keyStruct = GetKeyStruct (keyIndex);
  4150. if (!keyStruct) {
  4151. __leave;
  4152. }
  4153. parentKeyStruct = GetKeyStruct (parentIndex);
  4154. if (!parentKeyStruct) {
  4155. __leave;
  4156. }
  4157. treeOffset = parentKeyStruct->NextLevelTree;
  4158. if (treeOffset == INVALID_OFFSET) {
  4159. __leave;
  4160. }
  4161. if (!BinTreeDeleteNode (treeOffset, keyStruct->KeyName, NULL)) {
  4162. __leave;
  4163. }
  4164. if (!BinTreeAddNode (treeOffset, keyIndex)) {
  4165. __leave;
  4166. }
  4167. b = TRUE;
  4168. }
  4169. __finally {
  4170. #ifdef DEBUG
  4171. if (g_DatabaseCheckLevel) {
  4172. CheckDatabase (g_DatabaseCheckLevel);
  4173. }
  4174. #endif
  4175. LeaveCriticalSection (&g_MemDbCs);
  4176. }
  4177. return b;
  4178. }
  4179. PCBYTE
  4180. MemDbGetDatabaseAddress (
  4181. VOID
  4182. )
  4183. {
  4184. PCBYTE result = NULL;
  4185. if (!g_Initialized) {
  4186. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  4187. return result;
  4188. }
  4189. MYASSERT (g_MemDbPool);
  4190. EnterCriticalSection (&g_MemDbCs);
  4191. if (SelectDatabase(0)) {
  4192. result = g_CurrentDatabase->Buf;
  4193. }
  4194. LeaveCriticalSection (&g_MemDbCs);
  4195. return result;
  4196. }
  4197. UINT
  4198. MemDbGetDatabaseSize (
  4199. VOID
  4200. )
  4201. /*++
  4202. Routine Description:
  4203. MemDbGetDatabaseSize returns the size of the permanent database
  4204. Arguments:
  4205. None.
  4206. Return Value:
  4207. The size of the permanent database.
  4208. --*/
  4209. {
  4210. UINT result = 0;
  4211. if (!g_Initialized) {
  4212. DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
  4213. return result;
  4214. }
  4215. MYASSERT (g_MemDbPool);
  4216. EnterCriticalSection (&g_MemDbCs);
  4217. if (SelectDatabase(0)) {
  4218. result = g_CurrentDatabase->End;
  4219. }
  4220. LeaveCriticalSection (&g_MemDbCs);
  4221. return result;
  4222. }
  4223. #ifdef DEBUG
  4224. BOOL
  4225. MemDbCheckDatabase(
  4226. UINT Level
  4227. )
  4228. /*++
  4229. Routine Description:
  4230. MemDbCheckDatabase enumerates the entire database and verifies that each
  4231. enumerated key can be found in the hash table.
  4232. Arguments:
  4233. Level - Specifies database check level
  4234. Return Value:
  4235. TRUE if the database is valid, FALSE otherwise.
  4236. --*/
  4237. {
  4238. MYASSERT (g_MemDbPool);
  4239. return (CheckDatabase(Level) && CheckLevel(g_CurrentDatabase->FirstLevelTree, INVALID_OFFSET));
  4240. }
  4241. #endif