mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 09:52:56 +00:00
- Fix definitions of OB_QUERYNAME_METHOD and OB_OKAYTOCLOSE_METHOD. Add fixme for OB_SECURITY_METHOD, will change it later.
- Simplified NtDuplicateObject to a simple stub around ObDuplicateObject, there is no need to have lengthy hacks for NtCurrentProcess/NtCurrentThread(). - Cleanup ObDuplicateObject to use normal Ob routines instead of grovelling through handle table structures and manually touching the handle count: It now calls ObpIncrementHandleCount and all the underlying operations are done on the duplicated handle. Also access state creation is done if the duplicated handle has different desired access. svn path=/trunk/; revision=22303
This commit is contained in:
parent
d6a84751c7
commit
259db9be47
8 changed files with 252 additions and 279 deletions
|
@ -215,7 +215,7 @@ typedef NTSTATUS
|
||||||
(NTAPI *OB_SECURITY_METHOD)(
|
(NTAPI *OB_SECURITY_METHOD)(
|
||||||
IN PVOID Object,
|
IN PVOID Object,
|
||||||
IN SECURITY_OPERATION_CODE OperationType,
|
IN SECURITY_OPERATION_CODE OperationType,
|
||||||
IN SECURITY_INFORMATION SecurityInformation,
|
IN SECURITY_INFORMATION SecurityInformation, // FIXME: <= should be a pointer
|
||||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
IN OUT PULONG CapturedLength,
|
IN OUT PULONG CapturedLength,
|
||||||
IN OUT PSECURITY_DESCRIPTOR *ObjectSecurityDescriptor,
|
IN OUT PSECURITY_DESCRIPTOR *ObjectSecurityDescriptor,
|
||||||
|
@ -229,14 +229,16 @@ typedef NTSTATUS
|
||||||
IN BOOLEAN HasObjectName,
|
IN BOOLEAN HasObjectName,
|
||||||
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
|
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
|
||||||
IN ULONG Length,
|
IN ULONG Length,
|
||||||
OUT PULONG ReturnLength
|
OUT PULONG ReturnLength,
|
||||||
|
IN KPROCESSOR_MODE AccessMode
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef NTSTATUS
|
typedef NTSTATUS
|
||||||
(NTAPI *OB_OKAYTOCLOSE_METHOD)(
|
(NTAPI *OB_OKAYTOCLOSE_METHOD)(
|
||||||
IN PEPROCESS Process OPTIONAL,
|
IN PEPROCESS Process OPTIONAL,
|
||||||
IN PVOID Object,
|
IN PVOID Object,
|
||||||
IN HANDLE Handle
|
IN HANDLE Handle,
|
||||||
|
IN KPROCESSOR_MODE AccessMode
|
||||||
);
|
);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -467,7 +467,8 @@ CmiObjectQueryName (PVOID ObjectBody,
|
||||||
IN BOOLEAN HasObjectName,
|
IN BOOLEAN HasObjectName,
|
||||||
POBJECT_NAME_INFORMATION ObjectNameInfo,
|
POBJECT_NAME_INFORMATION ObjectNameInfo,
|
||||||
ULONG Length,
|
ULONG Length,
|
||||||
PULONG ReturnLength);
|
PULONG ReturnLength,
|
||||||
|
IN KPROCESSOR_MODE PreviousMode);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiImportHiveBins(PREGISTRY_HIVE Hive,
|
CmiImportHiveBins(PREGISTRY_HIVE Hive,
|
||||||
|
|
|
@ -691,7 +691,8 @@ CmiObjectQueryName (PVOID ObjectBody,
|
||||||
IN BOOLEAN HasName,
|
IN BOOLEAN HasName,
|
||||||
POBJECT_NAME_INFORMATION ObjectNameInfo,
|
POBJECT_NAME_INFORMATION ObjectNameInfo,
|
||||||
ULONG Length,
|
ULONG Length,
|
||||||
PULONG ReturnLength)
|
PULONG ReturnLength,
|
||||||
|
IN KPROCESSOR_MODE PreviousMode)
|
||||||
{
|
{
|
||||||
PKEY_OBJECT KeyObject;
|
PKEY_OBJECT KeyObject;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
|
@ -518,7 +518,8 @@ IopQueryNameFile(
|
||||||
IN BOOLEAN HasName,
|
IN BOOLEAN HasName,
|
||||||
POBJECT_NAME_INFORMATION ObjectNameInfo,
|
POBJECT_NAME_INFORMATION ObjectNameInfo,
|
||||||
ULONG Length,
|
ULONG Length,
|
||||||
PULONG ReturnLength
|
PULONG ReturnLength,
|
||||||
|
IN KPROCESSOR_MODE PreviousMode
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -121,18 +121,6 @@ ObpDeleteNameCheck(
|
||||||
IN PVOID Object
|
IN PVOID Object
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
ObDuplicateObject(
|
|
||||||
PEPROCESS SourceProcess,
|
|
||||||
PEPROCESS TargetProcess,
|
|
||||||
HANDLE SourceHandle,
|
|
||||||
PHANDLE TargetHandle,
|
|
||||||
ACCESS_MASK DesiredAccess,
|
|
||||||
ULONG HandleAttributes,
|
|
||||||
ULONG Options
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
ObQueryDeviceMapInformation(
|
ObQueryDeviceMapInformation(
|
||||||
|
|
|
@ -411,7 +411,8 @@ IopQueryNameFile(PVOID ObjectBody,
|
||||||
IN BOOLEAN HasName,
|
IN BOOLEAN HasName,
|
||||||
POBJECT_NAME_INFORMATION ObjectNameInfo,
|
POBJECT_NAME_INFORMATION ObjectNameInfo,
|
||||||
ULONG Length,
|
ULONG Length,
|
||||||
PULONG ReturnLength)
|
PULONG ReturnLength,
|
||||||
|
IN KPROCESSOR_MODE PreviousMode)
|
||||||
{
|
{
|
||||||
POBJECT_NAME_INFORMATION LocalInfo;
|
POBJECT_NAME_INFORMATION LocalInfo;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
|
|
|
@ -196,7 +196,8 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable,
|
||||||
/* Call it and check if it's not letting us close it */
|
/* Call it and check if it's not letting us close it */
|
||||||
if (!ObjectType->TypeInfo.OkayToCloseProcedure(PsGetCurrentProcess(),
|
if (!ObjectType->TypeInfo.OkayToCloseProcedure(PsGetCurrentProcess(),
|
||||||
Body,
|
Body,
|
||||||
Handle))
|
Handle,
|
||||||
|
AccessMode))
|
||||||
{
|
{
|
||||||
/* Fail */
|
/* Fail */
|
||||||
ExUnlockHandleTableEntry(HandleTable, HandleEntry);
|
ExUnlockHandleTableEntry(HandleTable, HandleEntry);
|
||||||
|
@ -1188,158 +1189,201 @@ ObKillProcess(IN PEPROCESS Process)
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
ObDuplicateObject(PEPROCESS SourceProcess,
|
ObDuplicateObject(IN PEPROCESS SourceProcess,
|
||||||
PEPROCESS TargetProcess,
|
IN HANDLE SourceHandle,
|
||||||
HANDLE SourceHandle,
|
IN PEPROCESS TargetProcess OPTIONAL,
|
||||||
PHANDLE TargetHandle,
|
IN PHANDLE TargetHandle OPTIONAL,
|
||||||
ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
ULONG HandleAttributes,
|
IN ULONG HandleAttributes,
|
||||||
ULONG Options)
|
IN ULONG Options,
|
||||||
|
IN KPROCESSOR_MODE PreviousMode)
|
||||||
{
|
{
|
||||||
PHANDLE_TABLE_ENTRY SourceHandleEntry;
|
|
||||||
HANDLE_TABLE_ENTRY NewHandleEntry;
|
HANDLE_TABLE_ENTRY NewHandleEntry;
|
||||||
BOOLEAN AttachedToProcess = FALSE;
|
BOOLEAN AttachedToProcess = FALSE;
|
||||||
PVOID ObjectBody;
|
PVOID SourceObject;
|
||||||
POBJECT_HEADER ObjectHeader;
|
POBJECT_HEADER ObjectHeader;
|
||||||
ULONG NewHandleCount;
|
POBJECT_TYPE ObjectType;
|
||||||
HANDLE NewTargetHandle;
|
HANDLE NewHandle;
|
||||||
PEPROCESS CurrentProcess;
|
|
||||||
KAPC_STATE ApcState;
|
KAPC_STATE ApcState;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
ACCESS_MASK TargetAccess, SourceAccess;
|
||||||
|
ACCESS_STATE AccessState;
|
||||||
|
PACCESS_STATE PassedAccessState = NULL;
|
||||||
|
AUX_DATA AuxData;
|
||||||
|
PHANDLE_TABLE HandleTable = NULL;
|
||||||
|
OBJECT_HANDLE_INFORMATION HandleInformation;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
OBTRACE("OBTRACE - %s - Duplicating handle: %lx for %p into %p\n",
|
||||||
|
__FUNCTION__,
|
||||||
|
SourceHandle,
|
||||||
|
SourceProcess,
|
||||||
|
TargetProcess);
|
||||||
|
|
||||||
if(SourceProcess == NULL ||
|
/* Check if we're not in the source process */
|
||||||
ObIsKernelHandle(SourceHandle, ExGetPreviousMode()))
|
if (SourceProcess != PsGetCurrentProcess())
|
||||||
{
|
{
|
||||||
SourceProcess = PsInitialSystemProcess;
|
/* Attach to it */
|
||||||
SourceHandle = ObKernelHandleToHandle(SourceHandle);
|
KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
|
||||||
}
|
|
||||||
|
|
||||||
CurrentProcess = PsGetCurrentProcess();
|
|
||||||
|
|
||||||
KeEnterCriticalRegion();
|
|
||||||
|
|
||||||
if (SourceProcess != CurrentProcess)
|
|
||||||
{
|
|
||||||
KeStackAttachProcess(&SourceProcess->Pcb,
|
|
||||||
&ApcState);
|
|
||||||
AttachedToProcess = TRUE;
|
AttachedToProcess = TRUE;
|
||||||
}
|
}
|
||||||
SourceHandleEntry = ExMapHandleToPointer(SourceProcess->ObjectTable,
|
|
||||||
SourceHandle);
|
|
||||||
if (SourceHandleEntry == NULL)
|
|
||||||
{
|
|
||||||
if (AttachedToProcess)
|
|
||||||
{
|
|
||||||
KeUnstackDetachProcess(&ApcState);
|
|
||||||
}
|
|
||||||
|
|
||||||
KeLeaveCriticalRegion();
|
/* Now reference the source handle */
|
||||||
return STATUS_INVALID_HANDLE;
|
Status = ObReferenceObjectByHandle(SourceHandle,
|
||||||
}
|
0,
|
||||||
|
NULL,
|
||||||
ObjectHeader = EX_HTE_TO_HDR(SourceHandleEntry);
|
PreviousMode,
|
||||||
ObjectBody = &ObjectHeader->Body;
|
(PVOID*)&SourceObject,
|
||||||
|
&HandleInformation);
|
||||||
NewHandleEntry.Object = SourceHandleEntry->Object;
|
|
||||||
if(HandleAttributes & OBJ_INHERIT)
|
|
||||||
NewHandleEntry.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
|
|
||||||
else
|
|
||||||
NewHandleEntry.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
|
|
||||||
NewHandleEntry.GrantedAccess = ((Options & DUPLICATE_SAME_ACCESS) ?
|
|
||||||
SourceHandleEntry->GrantedAccess :
|
|
||||||
DesiredAccess);
|
|
||||||
if (Options & DUPLICATE_SAME_ACCESS)
|
|
||||||
{
|
|
||||||
NewHandleEntry.GrantedAccess = SourceHandleEntry->GrantedAccess;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (DesiredAccess & GENERIC_ACCESS)
|
|
||||||
{
|
|
||||||
RtlMapGenericMask(&DesiredAccess,
|
|
||||||
&ObjectHeader->Type->TypeInfo.GenericMapping);
|
|
||||||
}
|
|
||||||
NewHandleEntry.GrantedAccess = DesiredAccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reference the object so it doesn't get deleted after releasing the lock
|
|
||||||
and before creating a new handle for it */
|
|
||||||
ObReferenceObject(ObjectBody);
|
|
||||||
|
|
||||||
/* increment the handle count of the object, it should always be >= 2 because
|
|
||||||
we're holding a handle lock to this object! if the new handle count was
|
|
||||||
1 here, we're in big trouble... it would've been safe to increment and
|
|
||||||
check the handle count without using interlocked functions because the
|
|
||||||
entry is locked, which means the handle count can't change. */
|
|
||||||
NewHandleCount = InterlockedIncrement(&ObjectHeader->HandleCount);
|
|
||||||
ASSERT(NewHandleCount >= 2);
|
|
||||||
|
|
||||||
ExUnlockHandleTableEntry(SourceProcess->ObjectTable,
|
|
||||||
SourceHandleEntry);
|
|
||||||
|
|
||||||
|
/* Check if we were attached */
|
||||||
if (AttachedToProcess)
|
if (AttachedToProcess)
|
||||||
{
|
{
|
||||||
|
/* We can safely detach now */
|
||||||
KeUnstackDetachProcess(&ApcState);
|
KeUnstackDetachProcess(&ApcState);
|
||||||
AttachedToProcess = FALSE;
|
AttachedToProcess = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TargetProcess != CurrentProcess)
|
/* Fail if we couldn't reference it */
|
||||||
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
|
/* Get the source access */
|
||||||
|
SourceAccess = HandleInformation.GrantedAccess;
|
||||||
|
|
||||||
|
/* Check if we're not in the target process */
|
||||||
|
if (TargetProcess != PsGetCurrentProcess())
|
||||||
{
|
{
|
||||||
KeStackAttachProcess(&TargetProcess->Pcb,
|
/* Attach to it */
|
||||||
&ApcState);
|
KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
|
||||||
AttachedToProcess = TRUE;
|
AttachedToProcess = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* attempt to create the new handle */
|
/* Check if we're duplicating the attributes */
|
||||||
NewTargetHandle = ExCreateHandle(TargetProcess->ObjectTable,
|
if (Options & DUPLICATE_SAME_ATTRIBUTES)
|
||||||
&NewHandleEntry);
|
{
|
||||||
|
/* Duplicate them */
|
||||||
|
HandleAttributes = HandleInformation.HandleAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we're duplicating the access */
|
||||||
|
if (Options & DUPLICATE_SAME_ACCESS) DesiredAccess = SourceAccess;
|
||||||
|
|
||||||
|
/* Get object data */
|
||||||
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(SourceObject);
|
||||||
|
ObjectType = ObjectHeader->Type;
|
||||||
|
|
||||||
|
/* Fill out the entry */
|
||||||
|
NewHandleEntry.Object = ObjectHeader;
|
||||||
|
NewHandleEntry.ObAttributes |= HandleAttributes &
|
||||||
|
(EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
|
||||||
|
EX_HANDLE_ENTRY_INHERITABLE |
|
||||||
|
EX_HANDLE_ENTRY_AUDITONCLOSE);
|
||||||
|
|
||||||
|
/* Check if we're using a generic mask */
|
||||||
|
if (DesiredAccess & GENERIC_ACCESS)
|
||||||
|
{
|
||||||
|
/* Map it */
|
||||||
|
RtlMapGenericMask(&DesiredAccess, &ObjectType->TypeInfo.GenericMapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the target access */
|
||||||
|
TargetAccess = DesiredAccess;
|
||||||
|
NewHandleEntry.GrantedAccess = TargetAccess;
|
||||||
|
|
||||||
|
/* Check if we're asking for new access */
|
||||||
|
if (TargetAccess & ~SourceAccess)
|
||||||
|
{
|
||||||
|
/* We are. We need the security procedure to validate this */
|
||||||
|
if (ObjectType->TypeInfo.SecurityProcedure == SeDefaultObjectMethod)
|
||||||
|
{
|
||||||
|
/* Use our built-in access state */
|
||||||
|
PassedAccessState = &AccessState;
|
||||||
|
Status = SeCreateAccessState(&AccessState,
|
||||||
|
&AuxData,
|
||||||
|
TargetAccess,
|
||||||
|
&ObjectType->TypeInfo.GenericMapping);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise we can't allow this privilege elevation */
|
||||||
|
Status = STATUS_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We don't need an access state */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure the access state was created OK */
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Add a new handle */
|
||||||
|
Status = ObpIncrementHandleCount(SourceObject,
|
||||||
|
PassedAccessState,
|
||||||
|
PreviousMode,
|
||||||
|
HandleAttributes,
|
||||||
|
PsGetCurrentProcess(),
|
||||||
|
ObDuplicateHandle);
|
||||||
|
|
||||||
|
/* Set the handle table, now that we know this handle was added */
|
||||||
|
HandleTable = PsGetCurrentProcess()->ObjectTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we were attached */
|
||||||
if (AttachedToProcess)
|
if (AttachedToProcess)
|
||||||
{
|
{
|
||||||
|
/* We can safely detach now */
|
||||||
KeUnstackDetachProcess(&ApcState);
|
KeUnstackDetachProcess(&ApcState);
|
||||||
AttachedToProcess = FALSE;
|
AttachedToProcess = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NewTargetHandle != NULL)
|
/* Check if we have to close the source handle */
|
||||||
|
if (Options & DUPLICATE_CLOSE_SOURCE)
|
||||||
{
|
{
|
||||||
if (Options & DUPLICATE_CLOSE_SOURCE)
|
/* Attach and close */
|
||||||
{
|
KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
|
||||||
if (SourceProcess != CurrentProcess)
|
NtClose(SourceHandle);
|
||||||
{
|
KeUnstackDetachProcess(&ApcState);
|
||||||
KeStackAttachProcess(&SourceProcess->Pcb,
|
|
||||||
&ApcState);
|
|
||||||
AttachedToProcess = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* delete the source handle */
|
|
||||||
NtClose(SourceHandle);
|
|
||||||
|
|
||||||
if (AttachedToProcess)
|
|
||||||
{
|
|
||||||
KeUnstackDetachProcess(&ApcState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ObDereferenceObject(ObjectBody);
|
|
||||||
|
|
||||||
*TargetHandle = NewTargetHandle;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* decrement the handle count we previously incremented, but don't call the
|
|
||||||
closing procedure because we're not closing a handle! */
|
|
||||||
if(InterlockedDecrement(&ObjectHeader->HandleCount) == 0)
|
|
||||||
{
|
|
||||||
ObDereferenceObject(ObjectBody);
|
|
||||||
}
|
|
||||||
|
|
||||||
ObDereferenceObject(ObjectBody);
|
|
||||||
Status = STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeLeaveCriticalRegion();
|
/* Check if we had an access state */
|
||||||
|
if (PassedAccessState) SeDeleteAccessState(PassedAccessState);
|
||||||
|
|
||||||
|
/* Now check if incrementing actually failed */
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Dereference the source object */
|
||||||
|
ObDereferenceObject(SourceObject);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now create the handle */
|
||||||
|
ObDereferenceObject(SourceObject);
|
||||||
|
NewHandle = ExCreateHandle(HandleTable, &NewHandleEntry);
|
||||||
|
if (!NewHandle)
|
||||||
|
{
|
||||||
|
/* Undo the increment */
|
||||||
|
ObpDecrementHandleCount(SourceObject,
|
||||||
|
TargetProcess,
|
||||||
|
TargetAccess);
|
||||||
|
|
||||||
|
/* Deference the object and set failure status */
|
||||||
|
ObDereferenceObject(SourceObject);
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the handle */
|
||||||
|
if (TargetHandle) *TargetHandle = NewHandle;
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
|
OBTRACE("OBTRACE - %s - Duplicated handle: %lx for %p into %p. Source: %p HC PC %lx %lx\n",
|
||||||
|
__FUNCTION__,
|
||||||
|
NewHandle,
|
||||||
|
SourceProcess,
|
||||||
|
TargetProcess,
|
||||||
|
SourceObject,
|
||||||
|
ObjectHeader->PointerCount,
|
||||||
|
ObjectHeader->HandleCount);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1934,184 +1978,118 @@ NtClose(IN HANDLE Handle)
|
||||||
return ObpCloseHandle(Handle, ExGetPreviousMode());
|
return ObpCloseHandle(Handle, ExGetPreviousMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
NTSTATUS
|
||||||
* @implemented
|
NTAPI
|
||||||
*/
|
NtDuplicateObject(IN HANDLE SourceProcessHandle,
|
||||||
NTSTATUS STDCALL
|
IN HANDLE SourceHandle,
|
||||||
NtDuplicateObject (IN HANDLE SourceProcessHandle,
|
IN HANDLE TargetProcessHandle OPTIONAL,
|
||||||
IN HANDLE SourceHandle,
|
OUT PHANDLE TargetHandle OPTIONAL,
|
||||||
IN HANDLE TargetProcessHandle,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
OUT PHANDLE TargetHandle OPTIONAL,
|
IN ULONG HandleAttributes,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ULONG Options)
|
||||||
IN ULONG HandleAttributes,
|
|
||||||
IN ULONG Options)
|
|
||||||
{
|
{
|
||||||
PEPROCESS SourceProcess;
|
PEPROCESS SourceProcess, TargetProcess, Target;
|
||||||
PEPROCESS TargetProcess;
|
|
||||||
PEPROCESS CurrentProcess;
|
|
||||||
HANDLE hTarget;
|
HANDLE hTarget;
|
||||||
BOOLEAN AttachedToProcess = FALSE;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
KPROCESSOR_MODE PreviousMode;
|
|
||||||
KAPC_STATE ApcState;
|
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
ACCESS_STATE AccessState;
|
|
||||||
AUX_DATA AuxData;
|
|
||||||
PACCESS_STATE PassedAccessState = NULL;
|
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
OBTRACE("OBTRACE - %s - Duplicating handle: %lx for %lx into %lx.\n",
|
||||||
|
__FUNCTION__,
|
||||||
|
SourceHandle,
|
||||||
|
SourceProcessHandle,
|
||||||
|
TargetProcessHandle);
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
if((TargetHandle) && (PreviousMode != KernelMode))
|
||||||
|
|
||||||
if(TargetHandle != NULL && PreviousMode != KernelMode)
|
|
||||||
{
|
{
|
||||||
|
/* Enter SEH */
|
||||||
_SEH_TRY
|
_SEH_TRY
|
||||||
{
|
{
|
||||||
|
/* Probe the handle */
|
||||||
ProbeForWriteHandle(TargetHandle);
|
ProbeForWriteHandle(TargetHandle);
|
||||||
}
|
}
|
||||||
_SEH_HANDLE
|
_SEH_HANDLE
|
||||||
{
|
{
|
||||||
|
/* Get the exception status */
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
}
|
||||||
_SEH_END;
|
_SEH_END;
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
/* Fail if the pointer was invalid */
|
||||||
{
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now reference the input handle */
|
||||||
Status = ObReferenceObjectByHandle(SourceProcessHandle,
|
Status = ObReferenceObjectByHandle(SourceProcessHandle,
|
||||||
PROCESS_DUP_HANDLE,
|
PROCESS_DUP_HANDLE,
|
||||||
NULL,
|
PsProcessType,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
(PVOID*)&SourceProcess,
|
(PVOID*)&SourceProcess,
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status)) return(Status);
|
||||||
|
|
||||||
|
/* Check if got a target handle */
|
||||||
|
if (TargetProcessHandle)
|
||||||
{
|
{
|
||||||
return(Status);
|
/* Now reference the output handle */
|
||||||
}
|
Status = ObReferenceObjectByHandle(TargetProcessHandle,
|
||||||
|
PROCESS_DUP_HANDLE,
|
||||||
Status = ObReferenceObjectByHandle(TargetProcessHandle,
|
PsProcessType,
|
||||||
PROCESS_DUP_HANDLE,
|
PreviousMode,
|
||||||
NULL,
|
(PVOID*)&TargetProcess,
|
||||||
PreviousMode,
|
NULL);
|
||||||
(PVOID*)&TargetProcess,
|
if (NT_SUCCESS(Status))
|
||||||
NULL);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
ObDereferenceObject(SourceProcess);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentProcess = PsGetCurrentProcess();
|
|
||||||
|
|
||||||
/* Check for magic handle first */
|
|
||||||
if (SourceHandle == NtCurrentThread() ||
|
|
||||||
SourceHandle == NtCurrentProcess())
|
|
||||||
{
|
|
||||||
PVOID ObjectBody;
|
|
||||||
POBJECT_TYPE ObjectType;
|
|
||||||
|
|
||||||
ObjectType = (SourceHandle == NtCurrentThread()) ? PsThreadType : PsProcessType;
|
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(SourceHandle,
|
|
||||||
0,
|
|
||||||
ObjectType,
|
|
||||||
PreviousMode,
|
|
||||||
&ObjectBody,
|
|
||||||
NULL);
|
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
if (Options & DUPLICATE_SAME_ACCESS)
|
/* Use this target process */
|
||||||
{
|
Target = TargetProcess;
|
||||||
/* grant all access rights */
|
}
|
||||||
DesiredAccess = ((ObjectType == PsThreadType) ? THREAD_ALL_ACCESS : PROCESS_ALL_ACCESS);
|
else
|
||||||
}
|
{
|
||||||
else
|
/* No target process */
|
||||||
{
|
Target = NULL;
|
||||||
if (DesiredAccess & GENERIC_ACCESS)
|
|
||||||
{
|
|
||||||
RtlMapGenericMask(&DesiredAccess,
|
|
||||||
&ObjectType->TypeInfo.GenericMapping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TargetProcess != CurrentProcess)
|
|
||||||
{
|
|
||||||
KeStackAttachProcess(&TargetProcess->Pcb,
|
|
||||||
&ApcState);
|
|
||||||
AttachedToProcess = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use our built-in access state */
|
|
||||||
PassedAccessState = &AccessState;
|
|
||||||
Status = SeCreateAccessState(&AccessState,
|
|
||||||
&AuxData,
|
|
||||||
DesiredAccess,
|
|
||||||
&ObjectType->TypeInfo.GenericMapping);
|
|
||||||
|
|
||||||
/* Add a new handle */
|
|
||||||
Status = ObpIncrementHandleCount(ObjectBody,
|
|
||||||
PassedAccessState,
|
|
||||||
PreviousMode,
|
|
||||||
HandleAttributes,
|
|
||||||
PsGetCurrentProcess(),
|
|
||||||
ObDuplicateHandle);
|
|
||||||
|
|
||||||
if (AttachedToProcess)
|
|
||||||
{
|
|
||||||
KeUnstackDetachProcess(&ApcState);
|
|
||||||
AttachedToProcess = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ObDereferenceObject(ObjectBody);
|
|
||||||
|
|
||||||
if (Options & DUPLICATE_CLOSE_SOURCE)
|
|
||||||
{
|
|
||||||
if (SourceProcess != CurrentProcess)
|
|
||||||
{
|
|
||||||
KeStackAttachProcess(&SourceProcess->Pcb,
|
|
||||||
&ApcState);
|
|
||||||
AttachedToProcess = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
NtClose(SourceHandle);
|
|
||||||
|
|
||||||
if (AttachedToProcess)
|
|
||||||
{
|
|
||||||
KeUnstackDetachProcess(&ApcState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Status = ObDuplicateObject(SourceProcess,
|
/* No target process */
|
||||||
TargetProcess,
|
Status = STATUS_SUCCESS;
|
||||||
SourceHandle,
|
Target = NULL;
|
||||||
&hTarget,
|
|
||||||
DesiredAccess,
|
|
||||||
HandleAttributes,
|
|
||||||
Options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ObDereferenceObject(TargetProcess);
|
/* Call the internal routine */
|
||||||
ObDereferenceObject(SourceProcess);
|
Status = ObDuplicateObject(SourceProcess,
|
||||||
|
SourceHandle,
|
||||||
|
Target,
|
||||||
|
&hTarget,
|
||||||
|
DesiredAccess,
|
||||||
|
HandleAttributes,
|
||||||
|
Options,
|
||||||
|
PreviousMode);
|
||||||
|
|
||||||
if(NT_SUCCESS(Status) && TargetHandle != NULL)
|
/* Check if the caller wanted the return handle */
|
||||||
|
if (TargetHandle)
|
||||||
{
|
{
|
||||||
|
/* Protect the write to user mode */
|
||||||
_SEH_TRY
|
_SEH_TRY
|
||||||
{
|
{
|
||||||
|
/* Write the new handle */
|
||||||
*TargetHandle = hTarget;
|
*TargetHandle = hTarget;
|
||||||
}
|
}
|
||||||
_SEH_HANDLE
|
_SEH_HANDLE
|
||||||
{
|
{
|
||||||
|
/* Otherwise, get the exception code */
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
}
|
||||||
_SEH_END;
|
_SEH_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dereference the processes */
|
||||||
|
OBTRACE("OBTRACE - %s - Duplicated handle: %lx into %lx S %lx\n",
|
||||||
|
__FUNCTION__,
|
||||||
|
hTarget,
|
||||||
|
TargetProcessHandle,
|
||||||
|
Status);
|
||||||
|
ObDereferenceObject(TargetProcess);
|
||||||
|
ObDereferenceObject(SourceProcess);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -394,7 +394,7 @@ Next:
|
||||||
/* PUBLIC FUNCTIONS *********************************************************/
|
/* PUBLIC FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
NTAPI
|
||||||
ObQueryNameString(IN PVOID Object,
|
ObQueryNameString(IN PVOID Object,
|
||||||
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
|
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
|
||||||
IN ULONG Length,
|
IN ULONG Length,
|
||||||
|
@ -418,7 +418,8 @@ ObQueryNameString(IN PVOID Object,
|
||||||
TRUE, //fixme
|
TRUE, //fixme
|
||||||
ObjectNameInfo,
|
ObjectNameInfo,
|
||||||
Length,
|
Length,
|
||||||
ReturnLength);
|
ReturnLength,
|
||||||
|
KernelMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the object doesn't even have a name */
|
/* Check if the object doesn't even have a name */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue