Author: ion Date: Mon Jun 12 09:58:08 2006 New Revision: 22319
URL: http://svn.reactos.ru/svn/reactos?rev=22319&view=rev Log: - Pretty much the last Ob implementation/optimization patch (Except for a minor fix by Thomas to fix handle sweeping), re-implemented the ObFindObject routine by using some code that I had written almost 2 years ago with help from Thomas and Filip, plus some fixes discovered today while testing. - Fixed symbolic link and desktop/winsta parse procedures to become NT-compatible now that ObFindObject is as well. Also fixed file/device parse routine for these changes. - ObFindObject now supports STATUS_REPARSE_OBJECT, and has an optimized path for parsing when a root directory is given, as well as is entirely unicode_string-based. - Cleaned up ob.h and added ob_x.h for the inlined functions. - Implemented new Ob tracing system.
Added: trunk/reactos/ntoskrnl/include/internal/ob_x.h Modified: trunk/reactos/ntoskrnl/include/internal/ob.h trunk/reactos/ntoskrnl/io/file.c trunk/reactos/ntoskrnl/ob/obhandle.c trunk/reactos/ntoskrnl/ob/obinit.c trunk/reactos/ntoskrnl/ob/obname.c trunk/reactos/ntoskrnl/ob/symlink.c trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c trunk/reactos/subsystems/win32/win32k/ntuser/winsta.c
Modified: trunk/reactos/ntoskrnl/include/internal/ob.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/include/internal/ob... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ob.h (original) +++ trunk/reactos/ntoskrnl/include/internal/ob.h Mon Jun 12 09:58:08 2006 @@ -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) - */ - -#ifndef __INCLUDE_INTERNAL_OBJMGR_H -#define __INCLUDE_INTERNAL_OBJMGR_H - +* 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" + +// +// 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 @@ 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 @@ IN PEPROCESS Process );
+// +// Object Lookup Functions +// NTSTATUS NTAPI ObFindObject( @@ -107,6 +167,9 @@ IN PVOID Insert );
+// +// Object Attribute Functions +// BOOLEAN NTAPI ObpSetHandleAttributes( @@ -117,17 +180,26 @@
VOID NTAPI -ObpDeleteNameCheck( - IN PVOID Object -); - -VOID -NTAPI ObQueryDeviceMapInformation( IN PEPROCESS Process, OUT PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo );
+// +// Object Lifetime Functions +// +VOID +FASTCALL +ObpDeleteObject( + IN PVOID Object +); + +VOID +NTAPI +ObpReapObject( + IN PVOID Unused +); + VOID FASTCALL ObpSetPermanentObject( @@ -136,22 +208,19 @@ );
VOID -FASTCALL -ObpDeleteObject( - IN PVOID Object -); - -VOID -NTAPI -ObpReapObject( - IN PVOID Unused -); - -/* Security descriptor cache functions */ - -NTSTATUS -NTAPI -ObpInitSdCache(VOID); +NTAPI +ObpDeleteNameCheck( + IN PVOID Object +); + +// +// Security descriptor cache functions +// +NTSTATUS +NTAPI +ObpInitSdCache( + VOID +);
NTSTATUS NTAPI @@ -162,7 +231,9 @@
NTSTATUS NTAPI -ObpRemoveSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor); +ObpRemoveSecurityDescriptor( + IN PSECURITY_DESCRIPTOR SecurityDescriptor +);
PSECURITY_DESCRIPTOR NTAPI @@ -172,37 +243,45 @@
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 -); - -/* Object Create and Object Name Capture Functions */ - -NTSTATUS -STDCALL + IN PVOID Object +); + +// +// Object Create and Object Name Capture Functions +// +NTSTATUS +NTAPI ObpCaptureObjectName( IN PUNICODE_STRING CapturedName, IN PUNICODE_STRING ObjectName, @@ -211,7 +290,7 @@ );
NTSTATUS -STDCALL +NTAPI ObpCaptureObjectAttributes( IN POBJECT_ATTRIBUTES ObjectAttributes, IN KPROCESSOR_MODE AccessMode, @@ -220,119 +299,17 @@ 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;
Added: trunk/reactos/ntoskrnl/include/internal/ob_x.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/include/internal/ob... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ob_x.h (added) +++ trunk/reactos/ntoskrnl/include/internal/ob_x.h Mon Jun 12 09:58:08 2006 @@ -1,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); +} +
Modified: trunk/reactos/ntoskrnl/io/file.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/io/file.c?rev=22319... ============================================================================== --- trunk/reactos/ntoskrnl/io/file.c (original) +++ trunk/reactos/ntoskrnl/io/file.c Mon Jun 12 09:58:08 2006 @@ -44,19 +44,15 @@ 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); - - if (!RemainingName || !RemainingName->Buffer) + "DeviceObject : %p\n" + "RelatedFileObject : %p\n" + "CompleteName : %wZ, RemainingName : %wZ\n", + ParseObject, + Context, + CompleteName, + RemainingName); + + if (!*RemainingName->Buffer) { DeviceObject = ParseObject;
@@ -71,6 +67,7 @@ (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 @@ 0, (PVOID*)&FileObject);
- if (ObjectType == IoDeviceObjectType) + if (!Context) { /* Parent is a device object */ DeviceObject = IoGetAttachedDevice((PDEVICE_OBJECT)ParseObject); @@ -110,7 +107,6 @@ RtlCreateUnicodeString(&FileObject->FileName, RemainingName->Buffer); FileObject->DeviceObject = DeviceObject; *Object = FileObject; - RemainingName->Buffer = NULL; // ros hack return STATUS_SUCCESS; }
Modified: trunk/reactos/ntoskrnl/ob/obhandle.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/ob/obhandle.c?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/ob/obhandle.c (original) +++ trunk/reactos/ntoskrnl/ob/obhandle.c Mon Jun 12 09:58:08 2006 @@ -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 @@ /* 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 @@
/* 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 @@ 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 @@ //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 @@ /* 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 @@
/* 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 @@ /* 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 @@
/* 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 @@
/* 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 @@ * 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 @@ /* 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 @@ /* 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 @@ * 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 @@ /* 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 @@ 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 @@ }
/* 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ }
/* 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,
Modified: trunk/reactos/ntoskrnl/ob/obinit.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/ob/obinit.c?rev=223... ============================================================================== --- trunk/reactos/ntoskrnl/ob/obinit.c (original) +++ trunk/reactos/ntoskrnl/ob/obinit.c Mon Jun 12 09:58:08 2006 @@ -38,6 +38,7 @@ };
PDEVICE_MAP ObSystemDeviceMap = NULL; +ULONG ObpTraceLevel = OB_NAMESPACE_DEBUG;
/* PRIVATE FUNCTIONS *********************************************************/
Modified: trunk/reactos/ntoskrnl/ob/obname.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/ob/obname.c?rev=223... ============================================================================== --- trunk/reactos/ntoskrnl/ob/obname.c (original) +++ trunk/reactos/ntoskrnl/ob/obname.c Mon Jun 12 09:58:08 2006 @@ -106,280 +106,433 @@ 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); - - RtlInitUnicodeString (RemainingPath, NULL); - - if (RootHandle == NULL) - { - ObReferenceObjectByPointer(NameSpaceRoot, - DIRECTORY_TRAVERSE, - NULL, - PreviousMode); - CurrentObject = NameSpaceRoot; + /* Assume failure */ + OBTRACE(OB_NAMESPACE_DEBUG, + "%s - Finding Object: %wZ. Expecting: %p\n", + __FUNCTION__, + ObjectName, + ExpectedObject); + *ReturnedObject = NULL; + + /* Check if we got a Root Directory */ + if (RootHandle) + { + /* We did. Reference it */ + Status = ObReferenceObjectByHandle(RootHandle, + 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; + } } else { - Status = ObReferenceObjectByHandle(RootHandle, - 0, - NULL, - PreviousMode, - &CurrentObject, - NULL); - if (!NT_SUCCESS(Status)) - { - 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; - + /* 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)) + { + /* 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 + { + /* 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);
- /* 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; + /* + * 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 { - 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) - { - if (wcschr(RemainingPath->Buffer + 1, L'\') == NULL) - Status = STATUS_OBJECT_NAME_NOT_FOUND; - else - Status =STATUS_OBJECT_PATH_NOT_FOUND; - } - } - + /* 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; }
Modified: trunk/reactos/ntoskrnl/ob/symlink.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/ob/symlink.c?rev=22... ============================================================================== --- trunk/reactos/ntoskrnl/ob/symlink.c (original) +++ trunk/reactos/ntoskrnl/ob/symlink.c Mon Jun 12 09:58:08 2006 @@ -100,24 +100,45 @@ POBJECT_SYMBOLIC_LINK SymlinkObject = (POBJECT_SYMBOLIC_LINK)ParsedObject; PUNICODE_STRING TargetPath; PWSTR NewTargetPath; - ULONG LengthUsed, MaximumLength, RemainLength; - PWSTR *RemainingPath = &RemainingName->Buffer; - - /* - * 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)) - { - *NextObject = NULL; - return(STATUS_SUCCESS); + ULONG LengthUsed, MaximumLength; + NTSTATUS Status; + + /* Assume failure */ + *NextObject = NULL; + + /* Check if we're out of name to parse */ + if (!RemainingName->Length) + { + /* 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 @@ }
/* 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 @@ 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; }
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c Mon Jun 12 09:58:08 2006 @@ -133,7 +133,6 @@ /* 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 @@
/* Set the desktop object and return success */ *Object = Desktop; - RemainingName->Buffer = NULL; // => ROS Parse routines need to do this return STATUS_SUCCESS; }
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/winsta.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/winsta.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/winsta.c Mon Jun 12 09:58:08 2006 @@ -126,8 +126,8 @@ }
/* 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 @@
/* * 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,