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.

807 lines
20 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. ctreg.c
  5. Abstract:
  6. Configuration Registry component test
  7. Needs to move from here
  8. Author:
  9. Scott Birrell (ScottBi) June 5, 1991
  10. Environment:
  11. Revision History:
  12. --*/
  13. #include <string.h>
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #define CT_REG_INITIAL_KEY_COUNT 8L
  17. #define CT_REG_INITIAL_LEVEL_COUNT 4L
  18. #define CT_REG_KEY_VALUE_MAX_LENGTH 0x00000100L
  19. //
  20. // List of initial Registry keys to be set up. The list must be
  21. // kept so that moving linearly through it visits key nodes with top
  22. // to bottom key traversal taking precedence over left-to-right.
  23. //
  24. typedef struct _CT_TEST_REGISTRY_KEY {
  25. ULONG KeyLevel;
  26. PUCHAR KeyName;
  27. ULONG KeyValueType;
  28. PUCHAR KeyValue;
  29. ULONG KeyValueLengthToQuery;
  30. ULONG KeyValueLengthToSet;
  31. NTSTATUS ExpectedStatus;
  32. HANDLE KeyHandle;
  33. HANDLE ParentKeyHandle;
  34. } CT_TEST_REGISTRY_KEY, *PCT_TEST_REGISTRY_KEY;
  35. CT_TEST_REGISTRY_KEY RegistryKeys[ CT_REG_INITIAL_KEY_COUNT ];
  36. UCHAR KeyValue[CT_REG_KEY_VALUE_MAX_LENGTH];
  37. ULONG KeyValueLengthToQuery;
  38. ULONG KeyValueType;
  39. LARGE_INTEGER LastWriteTime;
  40. HANDLE ParentKeyHandle[CT_REG_INITIAL_LEVEL_COUNT + 1] =
  41. { NULL, NULL, NULL, NULL, NULL };
  42. VOID
  43. InitTestKey(
  44. IN ULONG KeyNumber,
  45. IN ULONG KeyLevel,
  46. IN PUCHAR KeyName,
  47. IN ULONG KeyNameLength,
  48. IN ULONG KeyValueType,
  49. IN PUCHAR KeyValue,
  50. IN ULONG KeyValueLengthToQuery,
  51. IN ULONG KeyValueLengthToSet,
  52. IN NTSTATUS ExpectedStatus
  53. );
  54. VOID
  55. CtRegExamineResult(
  56. IN ULONG KeyNumber,
  57. IN ULONG KeyValueType,
  58. IN PUCHAR KeyValue,
  59. IN ULONG KeyValueLength,
  60. IN NTSTATUS ReturnedStatus
  61. );
  62. VOID
  63. CtCreateSetQueryKey();
  64. VOID
  65. CtOpenMakeTempCloseKey();
  66. VOID
  67. main ()
  68. {
  69. CtCreateSetQueryKey();
  70. CtOpenMakeTempCloseKey();
  71. }
  72. VOID
  73. CtCreateSetQueryKey(
  74. )
  75. /*++
  76. Routine Description:
  77. This function tests the RtlpNtOpenKey RtlpNtCreateKey and NtClose API.
  78. Arguments:
  79. None.
  80. Return Value:
  81. None.
  82. --*/
  83. {
  84. NTSTATUS Status;
  85. //
  86. // Set up a test hierarchy of keys
  87. //
  88. ULONG KeyNumber;
  89. ULONG ZeroLength;
  90. STRING Name;
  91. UNICODE_STRING UnicodeName;
  92. OBJECT_ATTRIBUTES ObjectAttributes;
  93. ZeroLength = 0L;
  94. DbgPrint("Start of Create, Set, Query Registry Key Test\n");
  95. //
  96. // Initialize the test array. I did it this way because a statically
  97. // initialized table is harder to read.
  98. //
  99. InitTestKey(
  100. 0,
  101. 0,
  102. "\\Registry\\RLM",
  103. sizeof ("\\Registry\\RLM"),
  104. 0,
  105. "Level 0 - RLM",
  106. sizeof ("\\Registry\\RLM") - 1,
  107. sizeof ("\\Registry\\RLM") - 1,
  108. STATUS_SUCCESS
  109. );
  110. InitTestKey(
  111. 1,
  112. 1,
  113. "Test",
  114. sizeof ("Test"),
  115. 1,
  116. "Keyname Test - this value too big",
  117. 6,
  118. sizeof ("Keyname Test - this value too big") -1,
  119. STATUS_BUFFER_OVERFLOW
  120. );
  121. InitTestKey(
  122. 2,
  123. 2,
  124. "SubTestA",
  125. sizeof("SubTestA"),
  126. 2,
  127. "Keyname SubTestA - value small",
  128. 30,
  129. sizeof ("Keyname SubTestA - value small") - 1,
  130. STATUS_SUCCESS
  131. );
  132. InitTestKey(
  133. 3,
  134. 3,
  135. "SSTestA",
  136. sizeof("SSTestA"),
  137. 3,
  138. "Keyname SSTestA - zero length buffer",
  139. 30,
  140. sizeof("Keyname SSTestA - zero length buffer") - 1,
  141. STATUS_BUFFER_OVERFLOW
  142. );
  143. InitTestKey(
  144. 4,
  145. 3,
  146. "SSTestB",
  147. sizeof("SSTestB"),
  148. 4,
  149. "Keyname SSTestB - value exact fit",
  150. sizeof ("Keyname SSTestB - value exact fit") -1,
  151. sizeof ("Keyname SSTestB - value exact fit") -1,
  152. STATUS_SUCCESS
  153. );
  154. InitTestKey(
  155. 5,
  156. 3,
  157. "SSTestC",
  158. sizeof("SSTestC"),
  159. 5,
  160. "Keyname SSTestC - value small",
  161. 40,
  162. sizeof ("Keyname SSTestC - value small") -1,
  163. STATUS_SUCCESS
  164. );
  165. InitTestKey(
  166. 6,
  167. 3,
  168. "SSTestD",
  169. sizeof("SSTestD"),
  170. 6,
  171. "Keyname SSTestD - value small",
  172. 40,
  173. sizeof ("Keyname SSTestD - value small") -1,
  174. STATUS_SUCCESS
  175. );
  176. InitTestKey(
  177. 7,
  178. 3,
  179. "SSTestE",
  180. sizeof("SSTestD"),
  181. 0,
  182. "Keyname SSTestD - no value set",
  183. 40,
  184. 0,
  185. STATUS_SUCCESS
  186. );
  187. DbgPrint("Start of Registry Test\n");
  188. //
  189. // Create all of the initial test registry keys
  190. //
  191. for (KeyNumber = 0; KeyNumber < CT_REG_INITIAL_KEY_COUNT; KeyNumber++) {
  192. RtlInitString(
  193. &Name,
  194. RegistryKeys[KeyNumber].KeyName
  195. );
  196. Status = RtlAnsiStringToUnicodeString(
  197. &UnicodeName,
  198. &Name,
  199. TRUE );
  200. if (!NT_SUCCESS(Status)) {
  201. DbgPrint("Security: Registry Init Ansi to Unicode failed 0x%lx\n",
  202. Status);
  203. return;
  204. }
  205. InitializeObjectAttributes(
  206. &ObjectAttributes,
  207. &UnicodeName,
  208. OBJ_CASE_INSENSITIVE,
  209. ParentKeyHandle[RegistryKeys[KeyNumber].KeyLevel],
  210. NULL
  211. );
  212. //
  213. // Remember the Parent Key handle
  214. //
  215. RegistryKeys[KeyNumber].ParentKeyHandle =
  216. ParentKeyHandle[RegistryKeys[KeyNumber].KeyLevel];
  217. //
  218. // Create the key if it does not already exist. If key does exist,
  219. // continue trying to create all of the other keys needed (for now).
  220. // Store the returned key handle as the parent key handle for the
  221. // next higher (child) level.
  222. //
  223. Status = RtlpNtCreateKey(
  224. &RegistryKeys[KeyNumber].KeyHandle,
  225. (KEY_READ | KEY_WRITE),
  226. &ObjectAttributes,
  227. 0L, // No options
  228. NULL, // Default provider
  229. NULL
  230. );
  231. //
  232. // Save the Key's handle as the next level's parent handle.
  233. //
  234. ParentKeyHandle[RegistryKeys[KeyNumber].KeyLevel + 1] =
  235. RegistryKeys[KeyNumber].KeyHandle;
  236. //
  237. // Free the memory allocated for the Unicode name
  238. //
  239. RtlFreeUnicodeString( &UnicodeName );
  240. if (NT_SUCCESS(Status) || Status == STATUS_OBJECT_NAME_COLLISION) {
  241. //
  242. // Set the key's value unless the length to set is zero.
  243. //
  244. if (RegistryKeys[KeyNumber].KeyValueLengthToSet != 0) {
  245. Status=RtlpNtSetValueKey(
  246. ParentKeyHandle[RegistryKeys[KeyNumber].KeyLevel+1],
  247. RegistryKeys[KeyNumber].KeyValueType,
  248. RegistryKeys[KeyNumber].KeyValue,
  249. RegistryKeys[KeyNumber].KeyValueLengthToSet
  250. );
  251. }
  252. //
  253. // Read the key's value back
  254. //
  255. KeyValueLengthToQuery =
  256. RegistryKeys[KeyNumber].KeyValueLengthToQuery;
  257. Status = RtlpNtQueryValueKey(
  258. ParentKeyHandle[RegistryKeys[KeyNumber].KeyLevel + 1],
  259. &KeyValueType,
  260. KeyValue,
  261. &KeyValueLengthToQuery,
  262. &LastWriteTime
  263. );
  264. //
  265. // Verify that the expected KeyValue, KeyLength and Status
  266. // were returned.
  267. //
  268. CtRegExamineResult(
  269. KeyNumber,
  270. KeyValueType,
  271. KeyValue,
  272. KeyValueLengthToQuery,
  273. Status
  274. );
  275. //
  276. // Test null pointer cases don't crash NtQueryValueKey
  277. //
  278. Status = RtlpNtQueryValueKey(
  279. ParentKeyHandle[RegistryKeys[KeyNumber].KeyLevel + 1],
  280. NULL, // No type
  281. KeyValue,
  282. &KeyValueLengthToQuery,
  283. &LastWriteTime
  284. );
  285. Status = RtlpNtQueryValueKey(
  286. ParentKeyHandle[RegistryKeys[KeyNumber].KeyLevel + 1],
  287. &KeyValueType,
  288. NULL, // No value
  289. &KeyValueLengthToQuery,
  290. &LastWriteTime
  291. );
  292. Status = RtlpNtQueryValueKey(
  293. ParentKeyHandle[RegistryKeys[KeyNumber].KeyLevel + 1],
  294. &KeyValueType,
  295. KeyValue,
  296. NULL, // No length
  297. &LastWriteTime
  298. );
  299. Status = RtlpNtQueryValueKey(
  300. ParentKeyHandle[RegistryKeys[KeyNumber].KeyLevel + 1],
  301. &KeyValueType,
  302. KeyValue,
  303. &ZeroLength, // Zero length
  304. &LastWriteTime
  305. );
  306. Status = RtlpNtQueryValueKey(
  307. ParentKeyHandle[RegistryKeys[KeyNumber].KeyLevel + 1],
  308. &KeyValueType,
  309. KeyValue,
  310. &KeyValueLengthToQuery,
  311. NULL // No time
  312. );
  313. //
  314. // Test null pointer cases don't crash NtSetValueKey
  315. //
  316. Status = RtlpNtSetValueKey(
  317. ParentKeyHandle[RegistryKeys[KeyNumber].KeyLevel+1],
  318. RegistryKeys[KeyNumber].KeyValueType,
  319. NULL, // No value, setting type only
  320. RegistryKeys[KeyNumber].KeyValueLengthToSet
  321. );
  322. } else {
  323. DbgPrint(
  324. "Key number %d creation failed 0x%lx\n",
  325. KeyNumber,
  326. Status
  327. );
  328. }
  329. }
  330. //
  331. // Close all the keys in the table
  332. //
  333. for (KeyNumber = 0; KeyNumber < CT_REG_INITIAL_KEY_COUNT; KeyNumber++) {
  334. Status = NtClose(
  335. RegistryKeys[KeyNumber].KeyHandle
  336. );
  337. if (!NT_SUCCESS(Status)) {
  338. DbgPrint("Closing KeyNumber %d failed 0x%lx\n", Status);
  339. }
  340. }
  341. DbgPrint("End of Create, Set, Query Registry Key Test\n");
  342. }
  343. VOID
  344. CtRegExamineResult(
  345. IN ULONG KeyNumber,
  346. IN ULONG KeyValueType,
  347. IN PUCHAR KeyValue,
  348. IN ULONG KeyValueLengthReturned,
  349. IN NTSTATUS ReturnedStatus
  350. )
  351. {
  352. ULONG KeyValueLengthToCompare;
  353. //
  354. // Check the status. If bad, skip the other checks.
  355. //
  356. if (ReturnedStatus != RegistryKeys[KeyNumber].ExpectedStatus) {
  357. DbgPrint(
  358. "KeyNumber %d: RtlpNtQueryValueKey returned 0x%lx, expected 0x%lx\n",
  359. KeyNumber,
  360. ReturnedStatus,
  361. RegistryKeys[KeyNumber].ExpectedStatus
  362. );
  363. } else {
  364. //
  365. // Check that the Key Type is as expected.
  366. //
  367. if (KeyValueType != RegistryKeys[KeyNumber].KeyValueType) {
  368. DbgPrint(
  369. "KeyNumber %d: RtlpNtQueryValueKey returned KeyValueType 0x%lx, \
  370. expected 0x%lx\n",
  371. KeyNumber,
  372. KeyValueType,
  373. RegistryKeys[KeyNumber].KeyValueType
  374. );
  375. }
  376. //
  377. // Check that the Key Length is as expected.
  378. //
  379. if (KeyValueLengthReturned !=
  380. RegistryKeys[KeyNumber].KeyValueLengthToSet) {
  381. DbgPrint(
  382. "KeyNumber %d: RtlpNtQueryValueKey returned ValLength 0x%lx, \
  383. expected 0x%lx\n",
  384. KeyNumber,
  385. KeyValueLengthReturned,
  386. RegistryKeys[KeyNumber].KeyValueLengthToSet
  387. );
  388. }
  389. //
  390. // Check that the Key Value is as expected. Distinguish between
  391. // Buffer truncated cases and regular cases.
  392. //
  393. if (RegistryKeys[KeyNumber].KeyValueLengthToSet != 0L) {
  394. //
  395. // Determine the length of returned key value to compare. This is
  396. // the min of the set length and and the size of the return
  397. // buffer.
  398. //
  399. KeyValueLengthToCompare =
  400. RegistryKeys[KeyNumber].KeyValueLengthToSet;
  401. if (KeyValueLengthToCompare >
  402. RegistryKeys[KeyNumber].KeyValueLengthToQuery) {
  403. KeyValueLengthToCompare =
  404. RegistryKeys[KeyNumber].KeyValueLengthToQuery;
  405. }
  406. if (strncmp(
  407. KeyValue,
  408. RegistryKeys[KeyNumber].KeyValue,
  409. KeyValueLengthToCompare
  410. ) != 0) {
  411. //
  412. // Output approriate error message. Message contains
  413. // "truncated.." if key value should have been truncated
  414. //
  415. if (RegistryKeys[KeyNumber].KeyValueLengthToSet >
  416. RegistryKeys[KeyNumber].KeyValueLengthToQuery) {
  417. DbgPrint(
  418. "KeyNumber %d: RtlpNtQueryValueKey returned KeyValue %s, \
  419. expected %s truncated to %d characters\n",
  420. KeyNumber,
  421. KeyValue,
  422. RegistryKeys[KeyNumber].KeyValue,
  423. RegistryKeys[KeyNumber].KeyValueLengthToQuery
  424. );
  425. } else {
  426. DbgPrint(
  427. "KeyNumber %d: RtlpNtQueryValueKey returned KeyValue %s, \
  428. expected %s\n",
  429. KeyNumber,
  430. KeyValue,
  431. RegistryKeys[KeyNumber].KeyValue
  432. );
  433. }
  434. }
  435. }
  436. }
  437. }
  438. VOID
  439. CtOpenMakeTempCloseKey()
  440. /*++
  441. Routine Description:
  442. This function tests NtDeleteKey by deleting the CT configuration
  443. Arguments:
  444. None.
  445. Return Value:
  446. None
  447. --*/
  448. {
  449. ULONG KeyNumber;
  450. ULONG KeyLevel;
  451. STRING Name;
  452. UNICODE_STRING UnicodeName;
  453. NTSTATUS Status;
  454. OBJECT_ATTRIBUTES ObjectAttributes;
  455. //
  456. // Open all of the initial test registry keys for write and delete
  457. // access, set, query and delete each key.
  458. //
  459. DbgPrint("Start of Open Make Temp and Close Delete Registry Key Test\n");
  460. //
  461. // First, set all of the Parent handles to NULL
  462. //
  463. for (KeyNumber = 0; KeyNumber < CT_REG_INITIAL_KEY_COUNT; KeyNumber++) {
  464. RegistryKeys[KeyNumber].ParentKeyHandle = NULL;
  465. }
  466. for (KeyLevel = 0; KeyLevel < CT_REG_INITIAL_LEVEL_COUNT; KeyLevel++) {
  467. ParentKeyHandle[KeyLevel] = NULL;
  468. }
  469. for (KeyNumber = 0; KeyNumber < CT_REG_INITIAL_KEY_COUNT; KeyNumber++) {
  470. RtlInitString(
  471. &Name,
  472. RegistryKeys[KeyNumber].KeyName
  473. );
  474. Status = RtlAnsiStringToUnicodeString(
  475. &UnicodeName,
  476. &Name,
  477. TRUE );
  478. if (!NT_SUCCESS(Status)) {
  479. DbgPrint("Security: Registry Init Ansi to Unicode failed 0x%lx\n",
  480. Status);
  481. return;
  482. }
  483. InitializeObjectAttributes(
  484. &ObjectAttributes,
  485. &UnicodeName,
  486. OBJ_CASE_INSENSITIVE,
  487. ParentKeyHandle[RegistryKeys[KeyNumber].KeyLevel],
  488. NULL
  489. );
  490. //
  491. // Open the key and store the returned key handle as the parent key
  492. // handle for the next higher (child) level.
  493. //
  494. Status = RtlpNtOpenKey(
  495. &RegistryKeys[KeyNumber].KeyHandle,
  496. (KEY_READ | KEY_WRITE | DELETE),
  497. &ObjectAttributes,
  498. 0L // No options
  499. );
  500. if (!NT_SUCCESS(Status)) {
  501. DbgPrint(
  502. "NtOpenKey - KeyNumber %d failed 0x%lx\n",
  503. KeyNumber,
  504. Status
  505. );
  506. }
  507. //
  508. // Save the Key's handle as the next level's parent handle.
  509. //
  510. ParentKeyHandle[RegistryKeys[KeyNumber].KeyLevel + 1] =
  511. RegistryKeys[KeyNumber].KeyHandle;
  512. //
  513. // Free the memory allocated for the Unicode name
  514. //
  515. RtlFreeUnicodeString( &UnicodeName );
  516. if (NT_SUCCESS(Status) || Status == STATUS_OBJECT_NAME_COLLISION) {
  517. //
  518. // Set the key's value unless the length to set is zero.
  519. //
  520. if (RegistryKeys[KeyNumber].KeyValueLengthToSet != 0) {
  521. Status=RtlpNtSetValueKey(
  522. ParentKeyHandle[RegistryKeys[KeyNumber].KeyLevel+1],
  523. RegistryKeys[KeyNumber].KeyValueType,
  524. RegistryKeys[KeyNumber].KeyValue,
  525. RegistryKeys[KeyNumber].KeyValueLengthToSet
  526. );
  527. }
  528. //
  529. // Read the key's value back
  530. //
  531. KeyValueLengthToQuery =
  532. RegistryKeys[KeyNumber].KeyValueLengthToQuery;
  533. Status = RtlpNtQueryValueKey(
  534. ParentKeyHandle[RegistryKeys[KeyNumber].KeyLevel + 1],
  535. &KeyValueType,
  536. KeyValue,
  537. &KeyValueLengthToQuery,
  538. &LastWriteTime
  539. );
  540. //
  541. // Verify that the expected KeyValue, KeyLength and Status
  542. // were returned.
  543. //
  544. CtRegExamineResult(
  545. KeyNumber,
  546. KeyValueType,
  547. KeyValue,
  548. KeyValueLengthToQuery,
  549. Status
  550. );
  551. } else {
  552. DbgPrint(
  553. "Key number %d open failed 0x%lx\n",
  554. KeyNumber,
  555. Status
  556. );
  557. }
  558. }
  559. //
  560. // Make Temporary and Close all the keys in the table
  561. //
  562. for (KeyNumber = CT_REG_INITIAL_KEY_COUNT-1; KeyNumber != 0L; KeyNumber--) {
  563. Status = RtlpNtMakeTemporaryKey( RegistryKeys[KeyNumber].KeyHandle );
  564. if (!NT_SUCCESS(Status)) {
  565. DbgPrint(
  566. "Making Temporary KeyNumber %d failed 0x%lx\n",
  567. KeyNumber,
  568. Status
  569. );
  570. }
  571. Status = NtClose(
  572. RegistryKeys[KeyNumber].KeyHandle
  573. );
  574. if (!NT_SUCCESS(Status)) {
  575. DbgPrint(
  576. "Closing KeyNumber %d failed 0x%lx\n",
  577. KeyNumber,
  578. Status
  579. );
  580. }
  581. }
  582. DbgPrint("End of Open Mk Temp and Close Registry Key Test\n");
  583. }
  584. VOID
  585. InitTestKey(
  586. IN ULONG KeyNumber,
  587. IN ULONG KeyLevel,
  588. IN PUCHAR KeyName,
  589. IN ULONG KeyNameLength,
  590. IN ULONG KeyValueType,
  591. IN PUCHAR KeyValue,
  592. IN ULONG KeyValueLengthToQuery,
  593. IN ULONG KeyValueLengthToSet,
  594. IN NTSTATUS ExpectedStatus
  595. )
  596. /*++
  597. Routine Description:
  598. This function initializes an entry in the array of test keys
  599. Arguments:
  600. TBS.
  601. Return Value:
  602. --*/
  603. {
  604. RegistryKeys[KeyNumber].KeyLevel = KeyLevel;
  605. RegistryKeys[KeyNumber].KeyName = KeyName;
  606. RegistryKeys[KeyNumber].KeyValueType = KeyValueType;
  607. RegistryKeys[KeyNumber].KeyValue = KeyValue;
  608. RegistryKeys[KeyNumber].KeyValueLengthToSet = KeyValueLengthToSet;
  609. RegistryKeys[KeyNumber].KeyValueLengthToQuery = KeyValueLengthToQuery;
  610. RegistryKeys[KeyNumber].ExpectedStatus = ExpectedStatus;
  611. RegistryKeys[KeyNumber].KeyHandle = NULL;
  612. RegistryKeys[KeyNumber].ParentKeyHandle = NULL;
  613. DBG_UNREFERENCED_PARAMETER (KeyNameLength);
  614. }
  615.