- Rewrote the Object Directory implementation to follow the NT Structures in the NDK. This got rid of the last remaining OBJECT_HEADER difference and switched over to OBJECT_DIRECTORY.

- The low-level implementation is based on information from "Undocumented Windows 2000 Internals: A Programmer's Cookbook", with some modifications done by myself to match the updated 2003 structures. This implementation was hackishly stuck into our messed up high-level object lookup implementation, which now has 4 more band-aids. Still needs a lot of work done to the upper echelons of object lookup, but at least this gets rid of ROS-internal stuff.

svn path=/trunk/; revision=22015
This commit is contained in:
Alex Ionescu 2006-05-24 20:06:13 +00:00
parent 238be0b59c
commit 3ccc97c6c4
13 changed files with 373 additions and 210 deletions

View file

@ -318,12 +318,44 @@ typedef struct _OBJECT_TYPE
ERESOURCE ObjectLocks[4]; ERESOURCE ObjectLocks[4];
} OBJECT_TYPE; } OBJECT_TYPE;
//
// Object Directory Structures
//
typedef struct _OBJECT_DIRECTORY_ENTRY
{
struct _OBJECT_DIRECTORY_ENTRY *ChainLink;
PVOID Object;
#if (NTDDI_VERSION >= NTDDI_WS03)
ULONG HashValue;
#endif
} OBJECT_DIRECTORY_ENTRY, *POBJECT_DIRECTORY_ENTRY;
typedef struct _OBJECT_DIRECTORY
{
struct _OBJECT_DIRECTORY_ENTRY *HashBuckets[NUMBER_HASH_BUCKETS];
#if (NTDDI_VERSION < NTDDI_WINXP)
ERESOURCE Lock;
#elif (NTDDI_VERSION >= NTDDI_WINXP)
ERESOURCE Lock; // FIXME: HACKHACK, SHOULD BE EX_PUSH_LOCK
#endif
#if (NTDDI_VERSION < NTDDI_WINXP)
BOOLEAN CurrentEntryValid;
#else
struct _DEVICE_MAP *DeviceMap;
#endif
ULONG SessionId;
#if (NTDDI_VERSION == NTDDI_WINXP)
USHORT Reserved;
USHORT SymbolicLinkUsageCount;
#endif
} OBJECT_DIRECTORY, *POBJECT_DIRECTORY;
// //
// Object Header Addon Information // Object Header Addon Information
// //
typedef struct _OBJECT_HEADER_NAME_INFO typedef struct _OBJECT_HEADER_NAME_INFO
{ {
struct _DIRECTORY_OBJECT *Directory; POBJECT_DIRECTORY Directory;
UNICODE_STRING Name; UNICODE_STRING Name;
ULONG QueryReferences; ULONG QueryReferences;
ULONG Reserved2; ULONG Reserved2;
@ -384,48 +416,16 @@ typedef struct _OBJECT_HEADER
QUAD Body; QUAD Body;
} OBJECT_HEADER, *POBJECT_HEADER; } OBJECT_HEADER, *POBJECT_HEADER;
//
// Object Directory Structures
//
typedef struct _OBJECT_DIRECTORY_ENTRY
{
struct _OBJECT_DIRECTORY_ENTRY *ChainLink;
PVOID Object;
#if (NTDDI_VERSION >= NTDDI_WS03)
ULONG HashValue;
#endif
} OBJECT_DIRECTORY_ENTRY, *POBJECT_DIRECTORY_ENTRY;
typedef struct _OBJECT_DIRECTORY
{
struct _OBJECT_DIRECTORY_ENTRY *HashBuckets[NUMBER_HASH_BUCKETS];
#if (NTDDI_VERSION < NTDDI_WINXP)
PERESOURCE Lock;
#elif (NTDDI_VERSION >= NTDDI_WINXP)
EX_PUSH_LOCK Lock;
#endif
#if (NTDDI_VERSION < NTDDI_WINXP)
BOOLEAN CurrentEntryValid;
#else
struct _DEVICE_MAP *DeviceMap;
#endif
ULONG SessionId;
#if (NTDDI_VERSION == NTDDI_WINXP)
USHORT Reserved;
USHORT SymbolicLinkUsageCount;
#endif
} OBJECT_DIRECTORY, *POBJECT_DIRECTORY;
// //
// Device Map // Device Map
// //
typedef struct _DEVICE_MAP typedef struct _DEVICE_MAP
{ {
POBJECT_DIRECTORY DosDevicesDirectory; POBJECT_DIRECTORY DosDevicesDirectory;
POBJECT_DIRECTORY GlobalDosDevicesDirectory; POBJECT_DIRECTORY GlobalDosDevicesDirectory;
ULONG ReferenceCount; ULONG ReferenceCount;
ULONG DriveMap; ULONG DriveMap;
UCHAR DriveType[32]; UCHAR DriveType[32];
} DEVICE_MAP, *PDEVICE_MAP; } DEVICE_MAP, *PDEVICE_MAP;
// //

View file

@ -199,6 +199,7 @@ NtCreateKey(OUT PHANDLE KeyHandle,
KPROCESSOR_MODE PreviousMode; KPROCESSOR_MODE PreviousMode;
UNICODE_STRING CapturedClass = {0}; UNICODE_STRING CapturedClass = {0};
HANDLE hKey; HANDLE hKey;
OBP_LOOKUP_CONTEXT Context;
PAGED_CODE(); PAGED_CODE();
@ -262,7 +263,8 @@ NtCreateKey(OUT PHANDLE KeyHandle,
&ObjectName, &ObjectName,
(PVOID*)&Object, (PVOID*)&Object,
&RemainingPath, &RemainingPath,
CmiKeyType); CmiKeyType,
&Context);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
PostCreateKeyInfo.Object = NULL; PostCreateKeyInfo.Object = NULL;
@ -1262,6 +1264,7 @@ NtOpenKey(OUT PHANDLE KeyHandle,
OBJECT_CREATE_INFORMATION ObjectCreateInfo; OBJECT_CREATE_INFORMATION ObjectCreateInfo;
REG_PRE_OPEN_KEY_INFORMATION PreOpenKeyInfo; REG_PRE_OPEN_KEY_INFORMATION PreOpenKeyInfo;
REG_POST_OPEN_KEY_INFORMATION PostOpenKeyInfo; REG_POST_OPEN_KEY_INFORMATION PostOpenKeyInfo;
OBP_LOOKUP_CONTEXT Context;
PAGED_CODE(); PAGED_CODE();
@ -1329,7 +1332,8 @@ NtOpenKey(OUT PHANDLE KeyHandle,
&ObjectName, &ObjectName,
(PVOID*)&Object, (PVOID*)&Object,
&RemainingPath, &RemainingPath,
CmiKeyType); CmiKeyType,
&Context);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("CmpFindObject() returned 0x%08lx\n", Status); DPRINT("CmpFindObject() returned 0x%08lx\n", Status);

View file

@ -704,6 +704,7 @@ CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
PWSTR SubName; PWSTR SubName;
UNICODE_STRING ObjectName; UNICODE_STRING ObjectName;
OBJECT_CREATE_INFORMATION ObjectCreateInfo; OBJECT_CREATE_INFORMATION ObjectCreateInfo;
OBP_LOOKUP_CONTEXT Context;
DPRINT("CmiConnectHive(%p, %p) called.\n", DPRINT("CmiConnectHive(%p, %p) called.\n",
KeyObjectAttributes, RegistryHive); KeyObjectAttributes, RegistryHive);
@ -725,7 +726,8 @@ CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
&ObjectName, &ObjectName,
(PVOID*)&ParentKey, (PVOID*)&ParentKey,
&RemainingPath, &RemainingPath,
CmiKeyType); CmiKeyType,
&Context);
ObpReleaseCapturedAttributes(&ObjectCreateInfo); ObpReleaseCapturedAttributes(&ObjectCreateInfo);
if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer); if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))

View file

@ -86,14 +86,16 @@ ExpWinStaObjectParse(PVOID Object,
PVOID *NextObject, PVOID *NextObject,
PUNICODE_STRING FullPath, PUNICODE_STRING FullPath,
PWSTR *Path, PWSTR *Path,
ULONG Attributes) ULONG Attributes,
POBP_LOOKUP_CONTEXT Context)
{ {
/* Call the Registered Callback */ /* Call the Registered Callback */
return ExpWindowStationObjectParse(Object, return ExpWindowStationObjectParse(Object,
NextObject, NextObject,
FullPath, FullPath,
Path, Path,
Attributes); Attributes,
Context);
} }
NTSTATUS NTSTATUS

View file

@ -11,21 +11,8 @@
struct _EPROCESS; struct _EPROCESS;
typedef struct _DIRECTORY_OBJECT
{
CSHORT Type;
CSHORT Size;
/*
* PURPOSE: Head of the list of our subdirectories
*/
LIST_ENTRY head;
KSPIN_LOCK Lock;
} DIRECTORY_OBJECT, *PDIRECTORY_OBJECT;
typedef struct _ROS_OBJECT_HEADER typedef struct _ROS_OBJECT_HEADER
{ {
LIST_ENTRY Entry;
LONG PointerCount; LONG PointerCount;
union union
{ {
@ -46,6 +33,16 @@ typedef struct _ROS_OBJECT_HEADER
QUAD Body; QUAD Body;
} ROS_OBJECT_HEADER, *PROS_OBJECT_HEADER; } ROS_OBJECT_HEADER, *PROS_OBJECT_HEADER;
typedef struct _OBP_LOOKUP_CONTEXT
{
POBJECT_DIRECTORY Directory;
PVOID Object;
ULONG HashValue;
USHORT HashIndex;
BOOLEAN DirectoryLocked;
ULONG LockStateSignature;
} OBP_LOOKUP_CONTEXT, *POBP_LOOKUP_CONTEXT;
#define BODY_TO_HEADER(objbdy) \ #define BODY_TO_HEADER(objbdy) \
CONTAINING_RECORD((objbdy), ROS_OBJECT_HEADER, Body) CONTAINING_RECORD((objbdy), ROS_OBJECT_HEADER, Body)
@ -69,7 +66,7 @@ typedef struct _ROS_OBJECT_HEADER
#define ObMarkHandleAsKernelHandle(Handle) \ #define ObMarkHandleAsKernelHandle(Handle) \
(HANDLE)((ULONG_PTR)(Handle) | KERNEL_HANDLE_FLAG) (HANDLE)((ULONG_PTR)(Handle) | KERNEL_HANDLE_FLAG)
extern PDIRECTORY_OBJECT NameSpaceRoot; extern POBJECT_DIRECTORY NameSpaceRoot;
extern POBJECT_TYPE ObSymbolicLinkType; extern POBJECT_TYPE ObSymbolicLinkType;
extern PHANDLE_TABLE ObpKernelHandleTable; extern PHANDLE_TABLE ObpKernelHandleTable;
@ -94,30 +91,27 @@ typedef NTSTATUS
PVOID *NextObject, PVOID *NextObject,
PUNICODE_STRING FullPath, PUNICODE_STRING FullPath,
PWSTR *Path, PWSTR *Path,
ULONG Attributes ULONG Attributes,
POBP_LOOKUP_CONTEXT Context
); );
VOID BOOLEAN
NTAPI NTAPI
ObpAddEntryDirectory( ObpDeleteEntryDirectory(POBP_LOOKUP_CONTEXT Context);
PDIRECTORY_OBJECT Parent,
PROS_OBJECT_HEADER Header,
PWSTR Name
);
NTSTATUS BOOLEAN
NTAPI NTAPI
ObpCreateDirectory( ObpInsertEntryDirectory(IN POBJECT_DIRECTORY Parent,
OB_OPEN_REASON Reason, IN POBP_LOOKUP_CONTEXT Context,
PEPROCESS Process, IN POBJECT_HEADER ObjectHeader);
PVOID ObjectBody,
ACCESS_MASK GrantedAccess,
ULONG HandleCount
);
VOID PVOID
NTAPI NTAPI
ObpRemoveEntryDirectory(PROS_OBJECT_HEADER Header); ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
IN PUNICODE_STRING Name,
IN ULONG Attributes,
IN UCHAR SearchShadow,
IN POBP_LOOKUP_CONTEXT Context);
VOID VOID
NTAPI NTAPI
@ -139,7 +133,8 @@ ObpParseDirectory(
PVOID * NextObject, PVOID * NextObject,
PUNICODE_STRING FullPath, PUNICODE_STRING FullPath,
PWSTR * Path, PWSTR * Path,
ULONG Attributes ULONG Attributes,
POBP_LOOKUP_CONTEXT Context
); );
VOID VOID
@ -157,7 +152,8 @@ ObFindObject(
PUNICODE_STRING ObjectName, PUNICODE_STRING ObjectName,
PVOID* ReturnedObject, PVOID* ReturnedObject,
PUNICODE_STRING RemainingPath, PUNICODE_STRING RemainingPath,
POBJECT_TYPE ObjectType POBJECT_TYPE ObjectType,
POBP_LOOKUP_CONTEXT Context
); );
NTSTATUS NTSTATUS

View file

@ -8,10 +8,12 @@
/* INCLUDES ***************************************************************/ /* INCLUDES ***************************************************************/
#define NTDDI_VERSION NTDDI_WS03
#include <ntoskrnl.h> #include <ntoskrnl.h>
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
#define OBP_PROFILE
#ifdef OBP_PROFILE #ifdef OBP_PROFILE
LARGE_INTEGER ObpProfileTime; LARGE_INTEGER ObpProfileTime;
@ -48,119 +50,228 @@ BOOLEAN ObpProfileComplete;
/* PRIVATE FUNCTIONS ******************************************************/ /* PRIVATE FUNCTIONS ******************************************************/
VOID BOOLEAN
NTAPI NTAPI
ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent, ObpInsertEntryDirectory(IN POBJECT_DIRECTORY Parent,
PROS_OBJECT_HEADER Header, IN POBP_LOOKUP_CONTEXT Context,
PWSTR Name) IN POBJECT_HEADER ObjectHeader)
{ {
KIRQL oldlvl; POBJECT_DIRECTORY_ENTRY *AllocatedEntry;
POBJECT_DIRECTORY_ENTRY NewEntry;
POBJECT_HEADER_NAME_INFO HeaderNameInfo;
ObpStartProfile(); /* Make sure we have a name */
ASSERT(HEADER_TO_OBJECT_NAME(Header)); ASSERT(ObjectHeader->NameInfoOffset != 0);
HEADER_TO_OBJECT_NAME(Header)->Directory = Parent;
KeAcquireSpinLock(&Parent->Lock, &oldlvl); /* Validate the context */
InsertTailList(&Parent->head, &Header->Entry); if ((Context->Object) || !(Context->DirectoryLocked) || !Parent)
KeReleaseSpinLock(&Parent->Lock, oldlvl);
ObpEndProfile();
}
VOID
NTAPI
ObpRemoveEntryDirectory(PROS_OBJECT_HEADER Header)
{
KIRQL oldlvl;
ObpStartProfile();
DPRINT("ObpRemoveEntryDirectory(Header %x)\n",Header);
KeAcquireSpinLock(&(HEADER_TO_OBJECT_NAME(Header)->Directory->Lock),&oldlvl);
if (Header->Entry.Flink && Header->Entry.Blink)
{ {
RemoveEntryList(&(Header->Entry)); DbgPrint("OB: ObpInsertEntryDirectory - invalid context %p %ld\n",
Header->Entry.Flink = Header->Entry.Blink = NULL; Context, Context->DirectoryLocked);
DbgBreakPoint();
return FALSE;
} }
KeReleaseSpinLock(&(HEADER_TO_OBJECT_NAME(Header)->Directory->Lock),oldlvl);
ObpEndProfile();
}
NTSTATUS /* Allocate a new Directory Entry */
NTAPI NewEntry = ExAllocatePoolWithTag(PagedPool,
ObpCreateDirectory(OB_OPEN_REASON Reason, sizeof(OBJECT_DIRECTORY_ENTRY),
PEPROCESS Process, TAG('O', 'b', 'D', 'i'));
PVOID ObjectBody, if (!NewEntry) return FALSE;
ACCESS_MASK GrantedAccess,
ULONG HandleCount)
{
PDIRECTORY_OBJECT Directory = ObjectBody;
ObpStartProfile(); /* Save the hash */
if (Reason == ObCreateHandle) NewEntry->HashValue = Context->HashValue;
{
InitializeListHead(&Directory->head);
KeInitializeSpinLock(&Directory->Lock);
}
ObpEndProfile();
return STATUS_SUCCESS; /* Get the Object Name Information */
HeaderNameInfo = HEADER_TO_OBJECT_NAME(ObjectHeader);
/* Get the Allocated entry */
AllocatedEntry = &Parent->HashBuckets[Context->HashIndex];
DPRINT("ADD: Allocated Entry: %p. NewEntry: %p\n", AllocatedEntry, NewEntry);
DPRINT("ADD: Name: %wZ, Hash: %lx\n", &HeaderNameInfo->Name, Context->HashIndex);
DPRINT("ADD: Parent: %p. Name: %wZ\n",
Parent,
HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Parent)) ?
&HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Parent))->Name : NULL);
/* Set it */
NewEntry->ChainLink = *AllocatedEntry;
*AllocatedEntry = NewEntry;
/* Associate the Object */
NewEntry->Object = &ObjectHeader->Body;
/* Associate the Directory */
HeaderNameInfo->Directory = Parent;
return TRUE;
} }
PVOID PVOID
NTAPI NTAPI
ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject, ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
PWSTR Name, IN PUNICODE_STRING Name,
ULONG Attributes) IN ULONG Attributes,
IN UCHAR SearchShadow,
IN POBP_LOOKUP_CONTEXT Context)
{ {
PLIST_ENTRY current = DirectoryObject->head.Flink; BOOLEAN CaseInsensitive = FALSE;
PROS_OBJECT_HEADER current_obj; POBJECT_HEADER_NAME_INFO HeaderNameInfo;
ULONG HashValue;
ULONG HashIndex;
LONG TotalChars;
WCHAR CurrentChar;
POBJECT_DIRECTORY_ENTRY *AllocatedEntry;
POBJECT_DIRECTORY_ENTRY *LookupBucket;
POBJECT_DIRECTORY_ENTRY CurrentEntry;
PVOID FoundObject = NULL;
PWSTR Buffer;
PAGED_CODE();
ObpStartProfile(); /* Always disable this until we have LUID Device Maps */
DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject, Name); SearchShadow = FALSE;
ObpCompleteProfile();
if (Name[0]==0) /* Fail the following cases */
TotalChars = Name->Length / sizeof(WCHAR);
if (!(Directory) || !(Name) || !(Name->Buffer) || !(TotalChars))
{ {
ObpEndProfile(); goto Quickie;
return(DirectoryObject);
} }
if (Name[0]=='.' && Name[1]==0)
/* Set up case-sensitivity */
if (Attributes & OBJ_CASE_INSENSITIVE) CaseInsensitive = TRUE;
/* Create the Hash */
Buffer = Name->Buffer;
for (HashValue = 0; TotalChars; TotalChars--)
{ {
ObpEndProfile(); /* Go to the next Character */
return(DirectoryObject); CurrentChar = *Buffer++;
/* Prepare the Hash */
HashValue += (HashValue << 1) + (HashValue >> 1);
/* Create the rest based on the name */
if (CurrentChar < 'a') HashValue += CurrentChar;
else if (CurrentChar > 'z') HashValue += RtlUpcaseUnicodeChar(CurrentChar);
else HashValue += (CurrentChar - ('a'-'A'));
} }
if (Name[0]=='.' && Name[1]=='.' && Name[2]==0)
/* Merge it with our number of hash buckets */
HashIndex = HashValue % 37;
DPRINT("LOOKUP: ObjectName: %wZ\n", Name);
DPRINT("LOOKUP: Generated Hash: 0x%x. Generated Id: 0x%x\n", HashValue, HashIndex);
/* Save the result */
Context->HashValue = HashValue;
Context->HashIndex = HashIndex;
/* Get the root entry and set it as our lookup bucket */
AllocatedEntry = &Directory->HashBuckets[HashIndex];
LookupBucket = AllocatedEntry;
DPRINT("LOOKUP: Allocated Entry: %p. LookupBucket: %p\n", AllocatedEntry, LookupBucket);
/* Check if the directory is already locked */
if (!Context->DirectoryLocked)
{ {
ObpEndProfile(); /* Lock it */
return(HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(DirectoryObject))->Directory); KeEnterCriticalRegion();
ExAcquireResourceSharedLite(&Directory->Lock, TRUE);
Context->LockStateSignature = 0xDDDD1234;
} }
while (current!=(&(DirectoryObject->head)))
/* Start looping */
while ((CurrentEntry = *AllocatedEntry))
{ {
current_obj = CONTAINING_RECORD(current,ROS_OBJECT_HEADER,Entry); /* Do the hashes match? */
DPRINT(" Scanning: %S for: %S\n",HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name); DPRINT("CurrentEntry: %p. CurrentHash: %lx\n", CurrentEntry, CurrentEntry->HashValue);
if (Attributes & OBJ_CASE_INSENSITIVE) if (CurrentEntry->HashValue == HashValue)
{ {
if (_wcsicmp(HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name)==0) /* Make sure that it has a name */
ASSERT(BODY_TO_HEADER(CurrentEntry->Object)->NameInfoOffset != 0);
/* Get the name information */
HeaderNameInfo = HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(CurrentEntry->Object));
/* Do the names match? */
DPRINT("NameCheck: %wZ, %wZ\n", Name, &HeaderNameInfo->Name);
if ((Name->Length == HeaderNameInfo->Name.Length) &&
(RtlEqualUnicodeString(Name, &HeaderNameInfo->Name, CaseInsensitive)))
{ {
DPRINT("Found it %x\n",&current_obj->Body); DPRINT("Found Name Match\n");
ObpEndProfile(); break;
return(&current_obj->Body);
} }
} }
else
{ /* Move to the next entry */
if ( wcscmp(HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name)==0) AllocatedEntry = &CurrentEntry->ChainLink;
{
DPRINT("Found it %x\n",&current_obj->Body);
ObpEndProfile();
return(&current_obj->Body);
}
}
current = current->Flink;
} }
DPRINT(" Not Found: %s() = NULL\n",__FUNCTION__);
ObpEndProfile(); /* Check if we still have an entry */
return(NULL); if (CurrentEntry)
{
/* Set this entry as the first, to speed up incoming insertion */
if (AllocatedEntry != LookupBucket)
{
/* Set the Current Entry */
*AllocatedEntry = CurrentEntry->ChainLink;
/* Link to the old Hash Entry */
CurrentEntry->ChainLink = *LookupBucket;
/* Set the new Hash Entry */
*LookupBucket = CurrentEntry;
}
/* Save the found object */
FoundObject = CurrentEntry->Object;
if (!FoundObject) goto Quickie;
/* Add a reference to the object */
ObReferenceObject(FoundObject);
}
/* Check if the directory was unlocked (which means we locked it) */
if (!Context->DirectoryLocked)
{
/* Lock it */
ExReleaseResourceLite(&Directory->Lock);
KeLeaveCriticalRegion();
Context->LockStateSignature = 0xEEEE1234;
}
Quickie:
/* Return the object we found */
DPRINT("Object Found: %p Context: %p\n", FoundObject, Context);
Context->Object = FoundObject;
return FoundObject;
}
BOOLEAN
NTAPI
ObpDeleteEntryDirectory(POBP_LOOKUP_CONTEXT Context)
{
POBJECT_DIRECTORY Directory;
POBJECT_DIRECTORY_ENTRY *AllocatedEntry;
POBJECT_DIRECTORY_ENTRY CurrentEntry;
/* Get the Directory */
Directory = Context->Directory;
if (!Directory) return FALSE;
/* Get the Entry */
AllocatedEntry = &Directory->HashBuckets[Context->HashIndex];
CurrentEntry = *AllocatedEntry;
DPRINT("DEL: Parent: %p, Hash: %lx, AllocatedEntry: %p, CurrentEntry: %p\n",
Directory, Context->HashIndex, AllocatedEntry, CurrentEntry);
/* Unlink the Entry */
*AllocatedEntry = CurrentEntry->ChainLink;
CurrentEntry->ChainLink = NULL;
/* Free it */
ExFreePool(CurrentEntry);
/* Return */
return TRUE;
} }
NTSTATUS NTSTATUS
@ -169,22 +280,19 @@ ObpParseDirectory(PVOID Object,
PVOID * NextObject, PVOID * NextObject,
PUNICODE_STRING FullPath, PUNICODE_STRING FullPath,
PWSTR * Path, PWSTR * Path,
ULONG Attributes) ULONG Attributes,
POBP_LOOKUP_CONTEXT Context)
{ {
PWSTR Start; PWSTR Start;
PWSTR End; PWSTR End;
PVOID FoundObject; PVOID FoundObject;
KIRQL oldlvl; //KIRQL oldlvl;
UNICODE_STRING StartUs;
ObpStartProfile();
DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
Object,Path,*Path);
*NextObject = NULL; *NextObject = NULL;
if ((*Path) == NULL) if ((*Path) == NULL)
{ {
ObpEndProfile();
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
@ -198,16 +306,18 @@ ObpParseDirectory(PVOID Object,
*End = 0; *End = 0;
} }
KeAcquireSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), &oldlvl); //KeAcquireSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), &oldlvl);
FoundObject = ObpFindEntryDirectory(Object, Start, Attributes); RtlInitUnicodeString(&StartUs, Start);
Context->DirectoryLocked = TRUE;
Context->Directory = Object;
FoundObject = ObpLookupEntryDirectory(Object, &StartUs, Attributes, FALSE, Context);
if (FoundObject == NULL) if (FoundObject == NULL)
{ {
KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl); //KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
if (End != NULL) if (End != NULL)
{ {
*End = L'\\'; *End = L'\\';
} }
ObpEndProfile();
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
@ -215,7 +325,7 @@ ObpParseDirectory(PVOID Object,
STANDARD_RIGHTS_REQUIRED, STANDARD_RIGHTS_REQUIRED,
NULL, NULL,
UserMode); UserMode);
KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl); //KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
if (End != NULL) if (End != NULL)
{ {
*End = L'\\'; *End = L'\\';
@ -228,7 +338,6 @@ ObpParseDirectory(PVOID Object,
*NextObject = FoundObject; *NextObject = FoundObject;
ObpEndProfile();
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -360,7 +469,7 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
IN OUT PULONG Context, IN OUT PULONG Context,
OUT PULONG ReturnLength OPTIONAL) OUT PULONG ReturnLength OPTIONAL)
{ {
PDIRECTORY_OBJECT Directory; POBJECT_DIRECTORY Directory;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
ULONG SkipEntries = 0; ULONG SkipEntries = 0;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
@ -441,7 +550,7 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes) IN POBJECT_ATTRIBUTES ObjectAttributes)
{ {
PDIRECTORY_OBJECT Directory; POBJECT_DIRECTORY Directory;
HANDLE hDirectory; HANDLE hDirectory;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
@ -475,7 +584,7 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
ObjectAttributes, ObjectAttributes,
PreviousMode, PreviousMode,
NULL, NULL,
sizeof(DIRECTORY_OBJECT), sizeof(OBJECT_DIRECTORY),
0, 0,
0, 0,
(PVOID*)&Directory); (PVOID*)&Directory);
@ -488,12 +597,6 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
0, 0,
NULL, NULL,
&hDirectory); &hDirectory);
if (!NT_SUCCESS(Status))
{
ObMakeTemporaryObject(Directory);
}
ObDereferenceObject(Directory);
if(NT_SUCCESS(Status)) if(NT_SUCCESS(Status))
{ {
_SEH_TRY _SEH_TRY
@ -506,6 +609,8 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
} }
_SEH_END; _SEH_END;
} }
ObDereferenceObject(Directory);
} }
return Status; return Status;

View file

@ -54,6 +54,7 @@ ObpDecrementHandleCount(PVOID ObjectBody)
{ {
PROS_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody); PROS_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
LONG NewHandleCount = InterlockedDecrement(&ObjectHeader->HandleCount); LONG NewHandleCount = InterlockedDecrement(&ObjectHeader->HandleCount);
OBP_LOOKUP_CONTEXT Context;
DPRINT("Header: %x\n", ObjectHeader); DPRINT("Header: %x\n", ObjectHeader);
DPRINT("NewHandleCount: %x\n", NewHandleCount); DPRINT("NewHandleCount: %x\n", NewHandleCount);
DPRINT("HEADER_TO_OBJECT_NAME: %x\n", HEADER_TO_OBJECT_NAME(ObjectHeader)); DPRINT("HEADER_TO_OBJECT_NAME: %x\n", HEADER_TO_OBJECT_NAME(ObjectHeader));
@ -75,7 +76,18 @@ ObpDecrementHandleCount(PVOID ObjectBody)
/* delete the object from the namespace when the last handle got closed. /* delete the object from the namespace when the last handle got closed.
Only do this if it's actually been inserted into the namespace and Only do this if it's actually been inserted into the namespace and
if it's not a permanent object. */ if it's not a permanent object. */
ObpRemoveEntryDirectory((PROS_OBJECT_HEADER)ObjectHeader);
/* Make sure it's still inserted */
Context.Directory = HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory;
Context.DirectoryLocked = TRUE;
if (ObpLookupEntryDirectory(HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory,
&HEADER_TO_OBJECT_NAME(ObjectHeader)->Name,
0,
FALSE,
&Context))
{
ObpDeleteEntryDirectory(&Context);
}
} }
/* remove the keep-alive reference */ /* remove the keep-alive reference */
@ -1150,6 +1162,7 @@ ObInsertObject(IN PVOID Object,
BOOLEAN ObjectAttached = FALSE; BOOLEAN ObjectAttached = FALSE;
PSECURITY_DESCRIPTOR NewSecurityDescriptor = NULL; PSECURITY_DESCRIPTOR NewSecurityDescriptor = NULL;
SECURITY_SUBJECT_CONTEXT SubjectContext; SECURITY_SUBJECT_CONTEXT SubjectContext;
OBP_LOOKUP_CONTEXT Context;
PAGED_CODE(); PAGED_CODE();
@ -1167,7 +1180,8 @@ ObInsertObject(IN PVOID Object,
&ObjectNameInfo->Name, &ObjectNameInfo->Name,
&FoundObject, &FoundObject,
&RemainingPath, &RemainingPath,
NULL); NULL,
&Context);
DPRINT("FoundObject: %x, Path: %wZ\n", FoundObject, &RemainingPath); DPRINT("FoundObject: %x, Path: %wZ\n", FoundObject, &RemainingPath);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -1202,10 +1216,7 @@ ObInsertObject(IN PVOID Object,
PVOID NewName; PVOID NewName;
PWSTR BufferPos = RemainingPath.Buffer; PWSTR BufferPos = RemainingPath.Buffer;
ULONG Delta = 0; ULONG Delta = 0;
ObpAddEntryDirectory(FoundObject, (PROS_OBJECT_HEADER)Header, NULL);
ObjectAttached = TRUE;
ObjectNameInfo = HEADER_TO_OBJECT_NAME(Header); ObjectNameInfo = HEADER_TO_OBJECT_NAME(Header);
if (BufferPos[0] == L'\\') if (BufferPos[0] == L'\\')
@ -1219,7 +1230,8 @@ ObInsertObject(IN PVOID Object,
ObjectNameInfo->Name.Buffer = NewName; ObjectNameInfo->Name.Buffer = NewName;
ObjectNameInfo->Name.Length = RemainingPath.Length - Delta; ObjectNameInfo->Name.Length = RemainingPath.Length - Delta;
ObjectNameInfo->Name.MaximumLength = RemainingPath.MaximumLength - Delta; ObjectNameInfo->Name.MaximumLength = RemainingPath.MaximumLength - Delta;
DPRINT("Name: %S\n", ObjectNameInfo->Name.Buffer); ObpInsertEntryDirectory(FoundObject, &Context, (POBJECT_HEADER)Header);
ObjectAttached = TRUE;
} }
if ((Header->Type == IoFileObjectType) || if ((Header->Type == IoFileObjectType) ||
@ -1262,7 +1274,7 @@ ObInsertObject(IN PVOID Object,
DPRINT("Create Failed\n"); DPRINT("Create Failed\n");
if (ObjectAttached == TRUE) if (ObjectAttached == TRUE)
{ {
ObpRemoveEntryDirectory((PROS_OBJECT_HEADER)Header); ObpDeleteEntryDirectory(&Context);
} }
if (FoundObject) if (FoundObject)
{ {

View file

@ -26,8 +26,8 @@ extern ULONG NtGlobalFlag;
POBJECT_TYPE ObDirectoryType = NULL; POBJECT_TYPE ObDirectoryType = NULL;
POBJECT_TYPE ObTypeObjectType = NULL; POBJECT_TYPE ObTypeObjectType = NULL;
PDIRECTORY_OBJECT NameSpaceRoot = NULL; POBJECT_DIRECTORY NameSpaceRoot = NULL;
PDIRECTORY_OBJECT ObpTypeDirectoryObject = NULL; POBJECT_DIRECTORY ObpTypeDirectoryObject = NULL;
/* FIXME: Move this somewhere else once devicemap support is in */ /* FIXME: Move this somewhere else once devicemap support is in */
PDEVICE_MAP ObSystemDeviceMap = NULL; PDEVICE_MAP ObSystemDeviceMap = NULL;
KEVENT ObpDefaultObject; KEVENT ObpDefaultObject;
@ -72,6 +72,7 @@ ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
UNICODE_STRING ObjectName; UNICODE_STRING ObjectName;
OBJECT_CREATE_INFORMATION ObjectCreateInfo; OBJECT_CREATE_INFORMATION ObjectCreateInfo;
NTSTATUS Status; NTSTATUS Status;
OBP_LOOKUP_CONTEXT Context;
PAGED_CODE(); PAGED_CODE();
@ -95,7 +96,8 @@ ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
&ObjectName, &ObjectName,
&Object, &Object,
&RemainingPath, &RemainingPath,
ObjectType); ObjectType,
&Context);
if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer); if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
@ -160,6 +162,7 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
UNICODE_STRING ObjectName; UNICODE_STRING ObjectName;
OBJECT_CREATE_INFORMATION ObjectCreateInfo; OBJECT_CREATE_INFORMATION ObjectCreateInfo;
NTSTATUS Status; NTSTATUS Status;
OBP_LOOKUP_CONTEXT Context;
PAGED_CODE(); PAGED_CODE();
@ -182,7 +185,8 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
&ObjectName, &ObjectName,
&Object, &Object,
&RemainingPath, &RemainingPath,
ObjectType); ObjectType,
&Context);
if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer); if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -252,6 +256,7 @@ ObInit(VOID)
UNICODE_STRING Name; UNICODE_STRING Name;
SECURITY_DESCRIPTOR SecurityDescriptor; SECURITY_DESCRIPTOR SecurityDescriptor;
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
OBP_LOOKUP_CONTEXT Context;
/* Initialize the security descriptor cache */ /* Initialize the security descriptor cache */
ObpInitSdCache(); ObpInitSdCache();
@ -279,11 +284,10 @@ ObInit(VOID)
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS; ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS;
ObjectTypeInitializer.UseDefaultObject = FALSE; ObjectTypeInitializer.UseDefaultObject = FALSE;
ObjectTypeInitializer.OpenProcedure = ObpCreateDirectory;
ObjectTypeInitializer.ParseProcedure = (OB_PARSE_METHOD)ObpParseDirectory; ObjectTypeInitializer.ParseProcedure = (OB_PARSE_METHOD)ObpParseDirectory;
ObjectTypeInitializer.MaintainTypeList = FALSE; ObjectTypeInitializer.MaintainTypeList = FALSE;
ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping; ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping;
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DIRECTORY_OBJECT); ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_DIRECTORY);
ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObDirectoryType); ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObDirectoryType);
/* Create security descriptor */ /* Create security descriptor */
@ -312,7 +316,7 @@ ObInit(VOID)
&ObjectAttributes, &ObjectAttributes,
KernelMode, KernelMode,
NULL, NULL,
sizeof(DIRECTORY_OBJECT), sizeof(OBJECT_DIRECTORY),
0, 0,
0, 0,
(PVOID*)&NameSpaceRoot); (PVOID*)&NameSpaceRoot);
@ -335,7 +339,7 @@ ObInit(VOID)
&ObjectAttributes, &ObjectAttributes,
KernelMode, KernelMode,
NULL, NULL,
sizeof(DIRECTORY_OBJECT), sizeof(OBJECT_DIRECTORY),
0, 0,
0, 0,
(PVOID*)&ObpTypeDirectoryObject); (PVOID*)&ObpTypeDirectoryObject);
@ -348,8 +352,24 @@ ObInit(VOID)
/* Insert the two objects we already created but couldn't add */ /* Insert the two objects we already created but couldn't add */
/* NOTE: Uses TypeList & Creator Info in OB 2.0 */ /* NOTE: Uses TypeList & Creator Info in OB 2.0 */
ObpAddEntryDirectory(ObpTypeDirectoryObject, (PROS_OBJECT_HEADER)BODY_TO_HEADER(ObTypeObjectType), NULL); Context.Directory = ObpTypeDirectoryObject;
ObpAddEntryDirectory(ObpTypeDirectoryObject, (PROS_OBJECT_HEADER)BODY_TO_HEADER(ObDirectoryType), NULL); Context.DirectoryLocked = TRUE;
if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject,
&HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ObTypeObjectType))->Name,
OBJ_CASE_INSENSITIVE,
FALSE,
&Context))
{
ObpInsertEntryDirectory(ObpTypeDirectoryObject, &Context, (POBJECT_HEADER)BODY_TO_HEADER(ObTypeObjectType));
}
if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject,
&HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ObDirectoryType))->Name,
OBJ_CASE_INSENSITIVE,
FALSE,
&Context))
{
ObpInsertEntryDirectory(ObpTypeDirectoryObject, &Context, (POBJECT_HEADER)BODY_TO_HEADER(ObDirectoryType));
}
/* Create 'symbolic link' object type */ /* Create 'symbolic link' object type */
ObInitSymbolicLinkImplementation(); ObInitSymbolicLinkImplementation();
@ -471,7 +491,15 @@ ObpCreateTypeObject(POBJECT_TYPE_INITIALIZER ObjectTypeInitializer,
/* Insert it into the Object Directory */ /* Insert it into the Object Directory */
if (ObpTypeDirectoryObject) if (ObpTypeDirectoryObject)
{ {
ObpAddEntryDirectory(ObpTypeDirectoryObject, Header, TypeName->Buffer); OBP_LOOKUP_CONTEXT Context;
Context.Directory = ObpTypeDirectoryObject;
Context.DirectoryLocked = TRUE;
ObpLookupEntryDirectory(ObpTypeDirectoryObject,
TypeName,
OBJ_CASE_INSENSITIVE,
FALSE,
&Context);
ObpInsertEntryDirectory(ObpTypeDirectoryObject, &Context, (POBJECT_HEADER)Header);
ObReferenceObject(ObpTypeDirectoryObject); ObReferenceObject(ObpTypeDirectoryObject);
} }

View file

@ -36,6 +36,7 @@ ObpSetPermanentObject(IN PVOID ObjectBody,
IN BOOLEAN Permanent) IN BOOLEAN Permanent)
{ {
PROS_OBJECT_HEADER ObjectHeader; PROS_OBJECT_HEADER ObjectHeader;
OBP_LOOKUP_CONTEXT Context;
ObjectHeader = BODY_TO_HEADER(ObjectBody); ObjectHeader = BODY_TO_HEADER(ObjectBody);
ASSERT (ObjectHeader->PointerCount > 0); ASSERT (ObjectHeader->PointerCount > 0);
@ -49,8 +50,17 @@ ObpSetPermanentObject(IN PVOID ObjectBody,
if (ObjectHeader->HandleCount == 0 && if (ObjectHeader->HandleCount == 0 &&
HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory) HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory)
{ {
/* Remove the object from the namespace */ /* Make sure it's still inserted */
ObpRemoveEntryDirectory((PROS_OBJECT_HEADER)ObjectHeader); Context.Directory = HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory;
Context.DirectoryLocked = TRUE;
if (ObpLookupEntryDirectory(HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory,
&HEADER_TO_OBJECT_NAME(ObjectHeader)->Name,
0,
FALSE,
&Context))
{
ObpDeleteEntryDirectory(&Context);
}
} }
} }
} }

View file

@ -293,7 +293,8 @@ ObFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
PUNICODE_STRING ObjectName, PUNICODE_STRING ObjectName,
PVOID* ReturnedObject, PVOID* ReturnedObject,
PUNICODE_STRING RemainingPath, PUNICODE_STRING RemainingPath,
POBJECT_TYPE ObjectType) POBJECT_TYPE ObjectType,
POBP_LOOKUP_CONTEXT Context)
{ {
PVOID NextObject; PVOID NextObject;
PVOID CurrentObject; PVOID CurrentObject;
@ -388,7 +389,8 @@ ObFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
&NextObject, &NextObject,
&PathString, &PathString,
&current, &current,
Attributes); Attributes,
Context);
if (Status == STATUS_REPARSE) if (Status == STATUS_REPARSE)
{ {
/* reparse the object path */ /* reparse the object path */
@ -442,7 +444,7 @@ ObQueryNameString(IN PVOID Object,
{ {
POBJECT_HEADER_NAME_INFO LocalInfo; POBJECT_HEADER_NAME_INFO LocalInfo;
PROS_OBJECT_HEADER ObjectHeader; PROS_OBJECT_HEADER ObjectHeader;
PDIRECTORY_OBJECT ParentDirectory; POBJECT_DIRECTORY ParentDirectory;
ULONG NameSize; ULONG NameSize;
PWCH ObjectName; PWCH ObjectName;
NTSTATUS Status; NTSTATUS Status;

View file

@ -74,7 +74,8 @@ IntWinStaObjectParse(PVOID Object,
PVOID *NextObject, PVOID *NextObject,
PUNICODE_STRING FullPath, PUNICODE_STRING FullPath,
PWSTR *Path, PWSTR *Path,
ULONG Attributes); ULONG Attributes,
PVOID Context);
NTSTATUS FASTCALL NTSTATUS FASTCALL
IntValidateWindowStationHandle( IntValidateWindowStationHandle(

View file

@ -382,7 +382,7 @@ DriverEntry (
* Register Object Manager Callbacks * Register Object Manager Callbacks
*/ */
CalloutData.WinStaOpen = IntWinStaObjectOpen; CalloutData.WinStaOpen = IntWinStaObjectOpen;
CalloutData.WinStaParse = IntWinStaObjectParse; CalloutData.WinStaParse = (OB_ROS_PARSE_METHOD)IntWinStaObjectParse;
CalloutData.WinStaDelete = IntWinStaObjectDelete; CalloutData.WinStaDelete = IntWinStaObjectDelete;
CalloutData.WinStaFind = IntWinStaObjectFind; CalloutData.WinStaFind = IntWinStaObjectFind;
CalloutData.DesktopCreate = IntDesktopObjectCreate; CalloutData.DesktopCreate = IntDesktopObjectCreate;

View file

@ -190,7 +190,8 @@ IntWinStaObjectParse(PVOID Object,
PVOID *NextObject, PVOID *NextObject,
PUNICODE_STRING FullPath, PUNICODE_STRING FullPath,
PWSTR *Path, PWSTR *Path,
ULONG Attributes) ULONG Attributes,
PVOID Context)
{ {
PVOID FoundObject; PVOID FoundObject;
NTSTATUS Status; NTSTATUS Status;