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
35 #define WIN32_NO_STATUS
36 #include "wine/debug.h"
39 #include "ntdll_misc.h"
40 #include "wine/server.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
46 * Generic object functions
49 /******************************************************************************
50 * NtQueryObject [NTDLL.@]
51 * ZwQueryObject [NTDLL.@]
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)
59 TRACE("(%p,0x%08x,%p,0x%08x,%p): stub\n",
60 handle, info_class, ptr, len, used_len);
62 if (used_len) *used_len = 0;
66 case ObjectBasicInformation:
68 POBJECT_BASIC_INFORMATION p = ptr;
70 if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE;
72 SERVER_START_REQ( get_object_info )
74 req->handle = wine_server_obj_handle( handle );
75 status = wine_server_call( req );
76 if (status == STATUS_SUCCESS)
78 memset( p, 0, sizeof(*p) );
79 p->GrantedAccess = reply->access;
80 p->PointerCount = reply->ref_count;
81 p->HandleCount = 1; /* at least one */
82 if (used_len) *used_len = sizeof(*p);
88 case ObjectNameInformation:
90 OBJECT_NAME_INFORMATION* p = ptr;
91 ANSI_STRING unix_name;
93 /* first try as a file object */
95 if (!(status = server_get_unix_name( handle, &unix_name )))
97 UNICODE_STRING nt_name;
100 if (!(status = wine_unix_to_nt_file_name( &unix_name, &nt_name )))
102 if (sizeof(*p) + nt_name.MaximumLength <= len)
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 else status = STATUS_INFO_LENGTH_MISMATCH;
110 if (used_len) *used_len = sizeof(*p) + nt_name.MaximumLength;
111 RtlFreeUnicodeString( &nt_name );
113 RtlFreeAnsiString( &unix_name );
116 else if (status != STATUS_OBJECT_TYPE_MISMATCH) break;
118 /* not a file, treat as a generic object */
120 SERVER_START_REQ( get_object_info )
122 req->handle = wine_server_obj_handle( handle );
123 if (len > sizeof(*p)) wine_server_set_reply( req, p + 1, len - sizeof(*p) );
124 status = wine_server_call( req );
125 if (status == STATUS_SUCCESS)
127 if (!reply->total) /* no name */
129 if (sizeof(*p) > len) status = STATUS_INFO_LENGTH_MISMATCH;
130 else memset( p, 0, sizeof(*p) );
131 if (used_len) *used_len = sizeof(*p);
133 else if (sizeof(*p) + reply->total + sizeof(WCHAR) > len)
135 if (used_len) *used_len = sizeof(*p) + reply->total + sizeof(WCHAR);
136 status = STATUS_INFO_LENGTH_MISMATCH;
140 ULONG res = wine_server_reply_size( reply );
141 p->Name.Buffer = (WCHAR *)(p + 1);
142 p->Name.Length = res;
143 p->Name.MaximumLength = res + sizeof(WCHAR);
144 p->Name.Buffer[res / sizeof(WCHAR)] = 0;
145 if (used_len) *used_len = sizeof(*p) + p->Name.MaximumLength;
152 case ObjectDataInformation:
154 OBJECT_DATA_INFORMATION* p = ptr;
156 if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE;
158 SERVER_START_REQ( set_handle_info )
160 req->handle = wine_server_obj_handle( handle );
163 status = wine_server_call( req );
164 if (status == STATUS_SUCCESS)
166 p->InheritHandle = (reply->old_flags & HANDLE_FLAG_INHERIT) ? TRUE : FALSE;
167 p->ProtectFromClose = (reply->old_flags & HANDLE_FLAG_PROTECT_FROM_CLOSE) ? TRUE : FALSE;
168 if (used_len) *used_len = sizeof(*p);
175 FIXME("Unsupported information class %u\n", info_class);
176 status = STATUS_NOT_IMPLEMENTED;
182 /******************************************************************
183 * NtSetInformationObject [NTDLL.@]
184 * ZwSetInformationObject [NTDLL.@]
187 NTSTATUS WINAPI NtSetInformationObject(IN HANDLE handle,
188 IN OBJECT_INFORMATION_CLASS info_class,
189 IN PVOID ptr, IN ULONG len)
193 TRACE("(%p,0x%08x,%p,0x%08x): stub\n",
194 handle, info_class, ptr, len);
198 case ObjectDataInformation:
200 OBJECT_DATA_INFORMATION* p = ptr;
202 if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE;
204 SERVER_START_REQ( set_handle_info )
206 req->handle = wine_server_obj_handle( handle );
208 req->mask = HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE;
209 if (p->InheritHandle) req->flags |= HANDLE_FLAG_INHERIT;
210 if (p->ProtectFromClose) req->flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE;
211 status = wine_server_call( req );
217 FIXME("Unsupported information class %u\n", info_class);
218 status = STATUS_NOT_IMPLEMENTED;
224 /******************************************************************************
225 * NtQuerySecurityObject [NTDLL.@]
227 * An ntdll analogue to GetKernelObjectSecurity().
231 NtQuerySecurityObject(
233 IN SECURITY_INFORMATION RequestedInformation,
234 OUT PSECURITY_DESCRIPTOR pSecurityDescriptor,
236 OUT PULONG ResultLength)
238 PISECURITY_DESCRIPTOR_RELATIVE psd = pSecurityDescriptor;
240 unsigned int buffer_size = 512;
241 BOOLEAN need_more_memory;
243 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n",
244 Object, RequestedInformation, pSecurityDescriptor, Length, ResultLength);
248 char *buffer = RtlAllocateHeap(GetProcessHeap(), 0, buffer_size);
250 return STATUS_NO_MEMORY;
252 need_more_memory = FALSE;
254 SERVER_START_REQ( get_security_object )
256 req->handle = wine_server_obj_handle( Object );
257 req->security_info = RequestedInformation;
258 wine_server_set_reply( req, buffer, buffer_size );
259 status = wine_server_call( req );
260 if (status == STATUS_SUCCESS)
262 struct security_descriptor *sd = (struct security_descriptor *)buffer;
265 *ResultLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
266 sd->owner_len + sd->group_len + sd->sacl_len + sd->dacl_len;
267 if (Length >= *ResultLength)
269 psd->Revision = SECURITY_DESCRIPTOR_REVISION;
271 psd->Control = sd->control | SE_SELF_RELATIVE;
272 psd->Owner = sd->owner_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) : 0;
273 psd->Group = sd->group_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sd->owner_len : 0;
274 psd->Sacl = sd->sacl_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sd->owner_len + sd->group_len : 0;
275 psd->Dacl = sd->dacl_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sd->owner_len + sd->group_len + sd->sacl_len : 0;
276 /* owner, group, sacl and dacl are the same type as in the server
277 * and in the same order so we copy the memory in one block */
278 memcpy((char *)pSecurityDescriptor + sizeof(SECURITY_DESCRIPTOR_RELATIVE),
279 buffer + sizeof(struct security_descriptor),
280 sd->owner_len + sd->group_len + sd->sacl_len + sd->dacl_len);
283 status = STATUS_BUFFER_TOO_SMALL;
287 *ResultLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
288 if (Length >= *ResultLength)
290 memset(psd, 0, sizeof(*psd));
291 psd->Revision = SECURITY_DESCRIPTOR_REVISION;
292 psd->Control = SE_SELF_RELATIVE;
295 status = STATUS_BUFFER_TOO_SMALL;
298 else if (status == STATUS_BUFFER_TOO_SMALL)
300 buffer_size = reply->sd_len;
301 need_more_memory = TRUE;
305 RtlFreeHeap(GetProcessHeap(), 0, buffer);
306 } while (need_more_memory);
312 /******************************************************************************
313 * NtDuplicateObject [NTDLL.@]
314 * ZwDuplicateObject [NTDLL.@]
316 NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source,
317 HANDLE dest_process, PHANDLE dest,
318 ACCESS_MASK access, ULONG attributes, ULONG options )
321 SERVER_START_REQ( dup_handle )
323 req->src_process = wine_server_obj_handle( source_process );
324 req->src_handle = wine_server_obj_handle( source );
325 req->dst_process = wine_server_obj_handle( dest_process );
326 req->access = access;
327 req->attributes = attributes;
328 req->options = options;
330 if (!(ret = wine_server_call( req )))
332 if (dest) *dest = wine_server_ptr_handle( reply->handle );
337 int fd = server_remove_fd_from_cache( source );
338 if (fd != -1) close( fd );
341 else if (options & DUPLICATE_CLOSE_SOURCE)
342 WARN( "failed to close handle %p in process %p\n", source, source_process );
349 /**************************************************************************
352 * Close a handle reference to an object.
355 * Handle [I] handle to close
358 * Success: ERROR_SUCCESS.
359 * Failure: An NTSTATUS error code.
361 NTSTATUS WINAPI NtClose( HANDLE Handle )
364 int fd = server_remove_fd_from_cache( Handle );
366 SERVER_START_REQ( close_handle )
368 req->handle = wine_server_obj_handle( Handle );
369 ret = wine_server_call( req );
372 if (fd != -1) close( fd );
377 * Directory functions
380 /**************************************************************************
381 * NtOpenDirectoryObject [NTDLL.@]
382 * ZwOpenDirectoryObject [NTDLL.@]
384 * Open a namespace directory object.
387 * DirectoryHandle [O] Destination for the new directory handle
388 * DesiredAccess [I] Desired access to the directory
389 * ObjectAttributes [I] Structure describing the directory
392 * Success: ERROR_SUCCESS.
393 * Failure: An NTSTATUS error code.
395 NTSTATUS WINAPI NtOpenDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess,
396 POBJECT_ATTRIBUTES ObjectAttributes)
399 TRACE("(%p,0x%08x,%s)\n", DirectoryHandle, DesiredAccess, debugstr_ObjectAttributes(ObjectAttributes));
401 if (!DirectoryHandle) return STATUS_ACCESS_VIOLATION;
402 if (!ObjectAttributes) return STATUS_INVALID_PARAMETER;
403 /* Have to test it here because server won't know difference between
404 * ObjectName == NULL and ObjectName == "" */
405 if (!ObjectAttributes->ObjectName)
407 if (ObjectAttributes->RootDirectory)
408 return STATUS_OBJECT_NAME_INVALID;
410 return STATUS_OBJECT_PATH_SYNTAX_BAD;
413 SERVER_START_REQ(open_directory)
415 req->access = DesiredAccess;
416 req->attributes = ObjectAttributes->Attributes;
417 req->rootdir = wine_server_obj_handle( ObjectAttributes->RootDirectory );
418 if (ObjectAttributes->ObjectName)
419 wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
420 ObjectAttributes->ObjectName->Length);
421 ret = wine_server_call( req );
422 *DirectoryHandle = wine_server_ptr_handle( reply->handle );
428 /******************************************************************************
429 * NtCreateDirectoryObject [NTDLL.@]
430 * ZwCreateDirectoryObject [NTDLL.@]
432 * Create a namespace directory object.
435 * DirectoryHandle [O] Destination for the new directory handle
436 * DesiredAccess [I] Desired access to the directory
437 * ObjectAttributes [I] Structure describing the directory
440 * Success: ERROR_SUCCESS.
441 * Failure: An NTSTATUS error code.
443 NTSTATUS WINAPI NtCreateDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess,
444 POBJECT_ATTRIBUTES ObjectAttributes)
447 TRACE("(%p,0x%08x,%s)\n", DirectoryHandle, DesiredAccess, debugstr_ObjectAttributes(ObjectAttributes));
449 if (!DirectoryHandle) return STATUS_ACCESS_VIOLATION;
451 SERVER_START_REQ(create_directory)
453 req->access = DesiredAccess;
454 req->attributes = ObjectAttributes ? ObjectAttributes->Attributes : 0;
455 req->rootdir = wine_server_obj_handle( ObjectAttributes ? ObjectAttributes->RootDirectory : 0 );
456 if (ObjectAttributes && ObjectAttributes->ObjectName)
457 wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
458 ObjectAttributes->ObjectName->Length);
459 ret = wine_server_call( req );
460 *DirectoryHandle = wine_server_ptr_handle( reply->handle );
466 /******************************************************************************
467 * NtQueryDirectoryObject [NTDLL.@]
468 * ZwQueryDirectoryObject [NTDLL.@]
470 * Read information from a namespace directory.
473 * handle [I] Handle to a directory object
474 * buffer [O] Buffer to hold the read data
475 * size [I] Size of the buffer in bytes
476 * single_entry [I] If TRUE, return a single entry, if FALSE, return as many as fit in the buffer
477 * restart [I] If TRUE, start scanning from the start, if FALSE, scan from Context
478 * context [I/O] Indicates what point of the directory the scan is at
479 * ret_size [O] Caller supplied storage for the number of bytes written (or NULL)
482 * Success: ERROR_SUCCESS.
483 * Failure: An NTSTATUS error code.
485 NTSTATUS WINAPI NtQueryDirectoryObject(HANDLE handle, PDIRECTORY_BASIC_INFORMATION buffer,
486 ULONG size, BOOLEAN single_entry, BOOLEAN restart,
487 PULONG context, PULONG ret_size)
491 if (restart) *context = 0;
495 if (size <= sizeof(*buffer) + 2*sizeof(WCHAR)) return STATUS_BUFFER_OVERFLOW;
497 SERVER_START_REQ( get_directory_entry )
499 req->handle = wine_server_obj_handle( handle );
500 req->index = *context;
501 wine_server_set_reply( req, buffer + 1, size - sizeof(*buffer) - 2*sizeof(WCHAR) );
502 if (!(ret = wine_server_call( req )))
504 buffer->ObjectName.Buffer = (WCHAR *)(buffer + 1);
505 buffer->ObjectName.Length = reply->name_len;
506 buffer->ObjectName.MaximumLength = reply->name_len + sizeof(WCHAR);
507 buffer->ObjectTypeName.Buffer = (WCHAR *)(buffer + 1) + reply->name_len/sizeof(WCHAR) + 1;
508 buffer->ObjectTypeName.Length = wine_server_reply_size( reply ) - reply->name_len;
509 buffer->ObjectTypeName.MaximumLength = buffer->ObjectTypeName.Length + sizeof(WCHAR);
510 /* make room for the terminating null */
511 memmove( buffer->ObjectTypeName.Buffer, buffer->ObjectTypeName.Buffer - 1,
512 buffer->ObjectTypeName.Length );
513 buffer->ObjectName.Buffer[buffer->ObjectName.Length/sizeof(WCHAR)] = 0;
514 buffer->ObjectTypeName.Buffer[buffer->ObjectTypeName.Length/sizeof(WCHAR)] = 0;
520 *ret_size = buffer->ObjectName.MaximumLength + buffer->ObjectTypeName.MaximumLength + sizeof(*buffer);
524 FIXME("multiple entries not implemented\n");
525 ret = STATUS_NOT_IMPLEMENTED;
535 /******************************************************************************
536 * NtOpenSymbolicLinkObject [NTDLL.@]
537 * ZwOpenSymbolicLinkObject [NTDLL.@]
539 * Open a namespace symbolic link object.
542 * LinkHandle [O] Destination for the new symbolic link handle
543 * DesiredAccess [I] Desired access to the symbolic link
544 * ObjectAttributes [I] Structure describing the symbolic link
547 * Success: ERROR_SUCCESS.
548 * Failure: An NTSTATUS error code.
550 NTSTATUS WINAPI NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle, IN ACCESS_MASK DesiredAccess,
551 IN POBJECT_ATTRIBUTES ObjectAttributes)
554 TRACE("(%p,0x%08x,%s)\n",LinkHandle, DesiredAccess, debugstr_ObjectAttributes(ObjectAttributes));
556 if (!LinkHandle) return STATUS_ACCESS_VIOLATION;
557 if (!ObjectAttributes) return STATUS_INVALID_PARAMETER;
558 /* Have to test it here because server won't know difference between
559 * ObjectName == NULL and ObjectName == "" */
560 if (!ObjectAttributes->ObjectName)
562 if (ObjectAttributes->RootDirectory)
563 return STATUS_OBJECT_NAME_INVALID;
565 return STATUS_OBJECT_PATH_SYNTAX_BAD;
568 SERVER_START_REQ(open_symlink)
570 req->access = DesiredAccess;
571 req->attributes = ObjectAttributes->Attributes;
572 req->rootdir = wine_server_obj_handle( ObjectAttributes->RootDirectory );
573 if (ObjectAttributes->ObjectName)
574 wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
575 ObjectAttributes->ObjectName->Length);
576 ret = wine_server_call( req );
577 *LinkHandle = wine_server_ptr_handle( reply->handle );
583 /******************************************************************************
584 * NtCreateSymbolicLinkObject [NTDLL.@]
585 * ZwCreateSymbolicLinkObject [NTDLL.@]
587 * Open a namespace symbolic link object.
590 * SymbolicLinkHandle [O] Destination for the new symbolic link handle
591 * DesiredAccess [I] Desired access to the symbolic link
592 * ObjectAttributes [I] Structure describing the symbolic link
593 * TargetName [I] Name of the target symbolic link points to
596 * Success: ERROR_SUCCESS.
597 * Failure: An NTSTATUS error code.
599 NTSTATUS WINAPI NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle,IN ACCESS_MASK DesiredAccess,
600 IN POBJECT_ATTRIBUTES ObjectAttributes,
601 IN PUNICODE_STRING TargetName)
605 if (!SymbolicLinkHandle || !TargetName) return STATUS_ACCESS_VIOLATION;
606 if (!TargetName->Buffer) return STATUS_INVALID_PARAMETER;
608 TRACE("(%p,0x%08x,%s -> %s)\n", SymbolicLinkHandle, DesiredAccess,
609 debugstr_ObjectAttributes(ObjectAttributes), debugstr_us(TargetName));
611 SERVER_START_REQ(create_symlink)
613 req->access = DesiredAccess;
614 req->attributes = ObjectAttributes ? ObjectAttributes->Attributes : 0;
615 req->rootdir = wine_server_obj_handle( ObjectAttributes ? ObjectAttributes->RootDirectory : 0 );
616 if (ObjectAttributes && ObjectAttributes->ObjectName)
618 req->name_len = ObjectAttributes->ObjectName->Length;
619 wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
620 ObjectAttributes->ObjectName->Length);
624 wine_server_add_data(req, TargetName->Buffer, TargetName->Length);
625 ret = wine_server_call( req );
626 *SymbolicLinkHandle = wine_server_ptr_handle( reply->handle );
632 /******************************************************************************
633 * NtQuerySymbolicLinkObject [NTDLL.@]
634 * ZwQuerySymbolicLinkObject [NTDLL.@]
636 * Query a namespace symbolic link object target name.
639 * LinkHandle [I] Handle to a symbolic link object
640 * LinkTarget [O] Destination for the symbolic link target
641 * ReturnedLength [O] Size of returned data
644 * Success: ERROR_SUCCESS.
645 * Failure: An NTSTATUS error code.
647 NTSTATUS WINAPI NtQuerySymbolicLinkObject(IN HANDLE LinkHandle, IN OUT PUNICODE_STRING LinkTarget,
648 OUT PULONG ReturnedLength OPTIONAL)
651 TRACE("(%p,%p,%p)\n", LinkHandle, LinkTarget, ReturnedLength);
653 if (!LinkTarget) return STATUS_ACCESS_VIOLATION;
655 SERVER_START_REQ(query_symlink)
657 req->handle = wine_server_obj_handle( LinkHandle );
658 wine_server_set_reply( req, LinkTarget->Buffer, LinkTarget->MaximumLength );
659 if (!(ret = wine_server_call( req )))
661 LinkTarget->Length = wine_server_reply_size(reply);
662 if (ReturnedLength) *ReturnedLength = LinkTarget->Length;
669 /******************************************************************************
670 * NtAllocateUuids [NTDLL.@]
672 NTSTATUS WINAPI NtAllocateUuids(
673 PULARGE_INTEGER Time,
677 FIXME("(%p,%p,%p), stub.\n", Time, Range, Sequence);
681 /**************************************************************************
682 * NtMakeTemporaryObject [NTDLL.@]
683 * ZwMakeTemporaryObject [NTDLL.@]
685 * Make a permanent object temporary.
688 * Handle [I] handle to permanent object
691 * Success: STATUS_SUCCESS.
692 * Failure: An NTSTATUS error code.
694 NTSTATUS WINAPI NtMakeTemporaryObject( HANDLE Handle )
696 FIXME("(%p), stub.\n", Handle);
697 return STATUS_SUCCESS;