diff --git a/reactos/ntoskrnl/include/internal/ob.h b/reactos/ntoskrnl/include/internal/ob.h index 251148f08d5..ddbfbd7cadc 100644 --- a/reactos/ntoskrnl/include/internal/ob.h +++ b/reactos/ntoskrnl/include/internal/ob.h @@ -1,53 +1,89 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: include/internal/objmgr.h - * PURPOSE: Object manager definitions - * PROGRAMMER: David Welch (welch@mcmail.com) - */ +* PROJECT: ReactOS Kernel +* LICENSE: GPL - See COPYING in the top level directory +* FILE: ntoskrnl/include/ob.h +* PURPOSE: Internal header for the Object Manager +* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) +*/ +#include "ob_x.h" -#ifndef __INCLUDE_INTERNAL_OBJMGR_H -#define __INCLUDE_INTERNAL_OBJMGR_H +// +// Define this if you want debugging support +// +#define _OB_DEBUG_ 0x00 +// +// These define the Debug Masks Supported +// +#define OB_HANDLE_DEBUG 0x01 +#define OB_NAMESPACE_DEBUG 0x02 +#define OB_SECURITY_DEBUG 0x04 +#define OB_REFERENCE_DEBUG 0x08 +#define OB_CALLBACK_DEBUG 0x10 + +// +// Debug/Tracing support +// +#if _OB_DEBUG_ +#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented +#define OBTRACE DbgPrintEx +#else +#define OBTRACE(x, ...) \ + if (x & ObpTraceLevel) DbgPrint(__VA_ARGS__) +#endif +#else +#define OBTRACE(x, ...) DPRINT(__VA_ARGS__) +#endif + +// +// Mask to detect GENERIC_XXX access masks being used +// +#define GENERIC_ACCESS \ + (GENERIC_READ | \ + GENERIC_WRITE | \ + GENERIC_EXECUTE | \ + GENERIC_ALL) + +// +// Identifies a Kernel Handle +// +#define KERNEL_HANDLE_FLAG \ + (1 << ((sizeof(HANDLE) * 8) - 1)) +#define ObIsKernelHandle(Handle, ProcessorMode) \ + (((ULONG_PTR)(Handle) & KERNEL_HANDLE_FLAG) && \ + ((ProcessorMode) == KernelMode)) + +// +// Converts to and from a Kernel Handle to a normal handle +// +#define ObKernelHandleToHandle(Handle) \ + (HANDLE)((ULONG_PTR)(Handle) & ~KERNEL_HANDLE_FLAG) +#define ObMarkHandleAsKernelHandle(Handle) \ + (HANDLE)((ULONG_PTR)(Handle) | KERNEL_HANDLE_FLAG) + +// +// Returns the number of handles in a handle table +// +#define ObpGetHandleCountByHandleTable(HandleTable) \ + ((PHANDLE_TABLE)HandleTable)->HandleCount + +// +// Context Structures for Ex*Handle Callbacks +// 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; - typedef struct _OBP_CLOSE_HANDLE_CONTEXT { PHANDLE_TABLE HandleTable; KPROCESSOR_MODE AccessMode; } OBP_CLOSE_HANDLE_CONTEXT, *POBP_CLOSE_HANDLE_CONTEXT; -#define GENERIC_ACCESS (GENERIC_READ | \ - GENERIC_WRITE | \ - GENERIC_EXECUTE | \ - GENERIC_ALL) - -#define KERNEL_HANDLE_FLAG (1 << ((sizeof(HANDLE) * 8) - 1)) -#define ObIsKernelHandle(Handle, ProcessorMode) \ - (((ULONG_PTR)(Handle) & KERNEL_HANDLE_FLAG) && \ - ((ProcessorMode) == KernelMode)) -#define ObKernelHandleToHandle(Handle) \ - (HANDLE)((ULONG_PTR)(Handle) & ~KERNEL_HANDLE_FLAG) -#define ObMarkHandleAsKernelHandle(Handle) \ - (HANDLE)((ULONG_PTR)(Handle) | KERNEL_HANDLE_FLAG) -#define ObpGetHandleCountByHandleTable(HandleTable) \ - ((PHANDLE_TABLE)HandleTable)->HandleCount - -extern KEVENT ObpDefaultObject; -extern POBJECT_TYPE ObpTypeObjectType; -extern POBJECT_TYPE ObSymbolicLinkType; -extern POBJECT_TYPE ObTypeObjectType; -extern POBJECT_DIRECTORY NameSpaceRoot; -extern POBJECT_DIRECTORY ObpTypeDirectoryObject; -extern PHANDLE_TABLE ObpKernelHandleTable; -extern WORK_QUEUE_ITEM ObpReaperWorkItem; -extern volatile PVOID ObpReaperList; -extern NPAGED_LOOKASIDE_LIST ObpNmLookasideList, ObpCiLookasideList; - +// +// Directory Namespace Functions +// BOOLEAN NTAPI ObpDeleteEntryDirectory( @@ -72,12 +108,33 @@ ObpLookupEntryDirectory( IN POBP_LOOKUP_CONTEXT Context ); +// +// Symbolic Link Functions +// VOID NTAPI ObInitSymbolicLinkImplementation( VOID ); +NTSTATUS +NTAPI +ObpParseSymbolicLink( + IN PVOID ParsedObject, + IN PVOID ObjectType, + IN OUT PACCESS_STATE AccessState, + IN KPROCESSOR_MODE AccessMode, + IN ULONG Attributes, + IN OUT PUNICODE_STRING FullPath, + IN OUT PUNICODE_STRING RemainingName, + IN OUT PVOID Context OPTIONAL, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, + OUT PVOID *NextObject +); + +// +// Process/Handle Table Init/Rundown +// NTSTATUS NTAPI ObpCreateHandleTable( @@ -91,6 +148,9 @@ ObKillProcess( IN PEPROCESS Process ); +// +// Object Lookup Functions +// NTSTATUS NTAPI ObFindObject( @@ -107,6 +167,9 @@ ObFindObject( IN PVOID Insert ); +// +// Object Attribute Functions +// BOOLEAN NTAPI ObpSetHandleAttributes( @@ -115,12 +178,6 @@ ObpSetHandleAttributes( IN PVOID Context ); -VOID -NTAPI -ObpDeleteNameCheck( - IN PVOID Object -); - VOID NTAPI ObQueryDeviceMapInformation( @@ -128,13 +185,9 @@ ObQueryDeviceMapInformation( OUT PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo ); -VOID -FASTCALL -ObpSetPermanentObject( - IN PVOID ObjectBody, - IN BOOLEAN Permanent -); - +// +// Object Lifetime Functions +// VOID FASTCALL ObpDeleteObject( @@ -147,11 +200,27 @@ ObpReapObject( IN PVOID Unused ); -/* Security descriptor cache functions */ +VOID +FASTCALL +ObpSetPermanentObject( + IN PVOID ObjectBody, + IN BOOLEAN Permanent +); +VOID +NTAPI +ObpDeleteNameCheck( + IN PVOID Object +); + +// +// Security descriptor cache functions +// NTSTATUS NTAPI -ObpInitSdCache(VOID); +ObpInitSdCache( + VOID +); NTSTATUS NTAPI @@ -162,7 +231,9 @@ ObpAddSecurityDescriptor( NTSTATUS NTAPI -ObpRemoveSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor); +ObpRemoveSecurityDescriptor( + IN PSECURITY_DESCRIPTOR SecurityDescriptor +); PSECURITY_DESCRIPTOR NTAPI @@ -172,37 +243,45 @@ ObpReferenceCachedSecurityDescriptor( VOID NTAPI -ObpDereferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor); +ObpDereferenceCachedSecurityDescriptor( + IN PSECURITY_DESCRIPTOR SecurityDescriptor +); +// +// Executive Fast Referencing Functions +// VOID FASTCALL ObInitializeFastReference( IN PEX_FAST_REF FastRef, - PVOID Object + IN PVOID Object ); PVOID FASTCALL ObFastReplaceObject( IN PEX_FAST_REF FastRef, - PVOID Object + IN PVOID Object ); PVOID FASTCALL -ObFastReferenceObject(IN PEX_FAST_REF FastRef); +ObFastReferenceObject( + IN PEX_FAST_REF FastRef +); VOID FASTCALL ObFastDereferenceObject( IN PEX_FAST_REF FastRef, - PVOID Object + IN PVOID Object ); -/* Object Create and Object Name Capture Functions */ - +// +// Object Create and Object Name Capture Functions +// NTSTATUS -STDCALL +NTAPI ObpCaptureObjectName( IN PUNICODE_STRING CapturedName, IN PUNICODE_STRING ObjectName, @@ -211,7 +290,7 @@ ObpCaptureObjectName( ); NTSTATUS -STDCALL +NTAPI ObpCaptureObjectAttributes( IN POBJECT_ATTRIBUTES ObjectAttributes, IN KPROCESSOR_MODE AccessMode, @@ -220,119 +299,17 @@ ObpCaptureObjectAttributes( OUT PUNICODE_STRING ObjectName ); -VOID -static __inline -ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo) -{ - /* Check if we have a security descriptor */ - if (ObjectCreateInfo->SecurityDescriptor) - { - /* Release it */ - SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor, - ObjectCreateInfo->ProbeMode, - TRUE); - ObjectCreateInfo->SecurityDescriptor = NULL; - } -} - -PVOID -static __inline -ObpAllocateCapturedAttributes(IN PP_NPAGED_LOOKASIDE_NUMBER Type) -{ - PKPRCB Prcb = KeGetCurrentPrcb(); - PVOID Buffer; - PNPAGED_LOOKASIDE_LIST List; - - /* Get the P list first */ - List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].P; - - /* Attempt allocation */ - List->L.TotalAllocates++; - Buffer = (PVOID)InterlockedPopEntrySList(&List->L.ListHead); - if (!Buffer) - { - /* Let the balancer know that the P list failed */ - List->L.AllocateMisses++; - - /* Try the L List */ - List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].L; - List->L.TotalAllocates++; - Buffer = (PVOID)InterlockedPopEntrySList(&List->L.ListHead); - if (!Buffer) - { - /* Let the balancer know the L list failed too */ - List->L.AllocateMisses++; - - /* Allocate it */ - Buffer = List->L.Allocate(List->L.Type, List->L.Size, List->L.Tag); - } - } - - /* Return buffer */ - return Buffer; -} - -VOID -static __inline -ObpFreeCapturedAttributes(IN PVOID Buffer, - IN PP_NPAGED_LOOKASIDE_NUMBER Type) -{ - PKPRCB Prcb = KeGetCurrentPrcb(); - PNPAGED_LOOKASIDE_LIST List; - - /* Use the P List */ - List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].P; - List->L.TotalFrees++; - - /* Check if the Free was within the Depth or not */ - if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth) - { - /* Let the balancer know */ - List->L.FreeMisses++; - - /* Use the L List */ - List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].L; - List->L.TotalFrees++; - - /* Check if the Free was within the Depth or not */ - if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth) - { - /* All lists failed, use the pool */ - List->L.FreeMisses++; - List->L.Free(Buffer); - } - } - else - { - /* The free was within the Depth */ - InterlockedPushEntrySList(&List->L.ListHead, - (PSINGLE_LIST_ENTRY)Buffer); - } -} - -VOID -static __inline -ObpReleaseCapturedName(IN PUNICODE_STRING Name) -{ - /* We know this is a pool-allocation if the size doesn't match */ - if (Name->MaximumLength != 248) - { - ExFreePool(Name->Buffer); - } - else - { - /* Otherwise, free from the lookaside */ - ObpFreeCapturedAttributes(Name, LookasideNameBufferList); - } -} - -VOID -static __inline -ObpFreeAndReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo) -{ - /* First release the attributes, then free them from the lookaside list */ - ObpReleaseCapturedAttributes(ObjectCreateInfo); - ObpFreeCapturedAttributes(ObjectCreateInfo, LookasideCreateInfoList); -} - -#endif /* __INCLUDE_INTERNAL_OBJMGR_H */ +// +// Global data inside the Object Manager +// +extern ULONG ObpTraceLevel; +extern KEVENT ObpDefaultObject; +extern POBJECT_TYPE ObpTypeObjectType; +extern POBJECT_TYPE ObSymbolicLinkType; +extern POBJECT_TYPE ObTypeObjectType; +extern POBJECT_DIRECTORY NameSpaceRoot; +extern POBJECT_DIRECTORY ObpTypeDirectoryObject; +extern PHANDLE_TABLE ObpKernelHandleTable; +extern WORK_QUEUE_ITEM ObpReaperWorkItem; +extern volatile PVOID ObpReaperList; +extern NPAGED_LOOKASIDE_LIST ObpNmLookasideList, ObpCiLookasideList; diff --git a/reactos/ntoskrnl/include/internal/ob_x.h b/reactos/ntoskrnl/include/internal/ob_x.h new file mode 100644 index 00000000000..c1dfeec9659 --- /dev/null +++ b/reactos/ntoskrnl/include/internal/ob_x.h @@ -0,0 +1,123 @@ +/* +* PROJECT: ReactOS Kernel +* LICENSE: GPL - See COPYING in the top level directory +* FILE: ntoskrnl/include/ob_x.h +* PURPOSE: Intenral Inlined Functions for the Object Manager +* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) +*/ + +VOID +static __inline +ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo) +{ + /* Check if we have a security descriptor */ + if (ObjectCreateInfo->SecurityDescriptor) + { + /* Release it */ + SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor, + ObjectCreateInfo->ProbeMode, + TRUE); + ObjectCreateInfo->SecurityDescriptor = NULL; + } +} + +PVOID +static __inline +ObpAllocateCapturedAttributes(IN PP_NPAGED_LOOKASIDE_NUMBER Type) +{ + PKPRCB Prcb = KeGetCurrentPrcb(); + PVOID Buffer; + PNPAGED_LOOKASIDE_LIST List; + + /* Get the P list first */ + List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].P; + + /* Attempt allocation */ + List->L.TotalAllocates++; + Buffer = (PVOID)InterlockedPopEntrySList(&List->L.ListHead); + if (!Buffer) + { + /* Let the balancer know that the P list failed */ + List->L.AllocateMisses++; + + /* Try the L List */ + List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].L; + List->L.TotalAllocates++; + Buffer = (PVOID)InterlockedPopEntrySList(&List->L.ListHead); + if (!Buffer) + { + /* Let the balancer know the L list failed too */ + List->L.AllocateMisses++; + + /* Allocate it */ + Buffer = List->L.Allocate(List->L.Type, List->L.Size, List->L.Tag); + } + } + + /* Return buffer */ + return Buffer; +} + +VOID +static __inline +ObpFreeCapturedAttributes(IN PVOID Buffer, + IN PP_NPAGED_LOOKASIDE_NUMBER Type) +{ + PKPRCB Prcb = KeGetCurrentPrcb(); + PNPAGED_LOOKASIDE_LIST List; + + /* Use the P List */ + List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].P; + List->L.TotalFrees++; + + /* Check if the Free was within the Depth or not */ + if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth) + { + /* Let the balancer know */ + List->L.FreeMisses++; + + /* Use the L List */ + List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].L; + List->L.TotalFrees++; + + /* Check if the Free was within the Depth or not */ + if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth) + { + /* All lists failed, use the pool */ + List->L.FreeMisses++; + List->L.Free(Buffer); + } + } + else + { + /* The free was within the Depth */ + InterlockedPushEntrySList(&List->L.ListHead, + (PSINGLE_LIST_ENTRY)Buffer); + } +} + +VOID +static __inline +ObpReleaseCapturedName(IN PUNICODE_STRING Name) +{ + /* We know this is a pool-allocation if the size doesn't match */ + if (Name->MaximumLength != 248) + { + ExFreePool(Name->Buffer); + } + else + { + /* Otherwise, free from the lookaside */ + ObpFreeCapturedAttributes(Name, LookasideNameBufferList); + } +} + +VOID +static __inline +ObpFreeAndReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo) +{ + /* First release the attributes, then free them from the lookaside list */ + ObpReleaseCapturedAttributes(ObjectCreateInfo); + ObpFreeCapturedAttributes(ObjectCreateInfo, LookasideCreateInfoList); +} + diff --git a/reactos/ntoskrnl/io/file.c b/reactos/ntoskrnl/io/file.c index 6b783ae1b4b..fde7bbe4816 100644 --- a/reactos/ntoskrnl/io/file.c +++ b/reactos/ntoskrnl/io/file.c @@ -44,19 +44,15 @@ IopParseDevice(IN PVOID ParseObject, NTSTATUS Status; PFILE_OBJECT FileObject; DPRINT("IopParseDevice:\n" - "DeviceObject : %p, Type : %p, TypeName : %wZ\n" - "FileObject : %p, Type : %p, TypeName : %wZ\n" - "CompleteName : %wZ, RemainingName : %wZ\n", - ParseObject, - ObjectType, - &ObjectType->Name, - Context, - Context ? OBJECT_TO_OBJECT_HEADER(Context)->Type : NULL, - Context ? &OBJECT_TO_OBJECT_HEADER(Context)->Type->Name: NULL, - CompleteName, - RemainingName); + "DeviceObject : %p\n" + "RelatedFileObject : %p\n" + "CompleteName : %wZ, RemainingName : %wZ\n", + ParseObject, + Context, + CompleteName, + RemainingName); - if (!RemainingName || !RemainingName->Buffer) + if (!*RemainingName->Buffer) { DeviceObject = ParseObject; @@ -71,6 +67,7 @@ IopParseDevice(IN PVOID ParseObject, (PVOID*)&FileObject); /* Set File Object Data */ FileObject->DeviceObject = IoGetAttachedDevice(DeviceObject); + DPRINT("DO. DRV Name: %p %wZ\n", DeviceObject, &DeviceObject->DriverObject->DriverName); /* HACK */ FileObject->Flags |= FO_DIRECT_DEVICE_OPEN; @@ -88,7 +85,7 @@ IopParseDevice(IN PVOID ParseObject, 0, (PVOID*)&FileObject); - if (ObjectType == IoDeviceObjectType) + if (!Context) { /* Parent is a device object */ DeviceObject = IoGetAttachedDevice((PDEVICE_OBJECT)ParseObject); @@ -110,7 +107,6 @@ IopParseDevice(IN PVOID ParseObject, RtlCreateUnicodeString(&FileObject->FileName, RemainingName->Buffer); FileObject->DeviceObject = DeviceObject; *Object = FileObject; - RemainingName->Buffer = NULL; // ros hack return STATUS_SUCCESS; } diff --git a/reactos/ntoskrnl/ob/obhandle.c b/reactos/ntoskrnl/ob/obhandle.c index 1c9d672f7ee..e9aff3f7c91 100644 --- a/reactos/ntoskrnl/ob/obhandle.c +++ b/reactos/ntoskrnl/ob/obhandle.c @@ -19,12 +19,6 @@ PHANDLE_TABLE ObpKernelHandleTable = NULL; -#ifdef _OBDEBUG_ -#define OBTRACE DPRINT1 -#else -#define OBTRACE DPRINT -#endif - /* PRIVATE FUNCTIONS *********************************************************/ NTSTATUS @@ -103,7 +97,8 @@ ObpDecrementHandleCount(IN PVOID ObjectBody, /* Get the object type and header */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody); ObjectType = ObjectHeader->Type; - OBTRACE("OBTRACE - %s - Decrementing count for: %p. HC LC %lx %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Decrementing count for: %p. HC LC %lx %lx\n", __FUNCTION__, ObjectBody, ObjectHeader->HandleCount, @@ -132,7 +127,8 @@ ObpDecrementHandleCount(IN PVOID ObjectBody, /* Decrease the total number of handles for this type */ ObjectType->TotalNumberOfHandles--; - OBTRACE("OBTRACE - %s - Decremented count for: %p. HC LC %lx %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Decremented count for: %p. HC LC %lx %lx\n", __FUNCTION__, ObjectBody, ObjectHeader->HandleCount, @@ -183,7 +179,8 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable, ObjectType = ObjectHeader->Type; Body = &ObjectHeader->Body; GrantedAccess = HandleEntry->GrantedAccess; - OBTRACE("OBTRACE - %s - Closing handle: %lx for %p. HC LC %lx %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Closing handle: %lx for %p. HC LC %lx %lx\n", __FUNCTION__, Handle, Body, @@ -243,7 +240,8 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable, //ObDereferenceObject(Body); // FIXME: Needs sync changes in other code /* Return to caller */ - OBTRACE("OBTRACE - %s - Closed handle: %lx for %p. HC LC %lx %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Closed handle: %lx for %p. HC LC %lx %lx\n", __FUNCTION__, Handle, Body, @@ -297,7 +295,8 @@ ObpIncrementHandleCount(IN PVOID Object, /* Get the object header and type */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); ObjectType = ObjectHeader->Type; - OBTRACE("OBTRACE - %s - Incrementing count for: %p. Reason: %lx. HC LC %lx %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Incrementing count for: %p. Reason: %lx. HC LC %lx %lx\n", __FUNCTION__, Object, OpenReason, @@ -376,7 +375,8 @@ ObpIncrementHandleCount(IN PVOID Object, /* Increase total number of handles */ ObjectType->TotalNumberOfHandles++; - OBTRACE("OBTRACE - %s - Incremented count for: %p. Reason: %lx HC LC %lx %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Incremented count for: %p. Reason: %lx HC LC %lx %lx\n", __FUNCTION__, Object, OpenReason, @@ -429,7 +429,8 @@ ObpIncrementUnnamedHandleCount(IN PVOID Object, /* Get the object header and type */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); ObjectType = ObjectHeader->Type; - OBTRACE("OBTRACE - %s - Incrementing count for: %p. UNNAMED. HC LC %lx %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Incrementing count for: %p. UNNAMED. HC LC %lx %lx\n", __FUNCTION__, Object, ObjectHeader->HandleCount, @@ -486,7 +487,8 @@ ObpIncrementUnnamedHandleCount(IN PVOID Object, /* Increase total number of handles */ ObjectType->TotalNumberOfHandles++; - OBTRACE("OBTRACE - %s - Incremented count for: %p. UNNAMED HC LC %lx %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Incremented count for: %p. UNNAMED HC LC %lx %lx\n", __FUNCTION__, Object, ObjectHeader->HandleCount, @@ -546,7 +548,8 @@ ObpCreateUnnamedHandle(IN PVOID Object, /* Get the object header and type */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); - OBTRACE("OBTRACE - %s - Creating handle for: %p. UNNAMED. HC LC %lx %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Creating handle for: %p. UNNAMED. HC LC %lx %lx\n", __FUNCTION__, Object, ObjectHeader->HandleCount, @@ -606,7 +609,8 @@ ObpCreateUnnamedHandle(IN PVOID Object, * ObpIncrementHandleCount to make sure that Object Security is valid * (specified in Gl00my documentation on Ob) */ - OBTRACE("OBTRACE - %s - Handle Properties: [%p-%lx-%lx]\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Handle Properties: [%p-%lx-%lx]\n", __FUNCTION__, NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess); Handle = ExCreateHandle(HandleTable, &NewEntry); @@ -634,7 +638,8 @@ ObpCreateUnnamedHandle(IN PVOID Object, /* Return handle and object */ *ReturnedHandle = Handle; if (ReturnedObject) *ReturnedObject = Object; - OBTRACE("OBTRACE - %s - Returning Handle: %lx HC LC %lx %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s %s - Returning Handle: %lx HC LC %lx %lx\n", __FUNCTION__, Handle, ObjectHeader->HandleCount, @@ -716,7 +721,8 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason, /* Get the object header and type */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); ObjectType = ObjectHeader->Type; - OBTRACE("OBTRACE - %s - Creating handle for: %p. Reason: %lx. HC LC %lx %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Creating handle for: %p. Reason: %lx. HC LC %lx %lx\n", __FUNCTION__, Object, OpenReason, @@ -787,7 +793,8 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason, * ObpIncrementHandleCount to make sure that Object Security is valid * (specified in Gl00my documentation on Ob) */ - OBTRACE("OBTRACE - %s - Handle Properties: [%p-%lx-%lx]\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Handle Properties: [%p-%lx-%lx]\n", __FUNCTION__, NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess); Handle = ExCreateHandle(HandleTable, &NewEntry); @@ -815,7 +822,8 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason, /* Return handle and object */ *ReturnedHandle = Handle; if (ReturnedObject) *ReturnedObject = Object; - OBTRACE("OBTRACE - %s - Returning Handle: %lx HC LC %lx %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Returning Handle: %lx HC LC %lx %lx\n", __FUNCTION__, Handle, ObjectHeader->HandleCount, @@ -857,7 +865,8 @@ ObpCloseHandle(IN HANDLE Handle, PHANDLE_TABLE_ENTRY HandleTableEntry; NTSTATUS Status; PAGED_CODE(); - OBTRACE("OBTRACE - %s - Closing handle: %lx\n", __FUNCTION__, Handle); + OBTRACE(OB_HANDLE_DEBUG, + "%s - Closing handle: %lx\n", __FUNCTION__, Handle); /* Check if we're dealing with a kernel handle */ if (ObIsKernelHandle(Handle, AccessMode)) @@ -924,7 +933,8 @@ ObpCloseHandle(IN HANDLE Handle, } /* Return status */ - OBTRACE("OBTRACE - %s - Closed handle: %lx S: %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Closed handle: %lx S: %lx\n", __FUNCTION__, Handle, Status); return Status; } @@ -1213,7 +1223,8 @@ ObDuplicateObject(IN PEPROCESS SourceProcess, PHANDLE_TABLE HandleTable = NULL; OBJECT_HANDLE_INFORMATION HandleInformation; PAGED_CODE(); - OBTRACE("OBTRACE - %s - Duplicating handle: %lx for %p into %p\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Duplicating handle: %lx for %p into %p\n", __FUNCTION__, SourceHandle, SourceProcess, @@ -1376,7 +1387,8 @@ ObDuplicateObject(IN PEPROCESS SourceProcess, if (TargetHandle) *TargetHandle = NewHandle; /* Return status */ - OBTRACE("OBTRACE - %s - Duplicated handle: %lx for %p into %p. Source: %p HC PC %lx %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Duplicated handle: %lx for %p into %p. Source: %p HC PC %lx %lx\n", __FUNCTION__, NewHandle, SourceProcess, @@ -1534,7 +1546,8 @@ Cleanup: Quickie: ObpReleaseCapturedAttributes(&ObjectCreateInfo); if (ObjectName.Buffer) ObpReleaseCapturedName(&ObjectName); - OBTRACE("OBTRACE: %s returning Object with PC S: %lx %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s returning Object with PC S: %lx %lx\n", __FUNCTION__, OBJECT_TO_OBJECT_HEADER(Object)->PointerCount, Status); @@ -1633,7 +1646,8 @@ ObOpenObjectByPointer(IN PVOID Object, ObDereferenceObject(Object); /* Return */ - OBTRACE("OBTRACE: %s returning Object with PC S: %lx %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - returning Object with PC S: %lx %lx\n", __FUNCTION__, OBJECT_TO_OBJECT_HEADER(Object)->PointerCount, Status); @@ -1993,11 +2007,12 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle, KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE(); - OBTRACE("OBTRACE - %s - Duplicating handle: %lx for %lx into %lx.\n", - __FUNCTION__, - SourceHandle, - SourceProcessHandle, - TargetProcessHandle); + OBTRACE(OB_HANDLE_DEBUG, + "%s - Duplicating handle: %lx for %lx into %lx.\n", + __FUNCTION__, + SourceHandle, + SourceProcessHandle, + TargetProcessHandle); if((TargetHandle) && (PreviousMode != KernelMode)) { @@ -2083,7 +2098,8 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle, } /* Dereference the processes */ - OBTRACE("OBTRACE - %s - Duplicated handle: %lx into %lx S %lx\n", + OBTRACE(OB_HANDLE_DEBUG, + "%s - Duplicated handle: %lx into %lx S %lx\n", __FUNCTION__, hTarget, TargetProcessHandle, diff --git a/reactos/ntoskrnl/ob/obinit.c b/reactos/ntoskrnl/ob/obinit.c index 7f9cc8f348a..25e50154bff 100644 --- a/reactos/ntoskrnl/ob/obinit.c +++ b/reactos/ntoskrnl/ob/obinit.c @@ -38,6 +38,7 @@ GENERIC_MAPPING ObpDirectoryMapping = }; PDEVICE_MAP ObSystemDeviceMap = NULL; +ULONG ObpTraceLevel = OB_NAMESPACE_DEBUG; /* PRIVATE FUNCTIONS *********************************************************/ diff --git a/reactos/ntoskrnl/ob/obname.c b/reactos/ntoskrnl/ob/obname.c index fb4d7542717..d8afeccfd32 100644 --- a/reactos/ntoskrnl/ob/obname.c +++ b/reactos/ntoskrnl/ob/obname.c @@ -106,280 +106,433 @@ NTAPI ObFindObject(IN HANDLE RootHandle, IN PUNICODE_STRING ObjectName, IN ULONG Attributes, - IN KPROCESSOR_MODE PreviousMode, + IN KPROCESSOR_MODE AccessMode, IN PVOID *ReturnedObject, IN POBJECT_TYPE ObjectType, IN POBP_LOOKUP_CONTEXT Context, IN PACCESS_STATE AccessState, IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, IN PVOID ParseContext, - IN PVOID Insert) + OUT PVOID ExpectedObject) { - PVOID NextObject; - PVOID CurrentObject; - PVOID RootObject; + PVOID RootDirectory; + PVOID CurrentDirectory = NULL; + PVOID CurrentObject = NULL; POBJECT_HEADER CurrentHeader; NTSTATUS Status = STATUS_SUCCESS; - PWSTR current; - UNICODE_STRING PathString; - UNICODE_STRING CurrentUs; - UNICODE_STRING Path; - PUNICODE_STRING RemainingPath = &Path; - + PVOID NewName; + POBJECT_HEADER_NAME_INFO ObjectNameInfo; + UNICODE_STRING RemainingPath, PartName; + BOOLEAN InsideRoot = FALSE; + OB_PARSE_METHOD ParseRoutine; PAGED_CODE(); - DPRINT("ObFindObject(ObjectCreateInfo %x, ReturnedObject %x, " - "RemainingPath %x)\n",ObjectCreateInfo,ReturnedObject,RemainingPath); + /* Assume failure */ + OBTRACE(OB_NAMESPACE_DEBUG, + "%s - Finding Object: %wZ. Expecting: %p\n", + __FUNCTION__, + ObjectName, + ExpectedObject); + *ReturnedObject = NULL; - RtlInitUnicodeString (RemainingPath, NULL); - - if (RootHandle == NULL) - { - ObReferenceObjectByPointer(NameSpaceRoot, - DIRECTORY_TRAVERSE, - NULL, - PreviousMode); - CurrentObject = NameSpaceRoot; - } - else + /* Check if we got a Root Directory */ + if (RootHandle) { + /* We did. Reference it */ Status = ObReferenceObjectByHandle(RootHandle, - 0, - NULL, - PreviousMode, - &CurrentObject, - NULL); - if (!NT_SUCCESS(Status)) + 0, + NULL, + AccessMode, + &RootDirectory, + NULL); + if (!NT_SUCCESS(Status)) return Status; + + /* Get the header */ + CurrentHeader = OBJECT_TO_OBJECT_HEADER(RootDirectory); + + /* The name cannot start with a separator, unless this is a file */ + if ((ObjectName->Buffer) && + (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR) && + (CurrentHeader->Type != IoFileObjectType)) { + /* The syntax is bad, so fail this request */ + ObDereferenceObject(RootDirectory); + return STATUS_OBJECT_PATH_SYNTAX_BAD; + } + + /* Don't parse a Directory */ + if (CurrentHeader->Type != ObDirectoryType) + { + /* Make sure the Object Type has a parse routine */ + ParseRoutine = CurrentHeader->Type->TypeInfo.ParseProcedure; + if (!ParseRoutine) + { + /* We can't parse a name if we don't have a parse routine */ + ObDereferenceObject(RootDirectory); + return STATUS_INVALID_HANDLE; + } + + /* Now parse */ + while (TRUE) + { + /* Start with the full name */ + RemainingPath = *ObjectName; + + /* Call the Parse Procedure */ + Status = ParseRoutine(RootDirectory, + ObjectType, + AccessState, + AccessMode, + Attributes, + ObjectName, + &RemainingPath, + ParseContext, + SecurityQos, + &CurrentObject); + + /* Check for success or failure, so not reparse */ + if ((Status != STATUS_REPARSE) && + (Status != STATUS_REPARSE_OBJECT)) + { + /* Check for failure */ + if (!NT_SUCCESS(Status)) + { + /* Parse routine might not have cleared this, do it */ + CurrentObject = NULL; + } + else if (!CurrentObject) + { + /* Modify status to reflect failure inside Ob */ + Status = STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* We're done, return the status and object */ + *ReturnedObject = CurrentObject; + ObDereferenceObject(RootDirectory); + return Status; + } + else if ((!ObjectName->Length) || + (!ObjectName->Buffer) || + (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) + { + /* Reparsed to the root directory, so start over */ + ObDereferenceObject(RootDirectory); + RootDirectory = NameSpaceRoot; + + /* Don't use this anymore, since we're starting at root */ + RootHandle = NULL; + break; + } + } + } + else if (!(ObjectName->Length) || !(ObjectName->Buffer)) + { + /* Just return the Root Directory if we didn't get a name*/ + Status = ObReferenceObjectByPointer(RootDirectory, + 0, + ObjectType, + AccessMode); + if (NT_SUCCESS(Status)) *ReturnedObject = RootDirectory; + ObDereferenceObject(RootDirectory); return Status; } } - - if (ObjectName->Length == 0 || - ObjectName->Buffer[0] == UNICODE_NULL) - { - *ReturnedObject = CurrentObject; - return STATUS_SUCCESS; - } - - if (RootHandle == NULL && - ObjectName->Buffer[0] != L'\\') - { - ObDereferenceObject (CurrentObject); - DPRINT1("failed\n"); - return STATUS_UNSUCCESSFUL; - } - - /* Create a zero-terminated copy of the object name */ - PathString.Length = ObjectName->Length; - PathString.MaximumLength = ObjectName->Length + sizeof(WCHAR); - PathString.Buffer = ExAllocatePool (NonPagedPool, - PathString.MaximumLength); - if (PathString.Buffer == NULL) - { - ObDereferenceObject (CurrentObject); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlCopyMemory (PathString.Buffer, - ObjectName->Buffer, - ObjectName->Length); - PathString.Buffer[PathString.Length / sizeof(WCHAR)] = UNICODE_NULL; - - current = PathString.Buffer; - - RootObject = CurrentObject; - if (ObjectType == ObSymbolicLinkType) - Attributes |= OBJ_OPENLINK; - - while (TRUE) - { - CurrentHeader = OBJECT_TO_OBJECT_HEADER(CurrentObject); - - /* Loop as long as we're dealing with a directory */ - while (CurrentHeader->Type == ObDirectoryType) - { - PWSTR Start, End; - PVOID FoundObject; - UNICODE_STRING StartUs; - NextObject = NULL; - - if (!current) goto Next; - - Start = current; - if (*Start == L'\\') Start++; - - End = wcschr(Start, L'\\'); - if (End != NULL) *End = 0; - - RtlInitUnicodeString(&StartUs, Start); - Context->DirectoryLocked = TRUE; - Context->Directory = CurrentObject; - FoundObject = ObpLookupEntryDirectory(CurrentObject, &StartUs, Attributes, FALSE, Context); - if (FoundObject == NULL) - { - if (End != NULL) - { - *End = L'\\'; - } - goto Next; - } - - ObReferenceObjectByPointer(FoundObject, - STANDARD_RIGHTS_REQUIRED, - NULL, - UserMode); - if (End != NULL) - { - *End = L'\\'; - current = End; - } - else - { - current = NULL; - } - - NextObject = FoundObject; - -Next: - if (NextObject == NULL) - { - break; - } - ObDereferenceObject(CurrentObject); - CurrentObject = NextObject; - CurrentHeader = OBJECT_TO_OBJECT_HEADER(CurrentObject); - } - - if (CurrentHeader->Type->TypeInfo.ParseProcedure == NULL) - { - DPRINT("Current object can't parse\n"); - break; - } - - RtlInitUnicodeString(&CurrentUs, current); - Status = CurrentHeader->Type->TypeInfo.ParseProcedure(CurrentObject, - CurrentHeader->Type, - AccessState, - PreviousMode, - Attributes, - &PathString, - &CurrentUs, - ParseContext, - SecurityQos, - &NextObject); - current = CurrentUs.Buffer; - if (Status == STATUS_REPARSE) - { - /* reparse the object path */ - NextObject = NameSpaceRoot; - current = PathString.Buffer; - - ObReferenceObjectByPointer(NextObject, - DIRECTORY_TRAVERSE, - NULL, - PreviousMode); - } - - - if (NextObject == NULL) - { - break; - } - ObDereferenceObject(CurrentObject); - CurrentObject = NextObject; - if (!current) break; - } - - if (current) - { - RtlpCreateUnicodeString (RemainingPath, current, NonPagedPool); - } - - RtlFreeUnicodeString (&PathString); - *ReturnedObject = CurrentObject; - - /* - * Icky hack: put the code that was in ObInsertObject here so that - * we can get rid of the "RemainingPath" stuff, which shouldn't - * be exposed outside of here. - * Also makes the interface closer to NT parsing, and will make the - * eventual changes easier to deal with - */ - if (Insert) - { - PVOID FoundObject = NULL; - POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Insert); - POBJECT_HEADER FoundHeader = NULL; - FoundObject = *ReturnedObject; - if (FoundObject) - { - FoundHeader = OBJECT_TO_OBJECT_HEADER(FoundObject); - } - - if (FoundHeader && RemainingPath->Buffer == NULL) - { - DPRINT("Object exists\n"); - ObDereferenceObject(FoundObject); - return STATUS_OBJECT_NAME_COLLISION; - } - - /* - * MiniHack - * If we still have a remaining path on a directory object, but we are - * a file object, then fail, because this means the file doesn't exist - */ - if ((RemainingPath->Buffer) && - (FoundHeader && FoundHeader->Type == ObDirectoryType) && - (Header->Type == IoFileObjectType)) - { - /* Hack */ - RtlFreeUnicodeString(RemainingPath); - *ReturnedObject = NULL; - return STATUS_OBJECT_PATH_NOT_FOUND; - } - - if (FoundHeader && FoundHeader->Type == ObDirectoryType && - RemainingPath->Buffer) - { - /* The name was changed so let's update it */ - PVOID NewName; - PWSTR BufferPos = RemainingPath->Buffer; - ULONG Delta = 0; - POBJECT_HEADER_NAME_INFO ObjectNameInfo; - - ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(Header); - - if (BufferPos[0] == L'\\') - { - BufferPos++; - Delta = sizeof(WCHAR); - } - NewName = ExAllocatePool(NonPagedPool, RemainingPath->MaximumLength - Delta); - RtlMoveMemory(NewName, BufferPos, RemainingPath->MaximumLength - Delta); - if (ObjectNameInfo->Name.Buffer) ExFreePool(ObjectNameInfo->Name.Buffer); - ObjectNameInfo->Name.Buffer = NewName; - ObjectNameInfo->Name.Length = RemainingPath->Length - Delta; - ObjectNameInfo->Name.MaximumLength = RemainingPath->MaximumLength - Delta; - ObpInsertEntryDirectory(FoundObject, Context, Header); - } - - RtlFreeUnicodeString(RemainingPath); - *ReturnedObject = Insert; - } else { - /* ROS Hack */ - DPRINT("REmaining path: %wZ\n", RemainingPath); - if (RemainingPath->Buffer != NULL) + /* We did not get a Root Directory, so use the root */ + RootDirectory = NameSpaceRoot; + + /* It must start with a path separator */ + if (!(ObjectName->Length) || + !(ObjectName->Buffer) || + (ObjectName->Buffer[0] != OBJ_NAME_PATH_SEPARATOR)) { - if (wcschr(RemainingPath->Buffer + 1, L'\\') == NULL) - Status = STATUS_OBJECT_NAME_NOT_FOUND; + /* This name is invalid, so fail */ + return STATUS_OBJECT_PATH_SYNTAX_BAD; + } + + /* Check if the name is only the path separator */ + if (ObjectName->Length == sizeof(OBJ_NAME_PATH_SEPARATOR)) + { + /* So the caller only wants the root directory; do we have one? */ + if (!RootDirectory) + { + /* This must be the first time we're creating it... right? */ + if (ExpectedObject) + { + /* Yes, so return it to ObInsert so that it can create it */ + Status = ObReferenceObjectByPointer(ExpectedObject, + 0, + ObjectType, + AccessMode); + if (NT_SUCCESS(Status)) *ReturnedObject = ExpectedObject; + return Status; + } + else + { + /* This should never really happen */ + ASSERT(FALSE); + return STATUS_INVALID_PARAMETER; + } + } else - Status =STATUS_OBJECT_PATH_NOT_FOUND; + { + /* We do have the root directory, so just return it */ + Status = ObReferenceObjectByPointer(RootDirectory, + 0, + ObjectType, + AccessMode); + if (NT_SUCCESS(Status)) *ReturnedObject = RootDirectory; + return Status; + } } } + /* Save the name */ +ReparseNewDir: + RemainingPath = *ObjectName; + + /* Reparse */ + while (TRUE) + { + /* Check if we should use the Root Directory */ + if (!InsideRoot) + { + /* Yes, use the root directory and remember that */ + CurrentDirectory = RootDirectory; + InsideRoot = TRUE; + } + + /* Check if the name starts with a path separator */ + if ((RemainingPath.Length) && + (RemainingPath.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) + { + /* Skip the path separator */ + RemainingPath.Buffer++; + RemainingPath.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR); + } + + /* Find the next Part Name */ + PartName = RemainingPath; + while (RemainingPath.Length) + { + /* Break if we found the \ ending */ + if (RemainingPath.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) break; + + /* Move on */ + RemainingPath.Buffer++; + RemainingPath.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR); + } + + /* Get its size and make sure it's valid */ + if (!(PartName.Length -= RemainingPath.Length)) + { + Status = STATUS_OBJECT_NAME_INVALID; + break; + } + + /* Do the look up */ + Context->DirectoryLocked = TRUE; + Context->Directory = CurrentDirectory; + CurrentObject = ObpLookupEntryDirectory(CurrentDirectory, + &PartName, + Attributes, + FALSE, + Context); + if (!CurrentObject) + { + /* We didn't find it... do we still have a path? */ + if (RemainingPath.Length) + { + /* Then tell the caller the path wasn't found */ + Status = STATUS_OBJECT_PATH_NOT_FOUND; + break; + } + else if (!ExpectedObject) + { + /* Otherwise, we have a path, but the name isn't valid */ + Status = STATUS_OBJECT_NAME_NOT_FOUND; + break; + } + + /* Reference newly to be inserted object */ + ObReferenceObject(ExpectedObject); + CurrentHeader = OBJECT_TO_OBJECT_HEADER(ExpectedObject); + + /* Create Object Name */ + NewName = ExAllocatePoolWithTag(NonPagedPool, + PartName.MaximumLength, + OB_NAME_TAG); + ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(CurrentHeader); + + /* Copy the Name */ + RtlMoveMemory(NewName, PartName.Buffer, PartName.MaximumLength); + + /* Free old name */ + if (ObjectNameInfo->Name.Buffer) ExFreePool(ObjectNameInfo->Name.Buffer); + + /* Write new one */ + ObjectNameInfo->Name.Buffer = NewName; + ObjectNameInfo->Name.Length = PartName.Length; + ObjectNameInfo->Name.MaximumLength = PartName.MaximumLength; + + /* Rereference the Directory and insert */ + ObReferenceObject(CurrentDirectory); + ObpInsertEntryDirectory(CurrentDirectory, Context, CurrentHeader); + + /* Return Status and the Expected Object */ + Status = STATUS_SUCCESS; + CurrentObject = ExpectedObject; + + /* Get out of here */ + break; + } + +Reparse: + /* We found it, so now get its header */ + CurrentHeader = OBJECT_TO_OBJECT_HEADER(CurrentObject); + + /* + * Check for a parse Procedure, but don't bother to parse for an insert + * unless it's a Symbolic Link, in which case we MUST parse + */ + ParseRoutine = CurrentHeader->Type->TypeInfo.ParseProcedure; + if (ParseRoutine && + (!ExpectedObject || ParseRoutine == ObpParseSymbolicLink)) + { + /* Use the Root Directory next time */ + InsideRoot = FALSE; + + /* Call the Parse Procedure */ + Status = ParseRoutine(CurrentObject, + ObjectType, + AccessState, + AccessMode, + Attributes, + ObjectName, + &RemainingPath, + ParseContext, + SecurityQos, + &CurrentObject); + + /* Check if we have to reparse */ + if ((Status == STATUS_REPARSE) || + (Status == STATUS_REPARSE_OBJECT)) + { + /* Start over from root if we got sent back there */ + if ((Status == STATUS_REPARSE_OBJECT) || + (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) + { + /* Check if we got a root directory */ + if (RootHandle) + { + /* Stop using it, because we have a new directory now */ + ObDereferenceObject(RootDirectory); + RootHandle = NULL; + } + + /* Start at Root */ + RootDirectory = NameSpaceRoot; + + /* Check for reparse status */ + if (Status == STATUS_REPARSE_OBJECT) + { + /* Did we actually get an object to which to reparse? */ + if (!CurrentObject) + { + /* We didn't, so set a failure status */ + Status = STATUS_OBJECT_NAME_NOT_FOUND; + } + else + { + /* We did, so we're free to parse the new object */ + InsideRoot = TRUE; + goto Reparse; + } + } + + /* Restart the search */ + goto ReparseNewDir; + } + else if (RootDirectory == NameSpaceRoot) + { + /* We got STATUS_REPARSE but are at the Root Directory */ + CurrentObject = NULL; + Status = STATUS_OBJECT_NAME_NOT_FOUND; + } + } + else if (!NT_SUCCESS(Status)) + { + /* Total failure */ + CurrentObject = NULL; + } + else if (!CurrentObject) + { + /* We didn't reparse but we didn't find the Object Either */ + Status = STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* Break out of the loop */ + break; + } + else + { + /* No parse routine...do we still have a remaining name? */ + if (!RemainingPath.Length) + { + /* Are we creating an object? */ + if (!ExpectedObject) + { + /* We don't... reference the Object */ + Status = ObReferenceObjectByPointer(CurrentObject, + 0, + ObjectType, + AccessMode); + if (!NT_SUCCESS(Status)) CurrentObject = NULL; + } + + /* And get out of the reparse loop */ + break; + } + else + { + /* We still have a name; check if this is a directory object */ + if (CurrentHeader->Type == ObDirectoryType) + { + /* Restart from this directory */ + CurrentDirectory = CurrentObject; + } + else + { + /* We still have a name, but no parse routine for it */ + Status = STATUS_OBJECT_TYPE_MISMATCH; + CurrentObject = NULL; + break; + } + } + } + } + + /* Write what we found, and if it's null, check if we got success */ + if (!(*ReturnedObject = CurrentObject) && (NT_SUCCESS(Status))) + { + /* Nothing found... but we have success. Correct the status code */ + Status = STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* Check if we had a root directory */ + if (RootHandle) + { + /* Dereference it */ + ObDereferenceObject(RootDirectory); + } + + /* Return status to caller */ + OBTRACE(OB_NAMESPACE_DEBUG, + "%s - Found Object: %p. Expected: %p\n", + __FUNCTION__, + *ReturnedObject, + ExpectedObject); return Status; } diff --git a/reactos/ntoskrnl/ob/symlink.c b/reactos/ntoskrnl/ob/symlink.c index e0f0f8981c2..f4a0c5257e9 100644 --- a/reactos/ntoskrnl/ob/symlink.c +++ b/reactos/ntoskrnl/ob/symlink.c @@ -100,24 +100,45 @@ ObpParseSymbolicLink(IN PVOID ParsedObject, POBJECT_SYMBOLIC_LINK SymlinkObject = (POBJECT_SYMBOLIC_LINK)ParsedObject; PUNICODE_STRING TargetPath; PWSTR NewTargetPath; - ULONG LengthUsed, MaximumLength, RemainLength; - PWSTR *RemainingPath = &RemainingName->Buffer; + ULONG LengthUsed, MaximumLength; + NTSTATUS Status; - /* - * Stop parsing if the entire path has been parsed and - * the desired object is a symbolic link object. - */ - if (((*RemainingPath == NULL) || (**RemainingPath == 0)) && - (Attributes & OBJ_OPENLINK)) + /* Assume failure */ + *NextObject = NULL; + + /* Check if we're out of name to parse */ + if (!RemainingName->Length) { - *NextObject = NULL; - return(STATUS_SUCCESS); + /* Check if we got an object type */ + if (ObjectType) + { + /* Reference the object only */ + Status = ObReferenceObjectByPointer(ParsedObject, + 0, + ObjectType, + AccessMode); + if (NT_SUCCESS(Status)) + { + /* Return it */ + *NextObject = ParsedObject; + } + + if ((NT_SUCCESS(Status)) || (Status != STATUS_OBJECT_TYPE_MISMATCH)) + { + /* Fail */ + return Status; + } + } + } + else if (RemainingName->Buffer[0] != OBJ_NAME_PATH_SEPARATOR) + { + /* Symbolic links must start with a backslash */ + return STATUS_OBJECT_TYPE_MISMATCH; } /* Set the target path and length */ TargetPath = &SymlinkObject->LinkTarget; - RemainLength = *RemainingPath ? wcslen(*RemainingPath) * sizeof(WCHAR) : 0; - LengthUsed = TargetPath->Length + RemainLength; + LengthUsed = TargetPath->Length + RemainingName->Length; /* Optimization: check if the new name is shorter */ if (FullPath->MaximumLength <= LengthUsed) @@ -136,12 +157,12 @@ ObpParseSymbolicLink(IN PVOID ParsedObject, } /* Make sure we have a length */ - if (RemainLength) + if (RemainingName->Length) { /* Copy the new path */ RtlMoveMemory((PVOID)((ULONG_PTR)NewTargetPath + TargetPath->Length), - *RemainingPath, - RemainLength); + RemainingName->Buffer, + RemainingName->Length); } /* Copy the target path and null-terminate it */ @@ -156,10 +177,7 @@ ObpParseSymbolicLink(IN PVOID ParsedObject, FullPath->MaximumLength = MaximumLength; FullPath->Buffer = NewTargetPath; - /* Reinitialize RemainingPath for reparsing */ - *RemainingPath = FullPath->Buffer; - - *NextObject = NULL; + /* Tell the parse routine to start reparsing */ return STATUS_REPARSE; } diff --git a/reactos/subsystems/win32/win32k/ntuser/desktop.c b/reactos/subsystems/win32/win32k/ntuser/desktop.c index ec410a7413c..7afb5db7fe4 100644 --- a/reactos/subsystems/win32/win32k/ntuser/desktop.c +++ b/reactos/subsystems/win32/win32k/ntuser/desktop.c @@ -133,7 +133,6 @@ IntDesktopObjectParse(IN PVOID ParseObject, /* Reference the desktop and return it */ ObReferenceObject(Desktop); *Object = Desktop; - RemainingName->Buffer = NULL; // => ROS Parse routines need to do this return Status; } } @@ -168,7 +167,6 @@ IntDesktopObjectParse(IN PVOID ParseObject, /* Set the desktop object and return success */ *Object = Desktop; - RemainingName->Buffer = NULL; // => ROS Parse routines need to do this return STATUS_SUCCESS; } diff --git a/reactos/subsystems/win32/win32k/ntuser/winsta.c b/reactos/subsystems/win32/win32k/ntuser/winsta.c index e2c9941007d..237069e8ecb 100644 --- a/reactos/subsystems/win32/win32k/ntuser/winsta.c +++ b/reactos/subsystems/win32/win32k/ntuser/winsta.c @@ -126,8 +126,8 @@ IntWinStaObjectParse(PWIN32_PARSEMETHOD_PARAMETERS Parameters) } /* Reference the window station and return */ - //ObReferenceObject(Object); - //*NextObject = Object; => ROS Parse routines don't need to do this + ObReferenceObject(Parameters->ParseObject); + *Parameters->Object = Parameters->ParseObject; return STATUS_SUCCESS; } @@ -149,10 +149,8 @@ IntWinStaObjectParse(PWIN32_PARSEMETHOD_PARAMETERS Parameters) /* * Check if we are parsing a desktop. - * FIXME: ROS Sends the wrong Object Type. The parsed object's type - * should be sent, not the parsed parent's. */ - if (Parameters->ObjectType == ExWindowStationObjectType) + if (Parameters->ObjectType == ExDesktopObjectType) { /* Then call the desktop parse routine */ return IntDesktopObjectParse(Parameters->ParseObject,