1 /* 2 * PROJECT: ReactOS kernel-mode tests 3 * LICENSE: GPLv2+ - See COPYING in the top level directory 4 * PURPOSE: Kernel-Mode Test Suite Object Referencing test 5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org> 6 */ 7 8 #include <kmt_test.h> 9 #define NDEBUG 10 #include <debug.h> 11 12 #define CheckObject(Handle, Pointers, Handles) do \ 13 { \ 14 PUBLIC_OBJECT_BASIC_INFORMATION ObjectInfo; \ 15 Status = ZwQueryObject(Handle, ObjectBasicInformation, \ 16 &ObjectInfo, sizeof ObjectInfo, NULL); \ 17 ok_eq_hex(Status, STATUS_SUCCESS); \ 18 ok_eq_ulong(ObjectInfo.PointerCount, Pointers); \ 19 ok_eq_ulong(ObjectInfo.HandleCount, Handles); \ 20 } while (0) 21 22 static POBJECT_TYPE ObDirectoryObjectType; 23 24 static 25 VOID 26 TestReference( 27 IN HANDLE Handle, 28 IN PUNICODE_STRING Name OPTIONAL, 29 IN PUNICODE_STRING NameUpper OPTIONAL, 30 IN BOOLEAN CaseSensitive, 31 IN ULONG AdditionalReferences, 32 IN BOOLEAN Permanent) 33 { 34 NTSTATUS Status; 35 LONG_PTR Ret; 36 PVOID Object = NULL; 37 PVOID Object2 = NULL; 38 PVOID Object3 = NULL; 39 PVOID Object4 = NULL; 40 41 CheckObject(Handle, 2LU + AdditionalReferences, 1LU); 42 43 Status = ObReferenceObjectByHandle(Handle, DIRECTORY_ALL_ACCESS, NULL, KernelMode, &Object, NULL); 44 ok_eq_hex(Status, STATUS_SUCCESS); 45 ok(Object != NULL, "ObReferenceObjectByHandle returned NULL object\n"); 46 CheckObject(Handle, 3LU + AdditionalReferences, 1LU); 47 48 Status = ObReferenceObjectByHandle(Handle, DIRECTORY_ALL_ACCESS, NULL, KernelMode, &Object2, NULL); 49 ok_eq_hex(Status, STATUS_SUCCESS); 50 ok(Object != NULL, "ObReferenceObjectByHandle returned NULL object\n"); 51 ok_eq_pointer(Object, Object2); 52 CheckObject(Handle, 4LU + AdditionalReferences, 1LU); 53 54 if (!skip(Object != NULL, "No object to reference!\n")) 55 { 56 Ret = ObReferenceObject(Object); 57 ok_eq_longptr(Ret, (LONG_PTR)4 + AdditionalReferences); 58 CheckObject(Handle, 5LU + AdditionalReferences, 1LU); 59 60 Ret = ObReferenceObject(Object); 61 ok_eq_longptr(Ret, (LONG_PTR)5 + AdditionalReferences); 62 CheckObject(Handle, 6LU + AdditionalReferences, 1LU); 63 64 Status = ObReferenceObjectByPointer(Object, DIRECTORY_ALL_ACCESS, NULL, KernelMode); 65 ok_eq_hex(Status, STATUS_SUCCESS); 66 CheckObject(Handle, 7LU + AdditionalReferences, 1LU); 67 68 Status = ObReferenceObjectByPointer(Object, DIRECTORY_ALL_ACCESS, NULL, KernelMode); 69 ok_eq_hex(Status, STATUS_SUCCESS); 70 CheckObject(Handle, 8LU + AdditionalReferences, 1LU); 71 72 Ret = ObDereferenceObject(Object); 73 ok_eq_longptr(Ret, (LONG_PTR)6 + AdditionalReferences); 74 CheckObject(Handle, 7LU + AdditionalReferences, 1LU); 75 76 Ret = ObDereferenceObject(Object); 77 ok_eq_longptr(Ret, (LONG_PTR)5 + AdditionalReferences); 78 CheckObject(Handle, 6LU + AdditionalReferences, 1LU); 79 80 Ret = ObDereferenceObject(Object); 81 ok_eq_longptr(Ret, (LONG_PTR)4 + AdditionalReferences); 82 CheckObject(Handle, 5LU + AdditionalReferences, 1LU); 83 84 Ret = ObDereferenceObject(Object); 85 ok_eq_longptr(Ret, (LONG_PTR)3 + AdditionalReferences); 86 CheckObject(Handle, 4LU + AdditionalReferences, 1LU); 87 } 88 89 if (Name && !skip(ObDirectoryObjectType != NULL, "No directory object type\n")) 90 { 91 Status = ObReferenceObjectByName(Name, 0, NULL, DIRECTORY_ALL_ACCESS, ObDirectoryObjectType, KernelMode, NULL, &Object3); 92 ok_eq_hex(Status, STATUS_SUCCESS); 93 CheckObject(Handle, 5LU + AdditionalReferences, 1LU); 94 } 95 96 if (NameUpper && !skip(ObDirectoryObjectType != NULL, "No directory object type\n")) 97 { 98 Status = ObReferenceObjectByName(NameUpper, 0, NULL, DIRECTORY_ALL_ACCESS, ObDirectoryObjectType, KernelMode, NULL, &Object4); 99 ok_eq_hex(Status, CaseSensitive ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_SUCCESS); 100 CheckObject(Handle, 5LU + AdditionalReferences + !CaseSensitive, 1LU); 101 } 102 103 if (NameUpper && !skip(Object4 != NULL, "No object to dereference\n")) 104 { 105 Ret = ObDereferenceObject(Object4); 106 ok_eq_longptr(Ret, (LONG_PTR)4 + AdditionalReferences); 107 CheckObject(Handle, 5LU + AdditionalReferences, 1LU); 108 } 109 if (Name && !skip(Object3 != NULL, "No object to dereference\n")) 110 { 111 Ret = ObDereferenceObject(Object3); 112 ok_eq_longptr(Ret, (LONG_PTR)3 + AdditionalReferences); 113 CheckObject(Handle, 4LU + AdditionalReferences, 1LU); 114 } 115 if (!skip(Object2 != NULL, "No object to dereference\n")) 116 { 117 Ret = ObDereferenceObject(Object2); 118 ok_eq_longptr(Ret, (LONG_PTR)2 + AdditionalReferences); 119 CheckObject(Handle, 3LU + AdditionalReferences, 1LU); 120 } 121 if (!skip(Object != NULL, "No object to dereference\n")) 122 { 123 Ret = ObDereferenceObject(Object); 124 ok_eq_longptr(Ret, (LONG_PTR)1 + AdditionalReferences); 125 CheckObject(Handle, 2LU + AdditionalReferences, 1LU); 126 } 127 128 CheckObject(Handle, 2LU + AdditionalReferences, 1LU); 129 130 if (Permanent) 131 { 132 Status = ZwMakeTemporaryObject(Handle); 133 ok_eq_hex(Status, STATUS_SUCCESS); 134 CheckObject(Handle, 2LU + AdditionalReferences, 1LU); 135 136 Status = ZwMakeTemporaryObject(Handle); 137 ok_eq_hex(Status, STATUS_SUCCESS); 138 CheckObject(Handle, 2LU + AdditionalReferences, 1LU); 139 } 140 } 141 142 START_TEST(ObReference) 143 { 144 NTSTATUS Status; 145 HANDLE DirectoryHandle = NULL; 146 OBJECT_ATTRIBUTES ObjectAttributes; 147 UNICODE_STRING Name, *pName; 148 UNICODE_STRING NameUpper, *pNameUpper; 149 ULONG i; 150 struct 151 { 152 PWSTR Name; 153 ULONG Flags; 154 ULONG AdditionalReferences; 155 } Tests[] = 156 { 157 { NULL, 0, 0 }, 158 { NULL, OBJ_CASE_INSENSITIVE, 0 }, 159 { NULL, OBJ_KERNEL_HANDLE, 0 }, 160 { NULL, OBJ_PERMANENT, 0 }, 161 { NULL, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 0 }, 162 { NULL, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0 }, 163 { NULL, OBJ_KERNEL_HANDLE | OBJ_PERMANENT, 0 }, 164 { NULL, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_PERMANENT, 0 }, 165 { L"\\YayDirectory0", 0, 1 }, 166 { L"\\YayDirectory1", OBJ_CASE_INSENSITIVE, 1 }, 167 { L"\\YayDirectory2", OBJ_KERNEL_HANDLE, 1 }, 168 { L"\\YayDirectory3", OBJ_PERMANENT, 1 }, 169 { L"\\YayDirectory4", OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 1 }, 170 { L"\\YayDirectory5", OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 1 }, 171 { L"\\YayDirectory6", OBJ_KERNEL_HANDLE | OBJ_PERMANENT, 1 }, 172 { L"\\YayDirectory7", OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_PERMANENT, 1 }, 173 }; 174 HANDLE ObjectTypeHandle; 175 176 /* ObReferenceObjectByName needs the object type... so get it... */ 177 RtlInitUnicodeString(&Name, L"\\ObjectTypes\\Directory"); 178 InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_KERNEL_HANDLE, NULL, NULL); 179 Status = ObOpenObjectByName(&ObjectAttributes, NULL, KernelMode, NULL, 0, NULL, &ObjectTypeHandle); 180 ok_eq_hex(Status, STATUS_SUCCESS); 181 ok(ObjectTypeHandle != NULL, "ObjectTypeHandle = NULL\n"); 182 if (!skip(Status == STATUS_SUCCESS && ObjectTypeHandle, "No handle\n")) 183 { 184 Status = ObReferenceObjectByHandle(ObjectTypeHandle, 0, NULL, KernelMode, (PVOID)&ObDirectoryObjectType, NULL); 185 ok_eq_hex(Status, STATUS_SUCCESS); 186 ok(ObDirectoryObjectType != NULL, "ObDirectoryObjectType = NULL\n"); 187 Status = ZwClose(ObjectTypeHandle); 188 ok_eq_hex(Status, STATUS_SUCCESS); 189 } 190 191 for (i = 0; i < sizeof Tests / sizeof Tests[0]; ++i) 192 { 193 DPRINT("Run %d\n", i); 194 if (Tests[i].Name) 195 { 196 RtlInitUnicodeString(&Name, Tests[i].Name); 197 pName = &Name; 198 Status = RtlUpcaseUnicodeString(&NameUpper, &Name, TRUE); 199 ok_eq_hex(Status, STATUS_SUCCESS); 200 if (skip(Status == STATUS_SUCCESS, "No upper case name\n")) 201 pNameUpper = NULL; 202 else 203 pNameUpper = &NameUpper; 204 } 205 else 206 { 207 pName = NULL; 208 pNameUpper = NULL; 209 } 210 InitializeObjectAttributes(&ObjectAttributes, pName, Tests[i].Flags, NULL, NULL); 211 Status = ZwCreateDirectoryObject(&DirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes); 212 ok_eq_hex(Status, STATUS_SUCCESS); 213 ok(DirectoryHandle != NULL, "DirectoryHandle = NULL\n"); 214 215 if (!skip(Status == STATUS_SUCCESS && DirectoryHandle, "Cannot proceed without an object\n")) 216 { 217 TestReference(DirectoryHandle, pName, pNameUpper, FALSE, Tests[i].AdditionalReferences, (Tests[i].Flags & OBJ_PERMANENT) != 0); 218 /* try again for good measure */ 219 TestReference(DirectoryHandle, pName, pNameUpper, FALSE, Tests[i].AdditionalReferences, FALSE); 220 221 Status = ZwClose(DirectoryHandle); 222 ok_eq_hex(Status, STATUS_SUCCESS); 223 DirectoryHandle = NULL; 224 } 225 226 if (pNameUpper) 227 RtlFreeUnicodeString(pNameUpper); 228 } 229 230 if (DirectoryHandle) 231 { 232 Status = ZwClose(DirectoryHandle); 233 ok_eq_hex(Status, STATUS_SUCCESS); 234 } 235 236 /* parameter tests */ 237 /* bugcheck at APC_LEVEL 238 Status = ObReferenceObject(NULL); 239 Status = ObReferenceObjectByPointer(NULL, 0, NULL, UserMode); 240 Status = ObReferenceObjectByPointer(NULL, 0, NULL, KernelMode);*/ 241 242 if (ObDirectoryObjectType) 243 { 244 ObDereferenceObject(ObDirectoryObjectType); 245 ObDirectoryObjectType = NULL; 246 } 247 } 248