Author: ion Date: Thu Jun 22 06:20:34 2006 New Revision: 22494
URL: http://svn.reactos.ru/svn/reactos?rev=22494&view=rev Log: - Rename obwait/obsecure - Check for valid access in NtSignalAndWaitForSingleObject and don't check if ResultLength isn't NULL in NtQueryObject, because it's not optional. - Add Thomas's name to a file where it wasn't. - Reformatting (only code change is #2 above)
Added: trunk/reactos/ntoskrnl/ob/obsecure.c - copied, changed from r22345, trunk/reactos/ntoskrnl/ob/security.c trunk/reactos/ntoskrnl/ob/obwait.c - copied, changed from r22345, trunk/reactos/ntoskrnl/ob/wait.c Removed: trunk/reactos/ntoskrnl/ob/security.c trunk/reactos/ntoskrnl/ob/wait.c
Copied: trunk/reactos/ntoskrnl/ob/obsecure.c (from r22345, trunk/reactos/ntoskrnl/ob/security.c) URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/ob/obsecure.c?p2=tr... ============================================================================== --- trunk/reactos/ntoskrnl/ob/security.c (original) +++ trunk/reactos/ntoskrnl/ob/obsecure.c Thu Jun 22 06:20:34 2006 @@ -1,7 +1,7 @@ /* * PROJECT: ReactOS Kernel * LICENSE: GPL - See COPYING in the top level directory -* FILE: ntoskrnl/ob/security.c +* FILE: ntoskrnl/ob/obsecure.c * PURPOSE: SRM Interface of the Object Manager * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) * Eric Kohl @@ -12,6 +12,8 @@ #include <ntoskrnl.h> #define NDEBUG #include <internal/debug.h> + +#define TAG_SEC_QUERY TAG('O', 'b', 'S', 'q')
/* FUNCTIONS ***************************************************************/
@@ -144,7 +146,7 @@ /* Allocate security descriptor */ *SecurityDescriptor = ExAllocatePoolWithTag(PagedPool, Length, - TAG('O', 'b', 'S', 'q')); + TAG_SEC_QUERY); if (!(*SecurityDescriptor)) return STATUS_INSUFFICIENT_RESOURCES;
/* Query security descriptor */ @@ -248,72 +250,75 @@ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); PVOID Object; POBJECT_HEADER Header; - ACCESS_MASK DesiredAccess = (ACCESS_MASK)0; + POBJECT_TYPE Type; + ACCESS_MASK DesiredAccess; NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE();
+ /* Check if we came from user mode */ if (PreviousMode != KernelMode) { + /* Enter SEH */ _SEH_TRY { + /* Probe the SD and the length pointer */ ProbeForWrite(SecurityDescriptor, Length, sizeof(ULONG)); - if (ResultLength != NULL) - { ProbeForWriteUlong(ResultLength); - } } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END;
+ /* Fail if we got an access violation */ if (!NT_SUCCESS(Status)) return Status; }
- /* get the required access rights for the operation */ - SeQuerySecurityAccessMask(SecurityInformation, - &DesiredAccess); - + /* Get the required access rights for the operation */ + SeQuerySecurityAccessMask(SecurityInformation, &DesiredAccess); + + /* Reference the object */ Status = ObReferenceObjectByHandle(Handle, DesiredAccess, NULL, PreviousMode, &Object, NULL); - - if (NT_SUCCESS(Status)) - { - Header = OBJECT_TO_OBJECT_HEADER(Object); - ASSERT(Header->Type != NULL); - - Status = Header->Type->TypeInfo.SecurityProcedure( - Object, - QuerySecurityDescriptor, - SecurityInformation, - SecurityDescriptor, - &Length, - &Header->SecurityDescriptor, - Header->Type->TypeInfo.PoolType, - &Header->Type->TypeInfo.GenericMapping); - - ObDereferenceObject(Object); - - /* return the required length */ - if (ResultLength != NULL) - { - _SEH_TRY - { - *ResultLength = Length; - } - _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - } - + if (!NT_SUCCESS(Status)) return Status; + + /* Get the Object Header and Type */ + Header = OBJECT_TO_OBJECT_HEADER(Object); + Type = Header->Type; + + /* Call the security procedure's query function */ + Status = Type->TypeInfo.SecurityProcedure(Object, + QuerySecurityDescriptor, + SecurityInformation, + SecurityDescriptor, + &Length, + &Header->SecurityDescriptor, + Type->TypeInfo.PoolType, + &Type->TypeInfo.GenericMapping); + + /* Dereference the object */ + ObDereferenceObject(Object); + + /* Protect write with SEH */ + _SEH_TRY + { + /* Return the needed length */ + *ResultLength = Length; + } + _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) + { + /* Get the exception code */ + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + /* Return status */ return Status; }
@@ -346,75 +351,140 @@ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); PVOID Object; POBJECT_HEADER Header; - SECURITY_DESCRIPTOR_RELATIVE *CapturedSecurityDescriptor; - ACCESS_MASK DesiredAccess = (ACCESS_MASK)0; + POBJECT_TYPE Type; + SECURITY_DESCRIPTOR_RELATIVE *CapturedDescriptor; + ACCESS_MASK DesiredAccess; NTSTATUS Status; PAGED_CODE();
- /* make sure the caller doesn't pass a NULL security descriptor! */ - if (SecurityDescriptor == NULL) return STATUS_ACCESS_DENIED; - - /* capture and make a copy of the security descriptor */ + /* Make sure the caller doesn't pass a NULL security descriptor! */ + if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION; + + /* Capture and make a copy of the security descriptor */ Status = SeCaptureSecurityDescriptor(SecurityDescriptor, PreviousMode, PagedPool, TRUE, (PSECURITY_DESCRIPTOR*) - &CapturedSecurityDescriptor); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Capturing the security descriptor failed! Status: 0x%lx\n", Status); - return Status; - } + &CapturedDescriptor); + if (!NT_SUCCESS(Status)) return Status;
/* - * make sure the security descriptor passed by the caller + * Make sure the security descriptor passed by the caller * is valid for the operation we're about to perform */ if (((SecurityInformation & OWNER_SECURITY_INFORMATION) && - (CapturedSecurityDescriptor->Owner == 0)) || + !(CapturedDescriptor->Owner)) || ((SecurityInformation & GROUP_SECURITY_INFORMATION) && - (CapturedSecurityDescriptor->Group == 0))) - { + !(CapturedDescriptor->Group))) + { + /* Set the failure status */ Status = STATUS_INVALID_SECURITY_DESCR; } else { - /* get the required access rights for the operation */ - SeSetSecurityAccessMask(SecurityInformation, - &DesiredAccess); - + /* Set the required access rights for the operation */ + SeSetSecurityAccessMask(SecurityInformation, &DesiredAccess); + + /* Reference the object */ Status = ObReferenceObjectByHandle(Handle, DesiredAccess, NULL, PreviousMode, &Object, NULL); - if (NT_SUCCESS(Status)) { + /* Get the Object Header and Type */ Header = OBJECT_TO_OBJECT_HEADER(Object); - ASSERT(Header->Type != NULL); - - Status = Header->Type->TypeInfo.SecurityProcedure( - Object, - SetSecurityDescriptor, - SecurityInformation, - (PSECURITY_DESCRIPTOR)SecurityDescriptor, - NULL, - &Header->SecurityDescriptor, - Header->Type->TypeInfo.PoolType, - &Header->Type->TypeInfo.GenericMapping); - + Type = Header->Type; + + /* Call the security procedure's set function */ + Status = Type->TypeInfo.SecurityProcedure(Object, + SetSecurityDescriptor, + SecurityInformation, + SecurityDescriptor, + NULL, + &Header-> + SecurityDescriptor, + Type->TypeInfo.PoolType, + &Type-> + TypeInfo.GenericMapping); + + /* Now we can dereference the object */ ObDereferenceObject(Object); } }
- /* release the descriptor */ - SeReleaseSecurityDescriptor((PSECURITY_DESCRIPTOR)CapturedSecurityDescriptor, + /* Release the descriptor and return status */ + SeReleaseSecurityDescriptor((PSECURITY_DESCRIPTOR)CapturedDescriptor, PreviousMode, TRUE); - + return Status; +} + +/*++ +* @name ObQueryObjectAuditingByHandle +* @implemented NT5 +* +* The ObDereferenceSecurityDescriptor routine <FILLMEIN> +* +* @param SecurityDescriptor +* <FILLMEIN> +* +* @param Count +* <FILLMEIN> +* +* @return STATUS_SUCCESS or appropriate error value. +* +* @remarks None. +* +*--*/ +NTSTATUS +NTAPI +ObQueryObjectAuditingByHandle(IN HANDLE Handle, + OUT PBOOLEAN GenerateOnClose) +{ + PHANDLE_TABLE_ENTRY HandleEntry; + PVOID HandleTable; + NTSTATUS Status = STATUS_SUCCESS; + PAGED_CODE(); + + /* Check if we're dealing with a kernel handle */ + if (ObIsKernelHandle(Handle, ExGetPreviousMode())) + { + /* Use the kernel table and convert the handle */ + HandleTable = ObpKernelHandleTable; + Handle = ObKernelHandleToHandle(Handle); + } + else + { + /* Use the process's handle table */ + HandleTable = PsGetCurrentProcess()->ObjectTable; + } + + /* Enter a critical region while we touch the handle table */ + KeEnterCriticalRegion(); + + /* Map the handle */ + HandleEntry = ExMapHandleToPointer(HandleTable, Handle); + if(HandleEntry) + { + /* Check if the flag is set */ + *GenerateOnClose = (HandleEntry->ObAttributes & + EX_HANDLE_ENTRY_AUDITONCLOSE) != 0; + + /* Unlock the entry */ + ExUnlockHandleTableEntry(HandleTable, HandleEntry); + } + else + { + /* Otherwise, fail */ + Status = STATUS_INVALID_HANDLE; + } + + /* Leave the critical region and return the status */ + KeLeaveCriticalRegion(); return Status; }
@@ -480,69 +550,4 @@ DPRINT1("ObDereferenceSecurityDescriptor is not implemented!\n"); }
-/*++ -* @name ObQueryObjectAuditingByHandle -* @implemented NT5 -* -* The ObDereferenceSecurityDescriptor routine <FILLMEIN> -* -* @param SecurityDescriptor -* <FILLMEIN> -* -* @param Count -* <FILLMEIN> -* -* @return STATUS_SUCCESS or appropriate error value. -* -* @remarks None. -* -*--*/ -NTSTATUS -NTAPI -ObQueryObjectAuditingByHandle(IN HANDLE Handle, - OUT PBOOLEAN GenerateOnClose) -{ - PHANDLE_TABLE_ENTRY HandleEntry; - PVOID HandleTable; - NTSTATUS Status = STATUS_SUCCESS; - PAGED_CODE(); - - /* Check if we're dealing with a kernel handle */ - if (ObIsKernelHandle(Handle, ExGetPreviousMode())) - { - /* Use the kernel table and convert the handle */ - HandleTable = ObpKernelHandleTable; - Handle = ObKernelHandleToHandle(Handle); - } - else - { - /* Use the process's handle table */ - HandleTable = PsGetCurrentProcess()->ObjectTable; - } - - /* Enter a critical region while we touch the handle table */ - KeEnterCriticalRegion(); - - /* Map the handle */ - HandleEntry = ExMapHandleToPointer(HandleTable, Handle); - if(HandleEntry) - { - /* Check if the flag is set */ - *GenerateOnClose = (HandleEntry->ObAttributes & - EX_HANDLE_ENTRY_AUDITONCLOSE) != 0; - - /* Unlock the entry */ - ExUnlockHandleTableEntry(HandleTable, HandleEntry); - } - else - { - /* Otherwise, fail */ - Status = STATUS_INVALID_HANDLE; - } - - /* Leave the critical region and return the status */ - KeLeaveCriticalRegion(); - return Status; -} - /* EOF */
Copied: trunk/reactos/ntoskrnl/ob/obwait.c (from r22345, trunk/reactos/ntoskrnl/ob/wait.c) URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/ob/obwait.c?p2=trun... ============================================================================== --- trunk/reactos/ntoskrnl/ob/wait.c (original) +++ trunk/reactos/ntoskrnl/ob/obwait.c Thu Jun 22 06:20:34 2006 @@ -1,10 +1,10 @@ /* * PROJECT: ReactOS Kernel * LICENSE: GPL - See COPYING in the top level directory - * FILE: ntoskrnl/ob/wait.c + * FILE: ntoskrnl/ob/obwait.c * PURPOSE: Handles Waiting on Objects * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - * David Welch (welch@mcmail.com) + * Thomas Weidenmueller (w3seek@reactos.org) */
/* INCLUDES ******************************************************************/ @@ -65,7 +65,6 @@ ACCESS_MASK GrantedAccess; PVOID DefaultObject; NTSTATUS Status = STATUS_SUCCESS; - DPRINT("NtWaitForMultipleObjects(ObjectCount %lu HandleArray[] %x," " Alertable %d, TimeOut %x)\n", ObjectCount, HandleArray, Alertable, TimeOut); @@ -78,7 +77,6 @@ if ((ObjectCount > MAXIMUM_WAIT_OBJECTS) || !ObjectCount) { Status = STATUS_INVALID_PARAMETER_1; - DPRINT1("No object count, or too many objects\n"); goto Quickie; }
@@ -86,20 +84,20 @@ if ((WaitType != WaitAll) && (WaitType != WaitAny)) { Status = STATUS_INVALID_PARAMETER_3; - DPRINT1("Invalid wait type\n"); goto Quickie; }
- /* Capture arguments */ + /* Enter SEH */ _SEH_TRY { + /* Check if the call came from user mode */ if(PreviousMode != KernelMode) { + /* Probe all the handles */ ProbeForRead(HandleArray, ObjectCount * sizeof(HANDLE), sizeof(HANDLE)); - - if(TimeOut) + if (TimeOut) { /* Make a local copy of the timeout on the stack */ SafeTimeOut = ProbeForReadLargeInteger(TimeOut); @@ -118,18 +116,21 @@ } _SEH_HANDLE { + /* Get exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END;
- if(!NT_SUCCESS(Status)) goto Quickie; + /* Fail if we raised an exception */ + if (!NT_SUCCESS(Status)) goto Quickie;
/* Check if we can use the internal Wait Array */ if (ObjectCount > THREAD_WAIT_OBJECTS) { /* Allocate from Pool */ WaitBlockArray = ExAllocatePoolWithTag(NonPagedPool, - ObjectCount * sizeof(KWAIT_BLOCK), + ObjectCount * + sizeof(KWAIT_BLOCK), TAG_WAIT); }
@@ -137,7 +138,7 @@ do { /* Use the right Executive Handle */ - if(ObIsKernelHandle(Handles[i], PreviousMode)) + if (ObIsKernelHandle(Handles[i], PreviousMode)) { /* Use the System Handle Table and decode */ HandleTable = ObpKernelHandleTable; @@ -164,7 +165,6 @@ /* Unlock the entry and fail */ ExUnlockHandleTableEntry(HandleTable, HandleEntry); Status = STATUS_ACCESS_DENIED; - DPRINT1("Handle doesn't have SYNCH access\n"); goto Quickie; }
@@ -218,7 +218,6 @@ { /* Fail */ Status = STATUS_INVALID_PARAMETER_MIX; - DPRINT1("Objects duplicated with WaitAll\n"); goto Quickie; } } @@ -247,6 +246,7 @@ } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END; @@ -255,9 +255,13 @@ /* First derefence */ while (ReferencedObjects) { + /* Decrease the number of objects */ ReferencedObjects--; + + /* Check if we had a valid object in this position */ if (Objects[ReferencedObjects]) { + /* Dereference it */ ObDereferenceObject(Objects[ReferencedObjects]); } } @@ -269,7 +273,6 @@ if (LockInUse) KeLeaveCriticalRegion();
/* Return status */ - DPRINT("Returning: %x\n", Status); return Status; }
@@ -303,12 +306,11 @@ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); LARGE_INTEGER SafeTimeOut; NTSTATUS Status = STATUS_SUCCESS; - DPRINT("NtWaitForSingleObject(ObjectHandle %x, Alertable %d, TimeOut %x)\n", ObjectHandle,Alertable,TimeOut);
- /* Capture timeout */ - if(TimeOut && PreviousMode != KernelMode) + /* Check if we came with a timeout from user mode */ + if (TimeOut && PreviousMode != KernelMode) { _SEH_TRY { @@ -318,11 +320,13 @@ } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END;
- if(!NT_SUCCESS(Status)) return Status; + /* Fail if we got an access violation */ + if (!NT_SUCCESS(Status)) return Status; }
/* Get the Object */ @@ -345,9 +349,10 @@ (ULONG_PTR)WaitableObject); }
- /* Now wait. Also SEH this since it can also raise an exception */ + /* SEH this since it can also raise an exception */ _SEH_TRY { + /* Ask the kernel to do the wait */ Status = KeWaitForSingleObject(WaitableObject, UserRequest, PreviousMode, @@ -356,6 +361,7 @@ } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END; @@ -407,9 +413,8 @@ OBJECT_HANDLE_INFORMATION HandleInfo; NTSTATUS Status = STATUS_SUCCESS;
- /* Capture timeout */ - DPRINT("NtSignalAndWaitForSingleObject\n"); - if(TimeOut && PreviousMode != KernelMode) + /* Check if we came with a timeout from user mode */ + if (TimeOut && PreviousMode != KernelMode) { _SEH_TRY { @@ -419,11 +424,13 @@ } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END;
- if(!NT_SUCCESS(Status)) return Status; + /* Fail if we got an access violation */ + if (!NT_SUCCESS(Status)) return Status; }
/* Start by getting the signal object*/ @@ -433,10 +440,7 @@ PreviousMode, &SignalObj, &HandleInfo); - if (!NT_SUCCESS(Status)) - { - return Status; - } + if (!NT_SUCCESS(Status)) return Status;
/* Now get the wait object */ Status = ObReferenceObjectByHandle(WaitableObjectHandle, @@ -447,6 +451,7 @@ NULL); if (!NT_SUCCESS(Status)) { + /* Failed to reference the wait object */ ObDereferenceObject(SignalObj); return Status; } @@ -461,67 +466,88 @@ WaitableObject = (PVOID)((ULONG_PTR)WaitObj + (ULONG_PTR)WaitableObject); } - + /* Check Signal Object Type */ Type = OBJECT_TO_OBJECT_HEADER(WaitObj)->Type; if (Type == ExEventObjectType) { + /* Check if we came from user-mode without the right access */ + if ((PreviousMode != KernelMode) && + !(HandleInfo.GrantedAccess & EVENT_MODIFY_STATE)) + { + /* Fail: lack of rights */ + goto Quickie; + } + /* Set the Event */ - /* FIXME: Check permissions */ KeSetEvent(SignalObj, EVENT_INCREMENT, TRUE); } else if (Type == ExMutantObjectType) { - /* Release the Mutant. This can raise an exception*/ + /* This can raise an exception */ _SEH_TRY { + /* Release the mutant */ KeReleaseMutant(SignalObj, MUTANT_INCREMENT, FALSE, TRUE); } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + else if (Type == ExSemaphoreObjectType) + { + /* Check if we came from user-mode without the right access */ + if ((PreviousMode != KernelMode) && + !(HandleInfo.GrantedAccess & SEMAPHORE_MODIFY_STATE)) + { + /* Fail: lack of rights */ goto Quickie; } + + /* This can raise an exception*/ + _SEH_TRY + { + /* Release the semaphore */ + KeReleaseSemaphore(SignalObj, SEMAPHORE_INCREMENT, 1, TRUE); + } + _SEH_HANDLE + { + /* Get the exception code */ + Status = _SEH_GetExceptionCode(); + } _SEH_END; } - else if (Type == ExSemaphoreObjectType) - { - /* Release the Semaphore. This can raise an exception*/ - /* FIXME: Check permissions */ + else + { + /* This isn't a valid object to be waiting on */ + Status = STATUS_OBJECT_TYPE_MISMATCH; + } + + /* Make sure we didn't fail */ + if (NT_SUCCESS(Status)) + { + /* SEH this since it can also raise an exception */ _SEH_TRY { - KeReleaseSemaphore(SignalObj, SEMAPHORE_INCREMENT, 1, TRUE); + /* Perform the wait now */ + Status = KeWaitForSingleObject(WaitableObject, + UserRequest, + PreviousMode, + Alertable, + TimeOut); } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); - goto Quickie; } _SEH_END; } - else - { - Status = STATUS_OBJECT_TYPE_MISMATCH; - DPRINT1("Waiting on invalid object type\n"); - goto Quickie; - } - - /* Now wait. Also SEH this since it can also raise an exception */ - _SEH_TRY - { - Status = KeWaitForSingleObject(WaitableObject, - UserRequest, - PreviousMode, - Alertable, - TimeOut); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - /* We're done here */ + + /* We're done here, dereference both objects */ Quickie: ObDereferenceObject(SignalObj); ObDereferenceObject(WaitObj);
Removed: trunk/reactos/ntoskrnl/ob/security.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/ob/security.c?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/ob/security.c (original) +++ trunk/reactos/ntoskrnl/ob/security.c (removed) @@ -1,548 +1,0 @@ -/* -* PROJECT: ReactOS Kernel -* LICENSE: GPL - See COPYING in the top level directory -* FILE: ntoskrnl/ob/security.c -* PURPOSE: SRM Interface of the Object Manager -* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) -* Eric Kohl -*/ - -/* INCLUDES *****************************************************************/ - -#include <ntoskrnl.h> -#define NDEBUG -#include <internal/debug.h> - -/* FUNCTIONS ***************************************************************/ - -/*++ -* @name ObAssignSecurity -* @implemented NT4 -* -* The ObAssignSecurity routine <FILLMEIN> -* -* @param AccessState -* <FILLMEIN> -* -* @param SecurityDescriptor -* <FILLMEIN> -* -* @param Object -* <FILLMEIN> -* -* @param Type -* <FILLMEIN> -* -* @return STATUS_SUCCESS or appropriate error value. -* -* @remarks None. -* -*--*/ -NTSTATUS -NTAPI -ObAssignSecurity(IN PACCESS_STATE AccessState, - IN PSECURITY_DESCRIPTOR SecurityDescriptor, - IN PVOID Object, - IN POBJECT_TYPE Type) -{ - PSECURITY_DESCRIPTOR NewDescriptor; - NTSTATUS Status; - PAGED_CODE(); - - /* Build the new security descriptor */ - Status = SeAssignSecurity(SecurityDescriptor, - AccessState->SecurityDescriptor, - &NewDescriptor, - (Type == ObDirectoryType), - &AccessState->SubjectSecurityContext, - &Type->TypeInfo.GenericMapping, - PagedPool); - if (!NT_SUCCESS(Status)) return Status; - - /* Call the security method */ - Status = Type->TypeInfo.SecurityProcedure(Object, - AssignSecurityDescriptor, - 0, - NewDescriptor, - NULL, - NULL, - PagedPool, - &Type->TypeInfo.GenericMapping); - if (!NT_SUCCESS(Status)) - { - /* Release the new security descriptor */ - SeDeassignSecurity(&NewDescriptor); - } - - /* Return to caller */ - return Status; -} - -/*++ -* @name ObGetObjectSecurity -* @implemented NT4 -* -* The ObGetObjectSecurity routine <FILLMEIN> -* -* @param Object -* <FILLMEIN> -* -* @param SecurityDescriptor -* <FILLMEIN> -* -* @param MemoryAllocated -* <FILLMEIN> -* -* @return STATUS_SUCCESS or appropriate error value. -* -* @remarks None. -* -*--*/ -NTSTATUS -NTAPI -ObGetObjectSecurity(IN PVOID Object, - OUT PSECURITY_DESCRIPTOR *SecurityDescriptor, - OUT PBOOLEAN MemoryAllocated) -{ - POBJECT_HEADER Header; - POBJECT_TYPE Type; - ULONG Length; - NTSTATUS Status; - PAGED_CODE(); - - /* Get the object header and type */ - Header = OBJECT_TO_OBJECT_HEADER(Object); - Type = Header->Type; - - /* Check if the object uses default security */ - if (Type->TypeInfo.SecurityProcedure == SeDefaultObjectMethod) - { - /* Reference the descriptor */ - *SecurityDescriptor = - ObpReferenceCachedSecurityDescriptor(Header->SecurityDescriptor); - - /* Tell the caller that we didn't have to allocate anything */ - *MemoryAllocated = FALSE; - return STATUS_SUCCESS; - } - - /* Get the security descriptor size */ - Length = 0; - Status = Type->TypeInfo.SecurityProcedure(Object, - QuerySecurityDescriptor, - OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION | - SACL_SECURITY_INFORMATION, - *SecurityDescriptor, - &Length, - &Header->SecurityDescriptor, - Type->TypeInfo.PoolType, - &Type->TypeInfo.GenericMapping); - if (Status != STATUS_BUFFER_TOO_SMALL) return Status; - - /* Allocate security descriptor */ - *SecurityDescriptor = ExAllocatePoolWithTag(PagedPool, - Length, - TAG('O', 'b', 'S', 'q')); - if (!(*SecurityDescriptor)) return STATUS_INSUFFICIENT_RESOURCES; - - /* Query security descriptor */ - *MemoryAllocated = TRUE; - Status = Type->TypeInfo.SecurityProcedure(Object, - QuerySecurityDescriptor, - OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION | - SACL_SECURITY_INFORMATION, - *SecurityDescriptor, - &Length, - &Header->SecurityDescriptor, - Type->TypeInfo.PoolType, - &Type->TypeInfo.GenericMapping); - if (!NT_SUCCESS(Status)) - { - /* Free the descriptor and tell the caller we failed */ - ExFreePool(*SecurityDescriptor); - *MemoryAllocated = FALSE; - } - - /* Return status */ - return Status; -} - -/*++ -* @name ObReleaseObjectSecurity -* @implemented NT4 -* -* The ObReleaseObjectSecurity routine <FILLMEIN> -* -* @param SecurityDescriptor -* <FILLMEIN> -* -* @param MemoryAllocated -* <FILLMEIN> -* -* @return STATUS_SUCCESS or appropriate error value. -* -* @remarks None. -* -*--*/ -VOID -NTAPI -ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor, - IN BOOLEAN MemoryAllocated) -{ - PAGED_CODE(); - - /* Nothing to do in this case */ - if (!SecurityDescriptor) return; - - /* Check if we had allocated it from memory */ - if (MemoryAllocated) - { - /* Free it */ - ExFreePool(SecurityDescriptor); - } - else - { - /* Otherwise this means we used an internal descriptor */ - ObpDereferenceCachedSecurityDescriptor(SecurityDescriptor); - } -} - -/*++ -* @name NtQuerySecurityObject -* @implemented NT4 -* -* The NtQuerySecurityObject routine <FILLMEIN> -* -* @param Handle -* <FILLMEIN> -* -* @param SecurityInformation -* <FILLMEIN> -* -* @param SecurityDescriptor -* <FILLMEIN> -* -* @param Length -* <FILLMEIN> -* -* @param ResultLength -* <FILLMEIN> -* -* @return STATUS_SUCCESS or appropriate error value. -* -* @remarks None. -* -*--*/ -NTSTATUS -NTAPI -NtQuerySecurityObject(IN HANDLE Handle, - IN SECURITY_INFORMATION SecurityInformation, - OUT PSECURITY_DESCRIPTOR SecurityDescriptor, - IN ULONG Length, - OUT PULONG ResultLength) -{ - KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - PVOID Object; - POBJECT_HEADER Header; - ACCESS_MASK DesiredAccess = (ACCESS_MASK)0; - NTSTATUS Status = STATUS_SUCCESS; - PAGED_CODE(); - - if (PreviousMode != KernelMode) - { - _SEH_TRY - { - ProbeForWrite(SecurityDescriptor, Length, sizeof(ULONG)); - if (ResultLength != NULL) - { - ProbeForWriteUlong(ResultLength); - } - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) return Status; - } - - /* get the required access rights for the operation */ - SeQuerySecurityAccessMask(SecurityInformation, - &DesiredAccess); - - Status = ObReferenceObjectByHandle(Handle, - DesiredAccess, - NULL, - PreviousMode, - &Object, - NULL); - - if (NT_SUCCESS(Status)) - { - Header = OBJECT_TO_OBJECT_HEADER(Object); - ASSERT(Header->Type != NULL); - - Status = Header->Type->TypeInfo.SecurityProcedure( - Object, - QuerySecurityDescriptor, - SecurityInformation, - SecurityDescriptor, - &Length, - &Header->SecurityDescriptor, - Header->Type->TypeInfo.PoolType, - &Header->Type->TypeInfo.GenericMapping); - - ObDereferenceObject(Object); - - /* return the required length */ - if (ResultLength != NULL) - { - _SEH_TRY - { - *ResultLength = Length; - } - _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - } - - return Status; -} - -/*++ -* @name NtSetSecurityObject -* @implemented NT4 -* -* The NtSetSecurityObject routine <FILLMEIN> -* -* @param Handle -* <FILLMEIN> -* -* @param SecurityInformation -* <FILLMEIN> -* -* @param SecurityDescriptor -* <FILLMEIN> -* -* @return STATUS_SUCCESS or appropriate error value. -* -* @remarks None. -* -*--*/ -NTSTATUS -NTAPI -NtSetSecurityObject(IN HANDLE Handle, - IN SECURITY_INFORMATION SecurityInformation, - IN PSECURITY_DESCRIPTOR SecurityDescriptor) -{ - KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - PVOID Object; - POBJECT_HEADER Header; - SECURITY_DESCRIPTOR_RELATIVE *CapturedSecurityDescriptor; - ACCESS_MASK DesiredAccess = (ACCESS_MASK)0; - NTSTATUS Status; - PAGED_CODE(); - - /* make sure the caller doesn't pass a NULL security descriptor! */ - if (SecurityDescriptor == NULL) return STATUS_ACCESS_DENIED; - - /* capture and make a copy of the security descriptor */ - Status = SeCaptureSecurityDescriptor(SecurityDescriptor, - PreviousMode, - PagedPool, - TRUE, - (PSECURITY_DESCRIPTOR*) - &CapturedSecurityDescriptor); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Capturing the security descriptor failed! Status: 0x%lx\n", Status); - return Status; - } - - /* - * make sure the security descriptor passed by the caller - * is valid for the operation we're about to perform - */ - if (((SecurityInformation & OWNER_SECURITY_INFORMATION) && - (CapturedSecurityDescriptor->Owner == 0)) || - ((SecurityInformation & GROUP_SECURITY_INFORMATION) && - (CapturedSecurityDescriptor->Group == 0))) - { - Status = STATUS_INVALID_SECURITY_DESCR; - } - else - { - /* get the required access rights for the operation */ - SeSetSecurityAccessMask(SecurityInformation, - &DesiredAccess); - - Status = ObReferenceObjectByHandle(Handle, - DesiredAccess, - NULL, - PreviousMode, - &Object, - NULL); - - if (NT_SUCCESS(Status)) - { - Header = OBJECT_TO_OBJECT_HEADER(Object); - ASSERT(Header->Type != NULL); - - Status = Header->Type->TypeInfo.SecurityProcedure( - Object, - SetSecurityDescriptor, - SecurityInformation, - (PSECURITY_DESCRIPTOR)SecurityDescriptor, - NULL, - &Header->SecurityDescriptor, - Header->Type->TypeInfo.PoolType, - &Header->Type->TypeInfo.GenericMapping); - - ObDereferenceObject(Object); - } - } - - /* release the descriptor */ - SeReleaseSecurityDescriptor((PSECURITY_DESCRIPTOR)CapturedSecurityDescriptor, - PreviousMode, - TRUE); - - return Status; -} - -/*++ -* @name ObLogSecurityDescriptor -* @unimplemented NT5.2 -* -* The ObLogSecurityDescriptor routine <FILLMEIN> -* -* @param InputSecurityDescriptor -* <FILLMEIN> -* -* @param OutputSecurityDescriptor -* <FILLMEIN> -* -* @param RefBias -* <FILLMEIN> -* -* @return STATUS_SUCCESS or appropriate error value. -* -* @remarks None. -* -*--*/ -NTSTATUS -NTAPI -ObLogSecurityDescriptor(IN PSECURITY_DESCRIPTOR InputSecurityDescriptor, - OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor, - IN ULONG RefBias) -{ - /* HACK: Return the same descriptor back */ - PISECURITY_DESCRIPTOR SdCopy; - DPRINT1("ObLogSecurityDescriptor is not implemented!\n", - InputSecurityDescriptor); - - SdCopy = ExAllocatePool(PagedPool, sizeof(*SdCopy)); - RtlMoveMemory(SdCopy, InputSecurityDescriptor, sizeof(*SdCopy)); - *OutputSecurityDescriptor = SdCopy; - return STATUS_SUCCESS; -} - -/*++ -* @name ObDereferenceSecurityDescriptor -* @unimplemented NT5.2 -* -* The ObDereferenceSecurityDescriptor routine <FILLMEIN> -* -* @param SecurityDescriptor -* <FILLMEIN> -* -* @param Count -* <FILLMEIN> -* -* @return STATUS_SUCCESS or appropriate error value. -* -* @remarks None. -* -*--*/ -VOID -NTAPI -ObDereferenceSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, - IN ULONG Count) -{ - DPRINT1("ObDereferenceSecurityDescriptor is not implemented!\n"); -} - -/*++ -* @name ObQueryObjectAuditingByHandle -* @implemented NT5 -* -* The ObDereferenceSecurityDescriptor routine <FILLMEIN> -* -* @param SecurityDescriptor -* <FILLMEIN> -* -* @param Count -* <FILLMEIN> -* -* @return STATUS_SUCCESS or appropriate error value. -* -* @remarks None. -* -*--*/ -NTSTATUS -NTAPI -ObQueryObjectAuditingByHandle(IN HANDLE Handle, - OUT PBOOLEAN GenerateOnClose) -{ - PHANDLE_TABLE_ENTRY HandleEntry; - PVOID HandleTable; - NTSTATUS Status = STATUS_SUCCESS; - PAGED_CODE(); - - /* Check if we're dealing with a kernel handle */ - if (ObIsKernelHandle(Handle, ExGetPreviousMode())) - { - /* Use the kernel table and convert the handle */ - HandleTable = ObpKernelHandleTable; - Handle = ObKernelHandleToHandle(Handle); - } - else - { - /* Use the process's handle table */ - HandleTable = PsGetCurrentProcess()->ObjectTable; - } - - /* Enter a critical region while we touch the handle table */ - KeEnterCriticalRegion(); - - /* Map the handle */ - HandleEntry = ExMapHandleToPointer(HandleTable, Handle); - if(HandleEntry) - { - /* Check if the flag is set */ - *GenerateOnClose = (HandleEntry->ObAttributes & - EX_HANDLE_ENTRY_AUDITONCLOSE) != 0; - - /* Unlock the entry */ - ExUnlockHandleTableEntry(HandleTable, HandleEntry); - } - else - { - /* Otherwise, fail */ - Status = STATUS_INVALID_HANDLE; - } - - /* Leave the critical region and return the status */ - KeLeaveCriticalRegion(); - return Status; -} - -/* EOF */
Removed: trunk/reactos/ntoskrnl/ob/wait.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/ob/wait.c?rev=22493... ============================================================================== --- trunk/reactos/ntoskrnl/ob/wait.c (original) +++ trunk/reactos/ntoskrnl/ob/wait.c (removed) @@ -1,531 +1,0 @@ -/* - * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory - * FILE: ntoskrnl/ob/wait.c - * PURPOSE: Handles Waiting on Objects - * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - * David Welch (welch@mcmail.com) - */ - -/* INCLUDES ******************************************************************/ - -#include <ntoskrnl.h> -#define NDEBUG -#include <internal/debug.h> - -#define TAG_WAIT TAG('W', 'a', 'i', 't') - -/* FUNCTIONS *****************************************************************/ - -/*++ -* @name NtWaitForMultipleObjects -* @implemented NT4 -* -* The NtWaitForMultipleObjects routine <FILLMEIN> -* -* @param ObjectCount -* <FILLMEIN> -* -* @param HandleArray -* <FILLMEIN> -* -* @param WaitType -* <FILLMEIN> -* -* @param Alertable -* <FILLMEIN> -* -* @param TimeOut -* <FILLMEIN> -* -* @return STATUS_SUCCESS or appropriate error value. -* -* @remarks None. -* -*--*/ -NTSTATUS -NTAPI -NtWaitForMultipleObjects(IN ULONG ObjectCount, - IN PHANDLE HandleArray, - IN WAIT_TYPE WaitType, - IN BOOLEAN Alertable, - IN PLARGE_INTEGER TimeOut OPTIONAL) -{ - PKWAIT_BLOCK WaitBlockArray = NULL; - HANDLE Handles[MAXIMUM_WAIT_OBJECTS]; - PVOID Objects[MAXIMUM_WAIT_OBJECTS]; - PVOID WaitObjects[MAXIMUM_WAIT_OBJECTS]; - ULONG i = 0, ReferencedObjects = 0, j; - KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - LARGE_INTEGER SafeTimeOut; - BOOLEAN LockInUse; - PHANDLE_TABLE_ENTRY HandleEntry; - POBJECT_HEADER ObjectHeader; - PHANDLE_TABLE HandleTable; - ACCESS_MASK GrantedAccess; - PVOID DefaultObject; - NTSTATUS Status = STATUS_SUCCESS; - - DPRINT("NtWaitForMultipleObjects(ObjectCount %lu HandleArray[] %x," - " Alertable %d, TimeOut %x)\n", - ObjectCount, HandleArray, Alertable, TimeOut); - - /* Enter a critical region since we'll play with handles */ - LockInUse = TRUE; - KeEnterCriticalRegion(); - - /* Check for valid Object Count */ - if ((ObjectCount > MAXIMUM_WAIT_OBJECTS) || !ObjectCount) - { - Status = STATUS_INVALID_PARAMETER_1; - DPRINT1("No object count, or too many objects\n"); - goto Quickie; - } - - /* Check for valid Wait Type */ - if ((WaitType != WaitAll) && (WaitType != WaitAny)) - { - Status = STATUS_INVALID_PARAMETER_3; - DPRINT1("Invalid wait type\n"); - goto Quickie; - } - - /* Capture arguments */ - _SEH_TRY - { - if(PreviousMode != KernelMode) - { - ProbeForRead(HandleArray, - ObjectCount * sizeof(HANDLE), - sizeof(HANDLE)); - - if(TimeOut) - { - /* Make a local copy of the timeout on the stack */ - SafeTimeOut = ProbeForReadLargeInteger(TimeOut); - TimeOut = &SafeTimeOut; - } - } - - /* - * Make a copy so we don't have to guard with SEH later and keep - * track of what objects we referenced if dereferencing pointers - * suddenly fails - */ - RtlCopyMemory(Handles, - HandleArray, - ObjectCount * sizeof(HANDLE)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if(!NT_SUCCESS(Status)) goto Quickie; - - /* Check if we can use the internal Wait Array */ - if (ObjectCount > THREAD_WAIT_OBJECTS) - { - /* Allocate from Pool */ - WaitBlockArray = ExAllocatePoolWithTag(NonPagedPool, - ObjectCount * sizeof(KWAIT_BLOCK), - TAG_WAIT); - } - - /* Start the loop */ - do - { - /* Use the right Executive Handle */ - if(ObIsKernelHandle(Handles[i], PreviousMode)) - { - /* Use the System Handle Table and decode */ - HandleTable = ObpKernelHandleTable; - Handles[i] = ObKernelHandleToHandle(Handles[i]); - } - else - { - /* Use the Process' Handle table and get the Ex Handle */ - HandleTable = PsGetCurrentProcess()->ObjectTable; - } - - /* Get a pointer to it */ - if (!(HandleEntry = ExMapHandleToPointer(HandleTable, Handles[i]))) - { - DPRINT1("Invalid handle\n"); - Status = STATUS_INVALID_HANDLE; - goto Quickie; - } - - /* Check for synchronize access */ - GrantedAccess = HandleEntry->GrantedAccess; - if ((PreviousMode != KernelMode) && (!(GrantedAccess & SYNCHRONIZE))) - { - /* Unlock the entry and fail */ - ExUnlockHandleTableEntry(HandleTable, HandleEntry); - Status = STATUS_ACCESS_DENIED; - DPRINT1("Handle doesn't have SYNCH access\n"); - goto Quickie; - } - - /* Get the Object Header */ - ObjectHeader = EX_HTE_TO_HDR(HandleEntry); - - /* Get default Object */ - DefaultObject = ObjectHeader->Type->DefaultObject; - - /* Check if it's the internal offset */ - if (IsPointerOffset(DefaultObject)) - { - /* Increase reference count */ - InterlockedIncrement(&ObjectHeader->PointerCount); - ReferencedObjects++; - - /* Save the Object and Wait Object, this is a relative offset */ - Objects[i] = &ObjectHeader->Body; - WaitObjects[i] = (PVOID)((ULONG_PTR)&ObjectHeader->Body + - (ULONG_PTR)DefaultObject); - } - else - { - /* This is our internal Object */ - ReferencedObjects++; - Objects[i] = NULL; - WaitObjects[i] = DefaultObject; - } - - /* Unlock the Handle Table Entry */ - ExUnlockHandleTableEntry(HandleTable, HandleEntry); - - /* Keep looping */ - i++; - } while (i < ObjectCount); - - /* For a Waitall, we can't have the same object more then once */ - if (WaitType == WaitAll) - { - /* Clear the main loop variable */ - i = 0; - - /* Start the loop */ - do - { - /* Check the current and forward object */ - for (j = i + 1; j < ObjectCount; j++) - { - /* Make sure they don't match */ - if (WaitObjects[i] == WaitObjects[j]) - { - /* Fail */ - Status = STATUS_INVALID_PARAMETER_MIX; - DPRINT1("Objects duplicated with WaitAll\n"); - goto Quickie; - } - } - - /* Keep looping */ - i++; - } while (i < ObjectCount); - } - - /* Now we can finally wait. Use SEH since it can raise an exception */ - _SEH_TRY - { - /* We're done playing with handles */ - LockInUse = FALSE; - KeLeaveCriticalRegion(); - - /* Do the kernel wait */ - Status = KeWaitForMultipleObjects(ObjectCount, - WaitObjects, - WaitType, - UserRequest, - PreviousMode, - Alertable, - TimeOut, - WaitBlockArray); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - -Quickie: - /* First derefence */ - while (ReferencedObjects) - { - ReferencedObjects--; - if (Objects[ReferencedObjects]) - { - ObDereferenceObject(Objects[ReferencedObjects]); - } - } - - /* Free wait block array */ - if (WaitBlockArray) ExFreePool(WaitBlockArray); - - /* Re-enable APCs if needed */ - if (LockInUse) KeLeaveCriticalRegion(); - - /* Return status */ - DPRINT("Returning: %x\n", Status); - return Status; -} - -/*++ -* @name NtWaitForSingleObject -* @implemented NT4 -* -* The NtWaitForSingleObject routine <FILLMEIN> -* -* @param ObjectHandle -* <FILLMEIN> -* -* @param Alertable -* <FILLMEIN> -* -* @param TimeOut -* <FILLMEIN> -* -* @return STATUS_SUCCESS or appropriate error value. -* -* @remarks None. -* -*--*/ -NTSTATUS -NTAPI -NtWaitForSingleObject(IN HANDLE ObjectHandle, - IN BOOLEAN Alertable, - IN PLARGE_INTEGER TimeOut OPTIONAL) -{ - PVOID Object, WaitableObject; - KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - LARGE_INTEGER SafeTimeOut; - NTSTATUS Status = STATUS_SUCCESS; - - DPRINT("NtWaitForSingleObject(ObjectHandle %x, Alertable %d, TimeOut %x)\n", - ObjectHandle,Alertable,TimeOut); - - /* Capture timeout */ - if(TimeOut && PreviousMode != KernelMode) - { - _SEH_TRY - { - /* Make a copy on the stack */ - SafeTimeOut = ProbeForReadLargeInteger(TimeOut); - TimeOut = &SafeTimeOut; - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if(!NT_SUCCESS(Status)) return Status; - } - - /* Get the Object */ - Status = ObReferenceObjectByHandle(ObjectHandle, - SYNCHRONIZE, - NULL, - PreviousMode, - &Object, - NULL); - if (NT_SUCCESS(Status)) - { - /* Get the Waitable Object */ - WaitableObject = OBJECT_TO_OBJECT_HEADER(Object)->Type->DefaultObject; - - /* Is it an offset for internal objects? */ - if (IsPointerOffset(WaitableObject)) - { - /* Turn it into a pointer */ - WaitableObject = (PVOID)((ULONG_PTR)Object + - (ULONG_PTR)WaitableObject); - } - - /* Now wait. Also SEH this since it can also raise an exception */ - _SEH_TRY - { - Status = KeWaitForSingleObject(WaitableObject, - UserRequest, - PreviousMode, - Alertable, - TimeOut); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - /* Dereference the Object */ - ObDereferenceObject(Object); - } - - /* Return the status */ - return Status; -} - -/*++ -* @name NtSignalAndWaitForSingleObject -* @implemented NT4 -* -* The NtSignalAndWaitForSingleObject routine <FILLMEIN> -* -* @param ObjectHandleToSignal -* <FILLMEIN> -* -* @param WaitableObjectHandle -* <FILLMEIN> -* -* @param Alertable -* <FILLMEIN> -* -* @param TimeOut -* <FILLMEIN> -* -* @return STATUS_SUCCESS or appropriate error value. -* -* @remarks None. -* -*--*/ -NTSTATUS -NTAPI -NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal, - IN HANDLE WaitableObjectHandle, - IN BOOLEAN Alertable, - IN PLARGE_INTEGER TimeOut OPTIONAL) -{ - KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - POBJECT_TYPE Type; - PVOID SignalObj; - PVOID WaitObj; - PVOID WaitableObject; - LARGE_INTEGER SafeTimeOut; - OBJECT_HANDLE_INFORMATION HandleInfo; - NTSTATUS Status = STATUS_SUCCESS; - - /* Capture timeout */ - DPRINT("NtSignalAndWaitForSingleObject\n"); - if(TimeOut && PreviousMode != KernelMode) - { - _SEH_TRY - { - /* Make a copy on the stack */ - SafeTimeOut = ProbeForReadLargeInteger(TimeOut); - TimeOut = &SafeTimeOut; - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if(!NT_SUCCESS(Status)) return Status; - } - - /* Start by getting the signal object*/ - Status = ObReferenceObjectByHandle(ObjectHandleToSignal, - 0, - NULL, - PreviousMode, - &SignalObj, - &HandleInfo); - if (!NT_SUCCESS(Status)) - { - return Status; - } - - /* Now get the wait object */ - Status = ObReferenceObjectByHandle(WaitableObjectHandle, - SYNCHRONIZE, - NULL, - PreviousMode, - &WaitObj, - NULL); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(SignalObj); - return Status; - } - - /* Get the real waitable object */ - WaitableObject = OBJECT_TO_OBJECT_HEADER(WaitObj)->Type->DefaultObject; - - /* Handle internal offset */ - if (IsPointerOffset(WaitableObject)) - { - /* Get real pointer */ - WaitableObject = (PVOID)((ULONG_PTR)WaitObj + - (ULONG_PTR)WaitableObject); - } - - /* Check Signal Object Type */ - Type = OBJECT_TO_OBJECT_HEADER(WaitObj)->Type; - if (Type == ExEventObjectType) - { - /* Set the Event */ - /* FIXME: Check permissions */ - KeSetEvent(SignalObj, EVENT_INCREMENT, TRUE); - } - else if (Type == ExMutantObjectType) - { - /* Release the Mutant. This can raise an exception*/ - _SEH_TRY - { - KeReleaseMutant(SignalObj, MUTANT_INCREMENT, FALSE, TRUE); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - goto Quickie; - } - _SEH_END; - } - else if (Type == ExSemaphoreObjectType) - { - /* Release the Semaphore. This can raise an exception*/ - /* FIXME: Check permissions */ - _SEH_TRY - { - KeReleaseSemaphore(SignalObj, SEMAPHORE_INCREMENT, 1, TRUE); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - goto Quickie; - } - _SEH_END; - } - else - { - Status = STATUS_OBJECT_TYPE_MISMATCH; - DPRINT1("Waiting on invalid object type\n"); - goto Quickie; - } - - /* Now wait. Also SEH this since it can also raise an exception */ - _SEH_TRY - { - Status = KeWaitForSingleObject(WaitableObject, - UserRequest, - PreviousMode, - Alertable, - TimeOut); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - /* We're done here */ -Quickie: - ObDereferenceObject(SignalObj); - ObDereferenceObject(WaitObj); - return Status; -} - -/* EOF */