|  | /* | 
|  | *	Object management functions | 
|  | * | 
|  | * Copyright 1999, 2000 Juergen Schmied | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
|  | */ | 
|  |  | 
|  | #include "config.h" | 
|  |  | 
|  | #include <stdarg.h> | 
|  | #include <stdlib.h> | 
|  | #include <string.h> | 
|  | #ifdef HAVE_IO_H | 
|  | # include <io.h> | 
|  | #endif | 
|  | #ifdef HAVE_UNISTD_H | 
|  | # include <unistd.h> | 
|  | #endif | 
|  | #include "wine/debug.h" | 
|  |  | 
|  | #include "windef.h" | 
|  | #include "winternl.h" | 
|  | #include "ntdll_misc.h" | 
|  | #include "wine/server.h" | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(ntdll); | 
|  |  | 
|  |  | 
|  | /* | 
|  | *	Generic object functions | 
|  | */ | 
|  |  | 
|  | /****************************************************************************** | 
|  | * NtQueryObject [NTDLL.@] | 
|  | * ZwQueryObject [NTDLL.@] | 
|  | */ | 
|  | NTSTATUS WINAPI NtQueryObject(IN HANDLE handle, | 
|  | IN OBJECT_INFORMATION_CLASS info_class, | 
|  | OUT PVOID ptr, IN ULONG len, OUT PULONG used_len) | 
|  | { | 
|  | NTSTATUS status; | 
|  |  | 
|  | TRACE("(%p,0x%08x,%p,0x%08lx,%p): stub\n", | 
|  | handle, info_class, ptr, len, used_len); | 
|  |  | 
|  | if (used_len) *used_len = 0; | 
|  |  | 
|  | switch (info_class) | 
|  | { | 
|  | case ObjectDataInformation: | 
|  | { | 
|  | OBJECT_DATA_INFORMATION* p = (OBJECT_DATA_INFORMATION*)ptr; | 
|  |  | 
|  | if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE; | 
|  |  | 
|  | SERVER_START_REQ( set_handle_info ) | 
|  | { | 
|  | req->handle = handle; | 
|  | req->flags  = 0; | 
|  | req->mask   = 0; | 
|  | req->fd     = -1; | 
|  | status = wine_server_call( req ); | 
|  | if (status == STATUS_SUCCESS) | 
|  | { | 
|  | p->InheritHandle = (reply->old_flags & HANDLE_FLAG_INHERIT) ? TRUE : FALSE; | 
|  | p->ProtectFromClose = (reply->old_flags & HANDLE_FLAG_PROTECT_FROM_CLOSE) ? TRUE : FALSE; | 
|  | if (used_len) *used_len = sizeof(*p); | 
|  | } | 
|  | } | 
|  | SERVER_END_REQ; | 
|  | } | 
|  | break; | 
|  | default: | 
|  | FIXME("Unsupported information class %u\n", info_class); | 
|  | status = STATUS_NOT_IMPLEMENTED; | 
|  | break; | 
|  | } | 
|  | return status; | 
|  | } | 
|  |  | 
|  | /****************************************************************** | 
|  | *		NtSetInformationObject [NTDLL.@] | 
|  | *		ZwSetInformationObject [NTDLL.@] | 
|  | * | 
|  | */ | 
|  | NTSTATUS WINAPI NtSetInformationObject(IN HANDLE handle, | 
|  | IN OBJECT_INFORMATION_CLASS info_class, | 
|  | IN PVOID ptr, IN ULONG len) | 
|  | { | 
|  | NTSTATUS status; | 
|  |  | 
|  | TRACE("(%p,0x%08x,%p,0x%08lx): stub\n", | 
|  | handle, info_class, ptr, len); | 
|  |  | 
|  | switch (info_class) | 
|  | { | 
|  | case ObjectDataInformation: | 
|  | { | 
|  | OBJECT_DATA_INFORMATION* p = (OBJECT_DATA_INFORMATION*)ptr; | 
|  |  | 
|  | if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE; | 
|  |  | 
|  | SERVER_START_REQ( set_handle_info ) | 
|  | { | 
|  | req->handle = handle; | 
|  | req->flags  = 0; | 
|  | req->mask   = HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE; | 
|  | req->fd     = -1; | 
|  | if (p->InheritHandle)    req->flags |= HANDLE_FLAG_INHERIT; | 
|  | if (p->ProtectFromClose) req->flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE; | 
|  | status = wine_server_call( req ); | 
|  | } | 
|  | SERVER_END_REQ; | 
|  | } | 
|  | break; | 
|  | default: | 
|  | FIXME("Unsupported information class %u\n", info_class); | 
|  | status = STATUS_NOT_IMPLEMENTED; | 
|  | break; | 
|  | } | 
|  | return status; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | *  NtQuerySecurityObject	[NTDLL.@] | 
|  | * | 
|  | * An ntdll analogue to GetKernelObjectSecurity(). | 
|  | * | 
|  | * NOTES | 
|  | *  only the lowest 4 bit of SecurityObjectInformationClass are used | 
|  | *  0x7-0xf returns STATUS_ACCESS_DENIED (even running with system privileges) | 
|  | * | 
|  | * FIXME | 
|  | *  We are constructing a fake sid (Administrators:Full, System:Full, Everyone:Read) | 
|  | */ | 
|  | NTSTATUS WINAPI | 
|  | NtQuerySecurityObject( | 
|  | IN HANDLE Object, | 
|  | IN SECURITY_INFORMATION RequestedInformation, | 
|  | OUT PSECURITY_DESCRIPTOR pSecurityDesriptor, | 
|  | IN ULONG Length, | 
|  | OUT PULONG ResultLength) | 
|  | { | 
|  | static SID_IDENTIFIER_AUTHORITY localSidAuthority = {SECURITY_NT_AUTHORITY}; | 
|  | static SID_IDENTIFIER_AUTHORITY worldSidAuthority = {SECURITY_WORLD_SID_AUTHORITY}; | 
|  | BYTE Buffer[256]; | 
|  | PISECURITY_DESCRIPTOR_RELATIVE psd = (PISECURITY_DESCRIPTOR_RELATIVE)Buffer; | 
|  | UINT BufferIndex = sizeof(SECURITY_DESCRIPTOR_RELATIVE); | 
|  |  | 
|  | FIXME("(%p,0x%08lx,%p,0x%08lx,%p) stub!\n", | 
|  | Object, RequestedInformation, pSecurityDesriptor, Length, ResultLength); | 
|  |  | 
|  | RequestedInformation &= 0x0000000f; | 
|  |  | 
|  | if (RequestedInformation & SACL_SECURITY_INFORMATION) return STATUS_ACCESS_DENIED; | 
|  |  | 
|  | ZeroMemory(Buffer, 256); | 
|  | RtlCreateSecurityDescriptor((PSECURITY_DESCRIPTOR)psd, SECURITY_DESCRIPTOR_REVISION); | 
|  | psd->Control = SE_SELF_RELATIVE | | 
|  | ((RequestedInformation & DACL_SECURITY_INFORMATION) ? SE_DACL_PRESENT:0); | 
|  |  | 
|  | /* owner: administrator S-1-5-20-220*/ | 
|  | if (OWNER_SECURITY_INFORMATION & RequestedInformation) | 
|  | { | 
|  | SID* psid = (SID*)&(Buffer[BufferIndex]); | 
|  |  | 
|  | psd->Owner = BufferIndex; | 
|  | BufferIndex += RtlLengthRequiredSid(2); | 
|  |  | 
|  | psid->Revision = SID_REVISION; | 
|  | psid->SubAuthorityCount = 2; | 
|  | psid->IdentifierAuthority = localSidAuthority; | 
|  | psid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID; | 
|  | psid->SubAuthority[1] = DOMAIN_ALIAS_RID_ADMINS; | 
|  | } | 
|  |  | 
|  | /* group: built in domain S-1-5-12 */ | 
|  | if (GROUP_SECURITY_INFORMATION & RequestedInformation) | 
|  | { | 
|  | SID* psid = (SID*) &(Buffer[BufferIndex]); | 
|  |  | 
|  | psd->Group = BufferIndex; | 
|  | BufferIndex += RtlLengthRequiredSid(1); | 
|  |  | 
|  | psid->Revision = SID_REVISION; | 
|  | psid->SubAuthorityCount = 1; | 
|  | psid->IdentifierAuthority = localSidAuthority; | 
|  | psid->SubAuthority[0] = SECURITY_LOCAL_SYSTEM_RID; | 
|  | } | 
|  |  | 
|  | /* discretionary ACL */ | 
|  | if (DACL_SECURITY_INFORMATION & RequestedInformation) | 
|  | { | 
|  | /* acl header */ | 
|  | PACL pacl = (PACL)&(Buffer[BufferIndex]); | 
|  | PACCESS_ALLOWED_ACE pace; | 
|  | SID* psid; | 
|  |  | 
|  | psd->Dacl = BufferIndex; | 
|  |  | 
|  | pacl->AclRevision = MIN_ACL_REVISION; | 
|  | pacl->AceCount = 3; | 
|  | pacl->AclSize = BufferIndex; /* storing the start index temporary */ | 
|  |  | 
|  | BufferIndex += sizeof(ACL); | 
|  |  | 
|  | /* ACE System - full access */ | 
|  | pace = (PACCESS_ALLOWED_ACE)&(Buffer[BufferIndex]); | 
|  | BufferIndex += sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD); | 
|  |  | 
|  | pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; | 
|  | pace->Header.AceFlags = CONTAINER_INHERIT_ACE; | 
|  | pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + RtlLengthRequiredSid(1); | 
|  | pace->Mask = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER  | 0x3f; | 
|  | pace->SidStart = BufferIndex; | 
|  |  | 
|  | /* SID S-1-5-12 (System) */ | 
|  | psid = (SID*)&(Buffer[BufferIndex]); | 
|  |  | 
|  | BufferIndex += RtlLengthRequiredSid(1); | 
|  |  | 
|  | psid->Revision = SID_REVISION; | 
|  | psid->SubAuthorityCount = 1; | 
|  | psid->IdentifierAuthority = localSidAuthority; | 
|  | psid->SubAuthority[0] = SECURITY_LOCAL_SYSTEM_RID; | 
|  |  | 
|  | /* ACE Administrators - full access*/ | 
|  | pace = (PACCESS_ALLOWED_ACE) &(Buffer[BufferIndex]); | 
|  | BufferIndex += sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD); | 
|  |  | 
|  | pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; | 
|  | pace->Header.AceFlags = CONTAINER_INHERIT_ACE; | 
|  | pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + RtlLengthRequiredSid(2); | 
|  | pace->Mask = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER  | 0x3f; | 
|  | pace->SidStart = BufferIndex; | 
|  |  | 
|  | /* S-1-5-12 (Administrators) */ | 
|  | psid = (SID*)&(Buffer[BufferIndex]); | 
|  |  | 
|  | BufferIndex += RtlLengthRequiredSid(2); | 
|  |  | 
|  | psid->Revision = SID_REVISION; | 
|  | psid->SubAuthorityCount = 2; | 
|  | psid->IdentifierAuthority = localSidAuthority; | 
|  | psid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID; | 
|  | psid->SubAuthority[1] = DOMAIN_ALIAS_RID_ADMINS; | 
|  |  | 
|  | /* ACE Everyone - read access */ | 
|  | pace = (PACCESS_ALLOWED_ACE)&(Buffer[BufferIndex]); | 
|  | BufferIndex += sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD); | 
|  |  | 
|  | pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; | 
|  | pace->Header.AceFlags = CONTAINER_INHERIT_ACE; | 
|  | pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + RtlLengthRequiredSid(1); | 
|  | pace->Mask = READ_CONTROL| 0x19; | 
|  | pace->SidStart = BufferIndex; | 
|  |  | 
|  | /* SID S-1-1-0 (Everyone) */ | 
|  | psid = (SID*)&(Buffer[BufferIndex]); | 
|  |  | 
|  | BufferIndex += RtlLengthRequiredSid(1); | 
|  |  | 
|  | psid->Revision = SID_REVISION; | 
|  | psid->SubAuthorityCount = 1; | 
|  | psid->IdentifierAuthority = worldSidAuthority; | 
|  | psid->SubAuthority[0] = 0; | 
|  |  | 
|  | /* calculate used bytes */ | 
|  | pacl->AclSize = BufferIndex - pacl->AclSize; | 
|  | } | 
|  | *ResultLength = BufferIndex; | 
|  | TRACE("len=%lu\n", *ResultLength); | 
|  | if (Length < *ResultLength) return STATUS_BUFFER_TOO_SMALL; | 
|  | memcpy(pSecurityDesriptor, Buffer, *ResultLength); | 
|  |  | 
|  | return STATUS_SUCCESS; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | *  NtDuplicateObject		[NTDLL.@] | 
|  | *  ZwDuplicateObject		[NTDLL.@] | 
|  | */ | 
|  | NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, | 
|  | HANDLE dest_process, PHANDLE dest, | 
|  | ACCESS_MASK access, ULONG attributes, ULONG options ) | 
|  | { | 
|  | NTSTATUS ret; | 
|  | SERVER_START_REQ( dup_handle ) | 
|  | { | 
|  | req->src_process = source_process; | 
|  | req->src_handle  = source; | 
|  | req->dst_process = dest_process; | 
|  | req->access      = access; | 
|  | req->inherit     = (attributes & OBJ_INHERIT) != 0; | 
|  | req->options     = options; | 
|  |  | 
|  | if (!(ret = wine_server_call( req ))) | 
|  | { | 
|  | if (dest) *dest = reply->handle; | 
|  | if (reply->fd != -1) close( reply->fd ); | 
|  | } | 
|  | } | 
|  | SERVER_END_REQ; | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /************************************************************************** | 
|  | *                 NtClose				[NTDLL.@] | 
|  | * | 
|  | * Close a handle reference to an object. | 
|  | * | 
|  | * PARAMS | 
|  | *  Handle [I] handle to close | 
|  | * | 
|  | * RETURNS | 
|  | *  Success: ERROR_SUCCESS. | 
|  | *  Failure: An NTSTATUS error code. | 
|  | */ | 
|  | NTSTATUS WINAPI NtClose( HANDLE Handle ) | 
|  | { | 
|  | NTSTATUS ret; | 
|  | SERVER_START_REQ( close_handle ) | 
|  | { | 
|  | req->handle = Handle; | 
|  | ret = wine_server_call( req ); | 
|  | if (!ret && reply->fd != -1) close( reply->fd ); | 
|  | } | 
|  | SERVER_END_REQ; | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /* | 
|  | *	Directory functions | 
|  | */ | 
|  |  | 
|  | /************************************************************************** | 
|  | * NtOpenDirectoryObject [NTDLL.@] | 
|  | * ZwOpenDirectoryObject [NTDLL.@] | 
|  | * | 
|  | * Open a namespace directory object. | 
|  | * | 
|  | * PARAMS | 
|  | *  DirectoryHandle  [O] Destination for the new directory handle | 
|  | *  DesiredAccess    [I] Desired access to the directory | 
|  | *  ObjectAttributes [I] Structure describing the directory | 
|  | * | 
|  | * RETURNS | 
|  | *  Success: ERROR_SUCCESS. | 
|  | *  Failure: An NTSTATUS error code. | 
|  | */ | 
|  | NTSTATUS WINAPI NtOpenDirectoryObject( | 
|  | PHANDLE DirectoryHandle, | 
|  | ACCESS_MASK DesiredAccess, | 
|  | POBJECT_ATTRIBUTES ObjectAttributes) | 
|  | { | 
|  | FIXME("(%p,0x%08lx,%p): stub\n", | 
|  | DirectoryHandle, DesiredAccess, ObjectAttributes); | 
|  | dump_ObjectAttributes(ObjectAttributes); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | *  NtCreateDirectoryObject	[NTDLL.@] | 
|  | *  ZwCreateDirectoryObject	[NTDLL.@] | 
|  | */ | 
|  | NTSTATUS WINAPI NtCreateDirectoryObject( | 
|  | PHANDLE DirectoryHandle, | 
|  | ACCESS_MASK DesiredAccess, | 
|  | POBJECT_ATTRIBUTES ObjectAttributes) | 
|  | { | 
|  | FIXME("(%p,0x%08lx,%p),stub!\n", | 
|  | DirectoryHandle,DesiredAccess,ObjectAttributes); | 
|  | dump_ObjectAttributes(ObjectAttributes); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | * NtQueryDirectoryObject [NTDLL.@] | 
|  | * ZwQueryDirectoryObject [NTDLL.@] | 
|  | * | 
|  | * Read information from a namespace directory. | 
|  | * | 
|  | * PARAMS | 
|  | *  DirObjHandle      [I]   Object handle | 
|  | *  DirObjInformation [O]   Buffer to hold the data read | 
|  | *  BufferLength      [I]   Size of the buffer in bytes | 
|  | *  GetNextIndex      [I]   Set ObjectIndex to TRUE=next object, FALSE=last object | 
|  | *  IgnoreInputIndex  [I]   Start reading at index TRUE=0, FALSE=ObjectIndex | 
|  | *  ObjectIndex       [I/O] 0 based index into the directory, see IgnoreInputIndex and GetNextIndex | 
|  | *  DataWritten       [O]   Caller supplied storage for the number of bytes written (or NULL) | 
|  | * | 
|  | * RETURNS | 
|  | *  Success: ERROR_SUCCESS. | 
|  | *  Failure: An NTSTATUS error code. | 
|  | */ | 
|  | NTSTATUS WINAPI NtQueryDirectoryObject( | 
|  | IN HANDLE DirObjHandle, | 
|  | OUT POBJDIR_INFORMATION DirObjInformation, | 
|  | IN ULONG BufferLength, | 
|  | IN BOOLEAN GetNextIndex, | 
|  | IN BOOLEAN IgnoreInputIndex, | 
|  | IN OUT PULONG ObjectIndex, | 
|  | OUT PULONG DataWritten OPTIONAL) | 
|  | { | 
|  | FIXME("(%p,%p,0x%08lx,0x%08x,0x%08x,%p,%p) stub\n", | 
|  | DirObjHandle, DirObjInformation, BufferLength, GetNextIndex, | 
|  | IgnoreInputIndex, ObjectIndex, DataWritten); | 
|  | return 0xc0000000; /* We don't have any. Whatever. (Yet.) */ | 
|  | } | 
|  |  | 
|  | /* | 
|  | *	Link objects | 
|  | */ | 
|  |  | 
|  | /****************************************************************************** | 
|  | *  NtOpenSymbolicLinkObject	[NTDLL.@] | 
|  | */ | 
|  | NTSTATUS WINAPI NtOpenSymbolicLinkObject( | 
|  | OUT PHANDLE LinkHandle, | 
|  | IN ACCESS_MASK DesiredAccess, | 
|  | IN POBJECT_ATTRIBUTES ObjectAttributes) | 
|  | { | 
|  | FIXME("(%p,0x%08lx,%p) stub\n", | 
|  | LinkHandle, DesiredAccess, ObjectAttributes); | 
|  | dump_ObjectAttributes(ObjectAttributes); | 
|  | return STATUS_OBJECT_NAME_NOT_FOUND; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | *  NtCreateSymbolicLinkObject	[NTDLL.@] | 
|  | */ | 
|  | NTSTATUS WINAPI NtCreateSymbolicLinkObject( | 
|  | OUT PHANDLE SymbolicLinkHandle, | 
|  | IN ACCESS_MASK DesiredAccess, | 
|  | IN POBJECT_ATTRIBUTES ObjectAttributes, | 
|  | IN PUNICODE_STRING Name) | 
|  | { | 
|  | FIXME("(%p,0x%08lx,%p, %p) stub\n", | 
|  | SymbolicLinkHandle, DesiredAccess, ObjectAttributes, debugstr_us(Name)); | 
|  | dump_ObjectAttributes(ObjectAttributes); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | *  NtQuerySymbolicLinkObject	[NTDLL.@] | 
|  | */ | 
|  | NTSTATUS WINAPI NtQuerySymbolicLinkObject( | 
|  | IN HANDLE LinkHandle, | 
|  | IN OUT PUNICODE_STRING LinkTarget, | 
|  | OUT PULONG ReturnedLength OPTIONAL) | 
|  | { | 
|  | FIXME("(%p,%p,%p) stub\n", | 
|  | LinkHandle, debugstr_us(LinkTarget), ReturnedLength); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | *  NtAllocateUuids   [NTDLL.@] | 
|  | */ | 
|  | NTSTATUS WINAPI NtAllocateUuids( | 
|  | PULARGE_INTEGER Time, | 
|  | PULONG Range, | 
|  | PULONG Sequence) | 
|  | { | 
|  | FIXME("(%p,%p,%p), stub.\n", Time, Range, Sequence); | 
|  | return 0; | 
|  | } |