353 lines
9.2 KiB
C
353 lines
9.2 KiB
C
/*++
|
||
|
||
Copyright (c) 1995 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
proc.c
|
||
|
||
Abstract:
|
||
|
||
Code for dumping information about processes using the NT API rather than
|
||
the win32 API.
|
||
|
||
Environment:
|
||
|
||
User mode only
|
||
|
||
Revision History:
|
||
|
||
03-26-96 : Created
|
||
|
||
--*/
|
||
|
||
//
|
||
// this module may be compiled at warning level 4 with the following
|
||
// warnings disabled:
|
||
//
|
||
|
||
#pragma warning(disable:4200) // array[0]
|
||
#pragma warning(disable:4201) // nameless struct/unions
|
||
#pragma warning(disable:4214) // bit fields other than int
|
||
|
||
#include <nt.h>
|
||
#include <ntrtl.h>
|
||
#include <nturtl.h>
|
||
|
||
#include <windows.h>
|
||
|
||
#include <string.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
|
||
#include <assert.h>
|
||
|
||
#define PROCESS_BUFFER_INCREMENT (16 * 4096)
|
||
|
||
PSYSTEM_PROCESS_INFORMATION ProcessInfo = NULL;
|
||
DWORD ProcessInfoLength;
|
||
|
||
|
||
VOID
|
||
GetAllProcessInfo(
|
||
VOID
|
||
)
|
||
{
|
||
PSYSTEM_PROCESS_INFORMATION buffer;
|
||
DWORD bufferSize = 1 * PROCESS_BUFFER_INCREMENT;
|
||
|
||
NTSTATUS status;
|
||
|
||
assert(ProcessInfo == NULL);
|
||
|
||
do {
|
||
buffer = LocalAlloc(LMEM_FIXED, bufferSize);
|
||
|
||
if(buffer == NULL) {
|
||
return;
|
||
}
|
||
|
||
status = NtQuerySystemInformation(SystemProcessInformation,
|
||
buffer,
|
||
bufferSize,
|
||
&ProcessInfoLength);
|
||
|
||
if(status == STATUS_INFO_LENGTH_MISMATCH) {
|
||
|
||
LocalFree(buffer);
|
||
bufferSize += PROCESS_BUFFER_INCREMENT;
|
||
continue;
|
||
}
|
||
|
||
} while(status == STATUS_INFO_LENGTH_MISMATCH);
|
||
|
||
if(NT_SUCCESS(status)) {
|
||
ProcessInfo = buffer;
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
VOID
|
||
PrintProcessInfo(
|
||
DWORD_PTR ProcessId
|
||
)
|
||
{
|
||
PSYSTEM_PROCESS_INFORMATION info;
|
||
|
||
if(ProcessInfo == NULL) {
|
||
return;
|
||
}
|
||
|
||
info = ProcessInfo;
|
||
|
||
do {
|
||
|
||
if(ProcessId == (DWORD_PTR) info->UniqueProcessId) {
|
||
|
||
printf(": %.*S",
|
||
(info->ImageName.Length / 2),
|
||
info->ImageName.Buffer);
|
||
|
||
break;
|
||
}
|
||
|
||
info = (PSYSTEM_PROCESS_INFORMATION) (((ULONG_PTR) info) +
|
||
info->NextEntryOffset);
|
||
} while((ULONG_PTR) info <= (ULONG_PTR) ProcessInfo + ProcessInfoLength);
|
||
|
||
return;
|
||
}
|
||
|
||
#if 0
|
||
|
||
DWORD
|
||
QueryDirectory(
|
||
IN PSTRING DirectoryName
|
||
)
|
||
{
|
||
NTSTATUS Status;
|
||
HANDLE DirectoryHandle, LinkHandle;
|
||
ULONG Context = 0;
|
||
ULONG i, ReturnedLength;
|
||
UNICODE_STRING LinkTarget;
|
||
|
||
POBJECT_DIRECTORY_INFORMATION DirInfo;
|
||
POBJECT_NAME_INFORMATION NameInfo;
|
||
OBJECT_ATTRIBUTES Attributes;
|
||
UNICODE_STRING UnicodeString;
|
||
|
||
//
|
||
// Perform initial setup
|
||
//
|
||
|
||
RtlZeroMemory( Buffer, BUFFERSIZE );
|
||
|
||
//
|
||
// Open the directory for list directory access
|
||
//
|
||
|
||
Status = RtlAnsiStringToUnicodeString(
|
||
&UnicodeString,
|
||
DirectoryName,
|
||
TRUE
|
||
);
|
||
|
||
ASSERT(NT_SUCCESS(Status));
|
||
|
||
InitializeObjectAttributes(&Attributes,
|
||
&UnicodeString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL);
|
||
|
||
Status = NtOpenDirectoryObject(&DirectoryHandle,
|
||
DIRECTORY_QUERY,
|
||
&Attributes);
|
||
|
||
if(!NT_SUCCESS(Status)) {
|
||
if (Status == STATUS_OBJECT_TYPE_MISMATCH) {
|
||
printf("%Z is not a valid Object Directory Object name\n",
|
||
DirectoryName );
|
||
} else {
|
||
printf("Error %#08lx opening %Z\n", Status, DirectoryName);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Query the entire directory in one sweep
|
||
//
|
||
|
||
NumberOfDirEntries = 0;
|
||
for (Status = NtQueryDirectoryObject( DirectoryHandle,
|
||
&Buffer,
|
||
BUFFERSIZE,
|
||
FALSE,
|
||
FALSE,
|
||
&Context,
|
||
&ReturnedLength );
|
||
NT_SUCCESS( Status );
|
||
Status = NtQueryDirectoryObject( DirectoryHandle,
|
||
&Buffer,
|
||
BUFFERSIZE,
|
||
FALSE,
|
||
FALSE,
|
||
&Context,
|
||
&ReturnedLength ) ) {
|
||
|
||
//
|
||
// Check the status of the operation.
|
||
//
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
if (Status != STATUS_NO_MORE_FILES) {
|
||
Error( Status, Status );
|
||
}
|
||
break;
|
||
}
|
||
|
||
//
|
||
// For every record in the buffer type out the directory information
|
||
//
|
||
|
||
//
|
||
// Point to the first record in the buffer, we are guaranteed to have
|
||
// one otherwise Status would have been No More Files
|
||
//
|
||
|
||
DirInfo = (POBJECT_DIRECTORY_INFORMATION) &Buffer[0];
|
||
|
||
while (TRUE) {
|
||
|
||
//
|
||
// Check if there is another record. If there isn't, then get out
|
||
// of the loop now
|
||
//
|
||
|
||
if (DirInfo->Name.Length == 0) {
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Print out information about the file
|
||
//
|
||
|
||
if (NumberOfDirEntries >= MAX_DIR_ENTRIES) {
|
||
printf( "OBJDIR: Too many directory entries.\n" );
|
||
exit( 1 );
|
||
}
|
||
|
||
DirEntries[ NumberOfDirEntries ].Name = RtlAllocateHeap( RtlProcessHeap(),
|
||
HEAP_ZERO_MEMORY,
|
||
DirInfo->Name.Length +
|
||
sizeof( UNICODE_NULL )
|
||
);
|
||
DirEntries[ NumberOfDirEntries ].Type = RtlAllocateHeap( RtlProcessHeap(),
|
||
HEAP_ZERO_MEMORY,
|
||
DirInfo->TypeName.Length +
|
||
sizeof( UNICODE_NULL )
|
||
);
|
||
memmove( DirEntries[ NumberOfDirEntries ].Name,
|
||
DirInfo->Name.Buffer,
|
||
DirInfo->Name.Length
|
||
);
|
||
memmove( DirEntries[ NumberOfDirEntries ].Type,
|
||
DirInfo->TypeName.Buffer,
|
||
DirInfo->TypeName.Length
|
||
);
|
||
|
||
NumberOfDirEntries++;
|
||
|
||
//
|
||
// There is another record so advance DirInfo to the next entry
|
||
//
|
||
|
||
DirInfo = (POBJECT_DIRECTORY_INFORMATION) (((PUCHAR) DirInfo) +
|
||
sizeof( OBJECT_DIRECTORY_INFORMATION ) );
|
||
|
||
}
|
||
|
||
RtlZeroMemory( Buffer, BUFFERSIZE );
|
||
|
||
}
|
||
|
||
|
||
qsort( DirEntries,
|
||
NumberOfDirEntries,
|
||
sizeof( DIR_ENTRY ),
|
||
CompareDirEntry
|
||
);
|
||
for (i=0; i<NumberOfDirEntries; i++) {
|
||
printf( "%-32ws ", DirEntries[ i ].Name);
|
||
if (CompoundLineOutput) {
|
||
printf("\n ");
|
||
}
|
||
printf( "%ws", DirEntries[ i ].Type );
|
||
|
||
if (!wcscmp( DirEntries[ i ].Type, L"SymbolicLink" )) {
|
||
RtlInitUnicodeString( &UnicodeString, DirEntries[ i ].Name );
|
||
InitializeObjectAttributes( &Attributes,
|
||
&UnicodeString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
DirectoryHandle,
|
||
NULL );
|
||
Status = NtOpenSymbolicLinkObject( &LinkHandle,
|
||
SYMBOLIC_LINK_QUERY,
|
||
&Attributes
|
||
);
|
||
if (NT_SUCCESS( Status )) {
|
||
LinkTarget.Buffer = LinkTargetBuffer;
|
||
LinkTarget.Length = 0;
|
||
LinkTarget.MaximumLength = sizeof( LinkTargetBuffer );
|
||
Status = NtQuerySymbolicLinkObject( LinkHandle,
|
||
&LinkTarget,
|
||
NULL
|
||
);
|
||
NtClose( LinkHandle );
|
||
}
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
printf( " - unable to query link target (Status == %09X)\n", Status );
|
||
}
|
||
else {
|
||
printf( " - %wZ\n", &LinkTarget );
|
||
}
|
||
}
|
||
else {
|
||
printf( "\n" );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Output final messages
|
||
//
|
||
|
||
if (NumberOfDirEntries == 0) {
|
||
printf( "no entries\n" );
|
||
}
|
||
else
|
||
if (NumberOfDirEntries == 1) {
|
||
printf( "\n1 entry\n" );
|
||
}
|
||
else {
|
||
printf( "\n%ld entries\n", NumberOfDirEntries );
|
||
}
|
||
|
||
//
|
||
// Now close the directory object
|
||
//
|
||
|
||
(VOID) NtClose( DirectoryHandle );
|
||
|
||
//
|
||
// And return to our caller
|
||
//
|
||
|
||
return;
|
||
|
||
}
|
||
#endif
|
||
|