- Fix ExChangeHandle not to send NULL but the actual context to the callback function (fix by Thomas Weidenmueller <w3seek@reactos.org>)

- Re-implement NtSetInformationObject based on ExChangeHandle and using ObpSetHandleAttributes as a callback.
- Re-implement NtQueryObject's ObjectHandleInformation case to simply return the information that's already in HandleAttributes; there is no point in querying for it all over again.
- Fix NtSetInformationObject not to allow a user-mode call to modify kernel-mdoe handle attributes. Add FIXME for Inheritance permissions check.
- Fix NtQueryObject to properly return OBJ_PERMANENT and OBJ_EXCLUSIVE; these flags are not stored in Handle Attributes.
- Fix NtQueryObject not to attempt referencing the handle if the caller specified AllTypesInformation, because then a handle is not needed.

svn path=/trunk/; revision=22228
This commit is contained in:
Alex Ionescu 2006-06-05 00:04:36 +00:00
parent 7c2e312093
commit 02d0bb9dbd
4 changed files with 203 additions and 182 deletions

View file

@ -916,7 +916,7 @@ ExChangeHandle(IN PHANDLE_TABLE HandleTable,
{
Ret = ChangeHandleCallback(HandleTable,
HandleTableEntry,
NULL);
Context);
ExUnlockHandleTableEntry(HandleTable,
HandleTableEntry);

View file

@ -9,6 +9,12 @@
#ifndef __INCLUDE_INTERNAL_OBJMGR_H
#define __INCLUDE_INTERNAL_OBJMGR_H
typedef struct _OBP_SET_HANDLE_ATTRIBUTES_CONTEXT
{
KPROCESSOR_MODE PreviousMode;
OBJECT_HANDLE_ATTRIBUTE_INFORMATION Information;
} OBP_SET_HANDLE_ATTRIBUTES_CONTEXT, *POBP_SET_HANDLE_ATTRIBUTES_CONTEXT;
#define GENERIC_ACCESS (GENERIC_READ | \
GENERIC_WRITE | \
GENERIC_EXECUTE | \
@ -100,18 +106,12 @@ ObFindObject(
IN PVOID Insert
);
NTSTATUS
NTAPI
ObpQueryHandleAttributes(
HANDLE Handle,
POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
);
NTSTATUS
BOOLEAN
NTAPI
ObpSetHandleAttributes(
HANDLE Handle,
POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
IN PHANDLE_TABLE HandleTable,
IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry,
IN PVOID Context
);
NTSTATUS

View file

@ -154,129 +154,51 @@ ObpDecrementHandleCount(PVOID ObjectBody)
}
}
NTSTATUS
BOOLEAN
NTAPI
ObpQueryHandleAttributes(HANDLE Handle,
POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
ObpSetHandleAttributes(IN PHANDLE_TABLE HandleTable,
IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry,
IN PVOID Context)
{
PHANDLE_TABLE_ENTRY HandleTableEntry;
PEPROCESS Process, CurrentProcess;
KAPC_STATE ApcState;
BOOLEAN AttachedToProcess = FALSE;
NTSTATUS Status = STATUS_SUCCESS;
POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo =
(POBP_SET_HANDLE_ATTRIBUTES_CONTEXT)Context;
POBJECT_HEADER ObjectHeader = EX_HTE_TO_HDR(HandleTableEntry);
PAGED_CODE();
DPRINT("ObpQueryHandleAttributes(Handle %p)\n", Handle);
CurrentProcess = PsGetCurrentProcess();
KeEnterCriticalRegion();
if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
/* Don't allow operations on kernel objects */
if ((ObjectHeader->Flags & OB_FLAG_KERNEL_MODE) &&
(SetHandleInfo->PreviousMode != KernelMode))
{
Process = PsInitialSystemProcess;
Handle = ObKernelHandleToHandle(Handle);
/* Fail */
return FALSE;
}
if (Process != CurrentProcess)
{
KeStackAttachProcess(&Process->Pcb,
&ApcState);
AttachedToProcess = TRUE;
}
/* Check if making the handle inheritable */
if (SetHandleInfo->Information.Inherit)
{
/* Set the flag. FIXME: Need to check if this is allowed */
HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
}
else
{
Process = CurrentProcess;
/* Otherwise this implies we're removing the flag */
HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
}
HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
Handle);
if (HandleTableEntry != NULL)
/* Check if making the handle protected */
if (SetHandleInfo->Information.ProtectFromClose)
{
HandleInfo->Inherit = (HandleTableEntry->ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
HandleInfo->ProtectFromClose = (HandleTableEntry->ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0;
ExUnlockHandleTableEntry(Process->ObjectTable,
HandleTableEntry);
}
else
Status = STATUS_INVALID_HANDLE;
if (AttachedToProcess)
{
KeUnstackDetachProcess(&ApcState);
}
KeLeaveCriticalRegion();
return Status;
}
NTSTATUS
NTAPI
ObpSetHandleAttributes(HANDLE Handle,
POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
{
PHANDLE_TABLE_ENTRY HandleTableEntry;
PEPROCESS Process, CurrentProcess;
KAPC_STATE ApcState;
BOOLEAN AttachedToProcess = FALSE;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT("ObpSetHandleAttributes(Handle %p)\n", Handle);
CurrentProcess = PsGetCurrentProcess();
KeEnterCriticalRegion();
if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
{
Process = PsInitialSystemProcess;
Handle = ObKernelHandleToHandle(Handle);
if (Process != CurrentProcess)
{
KeStackAttachProcess(&Process->Pcb,
&ApcState);
AttachedToProcess = TRUE;
}
/* Set the flag */
HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
}
else
{
Process = CurrentProcess;
/* Otherwise, remove it */
HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
}
HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
Handle);
if (HandleTableEntry != NULL)
{
if (HandleInfo->Inherit)
HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
else
HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
if (HandleInfo->ProtectFromClose)
HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
else
HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
/* FIXME: Do we need to set anything in the object header??? */
ExUnlockHandleTableEntry(Process->ObjectTable,
HandleTableEntry);
}
else
Status = STATUS_INVALID_HANDLE;
if (AttachedToProcess)
{
KeUnstackDetachProcess(&ApcState);
}
KeLeaveCriticalRegion();
return Status;
/* Return success */
return TRUE;
}
static NTSTATUS

View file

@ -790,95 +790,157 @@ NtQueryObject(IN HANDLE ObjectHandle,
OUT PULONG ResultLength OPTIONAL)
{
OBJECT_HANDLE_INFORMATION HandleInfo;
POBJECT_HEADER ObjectHeader;
POBJECT_HEADER ObjectHeader = NULL;
POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
POBJECT_BASIC_INFORMATION BasicInfo;
ULONG InfoLength;
PVOID Object;
PVOID Object = NULL;
NTSTATUS Status;
PAGED_CODE();
Status = ObReferenceObjectByHandle(ObjectHandle,
0,
NULL,
KeGetPreviousMode(),
&Object,
&HandleInfo);
if (!NT_SUCCESS (Status)) return Status;
/* FIXME: Needs SEH */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
/*
* Make sure this isn't a generic type query, since the caller doesn't
* have to give a handle for it
*/
if (ObjectInformationClass != ObjectAllTypesInformation)
{
/* Reference the object */
Status = ObReferenceObjectByHandle(ObjectHandle,
0,
NULL,
KeGetPreviousMode(),
&Object,
&HandleInfo);
if (!NT_SUCCESS (Status)) return Status;
/* Get the object header */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
}
/* Check the information class */
switch (ObjectInformationClass)
{
case ObjectBasicInformation:
InfoLength = sizeof(OBJECT_BASIC_INFORMATION);
if (Length != sizeof(OBJECT_BASIC_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
}
else
{
POBJECT_BASIC_INFORMATION BasicInfo;
/* Basic info */
case ObjectBasicInformation:
/* Validate length */
InfoLength = sizeof(OBJECT_BASIC_INFORMATION);
if (Length != sizeof(OBJECT_BASIC_INFORMATION))
{
/* Fail */
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
/* Fill out the basic information */
BasicInfo = (POBJECT_BASIC_INFORMATION)ObjectInformation;
BasicInfo->Attributes = HandleInfo.HandleAttributes;
BasicInfo->GrantedAccess = HandleInfo.GrantedAccess;
BasicInfo->HandleCount = ObjectHeader->HandleCount;
BasicInfo->PointerCount = ObjectHeader->PointerCount;
/* Permanent/Exclusive Flags are NOT in Handle attributes! */
if (ObjectHeader->Flags & OB_FLAG_EXCLUSIVE)
{
/* Set the flag */
BasicInfo->Attributes |= OBJ_EXCLUSIVE;
}
if (ObjectHeader->Flags & OB_FLAG_PERMANENT)
{
/* Set the flag */
BasicInfo->Attributes |= OBJ_PERMANENT;
}
/* Copy quota information */
BasicInfo->PagedPoolUsage = 0; /* FIXME*/
BasicInfo->NonPagedPoolUsage = 0; /* FIXME*/
/* Copy name information */
BasicInfo->NameInformationLength = 0; /* FIXME*/
BasicInfo->TypeInformationLength = 0; /* FIXME*/
/* Copy security information */
BasicInfo->SecurityDescriptorLength = 0; /* FIXME*/
/* Check if this is a symlink */
if (ObjectHeader->Type == ObSymbolicLinkType)
{
/* Return the creation time */
BasicInfo->CreateTime.QuadPart =
((POBJECT_SYMBOLIC_LINK)Object)->CreationTime.QuadPart;
}
else
{
/* Otherwise return 0 */
BasicInfo->CreateTime.QuadPart = (ULONGLONG)0;
}
/* Break out with success */
Status = STATUS_SUCCESS;
}
break;
break;
case ObjectNameInformation:
Status = ObQueryNameString(Object,
(POBJECT_NAME_INFORMATION)ObjectInformation,
Length,
&InfoLength);
break;
/* Name information */
case ObjectNameInformation:
case ObjectTypeInformation:
Status = STATUS_NOT_IMPLEMENTED;
break;
/* Call the helper and break out */
Status = ObQueryNameString(Object,
(POBJECT_NAME_INFORMATION)
ObjectInformation,
Length,
&InfoLength);
break;
case ObjectAllTypesInformation:
Status = STATUS_NOT_IMPLEMENTED;
break;
/* Information about this type */
case ObjectTypeInformation:
DPRINT1("NOT IMPLEMENTED!\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case ObjectHandleInformation:
InfoLength = sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION);
if (Length != sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
}
else
{
Status = ObpQueryHandleAttributes(
ObjectHandle,
(POBJECT_HANDLE_ATTRIBUTE_INFORMATION)ObjectInformation);
}
break;
/* Information about all types */
case ObjectAllTypesInformation:
DPRINT1("NOT IMPLEMENTED!\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
default:
Status = STATUS_INVALID_INFO_CLASS;
break;
/* Information about the handle flags */
case ObjectHandleInformation:
/* Validate length */
InfoLength = sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION);
if (Length != sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
/* Get the structure */
HandleFlags = (POBJECT_HANDLE_ATTRIBUTE_INFORMATION)
ObjectInformation;
/* Set the flags */
HandleFlags->Inherit = (HandleInfo.HandleAttributes &
EX_HANDLE_ENTRY_INHERITABLE) != 0;
HandleFlags->ProtectFromClose = (HandleInfo.HandleAttributes &
EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0;
/* Break out with success */
Status = STATUS_SUCCESS;
break;
/* Anything else */
default:
/* Fail it */
Status = STATUS_INVALID_INFO_CLASS;
break;
}
ObDereferenceObject (Object);
if (ResultLength != NULL) *ResultLength = InfoLength;
/* Derefernece the object if we had referenced it */
if (Object) ObDereferenceObject (Object);
/* Return the length and status */
if (ResultLength) *ResultLength = InfoLength;
return Status;
}
@ -912,29 +974,66 @@ NtSetInformationObject(IN HANDLE ObjectHandle,
IN PVOID ObjectInformation,
IN ULONG Length)
{
PVOID Object;
NTSTATUS Status;
NTSTATUS Status = STATUS_SUCCESS;
OBP_SET_HANDLE_ATTRIBUTES_CONTEXT Context;
PVOID ObjectTable;
KAPC_STATE ApcState;
BOOLEAN AttachedToProcess = FALSE;
PAGED_CODE();
/* Validate the information class */
if (ObjectInformationClass != ObjectHandleInformation)
{
/* Invalid class */
return STATUS_INVALID_INFO_CLASS;
}
/* Validate the length */
if (Length != sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION))
{
/* Invalid length */
return STATUS_INFO_LENGTH_MISMATCH;
}
Status = ObReferenceObjectByHandle(ObjectHandle,
0,
NULL,
KeGetPreviousMode(),
&Object,
NULL);
if (!NT_SUCCESS (Status)) return Status;
/* Save the previous mode and actual information */
Context.PreviousMode = ExGetPreviousMode();
Context.Information = *(POBJECT_HANDLE_ATTRIBUTE_INFORMATION)
ObjectInformation;
Status = ObpSetHandleAttributes(ObjectHandle,
(POBJECT_HANDLE_ATTRIBUTE_INFORMATION)
ObjectInformation);
/* Check if this is a kernel handle */
if (ObIsKernelHandle(ObjectHandle, Context.PreviousMode))
{
/* Get the actual handle */
ObjectHandle = ObKernelHandleToHandle(ObjectHandle);
ObjectTable = ObpKernelHandleTable;
ObDereferenceObject (Object);
/* Check if we're not in the system process */
if (PsGetCurrentProcess() != PsInitialSystemProcess)
{
/* Attach to it */
KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
AttachedToProcess = TRUE;
}
}
else
{
/* Use the current table */
ObjectTable = PsGetCurrentProcess()->ObjectTable;
}
/* Change the handle attributes */
if (!ExChangeHandle(ObjectTable,
ObjectHandle,
ObpSetHandleAttributes,
&Context))
{
/* Some failure */
Status = STATUS_ACCESS_DENIED;
}
/* De-attach if we were attached, and return status */
if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
return Status;
}
/* EOF */