wintrust: Use helper function for setting confidence in SoftpubCheckCert.
[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         "NtOpenFile 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         "NtOpenFile 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     BOOL is_nt4;
289
290     /* No name and/or no attributes */
291     status = pNtCreateDirectoryObject(NULL, DIRECTORY_QUERY, &attr);
292     ok(status == STATUS_ACCESS_VIOLATION,
293         "NtCreateDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
294     status = pNtOpenDirectoryObject(NULL, DIRECTORY_QUERY, &attr);
295     ok(status == STATUS_ACCESS_VIOLATION,
296         "NtOpenDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
297
298     status = pNtCreateDirectoryObject(&h, DIRECTORY_QUERY, NULL);
299     ok(status == STATUS_SUCCESS, "Failed to create Directory without attributes(%08x)\n", status);
300     pNtClose(h);
301     status = pNtOpenDirectoryObject(&h, DIRECTORY_QUERY, NULL);
302     ok(status == STATUS_INVALID_PARAMETER,
303         "NtOpenDirectoryObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
304
305     InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
306     DIR_TEST_CREATE_SUCCESS(&dir)
307     DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
308
309     /* Bad name */
310     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
311
312     pRtlCreateUnicodeStringFromAsciiz(&str, "");
313     DIR_TEST_CREATE_SUCCESS(&h)
314     pNtClose(h);
315     DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
316     pRtlFreeUnicodeString(&str);
317     pNtClose(dir);
318
319     DIR_TEST_CREATE_OPEN_FAILURE(&h, "BaseNamedObjects", STATUS_OBJECT_PATH_SYNTAX_BAD)
320     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\", STATUS_OBJECT_NAME_INVALID)
321     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\\\BaseNamedObjects", STATUS_OBJECT_NAME_INVALID)
322     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\\\om.c-test", STATUS_OBJECT_NAME_INVALID)
323     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\om.c-test\\", STATUS_OBJECT_PATH_NOT_FOUND)
324
325     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test");
326     DIR_TEST_CREATE_SUCCESS(&h)
327     DIR_TEST_OPEN_SUCCESS(&dir1)
328     pRtlFreeUnicodeString(&str);
329     pNtClose(h);
330     pNtClose(dir1);
331
332
333     /* Use of root directory */
334
335     /* Can't use symlinks as a directory */
336     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local");
337     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
338     status = pNtOpenSymbolicLinkObject(&dir, SYMBOLIC_LINK_QUERY, &attr);
339     is_nt4 = (status == STATUS_OBJECT_NAME_NOT_FOUND);  /* nt4 doesn't have Local\\ symlink */
340     if (!is_nt4)
341     {
342         ok(status == STATUS_SUCCESS, "Failed to open SymbolicLink(%08x)\n", status);
343         pRtlFreeUnicodeString(&str);
344         InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
345         pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
346         DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_TYPE_MISMATCH)
347         pRtlFreeUnicodeString(&str);
348         pNtClose(h);
349         pNtClose(dir);
350     }
351
352     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
353     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
354     DIR_TEST_OPEN_SUCCESS(&dir)
355     pRtlFreeUnicodeString(&str);
356
357     InitializeObjectAttributes(&attr, NULL, 0, dir, NULL);
358     DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_NAME_INVALID)
359
360     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
361     DIR_TEST_CREATE_OPEN_SUCCESS(h, "")
362     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\", STATUS_OBJECT_PATH_SYNTAX_BAD)
363     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test", STATUS_OBJECT_PATH_SYNTAX_BAD)
364     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test\\", STATUS_OBJECT_PATH_SYNTAX_BAD)
365     DIR_TEST_CREATE_OPEN_FAILURE(&h, "om.c-test\\", STATUS_OBJECT_PATH_NOT_FOUND)
366
367     pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-test");
368     DIR_TEST_CREATE_SUCCESS(&dir1)
369     DIR_TEST_OPEN_SUCCESS(&h)
370     pRtlFreeUnicodeString(&str);
371
372     pNtClose(h);
373     pNtClose(dir1);
374     pNtClose(dir);
375
376     /* Nested directories */
377     pRtlCreateUnicodeStringFromAsciiz(&str, "\\");
378     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
379     DIR_TEST_OPEN_SUCCESS(&dir)
380     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
381     DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
382     pRtlFreeUnicodeString(&str);
383     pNtClose(dir);
384
385     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
386     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test");
387     DIR_TEST_CREATE_SUCCESS(&dir)
388     pRtlFreeUnicodeString(&str);
389     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test\\one more level");
390     DIR_TEST_CREATE_SUCCESS(&h)
391     pRtlFreeUnicodeString(&str);
392     pNtClose(h);
393     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
394     pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
395     DIR_TEST_CREATE_SUCCESS(&h)
396     pRtlFreeUnicodeString(&str);
397     pNtClose(h);
398
399     pNtClose(dir);
400
401     if (!is_nt4)
402     {
403         InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
404         pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Global\\om.c-test");
405         DIR_TEST_CREATE_SUCCESS(&dir)
406         pRtlFreeUnicodeString(&str);
407         pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local\\om.c-test\\one more level");
408         DIR_TEST_CREATE_SUCCESS(&h)
409         pRtlFreeUnicodeString(&str);
410         pNtClose(h);
411         InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
412         pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
413         DIR_TEST_CREATE_SUCCESS(&dir)
414         pRtlFreeUnicodeString(&str);
415         pNtClose(h);
416         pNtClose(dir);
417     }
418
419     /* Create other objects using RootDirectory */
420
421     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
422     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
423     DIR_TEST_OPEN_SUCCESS(&dir)
424     pRtlFreeUnicodeString(&str);
425     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
426
427     /* Test invalid paths */
428     pRtlCreateUnicodeStringFromAsciiz(&str, "\\om.c-mutant");
429     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
430     ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
431         "NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
432     pRtlFreeUnicodeString(&str);
433     pRtlCreateUnicodeStringFromAsciiz(&str, "\\om.c-mutant\\");
434     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
435     ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
436         "NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD 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_OBJECT_PATH_NOT_FOUND,
442         "NtCreateMutant should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
443     pRtlFreeUnicodeString(&str);
444
445     pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-mutant");
446     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
447     ok(status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status);
448     pRtlFreeUnicodeString(&str);
449     pNtClose(h);
450
451     pNtClose(dir);
452 }
453
454 #define SYMLNK_TEST_CREATE_OPEN_FAILURE2(h,n,t,e,e2) \
455     pRtlCreateUnicodeStringFromAsciiz(&str, n);\
456     pRtlCreateUnicodeStringFromAsciiz(&target, t);\
457     status = pNtCreateSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr, &target);\
458     ok(status == e || status == e2, \
459        "NtCreateSymbolicLinkObject should have failed with %s or %s got(%08x)\n", #e, #e2, status);\
460     status = pNtOpenSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr);\
461     ok(status == e || status == e2, \
462        "NtOpenSymbolicLinkObject should have failed with %s or %s got(%08x)\n", #e, #e2, status);\
463     pRtlFreeUnicodeString(&target);\
464     pRtlFreeUnicodeString(&str);
465
466 #define SYMLNK_TEST_CREATE_OPEN_FAILURE(h,n,t,e) SYMLNK_TEST_CREATE_OPEN_FAILURE2(h,n,t,e,e)
467
468 static void test_symboliclink(void)
469 {
470     NTSTATUS status;
471     UNICODE_STRING str, target;
472     OBJECT_ATTRIBUTES attr;
473     HANDLE dir, link, h;
474     IO_STATUS_BLOCK iosb;
475
476     /* No name and/or no attributes */
477     SYMLNK_TEST_CREATE_OPEN_FAILURE(NULL, "", "", STATUS_ACCESS_VIOLATION)
478
479     status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL, NULL);
480     ok(status == STATUS_ACCESS_VIOLATION,
481         "NtCreateSymbolicLinkObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
482     status = pNtOpenSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL);
483     ok(status == STATUS_INVALID_PARAMETER,
484         "NtOpenSymbolicLinkObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
485
486     /* No attributes */
487     pRtlCreateUnicodeStringFromAsciiz(&target, "\\DosDevices");
488     status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL, &target);
489     ok(status == STATUS_SUCCESS || status == STATUS_ACCESS_VIOLATION, /* nt4 */
490        "NtCreateSymbolicLinkObject failed(%08x)\n", status);
491     pRtlFreeUnicodeString(&target);
492     if (!status) pNtClose(h);
493
494     InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
495     status = pNtCreateSymbolicLinkObject(&link, SYMBOLIC_LINK_QUERY, &attr, &target);
496     ok(status == STATUS_INVALID_PARAMETER ||
497        broken(status == STATUS_SUCCESS),  /* nt4 */
498        "NtCreateSymbolicLinkObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
499     if (!status) pNtClose(h);
500     status = pNtOpenSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, &attr);
501     ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
502        "NtOpenSymbolicLinkObject should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
503
504     /* Bad name */
505     pRtlCreateUnicodeStringFromAsciiz(&target, "anywhere");
506     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
507
508     pRtlCreateUnicodeStringFromAsciiz(&str, "");
509     status = pNtCreateSymbolicLinkObject(&link, SYMBOLIC_LINK_QUERY, &attr, &target);
510     ok(status == STATUS_SUCCESS, "Failed to create SymbolicLink(%08x)\n", status);
511     status = pNtOpenSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, &attr);
512     ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
513        "NtOpenSymbolicLinkObject should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
514     pNtClose(link);
515     pRtlFreeUnicodeString(&str);
516
517     pRtlCreateUnicodeStringFromAsciiz(&str, "\\");
518     status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, &attr, &target);
519     todo_wine ok(status == STATUS_OBJECT_TYPE_MISMATCH,
520                  "NtCreateSymbolicLinkObject should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
521     pRtlFreeUnicodeString(&str);
522     pRtlFreeUnicodeString(&target);
523
524     SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "BaseNamedObjects", "->Somewhere", STATUS_OBJECT_PATH_SYNTAX_BAD)
525     SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
526     SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\\\BaseNamedObjects", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
527     SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\\\om.c-test", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
528     SYMLNK_TEST_CREATE_OPEN_FAILURE2(&h, "\\BaseNamedObjects\\om.c-test\\", "->Somewhere",
529                                      STATUS_OBJECT_NAME_INVALID, STATUS_OBJECT_PATH_NOT_FOUND)
530
531
532     /* Compaund test */
533     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local");
534     status = pNtOpenDirectoryObject(&dir, DIRECTORY_QUERY, &attr);
535     if (status == STATUS_OBJECT_NAME_NOT_FOUND)  /* nt4 doesn't have Local\\ */
536     {
537         pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
538         status = pNtOpenDirectoryObject(&dir, DIRECTORY_QUERY, &attr);
539     }
540     ok(status == STATUS_SUCCESS, "Failed to open Directory(%08x)\n", status);
541     pRtlFreeUnicodeString(&str);
542
543     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
544     pRtlCreateUnicodeStringFromAsciiz(&str, "test-link");
545     pRtlCreateUnicodeStringFromAsciiz(&target, "\\DosDevices");
546     status = pNtCreateSymbolicLinkObject(&link, SYMBOLIC_LINK_QUERY, &attr, &target);
547     ok(status == STATUS_SUCCESS, "Failed to create SymbolicLink(%08x)\n", status);
548     pRtlFreeUnicodeString(&str);
549     pRtlFreeUnicodeString(&target);
550
551     pRtlCreateUnicodeStringFromAsciiz(&str, "test-link\\PIPE");
552     status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
553     todo_wine ok(status == STATUS_SUCCESS, "Failed to open NamedPipe(%08x)\n", status);
554     pRtlFreeUnicodeString(&str);
555
556     pNtClose(h);
557     pNtClose(link);
558     pNtClose(dir);
559 }
560
561 START_TEST(om)
562 {
563     HMODULE hntdll = GetModuleHandleA("ntdll.dll");
564     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
565
566     if (!hntdll)
567     {
568         skip("not running on NT, skipping test\n");
569         return;
570     }
571
572     pCreateWaitableTimerA = (void *)GetProcAddress(hkernel32, "CreateWaitableTimerA");
573
574     pRtlCreateUnicodeStringFromAsciiz = (void *)GetProcAddress(hntdll, "RtlCreateUnicodeStringFromAsciiz");
575     pRtlFreeUnicodeString   = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
576     pNtCreateEvent          = (void *)GetProcAddress(hntdll, "NtCreateEvent");
577     pNtCreateMutant         = (void *)GetProcAddress(hntdll, "NtCreateMutant");
578     pNtOpenMutant           = (void *)GetProcAddress(hntdll, "NtOpenMutant");
579     pNtOpenFile             = (void *)GetProcAddress(hntdll, "NtOpenFile");
580     pNtClose                = (void *)GetProcAddress(hntdll, "NtClose");
581     pRtlInitUnicodeString   = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
582     pNtCreateNamedPipeFile  = (void *)GetProcAddress(hntdll, "NtCreateNamedPipeFile");
583     pNtOpenDirectoryObject  = (void *)GetProcAddress(hntdll, "NtOpenDirectoryObject");
584     pNtCreateDirectoryObject= (void *)GetProcAddress(hntdll, "NtCreateDirectoryObject");
585     pNtOpenSymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtOpenSymbolicLinkObject");
586     pNtCreateSymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtCreateSymbolicLinkObject");
587     pNtCreateSemaphore      =  (void *)GetProcAddress(hntdll, "NtCreateSemaphore");
588     pNtCreateTimer          =  (void *)GetProcAddress(hntdll, "NtCreateTimer");
589     pNtCreateSection        =  (void *)GetProcAddress(hntdll, "NtCreateSection");
590
591     test_case_sensitive();
592     test_namespace_pipe();
593     test_name_collisions();
594     test_directory();
595     test_symboliclink();
596 }