mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 19:26:32 +00:00
NtQueryDirectoryObject rewritten.
apps/objdir.c fixed to work under nt4sp6a AND reactos. svn path=/trunk/; revision=1847
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/* $Id: objdir.c,v 1.5 2000/08/11 17:18:31 ea Exp $
|
||||
/* $Id: objdir.c,v 1.6 2001/05/01 21:43:45 ea Exp $
|
||||
*
|
||||
* DESCRIPTION: Object Manager Simple Explorer
|
||||
* PROGRAMMER: David Welch
|
||||
@@ -9,6 +9,10 @@
|
||||
* 2000-08-11 (ea)
|
||||
* Added symbolic link expansion.
|
||||
* (tested under nt4sp4/x86)
|
||||
* 2001-05-01 (ea)
|
||||
* Fixed entries counter. Added more
|
||||
* error codes check. Removed wprintf,
|
||||
* because it does not work in .17.
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
@@ -17,9 +21,24 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
BYTE DirectoryEntry [(2 * MAX_PATH) + sizeof (OBJDIR_INFORMATION)];
|
||||
BYTE DirectoryEntry [32768];
|
||||
POBJDIR_INFORMATION pDirectoryEntry = (POBJDIR_INFORMATION) DirectoryEntry;
|
||||
|
||||
static
|
||||
PCHAR
|
||||
STDCALL
|
||||
RawUszAsz (
|
||||
PWCHAR szU,
|
||||
PCHAR szA
|
||||
)
|
||||
{
|
||||
register PCHAR a = szA;
|
||||
|
||||
while (*szU) {*szA++ = (CHAR) (0x00ff & * szU++);}
|
||||
*szA = '\0';
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
const char *
|
||||
@@ -40,6 +59,10 @@ StatusToName (NTSTATUS Status)
|
||||
return "STATUS_OBJECT_NAME_NOT_FOUND";
|
||||
case STATUS_PATH_SYNTAX_BAD:
|
||||
return "STATUS_PATH_SYNTAX_BAD";
|
||||
case STATUS_NO_MORE_ENTRIES:
|
||||
return "STATUS_NO_MORE_ENTRIES";
|
||||
case STATUS_UNSUCCESSFUL:
|
||||
return "STATUS_UNSUCCESSFUL";
|
||||
}
|
||||
sprintf (RawValue, "0x%08lx", Status);
|
||||
return (const char *) RawValue;
|
||||
@@ -127,7 +150,8 @@ int main(int argc, char* argv[])
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
NTSTATUS Status;
|
||||
HANDLE DirectoryHandle;
|
||||
ULONG BytesReturned = 0;
|
||||
ULONG Context = 0;
|
||||
ULONG ReturnLength = 0;
|
||||
ULONG EntryCount = 0;
|
||||
|
||||
/* For expanding symbolic links */
|
||||
@@ -187,6 +211,7 @@ int main(int argc, char* argv[])
|
||||
);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
printf ("\n Directory of %s\n\n", argv[1]);
|
||||
/*
|
||||
* Enumerate each item in the directory.
|
||||
*/
|
||||
@@ -194,10 +219,10 @@ int main(int argc, char* argv[])
|
||||
DirectoryHandle,
|
||||
pDirectoryEntry,
|
||||
sizeof DirectoryEntry,
|
||||
TRUE,
|
||||
TRUE,
|
||||
& BytesReturned,
|
||||
& EntryCount
|
||||
FALSE,/* ReturnSingleEntry */
|
||||
TRUE, /* RestartScan */
|
||||
& Context,
|
||||
& ReturnLength
|
||||
);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
@@ -208,9 +233,12 @@ int main(int argc, char* argv[])
|
||||
NtClose (DirectoryHandle);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
wprintf (L"%d entries:\n", EntryCount);
|
||||
while (STATUS_NO_MORE_ENTRIES != Status)
|
||||
while (0 != pDirectoryEntry->ObjectTypeName.Length)
|
||||
{
|
||||
CHAR ObjectNameA [MAX_PATH];
|
||||
CHAR TypeNameA [MAX_PATH];
|
||||
CHAR TargetNameA [MAX_PATH];
|
||||
|
||||
if (0 == wcscmp (L"SymbolicLink", pDirectoryEntry->ObjectTypeName.Buffer))
|
||||
{
|
||||
if (TRUE == ExpandSymbolicLink (
|
||||
@@ -220,40 +248,37 @@ int main(int argc, char* argv[])
|
||||
)
|
||||
)
|
||||
{
|
||||
wprintf (
|
||||
L"%-16s %s -> %s\n",
|
||||
pDirectoryEntry->ObjectTypeName.Buffer,
|
||||
pDirectoryEntry->ObjectName.Buffer,
|
||||
TargetObjectName.Buffer
|
||||
|
||||
printf (
|
||||
"%-16s %s -> %s\n",
|
||||
RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA),
|
||||
RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA),
|
||||
RawUszAsz (TargetObjectName.Buffer, TargetNameA)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
wprintf (
|
||||
L"%-16s %s -> (error!)\n",
|
||||
pDirectoryEntry->ObjectTypeName.Buffer,
|
||||
pDirectoryEntry->ObjectName.Buffer
|
||||
printf (
|
||||
"%-16s %s -> (error!)\n",
|
||||
RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA),
|
||||
RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA)
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wprintf (
|
||||
L"%-16s %s\n",
|
||||
pDirectoryEntry->ObjectTypeName.Buffer,
|
||||
pDirectoryEntry->ObjectName.Buffer
|
||||
printf (
|
||||
"%-16s %s\n",
|
||||
RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA),
|
||||
RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA)
|
||||
);
|
||||
}
|
||||
Status = NtQueryDirectoryObject (
|
||||
DirectoryHandle,
|
||||
pDirectoryEntry,
|
||||
sizeof DirectoryEntry,
|
||||
TRUE,
|
||||
FALSE,
|
||||
& BytesReturned,
|
||||
& EntryCount
|
||||
);
|
||||
++ EntryCount;
|
||||
++ pDirectoryEntry;
|
||||
|
||||
|
||||
}
|
||||
printf ("\n\t%d object(s)\n", EntryCount);
|
||||
/*
|
||||
* Free any resource.
|
||||
*/
|
||||
|
||||
+172
-120
@@ -1,4 +1,4 @@
|
||||
/* $Id: dirobj.c,v 1.9 2000/10/22 16:36:52 ekohl Exp $
|
||||
/* $Id: dirobj.c,v 1.10 2001/05/01 21:43:45 ea Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
@@ -81,29 +81,32 @@ NTSTATUS STDCALL NtOpenDirectoryObject(PHANDLE DirectoryHandle,
|
||||
* NtQueryDirectoryObject
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Reads information from a namespace directory.
|
||||
* Reads information from a directory in the system namespace.
|
||||
*
|
||||
* ARGUMENTS
|
||||
* DirObjHandle
|
||||
* Handle, obtained with NtOpenDirectoryObject(), which
|
||||
* must grant DIRECTORY_QUERY access to the directory
|
||||
* object.
|
||||
*
|
||||
* DirObjInformation (OUT)
|
||||
* Buffer to hold the data read.
|
||||
*
|
||||
* BufferLength
|
||||
* Size of the buffer in bytes.
|
||||
*
|
||||
* GetNextIndex
|
||||
* If TRUE then set ObjectIndex to the index of the
|
||||
* next object.
|
||||
* If FALSE then set ObjectIndex to the number of
|
||||
* objects in the directory.
|
||||
* ReturnSingleEntry
|
||||
* When TRUE, only 1 entry is written in DirObjInformation;
|
||||
* otherwise as many as will fit in the buffer.
|
||||
*
|
||||
* IgnoreInputIndex
|
||||
* RestartScan
|
||||
* If TRUE start reading at index 0.
|
||||
* If FALSE start reading at the index specified
|
||||
* by object index.
|
||||
* by object index *ObjectIndex.
|
||||
*
|
||||
* ObjectIndex
|
||||
* Zero based index into the directory, interpretation
|
||||
* depends on IgnoreInputIndex and GetNextIndex.
|
||||
* depends on RestartScan.
|
||||
*
|
||||
* DataWritten (OUT)
|
||||
* Caller supplied storage for the number of bytes
|
||||
@@ -111,134 +114,183 @@ NTSTATUS STDCALL NtOpenDirectoryObject(PHANDLE DirectoryHandle,
|
||||
*
|
||||
* RETURN VALUE
|
||||
* Status.
|
||||
*
|
||||
* REVISIONS
|
||||
* 2001-05-01 (ea)
|
||||
* Changed 4th, and 5th parameter names after
|
||||
* G.Nebbett "WNT/W2k Native API Reference".
|
||||
* Mostly rewritten.
|
||||
*/
|
||||
NTSTATUS STDCALL NtQueryDirectoryObject (IN HANDLE DirObjHandle,
|
||||
OUT POBJDIR_INFORMATION
|
||||
DirObjInformation,
|
||||
IN ULONG BufferLength,
|
||||
IN BOOLEAN GetNextIndex,
|
||||
IN BOOLEAN IgnoreInputIndex,
|
||||
IN BOOLEAN ReturnSingleEntry,
|
||||
IN BOOLEAN RestartScan,
|
||||
IN OUT PULONG ObjectIndex,
|
||||
OUT PULONG DataWritten OPTIONAL)
|
||||
{
|
||||
PDIRECTORY_OBJECT dir = NULL;
|
||||
PLIST_ENTRY current_entry;
|
||||
POBJECT_HEADER current;
|
||||
ULONG i = 0;
|
||||
ULONG EntriesToSkip;
|
||||
NTSTATUS Status;
|
||||
ULONG SpaceRequired;
|
||||
ULONG FirstFree;
|
||||
|
||||
DPRINT("NtQueryDirectoryObject(DirObjHandle %x)\n", DirObjHandle);
|
||||
PDIRECTORY_OBJECT dir = NULL;
|
||||
PLIST_ENTRY current_entry = NULL;
|
||||
POBJECT_HEADER current = NULL;
|
||||
ULONG i = 0;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
DWORD DirectoryCount = 0;
|
||||
DWORD DirectorySize = 0;
|
||||
ULONG SpaceLeft = BufferLength;
|
||||
ULONG SpaceRequired = 0;
|
||||
ULONG NameLength = 0;
|
||||
ULONG TypeNameLength = 0;
|
||||
POBJDIR_INFORMATION current_odi = DirObjInformation;
|
||||
PBYTE FirstFree = (PBYTE) DirObjInformation;
|
||||
|
||||
Status = ObReferenceObjectByHandle(DirObjHandle,
|
||||
|
||||
DPRINT("NtQueryDirectoryObject(DirObjHandle %x)\n", DirObjHandle);
|
||||
|
||||
/* FIXME: if previous mode == user, use ProbeForWrite
|
||||
* on user params. */
|
||||
|
||||
/* Reference the DIRECTORY_OBJECT */
|
||||
Status = ObReferenceObjectByHandle(DirObjHandle,
|
||||
DIRECTORY_QUERY,
|
||||
ObDirectoryType,
|
||||
UserMode,
|
||||
(PVOID*)&dir,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Optionally, skip over some entries at the start of the directory
|
||||
*/
|
||||
if (!IgnoreInputIndex)
|
||||
{
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return (Status);
|
||||
}
|
||||
/* Check ObjectIndex is not NULL */
|
||||
if (NULL == ObjectIndex)
|
||||
{
|
||||
return (STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
/*
|
||||
* Compute the number of directory entries
|
||||
* and the size of the array (in bytes).
|
||||
* One more entry marks the end of the array.
|
||||
*/
|
||||
for ( current_entry = dir->head.Flink;
|
||||
(current_entry != & dir->head);
|
||||
current_entry = current_entry->Flink
|
||||
)
|
||||
{
|
||||
++ DirectoryCount;
|
||||
}
|
||||
DirectorySize = (DirectoryCount + 1) * sizeof (OBJDIR_INFORMATION);
|
||||
if (DirectorySize >= SpaceLeft)
|
||||
{
|
||||
return (STATUS_BUFFER_TOO_SMALL);
|
||||
}
|
||||
/*
|
||||
* Optionally, skip over some entries at the start of the directory
|
||||
* (use *ObjectIndex value)
|
||||
*/
|
||||
current_entry = dir->head.Flink;
|
||||
if (FALSE == RestartScan)
|
||||
{
|
||||
/* RestartScan == FALSE */
|
||||
register ULONG EntriesToSkip = *ObjectIndex;
|
||||
|
||||
CHECKPOINT;
|
||||
|
||||
EntriesToSkip = *ObjectIndex;
|
||||
i = 0;
|
||||
current_entry = dir->head.Flink;
|
||||
|
||||
while ((i < EntriesToSkip) && (current_entry != &dir->head))
|
||||
for ( ;
|
||||
((EntriesToSkip ++) && (current_entry != & dir->head));
|
||||
current_entry = current_entry->Flink
|
||||
);
|
||||
if ((EntriesToSkip) && (current_entry == & dir->head))
|
||||
{
|
||||
current_entry = current_entry->Flink;
|
||||
i++;
|
||||
return (STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
current_entry = dir->head.Flink;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we have reached the end of the directory
|
||||
*/
|
||||
if (current_entry != &dir->head)
|
||||
{
|
||||
*DataWritten = 0;
|
||||
return(STATUS_NO_MORE_ENTRIES);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the current entry into the buffer
|
||||
*/
|
||||
FirstFree = sizeof(OBJDIR_INFORMATION);
|
||||
|
||||
current = CONTAINING_RECORD(current_entry, OBJECT_HEADER, Entry);
|
||||
|
||||
SpaceRequired = (wcslen(current->Name.Buffer) + 1) * 2;
|
||||
SpaceRequired = SpaceRequired +
|
||||
((wcslen(current->ObjectType->TypeName.Buffer) + 1) * 2);
|
||||
SpaceRequired = SpaceRequired + sizeof(OBJDIR_INFORMATION);
|
||||
|
||||
if (SpaceRequired <= BufferLength)
|
||||
{
|
||||
|
||||
DirObjInformation->ObjectName.Length =
|
||||
current->Name.Length;
|
||||
DirObjInformation->ObjectName.MaximumLength =
|
||||
current->Name.Length;
|
||||
DirObjInformation->ObjectName.Buffer =
|
||||
(((PVOID)DirObjInformation) + FirstFree);
|
||||
FirstFree = FirstFree + (wcslen(current->Name.Buffer + 1) * 2);
|
||||
wcscpy(DirObjInformation->ObjectName.Buffer,
|
||||
current->Name.Buffer);
|
||||
|
||||
DirObjInformation->ObjectTypeName.Length =
|
||||
current->ObjectType->TypeName.Length;
|
||||
DirObjInformation->ObjectTypeName.MaximumLength =
|
||||
current->ObjectType->TypeName.Length;
|
||||
DirObjInformation->ObjectName.Buffer =
|
||||
(((PVOID)DirObjInformation) + FirstFree);
|
||||
FirstFree = FirstFree +
|
||||
(wcslen(current->ObjectType->TypeName.Buffer + 1) * 2);
|
||||
wcscpy(DirObjInformation->ObjectTypeName.Buffer,
|
||||
current->ObjectType->TypeName.Buffer);
|
||||
|
||||
*DataWritten = SpaceRequired;
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store into ObjectIndex
|
||||
*/
|
||||
if (GetNextIndex)
|
||||
{
|
||||
*ObjectIndex = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
current_entry = dir->head.Flink;
|
||||
while (current_entry != (&dir->head))
|
||||
{
|
||||
current_entry = current_entry->Flink;
|
||||
i++;
|
||||
}
|
||||
*ObjectIndex = i;
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
/*
|
||||
* Initialize the array of OBJDIR_INFORMATION.
|
||||
*/
|
||||
RtlZeroMemory (FirstFree, DirectorySize);
|
||||
/*
|
||||
* Move FirstFree to point to the Unicode strings area
|
||||
*/
|
||||
FirstFree += DirectorySize;
|
||||
/*
|
||||
* Compute how much space is left after allocating the
|
||||
* array in the user buffer.
|
||||
*/
|
||||
SpaceLeft -= DirectorySize;
|
||||
/* Scan the directory */
|
||||
do {
|
||||
/*
|
||||
* Check if we reached the end of the directory.
|
||||
*/
|
||||
if (current_entry == & dir->head)
|
||||
{
|
||||
/* Any data? */
|
||||
if (i) break; /* DONE */
|
||||
/* FIXME: better error handling here! */
|
||||
return (STATUS_NO_MORE_ENTRIES);
|
||||
}
|
||||
/*
|
||||
* Compute the current OBJECT_HEADER memory
|
||||
* object's address.
|
||||
*/
|
||||
current = CONTAINING_RECORD(current_entry, OBJECT_HEADER, Entry);
|
||||
/*
|
||||
* Compute the space required in the user buffer to copy
|
||||
* the data from the current object:
|
||||
*
|
||||
* Name (WCHAR) 0 TypeName (WCHAR) 0
|
||||
*/
|
||||
NameLength = (wcslen (current->Name.Buffer) * sizeof (WCHAR));
|
||||
TypeNameLength = (wcslen (current->ObjectType->TypeName.Buffer) * sizeof (WCHAR));
|
||||
SpaceRequired =
|
||||
(NameLength + sizeof (WCHAR))
|
||||
+ (TypeNameLength + sizeof (WCHAR));
|
||||
/*
|
||||
* Check for free space in the user buffer.
|
||||
*/
|
||||
if (SpaceRequired >= SpaceLeft)
|
||||
{
|
||||
return (STATUS_BUFFER_TOO_SMALL);
|
||||
}
|
||||
/*
|
||||
* Copy the current directory entry's data into the buffer
|
||||
* and update the OBJDIR_INFORMATION entry in the array.
|
||||
*/
|
||||
/* --- Object's name --- */
|
||||
current_odi->ObjectName.Length = NameLength;
|
||||
current_odi->ObjectName.MaximumLength = (NameLength + sizeof (WCHAR));
|
||||
current_odi->ObjectName.Buffer = (PWCHAR) FirstFree;
|
||||
wcscpy ((PWCHAR) FirstFree, current->Name.Buffer);
|
||||
FirstFree += (current_odi->ObjectName.MaximumLength);
|
||||
/* --- Object type's name --- */
|
||||
current_odi->ObjectTypeName.Length = TypeNameLength;
|
||||
current_odi->ObjectTypeName.MaximumLength = (TypeNameLength + sizeof (WCHAR));
|
||||
current_odi->ObjectTypeName.Buffer = (PWCHAR) FirstFree;
|
||||
wcscpy ((PWCHAR) FirstFree, current->ObjectType->TypeName.Buffer);
|
||||
FirstFree += (current_odi->ObjectTypeName.MaximumLength);
|
||||
/* Next entry in the array */
|
||||
++ current_odi;
|
||||
/* Decrease the space left count */
|
||||
SpaceLeft -= SpaceRequired;
|
||||
/* Increase the object index number */
|
||||
++ i;
|
||||
/* Next object in the directory */
|
||||
current_entry = current_entry->Flink;
|
||||
|
||||
} while (FALSE == ReturnSingleEntry);
|
||||
/*
|
||||
* Store current index in ObjectIndex
|
||||
*/
|
||||
*ObjectIndex = i;
|
||||
/*
|
||||
* Report to the caller how much bytes
|
||||
* we wrote in the user buffer.
|
||||
*/
|
||||
if (NULL != DataWritten)
|
||||
{
|
||||
*DataWritten = (BufferLength - SpaceLeft);
|
||||
}
|
||||
return (STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user