Merge the following revisions from kernel-fun branch:
[reactos.git] / rostests / winetests / ntdll / om.c
1 /*
2 * Unit test suite for object manager functions
3 *
4 * Copyright 2005 Robert Shearman
5 * Copyright 2005 Vitaliy Margolen
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "ntdll_test.h"
23 #include "wine/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 BOOLEAN (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 *pNtOpenEvent) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES);
34 static NTSTATUS (WINAPI *pNtPulseEvent) ( HANDLE, PULONG );
35 static NTSTATUS (WINAPI *pNtQueryEvent) ( HANDLE, EVENT_INFORMATION_CLASS, PVOID, ULONG, PULONG );
36 static NTSTATUS (WINAPI *pNtCreateMutant)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, BOOLEAN );
37 static NTSTATUS (WINAPI *pNtOpenMutant) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES );
38 static NTSTATUS (WINAPI *pNtCreateSemaphore)( PHANDLE, ACCESS_MASK,const POBJECT_ATTRIBUTES,LONG,LONG );
39 static NTSTATUS (WINAPI *pNtCreateTimer) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, TIMER_TYPE );
40 static NTSTATUS (WINAPI *pNtCreateSection)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, const PLARGE_INTEGER,
41 ULONG, ULONG, HANDLE );
42 static NTSTATUS (WINAPI *pNtOpenFile) ( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, ULONG, ULONG );
43 static NTSTATUS (WINAPI *pNtClose) ( HANDLE );
44 static NTSTATUS (WINAPI *pNtCreateNamedPipeFile)( PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
45 ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, PLARGE_INTEGER );
46 static NTSTATUS (WINAPI *pNtOpenDirectoryObject)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
47 static NTSTATUS (WINAPI *pNtCreateDirectoryObject)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
48 static NTSTATUS (WINAPI *pNtOpenSymbolicLinkObject)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
49 static NTSTATUS (WINAPI *pNtCreateSymbolicLinkObject)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PUNICODE_STRING);
50 static NTSTATUS (WINAPI *pNtQuerySymbolicLinkObject)(HANDLE,PUNICODE_STRING,PULONG);
51 static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,ULONG,PULONG);
52 static NTSTATUS (WINAPI *pNtReleaseSemaphore)(HANDLE, ULONG, PULONG);
53 static NTSTATUS (WINAPI *pNtCreateKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG );
54 static NTSTATUS (WINAPI *pNtOpenKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * );
55 static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
56 static NTSTATUS (WINAPI *pNtReleaseKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
57
58 #define KEYEDEVENT_WAIT 0x0001
59 #define KEYEDEVENT_WAKE 0x0002
60 #define KEYEDEVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x0003)
61
62 static void test_case_sensitive (void)
63 {
64 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};
65 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};
66 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};
67 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};
68 NTSTATUS status;
69 OBJECT_ATTRIBUTES attr;
70 UNICODE_STRING str;
71 HANDLE Event, Mutant, h;
72
73 pRtlInitUnicodeString(&str, buffer1);
74 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
75 status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
76 ok(status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status);
77
78 status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, FALSE, FALSE);
79 ok(status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH,
80 "NtCreateEvent should have failed with STATUS_OBJECT_NAME_COLLISION or STATUS_OBJECT_TYPE_MISMATCH got (%08x)\n", status);
81
82 pRtlInitUnicodeString(&str, buffer2);
83 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
84 status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, FALSE, FALSE);
85 ok(status == STATUS_SUCCESS, "Failed to create Event(%08x)\n", status);
86
87 pRtlInitUnicodeString(&str, buffer3);
88 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
89 status = pNtOpenMutant(&h, GENERIC_ALL, &attr);
90 ok(status == STATUS_OBJECT_TYPE_MISMATCH,
91 "NtOpenMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
92
93 pNtClose(Mutant);
94
95 pRtlInitUnicodeString(&str, buffer4);
96 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
97 status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
98 ok(status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH,
99 "NtCreateMutant should have failed with STATUS_OBJECT_NAME_COLLISION or STATUS_OBJECT_TYPE_MISMATCH got (%08x)\n", status);
100
101 status = pNtCreateEvent(&h, GENERIC_ALL, &attr, FALSE, FALSE);
102 ok(status == STATUS_OBJECT_NAME_COLLISION,
103 "NtCreateEvent should have failed with STATUS_OBJECT_NAME_COLLISION got(%08x)\n", status);
104
105 attr.Attributes = 0;
106 status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
107 ok(status == STATUS_OBJECT_PATH_NOT_FOUND,
108 "NtCreateMutant should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
109
110 pNtClose(Event);
111 }
112
113 static void test_namespace_pipe(void)
114 {
115 static const WCHAR buffer1[] = {'\\','?','?','\\','P','I','P','E','\\','t','e','s','t','\\','p','i','p','e',0};
116 static const WCHAR buffer2[] = {'\\','?','?','\\','P','I','P','E','\\','T','E','S','T','\\','P','I','P','E',0};
117 static const WCHAR buffer3[] = {'\\','?','?','\\','p','i','p','e','\\','t','e','s','t','\\','p','i','p','e',0};
118 static const WCHAR buffer4[] = {'\\','?','?','\\','p','i','p','e','\\','t','e','s','t',0};
119 OBJECT_ATTRIBUTES attr;
120 UNICODE_STRING str;
121 IO_STATUS_BLOCK iosb;
122 NTSTATUS status;
123 LARGE_INTEGER timeout;
124 HANDLE pipe, h;
125
126 timeout.QuadPart = -10000;
127
128 pRtlInitUnicodeString(&str, buffer1);
129 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
130 status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
131 FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
132 ok(status == STATUS_SUCCESS, "Failed to create NamedPipe(%08x)\n", status);
133
134 status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
135 FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
136 ok(status == STATUS_INSTANCE_NOT_AVAILABLE,
137 "NtCreateNamedPipeFile should have failed with STATUS_INSTANCE_NOT_AVAILABLE got(%08x)\n", status);
138
139 pRtlInitUnicodeString(&str, buffer2);
140 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
141 status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
142 FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
143 ok(status == STATUS_INSTANCE_NOT_AVAILABLE,
144 "NtCreateNamedPipeFile should have failed with STATUS_INSTANCE_NOT_AVAILABLE got(%08x)\n", status);
145
146 h = CreateFileA("\\\\.\\pipe\\test\\pipe", GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
147 OPEN_EXISTING, 0, 0 );
148 ok(h != INVALID_HANDLE_VALUE, "Failed to open NamedPipe (%u)\n", GetLastError());
149 pNtClose(h);
150
151 pRtlInitUnicodeString(&str, buffer3);
152 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
153 status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
154 ok(status == STATUS_OBJECT_PATH_NOT_FOUND ||
155 status == STATUS_PIPE_NOT_AVAILABLE ||
156 status == STATUS_OBJECT_NAME_INVALID || /* vista */
157 status == STATUS_OBJECT_NAME_NOT_FOUND, /* win8 */
158 "NtOpenFile should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
159
160 pRtlInitUnicodeString(&str, buffer4);
161 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
162 status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
163 ok(status == STATUS_OBJECT_NAME_NOT_FOUND ||
164 status == STATUS_OBJECT_NAME_INVALID, /* vista */
165 "NtOpenFile should have failed with STATUS_OBJECT_NAME_NOT_FOUND got(%08x)\n", status);
166
167 pNtClose(pipe);
168 }
169
170 #define DIRECTORY_QUERY (0x0001)
171 #define SYMBOLIC_LINK_QUERY 0x0001
172
173 #define DIR_TEST_CREATE_FAILURE(h,e) \
174 status = pNtCreateDirectoryObject(h, DIRECTORY_QUERY, &attr);\
175 ok(status == e,"NtCreateDirectoryObject should have failed with %s got(%08x)\n", #e, status);
176 #define DIR_TEST_OPEN_FAILURE(h,e) \
177 status = pNtOpenDirectoryObject(h, DIRECTORY_QUERY, &attr);\
178 ok(status == e,"NtOpenDirectoryObject should have failed with %s got(%08x)\n", #e, status);
179 #define DIR_TEST_CREATE_OPEN_FAILURE(h,n,e) \
180 pRtlCreateUnicodeStringFromAsciiz(&str, n);\
181 DIR_TEST_CREATE_FAILURE(h,e) DIR_TEST_OPEN_FAILURE(h,e)\
182 pRtlFreeUnicodeString(&str);
183
184 #define DIR_TEST_CREATE_SUCCESS(h) \
185 status = pNtCreateDirectoryObject(h, DIRECTORY_QUERY, &attr); \
186 ok(status == STATUS_SUCCESS, "Failed to create Directory(%08x)\n", status);
187 #define DIR_TEST_OPEN_SUCCESS(h) \
188 status = pNtOpenDirectoryObject(h, DIRECTORY_QUERY, &attr); \
189 ok(status == STATUS_SUCCESS, "Failed to open Directory(%08x)\n", status);
190 #define DIR_TEST_CREATE_OPEN_SUCCESS(h,n) \
191 pRtlCreateUnicodeStringFromAsciiz(&str, n);\
192 DIR_TEST_CREATE_SUCCESS(&h) pNtClose(h); DIR_TEST_OPEN_SUCCESS(&h) pNtClose(h); \
193 pRtlFreeUnicodeString(&str);
194
195 static BOOL is_correct_dir( HANDLE dir, const char *name )
196 {
197 NTSTATUS status;
198 UNICODE_STRING str;
199 OBJECT_ATTRIBUTES attr;
200 HANDLE h = 0;
201
202 pRtlCreateUnicodeStringFromAsciiz(&str, name);
203 InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, dir, NULL);
204 status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
205 pRtlFreeUnicodeString(&str);
206 if (h) pNtClose( h );
207 return (status == STATUS_OBJECT_NAME_EXISTS);
208 }
209
210 /* return a handle to the BaseNamedObjects dir where kernel32 objects get created */
211 static HANDLE get_base_dir(void)
212 {
213 static const char objname[] = "om.c_get_base_dir_obj";
214 NTSTATUS status;
215 UNICODE_STRING str;
216 OBJECT_ATTRIBUTES attr;
217 HANDLE dir, h;
218 unsigned int i;
219
220 h = CreateMutexA(NULL, FALSE, objname);
221 ok(h != 0, "CreateMutexA failed got ret=%p (%d)\n", h, GetLastError());
222 InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, 0, NULL);
223
224 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local");
225 status = pNtOpenDirectoryObject(&dir, DIRECTORY_QUERY, &attr);
226 pRtlFreeUnicodeString(&str);
227 if (!status && is_correct_dir( dir, objname )) goto done;
228 if (!status) pNtClose( dir );
229
230 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
231 status = pNtOpenDirectoryObject(&dir, DIRECTORY_QUERY, &attr);
232 pRtlFreeUnicodeString(&str);
233 if (!status && is_correct_dir( dir, objname )) goto done;
234 if (!status) pNtClose( dir );
235
236 for (i = 0; i < 20; i++)
237 {
238 char name[40];
239 sprintf( name, "\\BaseNamedObjects\\Session\\%u", i );
240 pRtlCreateUnicodeStringFromAsciiz(&str, name );
241 status = pNtOpenDirectoryObject(&dir, DIRECTORY_QUERY, &attr);
242 pRtlFreeUnicodeString(&str);
243 if (!status && is_correct_dir( dir, objname )) goto done;
244 if (!status) pNtClose( dir );
245 }
246 dir = 0;
247
248 done:
249 pNtClose( h );
250 return dir;
251 }
252
253 static void test_name_collisions(void)
254 {
255 NTSTATUS status;
256 UNICODE_STRING str;
257 OBJECT_ATTRIBUTES attr;
258 HANDLE dir, h, h1, h2;
259 DWORD winerr;
260 LARGE_INTEGER size;
261
262 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
263 pRtlCreateUnicodeStringFromAsciiz(&str, "\\");
264 DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_NAME_COLLISION)
265 InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, 0, NULL);
266
267 DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_NAME_EXISTS)
268 pNtClose(h);
269 status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
270 ok(status == STATUS_OBJECT_TYPE_MISMATCH,
271 "NtCreateMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
272 pRtlFreeUnicodeString(&str);
273
274 pRtlCreateUnicodeStringFromAsciiz(&str, "\\??\\PIPE\\om.c-mutant");
275 status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
276 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_OBJECT_PATH_NOT_FOUND,
277 "NtCreateMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
278 pRtlFreeUnicodeString(&str);
279
280 if (!(dir = get_base_dir()))
281 {
282 win_skip( "couldn't find the BaseNamedObjects dir\n" );
283 return;
284 }
285 pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-test");
286 InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, dir, NULL);
287 h = CreateMutexA(NULL, FALSE, "om.c-test");
288 ok(h != 0, "CreateMutexA failed got ret=%p (%d)\n", h, GetLastError());
289 status = pNtCreateMutant(&h1, GENERIC_ALL, &attr, FALSE);
290 ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
291 "NtCreateMutant should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
292 h2 = CreateMutexA(NULL, FALSE, "om.c-test");
293 winerr = GetLastError();
294 ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
295 "CreateMutexA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
296 pNtClose(h);
297 pNtClose(h1);
298 pNtClose(h2);
299
300 h = CreateEventA(NULL, FALSE, FALSE, "om.c-test");
301 ok(h != 0, "CreateEventA failed got ret=%p (%d)\n", h, GetLastError());
302 status = pNtCreateEvent(&h1, GENERIC_ALL, &attr, FALSE, FALSE);
303 ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
304 "NtCreateEvent should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
305 h2 = CreateEventA(NULL, FALSE, FALSE, "om.c-test");
306 winerr = GetLastError();
307 ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
308 "CreateEventA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
309 pNtClose(h);
310 pNtClose(h1);
311 pNtClose(h2);
312
313 h = CreateSemaphoreA(NULL, 1, 2, "om.c-test");
314 ok(h != 0, "CreateSemaphoreA failed got ret=%p (%d)\n", h, GetLastError());
315 status = pNtCreateSemaphore(&h1, GENERIC_ALL, &attr, 1, 2);
316 ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
317 "NtCreateSemaphore should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
318 h2 = CreateSemaphoreA(NULL, 1, 2, "om.c-test");
319 winerr = GetLastError();
320 ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
321 "CreateSemaphoreA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
322 pNtClose(h);
323 pNtClose(h1);
324 pNtClose(h2);
325
326 h = pCreateWaitableTimerA(NULL, TRUE, "om.c-test");
327 ok(h != 0, "CreateWaitableTimerA failed got ret=%p (%d)\n", h, GetLastError());
328 status = pNtCreateTimer(&h1, GENERIC_ALL, &attr, NotificationTimer);
329 ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
330 "NtCreateTimer should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
331 h2 = pCreateWaitableTimerA(NULL, TRUE, "om.c-test");
332 winerr = GetLastError();
333 ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
334 "CreateWaitableTimerA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
335 pNtClose(h);
336 pNtClose(h1);
337 pNtClose(h2);
338
339 h = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 256, "om.c-test");
340 ok(h != 0, "CreateFileMappingA failed got ret=%p (%d)\n", h, GetLastError());
341 size.u.LowPart = 256;
342 size.u.HighPart = 0;
343 status = pNtCreateSection(&h1, SECTION_MAP_WRITE, &attr, &size, PAGE_READWRITE, SEC_COMMIT, 0);
344 ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
345 "NtCreateSection should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
346 h2 = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 256, "om.c-test");
347 winerr = GetLastError();
348 ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
349 "CreateFileMappingA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
350 pNtClose(h);
351 pNtClose(h1);
352 pNtClose(h2);
353
354 pRtlFreeUnicodeString(&str);
355 pNtClose(dir);
356 }
357
358 static void test_directory(void)
359 {
360 NTSTATUS status;
361 UNICODE_STRING str;
362 OBJECT_ATTRIBUTES attr;
363 HANDLE dir, dir1, h;
364 BOOL is_nt4;
365
366 /* No name and/or no attributes */
367 status = pNtCreateDirectoryObject(NULL, DIRECTORY_QUERY, &attr);
368 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER,
369 "NtCreateDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
370 status = pNtOpenDirectoryObject(NULL, DIRECTORY_QUERY, &attr);
371 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER,
372 "NtOpenDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
373
374 status = pNtCreateDirectoryObject(&h, DIRECTORY_QUERY, NULL);
375 ok(status == STATUS_SUCCESS, "Failed to create Directory without attributes(%08x)\n", status);
376 pNtClose(h);
377 status = pNtOpenDirectoryObject(&h, DIRECTORY_QUERY, NULL);
378 ok(status == STATUS_INVALID_PARAMETER,
379 "NtOpenDirectoryObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
380
381 InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
382 DIR_TEST_CREATE_SUCCESS(&dir)
383 DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
384
385 /* Bad name */
386 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
387
388 pRtlCreateUnicodeStringFromAsciiz(&str, "");
389 DIR_TEST_CREATE_SUCCESS(&h)
390 pNtClose(h);
391 DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
392 pRtlFreeUnicodeString(&str);
393 pNtClose(dir);
394
395 DIR_TEST_CREATE_OPEN_FAILURE(&h, "BaseNamedObjects", STATUS_OBJECT_PATH_SYNTAX_BAD)
396 DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\", STATUS_OBJECT_NAME_INVALID)
397 DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\\\BaseNamedObjects", STATUS_OBJECT_NAME_INVALID)
398 DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\\\om.c-test", STATUS_OBJECT_NAME_INVALID)
399 DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\om.c-test\\", STATUS_OBJECT_PATH_NOT_FOUND)
400
401 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test");
402 DIR_TEST_CREATE_SUCCESS(&h)
403 DIR_TEST_OPEN_SUCCESS(&dir1)
404 pRtlFreeUnicodeString(&str);
405 pNtClose(h);
406 pNtClose(dir1);
407
408
409 /* Use of root directory */
410
411 /* Can't use symlinks as a directory */
412 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local");
413 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
414 status = pNtOpenSymbolicLinkObject(&dir, SYMBOLIC_LINK_QUERY, &attr);
415 is_nt4 = (status == STATUS_OBJECT_NAME_NOT_FOUND); /* nt4 doesn't have Local\\ symlink */
416 if (!is_nt4)
417 {
418 WCHAR buffer[256];
419 ULONG len, full_len;
420
421 ok(status == STATUS_SUCCESS, "Failed to open SymbolicLink(%08x)\n", status);
422 pRtlFreeUnicodeString(&str);
423 InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
424 pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
425 DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_TYPE_MISMATCH)
426 pRtlFreeUnicodeString(&str);
427
428 str.Buffer = buffer;
429 str.MaximumLength = sizeof(buffer);
430 len = 0xdeadbeef;
431 memset( buffer, 0xaa, sizeof(buffer) );
432 status = pNtQuerySymbolicLinkObject( dir, &str, &len );
433 ok( status == STATUS_SUCCESS, "NtQuerySymbolicLinkObject failed %08x\n", status );
434 if (status != STATUS_SUCCESS)
435 goto error;
436 full_len = str.Length + sizeof(WCHAR);
437 ok( len == full_len, "bad length %u/%u\n", len, full_len );
438 if (len == full_len)
439 ok( buffer[len / sizeof(WCHAR) - 1] == 0, "no terminating null\n" );
440
441 str.MaximumLength = str.Length;
442 len = 0xdeadbeef;
443 status = pNtQuerySymbolicLinkObject( dir, &str, &len );
444 ok( status == STATUS_BUFFER_TOO_SMALL, "NtQuerySymbolicLinkObject failed %08x\n", status );
445 ok( len == full_len, "bad length %u/%u\n", len, full_len );
446
447 str.MaximumLength = 0;
448 len = 0xdeadbeef;
449 status = pNtQuerySymbolicLinkObject( dir, &str, &len );
450 ok( status == STATUS_BUFFER_TOO_SMALL, "NtQuerySymbolicLinkObject failed %08x\n", status );
451 ok( len == full_len, "bad length %u/%u\n", len, full_len );
452
453 str.MaximumLength = str.Length + sizeof(WCHAR);
454 len = 0xdeadbeef;
455 status = pNtQuerySymbolicLinkObject( dir, &str, &len );
456 ok( status == STATUS_SUCCESS, "NtQuerySymbolicLinkObject failed %08x\n", status );
457 ok( len == full_len, "bad length %u/%u\n", len, full_len );
458
459 error:
460 pNtClose(dir);
461 }
462
463 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
464 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
465 DIR_TEST_OPEN_SUCCESS(&dir)
466 pRtlFreeUnicodeString(&str);
467
468 InitializeObjectAttributes(&attr, NULL, 0, dir, NULL);
469 DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_NAME_INVALID)
470
471 InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
472 DIR_TEST_CREATE_OPEN_SUCCESS(h, "")
473 DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\", STATUS_OBJECT_PATH_SYNTAX_BAD)
474 DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test", STATUS_OBJECT_PATH_SYNTAX_BAD)
475 DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test\\", STATUS_OBJECT_PATH_SYNTAX_BAD)
476 DIR_TEST_CREATE_OPEN_FAILURE(&h, "om.c-test\\", STATUS_OBJECT_PATH_NOT_FOUND)
477
478 pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-test");
479 DIR_TEST_CREATE_SUCCESS(&dir1)
480 DIR_TEST_OPEN_SUCCESS(&h)
481 pRtlFreeUnicodeString(&str);
482
483 pNtClose(h);
484 pNtClose(dir1);
485 pNtClose(dir);
486
487 /* Nested directories */
488 pRtlCreateUnicodeStringFromAsciiz(&str, "\\");
489 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
490 DIR_TEST_OPEN_SUCCESS(&dir)
491 InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
492 DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
493 pRtlFreeUnicodeString(&str);
494 pNtClose(dir);
495
496 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
497 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test");
498 DIR_TEST_CREATE_SUCCESS(&dir)
499 pRtlFreeUnicodeString(&str);
500 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test\\one more level");
501 DIR_TEST_CREATE_SUCCESS(&h)
502 pRtlFreeUnicodeString(&str);
503 pNtClose(h);
504 InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
505 pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
506 DIR_TEST_CREATE_SUCCESS(&h)
507 pRtlFreeUnicodeString(&str);
508 pNtClose(h);
509
510 pNtClose(dir);
511
512 if (!is_nt4)
513 {
514 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
515 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Global\\om.c-test");
516 DIR_TEST_CREATE_SUCCESS(&dir)
517 pRtlFreeUnicodeString(&str);
518 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local\\om.c-test\\one more level");
519 DIR_TEST_CREATE_SUCCESS(&h)
520 pRtlFreeUnicodeString(&str);
521 pNtClose(h);
522 InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
523 pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
524 DIR_TEST_CREATE_SUCCESS(&dir)
525 pRtlFreeUnicodeString(&str);
526 pNtClose(h);
527 pNtClose(dir);
528 }
529
530 /* Create other objects using RootDirectory */
531
532 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
533 pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects");
534 DIR_TEST_OPEN_SUCCESS(&dir)
535 pRtlFreeUnicodeString(&str);
536 InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
537
538 /* Test invalid paths */
539 pRtlCreateUnicodeStringFromAsciiz(&str, "\\om.c-mutant");
540 status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
541 ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
542 "NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
543 pRtlFreeUnicodeString(&str);
544 pRtlCreateUnicodeStringFromAsciiz(&str, "\\om.c-mutant\\");
545 status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
546 ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
547 "NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
548 pRtlFreeUnicodeString(&str);
549
550 pRtlCreateUnicodeStringFromAsciiz(&str, "om.c\\-mutant");
551 status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
552 ok(status == STATUS_OBJECT_PATH_NOT_FOUND,
553 "NtCreateMutant should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
554 pRtlFreeUnicodeString(&str);
555
556 pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-mutant");
557 status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
558 ok(status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status);
559 pRtlFreeUnicodeString(&str);
560 pNtClose(h);
561
562 pNtClose(dir);
563 }
564
565 #define SYMLNK_TEST_CREATE_OPEN_FAILURE2(h,n,t,e,e2) \
566 pRtlCreateUnicodeStringFromAsciiz(&str, n);\
567 pRtlCreateUnicodeStringFromAsciiz(&target, t);\
568 status = pNtCreateSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr, &target);\
569 ok(status == e || status == e2, \
570 "NtCreateSymbolicLinkObject should have failed with %s or %s got(%08x)\n", #e, #e2, status);\
571 status = pNtOpenSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr);\
572 ok(status == e || status == e2, \
573 "NtOpenSymbolicLinkObject should have failed with %s or %s got(%08x)\n", #e, #e2, status);\
574 pRtlFreeUnicodeString(&target);\
575 pRtlFreeUnicodeString(&str);
576
577 #define SYMLNK_TEST_CREATE_OPEN_FAILURE(h,n,t,e) SYMLNK_TEST_CREATE_OPEN_FAILURE2(h,n,t,e,e)
578
579 static void test_symboliclink(void)
580 {
581 NTSTATUS status;
582 UNICODE_STRING str, target;
583 OBJECT_ATTRIBUTES attr;
584 HANDLE dir, link, h;
585 IO_STATUS_BLOCK iosb;
586
587 /* No name and/or no attributes */
588 InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
589 SYMLNK_TEST_CREATE_OPEN_FAILURE2(NULL, "", "", STATUS_ACCESS_VIOLATION, STATUS_INVALID_PARAMETER)
590
591 status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL, NULL);
592 ok(status == STATUS_ACCESS_VIOLATION,
593 "NtCreateSymbolicLinkObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
594 status = pNtOpenSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL);
595 ok(status == STATUS_INVALID_PARAMETER,
596 "NtOpenSymbolicLinkObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
597
598 /* No attributes */
599 pRtlCreateUnicodeStringFromAsciiz(&target, "\\DosDevices");
600 status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL, &target);
601 ok(status == STATUS_SUCCESS || status == STATUS_ACCESS_VIOLATION, /* nt4 */
602 "NtCreateSymbolicLinkObject failed(%08x)\n", status);
603 pRtlFreeUnicodeString(&target);
604 if (!status) pNtClose(h);
605
606 InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
607 status = pNtCreateSymbolicLinkObject(&link, SYMBOLIC_LINK_QUERY, &attr, &target);
608 ok(status == STATUS_INVALID_PARAMETER ||
609 broken(status == STATUS_SUCCESS), /* nt4 */
610 "NtCreateSymbolicLinkObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
611 if (!status) pNtClose(h);
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
616 /* Bad name */
617 pRtlCreateUnicodeStringFromAsciiz(&target, "anywhere");
618 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
619
620 pRtlCreateUnicodeStringFromAsciiz(&str, "");
621 status = pNtCreateSymbolicLinkObject(&link, SYMBOLIC_LINK_QUERY, &attr, &target);
622 ok(status == STATUS_SUCCESS, "Failed to create SymbolicLink(%08x)\n", status);
623 status = pNtOpenSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, &attr);
624 ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
625 "NtOpenSymbolicLinkObject should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
626 pNtClose(link);
627 pRtlFreeUnicodeString(&str);
628
629 pRtlCreateUnicodeStringFromAsciiz(&str, "\\");
630 status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, &attr, &target);
631 todo_wine ok(status == STATUS_OBJECT_TYPE_MISMATCH,
632 "NtCreateSymbolicLinkObject should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
633 pRtlFreeUnicodeString(&str);
634 pRtlFreeUnicodeString(&target);
635
636 SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "BaseNamedObjects", "->Somewhere", STATUS_OBJECT_PATH_SYNTAX_BAD)
637 SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
638 SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\\\BaseNamedObjects", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
639 SYMLNK_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\\\om.c-test", "->Somewhere", STATUS_OBJECT_NAME_INVALID)
640 SYMLNK_TEST_CREATE_OPEN_FAILURE2(&h, "\\BaseNamedObjects\\om.c-test\\", "->Somewhere",
641 STATUS_OBJECT_NAME_INVALID, STATUS_OBJECT_PATH_NOT_FOUND)
642
643
644 /* Compound test */
645 if (!(dir = get_base_dir()))
646 {
647 win_skip( "couldn't find the BaseNamedObjects dir\n" );
648 return;
649 }
650
651 InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
652 pRtlCreateUnicodeStringFromAsciiz(&str, "test-link");
653 pRtlCreateUnicodeStringFromAsciiz(&target, "\\DosDevices");
654 status = pNtCreateSymbolicLinkObject(&link, SYMBOLIC_LINK_QUERY, &attr, &target);
655 ok(status == STATUS_SUCCESS, "Failed to create SymbolicLink(%08x)\n", status);
656 pRtlFreeUnicodeString(&str);
657 pRtlFreeUnicodeString(&target);
658
659 pRtlCreateUnicodeStringFromAsciiz(&str, "test-link\\NUL");
660 status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
661 todo_wine ok(status == STATUS_SUCCESS, "Failed to open NUL device(%08x)\n", status);
662 pRtlFreeUnicodeString(&str);
663
664 pNtClose(h);
665 pNtClose(link);
666 pNtClose(dir);
667 }
668
669 static void test_query_object(void)
670 {
671 static const WCHAR name[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s',
672 '\\','t','e','s','t','_','e','v','e','n','t'};
673 static const WCHAR type_event[] = {'E','v','e','n','t'};
674 static const WCHAR type_file[] = {'F','i','l','e'};
675 HANDLE handle;
676 char buffer[1024];
677 NTSTATUS status;
678 ULONG len, expected_len;
679 UNICODE_STRING *str;
680 char dir[MAX_PATH];
681
682 handle = CreateEventA( NULL, FALSE, FALSE, "test_event" );
683
684 len = 0;
685 status = pNtQueryObject( handle, ObjectNameInformation, buffer, 0, &len );
686 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
687 ok( len >= sizeof(UNICODE_STRING) + sizeof(name) + sizeof(WCHAR), "unexpected len %u\n", len );
688
689 len = 0;
690 status = pNtQueryObject( handle, ObjectTypeInformation, buffer, 0, &len );
691 todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
692 todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + sizeof(type_event) + sizeof(WCHAR), "unexpected len %u\n", len );
693
694 len = 0;
695 status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(UNICODE_STRING), &len );
696 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
697 ok( len >= sizeof(UNICODE_STRING) + sizeof(name) + sizeof(WCHAR), "unexpected len %u\n", len );
698
699 len = 0;
700 status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(OBJECT_TYPE_INFORMATION), &len );
701 todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
702 todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + sizeof(type_event) + sizeof(WCHAR), "unexpected len %u\n", len );
703
704 len = 0;
705 status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len );
706 ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
707 ok( len > sizeof(UNICODE_STRING), "unexpected len %u\n", len );
708 str = (UNICODE_STRING *)buffer;
709 ok( sizeof(UNICODE_STRING) + str->Length + sizeof(WCHAR) == len, "unexpected len %u\n", len );
710 ok( str->Length >= sizeof(name), "unexpected len %u\n", str->Length );
711 /* there can be a \\Sessions prefix in the name */
712 ok( !memcmp( str->Buffer + (str->Length - sizeof(name)) / sizeof(WCHAR), name, sizeof(name) ),
713 "wrong name %s\n", wine_dbgstr_w(str->Buffer) );
714
715 len -= sizeof(WCHAR);
716 status = pNtQueryObject( handle, ObjectNameInformation, buffer, len, &len );
717 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
718 ok( len >= sizeof(UNICODE_STRING) + sizeof(name) + sizeof(WCHAR), "unexpected len %u\n", len );
719
720 len = 0;
721 memset( buffer, 0, sizeof(buffer) );
722 status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
723 todo_wine ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
724 todo_wine ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
725 str = (UNICODE_STRING *)buffer;
726 todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR), "unexpected len %u\n", len );
727 todo_wine ok( str->Buffer && !memcmp( str->Buffer, type_event, sizeof(type_file) ),
728 "wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
729
730 len -= sizeof(WCHAR);
731 status = pNtQueryObject( handle, ObjectTypeInformation, buffer, len, &len );
732 todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
733 todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + sizeof(type_event) + sizeof(WCHAR), "unexpected len %u\n", len );
734
735 pNtClose( handle );
736
737 handle = CreateEventA( NULL, FALSE, FALSE, NULL );
738 len = 0;
739 status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len );
740 ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
741 ok( len == sizeof(UNICODE_STRING), "unexpected len %u\n", len );
742 str = (UNICODE_STRING *)buffer;
743 ok( str->Length == 0, "unexpected len %u\n", len );
744 ok( str->Buffer == NULL, "unexpected ptr %p\n", str->Buffer );
745 pNtClose( handle );
746
747 GetWindowsDirectoryA( dir, MAX_PATH );
748 handle = CreateFileA( dir, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
749 FILE_FLAG_BACKUP_SEMANTICS, 0 );
750 len = 0;
751 status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len );
752 ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
753 ok( len > sizeof(UNICODE_STRING), "unexpected len %u\n", len );
754 str = (UNICODE_STRING *)buffer;
755 expected_len = sizeof(UNICODE_STRING) + str->Length + sizeof(WCHAR);
756 ok( len == expected_len || broken(len == expected_len - sizeof(WCHAR)), /* NT4 */
757 "unexpected len %u\n", len );
758 trace( "got %s len %u\n", wine_dbgstr_w(str->Buffer), len );
759
760 len = 0;
761 status = pNtQueryObject( handle, ObjectNameInformation, buffer, 0, &len );
762 ok( status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INSUFFICIENT_RESOURCES),
763 "NtQueryObject failed %x\n", status );
764 ok( len == expected_len || broken(!len || len == sizeof(UNICODE_STRING)),
765 "unexpected len %u\n", len );
766
767 len = 0;
768 status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(UNICODE_STRING), &len );
769 ok( status == STATUS_BUFFER_OVERFLOW || broken(status == STATUS_INSUFFICIENT_RESOURCES
770 || status == STATUS_INFO_LENGTH_MISMATCH),
771 "NtQueryObject failed %x\n", status );
772 ok( len == expected_len || broken(!len),
773 "unexpected len %u\n", len );
774
775 len = 0;
776 memset( buffer, 0, sizeof(buffer) );
777 status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
778 todo_wine ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
779 todo_wine ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
780 str = (UNICODE_STRING *)buffer;
781 expected_len = sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR);
782 todo_wine ok( len >= expected_len, "unexpected len %u\n", len );
783 todo_wine ok( str->Buffer && !memcmp( str->Buffer, type_file, sizeof(type_file) ),
784 "wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
785
786 pNtClose( handle );
787 }
788
789 static void test_type_mismatch(void)
790 {
791 HANDLE h;
792 NTSTATUS res;
793 OBJECT_ATTRIBUTES attr;
794
795 attr.Length = sizeof(attr);
796 attr.RootDirectory = 0;
797 attr.ObjectName = NULL;
798 attr.Attributes = 0;
799 attr.SecurityDescriptor = NULL;
800 attr.SecurityQualityOfService = NULL;
801
802 res = pNtCreateEvent( &h, 0, &attr, 0, 0 );
803 ok(!res, "can't create event: %x\n", res);
804
805 res = pNtReleaseSemaphore( h, 30, NULL );
806 ok(res == STATUS_OBJECT_TYPE_MISMATCH, "expected 0xc0000024, got %x\n", res);
807
808 pNtClose( h );
809 }
810
811 static void test_event(void)
812 {
813 HANDLE Event;
814 HANDLE Event2;
815 NTSTATUS status;
816 UNICODE_STRING str;
817 OBJECT_ATTRIBUTES attr;
818 EVENT_BASIC_INFORMATION info;
819 static const WCHAR eventName[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s','\\','t','e','s','t','E','v','e','n','t',0};
820
821 pRtlInitUnicodeString(&str, eventName);
822 InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
823
824 status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, 1, 0);
825 ok( status == STATUS_SUCCESS, "NtCreateEvent failed %08x\n", status );
826
827 status = pNtPulseEvent(Event, NULL);
828 ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status );
829
830 status = pNtQueryEvent(Event, EventBasicInformation, &info, sizeof(info), NULL);
831 ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
832 ok( info.EventType == 1 && info.EventState == 0,
833 "NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState );
834
835 status = pNtOpenEvent(&Event2, GENERIC_ALL, &attr);
836 ok( status == STATUS_SUCCESS, "NtOpenEvent failed %08x\n", status );
837
838 pNtClose(Event);
839
840 status = pNtQueryEvent(Event2, EventBasicInformation, &info, sizeof(info), NULL);
841 ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
842 ok( info.EventType == 1 && info.EventState == 0,
843 "NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState );
844
845 pNtClose(Event2);
846 }
847
848 static const WCHAR keyed_nameW[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s',
849 '\\','W','i','n','e','T','e','s','t','E','v','e','n','t',0};
850
851 static DWORD WINAPI keyed_event_thread( void *arg )
852 {
853 HANDLE handle;
854 NTSTATUS status;
855 LARGE_INTEGER timeout;
856 OBJECT_ATTRIBUTES attr;
857 UNICODE_STRING str;
858 ULONG_PTR i;
859
860 attr.Length = sizeof(attr);
861 attr.RootDirectory = 0;
862 attr.ObjectName = &str;
863 attr.Attributes = 0;
864 attr.SecurityDescriptor = NULL;
865 attr.SecurityQualityOfService = NULL;
866 RtlInitUnicodeString( &str, keyed_nameW );
867
868 status = pNtOpenKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr );
869 ok( !status, "NtOpenKeyedEvent failed %x\n", status );
870
871 for (i = 0; i < 20; i++)
872 {
873 if (i & 1)
874 status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
875 else
876 status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
877 ok( status == STATUS_SUCCESS, "%li: failed %x\n", i, status );
878 Sleep( 20 - i );
879 }
880
881 status = pNtReleaseKeyedEvent( handle, (void *)0x1234, 0, NULL );
882 ok( status == STATUS_SUCCESS, "NtReleaseKeyedEvent %x\n", status );
883
884 timeout.QuadPart = -10000;
885 status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
886 ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
887 status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
888 ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
889
890 NtClose( handle );
891 return 0;
892 }
893
894 static void test_keyed_events(void)
895 {
896 OBJECT_ATTRIBUTES attr;
897 UNICODE_STRING str;
898 HANDLE handle, event, thread;
899 NTSTATUS status;
900 LARGE_INTEGER timeout;
901 ULONG_PTR i;
902
903 if (!pNtCreateKeyedEvent)
904 {
905 win_skip( "Keyed events not supported\n" );
906 return;
907 }
908
909 attr.Length = sizeof(attr);
910 attr.RootDirectory = 0;
911 attr.ObjectName = &str;
912 attr.Attributes = 0;
913 attr.SecurityDescriptor = NULL;
914 attr.SecurityQualityOfService = NULL;
915 RtlInitUnicodeString( &str, keyed_nameW );
916
917 status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS | SYNCHRONIZE, &attr, 0 );
918 ok( !status, "NtCreateKeyedEvent failed %x\n", status );
919
920 status = WaitForSingleObject( handle, 1000 );
921 ok( status == 0, "WaitForSingleObject %x\n", status );
922
923 timeout.QuadPart = -100000;
924 status = pNtWaitForKeyedEvent( handle, (void *)255, 0, &timeout );
925 ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %x\n", status );
926 status = pNtReleaseKeyedEvent( handle, (void *)255, 0, &timeout );
927 ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %x\n", status );
928
929 status = pNtWaitForKeyedEvent( handle, (void *)254, 0, &timeout );
930 ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
931 status = pNtReleaseKeyedEvent( handle, (void *)254, 0, &timeout );
932 ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
933
934 status = pNtWaitForKeyedEvent( handle, NULL, 0, &timeout );
935 ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
936 status = pNtReleaseKeyedEvent( handle, NULL, 0, &timeout );
937 ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
938
939 status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
940 ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %x\n", status );
941 status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
942 ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %x\n", status );
943
944 status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
945 ok( status == STATUS_INVALID_HANDLE, "NtWaitForKeyedEvent %x\n", status );
946 status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
947 ok( status == STATUS_INVALID_HANDLE, "NtReleaseKeyedEvent %x\n", status );
948
949 thread = CreateThread( NULL, 0, keyed_event_thread, 0, 0, NULL );
950 for (i = 0; i < 20; i++)
951 {
952 if (i & 1)
953 status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
954 else
955 status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
956 ok( status == STATUS_SUCCESS, "%li: failed %x\n", i, status );
957 Sleep( i );
958 }
959 status = pNtWaitForKeyedEvent( handle, (void *)0x1234, 0, &timeout );
960 ok( status == STATUS_SUCCESS, "NtWaitForKeyedEvent %x\n", status );
961 status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
962 ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
963 status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
964 ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
965
966 ok( WaitForSingleObject( thread, 30000 ) == 0, "wait failed\n" );
967
968 NtClose( handle );
969
970 /* test access rights */
971
972 status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAIT, &attr, 0 );
973 ok( !status, "NtCreateKeyedEvent failed %x\n", status );
974 status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
975 ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
976 status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
977 ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %x\n", status );
978 NtClose( handle );
979
980 status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAKE, &attr, 0 );
981 ok( !status, "NtCreateKeyedEvent failed %x\n", status );
982 status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
983 ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %x\n", status );
984 status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
985 ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
986 NtClose( handle );
987
988 status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr, 0 );
989 ok( !status, "NtCreateKeyedEvent failed %x\n", status );
990 status = WaitForSingleObject( handle, 1000 );
991 ok( status == WAIT_FAILED && GetLastError() == ERROR_ACCESS_DENIED,
992 "WaitForSingleObject %x err %u\n", status, GetLastError() );
993 status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
994 ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
995 status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
996 ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
997 NtClose( handle );
998
999 /* GENERIC_READ gives wait access */
1000 status = pNtCreateKeyedEvent( &handle, GENERIC_READ, &attr, 0 );
1001 ok( !status, "NtCreateKeyedEvent failed %x\n", status );
1002 status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
1003 ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
1004 status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
1005 ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %x\n", status );
1006 NtClose( handle );
1007
1008 /* GENERIC_WRITE gives wake access */
1009 status = pNtCreateKeyedEvent( &handle, GENERIC_WRITE, &attr, 0 );
1010 ok( !status, "NtCreateKeyedEvent failed %x\n", status );
1011 status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
1012 ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %x\n", status );
1013 status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
1014 ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
1015
1016 /* it's not an event */
1017 status = pNtPulseEvent( handle, NULL );
1018 ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtPulseEvent %x\n", status );
1019
1020 status = pNtCreateEvent( &event, GENERIC_ALL, &attr, FALSE, FALSE );
1021 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH,
1022 "CreateEvent %x\n", status );
1023
1024 NtClose( handle );
1025
1026 status = pNtCreateEvent( &event, GENERIC_ALL, &attr, FALSE, FALSE );
1027 ok( status == 0, "CreateEvent %x\n", status );
1028 status = pNtWaitForKeyedEvent( event, (void *)8, 0, &timeout );
1029 ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtWaitForKeyedEvent %x\n", status );
1030 status = pNtReleaseKeyedEvent( event, (void *)8, 0, &timeout );
1031 ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtReleaseKeyedEvent %x\n", status );
1032 NtClose( event );
1033 }
1034
1035 START_TEST(om)
1036 {
1037 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
1038 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
1039
1040 if (!hntdll)
1041 {
1042 skip("not running on NT, skipping test\n");
1043 return;
1044 }
1045
1046 pCreateWaitableTimerA = (void *)GetProcAddress(hkernel32, "CreateWaitableTimerA");
1047
1048 pRtlCreateUnicodeStringFromAsciiz = (void *)GetProcAddress(hntdll, "RtlCreateUnicodeStringFromAsciiz");
1049 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
1050 pNtCreateEvent = (void *)GetProcAddress(hntdll, "NtCreateEvent");
1051 pNtCreateMutant = (void *)GetProcAddress(hntdll, "NtCreateMutant");
1052 pNtOpenEvent = (void *)GetProcAddress(hntdll, "NtOpenEvent");
1053 pNtQueryEvent = (void *)GetProcAddress(hntdll, "NtQueryEvent");
1054 pNtPulseEvent = (void *)GetProcAddress(hntdll, "NtPulseEvent");
1055 pNtOpenMutant = (void *)GetProcAddress(hntdll, "NtOpenMutant");
1056 pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
1057 pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
1058 pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
1059 pNtCreateNamedPipeFile = (void *)GetProcAddress(hntdll, "NtCreateNamedPipeFile");
1060 pNtOpenDirectoryObject = (void *)GetProcAddress(hntdll, "NtOpenDirectoryObject");
1061 pNtCreateDirectoryObject= (void *)GetProcAddress(hntdll, "NtCreateDirectoryObject");
1062 pNtOpenSymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtOpenSymbolicLinkObject");
1063 pNtCreateSymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtCreateSymbolicLinkObject");
1064 pNtQuerySymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtQuerySymbolicLinkObject");
1065 pNtCreateSemaphore = (void *)GetProcAddress(hntdll, "NtCreateSemaphore");
1066 pNtCreateTimer = (void *)GetProcAddress(hntdll, "NtCreateTimer");
1067 pNtCreateSection = (void *)GetProcAddress(hntdll, "NtCreateSection");
1068 pNtQueryObject = (void *)GetProcAddress(hntdll, "NtQueryObject");
1069 pNtReleaseSemaphore = (void *)GetProcAddress(hntdll, "NtReleaseSemaphore");
1070 pNtCreateKeyedEvent = (void *)GetProcAddress(hntdll, "NtCreateKeyedEvent");
1071 pNtOpenKeyedEvent = (void *)GetProcAddress(hntdll, "NtOpenKeyedEvent");
1072 pNtWaitForKeyedEvent = (void *)GetProcAddress(hntdll, "NtWaitForKeyedEvent");
1073 pNtReleaseKeyedEvent = (void *)GetProcAddress(hntdll, "NtReleaseKeyedEvent");
1074
1075 test_case_sensitive();
1076 test_namespace_pipe();
1077 test_name_collisions();
1078 test_directory();
1079 test_symboliclink();
1080 test_query_object();
1081 test_type_mismatch();
1082 test_event();
1083 test_keyed_events();
1084 }