mirror of
https://github.com/reactos/reactos.git
synced 2025-01-22 11:33:39 +08:00
svn propset svn:eol-style native foo.py
svn path=/trunk/; revision=22025
This commit is contained in:
parent
901bb3dc40
commit
945ca8d68e
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,174 +1,174 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/ob/init.c
|
||||
* PURPOSE: Handles Object Manager Initialization and Shutdown
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
* Eric Kohl
|
||||
* Thomas Weidenmueller (w3seek@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#if defined (ALLOC_PRAGMA)
|
||||
#pragma alloc_text(INIT, ObInit)
|
||||
#endif
|
||||
|
||||
GENERIC_MAPPING ObpTypeMapping =
|
||||
{
|
||||
STANDARD_RIGHTS_READ,
|
||||
STANDARD_RIGHTS_WRITE,
|
||||
STANDARD_RIGHTS_EXECUTE,
|
||||
0x000F0001
|
||||
};
|
||||
|
||||
GENERIC_MAPPING ObpDirectoryMapping =
|
||||
{
|
||||
STANDARD_RIGHTS_READ | DIRECTORY_QUERY |
|
||||
DIRECTORY_TRAVERSE,
|
||||
STANDARD_RIGHTS_WRITE | DIRECTORY_CREATE_SUBDIRECTORY |
|
||||
DIRECTORY_CREATE_OBJECT,
|
||||
STANDARD_RIGHTS_EXECUTE | DIRECTORY_QUERY |
|
||||
DIRECTORY_TRAVERSE,
|
||||
DIRECTORY_ALL_ACCESS
|
||||
};
|
||||
|
||||
PDEVICE_MAP ObSystemDeviceMap = NULL;
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
ObInit(VOID)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING Name;
|
||||
SECURITY_DESCRIPTOR SecurityDescriptor;
|
||||
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
|
||||
OBP_LOOKUP_CONTEXT Context;
|
||||
|
||||
/* Initialize the security descriptor cache */
|
||||
ObpInitSdCache();
|
||||
|
||||
/* Initialize the Default Event */
|
||||
KeInitializeEvent(&ObpDefaultObject, NotificationEvent, TRUE );
|
||||
|
||||
/* Create the Type Type */
|
||||
DPRINT("Creating Type Type\n");
|
||||
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
|
||||
RtlInitUnicodeString(&Name, L"Type");
|
||||
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
|
||||
ObjectTypeInitializer.ValidAccessMask = OBJECT_TYPE_ALL_ACCESS;
|
||||
ObjectTypeInitializer.UseDefaultObject = TRUE;
|
||||
ObjectTypeInitializer.MaintainTypeList = TRUE;
|
||||
ObjectTypeInitializer.PoolType = NonPagedPool;
|
||||
ObjectTypeInitializer.GenericMapping = ObpTypeMapping;
|
||||
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_TYPE);
|
||||
ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObTypeObjectType);
|
||||
|
||||
/* Create the Directory Type */
|
||||
DPRINT("Creating Directory Type\n");
|
||||
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
|
||||
RtlInitUnicodeString(&Name, L"Directory");
|
||||
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
|
||||
ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS;
|
||||
ObjectTypeInitializer.UseDefaultObject = FALSE;
|
||||
ObjectTypeInitializer.ParseProcedure = (OB_PARSE_METHOD)ObpParseDirectory;
|
||||
ObjectTypeInitializer.MaintainTypeList = FALSE;
|
||||
ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping;
|
||||
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_DIRECTORY);
|
||||
ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObDirectoryType);
|
||||
|
||||
/* Create security descriptor */
|
||||
RtlCreateSecurityDescriptor(&SecurityDescriptor,
|
||||
SECURITY_DESCRIPTOR_REVISION1);
|
||||
RtlSetOwnerSecurityDescriptor(&SecurityDescriptor,
|
||||
SeAliasAdminsSid,
|
||||
FALSE);
|
||||
RtlSetGroupSecurityDescriptor(&SecurityDescriptor,
|
||||
SeLocalSystemSid,
|
||||
FALSE);
|
||||
RtlSetDaclSecurityDescriptor(&SecurityDescriptor,
|
||||
TRUE,
|
||||
SePublicDefaultDacl,
|
||||
FALSE);
|
||||
|
||||
/* Create root directory */
|
||||
DPRINT("Creating Root Directory\n");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
NULL,
|
||||
OBJ_PERMANENT,
|
||||
NULL,
|
||||
&SecurityDescriptor);
|
||||
ObCreateObject(KernelMode,
|
||||
ObDirectoryType,
|
||||
&ObjectAttributes,
|
||||
KernelMode,
|
||||
NULL,
|
||||
sizeof(OBJECT_DIRECTORY),
|
||||
0,
|
||||
0,
|
||||
(PVOID*)&NameSpaceRoot);
|
||||
ObInsertObject((PVOID)NameSpaceRoot,
|
||||
NULL,
|
||||
DIRECTORY_ALL_ACCESS,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
/* Create '\ObjectTypes' directory */
|
||||
RtlInitUnicodeString(&Name, L"\\ObjectTypes");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&Name,
|
||||
OBJ_PERMANENT,
|
||||
NULL,
|
||||
&SecurityDescriptor);
|
||||
ObCreateObject(KernelMode,
|
||||
ObDirectoryType,
|
||||
&ObjectAttributes,
|
||||
KernelMode,
|
||||
NULL,
|
||||
sizeof(OBJECT_DIRECTORY),
|
||||
0,
|
||||
0,
|
||||
(PVOID*)&ObpTypeDirectoryObject);
|
||||
ObInsertObject((PVOID)ObpTypeDirectoryObject,
|
||||
NULL,
|
||||
DIRECTORY_ALL_ACCESS,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
/* Insert the two objects we already created but couldn't add */
|
||||
/* NOTE: Uses TypeList & Creator Info in OB 2.0 */
|
||||
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, BODY_TO_HEADER(ObTypeObjectType));
|
||||
}
|
||||
if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject,
|
||||
&HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ObDirectoryType))->Name,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
FALSE,
|
||||
&Context))
|
||||
{
|
||||
ObpInsertEntryDirectory(ObpTypeDirectoryObject, &Context, BODY_TO_HEADER(ObDirectoryType));
|
||||
}
|
||||
|
||||
/* Create 'symbolic link' object type */
|
||||
ObInitSymbolicLinkImplementation();
|
||||
|
||||
/* FIXME: Hack Hack! */
|
||||
ObSystemDeviceMap = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ObSystemDeviceMap), TAG('O', 'b', 'D', 'm'));
|
||||
RtlZeroMemory(ObSystemDeviceMap, sizeof(*ObSystemDeviceMap));
|
||||
}
|
||||
/* EOF */
|
||||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/ob/init.c
|
||||
* PURPOSE: Handles Object Manager Initialization and Shutdown
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
* Eric Kohl
|
||||
* Thomas Weidenmueller (w3seek@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#if defined (ALLOC_PRAGMA)
|
||||
#pragma alloc_text(INIT, ObInit)
|
||||
#endif
|
||||
|
||||
GENERIC_MAPPING ObpTypeMapping =
|
||||
{
|
||||
STANDARD_RIGHTS_READ,
|
||||
STANDARD_RIGHTS_WRITE,
|
||||
STANDARD_RIGHTS_EXECUTE,
|
||||
0x000F0001
|
||||
};
|
||||
|
||||
GENERIC_MAPPING ObpDirectoryMapping =
|
||||
{
|
||||
STANDARD_RIGHTS_READ | DIRECTORY_QUERY |
|
||||
DIRECTORY_TRAVERSE,
|
||||
STANDARD_RIGHTS_WRITE | DIRECTORY_CREATE_SUBDIRECTORY |
|
||||
DIRECTORY_CREATE_OBJECT,
|
||||
STANDARD_RIGHTS_EXECUTE | DIRECTORY_QUERY |
|
||||
DIRECTORY_TRAVERSE,
|
||||
DIRECTORY_ALL_ACCESS
|
||||
};
|
||||
|
||||
PDEVICE_MAP ObSystemDeviceMap = NULL;
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
ObInit(VOID)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING Name;
|
||||
SECURITY_DESCRIPTOR SecurityDescriptor;
|
||||
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
|
||||
OBP_LOOKUP_CONTEXT Context;
|
||||
|
||||
/* Initialize the security descriptor cache */
|
||||
ObpInitSdCache();
|
||||
|
||||
/* Initialize the Default Event */
|
||||
KeInitializeEvent(&ObpDefaultObject, NotificationEvent, TRUE );
|
||||
|
||||
/* Create the Type Type */
|
||||
DPRINT("Creating Type Type\n");
|
||||
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
|
||||
RtlInitUnicodeString(&Name, L"Type");
|
||||
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
|
||||
ObjectTypeInitializer.ValidAccessMask = OBJECT_TYPE_ALL_ACCESS;
|
||||
ObjectTypeInitializer.UseDefaultObject = TRUE;
|
||||
ObjectTypeInitializer.MaintainTypeList = TRUE;
|
||||
ObjectTypeInitializer.PoolType = NonPagedPool;
|
||||
ObjectTypeInitializer.GenericMapping = ObpTypeMapping;
|
||||
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_TYPE);
|
||||
ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObTypeObjectType);
|
||||
|
||||
/* Create the Directory Type */
|
||||
DPRINT("Creating Directory Type\n");
|
||||
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
|
||||
RtlInitUnicodeString(&Name, L"Directory");
|
||||
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
|
||||
ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS;
|
||||
ObjectTypeInitializer.UseDefaultObject = FALSE;
|
||||
ObjectTypeInitializer.ParseProcedure = (OB_PARSE_METHOD)ObpParseDirectory;
|
||||
ObjectTypeInitializer.MaintainTypeList = FALSE;
|
||||
ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping;
|
||||
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_DIRECTORY);
|
||||
ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObDirectoryType);
|
||||
|
||||
/* Create security descriptor */
|
||||
RtlCreateSecurityDescriptor(&SecurityDescriptor,
|
||||
SECURITY_DESCRIPTOR_REVISION1);
|
||||
RtlSetOwnerSecurityDescriptor(&SecurityDescriptor,
|
||||
SeAliasAdminsSid,
|
||||
FALSE);
|
||||
RtlSetGroupSecurityDescriptor(&SecurityDescriptor,
|
||||
SeLocalSystemSid,
|
||||
FALSE);
|
||||
RtlSetDaclSecurityDescriptor(&SecurityDescriptor,
|
||||
TRUE,
|
||||
SePublicDefaultDacl,
|
||||
FALSE);
|
||||
|
||||
/* Create root directory */
|
||||
DPRINT("Creating Root Directory\n");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
NULL,
|
||||
OBJ_PERMANENT,
|
||||
NULL,
|
||||
&SecurityDescriptor);
|
||||
ObCreateObject(KernelMode,
|
||||
ObDirectoryType,
|
||||
&ObjectAttributes,
|
||||
KernelMode,
|
||||
NULL,
|
||||
sizeof(OBJECT_DIRECTORY),
|
||||
0,
|
||||
0,
|
||||
(PVOID*)&NameSpaceRoot);
|
||||
ObInsertObject((PVOID)NameSpaceRoot,
|
||||
NULL,
|
||||
DIRECTORY_ALL_ACCESS,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
/* Create '\ObjectTypes' directory */
|
||||
RtlInitUnicodeString(&Name, L"\\ObjectTypes");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&Name,
|
||||
OBJ_PERMANENT,
|
||||
NULL,
|
||||
&SecurityDescriptor);
|
||||
ObCreateObject(KernelMode,
|
||||
ObDirectoryType,
|
||||
&ObjectAttributes,
|
||||
KernelMode,
|
||||
NULL,
|
||||
sizeof(OBJECT_DIRECTORY),
|
||||
0,
|
||||
0,
|
||||
(PVOID*)&ObpTypeDirectoryObject);
|
||||
ObInsertObject((PVOID)ObpTypeDirectoryObject,
|
||||
NULL,
|
||||
DIRECTORY_ALL_ACCESS,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
/* Insert the two objects we already created but couldn't add */
|
||||
/* NOTE: Uses TypeList & Creator Info in OB 2.0 */
|
||||
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, BODY_TO_HEADER(ObTypeObjectType));
|
||||
}
|
||||
if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject,
|
||||
&HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ObDirectoryType))->Name,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
FALSE,
|
||||
&Context))
|
||||
{
|
||||
ObpInsertEntryDirectory(ObpTypeDirectoryObject, &Context, BODY_TO_HEADER(ObDirectoryType));
|
||||
}
|
||||
|
||||
/* Create 'symbolic link' object type */
|
||||
ObInitSymbolicLinkImplementation();
|
||||
|
||||
/* FIXME: Hack Hack! */
|
||||
ObSystemDeviceMap = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ObSystemDeviceMap), TAG('O', 'b', 'D', 'm'));
|
||||
RtlZeroMemory(ObSystemDeviceMap, sizeof(*ObSystemDeviceMap));
|
||||
}
|
||||
/* EOF */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,365 +1,365 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/ob/namespce.c
|
||||
* PURPOSE: Manages all functions related to the Object Manager name-
|
||||
* space, such as finding objects or querying their names.
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
* Eric Kohl
|
||||
* Thomas Weidenmueller (w3seek@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
POBJECT_DIRECTORY NameSpaceRoot = NULL;
|
||||
POBJECT_DIRECTORY ObpTypeDirectoryObject = NULL;
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ObFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
|
||||
PUNICODE_STRING ObjectName,
|
||||
PVOID* ReturnedObject,
|
||||
PUNICODE_STRING RemainingPath,
|
||||
POBJECT_TYPE ObjectType,
|
||||
POBP_LOOKUP_CONTEXT Context)
|
||||
{
|
||||
PVOID NextObject;
|
||||
PVOID CurrentObject;
|
||||
PVOID RootObject;
|
||||
POBJECT_HEADER CurrentHeader;
|
||||
NTSTATUS Status;
|
||||
PWSTR current;
|
||||
UNICODE_STRING PathString;
|
||||
ULONG Attributes;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT("ObFindObject(ObjectCreateInfo %x, ReturnedObject %x, "
|
||||
"RemainingPath %x)\n",ObjectCreateInfo,ReturnedObject,RemainingPath);
|
||||
|
||||
RtlInitUnicodeString (RemainingPath, NULL);
|
||||
|
||||
if (ObjectCreateInfo->RootDirectory == NULL)
|
||||
{
|
||||
ObReferenceObjectByPointer(NameSpaceRoot,
|
||||
DIRECTORY_TRAVERSE,
|
||||
NULL,
|
||||
ObjectCreateInfo->ProbeMode);
|
||||
CurrentObject = NameSpaceRoot;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ObReferenceObjectByHandle(ObjectCreateInfo->RootDirectory,
|
||||
0,
|
||||
NULL,
|
||||
ObjectCreateInfo->ProbeMode,
|
||||
&CurrentObject,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
if (ObjectName->Length == 0 ||
|
||||
ObjectName->Buffer[0] == UNICODE_NULL)
|
||||
{
|
||||
*ReturnedObject = CurrentObject;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (ObjectCreateInfo->RootDirectory == 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;
|
||||
Attributes = ObjectCreateInfo->Attributes;
|
||||
if (ObjectType == ObSymbolicLinkType)
|
||||
Attributes |= OBJ_OPENLINK;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
DPRINT("current %S\n",current);
|
||||
CurrentHeader = BODY_TO_HEADER(CurrentObject);
|
||||
|
||||
DPRINT("Current ObjectType %wZ\n",
|
||||
&CurrentHeader->Type->Name);
|
||||
|
||||
if (CurrentHeader->Type->TypeInfo.ParseProcedure == NULL)
|
||||
{
|
||||
DPRINT("Current object can't parse\n");
|
||||
break;
|
||||
}
|
||||
Status = ((OB_ROS_PARSE_METHOD)CurrentHeader->Type->TypeInfo.ParseProcedure)(CurrentObject,
|
||||
&NextObject,
|
||||
&PathString,
|
||||
¤t,
|
||||
Attributes,
|
||||
Context);
|
||||
if (Status == STATUS_REPARSE)
|
||||
{
|
||||
/* reparse the object path */
|
||||
NextObject = NameSpaceRoot;
|
||||
current = PathString.Buffer;
|
||||
|
||||
ObReferenceObjectByPointer(NextObject,
|
||||
DIRECTORY_TRAVERSE,
|
||||
NULL,
|
||||
ObjectCreateInfo->ProbeMode);
|
||||
}
|
||||
|
||||
if (NextObject == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
ObDereferenceObject(CurrentObject);
|
||||
CurrentObject = NextObject;
|
||||
}
|
||||
|
||||
if (current)
|
||||
{
|
||||
RtlpCreateUnicodeString (RemainingPath, current, NonPagedPool);
|
||||
}
|
||||
|
||||
RtlFreeUnicodeString (&PathString);
|
||||
*ReturnedObject = CurrentObject;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS *********************************************************/
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
ObQueryNameString(IN PVOID Object,
|
||||
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ReturnLength)
|
||||
{
|
||||
POBJECT_HEADER_NAME_INFO LocalInfo;
|
||||
POBJECT_HEADER ObjectHeader;
|
||||
POBJECT_DIRECTORY ParentDirectory;
|
||||
ULONG NameSize;
|
||||
PWCH ObjectName;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("ObQueryNameString: %x, %x\n", Object, ObjectNameInfo);
|
||||
|
||||
/* Get the Kernel Meta-Structures */
|
||||
ObjectHeader = BODY_TO_HEADER(Object);
|
||||
LocalInfo = HEADER_TO_OBJECT_NAME(ObjectHeader);
|
||||
|
||||
/* Check if a Query Name Procedure is available */
|
||||
if (ObjectHeader->Type->TypeInfo.QueryNameProcedure)
|
||||
{
|
||||
/* Call the procedure */
|
||||
DPRINT("Calling Object's Procedure\n");
|
||||
Status = ObjectHeader->Type->TypeInfo.QueryNameProcedure(Object,
|
||||
TRUE, //fixme
|
||||
ObjectNameInfo,
|
||||
Length,
|
||||
ReturnLength);
|
||||
|
||||
/* Return the status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Check if the object doesn't even have a name */
|
||||
if (!LocalInfo || !LocalInfo->Name.Buffer)
|
||||
{
|
||||
/* We're returning the name structure */
|
||||
DPRINT("Nameless Object\n");
|
||||
*ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
|
||||
|
||||
/* Check if we were given enough space */
|
||||
if (*ReturnLength > Length)
|
||||
{
|
||||
DPRINT1("Not enough buffer space\n");
|
||||
return STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
/* Return an empty buffer */
|
||||
ObjectNameInfo->Name.Length = 0;
|
||||
ObjectNameInfo->Name.MaximumLength = 0;
|
||||
ObjectNameInfo->Name.Buffer = NULL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the size needed for the name. We won't do
|
||||
* this during the Name Creation loop because we want
|
||||
* to let the caller know that the buffer isn't big
|
||||
* enough right at the beginning, not work our way through
|
||||
* and find out at the end
|
||||
*/
|
||||
if (Object == NameSpaceRoot)
|
||||
{
|
||||
/* Size of the '\' string */
|
||||
DPRINT("Object is Root\n");
|
||||
NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the Object Directory and add name of Object */
|
||||
ParentDirectory = LocalInfo->Directory;
|
||||
NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR) + LocalInfo->Name.Length;
|
||||
|
||||
/* Loop inside the directory to get the top-most one (meaning root) */
|
||||
while ((ParentDirectory != NameSpaceRoot) && (ParentDirectory))
|
||||
{
|
||||
/* Get the Name Information */
|
||||
LocalInfo = HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ParentDirectory));
|
||||
|
||||
/* Add the size of the Directory Name */
|
||||
if (LocalInfo && LocalInfo->Directory)
|
||||
{
|
||||
/* Size of the '\' string + Directory Name */
|
||||
NameSize += sizeof(OBJ_NAME_PATH_SEPARATOR) + LocalInfo->Name.Length;
|
||||
|
||||
/* Move to next parent Directory */
|
||||
ParentDirectory = LocalInfo->Directory;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Directory with no name. We append "...\" */
|
||||
DPRINT("Nameless Directory\n");
|
||||
NameSize += sizeof(L"...") + sizeof(OBJ_NAME_PATH_SEPARATOR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, add the name of the structure and the null char */
|
||||
*ReturnLength = NameSize + sizeof(OBJECT_NAME_INFORMATION) + sizeof(UNICODE_NULL);
|
||||
DPRINT("Final Length: %x\n", *ReturnLength);
|
||||
|
||||
/* Check if we were given enough space */
|
||||
if (*ReturnLength > Length)
|
||||
{
|
||||
DPRINT1("Not enough buffer space\n");
|
||||
return STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we will actually create the name. We work backwards because
|
||||
* it's easier to start off from the Name we have and walk up the
|
||||
* parent directories. We use the same logic as Name Length calculation.
|
||||
*/
|
||||
LocalInfo = HEADER_TO_OBJECT_NAME(ObjectHeader);
|
||||
ObjectName = (PWCH)((ULONG_PTR)ObjectNameInfo + *ReturnLength);
|
||||
*--ObjectName = UNICODE_NULL;
|
||||
|
||||
if (Object == NameSpaceRoot)
|
||||
{
|
||||
/* This is already the Root Directory, return "\\" */
|
||||
DPRINT("Returning Root Dir\n");
|
||||
*--ObjectName = OBJ_NAME_PATH_SEPARATOR;
|
||||
ObjectNameInfo->Name.Length = (USHORT)NameSize;
|
||||
ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize + sizeof(UNICODE_NULL));
|
||||
ObjectNameInfo->Name.Buffer = ObjectName;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Start by adding the Object's Name */
|
||||
ObjectName = (PWCH)((ULONG_PTR)ObjectName - LocalInfo->Name.Length);
|
||||
RtlMoveMemory(ObjectName, LocalInfo->Name.Buffer, LocalInfo->Name.Length);
|
||||
|
||||
/* Now parse the Parent directories until we reach the top */
|
||||
ParentDirectory = LocalInfo->Directory;
|
||||
while ((ParentDirectory != NameSpaceRoot) && (ParentDirectory))
|
||||
{
|
||||
/* Get the name information */
|
||||
LocalInfo = HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ParentDirectory));
|
||||
|
||||
/* Add the "\" */
|
||||
*(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
|
||||
|
||||
/* Add the Parent Directory's Name */
|
||||
if (LocalInfo && LocalInfo->Name.Buffer)
|
||||
{
|
||||
/* Add the name */
|
||||
ObjectName = (PWCH)((ULONG_PTR)ObjectName - LocalInfo->Name.Length);
|
||||
RtlMoveMemory(ObjectName, LocalInfo->Name.Buffer, LocalInfo->Name.Length);
|
||||
|
||||
/* Move to next parent */
|
||||
ParentDirectory = LocalInfo->Directory;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Directory without a name, we add "..." */
|
||||
DPRINT("Nameless Directory\n");
|
||||
ObjectName -= sizeof(L"...");
|
||||
ObjectName = L"...";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add Root Directory Name */
|
||||
*(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
|
||||
DPRINT("Current Buffer: %S\n", ObjectName);
|
||||
ObjectNameInfo->Name.Length = (USHORT)NameSize;
|
||||
ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize + sizeof(UNICODE_NULL));
|
||||
ObjectNameInfo->Name.Buffer = ObjectName;
|
||||
DPRINT("Complete: %wZ\n", ObjectNameInfo);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ObQueryDeviceMapInformation(IN PEPROCESS Process,
|
||||
IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
|
||||
{
|
||||
//KIRQL OldIrql ;
|
||||
|
||||
/*
|
||||
* FIXME: This is an ugly hack for now, to always return the System Device Map
|
||||
* instead of returning the Process Device Map. Not important yet since we don't use it
|
||||
*/
|
||||
|
||||
/* FIXME: Acquire the DeviceMap Spinlock */
|
||||
// KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
|
||||
|
||||
/* Make a copy */
|
||||
DeviceMapInfo->Query.DriveMap = ObSystemDeviceMap->DriveMap;
|
||||
RtlMoveMemory(DeviceMapInfo->Query.DriveType,
|
||||
ObSystemDeviceMap->DriveType,
|
||||
sizeof(ObSystemDeviceMap->DriveType));
|
||||
|
||||
/* FIXME: Release the DeviceMap Spinlock */
|
||||
// KeReleasepinLock(DeviceMap->Lock, OldIrql);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/ob/namespce.c
|
||||
* PURPOSE: Manages all functions related to the Object Manager name-
|
||||
* space, such as finding objects or querying their names.
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
* Eric Kohl
|
||||
* Thomas Weidenmueller (w3seek@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
POBJECT_DIRECTORY NameSpaceRoot = NULL;
|
||||
POBJECT_DIRECTORY ObpTypeDirectoryObject = NULL;
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ObFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
|
||||
PUNICODE_STRING ObjectName,
|
||||
PVOID* ReturnedObject,
|
||||
PUNICODE_STRING RemainingPath,
|
||||
POBJECT_TYPE ObjectType,
|
||||
POBP_LOOKUP_CONTEXT Context)
|
||||
{
|
||||
PVOID NextObject;
|
||||
PVOID CurrentObject;
|
||||
PVOID RootObject;
|
||||
POBJECT_HEADER CurrentHeader;
|
||||
NTSTATUS Status;
|
||||
PWSTR current;
|
||||
UNICODE_STRING PathString;
|
||||
ULONG Attributes;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT("ObFindObject(ObjectCreateInfo %x, ReturnedObject %x, "
|
||||
"RemainingPath %x)\n",ObjectCreateInfo,ReturnedObject,RemainingPath);
|
||||
|
||||
RtlInitUnicodeString (RemainingPath, NULL);
|
||||
|
||||
if (ObjectCreateInfo->RootDirectory == NULL)
|
||||
{
|
||||
ObReferenceObjectByPointer(NameSpaceRoot,
|
||||
DIRECTORY_TRAVERSE,
|
||||
NULL,
|
||||
ObjectCreateInfo->ProbeMode);
|
||||
CurrentObject = NameSpaceRoot;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ObReferenceObjectByHandle(ObjectCreateInfo->RootDirectory,
|
||||
0,
|
||||
NULL,
|
||||
ObjectCreateInfo->ProbeMode,
|
||||
&CurrentObject,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
if (ObjectName->Length == 0 ||
|
||||
ObjectName->Buffer[0] == UNICODE_NULL)
|
||||
{
|
||||
*ReturnedObject = CurrentObject;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (ObjectCreateInfo->RootDirectory == 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;
|
||||
Attributes = ObjectCreateInfo->Attributes;
|
||||
if (ObjectType == ObSymbolicLinkType)
|
||||
Attributes |= OBJ_OPENLINK;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
DPRINT("current %S\n",current);
|
||||
CurrentHeader = BODY_TO_HEADER(CurrentObject);
|
||||
|
||||
DPRINT("Current ObjectType %wZ\n",
|
||||
&CurrentHeader->Type->Name);
|
||||
|
||||
if (CurrentHeader->Type->TypeInfo.ParseProcedure == NULL)
|
||||
{
|
||||
DPRINT("Current object can't parse\n");
|
||||
break;
|
||||
}
|
||||
Status = ((OB_ROS_PARSE_METHOD)CurrentHeader->Type->TypeInfo.ParseProcedure)(CurrentObject,
|
||||
&NextObject,
|
||||
&PathString,
|
||||
¤t,
|
||||
Attributes,
|
||||
Context);
|
||||
if (Status == STATUS_REPARSE)
|
||||
{
|
||||
/* reparse the object path */
|
||||
NextObject = NameSpaceRoot;
|
||||
current = PathString.Buffer;
|
||||
|
||||
ObReferenceObjectByPointer(NextObject,
|
||||
DIRECTORY_TRAVERSE,
|
||||
NULL,
|
||||
ObjectCreateInfo->ProbeMode);
|
||||
}
|
||||
|
||||
if (NextObject == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
ObDereferenceObject(CurrentObject);
|
||||
CurrentObject = NextObject;
|
||||
}
|
||||
|
||||
if (current)
|
||||
{
|
||||
RtlpCreateUnicodeString (RemainingPath, current, NonPagedPool);
|
||||
}
|
||||
|
||||
RtlFreeUnicodeString (&PathString);
|
||||
*ReturnedObject = CurrentObject;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS *********************************************************/
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
ObQueryNameString(IN PVOID Object,
|
||||
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ReturnLength)
|
||||
{
|
||||
POBJECT_HEADER_NAME_INFO LocalInfo;
|
||||
POBJECT_HEADER ObjectHeader;
|
||||
POBJECT_DIRECTORY ParentDirectory;
|
||||
ULONG NameSize;
|
||||
PWCH ObjectName;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("ObQueryNameString: %x, %x\n", Object, ObjectNameInfo);
|
||||
|
||||
/* Get the Kernel Meta-Structures */
|
||||
ObjectHeader = BODY_TO_HEADER(Object);
|
||||
LocalInfo = HEADER_TO_OBJECT_NAME(ObjectHeader);
|
||||
|
||||
/* Check if a Query Name Procedure is available */
|
||||
if (ObjectHeader->Type->TypeInfo.QueryNameProcedure)
|
||||
{
|
||||
/* Call the procedure */
|
||||
DPRINT("Calling Object's Procedure\n");
|
||||
Status = ObjectHeader->Type->TypeInfo.QueryNameProcedure(Object,
|
||||
TRUE, //fixme
|
||||
ObjectNameInfo,
|
||||
Length,
|
||||
ReturnLength);
|
||||
|
||||
/* Return the status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Check if the object doesn't even have a name */
|
||||
if (!LocalInfo || !LocalInfo->Name.Buffer)
|
||||
{
|
||||
/* We're returning the name structure */
|
||||
DPRINT("Nameless Object\n");
|
||||
*ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
|
||||
|
||||
/* Check if we were given enough space */
|
||||
if (*ReturnLength > Length)
|
||||
{
|
||||
DPRINT1("Not enough buffer space\n");
|
||||
return STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
/* Return an empty buffer */
|
||||
ObjectNameInfo->Name.Length = 0;
|
||||
ObjectNameInfo->Name.MaximumLength = 0;
|
||||
ObjectNameInfo->Name.Buffer = NULL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the size needed for the name. We won't do
|
||||
* this during the Name Creation loop because we want
|
||||
* to let the caller know that the buffer isn't big
|
||||
* enough right at the beginning, not work our way through
|
||||
* and find out at the end
|
||||
*/
|
||||
if (Object == NameSpaceRoot)
|
||||
{
|
||||
/* Size of the '\' string */
|
||||
DPRINT("Object is Root\n");
|
||||
NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the Object Directory and add name of Object */
|
||||
ParentDirectory = LocalInfo->Directory;
|
||||
NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR) + LocalInfo->Name.Length;
|
||||
|
||||
/* Loop inside the directory to get the top-most one (meaning root) */
|
||||
while ((ParentDirectory != NameSpaceRoot) && (ParentDirectory))
|
||||
{
|
||||
/* Get the Name Information */
|
||||
LocalInfo = HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ParentDirectory));
|
||||
|
||||
/* Add the size of the Directory Name */
|
||||
if (LocalInfo && LocalInfo->Directory)
|
||||
{
|
||||
/* Size of the '\' string + Directory Name */
|
||||
NameSize += sizeof(OBJ_NAME_PATH_SEPARATOR) + LocalInfo->Name.Length;
|
||||
|
||||
/* Move to next parent Directory */
|
||||
ParentDirectory = LocalInfo->Directory;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Directory with no name. We append "...\" */
|
||||
DPRINT("Nameless Directory\n");
|
||||
NameSize += sizeof(L"...") + sizeof(OBJ_NAME_PATH_SEPARATOR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, add the name of the structure and the null char */
|
||||
*ReturnLength = NameSize + sizeof(OBJECT_NAME_INFORMATION) + sizeof(UNICODE_NULL);
|
||||
DPRINT("Final Length: %x\n", *ReturnLength);
|
||||
|
||||
/* Check if we were given enough space */
|
||||
if (*ReturnLength > Length)
|
||||
{
|
||||
DPRINT1("Not enough buffer space\n");
|
||||
return STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we will actually create the name. We work backwards because
|
||||
* it's easier to start off from the Name we have and walk up the
|
||||
* parent directories. We use the same logic as Name Length calculation.
|
||||
*/
|
||||
LocalInfo = HEADER_TO_OBJECT_NAME(ObjectHeader);
|
||||
ObjectName = (PWCH)((ULONG_PTR)ObjectNameInfo + *ReturnLength);
|
||||
*--ObjectName = UNICODE_NULL;
|
||||
|
||||
if (Object == NameSpaceRoot)
|
||||
{
|
||||
/* This is already the Root Directory, return "\\" */
|
||||
DPRINT("Returning Root Dir\n");
|
||||
*--ObjectName = OBJ_NAME_PATH_SEPARATOR;
|
||||
ObjectNameInfo->Name.Length = (USHORT)NameSize;
|
||||
ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize + sizeof(UNICODE_NULL));
|
||||
ObjectNameInfo->Name.Buffer = ObjectName;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Start by adding the Object's Name */
|
||||
ObjectName = (PWCH)((ULONG_PTR)ObjectName - LocalInfo->Name.Length);
|
||||
RtlMoveMemory(ObjectName, LocalInfo->Name.Buffer, LocalInfo->Name.Length);
|
||||
|
||||
/* Now parse the Parent directories until we reach the top */
|
||||
ParentDirectory = LocalInfo->Directory;
|
||||
while ((ParentDirectory != NameSpaceRoot) && (ParentDirectory))
|
||||
{
|
||||
/* Get the name information */
|
||||
LocalInfo = HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ParentDirectory));
|
||||
|
||||
/* Add the "\" */
|
||||
*(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
|
||||
|
||||
/* Add the Parent Directory's Name */
|
||||
if (LocalInfo && LocalInfo->Name.Buffer)
|
||||
{
|
||||
/* Add the name */
|
||||
ObjectName = (PWCH)((ULONG_PTR)ObjectName - LocalInfo->Name.Length);
|
||||
RtlMoveMemory(ObjectName, LocalInfo->Name.Buffer, LocalInfo->Name.Length);
|
||||
|
||||
/* Move to next parent */
|
||||
ParentDirectory = LocalInfo->Directory;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Directory without a name, we add "..." */
|
||||
DPRINT("Nameless Directory\n");
|
||||
ObjectName -= sizeof(L"...");
|
||||
ObjectName = L"...";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add Root Directory Name */
|
||||
*(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
|
||||
DPRINT("Current Buffer: %S\n", ObjectName);
|
||||
ObjectNameInfo->Name.Length = (USHORT)NameSize;
|
||||
ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize + sizeof(UNICODE_NULL));
|
||||
ObjectNameInfo->Name.Buffer = ObjectName;
|
||||
DPRINT("Complete: %wZ\n", ObjectNameInfo);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ObQueryDeviceMapInformation(IN PEPROCESS Process,
|
||||
IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
|
||||
{
|
||||
//KIRQL OldIrql ;
|
||||
|
||||
/*
|
||||
* FIXME: This is an ugly hack for now, to always return the System Device Map
|
||||
* instead of returning the Process Device Map. Not important yet since we don't use it
|
||||
*/
|
||||
|
||||
/* FIXME: Acquire the DeviceMap Spinlock */
|
||||
// KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
|
||||
|
||||
/* Make a copy */
|
||||
DeviceMapInfo->Query.DriveMap = ObSystemDeviceMap->DriveMap;
|
||||
RtlMoveMemory(DeviceMapInfo->Query.DriveType,
|
||||
ObSystemDeviceMap->DriveType,
|
||||
sizeof(ObSystemDeviceMap->DriveType));
|
||||
|
||||
/* FIXME: Release the DeviceMap Spinlock */
|
||||
// KeReleasepinLock(DeviceMap->Lock, OldIrql);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
@ -1,455 +1,455 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/ob/refderef.c
|
||||
* PURPOSE: Manages the referencing and de-referencing of all Objects,
|
||||
* as well as the Object Fast Reference implementation.
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
* Eric Kohl
|
||||
* Thomas Weidenmueller (w3seek@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
ObInitializeFastReference(IN PEX_FAST_REF FastRef,
|
||||
PVOID Object)
|
||||
{
|
||||
/* FIXME: Fast Referencing is Unimplemented */
|
||||
FastRef->Object = Object;
|
||||
}
|
||||
|
||||
PVOID
|
||||
FASTCALL
|
||||
ObFastReferenceObject(IN PEX_FAST_REF FastRef)
|
||||
{
|
||||
/* FIXME: Fast Referencing is Unimplemented */
|
||||
|
||||
/* Do a normal Reference */
|
||||
ObReferenceObject(FastRef->Object);
|
||||
|
||||
/* Return the Object */
|
||||
return FastRef->Object;
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
ObFastDereferenceObject(IN PEX_FAST_REF FastRef,
|
||||
PVOID Object)
|
||||
{
|
||||
/* FIXME: Fast Referencing is Unimplemented */
|
||||
|
||||
/* Do a normal Dereference */
|
||||
ObDereferenceObject(FastRef->Object);
|
||||
}
|
||||
|
||||
PVOID
|
||||
FASTCALL
|
||||
ObFastReplaceObject(IN PEX_FAST_REF FastRef,
|
||||
PVOID Object)
|
||||
{
|
||||
PVOID OldObject = FastRef->Object;
|
||||
|
||||
/* FIXME: Fast Referencing is Unimplemented */
|
||||
FastRef->Object = Object;
|
||||
|
||||
/* Do a normal Dereference */
|
||||
ObDereferenceObject(OldObject);
|
||||
|
||||
/* Return old Object*/
|
||||
return OldObject;
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS *********************************************************/
|
||||
|
||||
ULONG STDCALL
|
||||
ObGetObjectPointerCount(PVOID Object)
|
||||
{
|
||||
POBJECT_HEADER Header;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(Object);
|
||||
Header = BODY_TO_HEADER(Object);
|
||||
|
||||
return Header->PointerCount;
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
ObfReferenceObject(IN PVOID Object)
|
||||
{
|
||||
POBJECT_HEADER Header;
|
||||
|
||||
ASSERT(Object);
|
||||
|
||||
Header = BODY_TO_HEADER(Object);
|
||||
|
||||
/* No one should be referencing an object once we are deleting it. */
|
||||
if (InterlockedIncrement(&Header->PointerCount) == 1 && !(Header->Flags & OB_FLAG_PERMANENT))
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
ObfDereferenceObject(IN PVOID Object)
|
||||
{
|
||||
POBJECT_HEADER Header;
|
||||
LONG NewPointerCount;
|
||||
BOOL Permanent;
|
||||
|
||||
ASSERT(Object);
|
||||
|
||||
/* Extract the object header. */
|
||||
Header = BODY_TO_HEADER(Object);
|
||||
Permanent = Header->Flags & OB_FLAG_PERMANENT;
|
||||
|
||||
/*
|
||||
Drop our reference and get the new count so we can tell if this was the
|
||||
last reference.
|
||||
*/
|
||||
NewPointerCount = InterlockedDecrement(&Header->PointerCount);
|
||||
DPRINT("ObfDereferenceObject(0x%x)==%d\n", Object, NewPointerCount);
|
||||
ASSERT(NewPointerCount >= 0);
|
||||
|
||||
/* Check whether the object can now be deleted. */
|
||||
if (NewPointerCount == 0 &&
|
||||
!Permanent)
|
||||
{
|
||||
ObpDeleteObjectDpcLevel(Header, NewPointerCount);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
ObReferenceObjectByPointer(IN PVOID Object,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_TYPE ObjectType,
|
||||
IN KPROCESSOR_MODE AccessMode)
|
||||
{
|
||||
POBJECT_HEADER Header;
|
||||
|
||||
/* NOTE: should be possible to reference an object above APC_LEVEL! */
|
||||
|
||||
DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
|
||||
Object,ObjectType);
|
||||
|
||||
Header = BODY_TO_HEADER(Object);
|
||||
|
||||
if (ObjectType != NULL && Header->Type != ObjectType)
|
||||
{
|
||||
DPRINT("Failed %p (type was %x %wZ) should be %x %wZ\n",
|
||||
Header,
|
||||
Header->Type,
|
||||
&HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Header->Type))->Name,
|
||||
ObjectType,
|
||||
&HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ObjectType))->Name);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
if (Header->Type == PsProcessType)
|
||||
{
|
||||
DPRINT("Ref p 0x%x PointerCount %d type %x ",
|
||||
Object, Header->PointerCount, PsProcessType);
|
||||
DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
|
||||
}
|
||||
if (Header->Type == PsThreadType)
|
||||
{
|
||||
DPRINT("Deref t 0x%x with PointerCount %d type %x ",
|
||||
Object, Header->PointerCount, PsThreadType);
|
||||
DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
|
||||
}
|
||||
|
||||
if (Header->PointerCount == 0 && !(Header->Flags & OB_FLAG_PERMANENT))
|
||||
{
|
||||
if (Header->Type == PsProcessType)
|
||||
{
|
||||
return STATUS_PROCESS_IS_TERMINATING;
|
||||
}
|
||||
if (Header->Type == PsThreadType)
|
||||
{
|
||||
return STATUS_THREAD_IS_TERMINATING;
|
||||
}
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
if (1 == InterlockedIncrement(&Header->PointerCount) && !(Header->Flags & OB_FLAG_PERMANENT))
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
|
||||
ULONG Attributes,
|
||||
PACCESS_STATE PassedAccessState,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_TYPE ObjectType,
|
||||
KPROCESSOR_MODE AccessMode,
|
||||
PVOID ParseContext,
|
||||
PVOID* ObjectPtr)
|
||||
{
|
||||
PVOID Object = NULL;
|
||||
UNICODE_STRING RemainingPath;
|
||||
UNICODE_STRING ObjectName;
|
||||
OBJECT_CREATE_INFORMATION ObjectCreateInfo;
|
||||
NTSTATUS Status;
|
||||
OBP_LOOKUP_CONTEXT Context;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Capture the name */
|
||||
DPRINT("Capturing Name\n");
|
||||
Status = ObpCaptureObjectName(&ObjectName, ObjectPath, AccessMode);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ObpCaptureObjectName() failed (Status %lx)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a fake ObjectCreateInfo structure. Note that my upcoming
|
||||
* ObFindObject refactoring will remove the need for this hack.
|
||||
*/
|
||||
ObjectCreateInfo.RootDirectory = NULL;
|
||||
ObjectCreateInfo.Attributes = Attributes;
|
||||
|
||||
Status = ObFindObject(&ObjectCreateInfo,
|
||||
&ObjectName,
|
||||
&Object,
|
||||
&RemainingPath,
|
||||
ObjectType,
|
||||
&Context);
|
||||
|
||||
if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath.Buffer, Object);
|
||||
|
||||
if (RemainingPath.Buffer != NULL || Object == NULL)
|
||||
{
|
||||
DPRINT("Object %p\n", Object);
|
||||
*ObjectPtr = NULL;
|
||||
RtlFreeUnicodeString (&RemainingPath);
|
||||
return(STATUS_OBJECT_NAME_NOT_FOUND);
|
||||
}
|
||||
*ObjectPtr = Object;
|
||||
RtlFreeUnicodeString (&RemainingPath);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
ObReferenceObjectByHandle(HANDLE Handle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_TYPE ObjectType,
|
||||
KPROCESSOR_MODE AccessMode,
|
||||
PVOID* Object,
|
||||
POBJECT_HANDLE_INFORMATION HandleInformation)
|
||||
{
|
||||
PHANDLE_TABLE_ENTRY HandleEntry;
|
||||
POBJECT_HEADER ObjectHeader;
|
||||
PVOID ObjectBody;
|
||||
ACCESS_MASK GrantedAccess;
|
||||
ULONG Attributes;
|
||||
PEPROCESS CurrentProcess, Process;
|
||||
BOOLEAN AttachedToProcess = FALSE;
|
||||
KAPC_STATE ApcState;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT("ObReferenceObjectByHandle(Handle %p, DesiredAccess %x, "
|
||||
"ObjectType %p, AccessMode %d, Object %p)\n",Handle,DesiredAccess,
|
||||
ObjectType,AccessMode,Object);
|
||||
|
||||
if (Handle == NULL)
|
||||
{
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
CurrentProcess = PsGetCurrentProcess();
|
||||
|
||||
/*
|
||||
* Handle special handle names
|
||||
*/
|
||||
if (Handle == NtCurrentProcess() &&
|
||||
(ObjectType == PsProcessType || ObjectType == NULL))
|
||||
{
|
||||
ObReferenceObject(CurrentProcess);
|
||||
|
||||
if (HandleInformation != NULL)
|
||||
{
|
||||
HandleInformation->HandleAttributes = 0;
|
||||
HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS;
|
||||
}
|
||||
|
||||
*Object = CurrentProcess;
|
||||
DPRINT("Referencing current process %p\n", CurrentProcess);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (Handle == NtCurrentProcess())
|
||||
{
|
||||
CHECKPOINT;
|
||||
return(STATUS_OBJECT_TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
if (Handle == NtCurrentThread() &&
|
||||
(ObjectType == PsThreadType || ObjectType == NULL))
|
||||
{
|
||||
PETHREAD CurrentThread = PsGetCurrentThread();
|
||||
|
||||
ObReferenceObject(CurrentThread);
|
||||
|
||||
if (HandleInformation != NULL)
|
||||
{
|
||||
HandleInformation->HandleAttributes = 0;
|
||||
HandleInformation->GrantedAccess = THREAD_ALL_ACCESS;
|
||||
}
|
||||
|
||||
*Object = CurrentThread;
|
||||
CHECKPOINT;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (Handle == NtCurrentThread())
|
||||
{
|
||||
CHECKPOINT;
|
||||
return(STATUS_OBJECT_TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
/* desire as much access rights as possible */
|
||||
if (DesiredAccess & MAXIMUM_ALLOWED)
|
||||
{
|
||||
DesiredAccess &= ~MAXIMUM_ALLOWED;
|
||||
DesiredAccess |= GENERIC_ALL;
|
||||
}
|
||||
|
||||
if(ObIsKernelHandle(Handle, AccessMode))
|
||||
{
|
||||
Process = PsInitialSystemProcess;
|
||||
Handle = ObKernelHandleToHandle(Handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
Process = CurrentProcess;
|
||||
}
|
||||
|
||||
KeEnterCriticalRegion();
|
||||
|
||||
if (Process != CurrentProcess)
|
||||
{
|
||||
KeStackAttachProcess(&Process->Pcb,
|
||||
&ApcState);
|
||||
AttachedToProcess = TRUE;
|
||||
}
|
||||
|
||||
HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
|
||||
Handle);
|
||||
if (HandleEntry == NULL)
|
||||
{
|
||||
if (AttachedToProcess)
|
||||
{
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
}
|
||||
KeLeaveCriticalRegion();
|
||||
DPRINT("ExMapHandleToPointer() failed for handle 0x%p\n", Handle);
|
||||
return(STATUS_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
|
||||
ObjectBody = &ObjectHeader->Body;
|
||||
|
||||
DPRINT("locked1: ObjectHeader: 0x%p [HT:0x%p]\n", ObjectHeader, Process->ObjectTable);
|
||||
|
||||
if (ObjectType != NULL && ObjectType != ObjectHeader->Type)
|
||||
{
|
||||
DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%p)\n", &ObjectType->Name, ObjectHeader->Type ? &ObjectHeader->Type->Name : NULL, Handle);
|
||||
|
||||
ExUnlockHandleTableEntry(Process->ObjectTable,
|
||||
HandleEntry);
|
||||
|
||||
if (AttachedToProcess)
|
||||
{
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
}
|
||||
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
return(STATUS_OBJECT_TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
/* map the generic access masks if the caller asks for generic access */
|
||||
if (DesiredAccess & GENERIC_ACCESS)
|
||||
{
|
||||
RtlMapGenericMask(&DesiredAccess,
|
||||
&BODY_TO_HEADER(ObjectBody)->Type->TypeInfo.GenericMapping);
|
||||
}
|
||||
|
||||
GrantedAccess = HandleEntry->GrantedAccess;
|
||||
|
||||
/* Unless running as KernelMode, deny access if caller desires more access
|
||||
rights than the handle can grant */
|
||||
if(AccessMode != KernelMode && (~GrantedAccess & DesiredAccess))
|
||||
{
|
||||
ExUnlockHandleTableEntry(Process->ObjectTable,
|
||||
HandleEntry);
|
||||
|
||||
if (AttachedToProcess)
|
||||
{
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
}
|
||||
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
DPRINT1("GrantedAccess: 0x%x, ~GrantedAccess: 0x%x, DesiredAccess: 0x%x, denied: 0x%x\n", GrantedAccess, ~GrantedAccess, DesiredAccess, ~GrantedAccess & DesiredAccess);
|
||||
|
||||
return(STATUS_ACCESS_DENIED);
|
||||
}
|
||||
|
||||
ObReferenceObject(ObjectBody);
|
||||
|
||||
Attributes = HandleEntry->ObAttributes & (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
|
||||
EX_HANDLE_ENTRY_INHERITABLE |
|
||||
EX_HANDLE_ENTRY_AUDITONCLOSE);
|
||||
|
||||
ExUnlockHandleTableEntry(Process->ObjectTable,
|
||||
HandleEntry);
|
||||
|
||||
if (AttachedToProcess)
|
||||
{
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
}
|
||||
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
if (HandleInformation != NULL)
|
||||
{
|
||||
HandleInformation->HandleAttributes = Attributes;
|
||||
HandleInformation->GrantedAccess = GrantedAccess;
|
||||
}
|
||||
|
||||
*Object = ObjectBody;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
#ifdef ObDereferenceObject
|
||||
#undef ObDereferenceObject
|
||||
#endif
|
||||
|
||||
VOID STDCALL
|
||||
ObDereferenceObject(IN PVOID Object)
|
||||
{
|
||||
ObfDereferenceObject(Object);
|
||||
}
|
||||
/* EOF */
|
||||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/ob/refderef.c
|
||||
* PURPOSE: Manages the referencing and de-referencing of all Objects,
|
||||
* as well as the Object Fast Reference implementation.
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
* Eric Kohl
|
||||
* Thomas Weidenmueller (w3seek@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
ObInitializeFastReference(IN PEX_FAST_REF FastRef,
|
||||
PVOID Object)
|
||||
{
|
||||
/* FIXME: Fast Referencing is Unimplemented */
|
||||
FastRef->Object = Object;
|
||||
}
|
||||
|
||||
PVOID
|
||||
FASTCALL
|
||||
ObFastReferenceObject(IN PEX_FAST_REF FastRef)
|
||||
{
|
||||
/* FIXME: Fast Referencing is Unimplemented */
|
||||
|
||||
/* Do a normal Reference */
|
||||
ObReferenceObject(FastRef->Object);
|
||||
|
||||
/* Return the Object */
|
||||
return FastRef->Object;
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
ObFastDereferenceObject(IN PEX_FAST_REF FastRef,
|
||||
PVOID Object)
|
||||
{
|
||||
/* FIXME: Fast Referencing is Unimplemented */
|
||||
|
||||
/* Do a normal Dereference */
|
||||
ObDereferenceObject(FastRef->Object);
|
||||
}
|
||||
|
||||
PVOID
|
||||
FASTCALL
|
||||
ObFastReplaceObject(IN PEX_FAST_REF FastRef,
|
||||
PVOID Object)
|
||||
{
|
||||
PVOID OldObject = FastRef->Object;
|
||||
|
||||
/* FIXME: Fast Referencing is Unimplemented */
|
||||
FastRef->Object = Object;
|
||||
|
||||
/* Do a normal Dereference */
|
||||
ObDereferenceObject(OldObject);
|
||||
|
||||
/* Return old Object*/
|
||||
return OldObject;
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS *********************************************************/
|
||||
|
||||
ULONG STDCALL
|
||||
ObGetObjectPointerCount(PVOID Object)
|
||||
{
|
||||
POBJECT_HEADER Header;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(Object);
|
||||
Header = BODY_TO_HEADER(Object);
|
||||
|
||||
return Header->PointerCount;
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
ObfReferenceObject(IN PVOID Object)
|
||||
{
|
||||
POBJECT_HEADER Header;
|
||||
|
||||
ASSERT(Object);
|
||||
|
||||
Header = BODY_TO_HEADER(Object);
|
||||
|
||||
/* No one should be referencing an object once we are deleting it. */
|
||||
if (InterlockedIncrement(&Header->PointerCount) == 1 && !(Header->Flags & OB_FLAG_PERMANENT))
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
ObfDereferenceObject(IN PVOID Object)
|
||||
{
|
||||
POBJECT_HEADER Header;
|
||||
LONG NewPointerCount;
|
||||
BOOL Permanent;
|
||||
|
||||
ASSERT(Object);
|
||||
|
||||
/* Extract the object header. */
|
||||
Header = BODY_TO_HEADER(Object);
|
||||
Permanent = Header->Flags & OB_FLAG_PERMANENT;
|
||||
|
||||
/*
|
||||
Drop our reference and get the new count so we can tell if this was the
|
||||
last reference.
|
||||
*/
|
||||
NewPointerCount = InterlockedDecrement(&Header->PointerCount);
|
||||
DPRINT("ObfDereferenceObject(0x%x)==%d\n", Object, NewPointerCount);
|
||||
ASSERT(NewPointerCount >= 0);
|
||||
|
||||
/* Check whether the object can now be deleted. */
|
||||
if (NewPointerCount == 0 &&
|
||||
!Permanent)
|
||||
{
|
||||
ObpDeleteObjectDpcLevel(Header, NewPointerCount);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
ObReferenceObjectByPointer(IN PVOID Object,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_TYPE ObjectType,
|
||||
IN KPROCESSOR_MODE AccessMode)
|
||||
{
|
||||
POBJECT_HEADER Header;
|
||||
|
||||
/* NOTE: should be possible to reference an object above APC_LEVEL! */
|
||||
|
||||
DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
|
||||
Object,ObjectType);
|
||||
|
||||
Header = BODY_TO_HEADER(Object);
|
||||
|
||||
if (ObjectType != NULL && Header->Type != ObjectType)
|
||||
{
|
||||
DPRINT("Failed %p (type was %x %wZ) should be %x %wZ\n",
|
||||
Header,
|
||||
Header->Type,
|
||||
&HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Header->Type))->Name,
|
||||
ObjectType,
|
||||
&HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ObjectType))->Name);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
if (Header->Type == PsProcessType)
|
||||
{
|
||||
DPRINT("Ref p 0x%x PointerCount %d type %x ",
|
||||
Object, Header->PointerCount, PsProcessType);
|
||||
DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
|
||||
}
|
||||
if (Header->Type == PsThreadType)
|
||||
{
|
||||
DPRINT("Deref t 0x%x with PointerCount %d type %x ",
|
||||
Object, Header->PointerCount, PsThreadType);
|
||||
DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
|
||||
}
|
||||
|
||||
if (Header->PointerCount == 0 && !(Header->Flags & OB_FLAG_PERMANENT))
|
||||
{
|
||||
if (Header->Type == PsProcessType)
|
||||
{
|
||||
return STATUS_PROCESS_IS_TERMINATING;
|
||||
}
|
||||
if (Header->Type == PsThreadType)
|
||||
{
|
||||
return STATUS_THREAD_IS_TERMINATING;
|
||||
}
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
if (1 == InterlockedIncrement(&Header->PointerCount) && !(Header->Flags & OB_FLAG_PERMANENT))
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
|
||||
ULONG Attributes,
|
||||
PACCESS_STATE PassedAccessState,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_TYPE ObjectType,
|
||||
KPROCESSOR_MODE AccessMode,
|
||||
PVOID ParseContext,
|
||||
PVOID* ObjectPtr)
|
||||
{
|
||||
PVOID Object = NULL;
|
||||
UNICODE_STRING RemainingPath;
|
||||
UNICODE_STRING ObjectName;
|
||||
OBJECT_CREATE_INFORMATION ObjectCreateInfo;
|
||||
NTSTATUS Status;
|
||||
OBP_LOOKUP_CONTEXT Context;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Capture the name */
|
||||
DPRINT("Capturing Name\n");
|
||||
Status = ObpCaptureObjectName(&ObjectName, ObjectPath, AccessMode);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ObpCaptureObjectName() failed (Status %lx)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a fake ObjectCreateInfo structure. Note that my upcoming
|
||||
* ObFindObject refactoring will remove the need for this hack.
|
||||
*/
|
||||
ObjectCreateInfo.RootDirectory = NULL;
|
||||
ObjectCreateInfo.Attributes = Attributes;
|
||||
|
||||
Status = ObFindObject(&ObjectCreateInfo,
|
||||
&ObjectName,
|
||||
&Object,
|
||||
&RemainingPath,
|
||||
ObjectType,
|
||||
&Context);
|
||||
|
||||
if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath.Buffer, Object);
|
||||
|
||||
if (RemainingPath.Buffer != NULL || Object == NULL)
|
||||
{
|
||||
DPRINT("Object %p\n", Object);
|
||||
*ObjectPtr = NULL;
|
||||
RtlFreeUnicodeString (&RemainingPath);
|
||||
return(STATUS_OBJECT_NAME_NOT_FOUND);
|
||||
}
|
||||
*ObjectPtr = Object;
|
||||
RtlFreeUnicodeString (&RemainingPath);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
ObReferenceObjectByHandle(HANDLE Handle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_TYPE ObjectType,
|
||||
KPROCESSOR_MODE AccessMode,
|
||||
PVOID* Object,
|
||||
POBJECT_HANDLE_INFORMATION HandleInformation)
|
||||
{
|
||||
PHANDLE_TABLE_ENTRY HandleEntry;
|
||||
POBJECT_HEADER ObjectHeader;
|
||||
PVOID ObjectBody;
|
||||
ACCESS_MASK GrantedAccess;
|
||||
ULONG Attributes;
|
||||
PEPROCESS CurrentProcess, Process;
|
||||
BOOLEAN AttachedToProcess = FALSE;
|
||||
KAPC_STATE ApcState;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT("ObReferenceObjectByHandle(Handle %p, DesiredAccess %x, "
|
||||
"ObjectType %p, AccessMode %d, Object %p)\n",Handle,DesiredAccess,
|
||||
ObjectType,AccessMode,Object);
|
||||
|
||||
if (Handle == NULL)
|
||||
{
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
CurrentProcess = PsGetCurrentProcess();
|
||||
|
||||
/*
|
||||
* Handle special handle names
|
||||
*/
|
||||
if (Handle == NtCurrentProcess() &&
|
||||
(ObjectType == PsProcessType || ObjectType == NULL))
|
||||
{
|
||||
ObReferenceObject(CurrentProcess);
|
||||
|
||||
if (HandleInformation != NULL)
|
||||
{
|
||||
HandleInformation->HandleAttributes = 0;
|
||||
HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS;
|
||||
}
|
||||
|
||||
*Object = CurrentProcess;
|
||||
DPRINT("Referencing current process %p\n", CurrentProcess);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (Handle == NtCurrentProcess())
|
||||
{
|
||||
CHECKPOINT;
|
||||
return(STATUS_OBJECT_TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
if (Handle == NtCurrentThread() &&
|
||||
(ObjectType == PsThreadType || ObjectType == NULL))
|
||||
{
|
||||
PETHREAD CurrentThread = PsGetCurrentThread();
|
||||
|
||||
ObReferenceObject(CurrentThread);
|
||||
|
||||
if (HandleInformation != NULL)
|
||||
{
|
||||
HandleInformation->HandleAttributes = 0;
|
||||
HandleInformation->GrantedAccess = THREAD_ALL_ACCESS;
|
||||
}
|
||||
|
||||
*Object = CurrentThread;
|
||||
CHECKPOINT;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (Handle == NtCurrentThread())
|
||||
{
|
||||
CHECKPOINT;
|
||||
return(STATUS_OBJECT_TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
/* desire as much access rights as possible */
|
||||
if (DesiredAccess & MAXIMUM_ALLOWED)
|
||||
{
|
||||
DesiredAccess &= ~MAXIMUM_ALLOWED;
|
||||
DesiredAccess |= GENERIC_ALL;
|
||||
}
|
||||
|
||||
if(ObIsKernelHandle(Handle, AccessMode))
|
||||
{
|
||||
Process = PsInitialSystemProcess;
|
||||
Handle = ObKernelHandleToHandle(Handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
Process = CurrentProcess;
|
||||
}
|
||||
|
||||
KeEnterCriticalRegion();
|
||||
|
||||
if (Process != CurrentProcess)
|
||||
{
|
||||
KeStackAttachProcess(&Process->Pcb,
|
||||
&ApcState);
|
||||
AttachedToProcess = TRUE;
|
||||
}
|
||||
|
||||
HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
|
||||
Handle);
|
||||
if (HandleEntry == NULL)
|
||||
{
|
||||
if (AttachedToProcess)
|
||||
{
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
}
|
||||
KeLeaveCriticalRegion();
|
||||
DPRINT("ExMapHandleToPointer() failed for handle 0x%p\n", Handle);
|
||||
return(STATUS_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
|
||||
ObjectBody = &ObjectHeader->Body;
|
||||
|
||||
DPRINT("locked1: ObjectHeader: 0x%p [HT:0x%p]\n", ObjectHeader, Process->ObjectTable);
|
||||
|
||||
if (ObjectType != NULL && ObjectType != ObjectHeader->Type)
|
||||
{
|
||||
DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%p)\n", &ObjectType->Name, ObjectHeader->Type ? &ObjectHeader->Type->Name : NULL, Handle);
|
||||
|
||||
ExUnlockHandleTableEntry(Process->ObjectTable,
|
||||
HandleEntry);
|
||||
|
||||
if (AttachedToProcess)
|
||||
{
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
}
|
||||
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
return(STATUS_OBJECT_TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
/* map the generic access masks if the caller asks for generic access */
|
||||
if (DesiredAccess & GENERIC_ACCESS)
|
||||
{
|
||||
RtlMapGenericMask(&DesiredAccess,
|
||||
&BODY_TO_HEADER(ObjectBody)->Type->TypeInfo.GenericMapping);
|
||||
}
|
||||
|
||||
GrantedAccess = HandleEntry->GrantedAccess;
|
||||
|
||||
/* Unless running as KernelMode, deny access if caller desires more access
|
||||
rights than the handle can grant */
|
||||
if(AccessMode != KernelMode && (~GrantedAccess & DesiredAccess))
|
||||
{
|
||||
ExUnlockHandleTableEntry(Process->ObjectTable,
|
||||
HandleEntry);
|
||||
|
||||
if (AttachedToProcess)
|
||||
{
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
}
|
||||
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
DPRINT1("GrantedAccess: 0x%x, ~GrantedAccess: 0x%x, DesiredAccess: 0x%x, denied: 0x%x\n", GrantedAccess, ~GrantedAccess, DesiredAccess, ~GrantedAccess & DesiredAccess);
|
||||
|
||||
return(STATUS_ACCESS_DENIED);
|
||||
}
|
||||
|
||||
ObReferenceObject(ObjectBody);
|
||||
|
||||
Attributes = HandleEntry->ObAttributes & (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
|
||||
EX_HANDLE_ENTRY_INHERITABLE |
|
||||
EX_HANDLE_ENTRY_AUDITONCLOSE);
|
||||
|
||||
ExUnlockHandleTableEntry(Process->ObjectTable,
|
||||
HandleEntry);
|
||||
|
||||
if (AttachedToProcess)
|
||||
{
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
}
|
||||
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
if (HandleInformation != NULL)
|
||||
{
|
||||
HandleInformation->HandleAttributes = Attributes;
|
||||
HandleInformation->GrantedAccess = GrantedAccess;
|
||||
}
|
||||
|
||||
*Object = ObjectBody;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
#ifdef ObDereferenceObject
|
||||
#undef ObDereferenceObject
|
||||
#endif
|
||||
|
||||
VOID STDCALL
|
||||
ObDereferenceObject(IN PVOID Object)
|
||||
{
|
||||
ObfDereferenceObject(Object);
|
||||
}
|
||||
/* EOF */
|
||||
|
Loading…
Reference in New Issue
Block a user