Release 1.4.1.
[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 static NTSTATUS (WINAPI *pNtQuerySymbolicLinkObject)(HANDLE,PUNICODE_STRING,PULONG);
48 static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,ULONG,PULONG);
49 static NTSTATUS (WINAPI *pNtReleaseSemaphore)(HANDLE handle, ULONG count, PULONG previous);
50
51
52 static void test_case_sensitive (void)
53 {
54     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};
55     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};
56     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};
57     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};
58     NTSTATUS status;
59     OBJECT_ATTRIBUTES attr;
60     UNICODE_STRING str;
61     HANDLE Event, Mutant, h;
62
63     pRtlInitUnicodeString(&str, buffer1);
64     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
65     status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
66     ok(status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status);
67
68     status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, FALSE, FALSE);
69     ok(status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH,
70         "NtCreateEvent should have failed with STATUS_OBJECT_NAME_COLLISION or STATUS_OBJECT_TYPE_MISMATCH got (%08x)\n", status);
71
72     pRtlInitUnicodeString(&str, buffer2);
73     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
74     status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, FALSE, FALSE);
75     ok(status == STATUS_SUCCESS, "Failed to create Event(%08x)\n", status);
76
77     pRtlInitUnicodeString(&str, buffer3);
78     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
79     status = pNtOpenMutant(&h, GENERIC_ALL, &attr);
80     ok(status == STATUS_OBJECT_TYPE_MISMATCH,
81         "NtOpenMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
82
83     pNtClose(Mutant);
84
85     pRtlInitUnicodeString(&str, buffer4);
86     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
87     status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
88     ok(status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH,
89         "NtCreateMutant should have failed with STATUS_OBJECT_NAME_COLLISION or STATUS_OBJECT_TYPE_MISMATCH got (%08x)\n", status);
90
91     status = pNtCreateEvent(&h, GENERIC_ALL, &attr, FALSE, FALSE);
92     ok(status == STATUS_OBJECT_NAME_COLLISION,
93         "NtCreateEvent should have failed with STATUS_OBJECT_NAME_COLLISION got(%08x)\n", status);
94
95     attr.Attributes = 0;
96     status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
97     ok(status == STATUS_OBJECT_PATH_NOT_FOUND,
98         "NtCreateMutant should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
99
100     pNtClose(Event);
101 }
102
103 static void test_namespace_pipe(void)
104 {
105     static const WCHAR buffer1[] = {'\\','?','?','\\','P','I','P','E','\\','t','e','s','t','\\','p','i','p','e',0};
106     static const WCHAR buffer2[] = {'\\','?','?','\\','P','I','P','E','\\','T','E','S','T','\\','P','I','P','E',0};
107     static const WCHAR buffer3[] = {'\\','?','?','\\','p','i','p','e','\\','t','e','s','t','\\','p','i','p','e',0};
108     static const WCHAR buffer4[] = {'\\','?','?','\\','p','i','p','e','\\','t','e','s','t',0};
109     OBJECT_ATTRIBUTES attr;
110     UNICODE_STRING str;
111     IO_STATUS_BLOCK iosb;
112     NTSTATUS status;
113     LARGE_INTEGER timeout;
114     HANDLE pipe, h;
115
116     timeout.QuadPart = -10000;
117
118     pRtlInitUnicodeString(&str, buffer1);
119     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
120     status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
121                                     FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
122     ok(status == STATUS_SUCCESS, "Failed to create NamedPipe(%08x)\n", status);
123
124     status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
125                                     FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
126     ok(status == STATUS_INSTANCE_NOT_AVAILABLE,
127         "NtCreateNamedPipeFile should have failed with STATUS_INSTANCE_NOT_AVAILABLE got(%08x)\n", status);
128
129     pRtlInitUnicodeString(&str, buffer2);
130     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
131     status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
132                                     FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
133     ok(status == STATUS_INSTANCE_NOT_AVAILABLE,
134         "NtCreateNamedPipeFile should have failed with STATUS_INSTANCE_NOT_AVAILABLE got(%08x)\n", status);
135
136     h = CreateFileA("\\\\.\\pipe\\test\\pipe", GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
137                     OPEN_EXISTING, 0, 0 );
138     ok(h != INVALID_HANDLE_VALUE, "Failed to open NamedPipe (%u)\n", GetLastError());
139     pNtClose(h);
140
141     pRtlInitUnicodeString(&str, buffer3);
142     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
143     status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
144     ok(status == STATUS_OBJECT_PATH_NOT_FOUND ||
145        status == STATUS_PIPE_NOT_AVAILABLE ||
146        status == STATUS_OBJECT_NAME_INVALID, /* vista */
147         "NtOpenFile should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
148
149     pRtlInitUnicodeString(&str, buffer4);
150     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
151     status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
152     ok(status == STATUS_OBJECT_NAME_NOT_FOUND ||
153        status == STATUS_OBJECT_NAME_INVALID, /* vista */
154         "NtOpenFile should have failed with STATUS_OBJECT_NAME_NOT_FOUND got(%08x)\n", status);
155
156     pNtClose(pipe);
157 }
158
159 #define DIRECTORY_QUERY (0x0001)
160 #define SYMBOLIC_LINK_QUERY 0x0001
161
162 #define DIR_TEST_CREATE_FAILURE(h,e) \
163     status = pNtCreateDirectoryObject(h, DIRECTORY_QUERY, &attr);\
164     ok(status == e,"NtCreateDirectoryObject should have failed with %s got(%08x)\n", #e, status);
165 #define DIR_TEST_OPEN_FAILURE(h,e) \
166     status = pNtOpenDirectoryObject(h, DIRECTORY_QUERY, &attr);\
167     ok(status == e,"NtOpenDirectoryObject should have failed with %s got(%08x)\n", #e, status);
168 #define DIR_TEST_CREATE_OPEN_FAILURE(h,n,e) \
169     pRtlCreateUnicodeStringFromAsciiz(&str, n);\
170     DIR_TEST_CREATE_FAILURE(h,e) DIR_TEST_OPEN_FAILURE(h,e)\
171     pRtlFreeUnicodeString(&str);
172
173 #define DIR_TEST_CREATE_SUCCESS(h) \
174     status = pNtCreateDirectoryObject(h, DIRECTORY_QUERY, &attr); \
175     ok(status == STATUS_SUCCESS, "Failed to create Directory(%08x)\n", status);
176 #define DIR_TEST_OPEN_SUCCESS(h) \
177     status = pNtOpenDirectoryObject(h, DIRECTORY_QUERY, &attr); \
178     ok(status == STATUS_SUCCESS, "Failed to open Directory(%08x)\n", status);
179 #define DIR_TEST_CREATE_OPEN_SUCCESS(h,n) \
180     pRtlCreateUnicodeStringFromAsciiz(&str, n);\
181     DIR_TEST_CREATE_SUCCESS(&h) pNtClose(h); DIR_TEST_OPEN_SUCCESS(&h) pNtClose(h); \
182     pRtlFreeUnicodeString(&str);
183
184 static BOOL is_correct_dir( HANDLE dir, const char *name )
185 {
186     NTSTATUS status;
187     UNICODE_STRING str;
188     OBJECT_ATTRIBUTES attr;
189     HANDLE h = 0;
190
191     pRtlCreateUnicodeStringFromAsciiz(&str, name);
192     InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, dir, NULL);
193     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
194     pRtlFreeUnicodeString(&str);
195     if (h) pNtClose( h );
196     return (status == STATUS_OBJECT_NAME_EXISTS);
197 }
198
199 /* return a handle to the BaseNamedObjects dir where kernel32 objects get created */
200 static HANDLE get_base_dir(void)
201 {
202     static const char objname[] = "om.c_get_base_dir_obj";
203     NTSTATUS status;
204     UNICODE_STRING str;
205     OBJECT_ATTRIBUTES attr;
206     HANDLE dir, h;
207     unsigned int i;
208
209     h = CreateMutexA(NULL, FALSE, objname);
210     ok(h != 0, "CreateMutexA failed got ret=%p (%d)\n", h, GetLastError());
211     InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, 0, NULL);
212
213     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local");
214     status = pNtOpenDirectoryObject(&dir, DIRECTORY_QUERY, &attr);
215     pRtlFreeUnicodeString(&str);
216     if (!status && is_correct_dir( dir, objname )) goto done;
217     if (!status) pNtClose( dir );
218
219     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
220     status = pNtOpenDirectoryObject(&dir, DIRECTORY_QUERY, &attr);
221     pRtlFreeUnicodeString(&str);
222     if (!status && is_correct_dir( dir, objname )) goto done;
223     if (!status) pNtClose( dir );
224
225     for (i = 0; i < 20; i++)
226     {
227         char name[40];
228         sprintf( name, "\\BaseNamedObjects\\Session\\%u", i );
229         pRtlCreateUnicodeStringFromAsciiz(&str, name );
230         status = pNtOpenDirectoryObject(&dir, DIRECTORY_QUERY, &attr);
231         pRtlFreeUnicodeString(&str);
232         if (!status && is_correct_dir( dir, objname )) goto done;
233         if (!status) pNtClose( dir );
234     }
235     dir = 0;
236
237 done:
238     pNtClose( h );
239     return dir;
240 }
241
242 static void test_name_collisions(void)
243 {
244     NTSTATUS status;
245     UNICODE_STRING str;
246     OBJECT_ATTRIBUTES attr;
247     HANDLE dir, h, h1, h2;
248     DWORD winerr;
249     LARGE_INTEGER size;
250
251     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
252     pRtlCreateUnicodeStringFromAsciiz(&str, "\\");
253     DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_NAME_COLLISION)
254     InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, 0, NULL);
255
256     DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_NAME_EXISTS)
257     pNtClose(h);
258     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
259     ok(status == STATUS_OBJECT_TYPE_MISMATCH,
260         "NtCreateMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
261     pRtlFreeUnicodeString(&str);
262
263     pRtlCreateUnicodeStringFromAsciiz(&str, "\\??\\PIPE\\om.c-mutant");
264     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
265     ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_OBJECT_PATH_NOT_FOUND,
266         "NtCreateMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
267     pRtlFreeUnicodeString(&str);
268
269     if (!(dir = get_base_dir()))
270     {
271         win_skip( "couldn't find the BaseNamedObjects dir\n" );
272         return;
273     }
274     pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-test");
275     InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, dir, NULL);
276     h = CreateMutexA(NULL, FALSE, "om.c-test");
277     ok(h != 0, "CreateMutexA failed got ret=%p (%d)\n", h, GetLastError());
278     status = pNtCreateMutant(&h1, GENERIC_ALL, &attr, FALSE);
279     ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
280         "NtCreateMutant should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
281     h2 = CreateMutexA(NULL, FALSE, "om.c-test");
282     winerr = GetLastError();
283     ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
284         "CreateMutexA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
285     pNtClose(h);
286     pNtClose(h1);
287     pNtClose(h2);
288
289     h = CreateEventA(NULL, FALSE, FALSE, "om.c-test");
290     ok(h != 0, "CreateEventA failed got ret=%p (%d)\n", h, GetLastError());
291     status = pNtCreateEvent(&h1, GENERIC_ALL, &attr, FALSE, FALSE);
292     ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
293         "NtCreateEvent should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
294     h2 = CreateEventA(NULL, FALSE, FALSE, "om.c-test");
295     winerr = GetLastError();
296     ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
297         "CreateEventA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
298     pNtClose(h);
299     pNtClose(h1);
300     pNtClose(h2);
301
302     h = CreateSemaphoreA(NULL, 1, 2, "om.c-test");
303     ok(h != 0, "CreateSemaphoreA failed got ret=%p (%d)\n", h, GetLastError());
304     status = pNtCreateSemaphore(&h1, GENERIC_ALL, &attr, 1, 2);
305     ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
306         "NtCreateSemaphore should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
307     h2 = CreateSemaphoreA(NULL, 1, 2, "om.c-test");
308     winerr = GetLastError();
309     ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
310         "CreateSemaphoreA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
311     pNtClose(h);
312     pNtClose(h1);
313     pNtClose(h2);
314     
315     h = pCreateWaitableTimerA(NULL, TRUE, "om.c-test");
316     ok(h != 0, "CreateWaitableTimerA failed got ret=%p (%d)\n", h, GetLastError());
317     status = pNtCreateTimer(&h1, GENERIC_ALL, &attr, NotificationTimer);
318     ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
319         "NtCreateTimer should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
320     h2 = pCreateWaitableTimerA(NULL, TRUE, "om.c-test");
321     winerr = GetLastError();
322     ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
323         "CreateWaitableTimerA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
324     pNtClose(h);
325     pNtClose(h1);
326     pNtClose(h2);
327
328     h = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 256, "om.c-test");
329     ok(h != 0, "CreateFileMappingA failed got ret=%p (%d)\n", h, GetLastError());
330     size.u.LowPart = 256;
331     size.u.HighPart = 0;
332     status = pNtCreateSection(&h1, SECTION_MAP_WRITE, &attr, &size, PAGE_READWRITE, SEC_COMMIT, 0);
333     ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
334         "NtCreateSection should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
335     h2 = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 256, "om.c-test");
336     winerr = GetLastError();
337     ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
338         "CreateFileMappingA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
339     pNtClose(h);
340     pNtClose(h1);
341     pNtClose(h2);
342
343     pRtlFreeUnicodeString(&str);
344     pNtClose(dir);
345 }
346
347 static void test_directory(void)
348 {
349     NTSTATUS status;
350     UNICODE_STRING str;
351     OBJECT_ATTRIBUTES attr;
352     HANDLE dir, dir1, h;
353     BOOL is_nt4;
354
355     /* No name and/or no attributes */
356     status = pNtCreateDirectoryObject(NULL, DIRECTORY_QUERY, &attr);
357     ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER,
358         "NtCreateDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
359     status = pNtOpenDirectoryObject(NULL, DIRECTORY_QUERY, &attr);
360     ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER,
361         "NtOpenDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
362
363     status = pNtCreateDirectoryObject(&h, DIRECTORY_QUERY, NULL);
364     ok(status == STATUS_SUCCESS, "Failed to create Directory without attributes(%08x)\n", status);
365     pNtClose(h);
366     status = pNtOpenDirectoryObject(&h, DIRECTORY_QUERY, NULL);
367     ok(status == STATUS_INVALID_PARAMETER,
368         "NtOpenDirectoryObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
369
370     InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
371     DIR_TEST_CREATE_SUCCESS(&dir)
372     DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
373
374     /* Bad name */
375     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
376
377     pRtlCreateUnicodeStringFromAsciiz(&str, "");
378     DIR_TEST_CREATE_SUCCESS(&h)
379     pNtClose(h);
380     DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
381     pRtlFreeUnicodeString(&str);
382     pNtClose(dir);
383
384     DIR_TEST_CREATE_OPEN_FAILURE(&h, "BaseNamedObjects", STATUS_OBJECT_PATH_SYNTAX_BAD)
385     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\", STATUS_OBJECT_NAME_INVALID)
386     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\\\BaseNamedObjects", STATUS_OBJECT_NAME_INVALID)
387     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\\\om.c-test", STATUS_OBJECT_NAME_INVALID)
388     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\om.c-test\\", STATUS_OBJECT_PATH_NOT_FOUND)
389
390     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test");
391     DIR_TEST_CREATE_SUCCESS(&h)
392     DIR_TEST_OPEN_SUCCESS(&dir1)
393     pRtlFreeUnicodeString(&str);
394     pNtClose(h);
395     pNtClose(dir1);
396
397
398     /* Use of root directory */
399
400     /* Can't use symlinks as a directory */
401     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local");
402     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
403     status = pNtOpenSymbolicLinkObject(&dir, SYMBOLIC_LINK_QUERY, &attr);
404     is_nt4 = (status == STATUS_OBJECT_NAME_NOT_FOUND);  /* nt4 doesn't have Local\\ symlink */
405     if (!is_nt4)
406     {
407         WCHAR buffer[256];
408         ULONG len, full_len;
409
410         ok(status == STATUS_SUCCESS, "Failed to open SymbolicLink(%08x)\n", status);
411         pRtlFreeUnicodeString(&str);
412         InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
413         pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
414         DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_TYPE_MISMATCH)
415         pRtlFreeUnicodeString(&str);
416
417         str.Buffer = buffer;
418         str.MaximumLength = sizeof(buffer);
419         len = 0xdeadbeef;
420         memset( buffer, 0xaa, sizeof(buffer) );
421         status = pNtQuerySymbolicLinkObject( dir, &str, &len );
422         ok( status == STATUS_SUCCESS, "NtQuerySymbolicLinkObject failed %08x\n", status );
423         if (status != STATUS_SUCCESS)
424             goto error;
425         full_len = str.Length + sizeof(WCHAR);
426         ok( len == full_len, "bad length %u/%u\n", len, full_len );
427         if (len == full_len)
428             ok( buffer[len / sizeof(WCHAR) - 1] == 0, "no terminating null\n" );
429
430         str.MaximumLength = str.Length;
431         len = 0xdeadbeef;
432         status = pNtQuerySymbolicLinkObject( dir, &str, &len );
433         ok( status == STATUS_BUFFER_TOO_SMALL, "NtQuerySymbolicLinkObject failed %08x\n", status );
434         ok( len == full_len, "bad length %u/%u\n", len, full_len );
435
436         str.MaximumLength = 0;
437         len = 0xdeadbeef;
438         status = pNtQuerySymbolicLinkObject( dir, &str, &len );
439         ok( status == STATUS_BUFFER_TOO_SMALL, "NtQuerySymbolicLinkObject failed %08x\n", status );
440         ok( len == full_len, "bad length %u/%u\n", len, full_len );
441
442         str.MaximumLength = str.Length + sizeof(WCHAR);
443         len = 0xdeadbeef;
444         status = pNtQuerySymbolicLinkObject( dir, &str, &len );
445         ok( status == STATUS_SUCCESS, "NtQuerySymbolicLinkObject failed %08x\n", status );
446         ok( len == full_len, "bad length %u/%u\n", len, full_len );
447
448 error:
449         pNtClose(dir);
450     }
451
452     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
453     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
454     DIR_TEST_OPEN_SUCCESS(&dir)
455     pRtlFreeUnicodeString(&str);
456
457     InitializeObjectAttributes(&attr, NULL, 0, dir, NULL);
458     DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_NAME_INVALID)
459
460     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
461     DIR_TEST_CREATE_OPEN_SUCCESS(h, "")
462     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\", STATUS_OBJECT_PATH_SYNTAX_BAD)
463     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test", STATUS_OBJECT_PATH_SYNTAX_BAD)
464     DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test\\", STATUS_OBJECT_PATH_SYNTAX_BAD)
465     DIR_TEST_CREATE_OPEN_FAILURE(&h, "om.c-test\\", STATUS_OBJECT_PATH_NOT_FOUND)
466
467     pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-test");
468     DIR_TEST_CREATE_SUCCESS(&dir1)
469     DIR_TEST_OPEN_SUCCESS(&h)
470     pRtlFreeUnicodeString(&str);
471
472     pNtClose(h);
473     pNtClose(dir1);
474     pNtClose(dir);
475
476     /* Nested directories */
477     pRtlCreateUnicodeStringFromAsciiz(&str, "\\");
478     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
479     DIR_TEST_OPEN_SUCCESS(&dir)
480     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
481     DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
482     pRtlFreeUnicodeString(&str);
483     pNtClose(dir);
484
485     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
486     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test");
487     DIR_TEST_CREATE_SUCCESS(&dir)
488     pRtlFreeUnicodeString(&str);
489     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test\\one more level");
490     DIR_TEST_CREATE_SUCCESS(&h)
491     pRtlFreeUnicodeString(&str);
492     pNtClose(h);
493     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
494     pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
495     DIR_TEST_CREATE_SUCCESS(&h)
496     pRtlFreeUnicodeString(&str);
497     pNtClose(h);
498
499     pNtClose(dir);
500
501     if (!is_nt4)
502     {
503         InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
504         pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Global\\om.c-test");
505         DIR_TEST_CREATE_SUCCESS(&dir)
506         pRtlFreeUnicodeString(&str);
507         pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local\\om.c-test\\one more level");
508         DIR_TEST_CREATE_SUCCESS(&h)
509         pRtlFreeUnicodeString(&str);
510         pNtClose(h);
511         InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
512         pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
513         DIR_TEST_CREATE_SUCCESS(&dir)
514         pRtlFreeUnicodeString(&str);
515         pNtClose(h);
516         pNtClose(dir);
517     }
518
519     /* Create other objects using RootDirectory */
520
521     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
522     pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
523     DIR_TEST_OPEN_SUCCESS(&dir)
524     pRtlFreeUnicodeString(&str);
525     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
526
527     /* Test invalid paths */
528     pRtlCreateUnicodeStringFromAsciiz(&str, "\\om.c-mutant");
529     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
530     ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
531         "NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
532     pRtlFreeUnicodeString(&str);
533     pRtlCreateUnicodeStringFromAsciiz(&str, "\\om.c-mutant\\");
534     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
535     ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
536         "NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
537     pRtlFreeUnicodeString(&str);
538
539     pRtlCreateUnicodeStringFromAsciiz(&str, "om.c\\-mutant");
540     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
541     ok(status == STATUS_OBJECT_PATH_NOT_FOUND,
542         "NtCreateMutant should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
543     pRtlFreeUnicodeString(&str);
544
545     pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-mutant");
546     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
547     ok(status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status);
548     pRtlFreeUnicodeString(&str);
549     pNtClose(h);
550
551     pNtClose(dir);
552 }
553
554 #define SYMLNK_TEST_CREATE_OPEN_FAILURE2(h,n,t,e,e2) \
555     pRtlCreateUnicodeStringFromAsciiz(&str, n);\
556     pRtlCreateUnicodeStringFromAsciiz(&target, t);\
557     status = pNtCreateSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr, &target);\
558     ok(status == e || status == e2, \
559        "NtCreateSymbolicLinkObject should have failed with %s or %s got(%08x)\n", #e, #e2, status);\
560     status = pNtOpenSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr);\
561     ok(status == e || status == e2, \
562        "NtOpenSymbolicLinkObject should have failed with %s or %s got(%08x)\n", #e, #e2, status);\
563     pRtlFreeUnicodeString(&target);\
564     pRtlFreeUnicodeString(&str);
565
566 #define SYMLNK_TEST_CREATE_OPEN_FAILURE(h,n,t,e) SYMLNK_TEST_CREATE_OPEN_FAILURE2(h,n,t,e,e)
567
568 static void test_symboliclink(void)
569 {
570     NTSTATUS status;
571     UNICODE_STRING str, target;
572     OBJECT_ATTRIBUTES attr;
573     HANDLE dir, link, h;
574     IO_STATUS_BLOCK iosb;
575
576     /* No name and/or no attributes */
577     InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
578     SYMLNK_TEST_CREATE_OPEN_FAILURE2(NULL, "", "", STATUS_ACCESS_VIOLATION, STATUS_INVALID_PARAMETER)
579
580     status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL, NULL);
581     ok(status == STATUS_ACCESS_VIOLATION,
582         "NtCreateSymbolicLinkObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
583     status = pNtOpenSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL);
584     ok(status == STATUS_INVALID_PARAMETER,
585         "NtOpenSymbolicLinkObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
586
587     /* No attributes */
588     pRtlCreateUnicodeStringFromAsciiz(&target, "\\DosDevices");
589     status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL, &target);
590     ok(status == STATUS_SUCCESS || status == STATUS_ACCESS_VIOLATION, /* nt4 */
591        "NtCreateSymbolicLinkObject failed(%08x)\n", status);
592     pRtlFreeUnicodeString(&target);
593     if (!status) pNtClose(h);
594
595     InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
596     status = pNtCreateSymbolicLinkObject(&link, SYMBOLIC_LINK_QUERY, &attr, &target);
597     ok(status == STATUS_INVALID_PARAMETER ||
598        broken(status == STATUS_SUCCESS),  /* nt4 */
599        "NtCreateSymbolicLinkObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
600     if (!status) pNtClose(h);
601     status = pNtOpenSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, &attr);
602     ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
603        "NtOpenSymbolicLinkObject should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
604
605     /* Bad name */
606     pRtlCreateUnicodeStringFromAsciiz(&target, "anywhere");
607     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
608
609     pRtlCreateUnicodeStringFromAsciiz(&str, "");
610     status = pNtCreateSymbolicLinkObject(&link, SYMBOLIC_LINK_QUERY, &attr, &target);
611     ok(status == STATUS_SUCCESS, "Failed to create SymbolicLink(%08x)\n", status);
612     status = pNtOpenSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, &attr);
613     ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
614        "NtOpenSymbolicLinkObject should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
615     pNtClose(link);
616     pRtlFreeUnicodeString(&str);
617
618     pRtlCreateUnicodeStringFromAsciiz(&str, "\\");
619     status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, &attr, &target);
620     todo_wine ok(status == STATUS_OBJECT_TYPE_MISMATCH,
621                  "NtCreateSymbolicLinkObject should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
622     pRtlFreeUnicodeString(&str);
623     pRtlFreeUnicodeString(&target);
624
625     SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "BaseNamedObjects", "->Somewhere", STATUS_OBJECT_PATH_SYNTAX_BAD)
626     SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
627     SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\\\BaseNamedObjects", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
628     SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\\\om.c-test", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
629     SYMLNK_TEST_CREATE_OPEN_FAILURE2(&h, "\\BaseNamedObjects\\om.c-test\\", "->Somewhere",
630                                      STATUS_OBJECT_NAME_INVALID, STATUS_OBJECT_PATH_NOT_FOUND)
631
632
633     /* Compound test */
634     if (!(dir = get_base_dir()))
635     {
636         win_skip( "couldn't find the BaseNamedObjects dir\n" );
637         return;
638     }
639
640     InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
641     pRtlCreateUnicodeStringFromAsciiz(&str, "test-link");
642     pRtlCreateUnicodeStringFromAsciiz(&target, "\\DosDevices");
643     status = pNtCreateSymbolicLinkObject(&link, SYMBOLIC_LINK_QUERY, &attr, &target);
644     ok(status == STATUS_SUCCESS, "Failed to create SymbolicLink(%08x)\n", status);
645     pRtlFreeUnicodeString(&str);
646     pRtlFreeUnicodeString(&target);
647
648     pRtlCreateUnicodeStringFromAsciiz(&str, "test-link\\NUL");
649     status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
650     todo_wine ok(status == STATUS_SUCCESS, "Failed to open NUL device(%08x)\n", status);
651     pRtlFreeUnicodeString(&str);
652
653     pNtClose(h);
654     pNtClose(link);
655     pNtClose(dir);
656 }
657
658 static void test_query_object(void)
659 {
660     static const WCHAR name[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s',
661                                  '\\','t','e','s','t','_','e','v','e','n','t'};
662     static const WCHAR type_event[] = {'E','v','e','n','t'};
663     static const WCHAR type_file[] = {'F','i','l','e'};
664     HANDLE handle;
665     char buffer[1024];
666     NTSTATUS status;
667     ULONG len, expected_len;
668     UNICODE_STRING *str;
669     char dir[MAX_PATH];
670
671     handle = CreateEventA( NULL, FALSE, FALSE, "test_event" );
672
673     len = 0;
674     status = pNtQueryObject( handle, ObjectNameInformation, buffer, 0, &len );
675     ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
676     ok( len >= sizeof(UNICODE_STRING) + sizeof(name) + sizeof(WCHAR), "unexpected len %u\n", len );
677
678     len = 0;
679     status = pNtQueryObject( handle, ObjectTypeInformation, buffer, 0, &len );
680     todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
681     todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + sizeof(type_event) + sizeof(WCHAR), "unexpected len %u\n", len );
682
683     len = 0;
684     status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(UNICODE_STRING), &len );
685     ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
686     ok( len >= sizeof(UNICODE_STRING) + sizeof(name) + sizeof(WCHAR), "unexpected len %u\n", len );
687
688     len = 0;
689     status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(OBJECT_TYPE_INFORMATION), &len );
690     todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
691     todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + sizeof(type_event) + sizeof(WCHAR), "unexpected len %u\n", len );
692
693     len = 0;
694     status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len );
695     ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
696     ok( len > sizeof(UNICODE_STRING), "unexpected len %u\n", len );
697     str = (UNICODE_STRING *)buffer;
698     ok( sizeof(UNICODE_STRING) + str->Length + sizeof(WCHAR) == len, "unexpected len %u\n", len );
699     ok( str->Length >= sizeof(name), "unexpected len %u\n", str->Length );
700     /* there can be a \\Sessions prefix in the name */
701     ok( !memcmp( str->Buffer + (str->Length - sizeof(name)) / sizeof(WCHAR), name, sizeof(name) ),
702         "wrong name %s\n", wine_dbgstr_w(str->Buffer) );
703
704     len -= sizeof(WCHAR);
705     status = pNtQueryObject( handle, ObjectNameInformation, buffer, len, &len );
706     ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
707     ok( len >= sizeof(UNICODE_STRING) + sizeof(name) + sizeof(WCHAR), "unexpected len %u\n", len );
708
709     len = 0;
710     memset( buffer, 0, sizeof(buffer) );
711     status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
712     todo_wine ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
713     todo_wine ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
714     str = (UNICODE_STRING *)buffer;
715     todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR), "unexpected len %u\n", len );
716     todo_wine ok( str->Buffer && !memcmp( str->Buffer, type_event, sizeof(type_file) ),
717                   "wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
718
719     len -= sizeof(WCHAR);
720     status = pNtQueryObject( handle, ObjectTypeInformation, buffer, len, &len );
721     todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
722     todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + sizeof(type_event) + sizeof(WCHAR), "unexpected len %u\n", len );
723
724     pNtClose( handle );
725
726     handle = CreateEventA( NULL, FALSE, FALSE, NULL );
727     len = 0;
728     status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len );
729     ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
730     ok( len == sizeof(UNICODE_STRING), "unexpected len %u\n", len );
731     str = (UNICODE_STRING *)buffer;
732     ok( str->Length == 0, "unexpected len %u\n", len );
733     ok( str->Buffer == NULL, "unexpected ptr %p\n", str->Buffer );
734     pNtClose( handle );
735
736     GetWindowsDirectoryA( dir, MAX_PATH );
737     handle = CreateFileA( dir, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
738                           FILE_FLAG_BACKUP_SEMANTICS, 0 );
739     len = 0;
740     status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len );
741     ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
742     ok( len > sizeof(UNICODE_STRING), "unexpected len %u\n", len );
743     str = (UNICODE_STRING *)buffer;
744     expected_len = sizeof(UNICODE_STRING) + str->Length + sizeof(WCHAR);
745     ok( len == expected_len || broken(len == expected_len - sizeof(WCHAR)), /* NT4 */
746         "unexpected len %u\n", len );
747     trace( "got %s len %u\n", wine_dbgstr_w(str->Buffer), len );
748
749     len = 0;
750     status = pNtQueryObject( handle, ObjectNameInformation, buffer, 0, &len );
751     ok( status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INSUFFICIENT_RESOURCES),
752         "NtQueryObject failed %x\n", status );
753     ok( len == expected_len || broken(!len || len == sizeof(UNICODE_STRING)),
754         "unexpected len %u\n", len );
755
756     len = 0;
757     status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(UNICODE_STRING), &len );
758     ok( status == STATUS_BUFFER_OVERFLOW || broken(status == STATUS_INSUFFICIENT_RESOURCES
759             || status == STATUS_INFO_LENGTH_MISMATCH),
760         "NtQueryObject failed %x\n", status );
761     ok( len == expected_len || broken(!len),
762         "unexpected len %u\n", len );
763
764     len = 0;
765     memset( buffer, 0, sizeof(buffer) );
766     status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
767     todo_wine ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
768     todo_wine ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
769     str = (UNICODE_STRING *)buffer;
770     expected_len = sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR);
771     todo_wine ok( len >= expected_len, "unexpected len %u\n", len );
772     todo_wine ok( str->Buffer && !memcmp( str->Buffer, type_file, sizeof(type_file) ),
773                   "wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
774
775     pNtClose( handle );
776 }
777
778 static void test_type_mismatch(void)
779 {
780     HANDLE h;
781     NTSTATUS res;
782     OBJECT_ATTRIBUTES attr;
783
784     attr.Length                   = sizeof(attr);
785     attr.RootDirectory            = 0;
786     attr.ObjectName               = NULL;
787     attr.Attributes               = 0;
788     attr.SecurityDescriptor       = NULL;
789     attr.SecurityQualityOfService = NULL;
790
791     res = pNtCreateEvent( &h, 0, &attr, 0, 0 );
792     ok(!res, "can't create event: %x\n", res);
793
794     res = pNtReleaseSemaphore( h, 30, NULL );
795     ok(res == STATUS_OBJECT_TYPE_MISMATCH, "expected 0xc0000024, got %x\n", res);
796
797     pNtClose( h );
798 }
799
800 START_TEST(om)
801 {
802     HMODULE hntdll = GetModuleHandleA("ntdll.dll");
803     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
804
805     if (!hntdll)
806     {
807         skip("not running on NT, skipping test\n");
808         return;
809     }
810
811     pCreateWaitableTimerA = (void *)GetProcAddress(hkernel32, "CreateWaitableTimerA");
812
813     pRtlCreateUnicodeStringFromAsciiz = (void *)GetProcAddress(hntdll, "RtlCreateUnicodeStringFromAsciiz");
814     pRtlFreeUnicodeString   = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
815     pNtCreateEvent          = (void *)GetProcAddress(hntdll, "NtCreateEvent");
816     pNtCreateMutant         = (void *)GetProcAddress(hntdll, "NtCreateMutant");
817     pNtOpenMutant           = (void *)GetProcAddress(hntdll, "NtOpenMutant");
818     pNtOpenFile             = (void *)GetProcAddress(hntdll, "NtOpenFile");
819     pNtClose                = (void *)GetProcAddress(hntdll, "NtClose");
820     pRtlInitUnicodeString   = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
821     pNtCreateNamedPipeFile  = (void *)GetProcAddress(hntdll, "NtCreateNamedPipeFile");
822     pNtOpenDirectoryObject  = (void *)GetProcAddress(hntdll, "NtOpenDirectoryObject");
823     pNtCreateDirectoryObject= (void *)GetProcAddress(hntdll, "NtCreateDirectoryObject");
824     pNtOpenSymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtOpenSymbolicLinkObject");
825     pNtCreateSymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtCreateSymbolicLinkObject");
826     pNtQuerySymbolicLinkObject  = (void *)GetProcAddress(hntdll, "NtQuerySymbolicLinkObject");
827     pNtCreateSemaphore      =  (void *)GetProcAddress(hntdll, "NtCreateSemaphore");
828     pNtCreateTimer          =  (void *)GetProcAddress(hntdll, "NtCreateTimer");
829     pNtCreateSection        =  (void *)GetProcAddress(hntdll, "NtCreateSection");
830     pNtQueryObject          =  (void *)GetProcAddress(hntdll, "NtQueryObject");
831     pNtReleaseSemaphore     =  (void *)GetProcAddress(hntdll, "NtReleaseSemaphore");
832
833     test_case_sensitive();
834     test_namespace_pipe();
835     test_name_collisions();
836     test_directory();
837     test_symboliclink();
838     test_query_object();
839     test_type_mismatch();
840 }