ntdll: Make sure we don't try to attach the main exe a second time.
[wine/zf.git] / dlls / ntdll / om.c
blob0d66867496b75d70e58a5e4b5d03849836c1eaa2
1 /*
2 * Object management functions
4 * Copyright 1999, 2000 Juergen Schmied
5 * Copyright 2005 Vitaliy Margolen
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.
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.
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
22 #include "config.h"
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
31 #include "ntstatus.h"
32 #define WIN32_NO_STATUS
33 #include "wine/debug.h"
34 #include "windef.h"
35 #include "winternl.h"
36 #include "ntdll_misc.h"
37 #include "wine/server.h"
38 #include "wine/exception.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
44 * Generic object functions
47 /******************************************************************************
48 * NtQueryObject [NTDLL.@]
49 * ZwQueryObject [NTDLL.@]
51 NTSTATUS WINAPI NtQueryObject(IN HANDLE handle,
52 IN OBJECT_INFORMATION_CLASS info_class,
53 OUT PVOID ptr, IN ULONG len, OUT PULONG used_len)
55 NTSTATUS status;
57 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", handle, info_class, ptr, len, used_len);
59 if (used_len) *used_len = 0;
61 switch (info_class)
63 case ObjectBasicInformation:
65 POBJECT_BASIC_INFORMATION p = ptr;
67 if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE;
69 SERVER_START_REQ( get_object_info )
71 req->handle = wine_server_obj_handle( handle );
72 status = wine_server_call( req );
73 if (status == STATUS_SUCCESS)
75 memset( p, 0, sizeof(*p) );
76 p->GrantedAccess = reply->access;
77 p->PointerCount = reply->ref_count;
78 p->HandleCount = reply->handle_count;
79 if (used_len) *used_len = sizeof(*p);
82 SERVER_END_REQ;
84 break;
85 case ObjectNameInformation:
87 OBJECT_NAME_INFORMATION* p = ptr;
88 ANSI_STRING unix_name;
90 /* first try as a file object */
92 if (!(status = server_get_unix_name( handle, &unix_name )))
94 UNICODE_STRING nt_name;
96 if (!(status = wine_unix_to_nt_file_name( &unix_name, &nt_name )))
98 if (len < sizeof(*p))
99 status = STATUS_INFO_LENGTH_MISMATCH;
100 else if (len < sizeof(*p) + nt_name.MaximumLength)
101 status = STATUS_BUFFER_OVERFLOW;
102 else
104 p->Name.Buffer = (WCHAR *)(p + 1);
105 p->Name.Length = nt_name.Length;
106 p->Name.MaximumLength = nt_name.MaximumLength;
107 memcpy( p->Name.Buffer, nt_name.Buffer, nt_name.MaximumLength );
109 if (used_len) *used_len = sizeof(*p) + nt_name.MaximumLength;
110 RtlFreeUnicodeString( &nt_name );
112 RtlFreeAnsiString( &unix_name );
113 break;
115 else if (status != STATUS_OBJECT_TYPE_MISMATCH) break;
117 /* not a file, treat as a generic object */
119 SERVER_START_REQ( get_object_info )
121 req->handle = wine_server_obj_handle( handle );
122 if (len > sizeof(*p)) wine_server_set_reply( req, p + 1, len - sizeof(*p) );
123 status = wine_server_call( req );
124 if (status == STATUS_SUCCESS)
126 if (!reply->total) /* no name */
128 if (sizeof(*p) > len) status = STATUS_INFO_LENGTH_MISMATCH;
129 else memset( p, 0, sizeof(*p) );
130 if (used_len) *used_len = sizeof(*p);
132 else if (sizeof(*p) + reply->total + sizeof(WCHAR) > len)
134 if (used_len) *used_len = sizeof(*p) + reply->total + sizeof(WCHAR);
135 status = STATUS_INFO_LENGTH_MISMATCH;
137 else
139 ULONG res = wine_server_reply_size( reply );
140 p->Name.Buffer = (WCHAR *)(p + 1);
141 p->Name.Length = res;
142 p->Name.MaximumLength = res + sizeof(WCHAR);
143 p->Name.Buffer[res / sizeof(WCHAR)] = 0;
144 if (used_len) *used_len = sizeof(*p) + p->Name.MaximumLength;
148 SERVER_END_REQ;
150 break;
151 case ObjectTypeInformation:
153 OBJECT_TYPE_INFORMATION *p = ptr;
155 SERVER_START_REQ( get_object_type )
157 req->handle = wine_server_obj_handle( handle );
158 if (len > sizeof(*p)) wine_server_set_reply( req, p + 1, len - sizeof(*p) );
159 status = wine_server_call( req );
160 if (status == STATUS_SUCCESS)
162 if (!reply->total) /* no name */
164 if (sizeof(*p) > len) status = STATUS_INFO_LENGTH_MISMATCH;
165 else memset( p, 0, sizeof(*p) );
166 if (used_len) *used_len = sizeof(*p);
168 else if (sizeof(*p) + reply->total + sizeof(WCHAR) > len)
170 if (used_len) *used_len = sizeof(*p) + reply->total + sizeof(WCHAR);
171 status = STATUS_INFO_LENGTH_MISMATCH;
173 else
175 ULONG res = wine_server_reply_size( reply );
176 p->TypeName.Buffer = (WCHAR *)(p + 1);
177 p->TypeName.Length = res;
178 p->TypeName.MaximumLength = res + sizeof(WCHAR);
179 p->TypeName.Buffer[res / sizeof(WCHAR)] = 0;
180 if (used_len) *used_len = sizeof(*p) + p->TypeName.MaximumLength;
184 SERVER_END_REQ;
186 break;
187 case ObjectDataInformation:
189 OBJECT_DATA_INFORMATION* p = ptr;
191 if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE;
193 SERVER_START_REQ( set_handle_info )
195 req->handle = wine_server_obj_handle( handle );
196 req->flags = 0;
197 req->mask = 0;
198 status = wine_server_call( req );
199 if (status == STATUS_SUCCESS)
201 p->InheritHandle = (reply->old_flags & HANDLE_FLAG_INHERIT) != 0;
202 p->ProtectFromClose = (reply->old_flags & HANDLE_FLAG_PROTECT_FROM_CLOSE) != 0;
203 if (used_len) *used_len = sizeof(*p);
206 SERVER_END_REQ;
208 break;
209 default:
210 FIXME("Unsupported information class %u\n", info_class);
211 status = STATUS_NOT_IMPLEMENTED;
212 break;
214 return status;
217 /******************************************************************
218 * NtSetInformationObject [NTDLL.@]
219 * ZwSetInformationObject [NTDLL.@]
222 NTSTATUS WINAPI NtSetInformationObject(IN HANDLE handle,
223 IN OBJECT_INFORMATION_CLASS info_class,
224 IN PVOID ptr, IN ULONG len)
226 NTSTATUS status;
228 TRACE("(%p,0x%08x,%p,0x%08x)\n", handle, info_class, ptr, len);
230 switch (info_class)
232 case ObjectDataInformation:
234 OBJECT_DATA_INFORMATION* p = ptr;
236 if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE;
238 SERVER_START_REQ( set_handle_info )
240 req->handle = wine_server_obj_handle( handle );
241 req->flags = 0;
242 req->mask = HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE;
243 if (p->InheritHandle) req->flags |= HANDLE_FLAG_INHERIT;
244 if (p->ProtectFromClose) req->flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE;
245 status = wine_server_call( req );
247 SERVER_END_REQ;
249 break;
250 default:
251 FIXME("Unsupported information class %u\n", info_class);
252 status = STATUS_NOT_IMPLEMENTED;
253 break;
255 return status;
258 /******************************************************************************
259 * NtQuerySecurityObject [NTDLL.@]
261 * An ntdll analogue to GetKernelObjectSecurity().
264 NTSTATUS WINAPI
265 NtQuerySecurityObject(
266 IN HANDLE Object,
267 IN SECURITY_INFORMATION RequestedInformation,
268 OUT PSECURITY_DESCRIPTOR pSecurityDescriptor,
269 IN ULONG Length,
270 OUT PULONG ResultLength)
272 PISECURITY_DESCRIPTOR_RELATIVE psd = pSecurityDescriptor;
273 NTSTATUS status;
274 unsigned int buffer_size = 512;
275 BOOLEAN need_more_memory;
277 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n",
278 Object, RequestedInformation, pSecurityDescriptor, Length, ResultLength);
282 char *buffer = RtlAllocateHeap(GetProcessHeap(), 0, buffer_size);
283 if (!buffer)
284 return STATUS_NO_MEMORY;
286 need_more_memory = FALSE;
288 SERVER_START_REQ( get_security_object )
290 req->handle = wine_server_obj_handle( Object );
291 req->security_info = RequestedInformation;
292 wine_server_set_reply( req, buffer, buffer_size );
293 status = wine_server_call( req );
294 if (status == STATUS_SUCCESS)
296 struct security_descriptor *sd = (struct security_descriptor *)buffer;
297 if (reply->sd_len)
299 *ResultLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
300 sd->owner_len + sd->group_len + sd->sacl_len + sd->dacl_len;
301 if (Length >= *ResultLength)
303 psd->Revision = SECURITY_DESCRIPTOR_REVISION;
304 psd->Sbz1 = 0;
305 psd->Control = sd->control | SE_SELF_RELATIVE;
306 psd->Owner = sd->owner_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) : 0;
307 psd->Group = sd->group_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sd->owner_len : 0;
308 psd->Sacl = sd->sacl_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sd->owner_len + sd->group_len : 0;
309 psd->Dacl = sd->dacl_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sd->owner_len + sd->group_len + sd->sacl_len : 0;
310 /* owner, group, sacl and dacl are the same type as in the server
311 * and in the same order so we copy the memory in one block */
312 memcpy((char *)pSecurityDescriptor + sizeof(SECURITY_DESCRIPTOR_RELATIVE),
313 buffer + sizeof(struct security_descriptor),
314 sd->owner_len + sd->group_len + sd->sacl_len + sd->dacl_len);
316 else
317 status = STATUS_BUFFER_TOO_SMALL;
319 else
321 *ResultLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
322 if (Length >= *ResultLength)
324 memset(psd, 0, sizeof(*psd));
325 psd->Revision = SECURITY_DESCRIPTOR_REVISION;
326 psd->Control = SE_SELF_RELATIVE;
328 else
329 status = STATUS_BUFFER_TOO_SMALL;
332 else if (status == STATUS_BUFFER_TOO_SMALL)
334 buffer_size = reply->sd_len;
335 need_more_memory = TRUE;
338 SERVER_END_REQ;
339 RtlFreeHeap(GetProcessHeap(), 0, buffer);
340 } while (need_more_memory);
342 return status;
346 /******************************************************************************
347 * NtDuplicateObject [NTDLL.@]
348 * ZwDuplicateObject [NTDLL.@]
350 NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source,
351 HANDLE dest_process, PHANDLE dest,
352 ACCESS_MASK access, ULONG attributes, ULONG options )
354 NTSTATUS ret;
355 SERVER_START_REQ( dup_handle )
357 req->src_process = wine_server_obj_handle( source_process );
358 req->src_handle = wine_server_obj_handle( source );
359 req->dst_process = wine_server_obj_handle( dest_process );
360 req->access = access;
361 req->attributes = attributes;
362 req->options = options;
364 if (!(ret = wine_server_call( req )))
366 if (dest) *dest = wine_server_ptr_handle( reply->handle );
367 if (reply->closed && reply->self)
369 int fd = server_remove_fd_from_cache( source );
370 if (fd != -1) close( fd );
374 SERVER_END_REQ;
375 return ret;
378 static LONG WINAPI invalid_handle_exception_handler( EXCEPTION_POINTERS *eptr )
380 EXCEPTION_RECORD *rec = eptr->ExceptionRecord;
381 return (rec->ExceptionCode == EXCEPTION_INVALID_HANDLE) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
384 /* Everquest 2 / Pirates of the Burning Sea hooks NtClose, so we need a wrapper */
385 NTSTATUS close_handle( HANDLE handle )
387 NTSTATUS ret;
388 int fd = server_remove_fd_from_cache( handle );
390 SERVER_START_REQ( close_handle )
392 req->handle = wine_server_obj_handle( handle );
393 ret = wine_server_call( req );
395 SERVER_END_REQ;
396 if (fd != -1) close( fd );
398 if (ret == STATUS_INVALID_HANDLE && handle && NtCurrentTeb()->Peb->BeingDebugged)
400 __TRY
402 EXCEPTION_RECORD record;
403 record.ExceptionCode = EXCEPTION_INVALID_HANDLE;
404 record.ExceptionFlags = 0;
405 record.ExceptionRecord = NULL;
406 record.ExceptionAddress = NULL;
407 record.NumberParameters = 0;
408 RtlRaiseException( &record );
410 __EXCEPT(invalid_handle_exception_handler)
413 __ENDTRY
416 return ret;
419 /**************************************************************************
420 * NtClose [NTDLL.@]
422 * Close a handle reference to an object.
424 * PARAMS
425 * Handle [I] handle to close
427 * RETURNS
428 * Success: ERROR_SUCCESS.
429 * Failure: An NTSTATUS error code.
431 NTSTATUS WINAPI NtClose( HANDLE Handle )
433 return close_handle( Handle );
437 * Directory functions
440 /**************************************************************************
441 * NtOpenDirectoryObject [NTDLL.@]
442 * ZwOpenDirectoryObject [NTDLL.@]
444 * Open a namespace directory object.
446 * PARAMS
447 * DirectoryHandle [O] Destination for the new directory handle
448 * DesiredAccess [I] Desired access to the directory
449 * ObjectAttributes [I] Structure describing the directory
451 * RETURNS
452 * Success: ERROR_SUCCESS.
453 * Failure: An NTSTATUS error code.
455 NTSTATUS WINAPI NtOpenDirectoryObject( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr)
457 NTSTATUS ret;
459 if (!handle) return STATUS_ACCESS_VIOLATION;
460 if ((ret = validate_open_object_attributes( attr ))) return ret;
462 TRACE("(%p,0x%08x,%s)\n", handle, access, debugstr_ObjectAttributes(attr));
464 SERVER_START_REQ(open_directory)
466 req->access = access;
467 req->attributes = attr->Attributes;
468 req->rootdir = wine_server_obj_handle( attr->RootDirectory );
469 if (attr->ObjectName)
470 wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
471 ret = wine_server_call( req );
472 *handle = wine_server_ptr_handle( reply->handle );
474 SERVER_END_REQ;
475 return ret;
478 /******************************************************************************
479 * NtCreateDirectoryObject [NTDLL.@]
480 * ZwCreateDirectoryObject [NTDLL.@]
482 * Create a namespace directory object.
484 * PARAMS
485 * DirectoryHandle [O] Destination for the new directory handle
486 * DesiredAccess [I] Desired access to the directory
487 * ObjectAttributes [I] Structure describing the directory
489 * RETURNS
490 * Success: ERROR_SUCCESS.
491 * Failure: An NTSTATUS error code.
493 NTSTATUS WINAPI NtCreateDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess,
494 OBJECT_ATTRIBUTES *attr )
496 NTSTATUS ret;
497 data_size_t len;
498 struct object_attributes *objattr;
500 if (!DirectoryHandle) return STATUS_ACCESS_VIOLATION;
501 TRACE("(%p,0x%08x,%s)\n", DirectoryHandle, DesiredAccess, debugstr_ObjectAttributes(attr));
503 if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
505 SERVER_START_REQ(create_directory)
507 req->access = DesiredAccess;
508 wine_server_add_data( req, objattr, len );
509 ret = wine_server_call( req );
510 *DirectoryHandle = wine_server_ptr_handle( reply->handle );
512 SERVER_END_REQ;
514 RtlFreeHeap( GetProcessHeap(), 0, objattr );
515 return ret;
518 /******************************************************************************
519 * NtQueryDirectoryObject [NTDLL.@]
520 * ZwQueryDirectoryObject [NTDLL.@]
522 * Read information from a namespace directory.
524 * PARAMS
525 * handle [I] Handle to a directory object
526 * buffer [O] Buffer to hold the read data
527 * size [I] Size of the buffer in bytes
528 * single_entry [I] If TRUE, return a single entry, if FALSE, return as many as fit in the buffer
529 * restart [I] If TRUE, start scanning from the start, if FALSE, scan from Context
530 * context [I/O] Indicates what point of the directory the scan is at
531 * ret_size [O] Caller supplied storage for the number of bytes written (or NULL)
533 * RETURNS
534 * Success: ERROR_SUCCESS.
535 * Failure: An NTSTATUS error code.
537 NTSTATUS WINAPI NtQueryDirectoryObject(HANDLE handle, PDIRECTORY_BASIC_INFORMATION buffer,
538 ULONG size, BOOLEAN single_entry, BOOLEAN restart,
539 PULONG context, PULONG ret_size)
541 NTSTATUS ret;
543 if (restart) *context = 0;
545 if (single_entry)
547 if (size <= sizeof(*buffer) + 2*sizeof(WCHAR)) return STATUS_BUFFER_OVERFLOW;
549 SERVER_START_REQ( get_directory_entry )
551 req->handle = wine_server_obj_handle( handle );
552 req->index = *context;
553 wine_server_set_reply( req, buffer + 1, size - sizeof(*buffer) - 2*sizeof(WCHAR) );
554 if (!(ret = wine_server_call( req )))
556 buffer->ObjectName.Buffer = (WCHAR *)(buffer + 1);
557 buffer->ObjectName.Length = reply->name_len;
558 buffer->ObjectName.MaximumLength = reply->name_len + sizeof(WCHAR);
559 buffer->ObjectTypeName.Buffer = (WCHAR *)(buffer + 1) + reply->name_len/sizeof(WCHAR) + 1;
560 buffer->ObjectTypeName.Length = wine_server_reply_size( reply ) - reply->name_len;
561 buffer->ObjectTypeName.MaximumLength = buffer->ObjectTypeName.Length + sizeof(WCHAR);
562 /* make room for the terminating null */
563 memmove( buffer->ObjectTypeName.Buffer, buffer->ObjectTypeName.Buffer - 1,
564 buffer->ObjectTypeName.Length );
565 buffer->ObjectName.Buffer[buffer->ObjectName.Length/sizeof(WCHAR)] = 0;
566 buffer->ObjectTypeName.Buffer[buffer->ObjectTypeName.Length/sizeof(WCHAR)] = 0;
567 (*context)++;
570 SERVER_END_REQ;
571 if (ret_size)
572 *ret_size = buffer->ObjectName.MaximumLength + buffer->ObjectTypeName.MaximumLength + sizeof(*buffer);
574 else
576 FIXME("multiple entries not implemented\n");
577 ret = STATUS_NOT_IMPLEMENTED;
580 return ret;
584 * Link objects
587 /******************************************************************************
588 * NtOpenSymbolicLinkObject [NTDLL.@]
589 * ZwOpenSymbolicLinkObject [NTDLL.@]
591 * Open a namespace symbolic link object.
593 * PARAMS
594 * LinkHandle [O] Destination for the new symbolic link handle
595 * DesiredAccess [I] Desired access to the symbolic link
596 * ObjectAttributes [I] Structure describing the symbolic link
598 * RETURNS
599 * Success: ERROR_SUCCESS.
600 * Failure: An NTSTATUS error code.
602 NTSTATUS WINAPI NtOpenSymbolicLinkObject( HANDLE *handle, ACCESS_MASK access,
603 const OBJECT_ATTRIBUTES *attr)
605 NTSTATUS ret;
607 TRACE("(%p,0x%08x,%s)\n", handle, access, debugstr_ObjectAttributes(attr));
609 if (!handle) return STATUS_ACCESS_VIOLATION;
610 if ((ret = validate_open_object_attributes( attr ))) return ret;
612 SERVER_START_REQ(open_symlink)
614 req->access = access;
615 req->attributes = attr->Attributes;
616 req->rootdir = wine_server_obj_handle( attr->RootDirectory );
617 if (attr->ObjectName)
618 wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
619 ret = wine_server_call( req );
620 *handle = wine_server_ptr_handle( reply->handle );
622 SERVER_END_REQ;
623 return ret;
626 /******************************************************************************
627 * NtCreateSymbolicLinkObject [NTDLL.@]
628 * ZwCreateSymbolicLinkObject [NTDLL.@]
630 * Open a namespace symbolic link object.
632 * PARAMS
633 * SymbolicLinkHandle [O] Destination for the new symbolic link handle
634 * DesiredAccess [I] Desired access to the symbolic link
635 * ObjectAttributes [I] Structure describing the symbolic link
636 * TargetName [I] Name of the target symbolic link points to
638 * RETURNS
639 * Success: ERROR_SUCCESS.
640 * Failure: An NTSTATUS error code.
642 NTSTATUS WINAPI NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle,IN ACCESS_MASK DesiredAccess,
643 POBJECT_ATTRIBUTES attr, PUNICODE_STRING TargetName)
645 NTSTATUS ret;
646 data_size_t len;
647 struct object_attributes *objattr;
649 if (!SymbolicLinkHandle || !attr || !TargetName) return STATUS_ACCESS_VIOLATION;
650 if (!TargetName->Buffer) return STATUS_INVALID_PARAMETER;
652 TRACE("(%p,0x%08x,%s -> %s)\n", SymbolicLinkHandle, DesiredAccess,
653 debugstr_ObjectAttributes(attr), debugstr_us(TargetName));
655 if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
657 SERVER_START_REQ(create_symlink)
659 req->access = DesiredAccess;
660 wine_server_add_data( req, objattr, len );
661 wine_server_add_data(req, TargetName->Buffer, TargetName->Length);
662 ret = wine_server_call( req );
663 *SymbolicLinkHandle = wine_server_ptr_handle( reply->handle );
665 SERVER_END_REQ;
667 RtlFreeHeap( GetProcessHeap(), 0, objattr );
668 return ret;
671 /******************************************************************************
672 * NtQuerySymbolicLinkObject [NTDLL.@]
673 * ZwQuerySymbolicLinkObject [NTDLL.@]
675 * Query a namespace symbolic link object target name.
677 * PARAMS
678 * handle [I] Handle to a symbolic link object
679 * target [O] Destination for the symbolic link target
680 * length [O] Size of returned data
682 * RETURNS
683 * Success: ERROR_SUCCESS.
684 * Failure: An NTSTATUS error code.
686 NTSTATUS WINAPI NtQuerySymbolicLinkObject( HANDLE handle, PUNICODE_STRING target, PULONG length )
688 NTSTATUS ret;
690 TRACE("(%p,%p,%p)\n", handle, target, length );
692 if (!target) return STATUS_ACCESS_VIOLATION;
694 SERVER_START_REQ(query_symlink)
696 req->handle = wine_server_obj_handle( handle );
697 if (target->MaximumLength >= sizeof(WCHAR))
698 wine_server_set_reply( req, target->Buffer, target->MaximumLength - sizeof(WCHAR) );
699 if (!(ret = wine_server_call( req )))
701 target->Length = wine_server_reply_size(reply);
702 target->Buffer[target->Length / sizeof(WCHAR)] = 0;
703 if (length) *length = reply->total + sizeof(WCHAR);
705 else if (length && ret == STATUS_BUFFER_TOO_SMALL) *length = reply->total + sizeof(WCHAR);
707 SERVER_END_REQ;
708 return ret;
711 /******************************************************************************
712 * NtAllocateUuids [NTDLL.@]
714 NTSTATUS WINAPI NtAllocateUuids( ULARGE_INTEGER *time, ULONG *delta, ULONG *sequence, UCHAR *seed )
716 FIXME("(%p,%p,%p,%p), stub.\n", time, delta, sequence, seed);
717 return STATUS_SUCCESS;
720 /**************************************************************************
721 * NtMakeTemporaryObject [NTDLL.@]
722 * ZwMakeTemporaryObject [NTDLL.@]
724 * Make a permanent object temporary.
726 * PARAMS
727 * Handle [I] handle to permanent object
729 * RETURNS
730 * Success: STATUS_SUCCESS.
731 * Failure: An NTSTATUS error code.
733 NTSTATUS WINAPI NtMakeTemporaryObject( HANDLE Handle )
735 FIXME("(%p), stub.\n", Handle);
736 return STATUS_SUCCESS;