mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
Preliminary fix for NtQueryObject().
svn path=/trunk/; revision=4808
This commit is contained in:
parent
05a9cdcf10
commit
813549499b
1 changed files with 225 additions and 136 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: ntobj.c,v 1.11 2002/09/08 10:23:39 chorns Exp $
|
/* $Id: ntobj.c,v 1.12 2003/06/01 15:09:34 ekohl Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -18,58 +18,66 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
|
||||||
|
|
||||||
/* FUNCTIONS ************************************************************/
|
/* FUNCTIONS ************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
/**********************************************************************
|
||||||
STDCALL
|
* NAME EXPORTED
|
||||||
NtSetInformationObject (
|
* NtSetInformationObject
|
||||||
IN HANDLE ObjectHandle,
|
*
|
||||||
IN CINT ObjectInformationClass,
|
* DESCRIPTION
|
||||||
IN PVOID ObjectInformation,
|
*
|
||||||
IN ULONG Length
|
* ARGUMENTS
|
||||||
)
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
*
|
||||||
|
* REVISIONS
|
||||||
|
*/
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtSetInformationObject (IN HANDLE ObjectHandle,
|
||||||
|
IN CINT ObjectInformationClass,
|
||||||
|
IN PVOID ObjectInformation,
|
||||||
|
IN ULONG Length)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
internalNameBuilder
|
internalNameBuilder(POBJECT_HEADER ObjectHeader,
|
||||||
(
|
PUNICODE_STRING String)
|
||||||
POBJECT_HEADER ObjectHeader,
|
|
||||||
PUNICODE_STRING string)
|
|
||||||
/* So, what's the purpose of this function?
|
/* So, what's the purpose of this function?
|
||||||
It will take any OBJECT_HEADER and traverse the Parent structure up to the root
|
It will take any OBJECT_HEADER and traverse the Parent structure up to the root
|
||||||
and form the name, i.e. this will only work on objects where the Parent/Name fields
|
and form the name, i.e. this will only work on objects where the Parent/Name fields
|
||||||
have any meaning (not files) */
|
have any meaning (not files) */
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS Status;
|
||||||
if (ObjectHeader->Parent)
|
|
||||||
{
|
if (ObjectHeader->Parent)
|
||||||
status = internalNameBuilder(BODY_TO_HEADER(ObjectHeader->Parent),string);
|
{
|
||||||
if (status != STATUS_SUCCESS)
|
Status = internalNameBuilder(BODY_TO_HEADER(ObjectHeader->Parent),
|
||||||
{
|
String);
|
||||||
return status;
|
if (Status != STATUS_SUCCESS)
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ObjectHeader->Name.Buffer)
|
|
||||||
{
|
{
|
||||||
status = RtlAppendUnicodeToString(string, L"\\");
|
return Status;
|
||||||
if (status != STATUS_SUCCESS) return status;
|
|
||||||
return RtlAppendUnicodeStringToString(string, &ObjectHeader->Name);
|
|
||||||
}
|
}
|
||||||
return STATUS_SUCCESS;
|
}
|
||||||
|
|
||||||
|
if (ObjectHeader->Name.Buffer)
|
||||||
|
{
|
||||||
|
Status = RtlAppendUnicodeToString(String,
|
||||||
|
L"\\");
|
||||||
|
if (Status != STATUS_SUCCESS)
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
return RtlAppendUnicodeStringToString(String,
|
||||||
|
&ObjectHeader->Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
STDCALL
|
|
||||||
NtQueryObject (
|
|
||||||
IN HANDLE ObjectHandle,
|
|
||||||
IN CINT ObjectInformationClass,
|
|
||||||
OUT PVOID ObjectInformation,
|
|
||||||
IN ULONG Length,
|
|
||||||
OUT PULONG ResultLength
|
|
||||||
)
|
|
||||||
/*Very, very, very new implementation. Test it!
|
/*Very, very, very new implementation. Test it!
|
||||||
|
|
||||||
Probably we should add meaning to QueryName in POBJECT_TYPE, no matter if we know
|
Probably we should add meaning to QueryName in POBJECT_TYPE, no matter if we know
|
||||||
|
@ -79,95 +87,181 @@ NtQueryObject (
|
||||||
|
|
||||||
If we don't do it this way, we should anyway add switches and separate functions to handle
|
If we don't do it this way, we should anyway add switches and separate functions to handle
|
||||||
the different object types*/
|
the different object types*/
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* NAME EXPORTED
|
||||||
|
* NtQueryObject
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
*
|
||||||
|
* REVISIONS
|
||||||
|
*/
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtQueryObject (IN HANDLE ObjectHandle,
|
||||||
|
IN CINT ObjectInformationClass,
|
||||||
|
OUT PVOID ObjectInformation,
|
||||||
|
IN ULONG Length,
|
||||||
|
OUT PULONG ReturnLength)
|
||||||
{
|
{
|
||||||
POBJECT_NAME_INFORMATION nameinfo;
|
POBJECT_NAME_INFORMATION NameInfo;
|
||||||
POBJECT_TYPE_INFORMATION typeinfo;
|
POBJECT_TYPE_INFORMATION typeinfo;
|
||||||
PFILE_NAME_INFORMATION filenameinfo;
|
PFILE_NAME_INFORMATION filenameinfo;
|
||||||
PVOID Object;
|
PVOID Object;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
POBJECT_HEADER ObjectHeader;
|
POBJECT_HEADER ObjectHeader;
|
||||||
PFILE_OBJECT fileob;
|
PFILE_OBJECT fileob;
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(ObjectHandle,
|
Status = ObReferenceObjectByHandle (ObjectHandle,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
KernelMode,
|
KeGetPreviousMode(),
|
||||||
&Object,
|
&Object,
|
||||||
NULL);
|
NULL);
|
||||||
if (Status != STATUS_SUCCESS)
|
if (!NT_SUCCESS (Status))
|
||||||
{
|
{
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectHeader = BODY_TO_HEADER(Object);
|
ObjectHeader = BODY_TO_HEADER(Object);
|
||||||
|
|
||||||
switch (ObjectInformationClass)
|
switch (ObjectInformationClass)
|
||||||
{
|
{
|
||||||
case ObjectNameInformation:
|
case ObjectNameInformation:
|
||||||
if (Length!=sizeof(OBJECT_NAME_INFORMATION)) return STATUS_INVALID_BUFFER_SIZE;
|
#if 0
|
||||||
nameinfo = (POBJECT_NAME_INFORMATION)ObjectInformation;
|
Status = ObQueryNameString (Object,
|
||||||
(*ResultLength)=Length;
|
(POBJECT_NAME_INFORMATION)ObjectInformation,
|
||||||
|
Length,
|
||||||
if (ObjectHeader->Type==InternalFileType) // FIXME: Temporary QueryName implementation, or at least separate functions
|
ReturnLength);
|
||||||
{
|
break;
|
||||||
fileob = (PFILE_OBJECT) Object;
|
#endif
|
||||||
Status = internalNameBuilder(BODY_TO_HEADER(fileob->DeviceObject->Vpb->RealDevice), &nameinfo->Name);
|
|
||||||
|
if (Length < sizeof(OBJECT_NAME_INFORMATION) + sizeof(WCHAR))
|
||||||
if (Status != STATUS_SUCCESS)
|
return STATUS_INVALID_BUFFER_SIZE;
|
||||||
{
|
|
||||||
ObDereferenceObject(Object);
|
NameInfo = (POBJECT_NAME_INFORMATION)ObjectInformation;
|
||||||
return Status;
|
*ReturnLength = 0;
|
||||||
}
|
|
||||||
filenameinfo = ExAllocatePool(NonPagedPool,MAX_PATH*sizeof(WCHAR)+sizeof(ULONG));
|
NameInfo->Name.MaximumLength = sizeof(WCHAR);
|
||||||
IoQueryFileInformation(fileob,FileNameInformation,MAX_PATH*sizeof(WCHAR)+sizeof(ULONG), filenameinfo,NULL);
|
NameInfo->Name.Length = 0;
|
||||||
|
NameInfo->Name.Buffer = (PWCHAR)((ULONG_PTR)NameInfo + sizeof(OBJECT_NAME_INFORMATION));
|
||||||
Status = RtlAppendUnicodeToString(&(nameinfo->Name), filenameinfo->FileName);
|
NameInfo->Name.Buffer[0] = 0;
|
||||||
|
|
||||||
ExFreePool( filenameinfo);
|
// FIXME: Temporary QueryName implementation, or at least separate functions
|
||||||
ObDereferenceObject(Object);
|
if (ObjectHeader->Type==InternalFileType)
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (ObjectHeader->Name.Buffer) // If it's got a name there, we can probably just make the full path through Name and Parent
|
|
||||||
{
|
{
|
||||||
Status = internalNameBuilder(ObjectHeader, &nameinfo->Name);
|
NameInfo->Name.MaximumLength = Length - sizeof(OBJECT_NAME_INFORMATION);
|
||||||
ObDereferenceObject(Object);
|
fileob = (PFILE_OBJECT) Object;
|
||||||
return Status;
|
Status = internalNameBuilder(BODY_TO_HEADER(fileob->DeviceObject->Vpb->RealDevice),
|
||||||
|
&NameInfo->Name);
|
||||||
|
if (Status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
NameInfo->Name.MaximumLength = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
filenameinfo = ExAllocatePool (NonPagedPool,
|
||||||
|
MAX_PATH * sizeof(WCHAR) + sizeof(ULONG));
|
||||||
|
if (filenameinfo == NULL)
|
||||||
|
{
|
||||||
|
NameInfo->Name.MaximumLength = 0;
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = IoQueryFileInformation (fileob,
|
||||||
|
FileNameInformation,
|
||||||
|
MAX_PATH * sizeof(WCHAR) + sizeof(ULONG),
|
||||||
|
filenameinfo,
|
||||||
|
NULL);
|
||||||
|
if (Status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
NameInfo->Name.MaximumLength = 0;
|
||||||
|
ExFreePool (filenameinfo);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = RtlAppendUnicodeToString (&(NameInfo->Name),
|
||||||
|
filenameinfo->FileName);
|
||||||
|
|
||||||
|
ExFreePool (filenameinfo);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
NameInfo->Name.MaximumLength = NameInfo->Name.Length + sizeof(WCHAR);
|
||||||
|
*ReturnLength = sizeof(OBJECT_NAME_INFORMATION) + NameInfo->Name.MaximumLength;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ObDereferenceObject(Object);
|
else if (ObjectHeader->Name.Buffer)
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
{
|
||||||
case ObjectTypeInformation:
|
// If it's got a name there, we can probably just make the full path through Name and Parent
|
||||||
typeinfo = (POBJECT_TYPE_INFORMATION)ObjectInformation;
|
NameInfo->Name.MaximumLength = Length - sizeof(OBJECT_NAME_INFORMATION);
|
||||||
if (Length!=sizeof(OBJECT_TYPE_INFORMATION)) return STATUS_INVALID_BUFFER_SIZE;
|
|
||||||
|
Status = internalNameBuilder (ObjectHeader,
|
||||||
// FIXME: Is this supposed to only be the header's Name field?
|
&NameInfo->Name);
|
||||||
// Can somebody check/verify this?
|
if (NT_SUCCESS(Status))
|
||||||
RtlCopyUnicodeString(&typeinfo->Name,&ObjectHeader->Name);
|
{
|
||||||
|
NameInfo->Name.MaximumLength = NameInfo->Name.Length + sizeof(WCHAR);
|
||||||
if (Status != STATUS_SUCCESS)
|
*ReturnLength = sizeof(OBJECT_NAME_INFORMATION) + NameInfo->Name.MaximumLength;
|
||||||
{
|
}
|
||||||
ObDereferenceObject(Object);
|
}
|
||||||
return Status;
|
else
|
||||||
}
|
{
|
||||||
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
RtlCopyUnicodeString(&typeinfo->Type,&ObjectHeader->ObjectType->TypeName);
|
}
|
||||||
//This should be info from the object header, not the object type, right?
|
break;
|
||||||
typeinfo->TotalHandles = ObjectHeader-> HandleCount;
|
|
||||||
typeinfo->ReferenceCount = ObjectHeader -> RefCount;
|
case ObjectTypeInformation:
|
||||||
|
typeinfo = (POBJECT_TYPE_INFORMATION)ObjectInformation;
|
||||||
ObDereferenceObject(Object);
|
if (Length!=sizeof(OBJECT_TYPE_INFORMATION))
|
||||||
return Status;
|
return STATUS_INVALID_BUFFER_SIZE;
|
||||||
default:
|
|
||||||
ObDereferenceObject(Object);
|
// FIXME: Is this supposed to only be the header's Name field?
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
// Can somebody check/verify this?
|
||||||
|
RtlCopyUnicodeString(&typeinfo->Name,&ObjectHeader->Name);
|
||||||
|
|
||||||
|
if (Status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlCopyUnicodeString(&typeinfo->Type,&ObjectHeader->ObjectType->TypeName);
|
||||||
|
//This should be info from the object header, not the object type, right?
|
||||||
|
typeinfo->TotalHandles = ObjectHeader-> HandleCount;
|
||||||
|
typeinfo->ReferenceCount = ObjectHeader -> RefCount;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ObDereferenceObject(Object);
|
||||||
|
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* NAME EXPORTED
|
||||||
|
* ObMakeTemporaryObject
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
*
|
||||||
|
* REVISIONS
|
||||||
|
*/
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
ObMakeTemporaryObject (PVOID ObjectBody)
|
ObMakeTemporaryObject (IN PVOID ObjectBody)
|
||||||
{
|
{
|
||||||
POBJECT_HEADER ObjectHeader;
|
POBJECT_HEADER ObjectHeader;
|
||||||
|
|
||||||
ObjectHeader = BODY_TO_HEADER(ObjectBody);
|
ObjectHeader = BODY_TO_HEADER(ObjectBody);
|
||||||
ObjectHeader->Permanent = FALSE;
|
ObjectHeader->Permanent = FALSE;
|
||||||
}
|
}
|
||||||
|
@ -187,34 +281,29 @@ ObMakeTemporaryObject (PVOID ObjectBody)
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
NtMakeTemporaryObject (
|
NtMakeTemporaryObject (IN HANDLE Handle)
|
||||||
HANDLE Handle
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
PVOID Object;
|
POBJECT_HEADER ObjectHeader;
|
||||||
NTSTATUS Status;
|
PVOID Object;
|
||||||
POBJECT_HEADER ObjectHeader;
|
NTSTATUS Status;
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(
|
|
||||||
Handle,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
KernelMode,
|
|
||||||
& Object,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
if (Status != STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectHeader = BODY_TO_HEADER(Object);
|
Status = ObReferenceObjectByHandle(Handle,
|
||||||
ObjectHeader->Permanent = FALSE;
|
0,
|
||||||
|
NULL,
|
||||||
ObDereferenceObject(Object);
|
KernelMode,
|
||||||
|
& Object,
|
||||||
return STATUS_SUCCESS;
|
NULL);
|
||||||
|
if (Status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectHeader = BODY_TO_HEADER(Object);
|
||||||
|
ObjectHeader->Permanent = FALSE;
|
||||||
|
|
||||||
|
ObDereferenceObject(Object);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Reference in a new issue