Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

844 lines
21 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. rtmisc1.c
  5. Abstract:
  6. NT level registry api test program #1, basic non-error paths.
  7. Test open, create, setvalue, queryvalue, enumeratekey, enumeratevalue,
  8. querykey.
  9. Author:
  10. Bryan Willman (bryanwi) 19-Nov-91
  11. Revision History:
  12. --*/
  13. #include "cmp.h"
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. //
  18. // NOTE: This version of the test operations on \REGISTRY\MACHINE\TEST\*,
  19. // which is the TEST hive. This hive will not exist in production
  20. // systems, so the test will have to change.
  21. //
  22. void __cdecl main(int, char *);
  23. VOID
  24. NameClassAndTitle(
  25. KEY_NODE_INFORMATION *NodeInformation,
  26. UNICODE_STRING ClassName,
  27. ULONG TitleIndex,
  28. UNICODE_STRING KeyName,
  29. LARGE_INTEGER CompTime,
  30. BOOLEAN Strong, // time must be >= CompTime
  31. PUCHAR TestName
  32. );
  33. VOID
  34. expectstring(
  35. PWSTR expected,
  36. ULONG expectedlength,
  37. PWSTR actual,
  38. ULONG actuallength
  39. );
  40. VOID
  41. expecttime(
  42. LARGE_INTEGER ExpectTime,
  43. LARGE_INTEGER ActualTime
  44. );
  45. #define TITLE_INDEX_1 122259
  46. #define TITLE_INDEX_2 120858
  47. #define TITLE_INDEX_3 120159
  48. #define TYPE_1 666
  49. #define TYPE_2 1066
  50. ULONG failure = 0;
  51. void
  52. __cdecl main(int, char *)
  53. {
  54. NTSTATUS status;
  55. OBJECT_ATTRIBUTES ObjectAttributes;
  56. UNICODE_STRING KeyName;
  57. UNICODE_STRING KeyName2;
  58. UNICODE_STRING ClassName;
  59. UNICODE_STRING ClassName2;
  60. UNICODE_STRING ValueName;
  61. UNICODE_STRING ValueName2;
  62. HANDLE BaseHandle;
  63. HANDLE Testhand1;
  64. ULONG Disposition;
  65. LARGE_INTEGER CompTime;
  66. ULONG buffer[100];
  67. ULONG bufsize = sizeof(ULONG) * 100;
  68. PKEY_NODE_INFORMATION NodeInformation;
  69. PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
  70. PKEY_VALUE_BASIC_INFORMATION KeyValueBasic;
  71. ULONG ResultLength;
  72. PUCHAR datastring = "Some simple ascii data for use as a value";
  73. PUCHAR datastring2 = "Some more not so simple data $#";
  74. ULONG expected;
  75. PVOID tp;
  76. printf("rtmisc1: starting\n");
  77. NodeInformation = (PKEY_NODE_INFORMATION)&(buffer[0]);
  78. KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)&(buffer[0]);
  79. KeyValueBasic = (PKEY_VALUE_BASIC_INFORMATION)&(buffer[0]);
  80. //
  81. // t0: Perform all operations against a base node, open it here.
  82. //
  83. RtlInitUnicodeString(
  84. &KeyName,
  85. L"\\REGISTRY\\MACHINE\\TEST"
  86. );
  87. InitializeObjectAttributes(
  88. &ObjectAttributes,
  89. &KeyName,
  90. 0,
  91. (HANDLE)NULL,
  92. NULL
  93. );
  94. ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
  95. status = NtOpenKey(
  96. &BaseHandle,
  97. MAXIMUM_ALLOWED,
  98. &ObjectAttributes
  99. );
  100. if (!NT_SUCCESS(status)) {
  101. printf("rtmisc1: t0: %08lx\n", status);
  102. goto punt;
  103. }
  104. //
  105. // t1: Create a key with class and title index
  106. //
  107. RtlInitUnicodeString(
  108. &ClassName,
  109. L"t1 Class Name"
  110. );
  111. RtlInitUnicodeString(
  112. &KeyName,
  113. L"first_test_node"
  114. );
  115. InitializeObjectAttributes(
  116. &ObjectAttributes,
  117. &KeyName,
  118. 0,
  119. BaseHandle,
  120. NULL
  121. );
  122. ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
  123. NtQuerySystemTime(&CompTime);
  124. // printf("ClassName@%08lx KeyName@%08lx\n",
  125. // ClassName.Buffer, KeyName.Buffer);
  126. status = NtCreateKey(
  127. &Testhand1,
  128. MAXIMUM_ALLOWED,
  129. &ObjectAttributes,
  130. TITLE_INDEX_1,
  131. &ClassName,
  132. 0,
  133. &Disposition
  134. );
  135. if (!NT_SUCCESS(status)) {
  136. printf("rtmisc1: t1: %08lx\n", status);
  137. goto punt;
  138. }
  139. if (Disposition != REG_CREATED_NEW_KEY) {
  140. printf("rtmisc1: t1a: got old key, expected to create new one\n");
  141. failure++;
  142. }
  143. //
  144. // t2: See if we can get data back, and if it makes sense
  145. //
  146. RtlZeroMemory(NodeInformation, bufsize);
  147. status = NtQueryKey(
  148. Testhand1,
  149. KeyNodeInformation,
  150. NodeInformation,
  151. bufsize,
  152. &ResultLength
  153. );
  154. if (!NT_SUCCESS(status)) {
  155. printf("rtmisc1: t2a: %08lx\n", status);
  156. goto punt;
  157. }
  158. if (ResultLength != 80) {
  159. printf("rtmisc1: t2i: expect 80, ResultLength = %d\n", ResultLength);
  160. failure++;
  161. }
  162. NameClassAndTitle(
  163. NodeInformation,
  164. ClassName,
  165. TITLE_INDEX_1,
  166. KeyName,
  167. CompTime,
  168. FALSE, // time must be >= CompTime
  169. "rtmisc1: t2b: "
  170. );
  171. CompTime = NodeInformation->LastWriteTime;
  172. status = NtClose(Testhand1);
  173. if (!NT_SUCCESS(status)) {
  174. printf("rtmisc1: t2c: %08lx\n");
  175. goto punt;
  176. }
  177. //
  178. // t3: Reopen the key with create, see if data still there.
  179. //
  180. status = NtCreateKey(
  181. &Testhand1,
  182. MAXIMUM_ALLOWED,
  183. &ObjectAttributes,
  184. TITLE_INDEX_1,
  185. &ClassName,
  186. 0,
  187. &Disposition
  188. );
  189. if (!NT_SUCCESS(status)) {
  190. printf("rtmisc1: t3: %08lx\n", status);
  191. goto punt;
  192. }
  193. if (Disposition != REG_OPENED_EXISTING_KEY) {
  194. printf("rtmisc1: t3a failure\n");
  195. failure++;
  196. }
  197. RtlZeroMemory(NodeInformation, bufsize);
  198. status = NtQueryKey(
  199. Testhand1,
  200. KeyNodeInformation,
  201. NodeInformation,
  202. bufsize,
  203. &ResultLength
  204. );
  205. if (!NT_SUCCESS(status)) {
  206. printf("rtmisc1: t3b: %08lx\n", status);
  207. goto punt;
  208. }
  209. NameClassAndTitle(
  210. NodeInformation,
  211. ClassName,
  212. TITLE_INDEX_1,
  213. KeyName,
  214. CompTime,
  215. FALSE, // time must be >= CompTime
  216. "rtmisc1: t3c: "
  217. );
  218. status = NtClose(Testhand1);
  219. if (!NT_SUCCESS(status)) {
  220. printf("rtmisc1: t3d: %08lx\n");
  221. goto punt;
  222. }
  223. //
  224. // t4: Reopen the key with open, see if data still there.
  225. //
  226. status = NtOpenKey(
  227. &Testhand1,
  228. MAXIMUM_ALLOWED,
  229. &ObjectAttributes
  230. );
  231. if (!NT_SUCCESS(status)) {
  232. printf("rtmisc1: t4: %08lx\n", status);
  233. goto punt;
  234. }
  235. RtlZeroMemory(NodeInformation, bufsize);
  236. status = NtQueryKey(
  237. Testhand1,
  238. KeyNodeInformation,
  239. NodeInformation,
  240. bufsize,
  241. &ResultLength
  242. );
  243. if (!NT_SUCCESS(status)) {
  244. printf("rtmisc1: t4a: %08lx\n", status);
  245. goto punt;
  246. }
  247. NameClassAndTitle(
  248. NodeInformation,
  249. ClassName,
  250. TITLE_INDEX_1,
  251. KeyName,
  252. CompTime,
  253. FALSE, // time must be >= CompTime
  254. "rtmisc1: t4b: "
  255. );
  256. // status = NtClose(Testhand1);
  257. // if (!NT_SUCCESS(status)) {
  258. // printf("rtmisc1: t4c: %08lx\n");
  259. // exit(1);
  260. // }
  261. //
  262. // t5: Create a value
  263. //
  264. RtlInitUnicodeString(
  265. &ValueName,
  266. L"the very first value stored in the registry"
  267. );
  268. status = NtSetValueKey(
  269. Testhand1,
  270. &ValueName,
  271. TITLE_INDEX_2,
  272. TYPE_1,
  273. datastring,
  274. strlen(datastring)+1
  275. );
  276. if (!NT_SUCCESS(status)) {
  277. printf("rtmisc1: t5: %08lx\n", status);
  278. failure++;
  279. }
  280. //
  281. // t6: Read the value back
  282. //
  283. RtlZeroMemory(KeyValueInformation, bufsize);
  284. status = NtQueryValueKey(
  285. Testhand1,
  286. &ValueName,
  287. KeyValueFullInformation,
  288. KeyValueInformation,
  289. bufsize,
  290. &ResultLength
  291. );
  292. if (!NT_SUCCESS(status)) {
  293. printf("rtmisc1: t6: %08lx\n", status);
  294. goto punt;
  295. }
  296. expected = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name) +
  297. ValueName.Length + strlen(datastring) + 1;
  298. if (ResultLength != expected) {
  299. printf("rtmisc1: t6a: expected = %08lx actual = %08lx",
  300. expected, ResultLength);
  301. failure++;
  302. }
  303. if ( (KeyValueInformation->TitleIndex != TITLE_INDEX_2) ||
  304. (KeyValueInformation->Type != TYPE_1) ||
  305. (KeyValueInformation->NameLength != ValueName.Length) ||
  306. (KeyValueInformation->DataLength != strlen(datastring)+1))
  307. {
  308. printf("rtmisc1: t6b: wrong description data\n");
  309. failure++;
  310. }
  311. tp = (PWSTR)&(KeyValueInformation->Name[0]);
  312. if (wcsncmp(ValueName.Buffer, tp, (ValueName.Length/sizeof(WCHAR))) != 0) {
  313. printf("rtmisc1: t6c: wrong name\n");
  314. expectstring(
  315. ValueName.Buffer,
  316. (ValueName.Length/sizeof(WCHAR)),
  317. (PWSTR)&(KeyValueInformation->Name[0]),
  318. (KeyValueInformation->NameLength/sizeof(WCHAR))
  319. );
  320. failure++;
  321. }
  322. tp = (PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset;
  323. if (strcmp(tp, datastring) != 0) {
  324. printf("rtmisc1: t6d: wrong data\n");
  325. printf("expected '%s', got '%s'\n", datastring, tp);
  326. failure++;
  327. }
  328. //
  329. // t7: Create a second value
  330. //
  331. RtlInitUnicodeString(
  332. &ValueName2,
  333. L"the second value stored in the registry"
  334. );
  335. status = NtSetValueKey(
  336. Testhand1,
  337. &ValueName2,
  338. TITLE_INDEX_3,
  339. TYPE_2,
  340. datastring2,
  341. strlen(datastring2)+1
  342. );
  343. if (!NT_SUCCESS(status)) {
  344. printf("rtmisc1: t7: %08lx\n", status);
  345. failure++;
  346. }
  347. //
  348. // t8: Read the second value back (short form)
  349. //
  350. RtlZeroMemory(KeyValueBasic, bufsize);
  351. status = NtQueryValueKey(
  352. Testhand1,
  353. &ValueName2,
  354. KeyValueBasicInformation,
  355. KeyValueBasic,
  356. bufsize,
  357. &ResultLength
  358. );
  359. if (!NT_SUCCESS(status)) {
  360. printf("rtmisc1: t8: %08lx\n", status);
  361. goto punt;
  362. }
  363. expected = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name) +
  364. ValueName2.Length;
  365. if (ResultLength != expected) {
  366. printf("rtmisc1: t8a: expected = %08lx actual = %08lx",
  367. expected, ResultLength);
  368. failure++;
  369. }
  370. if ( (KeyValueBasic->TitleIndex != TITLE_INDEX_3) ||
  371. (KeyValueBasic->Type != TYPE_2) ||
  372. (KeyValueBasic->NameLength != ValueName2.Length))
  373. {
  374. printf("rtmisc1: t8b: wrong description data\n");
  375. failure++;
  376. }
  377. tp = (PWSTR)&(KeyValueBasic->Name[0]);
  378. if (wcsncmp(ValueName2.Buffer, tp, (ValueName2.Length/sizeof(WCHAR))) != 0) {
  379. printf("rtmisc1: t8c: wrong name\n");
  380. expectstring(
  381. ValueName2.Buffer,
  382. (ValueName2.Length/sizeof(WCHAR)),
  383. (PWSTR)&(KeyValueBasic->Name[0]),
  384. (KeyValueBasic->NameLength/sizeof(WCHAR))
  385. );
  386. failure++;
  387. }
  388. //
  389. // t9: Enumerate the values (short form)
  390. //
  391. RtlZeroMemory(KeyValueBasic, bufsize);
  392. status = NtEnumerateValueKey(
  393. Testhand1,
  394. 0, // Index
  395. KeyValueBasicInformation,
  396. KeyValueBasic,
  397. bufsize,
  398. &ResultLength
  399. );
  400. if (!NT_SUCCESS(status)) {
  401. printf("rtmisc1: t9: %08lx\n", status);
  402. goto punt;
  403. }
  404. expected = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name) +
  405. ValueName.Length;
  406. if (ResultLength != expected) {
  407. printf("rtmisc1: t9a: expected = %08lx actual = %08lx",
  408. expected, ResultLength);
  409. failure++;
  410. }
  411. if (KeyValueBasic->NameLength != ValueName.Length)
  412. {
  413. printf("rtmisc1: t9b: wrong description data\n");
  414. failure++;
  415. }
  416. tp = (PWSTR)&(KeyValueBasic->Name[0]);
  417. if (wcsncmp(ValueName.Buffer, tp, (ValueName.Length/sizeof(WCHAR))) != 0) {
  418. printf("rtmisc1: t9c: wrong name\n");
  419. expectstring(
  420. ValueName.Buffer,
  421. (ValueName.Length/sizeof(WCHAR)),
  422. (PWSTR)&(KeyValueBasic->Name[0]),
  423. (KeyValueBasic->NameLength/sizeof(WCHAR))
  424. );
  425. failure++;
  426. }
  427. RtlZeroMemory(KeyValueBasic, bufsize);
  428. status = NtEnumerateValueKey(
  429. Testhand1,
  430. 1, // Index
  431. KeyValueBasicInformation,
  432. KeyValueBasic,
  433. bufsize,
  434. &ResultLength
  435. );
  436. if (!NT_SUCCESS(status)) {
  437. printf("rtmisc1: t9d: %08lx\n", status);
  438. goto punt;
  439. }
  440. expected = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name) +
  441. ValueName2.Length;
  442. if (ResultLength != expected) {
  443. printf("rtmisc1: t9e: expected = %08lx actual = %08lx",
  444. expected, ResultLength);
  445. failure++;
  446. }
  447. if (KeyValueBasic->NameLength != ValueName2.Length)
  448. {
  449. printf("rtmisc1: t9f: wrong description data\n");
  450. failure++;
  451. }
  452. tp = (PWSTR)&(KeyValueBasic->Name[0]);
  453. if (wcsncmp(ValueName2.Buffer, tp, (ValueName2.Length/sizeof(WCHAR))) != 0) {
  454. printf("rtmisc1: t9g: wrong name\n");
  455. expectstring(
  456. ValueName2.Buffer,
  457. (ValueName2.Length/sizeof(WCHAR)),
  458. (PWSTR)&(KeyValueBasic->Name[0]),
  459. (KeyValueBasic->NameLength/sizeof(WCHAR))
  460. );
  461. failure++;
  462. }
  463. status = NtEnumerateValueKey(
  464. Testhand1,
  465. 2, // Index
  466. KeyValueBasicInformation,
  467. KeyValueBasic,
  468. bufsize,
  469. &ResultLength
  470. );
  471. if (status != STATUS_NO_MORE_ENTRIES) {
  472. printf("rtmisc1: t9h: %08lx\n", status);
  473. goto punt;
  474. }
  475. //
  476. // t10: create a second subkey and ennumerate the subkeys
  477. //
  478. status = NtClose(Testhand1);
  479. if (!NT_SUCCESS(status)) {
  480. printf("rtmisc1: t10a: %08lx\n", status);
  481. failure++;
  482. }
  483. RtlInitUnicodeString(
  484. &ClassName2,
  485. L"t2 Class Name"
  486. );
  487. RtlInitUnicodeString(
  488. &KeyName2,
  489. L"second_test_node"
  490. );
  491. InitializeObjectAttributes(
  492. &ObjectAttributes,
  493. &KeyName2,
  494. 0,
  495. BaseHandle,
  496. NULL
  497. );
  498. ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
  499. status = NtCreateKey(
  500. &Testhand1,
  501. MAXIMUM_ALLOWED,
  502. &ObjectAttributes,
  503. TITLE_INDEX_2,
  504. &ClassName2,
  505. 0,
  506. &Disposition
  507. );
  508. if (!NT_SUCCESS(status)) {
  509. printf("rtmisc1: t10b: %08lx\n", status);
  510. goto punt;
  511. }
  512. if (Disposition != REG_CREATED_NEW_KEY) {
  513. printf("rtmisc1: t10c: got old key, expected to create new one\n");
  514. failure++;
  515. }
  516. //
  517. // See if we can get data back, and if it makes sense
  518. //
  519. RtlZeroMemory(NodeInformation, bufsize);
  520. status = NtQueryKey(
  521. Testhand1,
  522. KeyNodeInformation,
  523. NodeInformation,
  524. bufsize,
  525. &ResultLength
  526. );
  527. if (!NT_SUCCESS(status)) {
  528. printf("rtmisc1: t10d: %08lx\n", status);
  529. goto punt;
  530. }
  531. CompTime = NodeInformation->LastWriteTime;
  532. NameClassAndTitle(
  533. NodeInformation,
  534. ClassName2,
  535. TITLE_INDEX_2,
  536. KeyName2,
  537. CompTime,
  538. TRUE,
  539. "rtmisc1: t10e: "
  540. );
  541. status = NtClose(Testhand1);
  542. if (!NT_SUCCESS(status)) {
  543. printf("rtmisc1: t10f: %08lx\n");
  544. goto punt;
  545. }
  546. RtlZeroMemory(NodeInformation, bufsize);
  547. status = NtEnumerateKey(
  548. BaseHandle,
  549. 0,
  550. KeyNodeInformation,
  551. NodeInformation,
  552. bufsize,
  553. &ResultLength
  554. );
  555. if (!NT_SUCCESS(status)) {
  556. printf("rtmisc1: t10g: %08lx\n", status);
  557. failure++;
  558. }
  559. CompTime = NodeInformation->LastWriteTime;
  560. NameClassAndTitle(
  561. NodeInformation,
  562. ClassName,
  563. TITLE_INDEX_1,
  564. KeyName,
  565. CompTime,
  566. TRUE,
  567. "rtmisc1: t10h: "
  568. );
  569. RtlZeroMemory(NodeInformation, bufsize);
  570. status = NtEnumerateKey(
  571. BaseHandle,
  572. 1,
  573. KeyNodeInformation,
  574. NodeInformation,
  575. bufsize,
  576. &ResultLength
  577. );
  578. if (!NT_SUCCESS(status)) {
  579. printf("rtmisc1: t10i: %08lx\n", status);
  580. failure++;
  581. }
  582. CompTime = NodeInformation->LastWriteTime;
  583. NameClassAndTitle(
  584. NodeInformation,
  585. ClassName2,
  586. TITLE_INDEX_2,
  587. KeyName2,
  588. CompTime,
  589. TRUE,
  590. "rtmisc1: t10j: "
  591. );
  592. status = NtEnumerateKey(
  593. BaseHandle,
  594. 2,
  595. KeyNodeInformation,
  596. NodeInformation,
  597. bufsize,
  598. &ResultLength
  599. );
  600. if (status != STATUS_NO_MORE_ENTRIES) {
  601. printf("rtmisc1: t10k: %08lx\n", status);
  602. failure++;
  603. }
  604. //
  605. // Summary report
  606. //
  607. if (!failure) {
  608. printf("rtmisc1: success");
  609. exit(0);
  610. } else {
  611. printf("rtmisc1: failed, %d failures\n", failure);
  612. exit(1);
  613. }
  614. punt:
  615. failure++;
  616. printf("rtmisc1: failed, %d failures\n", failure);
  617. exit(1);
  618. }
  619. VOID
  620. NameClassAndTitle(
  621. KEY_NODE_INFORMATION *NodeInformation,
  622. UNICODE_STRING ClassName,
  623. ULONG TitleIndex,
  624. UNICODE_STRING KeyName,
  625. LARGE_INTEGER CompTime,
  626. BOOLEAN Strong, // time must be >= CompTime
  627. PUCHAR TestName
  628. )
  629. {
  630. PWSTR p;
  631. if (Strong) {
  632. //
  633. // require exact match
  634. //
  635. if ((CompTime.HighPart != NodeInformation->LastWriteTime.HighPart) ||
  636. (CompTime.LowPart != NodeInformation->LastWriteTime.LowPart))
  637. {
  638. printf("%s Wrong time (a)\n", TestName);
  639. expecttime(CompTime, NodeInformation->LastWriteTime);
  640. failure++;
  641. }
  642. } else {
  643. //
  644. // >= will do
  645. //
  646. if ( (CompTime.HighPart > NodeInformation->LastWriteTime.HighPart) ||
  647. ((CompTime.HighPart == NodeInformation->LastWriteTime.HighPart) &&
  648. (CompTime.LowPart > NodeInformation->LastWriteTime.LowPart)) )
  649. {
  650. printf("%s Wrong time (b)\n", TestName);
  651. expecttime(CompTime, NodeInformation->LastWriteTime);
  652. failure++;
  653. }
  654. }
  655. p = (PWSTR)((PUCHAR)NodeInformation + NodeInformation->ClassOffset);
  656. if ( (NodeInformation->ClassLength != ClassName.Length) ||
  657. (wcsncmp(ClassName.Buffer, p, (ClassName.Length/sizeof(WCHAR))) != 0))
  658. {
  659. printf("%s wrong class name\n", TestName);
  660. failure++;
  661. }
  662. if (NodeInformation->TitleIndex != TitleIndex) {
  663. printf("%s wrong title index\n", TestName);
  664. failure++;
  665. }
  666. p = (PWSTR)(&(NodeInformation->Name[0]));
  667. if ( (NodeInformation->NameLength != KeyName.Length) ||
  668. (wcsncmp(KeyName.Buffer, p, (KeyName.Length/sizeof(WCHAR))) != 0))
  669. {
  670. printf("%s wrong name\n", TestName);
  671. expectstring(
  672. KeyName.Buffer,
  673. (KeyName.Length/sizeof(WCHAR)),
  674. (PWSTR)&(NodeInformation->Name[0]),
  675. (NodeInformation->NameLength/sizeof(WCHAR))
  676. );
  677. failure++;
  678. }
  679. }
  680. VOID
  681. expecttime(
  682. LARGE_INTEGER ExpectTime,
  683. LARGE_INTEGER ActualTime
  684. )
  685. {
  686. printf("Expected %08lx%08lx\n", ExpectTime.HighPart, ExpectTime.LowPart);
  687. printf("Got %08lx%08lx\n", ActualTime.HighPart, ActualTime.LowPart);
  688. return;
  689. }
  690. VOID
  691. expectstring(
  692. PWSTR expected,
  693. ULONG expectedlength,
  694. PWSTR actual,
  695. ULONG actuallength
  696. )
  697. {
  698. ULONG i;
  699. printf("Expected Len %d Str = '", expectedlength);
  700. for (i = 0; i < expectedlength; i++) {
  701. printf("%c", (UCHAR)(expected[i]));
  702. }
  703. printf("'\n");
  704. printf("Got Len %d Str = '", actuallength);
  705. for (i = 0; i < actuallength; i++) {
  706. printf("%c", (UCHAR)(actual[i]));
  707. }
  708. printf("'\n");
  709. return;
  710. }