- 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];
} 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
//
typedef struct _OBJECT_HEADER_NAME_INFO
{
struct _DIRECTORY_OBJECT *Directory;
POBJECT_DIRECTORY Directory;
UNICODE_STRING Name;
ULONG QueryReferences;
ULONG Reserved2;
@ -384,48 +416,16 @@ typedef struct _OBJECT_HEADER
QUAD Body;
} 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
//
typedef struct _DEVICE_MAP
{
POBJECT_DIRECTORY DosDevicesDirectory;
POBJECT_DIRECTORY GlobalDosDevicesDirectory;
ULONG ReferenceCount;
ULONG DriveMap;
UCHAR DriveType[32];
POBJECT_DIRECTORY DosDevicesDirectory;
POBJECT_DIRECTORY GlobalDosDevicesDirectory;
ULONG ReferenceCount;
ULONG DriveMap;
UCHAR DriveType[32];
} DEVICE_MAP, *PDEVICE_MAP;
//

View file

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

View file

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

View file

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

View file

@ -11,21 +11,8 @@
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
{
LIST_ENTRY Entry;
LONG PointerCount;
union
{
@ -46,6 +33,16 @@ typedef struct _ROS_OBJECT_HEADER
QUAD Body;
} 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) \
CONTAINING_RECORD((objbdy), ROS_OBJECT_HEADER, Body)
@ -69,7 +66,7 @@ typedef struct _ROS_OBJECT_HEADER
#define ObMarkHandleAsKernelHandle(Handle) \
(HANDLE)((ULONG_PTR)(Handle) | KERNEL_HANDLE_FLAG)
extern PDIRECTORY_OBJECT NameSpaceRoot;
extern POBJECT_DIRECTORY NameSpaceRoot;
extern POBJECT_TYPE ObSymbolicLinkType;
extern PHANDLE_TABLE ObpKernelHandleTable;
@ -94,30 +91,27 @@ typedef NTSTATUS
PVOID *NextObject,
PUNICODE_STRING FullPath,
PWSTR *Path,
ULONG Attributes
ULONG Attributes,
POBP_LOOKUP_CONTEXT Context
);
VOID
BOOLEAN
NTAPI
ObpAddEntryDirectory(
PDIRECTORY_OBJECT Parent,
PROS_OBJECT_HEADER Header,
PWSTR Name
);
ObpDeleteEntryDirectory(POBP_LOOKUP_CONTEXT Context);
NTSTATUS
BOOLEAN
NTAPI
ObpCreateDirectory(
OB_OPEN_REASON Reason,
PEPROCESS Process,
PVOID ObjectBody,
ACCESS_MASK GrantedAccess,
ULONG HandleCount
);
ObpInsertEntryDirectory(IN POBJECT_DIRECTORY Parent,
IN POBP_LOOKUP_CONTEXT Context,
IN POBJECT_HEADER ObjectHeader);
VOID
PVOID
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
NTAPI
@ -139,7 +133,8 @@ ObpParseDirectory(
PVOID * NextObject,
PUNICODE_STRING FullPath,
PWSTR * Path,
ULONG Attributes
ULONG Attributes,
POBP_LOOKUP_CONTEXT Context
);
VOID
@ -157,7 +152,8 @@ ObFindObject(
PUNICODE_STRING ObjectName,
PVOID* ReturnedObject,
PUNICODE_STRING RemainingPath,
POBJECT_TYPE ObjectType
POBJECT_TYPE ObjectType,
POBP_LOOKUP_CONTEXT Context
);
NTSTATUS

View file

@ -8,10 +8,12 @@
/* INCLUDES ***************************************************************/
#define NTDDI_VERSION NTDDI_WS03
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
#define OBP_PROFILE
#ifdef OBP_PROFILE
LARGE_INTEGER ObpProfileTime;
@ -48,119 +50,228 @@ BOOLEAN ObpProfileComplete;
/* PRIVATE FUNCTIONS ******************************************************/
VOID
BOOLEAN
NTAPI
ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
PROS_OBJECT_HEADER Header,
PWSTR Name)
ObpInsertEntryDirectory(IN POBJECT_DIRECTORY Parent,
IN POBP_LOOKUP_CONTEXT Context,
IN POBJECT_HEADER ObjectHeader)
{
KIRQL oldlvl;
POBJECT_DIRECTORY_ENTRY *AllocatedEntry;
POBJECT_DIRECTORY_ENTRY NewEntry;
POBJECT_HEADER_NAME_INFO HeaderNameInfo;
ObpStartProfile();
ASSERT(HEADER_TO_OBJECT_NAME(Header));
HEADER_TO_OBJECT_NAME(Header)->Directory = Parent;
/* Make sure we have a name */
ASSERT(ObjectHeader->NameInfoOffset != 0);
KeAcquireSpinLock(&Parent->Lock, &oldlvl);
InsertTailList(&Parent->head, &Header->Entry);
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)
/* Validate the context */
if ((Context->Object) || !(Context->DirectoryLocked) || !Parent)
{
RemoveEntryList(&(Header->Entry));
Header->Entry.Flink = Header->Entry.Blink = NULL;
DbgPrint("OB: ObpInsertEntryDirectory - invalid context %p %ld\n",
Context, Context->DirectoryLocked);
DbgBreakPoint();
return FALSE;
}
KeReleaseSpinLock(&(HEADER_TO_OBJECT_NAME(Header)->Directory->Lock),oldlvl);
ObpEndProfile();
}
NTSTATUS
NTAPI
ObpCreateDirectory(OB_OPEN_REASON Reason,
PEPROCESS Process,
PVOID ObjectBody,
ACCESS_MASK GrantedAccess,
ULONG HandleCount)
{
PDIRECTORY_OBJECT Directory = ObjectBody;
/* Allocate a new Directory Entry */
NewEntry = ExAllocatePoolWithTag(PagedPool,
sizeof(OBJECT_DIRECTORY_ENTRY),
TAG('O', 'b', 'D', 'i'));
if (!NewEntry) return FALSE;
ObpStartProfile();
if (Reason == ObCreateHandle)
{
InitializeListHead(&Directory->head);
KeInitializeSpinLock(&Directory->Lock);
}
ObpEndProfile();
/* Save the hash */
NewEntry->HashValue = Context->HashValue;
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
NTAPI
ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject,
PWSTR Name,
ULONG Attributes)
ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
IN PUNICODE_STRING Name,
IN ULONG Attributes,
IN UCHAR SearchShadow,
IN POBP_LOOKUP_CONTEXT Context)
{
PLIST_ENTRY current = DirectoryObject->head.Flink;
PROS_OBJECT_HEADER current_obj;
BOOLEAN CaseInsensitive = FALSE;
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();
DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject, Name);
ObpCompleteProfile();
/* Always disable this until we have LUID Device Maps */
SearchShadow = FALSE;
if (Name[0]==0)
/* Fail the following cases */
TotalChars = Name->Length / sizeof(WCHAR);
if (!(Directory) || !(Name) || !(Name->Buffer) || !(TotalChars))
{
ObpEndProfile();
return(DirectoryObject);
goto Quickie;
}
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();
return(DirectoryObject);
/* Go to the next Character */
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();
return(HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(DirectoryObject))->Directory);
/* Lock it */
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);
DPRINT(" Scanning: %S for: %S\n",HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name);
if (Attributes & OBJ_CASE_INSENSITIVE)
/* Do the hashes match? */
DPRINT("CurrentEntry: %p. CurrentHash: %lx\n", CurrentEntry, CurrentEntry->HashValue);
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);
ObpEndProfile();
return(&current_obj->Body);
DPRINT("Found Name Match\n");
break;
}
}
else
{
if ( wcscmp(HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name)==0)
{
DPRINT("Found it %x\n",&current_obj->Body);
ObpEndProfile();
return(&current_obj->Body);
}
}
current = current->Flink;
/* Move to the next entry */
AllocatedEntry = &CurrentEntry->ChainLink;
}
DPRINT(" Not Found: %s() = NULL\n",__FUNCTION__);
ObpEndProfile();
return(NULL);
/* Check if we still have an entry */
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
@ -169,22 +280,19 @@ ObpParseDirectory(PVOID Object,
PVOID * NextObject,
PUNICODE_STRING FullPath,
PWSTR * Path,
ULONG Attributes)
ULONG Attributes,
POBP_LOOKUP_CONTEXT Context)
{
PWSTR Start;
PWSTR End;
PVOID FoundObject;
KIRQL oldlvl;
ObpStartProfile();
DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
Object,Path,*Path);
//KIRQL oldlvl;
UNICODE_STRING StartUs;
*NextObject = NULL;
if ((*Path) == NULL)
{
ObpEndProfile();
return STATUS_UNSUCCESSFUL;
}
@ -198,16 +306,18 @@ ObpParseDirectory(PVOID Object,
*End = 0;
}
KeAcquireSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), &oldlvl);
FoundObject = ObpFindEntryDirectory(Object, Start, Attributes);
//KeAcquireSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), &oldlvl);
RtlInitUnicodeString(&StartUs, Start);
Context->DirectoryLocked = TRUE;
Context->Directory = Object;
FoundObject = ObpLookupEntryDirectory(Object, &StartUs, Attributes, FALSE, Context);
if (FoundObject == NULL)
{
KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
//KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
if (End != NULL)
{
*End = L'\\';
}
ObpEndProfile();
return STATUS_UNSUCCESSFUL;
}
@ -215,7 +325,7 @@ ObpParseDirectory(PVOID Object,
STANDARD_RIGHTS_REQUIRED,
NULL,
UserMode);
KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
//KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
if (End != NULL)
{
*End = L'\\';
@ -228,7 +338,6 @@ ObpParseDirectory(PVOID Object,
*NextObject = FoundObject;
ObpEndProfile();
return STATUS_SUCCESS;
}
@ -360,7 +469,7 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
IN OUT PULONG Context,
OUT PULONG ReturnLength OPTIONAL)
{
PDIRECTORY_OBJECT Directory;
POBJECT_DIRECTORY Directory;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
ULONG SkipEntries = 0;
NTSTATUS Status = STATUS_SUCCESS;
@ -441,7 +550,7 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
PDIRECTORY_OBJECT Directory;
POBJECT_DIRECTORY Directory;
HANDLE hDirectory;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
@ -475,7 +584,7 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(DIRECTORY_OBJECT),
sizeof(OBJECT_DIRECTORY),
0,
0,
(PVOID*)&Directory);
@ -488,12 +597,6 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
0,
NULL,
&hDirectory);
if (!NT_SUCCESS(Status))
{
ObMakeTemporaryObject(Directory);
}
ObDereferenceObject(Directory);
if(NT_SUCCESS(Status))
{
_SEH_TRY
@ -506,6 +609,8 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
}
_SEH_END;
}
ObDereferenceObject(Directory);
}
return Status;

View file

@ -54,6 +54,7 @@ ObpDecrementHandleCount(PVOID ObjectBody)
{
PROS_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
LONG NewHandleCount = InterlockedDecrement(&ObjectHeader->HandleCount);
OBP_LOOKUP_CONTEXT Context;
DPRINT("Header: %x\n", ObjectHeader);
DPRINT("NewHandleCount: %x\n", NewHandleCount);
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.
Only do this if it's actually been inserted into the namespace and
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 */
@ -1150,6 +1162,7 @@ ObInsertObject(IN PVOID Object,
BOOLEAN ObjectAttached = FALSE;
PSECURITY_DESCRIPTOR NewSecurityDescriptor = NULL;
SECURITY_SUBJECT_CONTEXT SubjectContext;
OBP_LOOKUP_CONTEXT Context;
PAGED_CODE();
@ -1167,7 +1180,8 @@ ObInsertObject(IN PVOID Object,
&ObjectNameInfo->Name,
&FoundObject,
&RemainingPath,
NULL);
NULL,
&Context);
DPRINT("FoundObject: %x, Path: %wZ\n", FoundObject, &RemainingPath);
if (!NT_SUCCESS(Status))
{
@ -1202,10 +1216,7 @@ ObInsertObject(IN PVOID Object,
PVOID NewName;
PWSTR BufferPos = RemainingPath.Buffer;
ULONG Delta = 0;
ObpAddEntryDirectory(FoundObject, (PROS_OBJECT_HEADER)Header, NULL);
ObjectAttached = TRUE;
ObjectNameInfo = HEADER_TO_OBJECT_NAME(Header);
if (BufferPos[0] == L'\\')
@ -1219,7 +1230,8 @@ ObInsertObject(IN PVOID Object,
ObjectNameInfo->Name.Buffer = NewName;
ObjectNameInfo->Name.Length = RemainingPath.Length - 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) ||
@ -1262,7 +1274,7 @@ ObInsertObject(IN PVOID Object,
DPRINT("Create Failed\n");
if (ObjectAttached == TRUE)
{
ObpRemoveEntryDirectory((PROS_OBJECT_HEADER)Header);
ObpDeleteEntryDirectory(&Context);
}
if (FoundObject)
{

View file

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

View file

@ -36,6 +36,7 @@ ObpSetPermanentObject(IN PVOID ObjectBody,
IN BOOLEAN Permanent)
{
PROS_OBJECT_HEADER ObjectHeader;
OBP_LOOKUP_CONTEXT Context;
ObjectHeader = BODY_TO_HEADER(ObjectBody);
ASSERT (ObjectHeader->PointerCount > 0);
@ -49,8 +50,17 @@ ObpSetPermanentObject(IN PVOID ObjectBody,
if (ObjectHeader->HandleCount == 0 &&
HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory)
{
/* Remove the object from the namespace */
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);
}
}
}
}

View file

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

View file

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

View file

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

View file

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