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.

1129 lines
27 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. Apitest.c
  5. Abstract:
  6. This module contains the function test for the Win32 Registry API.
  7. Author:
  8. David J. Gilman (davegi) 28-Dec-1991
  9. Environment:
  10. Windows, Crt - User Mode
  11. Notes:
  12. This test can be compiled for Unicode by defining the compiler symbol
  13. UNICODE.
  14. Since this is a test program it relies on assertions for error checking
  15. rather than a more robust mechanism.
  16. --*/
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <windows.h>
  21. #include "crtools.h"
  22. #define HKEY_ROOT HKEY_CURRENT_USER
  23. #define SAVE_RESTORE_FILE TEXT( "srkey.reg" )
  24. #define KEY_PATH \
  25. TEXT( "TestUser1\\TestUser1_1\\TestUser1_2" )
  26. #define PREDEFINED_HANDLE HKEY_USERS
  27. #define PREDEFINED_HANDLE_STRING \
  28. TEXT( "HKEY_USERS\\.Default\\TestUser1" )
  29. #define KEY_NAME_1 TEXT( "TestUser1" )
  30. #define KEY_NAME_1_TITLE_INDEX ( 0 )
  31. #define KEY_NAME_1_CLASS TEXT( "Test User Class" )
  32. #define KEY_NAME_1_CLASS_LENGTH LENGTH( KEY_NAME_1_CLASS )
  33. #define KEY_NAME_1_1 TEXT( "TestUser1_1" )
  34. #define KEY_NAME_1_1_LENGTH LENGTH( KEY_NAME_1_1 )
  35. #define KEY_NAME_1_1_TITLE_INDEX ( 0 )
  36. #define KEY_NAME_1_1_CLASS TEXT( "Test User Class" )
  37. #define KEY_NAME_1_1_CLASS_LENGTH LENGTH( KEY_NAME_1_1_CLASS )
  38. #define KEY_NAME_1_2 TEXT( "TestUser1_2" )
  39. #define KEY_NAME_1_2_LENGTH LENGTH( KEY_NAME_1_2 )
  40. #define KEY_NAME_1_2_TITLE_INDEX (0 )
  41. #define KEY_NAME_1_2_CLASS TEXT( "Test User Class" )
  42. #define KEY_NAME_1_2_CLASS_LENGTH LENGTH( KEY_NAME_1_2_CLASS )
  43. #define VALUE_NAME_1 TEXT( "One" )
  44. #define VALUE_NAME_1_LENGTH LENGTH( VALUE_NAME_1 )
  45. #define VALUE_NAME_1_TITLE_INDEX 0
  46. #define VALUE_DATA_1 "Number One"
  47. #define VALUE_DATA_1_LENGTH 11
  48. #define VALUE_DATA_1_TYPE REG_SZ
  49. #define VALUE_NAME_2 TEXT( "Second" )
  50. #define VALUE_NAME_2_LENGTH LENGTH( VALUE_NAME_2 )
  51. #define VALUE_NAME_2_TITLE_INDEX ( 0 )
  52. #define VALUE_DATA_2 ( 2 )
  53. #define VALUE_DATA_2_LENGTH ( sizeof( VALUE_DATA_2 ))
  54. #define VALUE_DATA_2_TYPE REG_DWORD
  55. #define MAX_DATA_LENGTH ( 32 )
  56. //
  57. // Root handle for apitest's nodes.
  58. //
  59. HKEY RootHandle;
  60. //
  61. // Error and informational messages.
  62. //
  63. PSTR UsageMessage =
  64. "Usage: apitest [-?] [-q] [\\machinename]\n";
  65. PSTR HelpMessage =
  66. "\n where:\n" \
  67. " -? - display this message.\n" \
  68. " -q - quiet - suppresses all output\n" \
  69. " machinename - remote machine.\n";
  70. PSTR InvalidSwitchMessage =
  71. "Invalid switch - %s\n";
  72. PSTR InvalidMachineNameMessage =
  73. "Invalid machine name - %s\n";
  74. //
  75. // Event handle used for synchronization.
  76. //
  77. HANDLE _EventHandle;
  78. HANDLE _EventHandle1;
  79. HANDLE _EventHandle2;
  80. BOOL Quiet;
  81. VOID
  82. DeleteTree(
  83. IN HKEY KeyHandle
  84. )
  85. {
  86. LONG Error;
  87. DWORD Index;
  88. HKEY ChildHandle;
  89. TSTR KeyName[ MAX_PATH ];
  90. DWORD KeyNameLength;
  91. TSTR ClassName[ MAX_PATH ];
  92. DWORD ClassNameLength;
  93. DWORD TitleIndex;
  94. DWORD NumberOfSubKeys;
  95. DWORD MaxSubKeyLength;
  96. DWORD MaxClassLength;
  97. DWORD NumberOfValues;
  98. DWORD MaxValueNameLength;
  99. DWORD MaxValueDataLength;
  100. DWORD SecurityDescriptorLength;
  101. FILETIME LastWriteTime;
  102. ClassNameLength = MAX_PATH;
  103. Error = RegQueryInfoKey(
  104. KeyHandle,
  105. ClassName,
  106. &ClassNameLength,
  107. NULL,
  108. &NumberOfSubKeys,
  109. &MaxSubKeyLength,
  110. &MaxClassLength,
  111. &NumberOfValues,
  112. &MaxValueNameLength,
  113. &MaxValueDataLength,
  114. &SecurityDescriptorLength,
  115. &LastWriteTime
  116. );
  117. REG_API_SUCCESS( RegQueryInfoKey );
  118. for( Index = 0; Index < NumberOfSubKeys; Index++ ) {
  119. KeyNameLength = MAX_PATH;
  120. Error = RegEnumKey(
  121. KeyHandle,
  122. 0,
  123. // Index,
  124. KeyName,
  125. KeyNameLength
  126. );
  127. REG_API_SUCCESS( RegEnumKey );
  128. Error = RegOpenKey(
  129. KeyHandle,
  130. KeyName,
  131. &ChildHandle
  132. );
  133. REG_API_SUCCESS( RegOpenKey );
  134. DeleteTree( ChildHandle );
  135. Error = RegCloseKey(
  136. ChildHandle
  137. );
  138. REG_API_SUCCESS( RegCloseKey );
  139. Error = RegDeleteKey(
  140. KeyHandle,
  141. KeyName
  142. );
  143. REG_API_SUCCESS( RegDeleteKey );
  144. }
  145. }
  146. VOID
  147. DeleteTestTree(
  148. )
  149. {
  150. LONG Error;
  151. HKEY KeyHandle;
  152. Error = RegOpenKey(
  153. RootHandle,
  154. KEY_NAME_1,
  155. &KeyHandle
  156. );
  157. if( Error == ERROR_SUCCESS ) {
  158. DeleteTree( KeyHandle );
  159. Error = RegCloseKey(
  160. KeyHandle
  161. );
  162. REG_API_SUCCESS( RegCloseKey );
  163. Error = RegDeleteKey(
  164. RootHandle,
  165. KEY_NAME_1
  166. );
  167. REG_API_SUCCESS( RegDeleteKey );
  168. }
  169. }
  170. DWORD
  171. NotifyThread(
  172. LPVOID Parameters
  173. )
  174. {
  175. LONG Error;
  176. BOOL ErrorFlag;
  177. HANDLE EventHandle;
  178. UNREFERENCED_PARAMETER( Parameters );
  179. //
  180. // Create the notification event.
  181. //
  182. EventHandle = CreateEvent(
  183. NULL,
  184. FALSE,
  185. FALSE,
  186. NULL
  187. );
  188. ASSERT( EventHandle != NULL );
  189. //
  190. // Set-up an asynchronous notify.
  191. //
  192. Error = RegNotifyChangeKeyValue(
  193. RootHandle,
  194. FALSE,
  195. REG_LEGAL_CHANGE_FILTER,
  196. EventHandle,
  197. TRUE
  198. );
  199. REG_API_SUCCESS( RegNotifyChangeKeyValue );
  200. //
  201. // Release the main thread.
  202. //
  203. ErrorFlag = SetEvent( _EventHandle );
  204. ASSERT( ErrorFlag == TRUE );
  205. //
  206. // Wait for a notification.
  207. //
  208. Error = (LONG)WaitForSingleObject( EventHandle, (DWORD)-1 );
  209. ASSERT( Error == 0 );
  210. if( ! Quiet ) {
  211. printf( "First notification triggered\n" );
  212. }
  213. CloseHandle( EventHandle );
  214. EventHandle = CreateEvent(
  215. NULL,
  216. FALSE,
  217. FALSE,
  218. NULL
  219. );
  220. ASSERT( EventHandle != NULL );
  221. //
  222. // Set-up an asynchronous notify.
  223. //
  224. Error = RegNotifyChangeKeyValue(
  225. RootHandle,
  226. FALSE,
  227. REG_LEGAL_CHANGE_FILTER,
  228. EventHandle,
  229. TRUE
  230. );
  231. REG_API_SUCCESS( RegNotifyChangeKeyValue );
  232. //
  233. // Release the main thread.
  234. //
  235. ErrorFlag = SetEvent( _EventHandle1 );
  236. ASSERT( ErrorFlag == TRUE );
  237. //
  238. // Wait for a notification.
  239. //
  240. Error = (LONG)WaitForSingleObject( EventHandle, (DWORD)-1 );
  241. ASSERT( Error == 0 );
  242. if( ! Quiet ) {
  243. printf( "Second notification triggered\n" );
  244. }
  245. CloseHandle( EventHandle );
  246. ErrorFlag = SetEvent( _EventHandle2 );
  247. ASSERT( ErrorFlag == TRUE );
  248. #endif
  249. return ( DWORD ) TRUE;
  250. }
  251. VOID
  252. main(
  253. INT argc,
  254. PCHAR argv[ ]
  255. )
  256. {
  257. LONG Error;
  258. BOOL ErrorFlag;
  259. DWORD Index;
  260. PTSTR MachineName;
  261. PKEY Key;
  262. TSTR NameString[ MAX_PATH ];
  263. HANDLE NotifyThreadHandle;
  264. DWORD ThreadID;
  265. HKEY PredefinedHandle;
  266. HKEY Handle1;
  267. HKEY Handle1_1;
  268. HKEY Handle1_2;
  269. PSECURITY_DESCRIPTOR SecurityDescriptor;
  270. SECURITY_ATTRIBUTES SecurityAttributes;
  271. DWORD Disposition;
  272. TSTR KeyName[ MAX_PATH ];
  273. DWORD KeyNameLength;
  274. TSTR ClassName[ MAX_PATH ];
  275. DWORD ClassNameLength;
  276. DWORD NumberOfSubKeys;
  277. DWORD MaxSubKeyLength;
  278. DWORD MaxClassLength;
  279. DWORD NumberOfValues;
  280. DWORD MaxValueNameLength;
  281. DWORD MaxValueDataLength;
  282. DWORD SecurityDescriptorLength;
  283. FILETIME LastWriteTime;
  284. TSTR ValueName[ MAX_PATH ];
  285. DWORD ValueNameLength;
  286. BYTE Data[ MAX_DATA_LENGTH ];
  287. DWORD DataLength;
  288. BYTE Data_1[ ] = VALUE_DATA_1;
  289. DWORD Data_2 = VALUE_DATA_2;
  290. DWORD TitleIndex;
  291. DWORD Type;
  292. UNREFERENCED_PARAMETER( argc );
  293. //
  294. // By default, be verbose and operate on the local machine.
  295. //
  296. Quiet = FALSE;
  297. MachineName = NULL;
  298. //
  299. // Initialize options based on the command line.
  300. //
  301. while( *++argv ) {
  302. //
  303. // If the command line argument is a switch character...
  304. //
  305. if( isswitch(( *argv )[ 0 ] )) {
  306. switch( tolower(( *argv )[ 1 ] )) {
  307. //
  308. // Display the detailed help message and quit.
  309. //
  310. case '?':
  311. DisplayMessage( FALSE, UsageMessage );
  312. DisplayMessage( TRUE, HelpMessage );
  313. break;
  314. //
  315. // Quiet - no output.
  316. //
  317. case 'q':
  318. Quiet = TRUE;
  319. break;
  320. //
  321. // Display invalid switch message and quit.
  322. //
  323. default:
  324. DisplayMessage( FALSE, InvalidSwitchMessage, *argv );
  325. DisplayMessage( TRUE, UsageMessage );
  326. }
  327. } else {
  328. MachineName = *argv;
  329. }
  330. }
  331. //
  332. // If a machine name was passed on the command line, connect to
  333. // the Registry on that machine else use the local Registry.
  334. // In either case construct a string representation of the
  335. // test's main key (i.e. \\machine\HKEY_USERS\.Default\TestUser1 or
  336. // HKEY_USERS\.Default\TestUser1.
  337. //
  338. if( MachineName ) {
  339. Error = RegConnectRegistry(
  340. MachineName,
  341. PREDEFINED_HANDLE,
  342. &PredefinedHandle
  343. );
  344. REG_API_SUCCESS( RegConnectRegistry );
  345. strcpy( NameString, MachineName );
  346. strcat( NameString, "\\\\" );
  347. strcat( NameString, PREDEFINED_HANDLE_STRING );
  348. } else {
  349. PredefinedHandle = PREDEFINED_HANDLE;
  350. strcpy( NameString, PREDEFINED_HANDLE_STRING );
  351. }
  352. //
  353. // Open ".Default" key as the root for the remainder of the test.
  354. //
  355. Error = RegOpenKeyEx(
  356. PredefinedHandle,
  357. ".Default",
  358. REG_OPTION_RESERVED,
  359. MAXIMUM_ALLOWED,
  360. &RootHandle
  361. );
  362. REG_API_SUCCESS( RegOpenKeyEx );
  363. //
  364. // Predefined handle is no longer needed.
  365. //
  366. Error = RegCloseKey(
  367. PredefinedHandle
  368. );
  369. REG_API_SUCCESS( RegCloseKey );
  370. //
  371. // Delete the save / restore file (in case it exists from a previous
  372. // run of the test) as RegSaveKey requires a new file.
  373. //
  374. DeleteFile( SAVE_RESTORE_FILE );
  375. //
  376. // Remove any leftover keys from previous runs of this test.
  377. //
  378. DeleteTestTree( );
  379. //
  380. // Use the Win 3.1 API (which calls the Win32 API) to create a path.
  381. //
  382. Error = RegCreateKey(
  383. RootHandle,
  384. KEY_PATH,
  385. &Handle1
  386. );
  387. REG_API_SUCCESS( RegCreateKey );
  388. //
  389. // Close the key so the delete (DeleteTestTree) will work.
  390. //
  391. Error = RegCloseKey(
  392. Handle1
  393. );
  394. REG_API_SUCCESS( RegCloseKey );
  395. //
  396. // Remove the path.
  397. //
  398. DeleteTestTree( );
  399. //
  400. // Create the synchronization event.
  401. //
  402. _EventHandle = CreateEvent(
  403. NULL,
  404. FALSE,
  405. FALSE,
  406. NULL
  407. );
  408. ASSERT( _EventHandle != NULL );
  409. _EventHandle1 = CreateEvent(
  410. NULL,
  411. FALSE,
  412. FALSE,
  413. NULL
  414. );
  415. ASSERT( _EventHandle1 != NULL );
  416. _EventHandle2 = CreateEvent(
  417. NULL,
  418. FALSE,
  419. FALSE,
  420. NULL
  421. );
  422. ASSERT( _EventHandle2 != NULL );
  423. //
  424. // Create the notify thread.
  425. //
  426. NotifyThreadHandle = CreateThread(
  427. NULL,
  428. 0,
  429. NotifyThread,
  430. NULL,
  431. 0,
  432. &ThreadID
  433. );
  434. ASSERT( NotifyThreadHandle != NULL );
  435. //
  436. // Wait for the notify thread to create its event.
  437. //
  438. Error = (LONG)WaitForSingleObject( _EventHandle, (DWORD)-1 );
  439. ASSERT( Error == 0 );
  440. //
  441. // Use Win 3.1 compatible APIs to create/close, open/close and delete
  442. // the key TestUser1.
  443. //
  444. Error = RegCreateKey(
  445. RootHandle,
  446. KEY_NAME_1,
  447. &Handle1
  448. );
  449. REG_API_SUCCESS( RegCreateKey );
  450. Error = RegCloseKey(
  451. Handle1
  452. );
  453. REG_API_SUCCESS( RegCloseKey );
  454. //
  455. // Wait for the notify thread to create its event.
  456. //
  457. Error = (LONG)WaitForSingleObject( _EventHandle1, (DWORD)-1 );
  458. ASSERT( Error == 0 );
  459. Error = RegOpenKey(
  460. RootHandle,
  461. KEY_NAME_1,
  462. &Handle1
  463. );
  464. REG_API_SUCCESS( RegOpenKey );
  465. Error = RegCloseKey(
  466. Handle1
  467. );
  468. REG_API_SUCCESS( RegCloseKey );
  469. Error = RegDeleteKey(
  470. RootHandle,
  471. KEY_NAME_1
  472. );
  473. REG_API_SUCCESS( RegDeleteKey );
  474. //
  475. // Use Win32 APIs to create/close, open/close and create (open) the
  476. // key TestUser1.
  477. //
  478. //
  479. // Allocate and initialize the SecurityDescriptor.
  480. //
  481. SecurityDescriptor = malloc( sizeof( SECURITY_DESCRIPTOR ));
  482. ASSERT( SecurityDescriptor != NULL );
  483. ErrorFlag = InitializeSecurityDescriptor(
  484. SecurityDescriptor,
  485. SECURITY_DESCRIPTOR_REVISION
  486. );
  487. ASSERT( ErrorFlag == TRUE );
  488. SecurityAttributes.nLength = sizeof( SECURITY_ATTRIBUTES );
  489. SecurityAttributes.lpSecurityDescriptor = SecurityDescriptor;
  490. SecurityAttributes.bInheritHandle = FALSE;
  491. Error = RegCreateKeyEx(
  492. RootHandle,
  493. KEY_NAME_1,
  494. 0,
  495. KEY_NAME_1_CLASS,
  496. REG_OPTION_RESERVED,
  497. KEY_ALL_ACCESS,
  498. &SecurityAttributes,
  499. &Handle1,
  500. &Disposition
  501. );
  502. REG_API_SUCCESS( RegCreateKeyEx );
  503. ASSERT( Disposition == REG_CREATED_NEW_KEY );
  504. Error = RegCloseKey(
  505. Handle1
  506. );
  507. REG_API_SUCCESS( RegCloseKey );
  508. //
  509. // Wait for the notify thread to create its event.
  510. //
  511. Error = RegOpenKeyEx(
  512. RootHandle,
  513. KEY_NAME_1,
  514. REG_OPTION_RESERVED,
  515. KEY_ALL_ACCESS,
  516. &Handle1
  517. );
  518. REG_API_SUCCESS( RegOpenKeyEx );
  519. Error = RegCloseKey(
  520. Handle1
  521. );
  522. REG_API_SUCCESS( RegCloseKey );
  523. Error = RegCreateKeyEx(
  524. RootHandle,
  525. KEY_NAME_1,
  526. 0,
  527. KEY_NAME_1_CLASS,
  528. REG_OPTION_RESERVED,
  529. KEY_ALL_ACCESS,
  530. NULL,
  531. &Handle1,
  532. &Disposition
  533. );
  534. REG_API_SUCCESS( RegCreateKeyEx );
  535. ASSERT( Disposition == REG_OPENED_EXISTING_KEY );
  536. //
  537. // Get and set the key's SECURITY_DESCRIPTOR. Setting will trigger
  538. // a notification.
  539. //
  540. SecurityDescriptorLength = 0;
  541. //
  542. // Get the SECURITY_DESCRIPTOR's length.
  543. //
  544. Error = RegGetKeySecurity(
  545. Handle1,
  546. OWNER_SECURITY_INFORMATION
  547. | GROUP_SECURITY_INFORMATION
  548. | DACL_SECURITY_INFORMATION,
  549. SecurityDescriptor,
  550. &SecurityDescriptorLength
  551. );
  552. ASSERT( Error == ERROR_INSUFFICIENT_BUFFER );
  553. SecurityDescriptor = realloc(
  554. SecurityDescriptor,
  555. SecurityDescriptorLength
  556. );
  557. ASSERT( SecurityDescriptor != NULL );
  558. ErrorFlag = InitializeSecurityDescriptor(
  559. SecurityDescriptor,
  560. SECURITY_DESCRIPTOR_REVISION
  561. );
  562. ASSERT( ErrorFlag == TRUE );
  563. Error = RegSetKeySecurity(
  564. Handle1,
  565. OWNER_SECURITY_INFORMATION
  566. | GROUP_SECURITY_INFORMATION
  567. | DACL_SECURITY_INFORMATION,
  568. SecurityDescriptor
  569. );
  570. REG_API_SUCCESS( RegSetKeySecurity );
  571. Error = (LONG)WaitForSingleObject( _EventHandle2, (DWORD)-1 );
  572. ASSERT( Error == 0 );
  573. //
  574. // Reinitialize after the realloc.
  575. //
  576. SecurityAttributes.lpSecurityDescriptor = SecurityDescriptor;
  577. //
  578. // Create two sub-keys.
  579. //
  580. Error = RegCreateKeyEx(
  581. Handle1,
  582. KEY_NAME_1_1,
  583. 0,
  584. KEY_NAME_1_1_CLASS,
  585. REG_OPTION_RESERVED,
  586. KEY_ALL_ACCESS,
  587. &SecurityAttributes,
  588. &Handle1_1,
  589. &Disposition
  590. );
  591. REG_API_SUCCESS( RegCreateKeyEx );
  592. ASSERT( Disposition == REG_CREATED_NEW_KEY );
  593. Error = RegCreateKeyEx(
  594. Handle1,
  595. KEY_NAME_1_2,
  596. 0,
  597. KEY_NAME_1_2_CLASS,
  598. 0,
  599. KEY_ALL_ACCESS,
  600. &SecurityAttributes,
  601. &Handle1_2,
  602. &Disposition
  603. );
  604. REG_API_SUCCESS( RegCreateKeyEx );
  605. ASSERT( Disposition == REG_CREATED_NEW_KEY );
  606. //
  607. // Enumerate the two sub-keys using the Win 3.1 and the the Win32
  608. // enumeration APIs.
  609. //
  610. KeyNameLength = MAX_PATH;
  611. Error = RegEnumKey(
  612. Handle1,
  613. 0,
  614. KeyName,
  615. KeyNameLength
  616. );
  617. REG_API_SUCCESS( RegEnumKey );
  618. ASSERT( Compare( KeyName, KEY_NAME_1_1, KEY_NAME_1_1_LENGTH ));
  619. KeyNameLength = MAX_PATH;
  620. ClassNameLength = MAX_PATH;
  621. Error = RegEnumKeyEx(
  622. Handle1,
  623. 1,
  624. KeyName,
  625. &KeyNameLength,
  626. NULL,
  627. ClassName,
  628. &ClassNameLength,
  629. &LastWriteTime
  630. );
  631. REG_API_SUCCESS( RegEnumKeyEx );
  632. ASSERT( Compare( KeyName, KEY_NAME_1_2, KEY_NAME_1_2_LENGTH ));
  633. ASSERT( KeyNameLength == KEY_NAME_1_2_LENGTH );
  634. //ASSERT( TitleIndex == KEY_NAME_1_2_TITLE_INDEX );
  635. ASSERT( Compare( ClassName, KEY_NAME_1_2_CLASS, KEY_NAME_1_2_CLASS_LENGTH ));
  636. ASSERT( ClassNameLength == KEY_NAME_1_2_CLASS_LENGTH );
  637. //
  638. // If the Quiet command line option wasn't set, display the TestUser1 key.
  639. //
  640. if( ! Quiet ) {
  641. Key = ParseKey( NameString );
  642. REG_API_SUCCESS( Key != NULL );
  643. DisplayKeys( Key, TRUE, TRUE, TRUE );
  644. FreeKey( Key );
  645. }
  646. //
  647. // Close the two sub-keys.
  648. //
  649. Error = RegCloseKey(
  650. Handle1_1
  651. );
  652. REG_API_SUCCESS( RegCloseKey );
  653. Error = RegCloseKey(
  654. Handle1_2
  655. );
  656. REG_API_SUCCESS( RegCloseKey );
  657. Error = RegFlushKey(
  658. Handle1
  659. );
  660. REG_API_SUCCESS( RegFlushKey );
  661. //
  662. // Save the TestUser1 tree to a file.
  663. //
  664. #if 0
  665. Error = RegSaveKey(
  666. Handle1,
  667. SAVE_RESTORE_FILE,
  668. SecurityDescriptor
  669. );
  670. REG_API_SUCCESS( RegSaveKey );
  671. RegCloseKey( Handle1 );
  672. //
  673. // Delete the TestUser1 tree.
  674. //
  675. DeleteTestTree( );
  676. //
  677. // Load TestUser1 from the file
  678. //
  679. Error = RegLoadKey(
  680. RootHandle,
  681. KEY_NAME_1,
  682. SAVE_RESTORE_FILE
  683. );
  684. REG_API_SUCCESS( RegLoadKey );
  685. //
  686. // Unload TestUser1
  687. //
  688. Error = RegUnLoadKey(
  689. RootHandle,
  690. KEY_NAME_1
  691. );
  692. REG_API_SUCCESS( RegUnLoadKey );
  693. //
  694. // Restore the TestUser1 tree from a file.
  695. //
  696. Error = RegCreateKey(
  697. RootHandle,
  698. KEY_NAME_1,
  699. &Handle1
  700. );
  701. REG_API_SUCCESS( RegCreateKey );
  702. Error = RegRestoreKey(
  703. Handle1,
  704. SAVE_RESTORE_FILE,
  705. 0
  706. );
  707. REG_API_SUCCESS( RegRestoreKey );
  708. #endif
  709. //
  710. // Delete the two sub-keys.
  711. //
  712. Error = RegDeleteKey(
  713. Handle1,
  714. KEY_NAME_1_1
  715. );
  716. REG_API_SUCCESS( RegDeleteKey );
  717. Error = RegDeleteKey(
  718. Handle1,
  719. KEY_NAME_1_2
  720. );
  721. REG_API_SUCCESS( RegDeleteKey );
  722. //
  723. // Set a value in the TestUser1 key using the Win 3.1 compatible API.
  724. //
  725. Error = RegSetValue(
  726. RootHandle,
  727. KEY_NAME_1,
  728. VALUE_DATA_1_TYPE,
  729. Data_1,
  730. VALUE_DATA_1_LENGTH
  731. );
  732. REG_API_SUCCESS( RegSetValue );
  733. //
  734. // Set a value in the TestUser1 key using the Win32 API.
  735. //
  736. Error = RegSetValueEx(
  737. Handle1,
  738. VALUE_NAME_2,
  739. 0,
  740. VALUE_DATA_2_TYPE,
  741. ( PVOID ) &Data_2,
  742. VALUE_DATA_2_LENGTH
  743. );
  744. REG_API_SUCCESS( RegSetValueEx );
  745. //
  746. // Commit the Key to the Registry.
  747. //
  748. Error = RegFlushKey(
  749. Handle1
  750. );
  751. REG_API_SUCCESS( RegFlushKey );
  752. //
  753. // If the Quiet command line option wasn't set, display the TestUser1 key.
  754. //
  755. if( ! Quiet ) {
  756. Key = ParseKey( NameString );
  757. REG_API_SUCCESS( Key != NULL );
  758. DisplayKeys( Key, TRUE, TRUE, TRUE );
  759. FreeKey( Key );
  760. }
  761. //
  762. // Query a value in the TestUser1 key using the Win 3.1 compatible API.
  763. //
  764. DataLength = MAX_DATA_LENGTH;
  765. Error = RegQueryValue(
  766. RootHandle,
  767. KEY_NAME_1,
  768. Data,
  769. &DataLength
  770. );
  771. REG_API_SUCCESS( RegQueryValue );
  772. ASSERT( Compare( Data, &Data_1, VALUE_DATA_1_LENGTH ));
  773. ASSERT( DataLength == VALUE_DATA_1_LENGTH );
  774. //
  775. // Query a value in the TestUser1 key using the Win32 API.
  776. //
  777. DataLength = MAX_DATA_LENGTH;
  778. Error = RegQueryValueEx(
  779. Handle1,
  780. VALUE_NAME_2,
  781. NULL,
  782. &Type,
  783. Data,
  784. &DataLength
  785. );
  786. REG_API_SUCCESS( RegQueryValueEx );
  787. //ASSERT( TitleIndex == VALUE_NAME_2_TITLE_INDEX );
  788. ASSERT( Type == VALUE_DATA_2_TYPE );
  789. ASSERT(( DWORD ) Data[ 0 ] == Data_2 );
  790. ASSERT( DataLength == VALUE_DATA_2_LENGTH );
  791. //
  792. // Query information about the key.
  793. //
  794. ClassNameLength = MAX_PATH;
  795. Error = RegQueryInfoKey(
  796. Handle1,
  797. ClassName,
  798. &ClassNameLength,
  799. NULL,
  800. &NumberOfSubKeys,
  801. &MaxSubKeyLength,
  802. &MaxClassLength,
  803. &NumberOfValues,
  804. &MaxValueNameLength,
  805. &MaxValueDataLength,
  806. &SecurityDescriptorLength,
  807. &LastWriteTime
  808. );
  809. REG_API_SUCCESS( RegQueryInfoKey );
  810. ASSERT( Compare( ClassName, KEY_NAME_1_CLASS, KEY_NAME_1_CLASS_LENGTH ));
  811. ASSERT( ClassNameLength == KEY_NAME_1_CLASS_LENGTH );
  812. //ASSERT( TitleIndex == KEY_NAME_1_TITLE_INDEX );
  813. ASSERT( NumberOfSubKeys == 0 );
  814. ASSERT( MaxSubKeyLength == 0 );
  815. ASSERT( MaxClassLength == 0 );
  816. ASSERT( NumberOfValues == 2 );
  817. ASSERT( MaxValueNameLength == VALUE_NAME_2_LENGTH * sizeof(WCHAR) );
  818. ASSERT( MaxValueDataLength == VALUE_DATA_1_LENGTH * sizeof(WCHAR) );
  819. //
  820. // Enumerate the values.
  821. //
  822. for( Index = 0; Index < 2; Index++ ) {
  823. ValueNameLength = MAX_PATH;
  824. DataLength = MAX_DATA_LENGTH;
  825. Error = RegEnumValue(
  826. Handle1,
  827. Index,
  828. ValueName,
  829. &ValueNameLength,
  830. NULL,
  831. &Type,
  832. Data,
  833. &DataLength
  834. );
  835. REG_API_SUCCESS( RegEnumValue );
  836. //
  837. // Check specifics depending on the value being queried.
  838. //
  839. switch( Index ) {
  840. case 0:
  841. //
  842. // No name - win 3.1 compatible value.
  843. //
  844. ASSERT( ValueNameLength == 0 );
  845. //ASSERT( TitleIndex == VALUE_NAME_1_TITLE_INDEX );
  846. ASSERT( Type == VALUE_DATA_1_TYPE );
  847. ASSERT( Compare( Data, Data_1, VALUE_DATA_1_LENGTH ));
  848. ASSERT( DataLength == VALUE_DATA_1_LENGTH );
  849. break;
  850. case 1:
  851. ASSERT( Compare( ValueName, VALUE_NAME_2, VALUE_NAME_2_LENGTH ));
  852. ASSERT( ValueNameLength == VALUE_NAME_2_LENGTH );
  853. //ASSERT( TitleIndex == VALUE_NAME_2_TITLE_INDEX );
  854. ASSERT( Type == VALUE_DATA_2_TYPE );
  855. ASSERT(( DWORD ) Data[ 0 ] == Data_2 );
  856. ASSERT( DataLength == VALUE_DATA_2_LENGTH );
  857. break;
  858. default:
  859. ASSERT_MESSAGE( FALSE, "Valid value enumeration index - " );
  860. }
  861. }
  862. //
  863. // All done! Get rid of the key and close it.
  864. //
  865. Error = RegDeleteKey(
  866. RootHandle,
  867. KEY_NAME_1
  868. );
  869. REG_API_SUCCESS( RegDeleteKey );
  870. Error = RegCloseKey(
  871. Handle1
  872. );
  873. REG_API_SUCCESS( RegCloseKey );
  874. }