1 /* 2 * PROJECT: ReactOS kernel-mode tests 3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory 4 * PURPOSE: Kernel-Mode Test Suite Object Handle 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, Attrib, Access) 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_hex(ObjectInfo.Attributes, Attrib); \ 19 ok_eq_hex(ObjectInfo.GrantedAccess, Access); \ 20 ok_eq_ulong(ObjectInfo.PointerCount, Pointers); \ 21 ok_eq_ulong(ObjectInfo.HandleCount, Handles); \ 22 } while (0) 23 24 #define KERNEL_HANDLE_FLAG ((ULONG_PTR)0xFFFFFFFF80000000) 25 #define IsUserHandle(h) (((ULONG_PTR)(h) & KERNEL_HANDLE_FLAG) == 0) 26 #define IsKernelHandle(h) (((ULONG_PTR)(h) & KERNEL_HANDLE_FLAG) == KERNEL_HANDLE_FLAG) 27 28 static HANDLE SystemProcessHandle; 29 30 static 31 VOID 32 TestDuplicate( 33 _In_ HANDLE Handle) 34 { 35 NTSTATUS Status; 36 HANDLE NewHandle; 37 struct 38 { 39 ACCESS_MASK DesiredAccess; 40 ULONG RequestedAttributes; 41 ULONG Options; 42 ACCESS_MASK GrantedAccess; 43 ULONG ExpectedAttributes; 44 } Tests[] = 45 { 46 { DIRECTORY_ALL_ACCESS, 0, 0, 47 DIRECTORY_ALL_ACCESS, 0 }, 48 { DIRECTORY_ALL_ACCESS, OBJ_KERNEL_HANDLE, 0, 49 DIRECTORY_ALL_ACCESS, 0 }, 50 { DIRECTORY_QUERY, 0, 0, 51 DIRECTORY_QUERY, 0 }, 52 { DIRECTORY_QUERY, OBJ_INHERIT, 0, 53 DIRECTORY_QUERY, OBJ_INHERIT }, 54 { DIRECTORY_QUERY, OBJ_INHERIT, DUPLICATE_SAME_ACCESS, 55 DIRECTORY_ALL_ACCESS, OBJ_INHERIT }, 56 /* 5 */ 57 { DIRECTORY_QUERY, OBJ_INHERIT, DUPLICATE_SAME_ATTRIBUTES, 58 DIRECTORY_QUERY, 0 }, 59 { DIRECTORY_QUERY, OBJ_INHERIT, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES, 60 DIRECTORY_ALL_ACCESS, 0 }, 61 }; 62 ULONG i; 63 64 for (i = 0; i < RTL_NUMBER_OF(Tests); i++) 65 { 66 trace("Test %lu\n", i); 67 Status = ZwDuplicateObject(ZwCurrentProcess(), 68 Handle, 69 ZwCurrentProcess(), 70 &NewHandle, 71 Tests[i].DesiredAccess, 72 Tests[i].RequestedAttributes, 73 Tests[i].Options); 74 ok_eq_hex(Status, STATUS_SUCCESS); 75 if (!skip(NT_SUCCESS(Status), "DuplicateHandle failed\n")) 76 { 77 ok(IsUserHandle(NewHandle), "New handle = %p\n", NewHandle); 78 CheckObject(NewHandle, 3UL, 2UL, Tests[i].ExpectedAttributes, Tests[i].GrantedAccess); 79 CheckObject(Handle, 3UL, 2UL, 0UL, DIRECTORY_ALL_ACCESS); 80 81 Status = ObCloseHandle(NewHandle, UserMode); 82 ok_eq_hex(Status, STATUS_SUCCESS); 83 CheckObject(Handle, 2UL, 1UL, 0UL, DIRECTORY_ALL_ACCESS); 84 } 85 } 86 87 /* If TargetProcess is the System process, we do get a kernel handle */ 88 Status = ZwDuplicateObject(ZwCurrentProcess(), 89 Handle, 90 SystemProcessHandle, 91 &NewHandle, 92 DIRECTORY_ALL_ACCESS, 93 OBJ_KERNEL_HANDLE, 94 0); 95 ok_eq_hex(Status, STATUS_SUCCESS); 96 if (!skip(NT_SUCCESS(Status), "DuplicateHandle failed\n")) 97 { 98 ok(IsKernelHandle(NewHandle), "New handle = %p\n", NewHandle); 99 CheckObject(NewHandle, 3UL, 2UL, 0, DIRECTORY_ALL_ACCESS); 100 CheckObject(Handle, 3UL, 2UL, 0UL, DIRECTORY_ALL_ACCESS); 101 102 Status = ObCloseHandle(NewHandle, UserMode); 103 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 104 CheckObject(NewHandle, 3UL, 2UL, 0, DIRECTORY_ALL_ACCESS); 105 CheckObject(Handle, 3UL, 2UL, 0UL, DIRECTORY_ALL_ACCESS); 106 107 if (IsKernelHandle(NewHandle)) 108 { 109 Status = ObCloseHandle(NewHandle, KernelMode); 110 ok_eq_hex(Status, STATUS_SUCCESS); 111 CheckObject(Handle, 2UL, 1UL, 0UL, DIRECTORY_ALL_ACCESS); 112 } 113 } 114 } 115 116 START_TEST(ObHandle) 117 { 118 NTSTATUS Status; 119 OBJECT_ATTRIBUTES ObjectAttributes; 120 HANDLE KernelDirectoryHandle; 121 HANDLE UserDirectoryHandle; 122 123 Status = ObOpenObjectByPointer(PsInitialSystemProcess, 124 OBJ_KERNEL_HANDLE, 125 NULL, 126 PROCESS_ALL_ACCESS, 127 *PsProcessType, 128 KernelMode, 129 &SystemProcessHandle); 130 ok_eq_hex(Status, STATUS_SUCCESS); 131 if (skip(NT_SUCCESS(Status), "No handle for system process\n")) 132 { 133 SystemProcessHandle = NULL; 134 } 135 136 InitializeObjectAttributes(&ObjectAttributes, 137 NULL, 138 0, 139 NULL, 140 NULL); 141 Status = ZwCreateDirectoryObject(&UserDirectoryHandle, 142 DIRECTORY_ALL_ACCESS, 143 &ObjectAttributes); 144 ok_eq_hex(Status, STATUS_SUCCESS); 145 if (!skip(NT_SUCCESS(Status), "No directory handle\n")) 146 { 147 ok(IsUserHandle(UserDirectoryHandle), "User handle = %p\n", UserDirectoryHandle); 148 CheckObject(UserDirectoryHandle, 2UL, 1UL, 0UL, DIRECTORY_ALL_ACCESS); 149 150 TestDuplicate(UserDirectoryHandle); 151 152 Status = ObCloseHandle(UserDirectoryHandle, UserMode); 153 ok_eq_hex(Status, STATUS_SUCCESS); 154 } 155 156 InitializeObjectAttributes(&ObjectAttributes, 157 NULL, 158 OBJ_KERNEL_HANDLE, 159 NULL, 160 NULL); 161 Status = ZwCreateDirectoryObject(&KernelDirectoryHandle, 162 DIRECTORY_ALL_ACCESS, 163 &ObjectAttributes); 164 ok_eq_hex(Status, STATUS_SUCCESS); 165 if (!skip(NT_SUCCESS(Status), "No directory handle\n")) 166 { 167 ok(IsKernelHandle(KernelDirectoryHandle), "Kernel handle = %p\n", KernelDirectoryHandle); 168 CheckObject(KernelDirectoryHandle, 2UL, 1UL, 0UL, DIRECTORY_ALL_ACCESS); 169 170 TestDuplicate(KernelDirectoryHandle); 171 172 Status = ObCloseHandle(KernelDirectoryHandle, UserMode); 173 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 174 CheckObject(KernelDirectoryHandle, 2UL, 1UL, 0UL, DIRECTORY_ALL_ACCESS); 175 176 Status = ObCloseHandle(KernelDirectoryHandle, KernelMode); 177 ok_eq_hex(Status, STATUS_SUCCESS); 178 } 179 180 /* Tests for closing handles */ 181 KmtStartSeh() 182 /* NtClose must accept everything */ 183 DPRINT("Closing null handle (NtClose)\n"); 184 Status = NtClose(NULL); 185 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 186 DPRINT("Closing null kernel handle (NtClose)\n"); 187 Status = NtClose(LongToHandle(0x80000000)); 188 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 189 DPRINT("Closing -1 handle (NtClose)\n"); 190 Status = NtClose(LongToHandle(0x7FFFFFFF)); 191 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 192 DPRINT("Closing -1 kernel handle (NtClose)\n"); 193 Status = NtClose(LongToHandle(0xFFFFFFFF)); 194 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 195 DPRINT("Closing 123 handle (NtClose)\n"); 196 Status = NtClose(LongToHandle(123)); 197 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 198 DPRINT("Closing 123 kernel handle (NtClose)\n"); 199 Status = NtClose(LongToHandle(123 | 0x80000000)); 200 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 201 202 /* ObCloseHandle with UserMode accepts everything */ 203 DPRINT("Closing null handle (ObCloseHandle, UserMode)\n"); 204 Status = ObCloseHandle(NULL, UserMode); 205 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 206 DPRINT("Closing null kernel handle (ObCloseHandle, UserMode)\n"); 207 Status = ObCloseHandle(LongToHandle(0x80000000), UserMode); 208 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 209 DPRINT("Closing -1 handle (ObCloseHandle, UserMode)\n"); 210 Status = ObCloseHandle(LongToHandle(0x7FFFFFFF), UserMode); 211 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 212 DPRINT("Closing -1 kernel handle (ObCloseHandle, UserMode)\n"); 213 Status = ObCloseHandle(LongToHandle(0xFFFFFFFF), UserMode); 214 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 215 DPRINT("Closing 123 handle (ObCloseHandle, UserMode)\n"); 216 Status = ObCloseHandle(LongToHandle(123), UserMode); 217 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 218 DPRINT("Closing 123 kernel handle (ObCloseHandle, UserMode)\n"); 219 Status = ObCloseHandle(LongToHandle(123 | 0x80000000), UserMode); 220 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 221 222 /* ZwClose only accepts 0 and -1 */ 223 DPRINT("Closing null handle (ZwClose)\n"); 224 Status = ZwClose(NULL); 225 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 226 DPRINT("Closing null kernel handle (ZwClose)\n"); 227 Status = ZwClose(LongToHandle(0x80000000)); 228 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 229 /* INVALID_KERNEL_HANDLE, 0x7FFFFFFF 230 Status = ZwClose((HANDLE)0x7FFFFFFF);*/ 231 DPRINT("Closing -1 kernel handle (ZwClose)\n"); 232 Status = ZwClose(LongToHandle(0xFFFFFFFF)); 233 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 234 /* INVALID_KERNEL_HANDLE, 0x7B, 1, 0, 0 235 Status = ZwClose(LongToHandle(123)); 236 Status = ZwClose(LongToHandle(123 | 0x80000000));*/ 237 238 /* ObCloseHandle with KernelMode accepts only 0 and -1 */ 239 DPRINT("Closing null handle (ObCloseHandle, KernelMode)\n"); 240 Status = ObCloseHandle(NULL, KernelMode); 241 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 242 DPRINT("Closing null kernel handle (ObCloseHandle, KernelMode)\n"); 243 Status = ObCloseHandle(LongToHandle(0x80000000), KernelMode); 244 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 245 /* INVALID_KERNEL_HANDLE, 0x7FFFFFFF, 1, 0, 0 246 Status = ObCloseHandle((HANDLE)0x7FFFFFFF, KernelMode);*/ 247 DPRINT("Closing -1 kernel handle (ObCloseHandle, KernelMode)\n"); 248 Status = ObCloseHandle(LongToHandle(0xFFFFFFFF), KernelMode); 249 ok_eq_hex(Status, STATUS_INVALID_HANDLE); 250 /* INVALID_KERNEL_HANDLE, 0x7B, 1, 0, 0 251 Status = ObCloseHandle(LongToHandle(123), KernelMode); 252 Status = ObCloseHandle(LongToHandle(123 | 0x80000000), KernelMode);*/ 253 KmtEndSeh(STATUS_SUCCESS); 254 255 if (SystemProcessHandle) 256 { 257 ObCloseHandle(SystemProcessHandle, KernelMode); 258 } 259 } 260