ntdll/tests: Make tests run again on win95.
[wine] / dlls / ntdll / tests / 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
48
49 static void test_case_sensitive (void)
50 {
51     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};
52     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};
53     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};
54     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};
55     NTSTATUS status;
56     OBJECT_ATTRIBUTES attr;
57     UNICODE_STRING str;
58     HANDLE Event, Mutant, h;
59
60     pRtlInitUnicodeString(&str, buffer1);
61     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
62     status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
63     ok(status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status);
64
65     status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, FALSE, FALSE);
66     ok(status == STATUS_OBJECT_NAME_COLLISION,
67         "NtCreateEvent should have failed with STATUS_OBJECT_NAME_COLLISION got(%08x)\n", status);
68
69     pRtlInitUnicodeString(&str, buffer2);
70     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
71     status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, FALSE, FALSE);
72     ok(status == STATUS_SUCCESS, "Failed to create Event(%08x)\n", status);
73
74     pRtlInitUnicodeString(&str, buffer3);
75     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
76     status = pNtOpenMutant(&h, GENERIC_ALL, &attr);
77     ok(status == STATUS_OBJECT_TYPE_MISMATCH,
78         "NtOpenMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
79
80     pNtClose(Mutant);
81
82     pRtlInitUnicodeString(&str, buffer4);
83     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
84     status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
85     ok(status == STATUS_OBJECT_NAME_COLLISION,
86         "NtCreateMutant should have failed with STATUS_OBJECT_NAME_COLLISION got(%08x)\n", status);
87
88     status = pNtCreateEvent(&h, GENERIC_ALL, &attr, FALSE, FALSE);
89     ok(status == STATUS_OBJECT_NAME_COLLISION,
90         "NtCreateEvent should have failed with STATUS_OBJECT_NAME_COLLISION got(%08x)\n", status);
91
92     attr.Attributes = 0;
93     status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
94     ok(status == STATUS_OBJECT_PATH_NOT_FOUND,
95         "NtCreateMutant should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
96
97     pNtClose(Event);
98 }
99
100 static void test_namespace_pipe(void)
101 {
102     static const WCHAR buffer1[] = {'\\','?','?','\\','P','I','P','E','\\','t','e','s','t','\\','p','i','p','e',0};
103     static const WCHAR buffer2[] = {'\\','?','?','\\','P','I','P','E','\\','T','E','S','T','\\','P','I','P','E',0};
104     static const WCHAR buffer3[] = {'\\','?','?','\\','p','i','p','e','\\','t','e','s','t','\\','p','i','p','e',0};
105     static const WCHAR buffer4[] = {'\\','?','?','\\','p','i','p','e','\\','t','e','s','t',0};
106     OBJECT_ATTRIBUTES attr;
107     UNICODE_STRING str;
108     IO_STATUS_BLOCK iosb;
109     NTSTATUS status;
110     LARGE_INTEGER timeout;
111     HANDLE pipe, h;
112
113     timeout.QuadPart = -10000;
114
115     pRtlInitUnicodeString(&str, buffer1);
116     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
117     status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
118                                     FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
119     ok(status == STATUS_SUCCESS, "Failed to create NamedPipe(%08x)\n", status);
120
121     status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
122                                     FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
123     ok(status == STATUS_INSTANCE_NOT_AVAILABLE,
124         "NtCreateNamedPipeFile should have failed with STATUS_INSTANCE_NOT_AVAILABLE got(%08x)\n", status);
125
126     pRtlInitUnicodeString(&str, buffer2);
127     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
128     status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
129                                     FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
130     ok(status == STATUS_INSTANCE_NOT_AVAILABLE,
131         "NtCreateNamedPipeFile should have failed with STATUS_INSTANCE_NOT_AVAILABLE got(%08x)\n", status);
132
133     attr.Attributes = OBJ_CASE_INSENSITIVE;
134     status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
135     ok(status == STATUS_SUCCESS, "Failed to open NamedPipe(%08x)\n", status);
136     pNtClose(h);
137
138     pRtlInitUnicodeString(&str, buffer3);
139     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
140     status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
141     ok(status == STATUS_OBJECT_PATH_NOT_FOUND || status == STATUS_PIPE_NOT_AVAILABLE,
142         "pNtOpenFile should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
143
144     pRtlInitUnicodeString(&str, buffer4);
145     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
146     status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
147     ok(status == STATUS_OBJECT_NAME_NOT_FOUND,
148         "pNtOpenFile should have failed with STATUS_OBJECT_NAME_NOT_FOUND got(%08x)\n", status);
149
150     pNtClose(pipe);
151 }
152
153 #define DIRECTORY_QUERY (0x0001)
154 #define SYMBOLIC_LINK_QUERY 0x0001
155
156 #define DIR_TEST_CREATE_FAILURE(h,e) \
157     status = pNtCreateDirectoryObject(h, DIRECTORY_QUERY, &attr);\
158     ok(status == e,"NtCreateDirectoryObject should have failed with %s got(%08x)\n", #e, status);
159 #define DIR_TEST_OPEN_FAILURE(h,e) \
160     status = pNtOpenDirectoryObject(h, DIRECTORY_QUERY, &attr);\
161     ok(status == e,"NtOpenDirectoryObject should have failed with %s got(%08x)\n", #e, status);
162 #define DIR_TEST_CREATE_OPEN_FAILURE(h,n,e) \
163     pRtlCreateUnicodeStringFromAsciiz(&str, n);\
164     DIR_TEST_CREATE_FAILURE(h,e) DIR_TEST_OPEN_FAILURE(h,e)\
165     pRtlFreeUnicodeString(&str);
166
167 #define DIR_TEST_CREATE_SUCCESS(h) \
168     status = pNtCreateDirectoryObject(h, DIRECTORY_QUERY, &attr); \
169     ok(status == STATUS_SUCCESS, "Failed to create Directory(%08x)\n", status);
170 #define DIR_TEST_OPEN_SUCCESS(h) \
171     status = pNtOpenDirectoryObject(h, DIRECTORY_QUERY, &attr); \
172     ok(status == STATUS_SUCCESS, "Failed to open Directory(%08x)\n", status);
173 #define DIR_TEST_CREATE_OPEN_SUCCESS(h,n) \
174     pRtlCreateUnicodeStringFromAsciiz(&str, n);\
175     DIR_TEST_CREATE_SUCCESS(&h) pNtClose(h); DIR_TEST_OPEN_SUCCESS(&h) pNtClose(h); \
176     pRtlFreeUnicodeString(&str);
177
178 static void test_name_collisions(void)
179 {
180     NTSTATUS status;
181     UNICODE_STRING str;
182     OBJECT_ATTRIBUTES attr;
183     HANDLE dir, h, h1, h2;
184     DWORD winerr;
185     LARGE_INTEGER size;
186
187     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
188     pRtlCreateUnicodeStringFromAsciiz(&str, "\\");
189     DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_NAME_COLLISION)
190     InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, 0, NULL);
191
192     DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_NAME_EXISTS)
193     pNtClose(h);
194     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
195     ok(status == STATUS_OBJECT_TYPE_MISMATCH,
196         "NtCreateMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
197     pRtlFreeUnicodeString(&str);
198
199     pRtlCreateUnicodeStringFromAsciiz(&str, "\\??\\PIPE\\om.c-mutant");
200     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
201     ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_OBJECT_PATH_NOT_FOUND,
202         "NtCreateMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
203     pRtlFreeUnicodeString(&str);
204
205
206     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
207     DIR_TEST_OPEN_SUCCESS(&dir)
208     pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-test");
209     InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, dir, NULL);
210     
211     h = CreateMutexA(NULL, FALSE, "om.c-test");
212     ok(h != 0, "CreateMutexA failed got ret=%p (%d)\n", h, GetLastError());
213     status = pNtCreateMutant(&h1, GENERIC_ALL, &attr, FALSE);
214     ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
215         "NtCreateMutant should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
216     h2 = CreateMutexA(NULL, FALSE, "om.c-test");
217     winerr = GetLastError();
218     ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
219         "CreateMutexA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
220     pNtClose(h);
221     pNtClose(h1);
222     pNtClose(h2);
223
224     h = CreateEventA(NULL, FALSE, FALSE, "om.c-test");
225     ok(h != 0, "CreateEventA failed got ret=%p (%d)\n", h, GetLastError());
226     status = pNtCreateEvent(&h1, GENERIC_ALL, &attr, FALSE, FALSE);
227     ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
228         "NtCreateEvent should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
229     h2 = CreateEventA(NULL, FALSE, FALSE, "om.c-test");
230     winerr = GetLastError();
231     ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
232         "CreateEventA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
233     pNtClose(h);
234     pNtClose(h1);
235     pNtClose(h2);
236
237     h = CreateSemaphoreA(NULL, 1, 2, "om.c-test");
238     ok(h != 0, "CreateSemaphoreA failed got ret=%p (%d)\n", h, GetLastError());
239     status = pNtCreateSemaphore(&h1, GENERIC_ALL, &attr, 1, 2);
240     ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
241         "NtCreateSemaphore should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
242     h2 = CreateSemaphoreA(NULL, 1, 2, "om.c-test");
243     winerr = GetLastError();
244     ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
245         "CreateSemaphoreA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
246     pNtClose(h);
247     pNtClose(h1);
248     pNtClose(h2);
249     
250     h = pCreateWaitableTimerA(NULL, TRUE, "om.c-test");
251     ok(h != 0, "CreateWaitableTimerA failed got ret=%p (%d)\n", h, GetLastError());
252     status = pNtCreateTimer(&h1, GENERIC_ALL, &attr, NotificationTimer);
253     ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
254         "NtCreateTimer should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
255     h2 = pCreateWaitableTimerA(NULL, TRUE, "om.c-test");
256     winerr = GetLastError();
257     ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
258         "CreateWaitableTimerA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
259     pNtClose(h);
260     pNtClose(h1);
261     pNtClose(h2);
262
263     h = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 256, "om.c-test");
264     ok(h != 0, "CreateFileMappingA failed got ret=%p (%d)\n", h, GetLastError());
265     size.u.LowPart = 256;
266     size.u.HighPart = 0;
267     status = pNtCreateSection(&h1, SECTION_MAP_WRITE, &attr, &size, PAGE_READWRITE, SEC_COMMIT, 0);
268     ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
269         "NtCreateSection should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
270     h2 = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 256, "om.c-test");
271     winerr = GetLastError();
272     ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
273         "CreateFileMappingA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
274     pNtClose(h);
275     pNtClose(h1);
276     pNtClose(h2);
277
278     pRtlFreeUnicodeString(&str);
279     pNtClose(dir);
280 }
281
282 static void test_directory(void)
283 {
284     NTSTATUS status;
285     UNICODE_STRING str;
286     OBJECT_ATTRIBUTES attr;
287     HANDLE dir, dir1, h;
288
289     /* No name and/or no attributes */
290     status = pNtCreateDirectoryObject(NULL, DIRECTORY_QUERY, &attr);
291     ok(status == STATUS_ACCESS_VIOLATION,
292         "NtCreateDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
293     status = pNtOpenDirectoryObject(NULL, DIRECTORY_QUERY, &attr);
294     ok(status == STATUS_ACCESS_VIOLATION,
295         "NtOpenDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
296
297     status = pNtCreateDirectoryObject(&h, DIRECTORY_QUERY, NULL);
298     ok(status == STATUS_SUCCESS, "Failed to create Directory without attributes(%08x)\n", status);
299     pNtClose(h);
300     status = pNtOpenDirectoryObject(&h, DIRECTORY_QUERY, NULL);
301     ok(status == STATUS_INVALID_PARAMETER,
302         "NtOpenDirectoryObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
303
304     InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
305     DIR_TEST_CREATE_SUCCESS(&dir)
306     DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
307
308     /* Bad name */
309     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
310
311     pRtlCreateUnicodeStringFromAsciiz(&str, "");
312     DIR_TEST_CREATE_SUCCESS(&h)
313     pNtClose(h);
314     DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
315     pRtlFreeUnicodeString(&str);
316     pNtClose(dir);
317
318     DIR_TEST_CREATE_OPEN_FAILURE(&h, "BaseNamedObjects", STATUS_OBJECT_PATH_SYNTAX_BAD)
319     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\", STATUS_OBJECT_NAME_INVALID)
320     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\\\BaseNamedObjects", STATUS_OBJECT_NAME_INVALID)
321     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\\\om.c-test", STATUS_OBJECT_NAME_INVALID)
322     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\om.c-test\\", STATUS_OBJECT_PATH_NOT_FOUND)
323
324     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test");
325     DIR_TEST_CREATE_SUCCESS(&h)
326     DIR_TEST_OPEN_SUCCESS(&dir1)
327     pRtlFreeUnicodeString(&str);
328     pNtClose(h);
329     pNtClose(dir1);
330
331
332     /* Use of root directory */
333
334     /* Can't use symlinks as a directory */
335     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local");
336     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
337     status = pNtOpenSymbolicLinkObject(&dir, SYMBOLIC_LINK_QUERY, &attr);
338     ok(status == STATUS_SUCCESS, "Failed to open SymbolicLink(%08x)\n", status);
339     pRtlFreeUnicodeString(&str);
340     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
341     pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
342     DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_TYPE_MISMATCH)
343     pRtlFreeUnicodeString(&str);
344     pNtClose(h);
345     pNtClose(dir);
346
347     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
348     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
349     DIR_TEST_OPEN_SUCCESS(&dir)
350     pRtlFreeUnicodeString(&str);
351
352     InitializeObjectAttributes(&attr, NULL, 0, dir, NULL);
353     DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_NAME_INVALID)
354
355     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
356     DIR_TEST_CREATE_OPEN_SUCCESS(h, "")
357     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\", STATUS_OBJECT_PATH_SYNTAX_BAD)
358     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test", STATUS_OBJECT_PATH_SYNTAX_BAD)
359     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test\\", STATUS_OBJECT_PATH_SYNTAX_BAD)
360     DIR_TEST_CREATE_OPEN_FAILURE(&h, "om.c-test\\", STATUS_OBJECT_PATH_NOT_FOUND)
361
362     pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-test");
363     DIR_TEST_CREATE_SUCCESS(&dir1)
364     DIR_TEST_OPEN_SUCCESS(&h)
365     pRtlFreeUnicodeString(&str);
366
367     pNtClose(h);
368     pNtClose(dir1);
369     pNtClose(dir);
370
371     /* Nested directories */
372     pRtlCreateUnicodeStringFromAsciiz(&str, "\\");
373     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
374     DIR_TEST_OPEN_SUCCESS(&dir)
375     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
376     DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
377     pRtlFreeUnicodeString(&str);
378     pNtClose(dir);
379
380     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
381     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test");
382     DIR_TEST_CREATE_SUCCESS(&dir)
383     pRtlFreeUnicodeString(&str);
384     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test\\one more level");
385     DIR_TEST_CREATE_SUCCESS(&h)
386     pRtlFreeUnicodeString(&str);
387     pNtClose(h);
388     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
389     pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
390     DIR_TEST_CREATE_SUCCESS(&h)
391     pRtlFreeUnicodeString(&str);
392     pNtClose(h);
393
394     pNtClose(dir);
395
396     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
397     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Global\\om.c-test");
398     DIR_TEST_CREATE_SUCCESS(&dir)
399     pRtlFreeUnicodeString(&str);
400     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local\\om.c-test\\one more level");
401     DIR_TEST_CREATE_SUCCESS(&h)
402     pRtlFreeUnicodeString(&str);
403     pNtClose(h);
404     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
405     pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
406     DIR_TEST_CREATE_SUCCESS(&dir)
407     pRtlFreeUnicodeString(&str);
408     pNtClose(h);
409
410     pNtClose(dir);
411
412
413     /* Create other objects using RootDirectory */
414
415     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
416     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
417     DIR_TEST_OPEN_SUCCESS(&dir)
418     pRtlFreeUnicodeString(&str);
419     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
420
421     /* Test inavalid paths */
422     pRtlCreateUnicodeStringFromAsciiz(&str, "\\om.c-mutant");
423     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
424     ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
425         "NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
426     pRtlFreeUnicodeString(&str);
427     pRtlCreateUnicodeStringFromAsciiz(&str, "\\om.c-mutant\\");
428     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
429     ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
430         "NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
431     pRtlFreeUnicodeString(&str);
432
433     pRtlCreateUnicodeStringFromAsciiz(&str, "om.c\\-mutant");
434     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
435     ok(status == STATUS_OBJECT_PATH_NOT_FOUND,
436         "NtCreateMutant should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
437     pRtlFreeUnicodeString(&str);
438
439     pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-mutant");
440     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
441     ok(status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status);
442     pRtlFreeUnicodeString(&str);
443     pNtClose(h);
444
445     pNtClose(dir);
446 }
447
448 #define SYMLNK_TEST_CREATE_FAILURE(h,e) \
449     status = pNtCreateSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr, &target);\
450     ok(status == e,"NtCreateSymbolicLinkObject should have failed with %s got(%08x)\n", #e, status);
451 #define SYMLNK_TEST_OPEN_FAILURE(h,e) \
452     status = pNtOpenSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr);\
453     ok(status == e,"NtOpenSymbolicLinkObject should have failed with %s got(%08x)\n", #e, status);
454 #define SYMLNK_TEST_CREATE_OPEN_FAILURE(h,n,t,e) \
455     pRtlCreateUnicodeStringFromAsciiz(&str, n);\
456     pRtlCreateUnicodeStringFromAsciiz(&target, t);\
457     SYMLNK_TEST_CREATE_FAILURE(h,e)\
458     SYMLNK_TEST_OPEN_FAILURE(h,e)\
459     pRtlFreeUnicodeString(&target);\
460     pRtlFreeUnicodeString(&str);
461
462 #define SYMLNK_TEST_CREATE_SUCCESS(h) \
463     status = pNtCreateSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr, &target); \
464     ok(status == STATUS_SUCCESS, "Failed to create SymbolicLink(%08x)\n", status);
465 #define SYMLNK_TEST_OPEN_SUCCESS(h) \
466     status = pNtOpenSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr); \
467     ok(status == STATUS_SUCCESS, "Failed to open SymbolicLink(%08x)\n", status);
468
469 static void test_symboliclink(void)
470 {
471     NTSTATUS status;
472     UNICODE_STRING str, target;
473     OBJECT_ATTRIBUTES attr;
474     HANDLE dir, link, h;
475     IO_STATUS_BLOCK iosb;
476
477     /* No name and/or no attributes */
478     SYMLNK_TEST_CREATE_OPEN_FAILURE(NULL, "", "", STATUS_ACCESS_VIOLATION)
479
480     status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL, NULL);
481     ok(status == STATUS_ACCESS_VIOLATION,
482         "NtCreateSymbolicLinkObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
483     status = pNtOpenSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL);
484     ok(status == STATUS_INVALID_PARAMETER,
485         "NtOpenSymbolicLinkObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
486
487     /* No attributes */
488     pRtlCreateUnicodeStringFromAsciiz(&target, "\\DosDevices");
489     status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL, &target);
490     ok(status == STATUS_SUCCESS, "NtCreateSymbolicLinkObject failed(%08x)\n", status);
491     pRtlFreeUnicodeString(&target);
492     pNtClose(h);
493
494     InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
495     SYMLNK_TEST_CREATE_FAILURE(&link, STATUS_INVALID_PARAMETER)
496     SYMLNK_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
497
498     /* Bad name */
499     pRtlCreateUnicodeStringFromAsciiz(&target, "anywhere");
500     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
501
502     pRtlCreateUnicodeStringFromAsciiz(&str, "");
503     SYMLNK_TEST_CREATE_SUCCESS(&link)
504     SYMLNK_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
505     pNtClose(link);
506     pRtlFreeUnicodeString(&str);
507
508     pRtlCreateUnicodeStringFromAsciiz(&str, "\\");
509     todo_wine {SYMLNK_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_TYPE_MISMATCH)}
510     pRtlFreeUnicodeString(&str);
511     pRtlFreeUnicodeString(&target);
512
513     SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "BaseNamedObjects", "->Somewhere", STATUS_OBJECT_PATH_SYNTAX_BAD)
514     SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
515     SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\\\BaseNamedObjects", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
516     SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\\\om.c-test", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
517     SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\om.c-test\\", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
518
519
520     /* Compaund test */
521     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
522     DIR_TEST_OPEN_SUCCESS(&dir)
523     pRtlFreeUnicodeString(&str);
524
525     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
526     pRtlCreateUnicodeStringFromAsciiz(&str, "Local\\test-link");
527     pRtlCreateUnicodeStringFromAsciiz(&target, "\\DosDevices");
528     SYMLNK_TEST_CREATE_SUCCESS(&link)
529     pRtlFreeUnicodeString(&str);
530     pRtlFreeUnicodeString(&target);
531
532     pRtlCreateUnicodeStringFromAsciiz(&str, "Local\\test-link\\PIPE");
533     status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
534     todo_wine ok(status == STATUS_SUCCESS, "Failed to open NamedPipe(%08x)\n", status);
535     pRtlFreeUnicodeString(&str);
536
537     pNtClose(h);
538     pNtClose(link);
539     pNtClose(dir);
540 }
541
542 START_TEST(om)
543 {
544     HMODULE hntdll = GetModuleHandleA("ntdll.dll");
545     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
546
547     if (!hntdll)
548     {
549         skip("not running on NT, skipping test\n");
550         return;
551     }
552
553     pCreateWaitableTimerA = (void *)GetProcAddress(hkernel32, "CreateWaitableTimerA");
554
555     pRtlCreateUnicodeStringFromAsciiz = (void *)GetProcAddress(hntdll, "RtlCreateUnicodeStringFromAsciiz");
556     pRtlFreeUnicodeString   = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
557     pNtCreateEvent          = (void *)GetProcAddress(hntdll, "NtCreateEvent");
558     pNtCreateMutant         = (void *)GetProcAddress(hntdll, "NtCreateMutant");
559     pNtOpenMutant           = (void *)GetProcAddress(hntdll, "NtOpenMutant");
560     pNtOpenFile             = (void *)GetProcAddress(hntdll, "NtOpenFile");
561     pNtClose                = (void *)GetProcAddress(hntdll, "NtClose");
562     pRtlInitUnicodeString   = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
563     pNtCreateNamedPipeFile  = (void *)GetProcAddress(hntdll, "NtCreateNamedPipeFile");
564     pNtOpenDirectoryObject  = (void *)GetProcAddress(hntdll, "NtOpenDirectoryObject");
565     pNtCreateDirectoryObject= (void *)GetProcAddress(hntdll, "NtCreateDirectoryObject");
566     pNtOpenSymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtOpenSymbolicLinkObject");
567     pNtCreateSymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtCreateSymbolicLinkObject");
568     pNtCreateSemaphore      =  (void *)GetProcAddress(hntdll, "NtCreateSemaphore");
569     pNtCreateTimer          =  (void *)GetProcAddress(hntdll, "NtCreateTimer");
570     pNtCreateSection        =  (void *)GetProcAddress(hntdll, "NtCreateSection");
571
572     test_case_sensitive();
573     test_namespace_pipe();
574     test_name_collisions();
575     test_directory();
576     test_symboliclink();
577 }