* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ob/dirobj.c
* PURPOSE: Interface functions to directory object
- *
+ *
* PROGRAMMERS: David Welch (welch@mcmail.com)
*/
*
* DESCRIPTION
* Opens a namespace directory object.
- *
+ *
* ARGUMENTS
* DirectoryHandle (OUT)
* Variable which receives the directory handle.
- *
+ *
* DesiredAccess
* Desired access to the directory.
- *
+ *
* ObjectAttributes
* Structure describing the directory.
- *
+ *
* RETURN VALUE
* Status.
- *
+ *
* NOTES
* Undocumented.
*/
HANDLE hDirectory;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
-
+
PAGED_CODE();
-
+
PreviousMode = ExGetPreviousMode();
-
+
if(PreviousMode != KernelMode)
{
_SEH_TRY
{
- ProbeForWrite(DirectoryHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
+ ProbeForWriteHandle(DirectoryHandle);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
-
+
if(!NT_SUCCESS(Status))
{
DPRINT1("NtOpenDirectoryObject failed, Status: 0x%x\n", Status);
return Status;
}
}
-
+
Status = ObOpenObjectByName(ObjectAttributes,
ObDirectoryType,
NULL,
}
_SEH_END;
}
-
+
return Status;
}
/**********************************************************************
* NAME EXPORTED
* NtQueryDirectoryObject
- *
+ *
* DESCRIPTION
* Reads information from a directory in the system namespace.
- *
+ *
* ARGUMENTS
* DirectoryHandle
* Handle, obtained with NtOpenDirectoryObject(), which
* must grant DIRECTORY_QUERY access to the directory
* object.
- *
+ *
* Buffer (OUT)
* Buffer to hold the data read.
- *
+ *
* BufferLength
* Size of the buffer in bytes.
- *
+ *
* ReturnSingleEntry
* When TRUE, only 1 entry is written in DirObjInformation;
* otherwise as many as will fit in the buffer.
- *
+ *
* RestartScan
* If TRUE start reading at index 0.
* If FALSE start reading at the index specified
* by object index *ObjectIndex.
- *
+ *
* Context
* Zero based index into the directory, interpretation
* depends on RestartScan.
- *
+ *
* ReturnLength (OUT)
* Caller supplied storage for the number of bytes
* written (or NULL).
ULONG NextEntry = 0;
ULONG CopyBytes = 0;
NTSTATUS Status = STATUS_SUCCESS;
-
+
PAGED_CODE();
-
+
PreviousMode = ExGetPreviousMode();
if(PreviousMode != KernelMode)
ProbeForWrite(Buffer,
BufferLength,
sizeof(WCHAR));
- ProbeForWrite(Context,
- sizeof(ULONG),
- sizeof(ULONG));
+ ProbeForWriteUlong(Context);
if(!RestartScan)
{
SkipEntries = *Context;
}
if(ReturnLength != NULL)
{
- ProbeForWrite(ReturnLength,
- sizeof(ULONG),
- sizeof(ULONG));
+ ProbeForWriteUlong(ReturnLength);
}
}
_SEH_HANDLE
{
SkipEntries = *Context;
}
-
+
Status = ObReferenceObjectByHandle(DirectoryHandle,
DIRECTORY_QUERY,
ObDirectoryType,
NULL);
if(NT_SUCCESS(Status))
{
- PVOID TemporaryBuffer = ExAllocatePool(PagedPool,
+ PVOID TemporaryBuffer = ExAllocatePool(NonPagedPool,
BufferLength);
if(TemporaryBuffer != NULL)
{
POBJECT_HEADER EntryHeader;
PLIST_ENTRY ListEntry;
KIRQL OldLevel;
- ULONG RequiredSize = 0;
+ ULONG RequiredSize = sizeof(OBJECT_DIRECTORY_INFORMATION);
ULONG nDirectories = 0;
POBJECT_DIRECTORY_INFORMATION DirInfo = (POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer;
-
+
Status = STATUS_NO_MORE_ENTRIES;
KeAcquireSpinLock(&Directory->Lock, &OldLevel);
EntryHeader = CONTAINING_RECORD(ListEntry, OBJECT_HEADER, Entry);
/* calculate the size of the required buffer space for this entry */
- Name = (EntryHeader->Name.Length != 0 ? &EntryHeader->Name : NULL);
- Type = &EntryHeader->ObjectType->TypeName;
+ Name = (HEADER_TO_OBJECT_NAME(EntryHeader)->Name.Length != 0 ? &HEADER_TO_OBJECT_NAME(EntryHeader)->Name : NULL);
+ Type = &EntryHeader->Type->Name;
EntrySize = sizeof(OBJECT_DIRECTORY_INFORMATION) +
((Name != NULL) ? ((ULONG)Name->Length + sizeof(WCHAR)) : 0) +
- (ULONG)EntryHeader->ObjectType->TypeName.Length + sizeof(WCHAR);
+ (ULONG)EntryHeader->Type->Name.Length + sizeof(WCHAR);
if(RequiredSize + EntrySize <= BufferLength)
{
nDirectories++;
RequiredSize += EntrySize;
-
+
Status = STATUS_SUCCESS;
if(ReturnSingleEntry)
RequiredSize += EntrySize;
Status = STATUS_BUFFER_TOO_SMALL;
}
-
+
/* we couldn't query this entry, so leave the index that will be stored
in Context to this entry so the caller can query it the next time
he queries (hopefully with a buffer that is large enough then...) */
NextEntry--;
-
+
/* just copy the entries that fit into the buffer */
break;
}
SkipEntries--;
}
}
-
+
if(!ReturnSingleEntry && ListEntry != &Directory->head)
{
/* there are more entries to enumerate but the buffer is already full.
if(NT_SUCCESS(Status) && nDirectories > 0)
{
- PWSTR strbuf = (PWSTR)((POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer + nDirectories);
- PWSTR deststrbuf = (PWSTR)((POBJECT_DIRECTORY_INFORMATION)Buffer + nDirectories);
-
- CopyBytes = nDirectories * sizeof(OBJECT_DIRECTORY_INFORMATION);
-
+ PWSTR strbuf = (PWSTR)((POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer + nDirectories + 1);
+ PWSTR deststrbuf = (PWSTR)((POBJECT_DIRECTORY_INFORMATION)Buffer + nDirectories + 1);
+ memset((POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer + nDirectories, 0, sizeof(OBJECT_DIRECTORY_INFORMATION));
+
+ CopyBytes = (nDirectories + 1) * sizeof(OBJECT_DIRECTORY_INFORMATION);
+
/* copy the names from the objects and append them to the list of the
objects. copy to the temporary buffer only because the directory
lock can't be released and the buffer might be pagable memory! */
nDirectories--, DirInfo++)
{
ULONG NameLength;
-
+
if(DirInfo->ObjectName.Length > 0)
{
RtlCopyMemory(strbuf,
CopyBytes += (NameLength + 1) * sizeof(WCHAR);
}
-
+
RtlCopyMemory(strbuf,
DirInfo->ObjectTypeName.Buffer,
DirInfo->ObjectTypeName.Length);
strbuf[NameLength] = L'\0';
strbuf += NameLength + 1;
deststrbuf += NameLength + 1;
-
+
CopyBytes += (NameLength + 1) * sizeof(WCHAR);
}
}
}
_SEH_END;
}
-
+
ExFreePool(TemporaryBuffer);
}
else
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
-
+
return Status;
}
/**********************************************************************
* NAME (EXPORTED as Zw)
* NtCreateDirectoryObject
- *
+ *
* DESCRIPTION
* Creates or opens a directory object (a container for other
* objects).
- *
+ *
* ARGUMENTS
* DirectoryHandle (OUT)
- * Caller supplied storage for the handle of the
+ * Caller supplied storage for the handle of the
* directory.
- *
+ *
* DesiredAccess
* Access desired to the directory.
- *
+ *
* ObjectAttributes
* Object attributes initialized with
* InitializeObjectAttributes.
- *
+ *
* RETURN VALUE
* Status.
*/
HANDLE hDirectory;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
-
+
PAGED_CODE();
-
+
DPRINT("NtCreateDirectoryObject(DirectoryHandle %x, "
- "DesiredAccess %x, ObjectAttributes %x\n",
- DirectoryHandle, DesiredAccess, ObjectAttributes);
+ "DesiredAccess %x, ObjectAttributes %x\n",
+ DirectoryHandle, DesiredAccess, ObjectAttributes);
PreviousMode = ExGetPreviousMode();
{
_SEH_TRY
{
- ProbeForWrite(DirectoryHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
+ ProbeForWriteHandle(DirectoryHandle);
}
_SEH_HANDLE
{
0,
0,
(PVOID*)&Directory);
+
if(NT_SUCCESS(Status))
{
Status = ObInsertObject((PVOID)Directory,
0,
NULL,
&hDirectory);
+ if (!NT_SUCCESS(Status))
+ {
+ ObMakeTemporaryObject(Directory);
+ }
ObDereferenceObject(Directory);
if(NT_SUCCESS(Status))