|
|
Definition at line 456 of file obdir.c.
Referenced by QueryDosDeviceW(), ScmCheckDriver(), ScmGetDriverStatus(), SmpTranslateSystemPartitionInformation(), and xHalpGetRDiskCount().
{
POBJECT_DIRECTORY Directory;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
ULONG SkipEntries = 0;
NTSTATUS Status;
PVOID LocalBuffer;
POBJECT_DIRECTORY_INFORMATION DirectoryInfo;
ULONG Length, TotalLength;
ULONG Count, CurrentEntry;
ULONG Hash;
POBJECT_DIRECTORY_ENTRY Entry;
POBJECT_HEADER ObjectHeader;
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
UNICODE_STRING Name;
PWSTR p;
OBP_LOOKUP_CONTEXT LookupContext;
PAGED_CODE();
ObpInitializeLookupContext(&LookupContext);
if (PreviousMode != KernelMode)
{
_SEH2_TRY
{
ProbeForWrite(Buffer, BufferLength, sizeof(WCHAR));
ProbeForWriteUlong(Context);
if (!RestartScan) SkipEntries = *Context;
if (ReturnLength) ProbeForWriteUlong(ReturnLength);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
}
else if (!RestartScan)
{
SkipEntries = *Context;
}
LocalBuffer = ExAllocatePoolWithTag(PagedPool,
sizeof(OBJECT_DIRECTORY_INFORMATION) +
BufferLength,
OB_NAME_TAG);
if (!LocalBuffer) return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(LocalBuffer, BufferLength);
Status = ObReferenceObjectByHandle(DirectoryHandle,
DIRECTORY_QUERY,
ObDirectoryType,
PreviousMode,
(PVOID*)&Directory,
NULL);
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(LocalBuffer, OB_NAME_TAG);
return Status;
}
ObpAcquireDirectoryLockShared(Directory, &LookupContext);
DirectoryInfo = (POBJECT_DIRECTORY_INFORMATION)LocalBuffer;
TotalLength = sizeof(OBJECT_DIRECTORY_INFORMATION);
Count = 0;
CurrentEntry = 0;
Status = STATUS_NO_MORE_ENTRIES;
for (Hash = 0; Hash < 37; Hash++)
{
Entry = Directory->HashBuckets[Hash];
while (Entry)
{
if (SkipEntries == CurrentEntry++)
{
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Entry->Object);
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
if (ObjectNameInfo)
{
Name = ObjectNameInfo->Name;
}
else
{
RtlInitEmptyUnicodeString(&Name, NULL, 0);
}
Length = sizeof(OBJECT_DIRECTORY_INFORMATION) +
Name.Length + sizeof(UNICODE_NULL) +
ObjectHeader->Type->Name.Length + sizeof(UNICODE_NULL);
if ((TotalLength + Length) > BufferLength)
{
if (ReturnSingleEntry)
{
TotalLength += Length;
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
Status = STATUS_MORE_ENTRIES;
}
CurrentEntry--;
goto Quickie;
}
DirectoryInfo->Name.Length = Name.Length;
DirectoryInfo->Name.MaximumLength = Name.Length +
sizeof(UNICODE_NULL);
DirectoryInfo->Name.Buffer = Name.Buffer;
DirectoryInfo->TypeName.Length = ObjectHeader->
Type->Name.Length;
DirectoryInfo->TypeName.MaximumLength = ObjectHeader->
Type->Name.Length +
sizeof(UNICODE_NULL);
DirectoryInfo->TypeName.Buffer = ObjectHeader->
Type->Name.Buffer;
Status = STATUS_SUCCESS;
TotalLength += Length;
DirectoryInfo++;
Count++;
if (ReturnSingleEntry) goto Quickie;
SkipEntries++;
}
Entry = Entry->ChainLink;
}
}
Quickie:
if (NT_SUCCESS(Status))
{
RtlZeroMemory(DirectoryInfo, sizeof(OBJECT_DIRECTORY_INFORMATION));
DirectoryInfo++;
p = (PWSTR)DirectoryInfo;
DirectoryInfo = LocalBuffer;
while (Count--)
{
RtlCopyMemory(p,
DirectoryInfo->Name.Buffer,
DirectoryInfo->Name.Length);
DirectoryInfo->Name.Buffer = (PVOID)((ULONG_PTR)Buffer +
((ULONG_PTR)p -
(ULONG_PTR)LocalBuffer));
p = (PVOID)((ULONG_PTR)p + DirectoryInfo->Name.Length);
*p++ = UNICODE_NULL;
RtlCopyMemory(p,
DirectoryInfo->TypeName.Buffer,
DirectoryInfo->TypeName.Length);
DirectoryInfo->TypeName.Buffer = (PVOID)((ULONG_PTR)Buffer +
((ULONG_PTR)p -
(ULONG_PTR)LocalBuffer));
p = (PVOID)((ULONG_PTR)p + DirectoryInfo->TypeName.Length);
*p++ = UNICODE_NULL;
DirectoryInfo++;
}
*Context = CurrentEntry;
}
_SEH2_TRY
{
RtlCopyMemory(Buffer,
LocalBuffer,
(TotalLength <= BufferLength) ?
TotalLength : BufferLength);
if (ReturnLength) *ReturnLength = TotalLength;
}
_SEH2_EXCEPT(ExSystemExceptionFilter())
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
ObpReleaseDirectoryLock(Directory, &LookupContext);
ObDereferenceObject(Directory);
ExFreePoolWithTag(LocalBuffer, OB_NAME_TAG);
return Status;
}
|