-/* $Id: ntobj.c,v 1.9 2002/08/14 20:58:38 dwelch Exp $
- *
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/ob/ntobj.c
- * PURPOSE: User mode interface to object manager
- * PROGRAMMER: David Welch (welch@cwcom.net)
- * UPDATE HISTORY:
- * 10/06/98: Created
+/* $Id$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/ob/ntobj.c
+ * PURPOSE: User mode interface to object manager
+ *
+ * PROGRAMMERS: David Welch (welch@cwcom.net)
*/
/* INCLUDES *****************************************************************/
-#include <ddk/ntddk.h>
-#include <internal/ob.h>
-#include <internal/id.h>
-
+#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
+
/* FUNCTIONS ************************************************************/
-NTSTATUS
-STDCALL
-NtSetInformationObject (
- IN HANDLE ObjectHandle,
- IN CINT ObjectInformationClass,
- IN PVOID ObjectInformation,
- IN ULONG Length
- )
+/**********************************************************************
+ * NAME EXPORTED
+ * NtSetInformationObject
+ *
+ * DESCRIPTION
+ *
+ * ARGUMENTS
+ *
+ * RETURN VALUE
+ *
+ * REVISIONS
+ */
+NTSTATUS STDCALL
+NtSetInformationObject (IN HANDLE ObjectHandle,
+ IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
+ IN PVOID ObjectInformation,
+ IN ULONG Length)
{
- UNIMPLEMENTED;
-}
+ PVOID Object;
+ NTSTATUS Status;
+ PAGED_CODE();
-NTSTATUS
-internalNameBuilder
-(
-POBJECT_HEADER ObjectHeader,
-PUNICODE_STRING string)
-/* So, what's the purpose of this function?
- 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
- have any meaning (not files) */
-{
- NTSTATUS status;
- if (ObjectHeader->Parent)
- {
- status = internalNameBuilder(BODY_TO_HEADER(ObjectHeader->Parent),string);
- if (status != STATUS_SUCCESS)
- {
- return status;
- }
- }
- if (ObjectHeader->Name.Buffer)
- {
- status = RtlAppendUnicodeToString(string, L"\\");
- if (status != STATUS_SUCCESS) return status;
- return RtlAppendUnicodeStringToString(string, &ObjectHeader->Name);
- }
- return STATUS_SUCCESS;
+ if (ObjectInformationClass != ObjectHandleInformation)
+ return STATUS_INVALID_INFO_CLASS;
+
+ if (Length != sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION))
+ return STATUS_INFO_LENGTH_MISMATCH;
+
+ Status = ObReferenceObjectByHandle (ObjectHandle,
+ 0,
+ NULL,
+ (KPROCESSOR_MODE)KeGetPreviousMode (),
+ &Object,
+ NULL);
+ if (!NT_SUCCESS (Status))
+ {
+ return Status;
+ }
+
+ Status = ObpSetHandleAttributes (ObjectHandle,
+ (POBJECT_HANDLE_ATTRIBUTE_INFORMATION)ObjectInformation);
+
+ ObDereferenceObject (Object);
+
+ return Status;
}
-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!
-
- Probably we should add meaning to QueryName in POBJECT_TYPE, no matter if we know
- the correct parameters or not. For FILE_OBJECTs, it would probably look like the code
- for ObjectNameInformation below. You give it a POBJECT and a PUNICODE_STRING, and it
- returns the full path in the PUNICODE_STRING
-
- If we don't do it this way, we should anyway add switches and separate functions to handle
- the different object types*/
+
+/**********************************************************************
+ * NAME EXPORTED
+ * NtQueryObject
+ *
+ * DESCRIPTION
+ *
+ * ARGUMENTS
+ *
+ * RETURN VALUE
+ *
+ * REVISIONS
+ */
+NTSTATUS STDCALL
+NtQueryObject (IN HANDLE ObjectHandle,
+ IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
+ OUT PVOID ObjectInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength OPTIONAL)
{
- POBJECT_NAME_INFORMATION nameinfo;
- POBJECT_TYPE_INFORMATION typeinfo;
- PFILE_NAME_INFORMATION filenameinfo;
- PVOID Object;
- NTSTATUS Status;
- POBJECT_HEADER ObjectHeader;
- PFILE_OBJECT fileob;
-
- Status = ObReferenceObjectByHandle(ObjectHandle,
- 0,
- NULL,
- KernelMode,
- &Object,
- NULL);
- if (Status != STATUS_SUCCESS)
+ OBJECT_HANDLE_INFORMATION HandleInfo;
+ POBJECT_HEADER ObjectHeader;
+ ULONG InfoLength;
+ PVOID Object;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ Status = ObReferenceObjectByHandle (ObjectHandle,
+ 0,
+ NULL,
+ (KPROCESSOR_MODE)KeGetPreviousMode(),
+ &Object,
+ &HandleInfo);
+ if (!NT_SUCCESS (Status))
{
return Status;
}
-
+
ObjectHeader = BODY_TO_HEADER(Object);
-
+
switch (ObjectInformationClass)
{
- case ObjectNameInformation:
- if (Length!=sizeof(OBJECT_NAME_INFORMATION)) return STATUS_INVALID_BUFFER_SIZE;
- nameinfo = (POBJECT_NAME_INFORMATION)ObjectInformation;
- (*ResultLength)=Length;
-
- if (ObjectHeader->Type==InternalFileType) // FIXME: Temporary QueryName implementation, or at least separate functions
- {
- fileob = (PFILE_OBJECT) Object;
- Status = internalNameBuilder(BODY_TO_HEADER(fileob->DeviceObject->Vpb->RealDevice), &nameinfo->Name);
-
- if (Status != STATUS_SUCCESS)
- {
- ObDereferenceObject(Object);
- return Status;
- }
- filenameinfo = ExAllocatePool(NonPagedPool,MAX_PATH*sizeof(WCHAR)+sizeof(ULONG));
- IoQueryFileInformation(fileob,FileNameInformation,MAX_PATH*sizeof(WCHAR)+sizeof(ULONG), filenameinfo,NULL);
-
- Status = RtlAppendUnicodeToString(&(nameinfo->Name), filenameinfo->FileName);
-
- ExFreePool( filenameinfo);
- ObDereferenceObject(Object);
- 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
+ case ObjectBasicInformation:
+ InfoLength = sizeof(OBJECT_BASIC_INFORMATION);
+ if (Length != sizeof(OBJECT_BASIC_INFORMATION))
{
- Status = internalNameBuilder(ObjectHeader, &nameinfo->Name);
- ObDereferenceObject(Object);
- return Status;
+ Status = STATUS_INFO_LENGTH_MISMATCH;
}
- ObDereferenceObject(Object);
- return STATUS_NOT_IMPLEMENTED;
- case ObjectTypeInformation:
- typeinfo = (POBJECT_TYPE_INFORMATION)ObjectInformation;
- if (Length!=sizeof(OBJECT_TYPE_INFORMATION)) return STATUS_INVALID_BUFFER_SIZE;
-
- // FIXME: Is this supposed to only be the header's Name field?
- // Can somebody check/verify this?
- RtlCopyUnicodeString(&typeinfo->Name,&ObjectHeader->Name);
-
- if (Status != STATUS_SUCCESS)
- {
- ObDereferenceObject(Object);
- return Status;
- }
-
- 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;
-
- ObDereferenceObject(Object);
- return Status;
- default:
- ObDereferenceObject(Object);
- return STATUS_NOT_IMPLEMENTED;
+ else
+ {
+ POBJECT_BASIC_INFORMATION BasicInfo;
+
+ BasicInfo = (POBJECT_BASIC_INFORMATION)ObjectInformation;
+ BasicInfo->Attributes = HandleInfo.HandleAttributes;
+ BasicInfo->GrantedAccess = HandleInfo.GrantedAccess;
+ BasicInfo->HandleCount = ObjectHeader->HandleCount;
+ BasicInfo->PointerCount = ObjectHeader->PointerCount;
+ BasicInfo->PagedPoolUsage = 0; /* FIXME*/
+ BasicInfo->NonPagedPoolUsage = 0; /* FIXME*/
+ BasicInfo->NameInformationLength = 0; /* FIXME*/
+ BasicInfo->TypeInformationLength = 0; /* FIXME*/
+ BasicInfo->SecurityDescriptorLength = 0; /* FIXME*/
+ if (ObjectHeader->Type == ObSymbolicLinkType)
+ {
+ BasicInfo->CreateTime.QuadPart =
+ ((PSYMLINK_OBJECT)Object)->CreateTime.QuadPart;
+ }
+ else
+ {
+ BasicInfo->CreateTime.QuadPart = (ULONGLONG)0;
+ }
+ Status = STATUS_SUCCESS;
+ }
+ break;
+
+ case ObjectNameInformation:
+ Status = ObQueryNameString (Object,
+ (POBJECT_NAME_INFORMATION)ObjectInformation,
+ Length,
+ &InfoLength);
+ break;
+
+ case ObjectTypeInformation:
+#if 0
+// InfoLength =
+ if (Length != sizeof(OBJECT_TYPE_INFORMATION))
+ {
+ Status = STATUS_INVALID_BUFFER_SIZE;
+ }
+ else
+ {
+ POBJECT_TYPE_INFORMATION TypeInfo;
+
+ TypeInfo = (POBJECT_TYPE_INFORMATION)ObjectInformation;
+ // FIXME: Is this supposed to only be the header's Name field?
+ // Can somebody check/verify this?
+ RtlCopyUnicodeString(&typeinfo->Name,&ObjectHeader->Name);
+
+ if (Status != STATUS_SUCCESS)
+ {
+ break;
+ }
+
+ RtlCopyUnicodeString(&typeinfo->Type,&ObjectHeader->Type->TypeName);
+ //This should be info from the object header, not the object type, right?
+ typeinfo->TotalHandles = ObjectHeader-> HandleCount;
+ typeinfo->ReferenceCount = ObjectHeader -> PointerCount;
+ }
+#endif
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case ObjectAllTypesInformation:
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case ObjectHandleInformation:
+ InfoLength = sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION);
+ if (Length != sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ else
+ {
+ Status = ObpQueryHandleAttributes (ObjectHandle,
+ (POBJECT_HANDLE_ATTRIBUTE_INFORMATION)ObjectInformation);
+ }
+ break;
+
+ default:
+ Status = STATUS_INVALID_INFO_CLASS;
+ break;
}
+
+ ObDereferenceObject (Object);
+
+ if (ResultLength != NULL)
+ *ResultLength = InfoLength;
+
+ return Status;
}
-VOID STDCALL
-ObMakeTemporaryObject (PVOID ObjectBody)
+
+/**********************************************************************
+ * NAME PRIVATE
+ * ObpSetPermanentObject/2
+ *
+ * DESCRIPTION
+ * Fast general purpose routine to set an object's permanent
+ * attribute, given a pointer to the object's body.
+ */
+VOID FASTCALL
+ObpSetPermanentObject (IN PVOID ObjectBody, IN BOOLEAN Permanent)
{
- POBJECT_HEADER ObjectHeader;
-
+ POBJECT_HEADER ObjectHeader;
+
ObjectHeader = BODY_TO_HEADER(ObjectBody);
- ObjectHeader->Permanent = FALSE;
+ ASSERT (ObjectHeader->PointerCount > 0);
+ if (Permanent)
+ {
+ ObjectHeader->Flags |= OB_FLAG_PERMANENT;
+ }
+ else
+ {
+ ObjectHeader->Flags &= ~OB_FLAG_PERMANENT;
+ if (ObjectHeader->HandleCount == 0 && HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory)
+ {
+ /* Remove the object from the namespace */
+ ObpRemoveEntryDirectory(ObjectHeader);
+ }
+ }
+}
+
+/**********************************************************************
+ * NAME EXPORTED
+ * ObMakeTemporaryObject/1
+ *
+ * DESCRIPTION
+ *
+ * ARGUMENTS
+ *
+ * RETURN VALUE
+ *
+ * REVISIONS
+ *
+ * @implemented
+ */
+VOID STDCALL
+ObMakeTemporaryObject(IN PVOID ObjectBody)
+{
+ ObpSetPermanentObject (ObjectBody, FALSE);
}
/**********************************************************************
* NAME EXPORTED
* NtMakeTemporaryObject
- *
+ *
* DESCRIPTION
*
* ARGUMENTS
*
* REVISIONS
*/
-NTSTATUS
-STDCALL
-NtMakeTemporaryObject (
- HANDLE Handle
- )
+NTSTATUS STDCALL
+NtMakeTemporaryObject(IN HANDLE ObjectHandle)
{
- PVOID Object;
- NTSTATUS Status;
- POBJECT_HEADER ObjectHeader;
-
- Status = ObReferenceObjectByHandle(
- Handle,
- 0,
- NULL,
- KernelMode,
- & Object,
- NULL
- );
- if (Status != STATUS_SUCCESS)
- {
- return Status;
- }
-
- ObjectHeader = BODY_TO_HEADER(Object);
- ObjectHeader->Permanent = FALSE;
-
- ObDereferenceObject(Object);
-
- return STATUS_SUCCESS;
+ PVOID ObjectBody;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ Status = ObReferenceObjectByHandle(ObjectHandle,
+ 0,
+ NULL,
+ (KPROCESSOR_MODE)KeGetPreviousMode(),
+ &ObjectBody,
+ NULL);
+ if (Status != STATUS_SUCCESS)
+ {
+ return Status;
+ }
+
+ ObpSetPermanentObject (ObjectBody, FALSE);
+
+ ObDereferenceObject(ObjectBody);
+
+ return STATUS_SUCCESS;
}
+/**********************************************************************
+ * NAME EXPORTED
+ * NtMakePermanentObject/1
+ *
+ * DESCRIPTION
+ *
+ * ARGUMENTS
+ *
+ * RETURN VALUE
+ *
+ * REVISIONS
+ *
+ * @implemented
+ */
+NTSTATUS STDCALL
+NtMakePermanentObject(IN HANDLE ObjectHandle)
+{
+ PVOID ObjectBody;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ Status = ObReferenceObjectByHandle(ObjectHandle,
+ 0,
+ NULL,
+ (KPROCESSOR_MODE)KeGetPreviousMode(),
+ &ObjectBody,
+ NULL);
+ if (Status != STATUS_SUCCESS)
+ {
+ return Status;
+ }
+
+ ObpSetPermanentObject (ObjectBody, TRUE);
+
+ ObDereferenceObject(ObjectBody);
+
+ return STATUS_SUCCESS;
+}
+
/* EOF */