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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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%08lx,%p): stub\n",
60 handle
, info_class
, ptr
, len
, used_len
);
62 if (used_len
) *used_len
= 0;
66 case ObjectDataInformation
:
68 OBJECT_DATA_INFORMATION
* p
= (OBJECT_DATA_INFORMATION
*)ptr
;
70 if (len
< sizeof(*p
)) return STATUS_INVALID_BUFFER_SIZE
;
72 SERVER_START_REQ( set_handle_info
)
77 status
= wine_server_call( req
);
78 if (status
== STATUS_SUCCESS
)
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
);
89 FIXME("Unsupported information class %u\n", info_class
);
90 status
= STATUS_NOT_IMPLEMENTED
;
96 /******************************************************************
97 * NtSetInformationObject [NTDLL.@]
98 * ZwSetInformationObject [NTDLL.@]
101 NTSTATUS WINAPI
NtSetInformationObject(IN HANDLE handle
,
102 IN OBJECT_INFORMATION_CLASS info_class
,
103 IN PVOID ptr
, IN ULONG len
)
107 TRACE("(%p,0x%08x,%p,0x%08lx): stub\n",
108 handle
, info_class
, ptr
, len
);
112 case ObjectDataInformation
:
114 OBJECT_DATA_INFORMATION
* p
= (OBJECT_DATA_INFORMATION
*)ptr
;
116 if (len
< sizeof(*p
)) return STATUS_INVALID_BUFFER_SIZE
;
118 SERVER_START_REQ( set_handle_info
)
120 req
->handle
= handle
;
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
);
131 FIXME("Unsupported information class %u\n", info_class
);
132 status
= STATUS_NOT_IMPLEMENTED
;
138 /******************************************************************************
139 * NtQuerySecurityObject [NTDLL.@]
141 * An ntdll analogue to GetKernelObjectSecurity().
144 * only the lowest 4 bit of SecurityObjectInformationClass are used
145 * 0x7-0xf returns STATUS_ACCESS_DENIED (even running with system privileges)
148 * We are constructing a fake sid (Administrators:Full, System:Full, Everyone:Read)
151 NtQuerySecurityObject(
153 IN SECURITY_INFORMATION RequestedInformation
,
154 OUT PSECURITY_DESCRIPTOR pSecurityDesriptor
,
156 OUT PULONG ResultLength
)
158 static SID_IDENTIFIER_AUTHORITY localSidAuthority
= {SECURITY_NT_AUTHORITY
};
159 static SID_IDENTIFIER_AUTHORITY worldSidAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
161 PISECURITY_DESCRIPTOR_RELATIVE psd
= (PISECURITY_DESCRIPTOR_RELATIVE
)Buffer
;
162 UINT BufferIndex
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
164 FIXME("(%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
165 Object
, RequestedInformation
, pSecurityDesriptor
, Length
, ResultLength
);
167 RequestedInformation
&= 0x0000000f;
169 if (RequestedInformation
& SACL_SECURITY_INFORMATION
) return STATUS_ACCESS_DENIED
;
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);
176 /* owner: administrator S-1-5-20-220*/
177 if (OWNER_SECURITY_INFORMATION
& RequestedInformation
)
179 SID
* psid
= (SID
*)&(Buffer
[BufferIndex
]);
181 psd
->Owner
= BufferIndex
;
182 BufferIndex
+= RtlLengthRequiredSid(2);
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
;
191 /* group: built in domain S-1-5-12 */
192 if (GROUP_SECURITY_INFORMATION
& RequestedInformation
)
194 SID
* psid
= (SID
*) &(Buffer
[BufferIndex
]);
196 psd
->Group
= BufferIndex
;
197 BufferIndex
+= RtlLengthRequiredSid(1);
199 psid
->Revision
= SID_REVISION
;
200 psid
->SubAuthorityCount
= 1;
201 psid
->IdentifierAuthority
= localSidAuthority
;
202 psid
->SubAuthority
[0] = SECURITY_LOCAL_SYSTEM_RID
;
205 /* discretionary ACL */
206 if (DACL_SECURITY_INFORMATION
& RequestedInformation
)
209 PACL pacl
= (PACL
)&(Buffer
[BufferIndex
]);
210 PACCESS_ALLOWED_ACE pace
;
213 psd
->Dacl
= BufferIndex
;
215 pacl
->AclRevision
= MIN_ACL_REVISION
;
217 pacl
->AclSize
= BufferIndex
; /* storing the start index temporary */
219 BufferIndex
+= sizeof(ACL
);
221 /* ACE System - full access */
222 pace
= (PACCESS_ALLOWED_ACE
)&(Buffer
[BufferIndex
]);
223 BufferIndex
+= sizeof(ACCESS_ALLOWED_ACE
)-sizeof(DWORD
);
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
;
231 /* SID S-1-5-12 (System) */
232 psid
= (SID
*)&(Buffer
[BufferIndex
]);
234 BufferIndex
+= RtlLengthRequiredSid(1);
236 psid
->Revision
= SID_REVISION
;
237 psid
->SubAuthorityCount
= 1;
238 psid
->IdentifierAuthority
= localSidAuthority
;
239 psid
->SubAuthority
[0] = SECURITY_LOCAL_SYSTEM_RID
;
241 /* ACE Administrators - full access*/
242 pace
= (PACCESS_ALLOWED_ACE
) &(Buffer
[BufferIndex
]);
243 BufferIndex
+= sizeof(ACCESS_ALLOWED_ACE
)-sizeof(DWORD
);
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
;
251 /* S-1-5-12 (Administrators) */
252 psid
= (SID
*)&(Buffer
[BufferIndex
]);
254 BufferIndex
+= RtlLengthRequiredSid(2);
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
;
262 /* ACE Everyone - read access */
263 pace
= (PACCESS_ALLOWED_ACE
)&(Buffer
[BufferIndex
]);
264 BufferIndex
+= sizeof(ACCESS_ALLOWED_ACE
)-sizeof(DWORD
);
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
;
272 /* SID S-1-1-0 (Everyone) */
273 psid
= (SID
*)&(Buffer
[BufferIndex
]);
275 BufferIndex
+= RtlLengthRequiredSid(1);
277 psid
->Revision
= SID_REVISION
;
278 psid
->SubAuthorityCount
= 1;
279 psid
->IdentifierAuthority
= worldSidAuthority
;
280 psid
->SubAuthority
[0] = 0;
282 /* calculate used bytes */
283 pacl
->AclSize
= BufferIndex
- pacl
->AclSize
;
285 *ResultLength
= BufferIndex
;
286 TRACE("len=%lu\n", *ResultLength
);
287 if (Length
< *ResultLength
) return STATUS_BUFFER_TOO_SMALL
;
288 memcpy(pSecurityDesriptor
, Buffer
, *ResultLength
);
290 return STATUS_SUCCESS
;
294 /******************************************************************************
295 * NtDuplicateObject [NTDLL.@]
296 * ZwDuplicateObject [NTDLL.@]
298 NTSTATUS WINAPI
NtDuplicateObject( HANDLE source_process
, HANDLE source
,
299 HANDLE dest_process
, PHANDLE dest
,
300 ACCESS_MASK access
, ULONG attributes
, ULONG options
)
303 SERVER_START_REQ( dup_handle
)
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
;
312 if (!(ret
= wine_server_call( req
)))
314 if (dest
) *dest
= reply
->handle
;
315 if (reply
->fd
!= -1) close( reply
->fd
);
322 /**************************************************************************
325 * Close a handle reference to an object.
328 * Handle [I] handle to close
331 * Success: ERROR_SUCCESS.
332 * Failure: An NTSTATUS error code.
334 NTSTATUS WINAPI
NtClose( HANDLE Handle
)
337 SERVER_START_REQ( close_handle
)
339 req
->handle
= Handle
;
340 ret
= wine_server_call( req
);
341 if (!ret
&& reply
->fd
!= -1) close( reply
->fd
);
348 * Directory functions
351 /**************************************************************************
352 * NtOpenDirectoryObject [NTDLL.@]
353 * ZwOpenDirectoryObject [NTDLL.@]
355 * Open a namespace directory object.
358 * DirectoryHandle [O] Destination for the new directory handle
359 * DesiredAccess [I] Desired access to the directory
360 * ObjectAttributes [I] Structure describing the directory
363 * Success: ERROR_SUCCESS.
364 * Failure: An NTSTATUS error code.
366 NTSTATUS WINAPI
NtOpenDirectoryObject(PHANDLE DirectoryHandle
, ACCESS_MASK DesiredAccess
,
367 POBJECT_ATTRIBUTES ObjectAttributes
)
370 TRACE("(%p,0x%08lx)\n", DirectoryHandle
, DesiredAccess
);
371 dump_ObjectAttributes(ObjectAttributes
);
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
)
379 if (ObjectAttributes
->RootDirectory
)
380 return STATUS_OBJECT_NAME_INVALID
;
382 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
385 SERVER_START_REQ(open_directory
)
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
;
400 /******************************************************************************
401 * NtCreateDirectoryObject [NTDLL.@]
402 * ZwCreateDirectoryObject [NTDLL.@]
404 * Create a namespace directory object.
407 * DirectoryHandle [O] Destination for the new directory handle
408 * DesiredAccess [I] Desired access to the directory
409 * ObjectAttributes [I] Structure describing the directory
412 * Success: ERROR_SUCCESS.
413 * Failure: An NTSTATUS error code.
415 NTSTATUS WINAPI
NtCreateDirectoryObject(PHANDLE DirectoryHandle
, ACCESS_MASK DesiredAccess
,
416 POBJECT_ATTRIBUTES ObjectAttributes
)
419 TRACE("(%p,0x%08lx)\n", DirectoryHandle
, DesiredAccess
);
420 dump_ObjectAttributes(ObjectAttributes
);
422 if (!DirectoryHandle
) return STATUS_ACCESS_VIOLATION
;
424 SERVER_START_REQ(create_directory
)
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
;
439 /******************************************************************************
440 * NtQueryDirectoryObject [NTDLL.@]
441 * ZwQueryDirectoryObject [NTDLL.@]
443 * Read information from a namespace directory.
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)
455 * Success: ERROR_SUCCESS.
456 * Failure: An NTSTATUS error code.
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
)
462 FIXME("(%p,%p,0x%08lx,0x%08x,0x%08x,%p,%p), stub\n", DirectoryHandle
, Buffer
, BufferLength
, ReturnSingleEntry
,
463 RestartScan
, Context
, ReturnLength
);
465 return STATUS_NOT_IMPLEMENTED
;
472 /******************************************************************************
473 * NtOpenSymbolicLinkObject [NTDLL.@]
474 * ZwOpenSymbolicLinkObject [NTDLL.@]
476 * Open a namespace symbolic link object.
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
484 * Success: ERROR_SUCCESS.
485 * Failure: An NTSTATUS error code.
487 NTSTATUS WINAPI
NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle
, IN ACCESS_MASK DesiredAccess
,
488 IN POBJECT_ATTRIBUTES ObjectAttributes
)
491 TRACE("(%p,0x%08lx,%p)\n",LinkHandle
, DesiredAccess
, ObjectAttributes
);
492 dump_ObjectAttributes(ObjectAttributes
);
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
)
500 if (ObjectAttributes
->RootDirectory
)
501 return STATUS_OBJECT_NAME_INVALID
;
503 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
506 SERVER_START_REQ(open_symlink
)
508 req
->access
= DesiredAccess
;
509 req
->attributes
= ObjectAttributes
? ObjectAttributes
->Attributes
: 0;
510 req
->rootdir
= ObjectAttributes
? ObjectAttributes
->RootDirectory
: 0;
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
;
521 /******************************************************************************
522 * NtCreateSymbolicLinkObject [NTDLL.@]
523 * ZwCreateSymbolicLinkObject [NTDLL.@]
525 * Open a namespace symbolic link object.
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
534 * Success: ERROR_SUCCESS.
535 * Failure: An NTSTATUS error code.
537 NTSTATUS WINAPI
NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle
,IN ACCESS_MASK DesiredAccess
,
538 IN POBJECT_ATTRIBUTES ObjectAttributes
,
539 IN PUNICODE_STRING TargetName
)
542 TRACE("(%p,0x%08lx,%p, -> %s)\n", SymbolicLinkHandle
, DesiredAccess
, ObjectAttributes
,
543 debugstr_us(TargetName
));
544 dump_ObjectAttributes(ObjectAttributes
);
546 if (!SymbolicLinkHandle
|| !TargetName
) return STATUS_ACCESS_VIOLATION
;
547 if (!TargetName
->Buffer
) return STATUS_INVALID_PARAMETER
;
549 SERVER_START_REQ(create_symlink
)
551 req
->access
= DesiredAccess
;
552 req
->attributes
= ObjectAttributes
? ObjectAttributes
->Attributes
: 0;
553 req
->rootdir
= ObjectAttributes
? ObjectAttributes
->RootDirectory
: 0;
554 if (ObjectAttributes
->ObjectName
)
556 req
->name_len
= ObjectAttributes
->ObjectName
->Length
;
557 wine_server_add_data(req
, ObjectAttributes
->ObjectName
->Buffer
,
558 ObjectAttributes
->ObjectName
->Length
);
562 wine_server_add_data(req
, TargetName
->Buffer
, TargetName
->Length
);
563 ret
= wine_server_call( req
);
564 *SymbolicLinkHandle
= reply
->handle
;
570 /******************************************************************************
571 * NtQuerySymbolicLinkObject [NTDLL.@]
572 * ZwQuerySymbolicLinkObject [NTDLL.@]
574 * Query a namespace symbolic link object target name.
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
582 * Success: ERROR_SUCCESS.
583 * Failure: An NTSTATUS error code.
585 NTSTATUS WINAPI
NtQuerySymbolicLinkObject(IN HANDLE LinkHandle
, IN OUT PUNICODE_STRING LinkTarget
,
586 OUT PULONG ReturnedLength OPTIONAL
)
589 TRACE("(%p,%p,%p)\n", LinkHandle
, LinkTarget
, ReturnedLength
);
591 if (!LinkTarget
) return STATUS_ACCESS_VIOLATION
;
593 SERVER_START_REQ(query_symlink
)
595 req
->handle
= LinkHandle
;
596 wine_server_set_reply( req
, LinkTarget
->Buffer
, LinkTarget
->MaximumLength
);
597 if (!(ret
= wine_server_call( req
)))
599 LinkTarget
->Length
= wine_server_reply_size(reply
);
600 if (ReturnedLength
) *ReturnedLength
= LinkTarget
->Length
;
607 /******************************************************************************
608 * NtAllocateUuids [NTDLL.@]
610 NTSTATUS WINAPI
NtAllocateUuids(
611 PULARGE_INTEGER Time
,
615 FIXME("(%p,%p,%p), stub.\n", Time
, Range
, Sequence
);