Merge from amd64 branch:
[reactos.git] / rostests / winetests / ntdll / om.c
1 /*
2 * Unit test suite for object manager functions
3 *
4 * Copyright 2005 Robert Shearman
5 * Copyright 2005 Vitaliy Margolen
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
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 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "ntdll_test.h"
23 #include "winternl.h"
24 #include "stdio.h"
25 #include "winnt.h"
26 #include "stdlib.h"
27
28 static HANDLE (WINAPI *pCreateWaitableTimerA)(SECURITY_ATTRIBUTES*, BOOL, LPCSTR);
29 static NTSTATUS (WINAPI *pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR);
30 static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
31 static VOID (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
32 static NTSTATUS (WINAPI *pNtCreateEvent) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, BOOLEAN, BOOLEAN);
33 static NTSTATUS (WINAPI *pNtCreateMutant)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, BOOLEAN );
34 static NTSTATUS (WINAPI *pNtOpenMutant) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES );
35 static NTSTATUS (WINAPI *pNtCreateSemaphore)( PHANDLE, ACCESS_MASK,const POBJECT_ATTRIBUTES,LONG,LONG );
36 static NTSTATUS (WINAPI *pNtCreateTimer) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, TIMER_TYPE );
37 static NTSTATUS (WINAPI *pNtCreateSection)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, const PLARGE_INTEGER,
38 ULONG, ULONG, HANDLE );
39 static NTSTATUS (WINAPI *pNtOpenFile) ( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, ULONG, ULONG );
40 static NTSTATUS (WINAPI *pNtClose) ( HANDLE );
41 static NTSTATUS (WINAPI *pNtCreateNamedPipeFile)( PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
42 ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, PLARGE_INTEGER );
43 static NTSTATUS (WINAPI *pNtOpenDirectoryObject)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
44 static NTSTATUS (WINAPI *pNtCreateDirectoryObject)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
45 static NTSTATUS (WINAPI *pNtOpenSymbolicLinkObject)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
46 static NTSTATUS (WINAPI *pNtCreateSymbolicLinkObject)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PUNICODE_STRING);
47 static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,ULONG,PULONG);
48
49
50 static void test_case_sensitive (void)
51 {
52 static const WCHAR buffer1[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s','\\','t','e','s','t',0};
53 static const WCHAR buffer2[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s','\\','T','e','s','t',0};
54 static const WCHAR buffer3[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s','\\','T','E','s','t',0};
55 static const WCHAR buffer4[] = {'\\','B','A','S','E','N','a','m','e','d','O','b','j','e','c','t','s','\\','t','e','s','t',0};
56 NTSTATUS status;
57 OBJECT_ATTRIBUTES attr;
58 UNICODE_STRING str;
59 HANDLE Event, Mutant, h;
60
61 pRtlInitUnicodeString(&str, buffer1);
62 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
63 status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
64 ok(status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status);
65
66 status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, FALSE, FALSE);
67 ok(status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH,
68 "NtCreateEvent should have failed with STATUS_OBJECT_NAME_COLLISION or STATUS_OBJECT_TYPE_MISMATCH got (%08x)\n", status);
69
70 pRtlInitUnicodeString(&str, buffer2);
71 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
72 status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, FALSE, FALSE);
73 ok(status == STATUS_SUCCESS, "Failed to create Event(%08x)\n", status);
74
75 pRtlInitUnicodeString(&str, buffer3);
76 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
77 status = pNtOpenMutant(&h, GENERIC_ALL, &attr);
78 ok(status == STATUS_OBJECT_TYPE_MISMATCH,
79 "NtOpenMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
80
81 pNtClose(Mutant);
82
83 pRtlInitUnicodeString(&str, buffer4);
84 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
85 status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
86 ok(status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH,
87 "NtCreateMutant should have failed with STATUS_OBJECT_NAME_COLLISION or STATUS_OBJECT_TYPE_MISMATCH got (%08x)\n", status);
88
89 status = pNtCreateEvent(&h, GENERIC_ALL, &attr, FALSE, FALSE);
90 ok(status == STATUS_OBJECT_NAME_COLLISION,
91 "NtCreateEvent should have failed with STATUS_OBJECT_NAME_COLLISION got(%08x)\n", status);
92
93 attr.Attributes = 0;
94 status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
95 ok(status == STATUS_OBJECT_PATH_NOT_FOUND,
96 "NtCreateMutant should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
97
98 pNtClose(Event);
99 }
100
101 static void test_namespace_pipe(void)
102 {
103 static const WCHAR buffer1[] = {'\\','?','?','\\','P','I','P','E','\\','t','e','s','t','\\','p','i','p','e',0};
104 static const WCHAR buffer2[] = {'\\','?','?','\\','P','I','P','E','\\','T','E','S','T','\\','P','I','P','E',0};
105 static const WCHAR buffer3[] = {'\\','?','?','\\','p','i','p','e','\\','t','e','s','t','\\','p','i','p','e',0};
106 static const WCHAR buffer4[] = {'\\','?','?','\\','p','i','p','e','\\','t','e','s','t',0};
107 OBJECT_ATTRIBUTES attr;
108 UNICODE_STRING str;
109 IO_STATUS_BLOCK iosb;
110 NTSTATUS status;
111 LARGE_INTEGER timeout;
112 HANDLE pipe, h;
113
114 timeout.QuadPart = -10000;
115
116 pRtlInitUnicodeString(&str, buffer1);
117 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
118 status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
119 FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
120 ok(status == STATUS_SUCCESS, "Failed to create NamedPipe(%08x)\n", status);
121
122 status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
123 FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
124 ok(status == STATUS_INSTANCE_NOT_AVAILABLE,
125 "NtCreateNamedPipeFile should have failed with STATUS_INSTANCE_NOT_AVAILABLE got(%08x)\n", status);
126
127 pRtlInitUnicodeString(&str, buffer2);
128 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
129 status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
130 FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
131 ok(status == STATUS_INSTANCE_NOT_AVAILABLE,
132 "NtCreateNamedPipeFile should have failed with STATUS_INSTANCE_NOT_AVAILABLE got(%08x)\n", status);
133
134 h = CreateFileA("\\\\.\\pipe\\test\\pipe", GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
135 OPEN_EXISTING, 0, 0 );
136 ok(h != INVALID_HANDLE_VALUE, "Failed to open NamedPipe (%u)\n", GetLastError());
137 pNtClose(h);
138
139 pRtlInitUnicodeString(&str, buffer3);
140 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
141 status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
142 ok(status == STATUS_OBJECT_PATH_NOT_FOUND ||
143 status == STATUS_PIPE_NOT_AVAILABLE ||
144 status == STATUS_OBJECT_NAME_INVALID, /* vista */
145 "NtOpenFile should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
146
147 pRtlInitUnicodeString(&str, buffer4);
148 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
149 status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
150 ok(status == STATUS_OBJECT_NAME_NOT_FOUND ||
151 status == STATUS_OBJECT_NAME_INVALID, /* vista */
152 "NtOpenFile should have failed with STATUS_OBJECT_NAME_NOT_FOUND got(%08x)\n", status);
153
154 pNtClose(pipe);
155 }
156
157 #define DIRECTORY_QUERY (0x0001)
158 #define SYMBOLIC_LINK_QUERY 0x0001
159
160 #define DIR_TEST_CREATE_FAILURE(h,e) \
161 status = pNtCreateDirectoryObject(h, DIRECTORY_QUERY, &attr);\
162 ok(status == e,"NtCreateDirectoryObject should have failed with %s got(%08x)\n", #e, status);
163 #define DIR_TEST_OPEN_FAILURE(h,e) \
164 status = pNtOpenDirectoryObject(h, DIRECTORY_QUERY, &attr);\
165 ok(status == e,"NtOpenDirectoryObject should have failed with %s got(%08x)\n", #e, status);
166 #define DIR_TEST_CREATE_OPEN_FAILURE(h,n,e) \
167 pRtlCreateUnicodeStringFromAsciiz(&str, n);\
168 DIR_TEST_CREATE_FAILURE(h,e) DIR_TEST_OPEN_FAILURE(h,e)\
169 pRtlFreeUnicodeString(&str);
170
171 #define DIR_TEST_CREATE_SUCCESS(h) \
172 status = pNtCreateDirectoryObject(h, DIRECTORY_QUERY, &attr); \
173 ok(status == STATUS_SUCCESS, "Failed to create Directory(%08x)\n", status);
174 #define DIR_TEST_OPEN_SUCCESS(h) \
175 status = pNtOpenDirectoryObject(h, DIRECTORY_QUERY, &attr); \
176 ok(status == STATUS_SUCCESS, "Failed to open Directory(%08x)\n", status);
177 #define DIR_TEST_CREATE_OPEN_SUCCESS(h,n) \
178 pRtlCreateUnicodeStringFromAsciiz(&str, n);\
179 DIR_TEST_CREATE_SUCCESS(&h) pNtClose(h); DIR_TEST_OPEN_SUCCESS(&h) pNtClose(h); \
180 pRtlFreeUnicodeString(&str);
181
182 static BOOL is_correct_dir( HANDLE dir, const char *name )
183 {
184 NTSTATUS status;
185 UNICODE_STRING str;
186 OBJECT_ATTRIBUTES attr;
187 HANDLE h = 0;
188
189 pRtlCreateUnicodeStringFromAsciiz(&str, name);
190 InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, dir, NULL);
191 status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
192 pRtlFreeUnicodeString(&str);
193 if (h) pNtClose( h );
194 return (status == STATUS_OBJECT_NAME_EXISTS);
195 }
196
197 /* return a handle to the BaseNamedObjects dir where kernel32 objects get created */
198 static HANDLE get_base_dir(void)
199 {
200 static const char objname[] = "om.c_get_base_dir_obj";
201 NTSTATUS status;
202 UNICODE_STRING str;
203 OBJECT_ATTRIBUTES attr;
204 HANDLE dir, h;
205 unsigned int i;
206
207 h = CreateMutexA(NULL, FALSE, objname);
208 ok(h != 0, "CreateMutexA failed got ret=%p (%d)\n", h, GetLastError());
209 InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, 0, NULL);
210
211 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local");
212 status = pNtOpenDirectoryObject(&dir, DIRECTORY_QUERY, &attr);
213 pRtlFreeUnicodeString(&str);
214 if (!status && is_correct_dir( dir, objname )) goto done;
215 if (!status) pNtClose( dir );
216
217 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
218 status = pNtOpenDirectoryObject(&dir, DIRECTORY_QUERY, &attr);
219 pRtlFreeUnicodeString(&str);
220 if (!status && is_correct_dir( dir, objname )) goto done;
221 if (!status) pNtClose( dir );
222
223 for (i = 0; i < 20; i++)
224 {
225 char name[40];
226 sprintf( name, "\\BaseNamedObjects\\Session\\%u", i );
227 pRtlCreateUnicodeStringFromAsciiz(&str, name );
228 status = pNtOpenDirectoryObject(&dir, DIRECTORY_QUERY, &attr);
229 pRtlFreeUnicodeString(&str);
230 if (!status && is_correct_dir( dir, objname )) goto done;
231 if (!status) pNtClose( dir );
232 }
233 dir = 0;
234
235 done:
236 pNtClose( h );
237 return dir;
238 }
239
240 static void test_name_collisions(void)
241 {
242 NTSTATUS status;
243 UNICODE_STRING str;
244 OBJECT_ATTRIBUTES attr;
245 HANDLE dir, h, h1, h2;
246 DWORD winerr;
247 LARGE_INTEGER size;
248
249 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
250 pRtlCreateUnicodeStringFromAsciiz(&str, "\\");
251 DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_NAME_COLLISION)
252 InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, 0, NULL);
253
254 DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_NAME_EXISTS)
255 pNtClose(h);
256 status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
257 ok(status == STATUS_OBJECT_TYPE_MISMATCH,
258 "NtCreateMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
259 pRtlFreeUnicodeString(&str);
260
261 pRtlCreateUnicodeStringFromAsciiz(&str, "\\??\\PIPE\\om.c-mutant");
262 status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
263 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_OBJECT_PATH_NOT_FOUND,
264 "NtCreateMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
265 pRtlFreeUnicodeString(&str);
266
267 if (!(dir = get_base_dir()))
268 {
269 win_skip( "couldn't find the BaseNamedObjects dir\n" );
270 return;
271 }
272 pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-test");
273 InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, dir, NULL);
274 h = CreateMutexA(NULL, FALSE, "om.c-test");
275 ok(h != 0, "CreateMutexA failed got ret=%p (%d)\n", h, GetLastError());
276 status = pNtCreateMutant(&h1, GENERIC_ALL, &attr, FALSE);
277 ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
278 "NtCreateMutant should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
279 h2 = CreateMutexA(NULL, FALSE, "om.c-test");
280 winerr = GetLastError();
281 ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
282 "CreateMutexA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
283 pNtClose(h);
284 pNtClose(h1);
285 pNtClose(h2);
286
287 h = CreateEventA(NULL, FALSE, FALSE, "om.c-test");
288 ok(h != 0, "CreateEventA failed got ret=%p (%d)\n", h, GetLastError());
289 status = pNtCreateEvent(&h1, GENERIC_ALL, &attr, FALSE, FALSE);
290 ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
291 "NtCreateEvent should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
292 h2 = CreateEventA(NULL, FALSE, FALSE, "om.c-test");
293 winerr = GetLastError();
294 ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
295 "CreateEventA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
296 pNtClose(h);
297 pNtClose(h1);
298 pNtClose(h2);
299
300 h = CreateSemaphoreA(NULL, 1, 2, "om.c-test");
301 ok(h != 0, "CreateSemaphoreA failed got ret=%p (%d)\n", h, GetLastError());
302 status = pNtCreateSemaphore(&h1, GENERIC_ALL, &attr, 1, 2);
303 ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
304 "NtCreateSemaphore should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
305 h2 = CreateSemaphoreA(NULL, 1, 2, "om.c-test");
306 winerr = GetLastError();
307 ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
308 "CreateSemaphoreA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
309 pNtClose(h);
310 pNtClose(h1);
311 pNtClose(h2);
312
313 h = pCreateWaitableTimerA(NULL, TRUE, "om.c-test");
314 ok(h != 0, "CreateWaitableTimerA failed got ret=%p (%d)\n", h, GetLastError());
315 status = pNtCreateTimer(&h1, GENERIC_ALL, &attr, NotificationTimer);
316 ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
317 "NtCreateTimer should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
318 h2 = pCreateWaitableTimerA(NULL, TRUE, "om.c-test");
319 winerr = GetLastError();
320 ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
321 "CreateWaitableTimerA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
322 pNtClose(h);
323 pNtClose(h1);
324 pNtClose(h2);
325
326 h = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 256, "om.c-test");
327 ok(h != 0, "CreateFileMappingA failed got ret=%p (%d)\n", h, GetLastError());
328 size.u.LowPart = 256;
329 size.u.HighPart = 0;
330 status = pNtCreateSection(&h1, SECTION_MAP_WRITE, &attr, &size, PAGE_READWRITE, SEC_COMMIT, 0);
331 ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
332 "NtCreateSection should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
333 h2 = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 256, "om.c-test");
334 winerr = GetLastError();
335 ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
336 "CreateFileMappingA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
337 pNtClose(h);
338 pNtClose(h1);
339 pNtClose(h2);
340
341 pRtlFreeUnicodeString(&str);
342 pNtClose(dir);
343 }
344
345 static void test_directory(void)
346 {
347 NTSTATUS status;
348 UNICODE_STRING str;
349 OBJECT_ATTRIBUTES attr;
350 HANDLE dir, dir1, h;
351 BOOL is_nt4;
352
353 /* No name and/or no attributes */
354 status = pNtCreateDirectoryObject(NULL, DIRECTORY_QUERY, &attr);
355 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER,
356 "NtCreateDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
357 status = pNtOpenDirectoryObject(NULL, DIRECTORY_QUERY, &attr);
358 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER,
359 "NtOpenDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
360
361 status = pNtCreateDirectoryObject(&h, DIRECTORY_QUERY, NULL);
362 ok(status == STATUS_SUCCESS, "Failed to create Directory without attributes(%08x)\n", status);
363 pNtClose(h);
364 status = pNtOpenDirectoryObject(&h, DIRECTORY_QUERY, NULL);
365 ok(status == STATUS_INVALID_PARAMETER,
366 "NtOpenDirectoryObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
367
368 InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
369 DIR_TEST_CREATE_SUCCESS(&dir)
370 DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
371
372 /* Bad name */
373 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
374
375 pRtlCreateUnicodeStringFromAsciiz(&str, "");
376 DIR_TEST_CREATE_SUCCESS(&h)
377 pNtClose(h);
378 DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
379 pRtlFreeUnicodeString(&str);
380 pNtClose(dir);
381
382 DIR_TEST_CREATE_OPEN_FAILURE(&h, "BaseNamedObjects", STATUS_OBJECT_PATH_SYNTAX_BAD)
383 DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\", STATUS_OBJECT_NAME_INVALID)
384 DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\\\BaseNamedObjects", STATUS_OBJECT_NAME_INVALID)
385 DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\\\om.c-test", STATUS_OBJECT_NAME_INVALID)
386 DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\om.c-test\\", STATUS_OBJECT_PATH_NOT_FOUND)
387
388 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test");
389 DIR_TEST_CREATE_SUCCESS(&h)
390 DIR_TEST_OPEN_SUCCESS(&dir1)
391 pRtlFreeUnicodeString(&str);
392 pNtClose(h);
393 pNtClose(dir1);
394
395
396 /* Use of root directory */
397
398 /* Can't use symlinks as a directory */
399 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local");
400 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
401 status = pNtOpenSymbolicLinkObject(&dir, SYMBOLIC_LINK_QUERY, &attr);
402 is_nt4 = (status == STATUS_OBJECT_NAME_NOT_FOUND); /* nt4 doesn't have Local\\ symlink */
403 if (!is_nt4)
404 {
405 ok(status == STATUS_SUCCESS, "Failed to open SymbolicLink(%08x)\n", status);
406 pRtlFreeUnicodeString(&str);
407 InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
408 pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
409 DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_TYPE_MISMATCH)
410 pRtlFreeUnicodeString(&str);
411 pNtClose(h);
412 pNtClose(dir);
413 }
414
415 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
416 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
417 DIR_TEST_OPEN_SUCCESS(&dir)
418 pRtlFreeUnicodeString(&str);
419
420 InitializeObjectAttributes(&attr, NULL, 0, dir, NULL);
421 DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_NAME_INVALID)
422
423 InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
424 DIR_TEST_CREATE_OPEN_SUCCESS(h, "")
425 DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\", STATUS_OBJECT_PATH_SYNTAX_BAD)
426 DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test", STATUS_OBJECT_PATH_SYNTAX_BAD)
427 DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test\\", STATUS_OBJECT_PATH_SYNTAX_BAD)
428 DIR_TEST_CREATE_OPEN_FAILURE(&h, "om.c-test\\", STATUS_OBJECT_PATH_NOT_FOUND)
429
430 pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-test");
431 DIR_TEST_CREATE_SUCCESS(&dir1)
432 DIR_TEST_OPEN_SUCCESS(&h)
433 pRtlFreeUnicodeString(&str);
434
435 pNtClose(h);
436 pNtClose(dir1);
437 pNtClose(dir);
438
439 /* Nested directories */
440 pRtlCreateUnicodeStringFromAsciiz(&str, "\\");
441 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
442 DIR_TEST_OPEN_SUCCESS(&dir)
443 InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
444 DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
445 pRtlFreeUnicodeString(&str);
446 pNtClose(dir);
447
448 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
449 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test");
450 DIR_TEST_CREATE_SUCCESS(&dir)
451 pRtlFreeUnicodeString(&str);
452 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test\\one more level");
453 DIR_TEST_CREATE_SUCCESS(&h)
454 pRtlFreeUnicodeString(&str);
455 pNtClose(h);
456 InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
457 pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
458 DIR_TEST_CREATE_SUCCESS(&h)
459 pRtlFreeUnicodeString(&str);
460 pNtClose(h);
461
462 pNtClose(dir);
463
464 if (!is_nt4)
465 {
466 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
467 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Global\\om.c-test");
468 DIR_TEST_CREATE_SUCCESS(&dir)
469 pRtlFreeUnicodeString(&str);
470 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local\\om.c-test\\one more level");
471 DIR_TEST_CREATE_SUCCESS(&h)
472 pRtlFreeUnicodeString(&str);
473 pNtClose(h);
474 InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
475 pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
476 DIR_TEST_CREATE_SUCCESS(&dir)
477 pRtlFreeUnicodeString(&str);
478 pNtClose(h);
479 pNtClose(dir);
480 }
481
482 /* Create other objects using RootDirectory */
483
484 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
485 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
486 DIR_TEST_OPEN_SUCCESS(&dir)
487 pRtlFreeUnicodeString(&str);
488 InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
489
490 /* Test invalid paths */
491 pRtlCreateUnicodeStringFromAsciiz(&str, "\\om.c-mutant");
492 status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
493 ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
494 "NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
495 pRtlFreeUnicodeString(&str);
496 pRtlCreateUnicodeStringFromAsciiz(&str, "\\om.c-mutant\\");
497 status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
498 ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
499 "NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
500 pRtlFreeUnicodeString(&str);
501
502 pRtlCreateUnicodeStringFromAsciiz(&str, "om.c\\-mutant");
503 status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
504 ok(status == STATUS_OBJECT_PATH_NOT_FOUND,
505 "NtCreateMutant should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
506 pRtlFreeUnicodeString(&str);
507
508 pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-mutant");
509 status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
510 ok(status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status);
511 pRtlFreeUnicodeString(&str);
512 pNtClose(h);
513
514 pNtClose(dir);
515 }
516
517 #define SYMLNK_TEST_CREATE_OPEN_FAILURE2(h,n,t,e,e2) \
518 pRtlCreateUnicodeStringFromAsciiz(&str, n);\
519 pRtlCreateUnicodeStringFromAsciiz(&target, t);\
520 status = pNtCreateSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr, &target);\
521 ok(status == e || status == e2, \
522 "NtCreateSymbolicLinkObject should have failed with %s or %s got(%08x)\n", #e, #e2, status);\
523 status = pNtOpenSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr);\
524 ok(status == e || status == e2, \
525 "NtOpenSymbolicLinkObject should have failed with %s or %s got(%08x)\n", #e, #e2, status);\
526 pRtlFreeUnicodeString(&target);\
527 pRtlFreeUnicodeString(&str);
528
529 #define SYMLNK_TEST_CREATE_OPEN_FAILURE(h,n,t,e) SYMLNK_TEST_CREATE_OPEN_FAILURE2(h,n,t,e,e)
530
531 static void test_symboliclink(void)
532 {
533 NTSTATUS status;
534 UNICODE_STRING str, target;
535 OBJECT_ATTRIBUTES attr;
536 HANDLE dir, link, h;
537 IO_STATUS_BLOCK iosb;
538
539 /* No name and/or no attributes */
540 InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
541 SYMLNK_TEST_CREATE_OPEN_FAILURE2(NULL, "", "", STATUS_ACCESS_VIOLATION, STATUS_INVALID_PARAMETER)
542
543 status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL, NULL);
544 ok(status == STATUS_ACCESS_VIOLATION,
545 "NtCreateSymbolicLinkObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
546 status = pNtOpenSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL);
547 ok(status == STATUS_INVALID_PARAMETER,
548 "NtOpenSymbolicLinkObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
549
550 /* No attributes */
551 pRtlCreateUnicodeStringFromAsciiz(&target, "\\DosDevices");
552 status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL, &target);
553 ok(status == STATUS_SUCCESS || status == STATUS_ACCESS_VIOLATION, /* nt4 */
554 "NtCreateSymbolicLinkObject failed(%08x)\n", status);
555 pRtlFreeUnicodeString(&target);
556 if (!status) pNtClose(h);
557
558 InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
559 status = pNtCreateSymbolicLinkObject(&link, SYMBOLIC_LINK_QUERY, &attr, &target);
560 ok(status == STATUS_INVALID_PARAMETER ||
561 broken(status == STATUS_SUCCESS), /* nt4 */
562 "NtCreateSymbolicLinkObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
563 if (!status) pNtClose(h);
564 status = pNtOpenSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, &attr);
565 ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
566 "NtOpenSymbolicLinkObject should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
567
568 /* Bad name */
569 pRtlCreateUnicodeStringFromAsciiz(&target, "anywhere");
570 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
571
572 pRtlCreateUnicodeStringFromAsciiz(&str, "");
573 status = pNtCreateSymbolicLinkObject(&link, SYMBOLIC_LINK_QUERY, &attr, &target);
574 ok(status == STATUS_SUCCESS, "Failed to create SymbolicLink(%08x)\n", status);
575 status = pNtOpenSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, &attr);
576 ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
577 "NtOpenSymbolicLinkObject should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
578 pNtClose(link);
579 pRtlFreeUnicodeString(&str);
580
581 pRtlCreateUnicodeStringFromAsciiz(&str, "\\");
582 status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, &attr, &target);
583 todo_wine ok(status == STATUS_OBJECT_TYPE_MISMATCH,
584 "NtCreateSymbolicLinkObject should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
585 pRtlFreeUnicodeString(&str);
586 pRtlFreeUnicodeString(&target);
587
588 SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "BaseNamedObjects", "->Somewhere", STATUS_OBJECT_PATH_SYNTAX_BAD)
589 SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
590 SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\\\BaseNamedObjects", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
591 SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\\\om.c-test", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
592 SYMLNK_TEST_CREATE_OPEN_FAILURE2(&h, "\\BaseNamedObjects\\om.c-test\\", "->Somewhere",
593 STATUS_OBJECT_NAME_INVALID, STATUS_OBJECT_PATH_NOT_FOUND)
594
595
596 /* Compound test */
597 if (!(dir = get_base_dir()))
598 {
599 win_skip( "couldn't find the BaseNamedObjects dir\n" );
600 return;
601 }
602
603 InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
604 pRtlCreateUnicodeStringFromAsciiz(&str, "test-link");
605 pRtlCreateUnicodeStringFromAsciiz(&target, "\\DosDevices");
606 status = pNtCreateSymbolicLinkObject(&link, SYMBOLIC_LINK_QUERY, &attr, &target);
607 ok(status == STATUS_SUCCESS, "Failed to create SymbolicLink(%08x)\n", status);
608 pRtlFreeUnicodeString(&str);
609 pRtlFreeUnicodeString(&target);
610
611 pRtlCreateUnicodeStringFromAsciiz(&str, "test-link\\NUL");
612 status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
613 todo_wine ok(status == STATUS_SUCCESS, "Failed to open NUL device(%08x)\n", status);
614 pRtlFreeUnicodeString(&str);
615
616 pNtClose(h);
617 pNtClose(link);
618 pNtClose(dir);
619 }
620
621 static void test_query_object(void)
622 {
623 static const WCHAR name[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s',
624 '\\','t','e','s','t','_','e','v','e','n','t'};
625 HANDLE handle;
626 char buffer[1024];
627 NTSTATUS status;
628 ULONG len;
629 UNICODE_STRING *str;
630 char dir[MAX_PATH];
631
632 handle = CreateEventA( NULL, FALSE, FALSE, "test_event" );
633
634 len = 0;
635 status = pNtQueryObject( handle, ObjectNameInformation, buffer, 0, &len );
636 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
637 ok( len >= sizeof(UNICODE_STRING) + sizeof(name) + sizeof(WCHAR), "unexpected len %u\n", len );
638
639 len = 0;
640 status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(UNICODE_STRING), &len );
641 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
642 ok( len >= sizeof(UNICODE_STRING) + sizeof(name) + sizeof(WCHAR), "unexpected len %u\n", len );
643
644 len = 0;
645 status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len );
646 ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
647 ok( len > sizeof(UNICODE_STRING), "unexpected len %u\n", len );
648 str = (UNICODE_STRING *)buffer;
649 ok( sizeof(UNICODE_STRING) + str->Length + sizeof(WCHAR) == len, "unexpected len %u\n", len );
650 ok( str->Length >= sizeof(name), "unexpected len %u\n", str->Length );
651 /* there can be a \\Sessions prefix in the name */
652 ok( !memcmp( str->Buffer + (str->Length - sizeof(name)) / sizeof(WCHAR), name, sizeof(name) ),
653 "wrong name %s\n", wine_dbgstr_w(str->Buffer) );
654
655 len -= sizeof(WCHAR);
656 status = pNtQueryObject( handle, ObjectNameInformation, buffer, len, &len );
657 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
658 ok( len >= sizeof(UNICODE_STRING) + sizeof(name) + sizeof(WCHAR), "unexpected len %u\n", len );
659
660 pNtClose( handle );
661
662 handle = CreateEventA( NULL, FALSE, FALSE, NULL );
663 len = 0;
664 status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len );
665 ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
666 ok( len == sizeof(UNICODE_STRING), "unexpected len %u\n", len );
667 str = (UNICODE_STRING *)buffer;
668 ok( str->Length == 0, "unexpected len %u\n", len );
669 ok( str->Buffer == NULL, "unexpected ptr %p\n", str->Buffer );
670 pNtClose( handle );
671
672 GetWindowsDirectoryA( dir, MAX_PATH );
673 handle = CreateFileA( dir, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
674 FILE_FLAG_BACKUP_SEMANTICS, 0 );
675 len = 0;
676 status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len );
677 ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
678 ok( len > sizeof(UNICODE_STRING), "unexpected len %u\n", len );
679 str = (UNICODE_STRING *)buffer;
680 ok( sizeof(UNICODE_STRING) + str->Length + sizeof(WCHAR) == len ||
681 broken(sizeof(UNICODE_STRING) + str->Length == len), /* NT4 */
682 "unexpected len %u\n", len );
683 trace( "got %s len %u\n", wine_dbgstr_w(str->Buffer), len );
684 pNtClose( handle );
685 }
686
687 START_TEST(om)
688 {
689 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
690 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
691
692 if (!hntdll)
693 {
694 skip("not running on NT, skipping test\n");
695 return;
696 }
697
698 pCreateWaitableTimerA = (void *)GetProcAddress(hkernel32, "CreateWaitableTimerA");
699
700 pRtlCreateUnicodeStringFromAsciiz = (void *)GetProcAddress(hntdll, "RtlCreateUnicodeStringFromAsciiz");
701 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
702 pNtCreateEvent = (void *)GetProcAddress(hntdll, "NtCreateEvent");
703 pNtCreateMutant = (void *)GetProcAddress(hntdll, "NtCreateMutant");
704 pNtOpenMutant = (void *)GetProcAddress(hntdll, "NtOpenMutant");
705 pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
706 pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
707 pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
708 pNtCreateNamedPipeFile = (void *)GetProcAddress(hntdll, "NtCreateNamedPipeFile");
709 pNtOpenDirectoryObject = (void *)GetProcAddress(hntdll, "NtOpenDirectoryObject");
710 pNtCreateDirectoryObject= (void *)GetProcAddress(hntdll, "NtCreateDirectoryObject");
711 pNtOpenSymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtOpenSymbolicLinkObject");
712 pNtCreateSymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtCreateSymbolicLinkObject");
713 pNtCreateSemaphore = (void *)GetProcAddress(hntdll, "NtCreateSemaphore");
714 pNtCreateTimer = (void *)GetProcAddress(hntdll, "NtCreateTimer");
715 pNtCreateSection = (void *)GetProcAddress(hntdll, "NtCreateSection");
716 pNtQueryObject = (void *)GetProcAddress(hntdll, "NtQueryObject");
717
718 test_case_sensitive();
719 test_namespace_pipe();
720 test_name_collisions();
721 test_directory();
722 test_symboliclink();
723 test_query_object();
724 }