- Fix definition of OBJECT_DIRECTORY_INFORMATION

- Implement most of NtQueryDirectoryObject. It lacks the last step of converting the absolute buffer to a relative one. I have no idea why the old code was re-implemented in a recent commit when I clearly said I would fix this tonight.

svn path=/trunk/; revision=23112
This commit is contained in:
Alex Ionescu 2006-07-17 03:16:15 +00:00
parent 8baa71bb63
commit 96722f7c02
9 changed files with 158 additions and 215 deletions

View file

@ -257,11 +257,11 @@ ListDirectory (
CHAR TypeNameA [MAX_PATH];
CHAR TargetNameA [MAX_PATH];
if (0 == wcscmp (L"SymbolicLink", pDirectoryEntry->ObjectTypeName.Buffer))
if (0 == wcscmp (L"SymbolicLink", pDirectoryEntry->TypeName.Buffer))
{
if (TRUE == ExpandSymbolicLink (
DirectoryNameW,
& pDirectoryEntry->ObjectName,
& pDirectoryEntry->Name,
& TargetObjectName
)
)
@ -269,8 +269,8 @@ ListDirectory (
printf (
"%-16s %s -> %s\n",
RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA),
RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA),
RawUszAsz (pDirectoryEntry->TypeName.Buffer, TypeNameA),
RawUszAsz (pDirectoryEntry->Name.Buffer, ObjectNameA),
RawUszAsz (TargetObjectName.Buffer, TargetNameA)
);
}
@ -278,8 +278,8 @@ ListDirectory (
{
printf (
"%-16s %s -> (error!)\n",
RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA),
RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA)
RawUszAsz (pDirectoryEntry->TypeName.Buffer, TypeNameA),
RawUszAsz (pDirectoryEntry->Name.Buffer, ObjectNameA)
);
}
}
@ -287,8 +287,8 @@ ListDirectory (
{
printf (
"%-16s %s\n",
RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA),
RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA)
RawUszAsz (pDirectoryEntry->TypeName.Buffer, TypeNameA),
RawUszAsz (pDirectoryEntry->Name.Buffer, ObjectNameA)
);
}
++ pDirectoryEntry;
@ -306,9 +306,9 @@ ListDirectory (
if (FALSE != Recurse)
{
pDirectoryEntry = (POBJECT_DIRECTORY_INFORMATION) DirectoryEntry;
while (0 != pDirectoryEntry->ObjectTypeName.Length)
while (0 != pDirectoryEntry->TypeName.Length)
{
if (0 == wcscmp (L"Directory", pDirectoryEntry->ObjectTypeName.Buffer))
if (0 == wcscmp (L"Directory", pDirectoryEntry->TypeName.Buffer))
{
WCHAR CurrentName [MAX_PATH];
UNICODE_STRING CurrentDirectory;
@ -319,7 +319,7 @@ ListDirectory (
{
wcscat (CurrentName, L"\\");
}
wcscat (CurrentName, pDirectoryEntry->ObjectName.Buffer);
wcscat (CurrentName, pDirectoryEntry->Name.Buffer);
RtlInitUnicodeString (& CurrentDirectory, CurrentName);
ListDirectory (& CurrentDirectory, Recurse);
}

View file

@ -470,12 +470,12 @@ ScmCheckDriver(PSERVICE Service)
if (!NT_SUCCESS(Status))
break;
DPRINT("Comparing: '%S' '%wZ'\n", Service->lpServiceName, &DirInfo->ObjectName);
DPRINT("Comparing: '%S' '%wZ'\n", Service->lpServiceName, &DirInfo->Name);
if (_wcsicmp(Service->lpServiceName, DirInfo->ObjectName.Buffer) == 0)
if (_wcsicmp(Service->lpServiceName, DirInfo->Name.Buffer) == 0)
{
DPRINT("Found: '%S' '%wZ'\n",
Service->lpServiceName, &DirInfo->ObjectName);
Service->lpServiceName, &DirInfo->Name);
/* Mark service as 'running' */
Service->Status.dwCurrentState = SERVICE_RUNNING;

View file

@ -140,12 +140,12 @@ ScmGetDriverStatus(PSERVICE lpService,
if (!NT_SUCCESS(Status))
break;
DPRINT("Comparing: '%S' '%wZ'\n", lpService->lpServiceName, &DirInfo->ObjectName);
DPRINT("Comparing: '%S' '%wZ'\n", lpService->lpServiceName, &DirInfo->Name);
if (_wcsicmp(lpService->lpServiceName, DirInfo->ObjectName.Buffer) == 0)
if (_wcsicmp(lpService->lpServiceName, DirInfo->Name.Buffer) == 0)
{
DPRINT1("Found: '%S' '%wZ'\n",
lpService->lpServiceName, &DirInfo->ObjectName);
lpService->lpServiceName, &DirInfo->Name);
bFound = TRUE;
break;

View file

@ -298,11 +298,11 @@ QueryDosDeviceW(
break;
}
if (!wcscmp (DirInfo->ObjectTypeName.Buffer, L"SymbolicLink"))
if (!wcscmp (DirInfo->TypeName.Buffer, L"SymbolicLink"))
{
DPRINT ("Name: '%wZ'\n", &DirInfo->ObjectName);
DPRINT ("Name: '%wZ'\n", &DirInfo->Name);
NameLength = DirInfo->ObjectName.Length / sizeof(WCHAR);
NameLength = DirInfo->Name.Length / sizeof(WCHAR);
if (Length + NameLength + 1 >= ucchMax)
{
Length = 0;
@ -311,8 +311,8 @@ QueryDosDeviceW(
}
memcpy (Ptr,
DirInfo->ObjectName.Buffer,
DirInfo->ObjectName.Length);
DirInfo->Name.Buffer,
DirInfo->Name.Length);
Ptr += NameLength;
Length += NameLength;
*Ptr = UNICODE_NULL;

View file

@ -261,8 +261,8 @@ typedef struct _OBJECT_HANDLE_ATTRIBUTE_INFORMATION
typedef struct _OBJECT_DIRECTORY_INFORMATION
{
UNICODE_STRING ObjectName;
UNICODE_STRING ObjectTypeName;
UNICODE_STRING Name;
UNICODE_STRING TypeName;
} OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION;
#ifndef NTOS_MODE_USER

View file

@ -513,12 +513,12 @@ xHalpGetRDiskCount(VOID)
if (NT_SUCCESS(Status))
{
Count = 0;
while (DirectoryInfo[Count].ObjectName.Buffer)
while (DirectoryInfo[Count].Name.Buffer)
{
DPRINT("Count %x\n", Count);
DirectoryInfo[Count].ObjectName.Buffer[DirectoryInfo[Count].ObjectName.Length / sizeof(WCHAR)] = 0;
ArcNameBuffer = DirectoryInfo[Count].ObjectName.Buffer;
if (DirectoryInfo[Count].ObjectName.Length >= sizeof(L"multi(0)disk(0)rdisk(0)") - sizeof(WCHAR) &&
DirectoryInfo[Count].Name.Buffer[DirectoryInfo[Count].Name.Length / sizeof(WCHAR)] = 0;
ArcNameBuffer = DirectoryInfo[Count].Name.Buffer;
if (DirectoryInfo[Count].Name.Length >= sizeof(L"multi(0)disk(0)rdisk(0)") - sizeof(WCHAR) &&
!_wcsnicmp(ArcNameBuffer, L"multi(0)disk(0)rdisk(", (sizeof(L"multi(0)disk(0)rdisk(") - sizeof(WCHAR)) / sizeof(WCHAR)))
{
DPRINT("%S\n", ArcNameBuffer);

View file

@ -414,6 +414,15 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
ULONG NextEntry = 0;
ULONG CopyBytes = 0;
NTSTATUS Status = STATUS_SUCCESS;
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;
PAGED_CODE();
/* Check if we need to do any probing */
@ -447,6 +456,14 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
SkipEntries = *Context;
}
/* Allocate a buffer */
LocalBuffer = ExAllocatePoolWithTag(PagedPool,
sizeof(OBJECT_DIRECTORY_INFORMATION) +
BufferLength,
OB_NAME_TAG);
if (!LocalBuffer) return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(LocalBuffer, BufferLength);
/* Get a reference to directory */
Status = ObReferenceObjectByHandle(DirectoryHandle,
DIRECTORY_QUERY,
@ -454,200 +471,126 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
PreviousMode,
(PVOID*)&Directory,
NULL);
if (NT_SUCCESS(Status))
if (!NT_SUCCESS(Status))
{
PVOID TemporaryBuffer = ExAllocatePool(NonPagedPool,
BufferLength);
if(TemporaryBuffer != NULL)
/* Free the buffer and fail */
ExFreePool(LocalBuffer);
return Status;
}
/* Start at position 0 */
DirectoryInfo = (POBJECT_DIRECTORY_INFORMATION)LocalBuffer;
TotalLength = sizeof(OBJECT_DIRECTORY_INFORMATION);
/* Start with 0 entries */
Count = 0;
CurrentEntry = 0;
/* Set default status and start looping */
Status = STATUS_NO_MORE_ENTRIES;
for (Hash = 0; Hash < 37; Hash++)
{
/* Get this entry and loop all of them */
Entry = Directory->HashBuckets[Hash];
while (Entry)
{
POBJECT_HEADER EntryHeader;
ULONG RequiredSize = sizeof(OBJECT_DIRECTORY_INFORMATION);
ULONG nDirectories = 0;
POBJECT_DIRECTORY_INFORMATION DirInfo = (POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer;
POBJECT_DIRECTORY_ENTRY DirectoryEntry;
ULONG i;
BOOLEAN StopIt = FALSE;
Status = STATUS_NO_MORE_ENTRIES;
KeEnterCriticalRegion();
ExAcquireResourceSharedLite(&Directory->Lock, TRUE);
for (i = 0; i < NUMBER_HASH_BUCKETS && !StopIt; i++)
/* Check if we should process this entry */
if (SkipEntries == CurrentEntry++)
{
DirectoryEntry = Directory->HashBuckets[i];
while (DirectoryEntry)
/* Get the header data */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Entry->Object);
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
/* Get the object name */
if (ObjectNameInfo)
{
NextEntry++;
if (SkipEntries == 0)
/* Use the one we have */
Name = ObjectNameInfo->Name;
}
else
{
/* Otherwise, use an empty one */
RtlInitEmptyUnicodeString(&Name, NULL, 0);
}
/* Calculate the length for this entry */
Length = sizeof(OBJECT_DIRECTORY_INFORMATION) +
Name.Length + sizeof(UNICODE_NULL) +
ObjectHeader->Type->Name.Length + sizeof(UNICODE_NULL);
/* Make sure this entry won't overflow */
if ((TotalLength + Length) > BufferLength)
{
/* Check if the caller wanted only an entry */
if (ReturnSingleEntry)
{
PUNICODE_STRING Name, Type;
ULONG EntrySize;
EntryHeader = OBJECT_TO_OBJECT_HEADER(DirectoryEntry->Object);
/* Calculate the size of the required buffer space for this entry */
Name = (OBJECT_HEADER_TO_NAME_INFO(EntryHeader)->Name.Length != 0 ? &OBJECT_HEADER_TO_NAME_INFO(EntryHeader)->Name : NULL);
Type = &EntryHeader->Type->Name;
EntrySize = sizeof(OBJECT_DIRECTORY_INFORMATION) +
((Name != NULL) ? ((ULONG)Name->Length + sizeof(WCHAR)) : 0) +
(ULONG)EntryHeader->Type->Name.Length + sizeof(WCHAR);
if (RequiredSize + EntrySize <= BufferLength)
{
/* The buffer is large enough to receive this entry. It would've
been much easier if the strings were directly appended to the
OBJECT_DIRECTORY_INFORMATION structured written into the buffer */
if (Name != NULL && Name->Length > 0)
DirInfo->ObjectName = *Name;
else
{
DirInfo->ObjectName.Length = DirInfo->ObjectName.MaximumLength = 0;
DirInfo->ObjectName.Buffer = NULL;
}
DirInfo->ObjectTypeName = *Type;
nDirectories++;
RequiredSize += EntrySize;
Status = STATUS_SUCCESS;
if (ReturnSingleEntry)
{
/* We're only supposed to query one entry, so bail and copy the
strings to the buffer */
StopIt = TRUE;
break;
}
DirInfo++;
}
else
{
if (ReturnSingleEntry)
{
/* The buffer is too small, so return the number of bytes that
would've been required for this query */
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 */
StopIt = TRUE;
break;
}
/* Then we'll fail and ask for more buffer */
TotalLength += Length;
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
/* Skip the entry */
SkipEntries--;
}
DirectoryEntry = DirectoryEntry->ChainLink;
}
}
if (!ReturnSingleEntry)
{
/* Check if there are more entries to enumerate but the buffer is already
full. Only tell this to the user if he queries multiple entries */
if (DirectoryEntry)
Status = STATUS_MORE_ENTRIES;
else
for (; i < NUMBER_HASH_BUCKETS; i++)
if (Directory->HashBuckets[i])
{
Status = STATUS_MORE_ENTRIES;
break;
}
}
if (NT_SUCCESS(Status) && nDirectories > 0)
{
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! */
for (DirInfo = (POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer;
nDirectories > 0;
nDirectories--, DirInfo++)
{
ULONG NameLength;
if (DirInfo->ObjectName.Length > 0)
{
RtlCopyMemory(strbuf,
DirInfo->ObjectName.Buffer,
DirInfo->ObjectName.Length);
/* Change the buffer pointer to the buffer */
DirInfo->ObjectName.Buffer = deststrbuf;
NameLength = DirInfo->ObjectName.Length / sizeof(WCHAR);
/* NULL-terminate the string */
strbuf[NameLength] = L'\0';
strbuf += NameLength + 1;
deststrbuf += NameLength + 1;
CopyBytes += (NameLength + 1) * sizeof(WCHAR);
/* Otherwise, we'll say we're done for now */
Status = STATUS_MORE_ENTRIES;
}
RtlCopyMemory(strbuf,
DirInfo->ObjectTypeName.Buffer,
DirInfo->ObjectTypeName.Length);
/* Change the buffer pointer to the buffer */
DirInfo->ObjectTypeName.Buffer = deststrbuf;
NameLength = DirInfo->ObjectTypeName.Length / sizeof(WCHAR);
/* NULL-terminate the string */
strbuf[NameLength] = L'\0';
strbuf += NameLength + 1;
deststrbuf += NameLength + 1;
CopyBytes += (NameLength + 1) * sizeof(WCHAR);
/* Decrease the entry since we didn't process */
CurrentEntry--;
goto Quickie;
}
/* Now fill in the buffer */
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;
/* Increase statistics */
TotalLength += Length;
DirectoryInfo++;
Count++;
/* If the caller only wanted an entry, bail out */
if (ReturnSingleEntry) goto Quickie;
/* Increase the key by one */
SkipEntries++;
}
ExReleaseResourceLite(&Directory->Lock);
KeLeaveCriticalRegion();
ObDereferenceObject(Directory);
if (NT_SUCCESS(Status) || ReturnSingleEntry)
{
_SEH_TRY
{
if (CopyBytes != 0)
{
RtlCopyMemory(Buffer,
TemporaryBuffer,
CopyBytes);
}
*Context = NextEntry;
if(ReturnLength != NULL)
{
*ReturnLength = RequiredSize;
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
ExFreePool(TemporaryBuffer);
}
else
{
Status = STATUS_INSUFFICIENT_RESOURCES;
}
/* Move to the next directory */
Entry = Entry->ChainLink;
}
Quickie:
/* Make sure we got success */
if (NT_SUCCESS(Status))
{
/* We need to parse all the entries and convert absolute to relative */
DPRINT1("NOT FULLY IMPLEMENTED\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
/* Copy the buffer */
RtlMoveMemory(Buffer,
LocalBuffer,
(TotalLength <= BufferLength) ?
TotalLength : BufferLength);
/* Check if the caller requested the return length and return it*/
if (ReturnLength) *ReturnLength = TotalLength;
}
/* Dereference the directory and free our buffer */
ObDereferenceObject(Directory);
ExFreePool(LocalBuffer);
/* Return status to caller */
return Status;
}

View file

@ -94,14 +94,14 @@ CsrPopulateDosDevicesDirectory(IN HANDLE hDosDevicesDirectory,
if (NT_SUCCESS(Status))
{
/* Make sure it has a name */
if (!QueryBuffer->ObjectName.Buffer[0]) continue;
if (!QueryBuffer->Name.Buffer[0]) continue;
/* Check if it's actually a symbolic link */
if (wcscmp(QueryBuffer->ObjectTypeName.Buffer, SYMLINK_NAME))
if (wcscmp(QueryBuffer->TypeName.Buffer, SYMLINK_NAME))
{
/* It is, open it */
InitializeObjectAttributes(&ObjectAttributes,
&QueryBuffer->ObjectName,
&QueryBuffer->Name,
OBJ_CASE_INSENSITIVE,
NULL,
hDirectory);

View file

@ -1235,10 +1235,10 @@ BuildWindowStationNameList(
*/
ReturnLength = sizeof(DWORD);
EntryCount = 0;
for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer; 0 != DirEntry->ObjectName.Length;
for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer; 0 != DirEntry->Name.Length;
DirEntry++)
{
ReturnLength += DirEntry->ObjectName.Length + sizeof(WCHAR);
ReturnLength += DirEntry->Name.Length + sizeof(WCHAR);
EntryCount++;
}
DPRINT("Required size: %d Entry count: %d\n", ReturnLength, EntryCount);
@ -1282,10 +1282,10 @@ BuildWindowStationNameList(
lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(DWORD));
NullWchar = L'\0';
for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer; 0 != DirEntry->ObjectName.Length;
for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer; 0 != DirEntry->Name.Length;
DirEntry++)
{
Status = MmCopyToCaller(lpBuffer, DirEntry->ObjectName.Buffer, DirEntry->ObjectName.Length);
Status = MmCopyToCaller(lpBuffer, DirEntry->Name.Buffer, DirEntry->Name.Length);
if (! NT_SUCCESS(Status))
{
if (Buffer != InitialBuffer)
@ -1294,7 +1294,7 @@ BuildWindowStationNameList(
}
return Status;
}
lpBuffer = (PVOID) ((PCHAR) lpBuffer + DirEntry->ObjectName.Length);
lpBuffer = (PVOID) ((PCHAR) lpBuffer + DirEntry->Name.Length);
Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR));
if (! NT_SUCCESS(Status))
{