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.

667 lines
24 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. uob.c
  5. Abstract:
  6. Object Manager User Mode Test Program
  7. Author:
  8. Steve Wood (stevewo) 03-Aug-1989
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <string.h>
  16. STRING DirTypeName;
  17. STRING LinkTypeName;
  18. VOID
  19. TestParent( VOID );
  20. VOID
  21. TestChild( VOID );
  22. VOID
  23. DumpObjectDirs(
  24. IN PCH DirName,
  25. IN ULONG Level
  26. )
  27. {
  28. OBJECT_ATTRIBUTES ObjectAttributes;
  29. STRING Name;
  30. HANDLE Handle;
  31. ULONG Context, Length;
  32. NTSTATUS Status;
  33. BOOLEAN RestartScan;
  34. POBJECT_DIRECTORY_INFORMATION DirInfo;
  35. CHAR DirInfoBuffer[ 256 ];
  36. CHAR SubDirName[ 128 ];
  37. STRING LinkName;
  38. STRING LinkTarget;
  39. HANDLE LinkHandle;
  40. RtlInitString( &Name, DirName );
  41. InitializeObjectAttributes( &ObjectAttributes,
  42. &Name,
  43. OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
  44. NULL,
  45. NULL
  46. );
  47. NtCreateDirectoryObject( &Handle,
  48. DIRECTORY_ALL_ACCESS,
  49. &ObjectAttributes
  50. );
  51. DirInfo = (POBJECT_DIRECTORY_INFORMATION)&DirInfoBuffer;
  52. RestartScan = TRUE;
  53. while (TRUE) {
  54. Status = NtQueryDirectoryObject( Handle,
  55. (PVOID)DirInfo,
  56. sizeof( DirInfoBuffer ),
  57. TRUE,
  58. RestartScan,
  59. &Context,
  60. &Length
  61. );
  62. if (!NT_SUCCESS( Status )) {
  63. break;
  64. }
  65. DbgPrint( "%s%s%Z - %Z",
  66. DirName,
  67. Level ? "\\" : "",
  68. &DirInfo->Name,
  69. &DirInfo->TypeName
  70. );
  71. if (RtlEqualString( &DirInfo->TypeName, &DirTypeName, TRUE )) {
  72. DbgPrint( "\n" );
  73. strcpy( SubDirName, DirName );
  74. if (Level) {
  75. strcat( SubDirName, "\\" );
  76. }
  77. strcat( SubDirName, DirInfo->Name.Buffer );
  78. DumpObjectDirs( SubDirName, Level+1 );
  79. }
  80. else
  81. if (RtlEqualString( &DirInfo->TypeName, &LinkTypeName, TRUE )) {
  82. strcpy( SubDirName, DirName );
  83. if (Level) {
  84. strcat( SubDirName, "\\" );
  85. }
  86. strcat( SubDirName, DirInfo->Name.Buffer );
  87. RtlInitString( &LinkName, SubDirName );
  88. InitializeObjectAttributes( &ObjectAttributes,
  89. &LinkName,
  90. 0,
  91. NULL,
  92. NULL
  93. );
  94. Status = NtOpenSymbolicLinkObject( &LinkHandle,
  95. SYMBOLIC_LINK_ALL_ACCESS,
  96. &ObjectAttributes
  97. );
  98. if (!NT_SUCCESS( Status )) {
  99. DbgPrint( " - unable to open symbolic link (%X)\n", Status );
  100. }
  101. else {
  102. LinkTarget.MaximumLength = sizeof( SubDirName );
  103. LinkTarget.Length = 0;
  104. LinkTarget.Buffer = SubDirName;
  105. Status = NtQuerySymbolicLinkObject( LinkHandle,
  106. &LinkTarget
  107. );
  108. if (!NT_SUCCESS( Status )) {
  109. DbgPrint( " - unable to query symbolic link target (%X)\n", Status );
  110. }
  111. else {
  112. DbgPrint( " => %Z\n", &LinkTarget );
  113. }
  114. NtClose( LinkHandle );
  115. }
  116. }
  117. else {
  118. DbgPrint( "\n" );
  119. }
  120. RestartScan = FALSE;
  121. }
  122. NtClose( Handle );
  123. }
  124. char ParameterBuffer[ 4096 ];
  125. main(
  126. int argc,
  127. char **argv,
  128. char **envp,
  129. int DebugFlag
  130. )
  131. {
  132. NTSTATUS Status;
  133. STRING ImageName;
  134. PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
  135. RTL_USER_PROCESS_INFORMATION ProcessInformation;
  136. if (argc == 1) {
  137. TestParent();
  138. Parameters[ RTL_USER_PROC_PARAMS_IMAGEFILE ] = argv[ 0 ];
  139. Parameters[ RTL_USER_PROC_PARAMS_CMDLINE ] = " CHILD";
  140. Parameters[ RTL_USER_PROC_PARAMS_DEBUGFLAG ] =
  141. DebugFlag ? "1" : "0";
  142. Parameters[ RTL_USER_PROC_PARAMS_DEBUGFLAG+1 ] = NULL;
  143. Arguments[ 0 ] = argv[ 0 ];
  144. Arguments[ 1 ] = "CHILD";
  145. Arguments[ 2 ] = NULL;
  146. ProcessParameters = (PRTL_USER_PROCESS_PARAMETERS)ParameterBuffer;
  147. ProcessParameters->Length = 0;
  148. ProcessParameters->MaximumLength = sizeof( ParameterBuffer );
  149. Status = RtlVectorsToProcessParameters( Arguments,
  150. envp,
  151. Parameters,
  152. ProcessParameters
  153. );
  154. if (!NT_SUCCESS( Status )) {
  155. DbgPrint( "RtlVectorToProcessParameters failed - Status = %X\n",
  156. Status
  157. );
  158. }
  159. else {
  160. RtlInitString( &ImageName, "\\C:\\TMP\\UOB.EXE" );
  161. Status = RtlCreateUserProcess( &ImageName,
  162. NULL,
  163. NULL,
  164. NULL,
  165. TRUE,
  166. NULL,
  167. NULL,
  168. ProcessParameters,
  169. &ProcessInformation,
  170. NULL
  171. );
  172. if (!NT_SUCCESS( Status )) {
  173. DbgPrint( "RtlCreateUserProcess( %Z ) failed - Status = %X\n",
  174. &ImageName, Status
  175. );
  176. }
  177. else {
  178. Status = NtResumeThread( ProcessInformation.Thread, NULL );
  179. Status = NtWaitForSingleObject( ProcessInformation.Process,
  180. FALSE,
  181. (PLARGE_INTEGER)NULL
  182. );
  183. if (!NT_SUCCESS( Status )) {
  184. DbgPrint( "NtWaitForSingleObject failed - Status = %X\n",
  185. Status
  186. );
  187. }
  188. }
  189. }
  190. }
  191. else {
  192. TestChild();
  193. }
  194. NtTerminateProcess( NtCurrentProcess(), Status );
  195. }
  196. VOID
  197. TestParent( VOID )
  198. {
  199. NTSTATUS Status;
  200. STRING DirectoryName;
  201. STRING LinkName;
  202. STRING LinkTarget;
  203. STRING SectionName;
  204. OBJECT_ATTRIBUTES ObjectAttributes;
  205. HANDLE DirectoryHandle, LinkHandle, SectionHandle;
  206. ULONG ReturnedLength;
  207. CHAR ObjectInfoBuffer[ 512 ];
  208. OBJECT_BASIC_INFORMATION ObjectBasicInfo;
  209. POBJECT_NAME_INFORMATION ObjectNameInfo;
  210. POBJECT_TYPE_INFORMATION ObjectTypeInfo;
  211. LARGE_INTEGER SectionSize;
  212. Status = STATUS_SUCCESS;
  213. DbgPrint( "Entering Object Manager User Mode Test Program\n" );
  214. RtlInitString( &SectionName, "\\A:\\OSO001.MSG" );
  215. InitializeObjectAttributes( &ObjectAttributes,
  216. &SectionName,
  217. OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
  218. NULL,
  219. NULL
  220. );
  221. SectionSize.LowPart = 0x1000;
  222. SectiinSize.HighPart = 0;
  223. Status = NtCreateSection( &SectionHandle,
  224. GENERIC_READ,
  225. &ObjectAttributes,
  226. &SectionSize,
  227. PAGE_READONLY,
  228. SEC_RESERVE,
  229. NULL
  230. );
  231. if (!NT_SUCCESS( Status )) {
  232. DbgPrint( "Unable to create %Z section object (%X) [OK]\n", &SectionName, Status );
  233. }
  234. RtlInitString( &DirectoryName, "\\Drives" );
  235. InitializeObjectAttributes( &ObjectAttributes,
  236. &DirectoryName,
  237. OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
  238. NULL,
  239. (PSECURITY_DESCRIPTOR)1
  240. );
  241. ObjectAttributes.Length = 0;
  242. Status = NtCreateDirectoryObject( &DirectoryHandle,
  243. -1,
  244. &ObjectAttributes
  245. );
  246. if (!NT_SUCCESS( Status )) {
  247. DbgPrint( "Unable to create %Z directory object (%X) [OK]\n",
  248. &DirectoryName, Status );
  249. }
  250. RtlInitString( &DirectoryName, "\\Drives" );
  251. InitializeObjectAttributes( &ObjectAttributes,
  252. &DirectoryName,
  253. OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
  254. NULL,
  255. (PSECURITY_DESCRIPTOR)1
  256. );
  257. ObjectAttributes.Length = 0;
  258. Status = NtCreateDirectoryObject( &DirectoryHandle,
  259. DIRECTORY_ALL_ACCESS,
  260. &ObjectAttributes
  261. );
  262. if (!NT_SUCCESS( Status )) {
  263. DbgPrint( "Unable to create %Z directory object (%X) [OK]\n",
  264. &DirectoryName, Status );
  265. }
  266. InitializeObjectAttributes( &ObjectAttributes,
  267. &DirectoryName,
  268. -1,
  269. NULL,
  270. (PSECURITY_DESCRIPTOR)1
  271. );
  272. Status = NtCreateDirectoryObject( &DirectoryHandle,
  273. DIRECTORY_ALL_ACCESS,
  274. &ObjectAttributes
  275. );
  276. if (!NT_SUCCESS( Status )) {
  277. DbgPrint( "Unable to create %Z directory object (%X) [OK]\n",
  278. &DirectoryName, Status );
  279. }
  280. InitializeObjectAttributes( &ObjectAttributes,
  281. &DirectoryName,
  282. OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
  283. NULL,
  284. (PSECURITY_DESCRIPTOR)1
  285. );
  286. Status = NtCreateDirectoryObject( &DirectoryHandle,
  287. DIRECTORY_ALL_ACCESS,
  288. &ObjectAttributes
  289. );
  290. if (!NT_SUCCESS( Status )) {
  291. DbgPrint( "Unable to create %Z directory object (%X) [OK]\n",
  292. &DirectoryName, Status );
  293. }
  294. InitializeObjectAttributes( &ObjectAttributes,
  295. &DirectoryName,
  296. OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
  297. NULL,
  298. NULL
  299. );
  300. Status = NtCreateDirectoryObject( &DirectoryHandle,
  301. DIRECTORY_ALL_ACCESS,
  302. &ObjectAttributes
  303. );
  304. if (!NT_SUCCESS( Status )) {
  305. DbgPrint( "Unable to create %Z directory object (%X)\n",
  306. &DirectoryName, Status );
  307. NtTerminateProcess( NtCurrentProcess(), Status );
  308. }
  309. Status = NtClose( DirectoryHandle );
  310. if (!NT_SUCCESS( Status )) {
  311. DbgPrint( "Unable to close %Z directory object handle - %lx (%X)\n",
  312. &DirectoryName,
  313. DirectoryHandle,
  314. Status
  315. );
  316. NtTerminateProcess( NtCurrentProcess(), Status );
  317. }
  318. InitializeObjectAttributes( &ObjectAttributes,
  319. &DirectoryName,
  320. OBJ_CASE_INSENSITIVE,
  321. NULL,
  322. NULL
  323. );
  324. Status = NtOpenDirectoryObject( &DirectoryHandle,
  325. DIRECTORY_ALL_ACCESS,
  326. &ObjectAttributes
  327. );
  328. if (!NT_SUCCESS( Status )) {
  329. DbgPrint( "Unable to open %Z directory object (%X)\n",
  330. &DirectoryName, Status );
  331. NtTerminateProcess( NtCurrentProcess(), Status );
  332. }
  333. Status = NtQueryObject( DirectoryHandle,
  334. ObjectBasicInformation,
  335. &ObjectBasicInfo,
  336. sizeof( ObjectBasicInfo ),
  337. &ReturnedLength
  338. );
  339. if (!NT_SUCCESS( Status )) {
  340. DbgPrint( "NtQueryObject( %lx, ObjectBasicInfo ) failed - Status == %X\n",
  341. DirectoryHandle,
  342. Status
  343. );
  344. NtTerminateProcess( NtCurrentProcess(), Status );
  345. }
  346. DbgPrint( "NtQueryObject( %lx, ObjectBasicInfo ) returned %lx bytes\n",
  347. DirectoryHandle,
  348. ReturnedLength
  349. );
  350. DbgPrint( " Attributes = %lx\n", ObjectBasicInfo.Attributes );
  351. DbgPrint( " GrantedAccess = %lx\n", ObjectBasicInfo.GrantedAccess );
  352. DbgPrint( " HandleCount = %lx\n", ObjectBasicInfo.HandleCount );
  353. DbgPrint( " PointerCount = %lx\n", ObjectBasicInfo.PointerCount );
  354. DbgPrint( " PagedPoolCharge = %lx\n", ObjectBasicInfo.PagedPoolCharge );
  355. DbgPrint( " NonPagedPoolCharge = %lx\n", ObjectBasicInfo.NonPagedPoolCharge );
  356. DbgPrint( " NameInfoSize = %lx\n", ObjectBasicInfo.NameInfoSize );
  357. DbgPrint( " TypeInfoSize = %lx\n", ObjectBasicInfo.TypeInfoSize );
  358. DbgPrint( " SecurityDescriptorSize = %lx\n", ObjectBasicInfo.SecurityDescriptorSize );
  359. ObjectNameInfo = (POBJECT_NAME_INFORMATION)ObjectInfoBuffer;
  360. Status = NtQueryObject( DirectoryHandle,
  361. ObjectNameInformation,
  362. ObjectNameInfo,
  363. sizeof( ObjectInfoBuffer ),
  364. &ReturnedLength
  365. );
  366. if (!NT_SUCCESS( Status )) {
  367. DbgPrint( "NtQueryObject( %lx, ObjectNameInfo ) failed - Status == %X\n",
  368. DirectoryHandle,
  369. Status
  370. );
  371. NtTerminateProcess( NtCurrentProcess(), Status );
  372. }
  373. DbgPrint( "NtQueryObject( %lx, ObjectNameInfo ) returned %lx bytes\n",
  374. DirectoryHandle,
  375. ReturnedLength
  376. );
  377. DbgPrint( " Name = (%ld,%ld) '%Z'\n",
  378. ObjectNameInfo->Name.MaximumLength,
  379. ObjectNameInfo->Name.Length,
  380. &ObjectNameInfo->Name
  381. );
  382. ObjectTypeInfo = (POBJECT_TYPE_INFORMATION)ObjectInfoBuffer;
  383. Status = NtQueryObject( DirectoryHandle,
  384. ObjectTypeInformation,
  385. ObjectTypeInfo,
  386. sizeof( ObjectInfoBuffer ),
  387. &ReturnedLength
  388. );
  389. if (!NT_SUCCESS( Status )) {
  390. DbgPrint( "NtQueryObject( %lx, ObjectTypeInfo ) failed - Status == %X\n",
  391. DirectoryHandle,
  392. Status
  393. );
  394. NtTerminateProcess( NtCurrentProcess(), Status );
  395. }
  396. DbgPrint( "NtQueryObject( %lx, ObjectTypeInfo ) returned %lx bytes\n",
  397. DirectoryHandle,
  398. ReturnedLength
  399. );
  400. DbgPrint( " TypeName = (%ld,%ld) '%Z'\n",
  401. ObjectTypeInfo->TypeName.MaximumLength,
  402. ObjectTypeInfo->TypeName.Length,
  403. &ObjectTypeInfo->TypeName
  404. );
  405. RtlInitString( &LinkName, "TestSymbolicLink" );
  406. InitializeObjectAttributes( &ObjectAttributes,
  407. &LinkName,
  408. OBJ_CASE_INSENSITIVE,
  409. NULL,
  410. NULL
  411. );
  412. ObjectAttributes.RootDirectory = DirectoryHandle;
  413. RtlInitString( &LinkTarget, "\\Device\\FileSystem" );
  414. Status = NtCreateSymbolicLinkObject( &LinkHandle,
  415. SYMBOLIC_LINK_ALL_ACCESS,
  416. &ObjectAttributes,
  417. &LinkTarget
  418. );
  419. if (!NT_SUCCESS( Status )) {
  420. DbgPrint( "Unable to create %Z => %Z symbolic link object (%X)\n",
  421. &LinkName, &LinkTarget, Status );
  422. NtTerminateProcess( NtCurrentProcess(), Status );
  423. }
  424. Status = NtClose( DirectoryHandle );
  425. if (!NT_SUCCESS( Status )) {
  426. DbgPrint( "Unable to close %Z directory object handle - %lx (%X)\n",
  427. &DirectoryName,
  428. DirectoryHandle,
  429. Status
  430. );
  431. NtTerminateProcess( NtCurrentProcess(), Status );
  432. }
  433. RtlInitString( &DirTypeName, "Directory" );
  434. RtlInitString( &LinkTypeName, "SymbolicLink" );
  435. DumpObjectDirs( "\\", 0 );
  436. RtlInitString( &LinkName, "TestSymbolicLink" );
  437. InitializeObjectAttributes( &ObjectAttributes,
  438. &LinkName,
  439. OBJ_CASE_INSENSITIVE,
  440. NULL,
  441. NULL
  442. );
  443. ObjectAttributes.RootDirectory = LinkHandle;
  444. Status = NtOpenDirectoryObject( &DirectoryHandle,
  445. DIRECTORY_ALL_ACCESS,
  446. &ObjectAttributes
  447. );
  448. if (!NT_SUCCESS( Status )) {
  449. DbgPrint( "Unable to open %Z directory object (%X) [OK]\n", &DirectoryName, Status );
  450. }
  451. Status = NtClose( LinkHandle );
  452. if (!NT_SUCCESS( Status )) {
  453. DbgPrint( "Unable to close %Z symbolic link handle - %lx (%X)\n",
  454. &LinkName,
  455. LinkHandle,
  456. Status
  457. );
  458. NtTerminateProcess( NtCurrentProcess(), Status );
  459. }
  460. InitializeObjectAttributes( &ObjectAttributes,
  461. &DirectoryName,
  462. OBJ_CASE_INSENSITIVE,
  463. NULL,
  464. NULL
  465. );
  466. Status = NtOpenDirectoryObject( &DirectoryHandle,
  467. DIRECTORY_ALL_ACCESS,
  468. &ObjectAttributes
  469. );
  470. if (!NT_SUCCESS( Status )) {
  471. DbgPrint( "Unable to open %Z directory object (%X)\n", &DirectoryName, Status );
  472. NtTerminateProcess( NtCurrentProcess(), Status );
  473. }
  474. Status = NtMakeTemporaryObject( DirectoryHandle );
  475. if (!NT_SUCCESS( Status )) {
  476. DbgPrint( "NtMakeTemporaryObject( %lx ) failed - Status == %X\n",
  477. DirectoryHandle,
  478. Status
  479. );
  480. NtTerminateProcess( NtCurrentProcess(), Status );
  481. }
  482. Status = NtClose( DirectoryHandle );
  483. if (!NT_SUCCESS( Status )) {
  484. DbgPrint( "Unable to close %Z directory object handle - %lx (%X)\n",
  485. &DirectoryName,
  486. DirectoryHandle,
  487. Status
  488. );
  489. NtTerminateProcess( NtCurrentProcess(), Status );
  490. }
  491. InitializeObjectAttributes( &ObjectAttributes,
  492. &DirectoryName,
  493. OBJ_CASE_INSENSITIVE,
  494. NULL,
  495. NULL
  496. );
  497. Status = NtOpenDirectoryObject( &DirectoryHandle,
  498. DIRECTORY_ALL_ACCESS,
  499. &ObjectAttributes
  500. );
  501. if (!NT_SUCCESS( Status )) {
  502. DbgPrint( "Unable to open %Z directory object (%X) [OK]\n", &DirectoryName, Status );
  503. }
  504. RtlInitString( &DirectoryName, "\\ExclusiveDir" );
  505. InitializeObjectAttributes( &ObjectAttributes,
  506. &DirectoryName,
  507. OBJ_CASE_INSENSITIVE | OBJ_EXCLUSIVE,
  508. NULL,
  509. NULL
  510. );
  511. Status = NtCreateDirectoryObject( &DirectoryHandle,
  512. DIRECTORY_ALL_ACCESS,
  513. &ObjectAttributes
  514. );
  515. if (!NT_SUCCESS( Status )) {
  516. DbgPrint( "Unable to create %Z directory object (%X)\n",
  517. &DirectoryName, Status );
  518. NtTerminateProcess( NtCurrentProcess(), Status );
  519. }
  520. InitializeObjectAttributes( &ObjectAttributes,
  521. &DirectoryName,
  522. OBJ_CASE_INSENSITIVE | OBJ_EXCLUSIVE,
  523. NULL,
  524. NULL
  525. );
  526. Status = NtOpenDirectoryObject( &DirectoryHandle,
  527. DIRECTORY_ALL_ACCESS,
  528. &ObjectAttributes
  529. );
  530. if (!NT_SUCCESS( Status )) {
  531. DbgPrint( "Unable to open %Z directory object (%X)\n",
  532. &DirectoryName, Status );
  533. NtTerminateProcess( NtCurrentProcess(), Status );
  534. }
  535. InitializeObjectAttributes( &ObjectAttributes,
  536. &DirectoryName,
  537. OBJ_CASE_INSENSITIVE,
  538. NULL,
  539. NULL
  540. );
  541. Status = NtOpenDirectoryObject( &DirectoryHandle,
  542. DIRECTORY_ALL_ACCESS,
  543. &ObjectAttributes
  544. );
  545. if (!NT_SUCCESS( Status )) {
  546. DbgPrint( "Unable to open %Z directory object (%X) [OK]\n",
  547. &DirectoryName, Status );
  548. }
  549. DbgPrint( "Exiting Object Manager User Mode Test Program with Status = %X\n", Status );
  550. }
  551. VOID
  552. TestChild( VOID )
  553. {
  554. NTSTATUS Status;
  555. STRING DirectoryName;
  556. HANDLE DirectoryHandle;
  557. OBJECT_ATTRIBUTES ObjectAttributes;
  558. Status = STATUS_SUCCESS;
  559. DbgPrint( "Entering Object Manager User Mode Child Test Program\n" );
  560. RtlInitString( &DirectoryName, "\\ExclusiveDir" );
  561. InitializeObjectAttributes( &ObjectAttributes,
  562. &DirectoryName,
  563. OBJ_CASE_INSENSITIVE,
  564. NULL,
  565. NULL
  566. );
  567. Status = NtOpenDirectoryObject( &DirectoryHandle,
  568. DIRECTORY_ALL_ACCESS,
  569. &ObjectAttributes
  570. );
  571. if (!NT_SUCCESS( Status )) {
  572. DbgPrint( "Unable to open %Z directory object (%X) [OK]\n",
  573. &DirectoryName, Status );
  574. }
  575. InitializeObjectAttributes( &ObjectAttributes,
  576. &DirectoryName,
  577. OBJ_CASE_INSENSITIVE | OBJ_EXCLUSIVE,
  578. NULL,
  579. NULL
  580. );
  581. Status = NtOpenDirectoryObject( &DirectoryHandle,
  582. DIRECTORY_ALL_ACCESS,
  583. &ObjectAttributes
  584. );
  585. if (!NT_SUCCESS( Status )) {
  586. DbgPrint( "Unable to open %Z directory object (%X) [OK]\n",
  587. &DirectoryName, Status );
  588. }
  589. DbgPrint( "Exiting Object Manager User Mode Child Test Program with Status = %X\n", Status );
  590. }