ntdll: Win64 printf format warning fixes.
[wine] / dlls / ntdll / om.c
1 /*
2  *      Object management functions
3  *
4  * Copyright 1999, 2000 Juergen Schmied
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 "config.h"
23
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #ifdef HAVE_IO_H
28 # include <io.h>
29 #endif
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33
34 #include "ntstatus.h"
35 #define WIN32_NO_STATUS
36 #include "wine/debug.h"
37 #include "windef.h"
38 #include "winternl.h"
39 #include "ntdll_misc.h"
40 #include "wine/server.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
43
44
45 /*
46  *      Generic object functions
47  */
48
49 /******************************************************************************
50  * NtQueryObject [NTDLL.@]
51  * ZwQueryObject [NTDLL.@]
52  */
53 NTSTATUS WINAPI NtQueryObject(IN HANDLE handle,
54                               IN OBJECT_INFORMATION_CLASS info_class,
55                               OUT PVOID ptr, IN ULONG len, OUT PULONG used_len)
56 {
57     NTSTATUS status;
58
59     TRACE("(%p,0x%08x,%p,0x%08x,%p): stub\n",
60           handle, info_class, ptr, len, used_len);
61
62     if (used_len) *used_len = 0;
63
64     switch (info_class)
65     {
66     case ObjectDataInformation:
67         {
68             OBJECT_DATA_INFORMATION* p = (OBJECT_DATA_INFORMATION*)ptr;
69
70             if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE;
71
72             SERVER_START_REQ( set_handle_info )
73             {
74                 req->handle = handle;
75                 req->flags  = 0;
76                 req->mask   = 0;
77                 status = wine_server_call( req );
78                 if (status == STATUS_SUCCESS)
79                 {
80                     p->InheritHandle = (reply->old_flags & HANDLE_FLAG_INHERIT) ? TRUE : FALSE;
81                     p->ProtectFromClose = (reply->old_flags & HANDLE_FLAG_PROTECT_FROM_CLOSE) ? TRUE : FALSE;
82                     if (used_len) *used_len = sizeof(*p);
83                 }
84             }
85             SERVER_END_REQ;
86         }
87         break;
88     default:
89         FIXME("Unsupported information class %u\n", info_class);
90         status = STATUS_NOT_IMPLEMENTED;
91         break;
92     }
93     return status;
94 }
95
96 /******************************************************************
97  *              NtSetInformationObject [NTDLL.@]
98  *              ZwSetInformationObject [NTDLL.@]
99  *
100  */
101 NTSTATUS WINAPI NtSetInformationObject(IN HANDLE handle,
102                                        IN OBJECT_INFORMATION_CLASS info_class,
103                                        IN PVOID ptr, IN ULONG len)
104 {
105     NTSTATUS status;
106
107     TRACE("(%p,0x%08x,%p,0x%08x): stub\n",
108           handle, info_class, ptr, len);
109
110     switch (info_class)
111     {
112     case ObjectDataInformation:
113         {
114             OBJECT_DATA_INFORMATION* p = (OBJECT_DATA_INFORMATION*)ptr;
115
116             if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE;
117
118             SERVER_START_REQ( set_handle_info )
119             {
120                 req->handle = handle;
121                 req->flags  = 0;
122                 req->mask   = HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE;
123                 if (p->InheritHandle)    req->flags |= HANDLE_FLAG_INHERIT;
124                 if (p->ProtectFromClose) req->flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE;
125                 status = wine_server_call( req );
126             }
127             SERVER_END_REQ;
128         }
129         break;
130     default:
131         FIXME("Unsupported information class %u\n", info_class);
132         status = STATUS_NOT_IMPLEMENTED;
133         break;
134     }
135     return status;
136 }
137
138 /******************************************************************************
139  *  NtQuerySecurityObject       [NTDLL.@]
140  *
141  * An ntdll analogue to GetKernelObjectSecurity().
142  *
143  * NOTES
144  *  only the lowest 4 bit of SecurityObjectInformationClass are used
145  *  0x7-0xf returns STATUS_ACCESS_DENIED (even running with system privileges)
146  *
147  * FIXME
148  *  We are constructing a fake sid (Administrators:Full, System:Full, Everyone:Read)
149  */
150 NTSTATUS WINAPI
151 NtQuerySecurityObject(
152         IN HANDLE Object,
153         IN SECURITY_INFORMATION RequestedInformation,
154         OUT PSECURITY_DESCRIPTOR pSecurityDesriptor,
155         IN ULONG Length,
156         OUT PULONG ResultLength)
157 {
158         static SID_IDENTIFIER_AUTHORITY localSidAuthority = {SECURITY_NT_AUTHORITY};
159         static SID_IDENTIFIER_AUTHORITY worldSidAuthority = {SECURITY_WORLD_SID_AUTHORITY};
160         BYTE Buffer[256];
161         PISECURITY_DESCRIPTOR_RELATIVE psd = (PISECURITY_DESCRIPTOR_RELATIVE)Buffer;
162         UINT BufferIndex = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
163
164         FIXME("(%p,0x%08x,%p,0x%08x,%p) stub!\n",
165         Object, RequestedInformation, pSecurityDesriptor, Length, ResultLength);
166
167         RequestedInformation &= 0x0000000f;
168
169         if (RequestedInformation & SACL_SECURITY_INFORMATION) return STATUS_ACCESS_DENIED;
170
171         ZeroMemory(Buffer, 256);
172         RtlCreateSecurityDescriptor((PSECURITY_DESCRIPTOR)psd, SECURITY_DESCRIPTOR_REVISION);
173         psd->Control = SE_SELF_RELATIVE |
174           ((RequestedInformation & DACL_SECURITY_INFORMATION) ? SE_DACL_PRESENT:0);
175
176         /* owner: administrator S-1-5-20-220*/
177         if (OWNER_SECURITY_INFORMATION & RequestedInformation)
178         {
179           SID* psid = (SID*)&(Buffer[BufferIndex]);
180
181           psd->Owner = BufferIndex;
182           BufferIndex += RtlLengthRequiredSid(2);
183
184           psid->Revision = SID_REVISION;
185           psid->SubAuthorityCount = 2;
186           psid->IdentifierAuthority = localSidAuthority;
187           psid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;
188           psid->SubAuthority[1] = DOMAIN_ALIAS_RID_ADMINS;
189         }
190
191         /* group: built in domain S-1-5-12 */
192         if (GROUP_SECURITY_INFORMATION & RequestedInformation)
193         {
194           SID* psid = (SID*) &(Buffer[BufferIndex]);
195
196           psd->Group = BufferIndex;
197           BufferIndex += RtlLengthRequiredSid(1);
198
199           psid->Revision = SID_REVISION;
200           psid->SubAuthorityCount = 1;
201           psid->IdentifierAuthority = localSidAuthority;
202           psid->SubAuthority[0] = SECURITY_LOCAL_SYSTEM_RID;
203         }
204
205         /* discretionary ACL */
206         if (DACL_SECURITY_INFORMATION & RequestedInformation)
207         {
208           /* acl header */
209           PACL pacl = (PACL)&(Buffer[BufferIndex]);
210           PACCESS_ALLOWED_ACE pace;
211           SID* psid;
212
213           psd->Dacl = BufferIndex;
214
215           pacl->AclRevision = MIN_ACL_REVISION;
216           pacl->AceCount = 3;
217           pacl->AclSize = BufferIndex; /* storing the start index temporary */
218
219           BufferIndex += sizeof(ACL);
220
221           /* ACE System - full access */
222           pace = (PACCESS_ALLOWED_ACE)&(Buffer[BufferIndex]);
223           BufferIndex += sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD);
224
225           pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
226           pace->Header.AceFlags = CONTAINER_INHERIT_ACE;
227           pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + RtlLengthRequiredSid(1);
228           pace->Mask = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER  | 0x3f;
229           pace->SidStart = BufferIndex;
230
231           /* SID S-1-5-12 (System) */
232           psid = (SID*)&(Buffer[BufferIndex]);
233
234           BufferIndex += RtlLengthRequiredSid(1);
235
236           psid->Revision = SID_REVISION;
237           psid->SubAuthorityCount = 1;
238           psid->IdentifierAuthority = localSidAuthority;
239           psid->SubAuthority[0] = SECURITY_LOCAL_SYSTEM_RID;
240
241           /* ACE Administrators - full access*/
242           pace = (PACCESS_ALLOWED_ACE) &(Buffer[BufferIndex]);
243           BufferIndex += sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD);
244
245           pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
246           pace->Header.AceFlags = CONTAINER_INHERIT_ACE;
247           pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + RtlLengthRequiredSid(2);
248           pace->Mask = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER  | 0x3f;
249           pace->SidStart = BufferIndex;
250
251           /* S-1-5-12 (Administrators) */
252           psid = (SID*)&(Buffer[BufferIndex]);
253
254           BufferIndex += RtlLengthRequiredSid(2);
255
256           psid->Revision = SID_REVISION;
257           psid->SubAuthorityCount = 2;
258           psid->IdentifierAuthority = localSidAuthority;
259           psid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;
260           psid->SubAuthority[1] = DOMAIN_ALIAS_RID_ADMINS;
261
262           /* ACE Everyone - read access */
263           pace = (PACCESS_ALLOWED_ACE)&(Buffer[BufferIndex]);
264           BufferIndex += sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD);
265
266           pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
267           pace->Header.AceFlags = CONTAINER_INHERIT_ACE;
268           pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + RtlLengthRequiredSid(1);
269           pace->Mask = READ_CONTROL| 0x19;
270           pace->SidStart = BufferIndex;
271
272           /* SID S-1-1-0 (Everyone) */
273           psid = (SID*)&(Buffer[BufferIndex]);
274
275           BufferIndex += RtlLengthRequiredSid(1);
276
277           psid->Revision = SID_REVISION;
278           psid->SubAuthorityCount = 1;
279           psid->IdentifierAuthority = worldSidAuthority;
280           psid->SubAuthority[0] = 0;
281
282           /* calculate used bytes */
283           pacl->AclSize = BufferIndex - pacl->AclSize;
284         }
285         *ResultLength = BufferIndex;
286         TRACE("len=%u\n", *ResultLength);
287         if (Length < *ResultLength) return STATUS_BUFFER_TOO_SMALL;
288         memcpy(pSecurityDesriptor, Buffer, *ResultLength);
289
290         return STATUS_SUCCESS;
291 }
292
293
294 /******************************************************************************
295  *  NtDuplicateObject           [NTDLL.@]
296  *  ZwDuplicateObject           [NTDLL.@]
297  */
298 NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source,
299                                    HANDLE dest_process, PHANDLE dest,
300                                    ACCESS_MASK access, ULONG attributes, ULONG options )
301 {
302     NTSTATUS ret;
303     SERVER_START_REQ( dup_handle )
304     {
305         req->src_process = source_process;
306         req->src_handle  = source;
307         req->dst_process = dest_process;
308         req->access      = access;
309         req->attributes  = attributes;
310         req->options     = options;
311
312         if (!(ret = wine_server_call( req )))
313         {
314             if (dest) *dest = reply->handle;
315             if (reply->fd != -1) close( reply->fd );
316         }
317     }
318     SERVER_END_REQ;
319     return ret;
320 }
321
322 /**************************************************************************
323  *                 NtClose                              [NTDLL.@]
324  *
325  * Close a handle reference to an object.
326  * 
327  * PARAMS
328  *  Handle [I] handle to close
329  *
330  * RETURNS
331  *  Success: ERROR_SUCCESS.
332  *  Failure: An NTSTATUS error code.
333  */
334 NTSTATUS WINAPI NtClose( HANDLE Handle )
335 {
336     NTSTATUS ret;
337     SERVER_START_REQ( close_handle )
338     {
339         req->handle = Handle;
340         ret = wine_server_call( req );
341         if (!ret && reply->fd != -1) close( reply->fd );
342     }
343     SERVER_END_REQ;
344     return ret;
345 }
346
347 /*
348  *      Directory functions
349  */
350
351 /**************************************************************************
352  * NtOpenDirectoryObject [NTDLL.@]
353  * ZwOpenDirectoryObject [NTDLL.@]
354  *
355  * Open a namespace directory object.
356  * 
357  * PARAMS
358  *  DirectoryHandle  [O] Destination for the new directory handle
359  *  DesiredAccess    [I] Desired access to the directory
360  *  ObjectAttributes [I] Structure describing the directory
361  *
362  * RETURNS
363  *  Success: ERROR_SUCCESS.
364  *  Failure: An NTSTATUS error code.
365  */
366 NTSTATUS WINAPI NtOpenDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess,
367                                       POBJECT_ATTRIBUTES ObjectAttributes)
368 {
369     NTSTATUS ret;
370     TRACE("(%p,0x%08x)\n", DirectoryHandle, DesiredAccess);
371     dump_ObjectAttributes(ObjectAttributes);
372
373     if (!DirectoryHandle) return STATUS_ACCESS_VIOLATION;
374     if (!ObjectAttributes) return STATUS_INVALID_PARAMETER;
375     /* Have to test it here because server won't know difference between
376      * ObjectName == NULL and ObjectName == "" */
377     if (!ObjectAttributes->ObjectName)
378     {
379         if (ObjectAttributes->RootDirectory)
380             return STATUS_OBJECT_NAME_INVALID;
381         else
382             return STATUS_OBJECT_PATH_SYNTAX_BAD;
383     }
384
385     SERVER_START_REQ(open_directory)
386     {
387         req->access = DesiredAccess;
388         req->attributes = ObjectAttributes->Attributes;
389         req->rootdir = ObjectAttributes->RootDirectory;
390         if (ObjectAttributes->ObjectName)
391             wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
392                                  ObjectAttributes->ObjectName->Length);
393         ret = wine_server_call( req );
394         *DirectoryHandle = reply->handle;
395     }
396     SERVER_END_REQ;
397     return ret;
398 }
399
400 /******************************************************************************
401  *  NtCreateDirectoryObject     [NTDLL.@]
402  *  ZwCreateDirectoryObject     [NTDLL.@]
403  *
404  * Create a namespace directory object.
405  * 
406  * PARAMS
407  *  DirectoryHandle  [O] Destination for the new directory handle
408  *  DesiredAccess    [I] Desired access to the directory
409  *  ObjectAttributes [I] Structure describing the directory
410  *
411  * RETURNS
412  *  Success: ERROR_SUCCESS.
413  *  Failure: An NTSTATUS error code.
414  */
415 NTSTATUS WINAPI NtCreateDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess,
416                                         POBJECT_ATTRIBUTES ObjectAttributes)
417 {
418     NTSTATUS ret;
419     TRACE("(%p,0x%08x)\n", DirectoryHandle, DesiredAccess);
420     dump_ObjectAttributes(ObjectAttributes);
421
422     if (!DirectoryHandle) return STATUS_ACCESS_VIOLATION;
423
424     SERVER_START_REQ(create_directory)
425     {
426         req->access = DesiredAccess;
427         req->attributes = ObjectAttributes ? ObjectAttributes->Attributes : 0;
428         req->rootdir = ObjectAttributes ? ObjectAttributes->RootDirectory : 0;
429         if (ObjectAttributes && ObjectAttributes->ObjectName)
430             wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
431                                  ObjectAttributes->ObjectName->Length);
432         ret = wine_server_call( req );
433         *DirectoryHandle = reply->handle;
434     }
435     SERVER_END_REQ;
436     return ret;
437 }
438
439 /******************************************************************************
440  * NtQueryDirectoryObject [NTDLL.@]
441  * ZwQueryDirectoryObject [NTDLL.@]
442  *
443  * Read information from a namespace directory.
444  * 
445  * PARAMS
446  *  DirectoryHandle   [I]   Handle to a directory object
447  *  Buffer            [O]   Buffer to hold the read data
448  *  BufferLength      [I]   Size of the buffer in bytes
449  *  ReturnSingleEntry [I]   If TRUE, return a single entry, if FALSE, return as many as fit in the buffer
450  *  RestartScan       [I]   If TRUE, start scanning from the start, if FALSE, scan from Context
451  *  Context           [I/O] Indicates what point of the directory the scan is at
452  *  ReturnLength      [O]   Caller supplied storage for the number of bytes written (or NULL)
453  *
454  * RETURNS
455  *  Success: ERROR_SUCCESS.
456  *  Failure: An NTSTATUS error code.
457  */
458 NTSTATUS WINAPI NtQueryDirectoryObject(IN HANDLE DirectoryHandle, OUT PDIRECTORY_BASIC_INFORMATION Buffer,
459                                        IN ULONG BufferLength, IN BOOLEAN ReturnSingleEntry, IN BOOLEAN RestartScan,
460                                        IN OUT PULONG Context, OUT PULONG ReturnLength OPTIONAL)
461 {
462     FIXME("(%p,%p,0x%08x,0x%08x,0x%08x,%p,%p), stub\n", DirectoryHandle, Buffer, BufferLength, ReturnSingleEntry,
463           RestartScan, Context, ReturnLength);
464
465     return STATUS_NOT_IMPLEMENTED;
466 }
467
468 /*
469  *      Link objects
470  */
471
472 /******************************************************************************
473  *  NtOpenSymbolicLinkObject    [NTDLL.@]
474  *  ZwOpenSymbolicLinkObject    [NTDLL.@]
475  *
476  * Open a namespace symbolic link object.
477  * 
478  * PARAMS
479  *  LinkHandle       [O] Destination for the new symbolic link handle
480  *  DesiredAccess    [I] Desired access to the symbolic link
481  *  ObjectAttributes [I] Structure describing the symbolic link
482  *
483  * RETURNS
484  *  Success: ERROR_SUCCESS.
485  *  Failure: An NTSTATUS error code.
486  */
487 NTSTATUS WINAPI NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle, IN ACCESS_MASK DesiredAccess,
488                                          IN POBJECT_ATTRIBUTES ObjectAttributes)
489 {
490     NTSTATUS ret;
491     TRACE("(%p,0x%08x,%p)\n",LinkHandle, DesiredAccess, ObjectAttributes);
492     dump_ObjectAttributes(ObjectAttributes);
493
494     if (!LinkHandle) return STATUS_ACCESS_VIOLATION;
495     if (!ObjectAttributes) return STATUS_INVALID_PARAMETER;
496     /* Have to test it here because server won't know difference between
497      * ObjectName == NULL and ObjectName == "" */
498     if (!ObjectAttributes->ObjectName)
499     {
500         if (ObjectAttributes->RootDirectory)
501             return STATUS_OBJECT_NAME_INVALID;
502         else
503             return STATUS_OBJECT_PATH_SYNTAX_BAD;
504     }
505
506     SERVER_START_REQ(open_symlink)
507     {
508         req->access = DesiredAccess;
509         req->attributes = ObjectAttributes->Attributes;
510         req->rootdir = ObjectAttributes->RootDirectory;
511         if (ObjectAttributes->ObjectName)
512             wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
513                                  ObjectAttributes->ObjectName->Length);
514         ret = wine_server_call( req );
515         *LinkHandle = reply->handle;
516     }
517     SERVER_END_REQ;
518     return ret;
519 }
520
521 /******************************************************************************
522  *  NtCreateSymbolicLinkObject  [NTDLL.@]
523  *  ZwCreateSymbolicLinkObject  [NTDLL.@]
524  *
525  * Open a namespace symbolic link object.
526  * 
527  * PARAMS
528  *  SymbolicLinkHandle [O] Destination for the new symbolic link handle
529  *  DesiredAccess      [I] Desired access to the symbolic link
530  *  ObjectAttributes   [I] Structure describing the symbolic link
531  *  TargetName         [I] Name of the target symbolic link points to
532  *
533  * RETURNS
534  *  Success: ERROR_SUCCESS.
535  *  Failure: An NTSTATUS error code.
536  */
537 NTSTATUS WINAPI NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle,IN ACCESS_MASK DesiredAccess,
538                                            IN POBJECT_ATTRIBUTES ObjectAttributes,
539                                            IN PUNICODE_STRING TargetName)
540 {
541     NTSTATUS ret;
542     TRACE("(%p,0x%08x,%p, -> %s)\n", SymbolicLinkHandle, DesiredAccess, ObjectAttributes,
543                                       debugstr_us(TargetName));
544     dump_ObjectAttributes(ObjectAttributes);
545
546     if (!SymbolicLinkHandle || !TargetName) return STATUS_ACCESS_VIOLATION;
547     if (!TargetName->Buffer) return STATUS_INVALID_PARAMETER;
548
549     SERVER_START_REQ(create_symlink)
550     {
551         req->access = DesiredAccess;
552         req->attributes = ObjectAttributes ? ObjectAttributes->Attributes : 0;
553         req->rootdir = ObjectAttributes ? ObjectAttributes->RootDirectory : 0;
554         if (ObjectAttributes->ObjectName)
555         {
556             req->name_len = ObjectAttributes->ObjectName->Length;
557             wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
558                                  ObjectAttributes->ObjectName->Length);
559         }
560         else
561             req->name_len = 0;
562         wine_server_add_data(req, TargetName->Buffer, TargetName->Length);
563         ret = wine_server_call( req );
564         *SymbolicLinkHandle = reply->handle;
565     }
566     SERVER_END_REQ;
567     return ret;
568 }
569
570 /******************************************************************************
571  *  NtQuerySymbolicLinkObject   [NTDLL.@]
572  *  ZwQuerySymbolicLinkObject   [NTDLL.@]
573  *
574  * Query a namespace symbolic link object target name.
575  * 
576  * PARAMS
577  *  LinkHandle     [I] Handle to a symbolic link object
578  *  LinkTarget     [O] Destination for the symbolic link target
579  *  ReturnedLength [O] Size of returned data
580  *
581  * RETURNS
582  *  Success: ERROR_SUCCESS.
583  *  Failure: An NTSTATUS error code.
584  */
585 NTSTATUS WINAPI NtQuerySymbolicLinkObject(IN HANDLE LinkHandle, IN OUT PUNICODE_STRING LinkTarget,
586                                           OUT PULONG ReturnedLength OPTIONAL)
587 {
588     NTSTATUS ret;
589     TRACE("(%p,%p,%p)\n", LinkHandle, LinkTarget, ReturnedLength);
590
591     if (!LinkTarget) return STATUS_ACCESS_VIOLATION;
592
593     SERVER_START_REQ(query_symlink)
594     {
595         req->handle = LinkHandle;
596         wine_server_set_reply( req, LinkTarget->Buffer, LinkTarget->MaximumLength );
597         if (!(ret = wine_server_call( req )))
598         {
599             LinkTarget->Length = wine_server_reply_size(reply);
600             if (ReturnedLength) *ReturnedLength = LinkTarget->Length;
601         }
602     }
603     SERVER_END_REQ;
604     return ret;
605 }
606
607 /******************************************************************************
608  *  NtAllocateUuids   [NTDLL.@]
609  */
610 NTSTATUS WINAPI NtAllocateUuids(
611         PULARGE_INTEGER Time,
612         PULONG Range,
613         PULONG Sequence)
614 {
615         FIXME("(%p,%p,%p), stub.\n", Time, Range, Sequence);
616         return 0;
617 }