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
= (POBJECT_BASIC_INFORMATION
)ptr
;
70 if (len
< sizeof(*p
)) return STATUS_INVALID_BUFFER_SIZE
;
72 SERVER_START_REQ( get_object_info
)
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 ObjectDataInformation
:
90 OBJECT_DATA_INFORMATION
* p
= (OBJECT_DATA_INFORMATION
*)ptr
;
92 if (len
< sizeof(*p
)) return STATUS_INVALID_BUFFER_SIZE
;
94 SERVER_START_REQ( set_handle_info
)
99 status
= wine_server_call( req
);
100 if (status
== STATUS_SUCCESS
)
102 p
->InheritHandle
= (reply
->old_flags
& HANDLE_FLAG_INHERIT
) ? TRUE
: FALSE
;
103 p
->ProtectFromClose
= (reply
->old_flags
& HANDLE_FLAG_PROTECT_FROM_CLOSE
) ? TRUE
: FALSE
;
104 if (used_len
) *used_len
= sizeof(*p
);
111 FIXME("Unsupported information class %u\n", info_class
);
112 status
= STATUS_NOT_IMPLEMENTED
;
118 /******************************************************************
119 * NtSetInformationObject [NTDLL.@]
120 * ZwSetInformationObject [NTDLL.@]
123 NTSTATUS WINAPI
NtSetInformationObject(IN HANDLE handle
,
124 IN OBJECT_INFORMATION_CLASS info_class
,
125 IN PVOID ptr
, IN ULONG len
)
129 TRACE("(%p,0x%08x,%p,0x%08x): stub\n",
130 handle
, info_class
, ptr
, len
);
134 case ObjectDataInformation
:
136 OBJECT_DATA_INFORMATION
* p
= (OBJECT_DATA_INFORMATION
*)ptr
;
138 if (len
< sizeof(*p
)) return STATUS_INVALID_BUFFER_SIZE
;
140 SERVER_START_REQ( set_handle_info
)
142 req
->handle
= handle
;
144 req
->mask
= HANDLE_FLAG_INHERIT
| HANDLE_FLAG_PROTECT_FROM_CLOSE
;
145 if (p
->InheritHandle
) req
->flags
|= HANDLE_FLAG_INHERIT
;
146 if (p
->ProtectFromClose
) req
->flags
|= HANDLE_FLAG_PROTECT_FROM_CLOSE
;
147 status
= wine_server_call( req
);
153 FIXME("Unsupported information class %u\n", info_class
);
154 status
= STATUS_NOT_IMPLEMENTED
;
160 /******************************************************************************
161 * NtQuerySecurityObject [NTDLL.@]
163 * An ntdll analogue to GetKernelObjectSecurity().
166 * only the lowest 4 bit of SecurityObjectInformationClass are used
167 * 0x7-0xf returns STATUS_ACCESS_DENIED (even running with system privileges)
170 * We are constructing a fake sid (Administrators:Full, System:Full, Everyone:Read)
173 NtQuerySecurityObject(
175 IN SECURITY_INFORMATION RequestedInformation
,
176 OUT PSECURITY_DESCRIPTOR pSecurityDesriptor
,
178 OUT PULONG ResultLength
)
180 static const SID_IDENTIFIER_AUTHORITY localSidAuthority
= {SECURITY_NT_AUTHORITY
};
181 static const SID_IDENTIFIER_AUTHORITY worldSidAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
183 PISECURITY_DESCRIPTOR_RELATIVE psd
= (PISECURITY_DESCRIPTOR_RELATIVE
)Buffer
;
184 UINT BufferIndex
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
186 FIXME("(%p,0x%08x,%p,0x%08x,%p) stub!\n",
187 Object
, RequestedInformation
, pSecurityDesriptor
, Length
, ResultLength
);
189 RequestedInformation
&= 0x0000000f;
191 if (RequestedInformation
& SACL_SECURITY_INFORMATION
) return STATUS_ACCESS_DENIED
;
193 ZeroMemory(Buffer
, 256);
194 RtlCreateSecurityDescriptor((PSECURITY_DESCRIPTOR
)psd
, SECURITY_DESCRIPTOR_REVISION
);
195 psd
->Control
= SE_SELF_RELATIVE
|
196 ((RequestedInformation
& DACL_SECURITY_INFORMATION
) ? SE_DACL_PRESENT
:0);
198 /* owner: administrator S-1-5-20-220*/
199 if (OWNER_SECURITY_INFORMATION
& RequestedInformation
)
201 SID
* psid
= (SID
*)&(Buffer
[BufferIndex
]);
203 psd
->Owner
= BufferIndex
;
204 BufferIndex
+= RtlLengthRequiredSid(2);
206 psid
->Revision
= SID_REVISION
;
207 psid
->SubAuthorityCount
= 2;
208 psid
->IdentifierAuthority
= localSidAuthority
;
209 psid
->SubAuthority
[0] = SECURITY_BUILTIN_DOMAIN_RID
;
210 psid
->SubAuthority
[1] = DOMAIN_ALIAS_RID_ADMINS
;
213 /* group: built in domain S-1-5-12 */
214 if (GROUP_SECURITY_INFORMATION
& RequestedInformation
)
216 SID
* psid
= (SID
*) &(Buffer
[BufferIndex
]);
218 psd
->Group
= BufferIndex
;
219 BufferIndex
+= RtlLengthRequiredSid(1);
221 psid
->Revision
= SID_REVISION
;
222 psid
->SubAuthorityCount
= 1;
223 psid
->IdentifierAuthority
= localSidAuthority
;
224 psid
->SubAuthority
[0] = SECURITY_LOCAL_SYSTEM_RID
;
227 /* discretionary ACL */
228 if (DACL_SECURITY_INFORMATION
& RequestedInformation
)
231 PACL pacl
= (PACL
)&(Buffer
[BufferIndex
]);
232 PACCESS_ALLOWED_ACE pace
;
235 psd
->Dacl
= BufferIndex
;
237 pacl
->AclRevision
= MIN_ACL_REVISION
;
239 pacl
->AclSize
= BufferIndex
; /* storing the start index temporary */
241 BufferIndex
+= sizeof(ACL
);
243 /* ACE System - full access */
244 pace
= (PACCESS_ALLOWED_ACE
)&(Buffer
[BufferIndex
]);
245 BufferIndex
+= sizeof(ACCESS_ALLOWED_ACE
)-sizeof(DWORD
);
247 pace
->Header
.AceType
= ACCESS_ALLOWED_ACE_TYPE
;
248 pace
->Header
.AceFlags
= CONTAINER_INHERIT_ACE
;
249 pace
->Header
.AceSize
= sizeof(ACCESS_ALLOWED_ACE
)-sizeof(DWORD
) + RtlLengthRequiredSid(1);
250 pace
->Mask
= STANDARD_RIGHTS_ALL
| SPECIFIC_RIGHTS_ALL
;
251 pace
->SidStart
= BufferIndex
;
253 /* SID S-1-5-12 (System) */
254 psid
= (SID
*)&(Buffer
[BufferIndex
]);
256 BufferIndex
+= RtlLengthRequiredSid(1);
258 psid
->Revision
= SID_REVISION
;
259 psid
->SubAuthorityCount
= 1;
260 psid
->IdentifierAuthority
= localSidAuthority
;
261 psid
->SubAuthority
[0] = SECURITY_LOCAL_SYSTEM_RID
;
263 /* ACE Administrators - full access*/
264 pace
= (PACCESS_ALLOWED_ACE
) &(Buffer
[BufferIndex
]);
265 BufferIndex
+= sizeof(ACCESS_ALLOWED_ACE
)-sizeof(DWORD
);
267 pace
->Header
.AceType
= ACCESS_ALLOWED_ACE_TYPE
;
268 pace
->Header
.AceFlags
= CONTAINER_INHERIT_ACE
;
269 pace
->Header
.AceSize
= sizeof(ACCESS_ALLOWED_ACE
)-sizeof(DWORD
) + RtlLengthRequiredSid(2);
270 pace
->Mask
= STANDARD_RIGHTS_ALL
| SPECIFIC_RIGHTS_ALL
;
271 pace
->SidStart
= BufferIndex
;
273 /* S-1-5-12 (Administrators) */
274 psid
= (SID
*)&(Buffer
[BufferIndex
]);
276 BufferIndex
+= RtlLengthRequiredSid(2);
278 psid
->Revision
= SID_REVISION
;
279 psid
->SubAuthorityCount
= 2;
280 psid
->IdentifierAuthority
= localSidAuthority
;
281 psid
->SubAuthority
[0] = SECURITY_BUILTIN_DOMAIN_RID
;
282 psid
->SubAuthority
[1] = DOMAIN_ALIAS_RID_ADMINS
;
284 /* ACE Everyone - read access */
285 pace
= (PACCESS_ALLOWED_ACE
)&(Buffer
[BufferIndex
]);
286 BufferIndex
+= sizeof(ACCESS_ALLOWED_ACE
)-sizeof(DWORD
);
288 pace
->Header
.AceType
= ACCESS_ALLOWED_ACE_TYPE
;
289 pace
->Header
.AceFlags
= CONTAINER_INHERIT_ACE
;
290 pace
->Header
.AceSize
= sizeof(ACCESS_ALLOWED_ACE
)-sizeof(DWORD
) + RtlLengthRequiredSid(1);
291 pace
->Mask
= READ_CONTROL
| 0x19;
292 pace
->SidStart
= BufferIndex
;
294 /* SID S-1-1-0 (Everyone) */
295 psid
= (SID
*)&(Buffer
[BufferIndex
]);
297 BufferIndex
+= RtlLengthRequiredSid(1);
299 psid
->Revision
= SID_REVISION
;
300 psid
->SubAuthorityCount
= 1;
301 psid
->IdentifierAuthority
= worldSidAuthority
;
302 psid
->SubAuthority
[0] = 0;
304 /* calculate used bytes */
305 pacl
->AclSize
= BufferIndex
- pacl
->AclSize
;
307 *ResultLength
= BufferIndex
;
308 TRACE("len=%u\n", *ResultLength
);
309 if (Length
< *ResultLength
) return STATUS_BUFFER_TOO_SMALL
;
310 memcpy(pSecurityDesriptor
, Buffer
, *ResultLength
);
312 return STATUS_SUCCESS
;
316 /******************************************************************************
317 * NtDuplicateObject [NTDLL.@]
318 * ZwDuplicateObject [NTDLL.@]
320 NTSTATUS WINAPI
NtDuplicateObject( HANDLE source_process
, HANDLE source
,
321 HANDLE dest_process
, PHANDLE dest
,
322 ACCESS_MASK access
, ULONG attributes
, ULONG options
)
325 SERVER_START_REQ( dup_handle
)
327 req
->src_process
= source_process
;
328 req
->src_handle
= source
;
329 req
->dst_process
= dest_process
;
330 req
->access
= access
;
331 req
->attributes
= attributes
;
332 req
->options
= options
;
334 if (!(ret
= wine_server_call( req
)))
336 if (dest
) *dest
= reply
->handle
;
341 int fd
= server_remove_fd_from_cache( source
);
342 if (fd
!= -1) close( fd
);
345 else if (options
& DUPLICATE_CLOSE_SOURCE
)
346 WARN( "failed to close handle %p in process %p\n", source
, source_process
);
353 /**************************************************************************
356 * Close a handle reference to an object.
359 * Handle [I] handle to close
362 * Success: ERROR_SUCCESS.
363 * Failure: An NTSTATUS error code.
365 NTSTATUS WINAPI
NtClose( HANDLE Handle
)
368 int fd
= server_remove_fd_from_cache( Handle
);
370 SERVER_START_REQ( close_handle
)
372 req
->handle
= Handle
;
373 ret
= wine_server_call( req
);
376 if (fd
!= -1) close( fd
);
381 * Directory functions
384 /**************************************************************************
385 * NtOpenDirectoryObject [NTDLL.@]
386 * ZwOpenDirectoryObject [NTDLL.@]
388 * Open a namespace directory object.
391 * DirectoryHandle [O] Destination for the new directory handle
392 * DesiredAccess [I] Desired access to the directory
393 * ObjectAttributes [I] Structure describing the directory
396 * Success: ERROR_SUCCESS.
397 * Failure: An NTSTATUS error code.
399 NTSTATUS WINAPI
NtOpenDirectoryObject(PHANDLE DirectoryHandle
, ACCESS_MASK DesiredAccess
,
400 POBJECT_ATTRIBUTES ObjectAttributes
)
403 TRACE("(%p,0x%08x)\n", DirectoryHandle
, DesiredAccess
);
404 dump_ObjectAttributes(ObjectAttributes
);
406 if (!DirectoryHandle
) return STATUS_ACCESS_VIOLATION
;
407 if (!ObjectAttributes
) return STATUS_INVALID_PARAMETER
;
408 /* Have to test it here because server won't know difference between
409 * ObjectName == NULL and ObjectName == "" */
410 if (!ObjectAttributes
->ObjectName
)
412 if (ObjectAttributes
->RootDirectory
)
413 return STATUS_OBJECT_NAME_INVALID
;
415 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
418 SERVER_START_REQ(open_directory
)
420 req
->access
= DesiredAccess
;
421 req
->attributes
= ObjectAttributes
->Attributes
;
422 req
->rootdir
= ObjectAttributes
->RootDirectory
;
423 if (ObjectAttributes
->ObjectName
)
424 wine_server_add_data(req
, ObjectAttributes
->ObjectName
->Buffer
,
425 ObjectAttributes
->ObjectName
->Length
);
426 ret
= wine_server_call( req
);
427 *DirectoryHandle
= reply
->handle
;
433 /******************************************************************************
434 * NtCreateDirectoryObject [NTDLL.@]
435 * ZwCreateDirectoryObject [NTDLL.@]
437 * Create a namespace directory object.
440 * DirectoryHandle [O] Destination for the new directory handle
441 * DesiredAccess [I] Desired access to the directory
442 * ObjectAttributes [I] Structure describing the directory
445 * Success: ERROR_SUCCESS.
446 * Failure: An NTSTATUS error code.
448 NTSTATUS WINAPI
NtCreateDirectoryObject(PHANDLE DirectoryHandle
, ACCESS_MASK DesiredAccess
,
449 POBJECT_ATTRIBUTES ObjectAttributes
)
452 TRACE("(%p,0x%08x)\n", DirectoryHandle
, DesiredAccess
);
453 dump_ObjectAttributes(ObjectAttributes
);
455 if (!DirectoryHandle
) return STATUS_ACCESS_VIOLATION
;
457 SERVER_START_REQ(create_directory
)
459 req
->access
= DesiredAccess
;
460 req
->attributes
= ObjectAttributes
? ObjectAttributes
->Attributes
: 0;
461 req
->rootdir
= ObjectAttributes
? ObjectAttributes
->RootDirectory
: 0;
462 if (ObjectAttributes
&& ObjectAttributes
->ObjectName
)
463 wine_server_add_data(req
, ObjectAttributes
->ObjectName
->Buffer
,
464 ObjectAttributes
->ObjectName
->Length
);
465 ret
= wine_server_call( req
);
466 *DirectoryHandle
= reply
->handle
;
472 /******************************************************************************
473 * NtQueryDirectoryObject [NTDLL.@]
474 * ZwQueryDirectoryObject [NTDLL.@]
476 * Read information from a namespace directory.
479 * DirectoryHandle [I] Handle to a directory object
480 * Buffer [O] Buffer to hold the read data
481 * BufferLength [I] Size of the buffer in bytes
482 * ReturnSingleEntry [I] If TRUE, return a single entry, if FALSE, return as many as fit in the buffer
483 * RestartScan [I] If TRUE, start scanning from the start, if FALSE, scan from Context
484 * Context [I/O] Indicates what point of the directory the scan is at
485 * ReturnLength [O] Caller supplied storage for the number of bytes written (or NULL)
488 * Success: ERROR_SUCCESS.
489 * Failure: An NTSTATUS error code.
491 NTSTATUS WINAPI
NtQueryDirectoryObject(IN HANDLE DirectoryHandle
, OUT PDIRECTORY_BASIC_INFORMATION Buffer
,
492 IN ULONG BufferLength
, IN BOOLEAN ReturnSingleEntry
, IN BOOLEAN RestartScan
,
493 IN OUT PULONG Context
, OUT PULONG ReturnLength OPTIONAL
)
495 FIXME("(%p,%p,0x%08x,0x%08x,0x%08x,%p,%p), stub\n", DirectoryHandle
, Buffer
, BufferLength
, ReturnSingleEntry
,
496 RestartScan
, Context
, ReturnLength
);
498 return STATUS_NOT_IMPLEMENTED
;
505 /******************************************************************************
506 * NtOpenSymbolicLinkObject [NTDLL.@]
507 * ZwOpenSymbolicLinkObject [NTDLL.@]
509 * Open a namespace symbolic link object.
512 * LinkHandle [O] Destination for the new symbolic link handle
513 * DesiredAccess [I] Desired access to the symbolic link
514 * ObjectAttributes [I] Structure describing the symbolic link
517 * Success: ERROR_SUCCESS.
518 * Failure: An NTSTATUS error code.
520 NTSTATUS WINAPI
NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle
, IN ACCESS_MASK DesiredAccess
,
521 IN POBJECT_ATTRIBUTES ObjectAttributes
)
524 TRACE("(%p,0x%08x,%p)\n",LinkHandle
, DesiredAccess
, ObjectAttributes
);
525 dump_ObjectAttributes(ObjectAttributes
);
527 if (!LinkHandle
) return STATUS_ACCESS_VIOLATION
;
528 if (!ObjectAttributes
) return STATUS_INVALID_PARAMETER
;
529 /* Have to test it here because server won't know difference between
530 * ObjectName == NULL and ObjectName == "" */
531 if (!ObjectAttributes
->ObjectName
)
533 if (ObjectAttributes
->RootDirectory
)
534 return STATUS_OBJECT_NAME_INVALID
;
536 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
539 SERVER_START_REQ(open_symlink
)
541 req
->access
= DesiredAccess
;
542 req
->attributes
= ObjectAttributes
->Attributes
;
543 req
->rootdir
= ObjectAttributes
->RootDirectory
;
544 if (ObjectAttributes
->ObjectName
)
545 wine_server_add_data(req
, ObjectAttributes
->ObjectName
->Buffer
,
546 ObjectAttributes
->ObjectName
->Length
);
547 ret
= wine_server_call( req
);
548 *LinkHandle
= reply
->handle
;
554 /******************************************************************************
555 * NtCreateSymbolicLinkObject [NTDLL.@]
556 * ZwCreateSymbolicLinkObject [NTDLL.@]
558 * Open a namespace symbolic link object.
561 * SymbolicLinkHandle [O] Destination for the new symbolic link handle
562 * DesiredAccess [I] Desired access to the symbolic link
563 * ObjectAttributes [I] Structure describing the symbolic link
564 * TargetName [I] Name of the target symbolic link points to
567 * Success: ERROR_SUCCESS.
568 * Failure: An NTSTATUS error code.
570 NTSTATUS WINAPI
NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle
,IN ACCESS_MASK DesiredAccess
,
571 IN POBJECT_ATTRIBUTES ObjectAttributes
,
572 IN PUNICODE_STRING TargetName
)
575 TRACE("(%p,0x%08x,%p, -> %s)\n", SymbolicLinkHandle
, DesiredAccess
, ObjectAttributes
,
576 debugstr_us(TargetName
));
577 dump_ObjectAttributes(ObjectAttributes
);
579 if (!SymbolicLinkHandle
|| !TargetName
) return STATUS_ACCESS_VIOLATION
;
580 if (!TargetName
->Buffer
) return STATUS_INVALID_PARAMETER
;
582 SERVER_START_REQ(create_symlink
)
584 req
->access
= DesiredAccess
;
585 req
->attributes
= ObjectAttributes
? ObjectAttributes
->Attributes
: 0;
586 req
->rootdir
= ObjectAttributes
? ObjectAttributes
->RootDirectory
: 0;
587 if (ObjectAttributes
&& ObjectAttributes
->ObjectName
)
589 req
->name_len
= ObjectAttributes
->ObjectName
->Length
;
590 wine_server_add_data(req
, ObjectAttributes
->ObjectName
->Buffer
,
591 ObjectAttributes
->ObjectName
->Length
);
595 wine_server_add_data(req
, TargetName
->Buffer
, TargetName
->Length
);
596 ret
= wine_server_call( req
);
597 *SymbolicLinkHandle
= reply
->handle
;
603 /******************************************************************************
604 * NtQuerySymbolicLinkObject [NTDLL.@]
605 * ZwQuerySymbolicLinkObject [NTDLL.@]
607 * Query a namespace symbolic link object target name.
610 * LinkHandle [I] Handle to a symbolic link object
611 * LinkTarget [O] Destination for the symbolic link target
612 * ReturnedLength [O] Size of returned data
615 * Success: ERROR_SUCCESS.
616 * Failure: An NTSTATUS error code.
618 NTSTATUS WINAPI
NtQuerySymbolicLinkObject(IN HANDLE LinkHandle
, IN OUT PUNICODE_STRING LinkTarget
,
619 OUT PULONG ReturnedLength OPTIONAL
)
622 TRACE("(%p,%p,%p)\n", LinkHandle
, LinkTarget
, ReturnedLength
);
624 if (!LinkTarget
) return STATUS_ACCESS_VIOLATION
;
626 SERVER_START_REQ(query_symlink
)
628 req
->handle
= LinkHandle
;
629 wine_server_set_reply( req
, LinkTarget
->Buffer
, LinkTarget
->MaximumLength
);
630 if (!(ret
= wine_server_call( req
)))
632 LinkTarget
->Length
= wine_server_reply_size(reply
);
633 if (ReturnedLength
) *ReturnedLength
= LinkTarget
->Length
;
640 /******************************************************************************
641 * NtAllocateUuids [NTDLL.@]
643 NTSTATUS WINAPI
NtAllocateUuids(
644 PULARGE_INTEGER Time
,
648 FIXME("(%p,%p,%p), stub.\n", Time
, Range
, Sequence
);