1 /* 2 * PROJECT: ReactOS kernel-mode tests 3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory 4 * PURPOSE: Kernel-Mode Test for Zw*SymbolicLinkObject 5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org> 6 */ 7 8 #include <kmt_test.h> 9 10 #define NDEBUG 11 #include <debug.h> 12 13 static 14 VOID 15 TestQueryLink( 16 _In_ HANDLE LinkHandle, 17 _In_ PCUNICODE_STRING ExpectedTarget) 18 { 19 NTSTATUS Status; 20 WCHAR QueriedTargetBuffer[32]; 21 UNICODE_STRING QueriedTarget; 22 ULONG ResultLength; 23 PULONG pResultLength; 24 ULONG i; 25 26 for (i = 0; i < 2; i++) 27 { 28 if (i == 0) 29 { 30 pResultLength = &ResultLength; 31 } 32 else 33 { 34 pResultLength = NULL; 35 } 36 37 /* Query with NULL Buffer just gives us the length */ 38 RtlInitEmptyUnicodeString(&QueriedTarget, NULL, 0); 39 if (pResultLength) ResultLength = 0x55555555; 40 Status = ZwQuerySymbolicLinkObject(LinkHandle, 41 &QueriedTarget, 42 pResultLength); 43 ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL); 44 ok_eq_uint(QueriedTarget.Length, 0); 45 ok_eq_uint(QueriedTarget.MaximumLength, 0); 46 ok_eq_pointer(QueriedTarget.Buffer, NULL); 47 if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); 48 49 /* Query with Length-1 buffer */ 50 RtlInitEmptyUnicodeString(&QueriedTarget, 51 QueriedTargetBuffer, 52 ExpectedTarget->Length - 1); 53 RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55); 54 if (pResultLength) ResultLength = 0x55555555; 55 Status = ZwQuerySymbolicLinkObject(LinkHandle, 56 &QueriedTarget, 57 pResultLength); 58 ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL); 59 ok_eq_uint(QueriedTarget.Length, 0); 60 ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length - 1); 61 ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer); 62 ok_eq_uint(QueriedTarget.Buffer[0], 0x5555); 63 if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); 64 65 /* Query with Length buffer */ 66 RtlInitEmptyUnicodeString(&QueriedTarget, 67 QueriedTargetBuffer, 68 ExpectedTarget->Length); 69 RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55); 70 if (pResultLength) ResultLength = 0x55555555; 71 Status = ZwQuerySymbolicLinkObject(LinkHandle, 72 &QueriedTarget, 73 pResultLength); 74 ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length); 75 ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer); 76 if (pResultLength && 77 QueriedTarget.MaximumLength < ExpectedTarget->MaximumLength) 78 { 79 ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL); 80 ok_eq_uint(QueriedTarget.Length, 0); 81 ok_eq_uint(QueriedTarget.Buffer[0], 0x5555); 82 if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); 83 } 84 else 85 { 86 ok_eq_hex(Status, STATUS_SUCCESS); 87 ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length); 88 ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget); 89 ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555); 90 } 91 92 /* Query with Length+1 buffer */ 93 RtlInitEmptyUnicodeString(&QueriedTarget, 94 QueriedTargetBuffer, 95 ExpectedTarget->Length + 1); 96 RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55); 97 if (pResultLength) ResultLength = 0x55555555; 98 Status = ZwQuerySymbolicLinkObject(LinkHandle, 99 &QueriedTarget, 100 pResultLength); 101 ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length + 1); 102 ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer); 103 if (pResultLength && 104 QueriedTarget.MaximumLength < ExpectedTarget->MaximumLength) 105 { 106 ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL); 107 ok_eq_uint(QueriedTarget.Length, 0); 108 ok_eq_uint(QueriedTarget.Buffer[0], 0x5555); 109 if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); 110 } 111 else 112 { 113 ok_eq_hex(Status, STATUS_SUCCESS); 114 ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length); 115 ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget); 116 ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555); 117 } 118 119 /* Query with Length+2 buffer */ 120 RtlInitEmptyUnicodeString(&QueriedTarget, 121 QueriedTargetBuffer, 122 ExpectedTarget->Length + sizeof(WCHAR)); 123 RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55); 124 if (pResultLength) ResultLength = 0x55555555; 125 Status = ZwQuerySymbolicLinkObject(LinkHandle, 126 &QueriedTarget, 127 pResultLength); 128 ok_eq_hex(Status, STATUS_SUCCESS); 129 ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length); 130 ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length + sizeof(WCHAR)); 131 ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer); 132 ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget); 133 if (pResultLength) 134 { 135 if (ExpectedTarget->MaximumLength >= ExpectedTarget->Length + sizeof(UNICODE_NULL)) 136 ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0); 137 ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); 138 } 139 else 140 { 141 ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555); 142 } 143 144 /* Query with full-sized buffer */ 145 RtlInitEmptyUnicodeString(&QueriedTarget, 146 QueriedTargetBuffer, 147 sizeof(QueriedTargetBuffer)); 148 RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55); 149 if (pResultLength) ResultLength = 0x55555555; 150 Status = ZwQuerySymbolicLinkObject(LinkHandle, 151 &QueriedTarget, 152 pResultLength); 153 ok_eq_hex(Status, STATUS_SUCCESS); 154 ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length); 155 ok_eq_uint(QueriedTarget.MaximumLength, sizeof(QueriedTargetBuffer)); 156 ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer); 157 ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget); 158 if (pResultLength) 159 { 160 if (ExpectedTarget->MaximumLength >= ExpectedTarget->Length + sizeof(UNICODE_NULL)) 161 ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0); 162 ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); 163 } 164 else 165 { 166 ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555); 167 } 168 } 169 } 170 171 START_TEST(ObSymbolicLink) 172 { 173 NTSTATUS Status; 174 HANDLE LinkHandle; 175 HANDLE LinkHandle2; 176 UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"\\Device\\ObSymbolicLinkKmtestNamedPipe"); 177 OBJECT_ATTRIBUTES ObjectAttributes; 178 UNICODE_STRING DefaultLinkTarget = RTL_CONSTANT_STRING(L"\\Device\\NamedPipe"); 179 UNICODE_STRING LinkTarget = DefaultLinkTarget; 180 181 InitializeObjectAttributes(&ObjectAttributes, 182 &LinkName, 183 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 184 NULL, 185 NULL); 186 LinkHandle = KmtInvalidPointer; 187 Status = ZwOpenSymbolicLinkObject(&LinkHandle, 188 SYMBOLIC_LINK_QUERY, 189 &ObjectAttributes); 190 ok_eq_hex(Status, STATUS_OBJECT_NAME_NOT_FOUND); 191 ok_eq_pointer(LinkHandle, NULL); 192 if (NT_SUCCESS(Status)) ObCloseHandle(LinkHandle, KernelMode); 193 194 /* Create it */ 195 LinkHandle = KmtInvalidPointer; 196 Status = ZwCreateSymbolicLinkObject(&LinkHandle, 197 SYMBOLIC_LINK_QUERY, 198 &ObjectAttributes, 199 &LinkTarget); 200 ok_eq_hex(Status, STATUS_SUCCESS); 201 ok(LinkHandle != NULL && LinkHandle != KmtInvalidPointer, "LinkHandle = %p\n", LinkHandle); 202 if (skip(NT_SUCCESS(Status), "Failed to create link\n")) 203 { 204 return; 205 } 206 207 /* Now we should be able to open it */ 208 LinkHandle2 = KmtInvalidPointer; 209 Status = ZwOpenSymbolicLinkObject(&LinkHandle2, 210 SYMBOLIC_LINK_QUERY, 211 &ObjectAttributes); 212 ok_eq_hex(Status, STATUS_SUCCESS); 213 ok(LinkHandle2 != NULL && LinkHandle2 != KmtInvalidPointer, "LinkHandle = %p\n", LinkHandle2); 214 if (!skip(NT_SUCCESS(Status), "Failed to open symlink\n")) 215 { 216 TestQueryLink(LinkHandle2, &LinkTarget); 217 ObCloseHandle(LinkHandle2, KernelMode); 218 } 219 220 /* Close it */ 221 ObCloseHandle(LinkHandle, KernelMode); 222 223 /* Open fails again */ 224 LinkHandle = KmtInvalidPointer; 225 Status = ZwOpenSymbolicLinkObject(&LinkHandle, 226 SYMBOLIC_LINK_QUERY, 227 &ObjectAttributes); 228 ok_eq_hex(Status, STATUS_OBJECT_NAME_NOT_FOUND); 229 ok_eq_pointer(LinkHandle, NULL); 230 if (NT_SUCCESS(Status)) ObCloseHandle(LinkHandle, KernelMode); 231 232 /* Create with broken LinkTarget */ 233 LinkHandle = KmtInvalidPointer; 234 LinkTarget.Buffer = NULL; 235 Status = ZwCreateSymbolicLinkObject(&LinkHandle, 236 SYMBOLIC_LINK_QUERY, 237 &ObjectAttributes, 238 &LinkTarget); 239 ok_eq_hex(Status, STATUS_ACCESS_VIOLATION); 240 ok(LinkHandle == KmtInvalidPointer, "LinkHandle = %p\n", LinkHandle); 241 if (NT_SUCCESS(Status)) ObCloseHandle(LinkHandle, KernelMode); 242 243 /* Since it failed, open should also fail */ 244 LinkHandle = KmtInvalidPointer; 245 Status = ZwOpenSymbolicLinkObject(&LinkHandle, 246 SYMBOLIC_LINK_QUERY, 247 &ObjectAttributes); 248 ok_eq_hex(Status, STATUS_OBJECT_NAME_NOT_FOUND); 249 ok_eq_pointer(LinkHandle, NULL); 250 if (NT_SUCCESS(Status)) ObCloseHandle(LinkHandle, KernelMode); 251 252 /* Create with valid, but not null-terminated LinkTarget */ 253 LinkTarget = DefaultLinkTarget; 254 LinkTarget.MaximumLength = LinkTarget.Length; 255 LinkHandle = KmtInvalidPointer; 256 Status = ZwCreateSymbolicLinkObject(&LinkHandle, 257 SYMBOLIC_LINK_QUERY, 258 &ObjectAttributes, 259 &LinkTarget); 260 ok_eq_hex(Status, STATUS_SUCCESS); 261 ok(LinkHandle != NULL && LinkHandle != KmtInvalidPointer, "LinkHandle = %p\n", LinkHandle); 262 if (skip(NT_SUCCESS(Status), "Failed to create link\n")) 263 { 264 return; 265 } 266 267 /* Now we should be able to open it */ 268 LinkHandle2 = KmtInvalidPointer; 269 Status = ZwOpenSymbolicLinkObject(&LinkHandle2, 270 SYMBOLIC_LINK_QUERY, 271 &ObjectAttributes); 272 ok_eq_hex(Status, STATUS_SUCCESS); 273 ok(LinkHandle2 != NULL && LinkHandle2 != KmtInvalidPointer, "LinkHandle = %p\n", LinkHandle2); 274 if (!skip(NT_SUCCESS(Status), "Failed to open symlink\n")) 275 { 276 TestQueryLink(LinkHandle2, &LinkTarget); 277 ObCloseHandle(LinkHandle2, KernelMode); 278 } 279 280 /* Close it */ 281 ObCloseHandle(LinkHandle, KernelMode); 282 } 283