2 * NTOSKRNL Ob Regressions KM-Test
3 * ReactOS Kernel Mode Regression Testing framework
5 * Copyright 2006 Aleksey Bragin <aleksey@reactos.org>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; see the file COPYING.LIB.
19 * If not, write to the Free Software Foundation,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 /* INCLUDES *******************************************************************/
25 #include <ddk/ntddk.h>
31 #include "ndk/obtypes.h"
32 #include "ndk/obfuncs.h"
34 #include "ndk/ifssupp.h"
35 #include "ndk/setypes.h"
36 #include "ndk/sefuncs.h"
38 // I ment to make this test scalable, but for now
39 // we work with two object types only
42 typedef struct _MY_OBJECT1
45 } MY_OBJECT1
, *PMY_OBJECT1
;
47 typedef struct _MY_OBJECT2
51 } MY_OBJECT2
, *PMY_OBJECT2
;
53 POBJECT_TYPE ObTypes
[NUM_OBTYPES
];
54 UNICODE_STRING ObTypeName
[NUM_OBTYPES
];
55 UNICODE_STRING ObName
[NUM_OBTYPES
];
56 OBJECT_TYPE_INITIALIZER ObTypeInitializer
[NUM_OBTYPES
];
57 UNICODE_STRING ObDirectoryName
;
58 OBJECT_ATTRIBUTES ObDirectoryAttributes
;
59 OBJECT_ATTRIBUTES ObAttributes
[NUM_OBTYPES
];
60 PVOID ObBody
[NUM_OBTYPES
];
61 PMY_OBJECT1 ObObject1
;
62 PMY_OBJECT2 ObObject2
;
63 HANDLE ObHandle1
[NUM_OBTYPES
];
64 HANDLE ObHandle2
[NUM_OBTYPES
];
65 HANDLE DirectoryHandle
;
67 USHORT DumpCount
, OpenCount
, CloseCount
, DeleteCount
,
68 ParseCount
, OkayToCloseCount
, QueryNameCount
;
70 /* PRIVATE FUNCTIONS **********************************************************/
74 DumpProc(IN PVOID Object
,
75 IN POB_DUMP_CONTROL DumpControl
)
77 DbgPrint("DumpProc() called\n");
84 OpenProc(IN OB_OPEN_REASON OpenReason
,
87 IN ACCESS_MASK GrantedAccess
,
90 DbgPrint("OpenProc() 0x%p, OpenReason %d, HC %d, AM 0x%X\n",
91 Object
, OpenReason
, HandleCount
, GrantedAccess
);
98 CloseProc(IN PEPROCESS Process
,
100 IN ACCESS_MASK GrantedAccess
,
101 IN ULONG ProcessHandleCount
,
102 IN ULONG SystemHandleCount
)
104 DbgPrint("CloseProc() 0x%p, PHC %d, SHC %d, AM 0x%X\n", Object
,
105 ProcessHandleCount
, SystemHandleCount
, GrantedAccess
);
112 DeleteProc(IN PVOID Object
)
114 DbgPrint("DeleteProc() 0x%p\n", Object
);
120 ParseProc(IN PVOID ParseObject
,
122 IN OUT PACCESS_STATE AccessState
,
123 IN KPROCESSOR_MODE AccessMode
,
125 IN OUT PUNICODE_STRING CompleteName
,
126 IN OUT PUNICODE_STRING RemainingName
,
127 IN OUT PVOID Context OPTIONAL
,
128 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
131 DbgPrint("ParseProc() called\n");
135 return STATUS_OBJECT_NAME_NOT_FOUND
;//STATUS_SUCCESS;
141 OkayToCloseProc(IN PEPROCESS Process OPTIONAL
,
144 IN KPROCESSOR_MODE AccessMode
)
146 DbgPrint("OkayToCloseProc() 0x%p, H 0x%p, AM 0x%X\n", Object
, Handle
,
149 return STATUS_SUCCESS
;
154 QueryNameProc(IN PVOID Object
,
155 IN BOOLEAN HasObjectName
,
156 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
158 OUT PULONG ReturnLength
,
159 IN KPROCESSOR_MODE AccessMode
)
161 DbgPrint("QueryNameProc() 0x%p, HON %d, Len %d, AM 0x%X\n",
162 Object
, HasObjectName
, Length
, AccessMode
);
165 ObjectNameInfo
= NULL
;
167 return STATUS_OBJECT_NAME_NOT_FOUND
;
172 ObtCreateObjectTypes()
178 for (i
=0; i
<NUM_OBTYPES
; i
++)
180 // Prepare object type name
181 // TODO: Generate type names and don't use this unprofessional,
182 swprintf(Name
, L
"MyObjectType%lx", i
);
183 RtlInitUnicodeString(&ObTypeName
[i
], Name
);
185 // Prepare initializer
186 RtlZeroMemory(&ObTypeInitializer
[i
], sizeof(ObTypeInitializer
[i
]));
187 ObTypeInitializer
[i
].Length
= sizeof(ObTypeInitializer
[i
]);
188 ObTypeInitializer
[i
].PoolType
= NonPagedPool
;
189 ObTypeInitializer
[i
].MaintainHandleCount
= TRUE
;
190 ObTypeInitializer
[i
].ValidAccessMask
= OBJECT_TYPE_ALL_ACCESS
;
192 // Test for invalid parameter
193 // FIXME: Make it more exact, to see which params Win2k3 checks
195 Status
= ObCreateObjectType(&ObTypeName
[i
], &ObTypeInitializer
[i
],
196 (PSECURITY_DESCRIPTOR
)NULL
, &ObTypes
[i
]);
197 ok(Status
== STATUS_INVALID_PARAMETER
,
198 "ObCreateObjectType returned 0x%lX", Status
);
201 ObTypeInitializer
[i
].CloseProcedure
= (OB_CLOSE_METHOD
)CloseProc
;
202 ObTypeInitializer
[i
].DeleteProcedure
= (OB_DELETE_METHOD
)DeleteProc
;
203 ObTypeInitializer
[i
].DumpProcedure
= (OB_DUMP_METHOD
)DumpProc
;
204 ObTypeInitializer
[i
].OpenProcedure
= (OB_OPEN_METHOD
)OpenProc
;
205 ObTypeInitializer
[i
].ParseProcedure
= (OB_PARSE_METHOD
)ParseProc
;
206 //ObTypeInitializer[i].OkayToCloseProcedure =
207 // (OB_OKAYTOCLOSE_METHOD)OkayToCloseProc;
209 //ObTypeInitializer[i].QueryNameProcedure =
210 // (OB_QUERYNAME_METHOD)QueryNameProc;
212 //ObTypeInitializer[i].SecurityProcedure =
213 // (OB_SECURITY_METHOD)SecurityProc;
215 Status
= ObCreateObjectType(&ObTypeName
[i
], &ObTypeInitializer
[i
],
216 (PSECURITY_DESCRIPTOR
)NULL
, &ObTypes
[i
]);
217 ok(Status
== STATUS_SUCCESS
,
218 "Failed to create object type with status=0x%lX", Status
);
227 // Directory will have permanent and case insensitive flags
228 RtlInitUnicodeString(&ObDirectoryName
, L
"\\ObtDirectory");
229 InitializeObjectAttributes(&ObDirectoryAttributes
, &ObDirectoryName
,
230 OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
232 Status
= ZwCreateDirectoryObject(&DirectoryHandle
, 0, &ObDirectoryAttributes
);
233 ok(Status
== STATUS_SUCCESS
,
234 "Failed to create directory object with status=0x%lX", Status
);
242 USHORT OpenSave
, CloseSave
, DeleteSave
, ParseSave
,
243 OkayToCloseSave
, QueryNameSave
;
245 // Create two objects
246 RtlInitUnicodeString(&ObName
[0], L
"\\ObtDirectory\\MyObject1");
247 InitializeObjectAttributes(&ObAttributes
[0], &ObName
[0],
248 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
250 RtlInitUnicodeString(&ObName
[1], L
"\\ObtDirectory\\MyObject2");
251 InitializeObjectAttributes(&ObAttributes
[1], &ObName
[1],
252 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
254 Status
= ObCreateObject(KernelMode
, ObTypes
[0], &ObAttributes
[0],
255 KernelMode
, NULL
, (ULONG
)sizeof(MY_OBJECT1
), 0L, 0L,
256 (PVOID
*)&ObBody
[0]);
257 ok(Status
== STATUS_SUCCESS
,
258 "Failed to create object with status=0x%lX", Status
);
260 Status
= ObCreateObject(KernelMode
, ObTypes
[1], &ObAttributes
[1],
261 KernelMode
, NULL
, (ULONG
)sizeof(MY_OBJECT2
), 0L, 0L,
262 (PVOID
*)&ObBody
[1]);
263 ok(Status
== STATUS_SUCCESS
,
264 "Failed to create object with status=0x%lX", Status
);
267 OpenSave
=OpenCount
; CloseSave
=CloseCount
; DeleteSave
=DeleteCount
;
268 ParseSave
=ParseCount
; OkayToCloseSave
=OkayToCloseCount
;
269 QueryNameSave
=QueryNameCount
;
272 Status
= ObInsertObject(ObBody
[0], NULL
, STANDARD_RIGHTS_ALL
, 0,
273 &ObBody
[0], &ObHandle1
[0]);
274 ok(Status
== STATUS_SUCCESS
,
275 "Failed to insert object 0 with status=0x%lX", Status
);
276 ok(ObBody
[0] != NULL
, "Object body = NULL");
277 ok(ObHandle1
[0] != NULL
, "Handle = NULL");
280 ok(OpenSave
+1 == OpenCount
, "Open method calls mismatch\n");
281 ok(CloseSave
== CloseCount
, "Excessive Close method call\n");
282 ok(DeleteSave
== DeleteCount
, "Excessive Delete method call\n");
283 ok(ParseSave
== ParseCount
, "Excessive Parse method call\n");
286 OpenSave
=OpenCount
; CloseSave
=CloseCount
; DeleteSave
=DeleteCount
;
287 ParseSave
=ParseCount
; OkayToCloseSave
=OkayToCloseCount
;
288 QueryNameSave
=QueryNameCount
;
290 Status
= ObInsertObject(ObBody
[1], NULL
, GENERIC_ALL
, 0,
291 &ObBody
[1], &ObHandle1
[1]);
292 ok(Status
== STATUS_SUCCESS
,
293 "Failed to insert object 1 with status=0x%lX", Status
);
294 ok(ObBody
[1] != NULL
, "Object body = NULL");
295 ok(ObHandle1
[1] != NULL
, "Handle = NULL");
298 ok(OpenSave
+1 == OpenCount
, "Open method calls mismatch\n");
299 ok(CloseSave
== CloseCount
, "Excessive Close method call\n");
300 ok(DeleteSave
== DeleteCount
, "Excessive Delete method call\n");
301 ok(ParseSave
== ParseCount
, "Excessive Parse method call\n");
304 OpenSave
=OpenCount
; CloseSave
=CloseCount
; DeleteSave
=DeleteCount
;
305 ParseSave
=ParseCount
; OkayToCloseSave
=OkayToCloseCount
;
306 QueryNameSave
=QueryNameCount
;
308 // Now create an object of type 0, of the same name and expect it to fail
309 // inserting, but success creation
310 RtlInitUnicodeString(&ObName
[0], L
"\\ObtDirectory\\MyObject1");
311 InitializeObjectAttributes(&ObAttributes
[0], &ObName
[0], OBJ_OPENIF
,
314 Status
= ObCreateObject(KernelMode
, ObTypes
[0], &ObAttributes
[0], KernelMode
,
315 NULL
, (ULONG
)sizeof(MY_OBJECT1
), 0L, 0L, (PVOID
*)&ObBody1
[0]);
316 ok(Status
== STATUS_SUCCESS
,
317 "Failed to create object with status=0x%lX", Status
);
320 ok(OpenSave
== OpenCount
, "Excessive Open method call\n");
321 ok(CloseSave
== CloseCount
, "Excessive Close method call\n");
322 ok(DeleteSave
== DeleteCount
, "Excessive Delete method call\n");
323 ok(ParseSave
== ParseCount
, "Excessive Parse method call\n");
325 Status
= ObInsertObject(ObBody1
[0], NULL
, GENERIC_ALL
, 0,
326 &ObBody1
[1], &ObHandle2
[0]);
327 ok(Status
== STATUS_OBJECT_NAME_EXISTS
,
328 "Object insertion should have failed, but got 0x%lX", Status
);
329 ok(ObBody
[0] == ObBody1
[1],
330 "Object bodies doesn't match, 0x%p != 0x%p", ObBody
[0], ObBody1
[1]);
331 ok(ObHandle2
[0] != NULL
, "Bad handle returned 0x%lX", (ULONG
)ObHandle2
[0]);
333 DPRINT1("%d %d %d %d %d %d %d\n", DumpCount
, OpenCount
, // deletecount+1
334 CloseCount
, DeleteCount
, ParseCount
, OkayToCloseCount
, QueryNameCount
);
336 // check counters and then save
337 ok(OpenSave
+1 == OpenCount
, "Excessive Open method call\n");
338 ok(CloseSave
== CloseCount
, "Excessive Close method call\n");
339 ok(DeleteSave
+1 == DeleteCount
, "Delete method call mismatch\n");
340 ok(ParseSave
== ParseCount
, "Excessive Parse method call\n");
341 OpenSave
=OpenCount
; CloseSave
=CloseCount
; DeleteSave
=DeleteCount
;
342 ParseSave
=ParseCount
; OkayToCloseSave
=OkayToCloseCount
;
343 QueryNameSave
=QueryNameCount
;
346 Status
= ZwClose(ObHandle2
[0]);
347 ok(Status
== STATUS_SUCCESS
,
348 "Failed to close handle status=0x%lX", Status
);
350 // check counters and then save
351 ok(OpenSave
== OpenCount
, "Excessive Open method call\n");
352 ok(CloseSave
+1 == CloseCount
, "Close method call mismatch\n");
353 ok(DeleteSave
== DeleteCount
, "Excessive Delete method call\n");
354 ok(ParseSave
== ParseCount
, "Excessive Parse method call\n");
355 OpenSave
=OpenCount
; CloseSave
=CloseCount
; DeleteSave
=DeleteCount
;
356 ParseSave
=ParseCount
; OkayToCloseSave
=OkayToCloseCount
;
357 QueryNameSave
=QueryNameCount
;
360 // Object referenced 2 times:
362 // 2) AdditionalReferences
363 ObDereferenceObject(ObBody1
[1]);
365 //DPRINT1("%d %d %d %d %d %d %d\n", DumpCount, OpenCount, // no change
366 // CloseCount, DeleteCount, ParseCount, OkayToCloseCount, QueryNameCount);
367 ok(OpenSave
== OpenCount
, "Open method call mismatch\n");
368 ok(CloseSave
== CloseCount
, "Close method call mismatch\n");
369 ok(DeleteSave
== DeleteCount
, "Delete method call mismatch\n");
370 ok(ParseSave
== ParseCount
, "Parse method call mismatch\n");
380 //UNICODE_STRING ObPathName[NUM_OBTYPES];
382 // Close what we have opened and free what we allocated
383 ZwClose(ObHandle1
[0]);
384 ZwClose(ObHandle1
[1]);
385 ZwClose(ObHandle2
[0]);
386 ZwClose(ObHandle2
[1]);
388 // Now we have to get rid of a directory object
389 // Since it is permanent, we have to firstly make it temporary
390 // and only then kill
391 // (this procedure is described in DDK)
392 Status
= ObReferenceObjectByHandle(DirectoryHandle
, 0L, NULL
,
393 KernelMode
, &DirObject
, NULL
);
394 ok(Status
== STATUS_SUCCESS
,
395 "Failed to reference object by handle with status=0x%lX", Status
);
397 // Dereference 2 times - first for just previous referencing
398 // and 2nd time for creation of permanent object itself
399 ObDereferenceObject(DirObject
);
400 ObDereferenceObject(DirObject
);
402 Status
= ZwMakeTemporaryObject(DirectoryHandle
);
403 ok(Status
== STATUS_SUCCESS
,
404 "Failed to make temp object with status=0x%lX", Status
);
406 // Close the handle now and we are done
407 Status
= ZwClose(DirectoryHandle
);
408 ok(Status
== STATUS_SUCCESS
,
409 "Failed to close handle with status=0x%lX", Status
);
411 // Now delete the last piece - object types
412 // In fact, it's weird to get rid of object types, especially the way,
413 // how it's done in the commented section below
414 for (i
=0; i
<NUM_OBTYPES
; i
++)
415 ObDereferenceObject(ObTypes
[i
]);
417 RtlInitUnicodeString(&ObPathName[0], L"\\ObjectTypes\\MyObjectType1");
418 RtlInitUnicodeString(&ObPathName[1], L"\\ObjectTypes\\MyObjectType2");
420 for (i=0; i<NUM_OBTYPES; i++)
422 Status = ObReferenceObjectByName(&ObPathName[i],
423 OBJ_CASE_INSENSITIVE, NULL, 0L, NULL, KernelMode, NULL,
426 ObDereferenceObject(TypeObject);
427 ObDereferenceObject(TypeObject);
428 DPRINT("Reference Name %S = %p, ObTypes[%d] = %p\n",
429 ObPathName[i], TypeObject, i, ObTypes[i]);
439 UNICODE_STRING ObPathName
[NUM_OBTYPES
];
441 // Reference them by handle
442 for (i
=0; i
<NUM_OBTYPES
; i
++)
444 Status
= ObReferenceObjectByHandle(ObHandle1
[i
], 0L, ObTypes
[i
],
445 KernelMode
, &ObBody
[i
], NULL
);
446 ok(Status
== STATUS_SUCCESS
,
447 "Failed to reference object by handle, status=0x%lX", Status
);
448 DPRINT("Ref by handle %lx = %p\n", ObHandle1
[i
], ObBody
[i
]);
451 // Reference them by pointer
452 for (i
=0; i
<NUM_OBTYPES
; i
++)
454 Status
= ObReferenceObjectByPointer(ObBody
[i
], 0L, ObTypes
[i
], KernelMode
);
455 ok(Status
== STATUS_SUCCESS
,
456 "Failed to reference object by pointer, status=0x%lX", Status
);
459 // Reference them by name
460 RtlInitUnicodeString(&ObPathName
[0], L
"\\ObtDirectory\\MyObject1");
461 RtlInitUnicodeString(&ObPathName
[1], L
"\\ObtDirectory\\MyObject2");
463 for (i
=0; i
<NUM_OBTYPES
; i
++)
465 Status
= ObReferenceObjectByName(&ObPathName
[i
],
466 OBJ_CASE_INSENSITIVE
, NULL
, 0L, ObTypes
[i
], KernelMode
, NULL
,
469 DPRINT("Ref by name %wZ = %p\n", &ObPathName
[i
], ObBody
[i
]);
472 // Dereference now all of them
474 // For ObInsertObject, AdditionalReference
475 ObDereferenceObject(ObBody
[0]);
476 ObDereferenceObject(ObBody
[1]);
479 ObDereferenceObject(ObBody
[0]);
480 ObDereferenceObject(ObBody
[1]);
483 ObDereferenceObject(ObBody
[0]);
484 ObDereferenceObject(ObBody
[1]);
487 ObDereferenceObject(ObBody
[0]);
488 ObDereferenceObject(ObBody
[1]);
491 /* PUBLIC FUNCTIONS ***********************************************************/
499 DumpCount
= 0; OpenCount
= 0; CloseCount
= 0;
500 DeleteCount
= 0; ParseCount
= 0;
502 // Create object-types to use in tests
503 ObtCreateObjectTypes();
504 DPRINT("ObtCreateObjectTypes() done\n");
507 ObtCreateDirectory();
508 DPRINT("ObtCreateDirectory() done\n");
510 // Create and insert objects
512 DPRINT("ObtCreateObjects() done\n");
514 // Reference them in a variety of ways
515 //ObtReferenceTests();
518 // FIXME: Disable to see results of creating objects in usermode.
519 // Also it has problems with object types removal
521 DPRINT("Cleanup done\n");
523 FinishTest("NTOSKRNL Ob Manager");