Dear Don Burn,
Thanks you’re interested in this topic.
As I’ve mentioned above I need to convert
process handle to process name in kernel mode.
May I ask you another thing ?
I guess I find something that will help me.
I’m using undocumented NtQuerySystemInformation,
but it works in NT 4.0 (SP6), 2K (SP4), XP and
2K3 (I checked up) in user mode.
I don’t know rules of this forum: I guess here I can’t
post my source code, but I will do it because I have to
realize it so quickly :(.
So, please take a look at (maybe it will be interesting for you):
/*----------------------------------------CUT LINE ------------------------------------------------*/
#include <tchar.h>
#include <windows.h>
#include <conio.h>
/* Common ntddk.h types /
typedef LONG NTSTATUS;
typedef LONG KPRIORITY;
#define NT_SUCCESS(_status) ((NTSTATUS)(_status) >= 0)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
/ Undocumented value /
#define SystemProcessesAndThreadsInformation 5
/ Common ntddk.h types /
typedef struct _CLIENT_ID {
DWORD UniqueProcess;
DWORD UniqueThread;
} CLIENT_ID;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef struct _VM_COUNTERS {
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG PageFaultCount;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
} VM_COUNTERS;
/ Undocumented structures for NtQuerySystemInformation /
typedef struct _SYSTEM_THREADS {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
LONG State;
LONG WaitReason;
} SYSTEM_THREADS, * PSYSTEM_THREADS;
typedef struct _SYSTEM_PROCESSES {
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved1[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
KPRIORITY BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
VM_COUNTERS VmCounters;
#if _WIN32_WINNT >= 0x500
IO_COUNTERS IoCounters;
#endif
SYSTEM_THREADS Threads[1];
} SYSTEM_PROCESSES, * PSYSTEM_PROCESSES;
/ Common ntddk.h types for NtQueryInformation */
#define ProcessBasicInformation 0
typedef struct _PEB *PPEB;
typedef struct _PROCESS_BASIC_INFORMATION {
NTSTATUS ExitStatus;
PPEB PebBaseAddress;
KAFFINITY AffinityMask;
KPRIORITY BasePriority;
ULONG UniqueProcessId;
ULONG InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION;
typedef PROCESS_BASIC_INFORMATION PPROCESS_BASIC_INFORMATION;
TCHAR g_szProcessName[MAX_PATH];
BOOL ProcessHandle2ProcessName(HANDLE hProcess) {
HINSTANCE hNtDll;
NTSTATUS ntStatus;
ULONG cbBuffer = 0x8000;
PVOID pBuffer = NULL;
typedef NTSTATUS (WINAPI PFNZWQUERYSYSTEMINFORMATION)(
UINT, PVOID, ULONG, PULONG);
PFNZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;
typedef NTSTATUS (WINAPI PFNZWQUERYINFORMATIONPROCESS)(
HANDLE, UINT, PVOID, ULONG, PULONG);
PFNZWQUERYINFORMATIONPROCESS ZwQueryInformationProcess = NULL;
HANDLE hHeap;
PCWSTR pszProcessName;
PSYSTEM_PROCESSES pProcesses;
PROCESS_BASIC_INFORMATION pbi;
hNtDll = GetModuleHandle(_T(“ntdll.dll”));
if (hNtDll == NULL)
return -1;
ZwQuerySystemInformation = (PFNZWQUERYSYSTEMINFORMATION)
GetProcAddress(hNtDll, “ZwQuerySystemInformation”);
ZwQueryInformationProcess = (PFNZWQUERYINFORMATIONPROCESS)
GetProcAddress(hNtDll, “ZwQueryInformationProcess”);
if (ZwQuerySystemInformation == NULL
|| ZwQueryInformationProcess == NULL)
return FALSE;
if (!NT_SUCCESS(ZwQueryInformationProcess(
hProcess, ProcessBasicInformation, &pbi,
sizeof(PROCESS_BASIC_INFORMATION), 0)))
return FALSE;
/ HOW IT WILL BE REALIZED IN KERNEL MODE ?
- I MEAN HEAP OPERATIONS/
/ Getting process heap /
hHeap = GetProcessHeap();
/ Getting buffer size /
do {
pBuffer = HeapAlloc(hHeap, 0, cbBuffer);
if (pBuffer == NULL)
return FALSE;
ntStatus = ZwQuerySystemInformation(
SystemProcessesAndThreadsInformation,
pBuffer, cbBuffer, NULL);
if (ntStatus == STATUS_INFO_LENGTH_MISMATCH) {
HeapFree(hHeap, 0, pBuffer);
cbBuffer = 2;
} else if (!NT_SUCCESS(ntStatus)) {
HeapFree(hHeap, 0, pBuffer);
return FALSE;
}
} while (ntStatus == STATUS_INFO_LENGTH_MISMATCH);
pProcesses = (PSYSTEM_PROCESSES)(pBuffer);
for (;
{
pszProcessName = pProcesses->ProcessName.Buffer;
if (pszProcessName == NULL)
pszProcessName = L"Idle";
if (pbi.UniqueProcessId == pProcesses->ProcessId) {
#ifdef UNICODE
lstrcpyW(g_szProcessName, pszProcessName);
#else
WideCharToMultiByte(CP_ACP, 0, pszProcessName, -1,
g_szProcessName, MAX_PATH, NULL, NULL);
#endif
break;
}
if (pProcesses->NextEntryDelta == 0)
break;
/ Finding the address of the next process structure /
pProcesses = (PSYSTEM_PROCESSES)(
(LPBYTE)(pProcesses) + pProcesses->NextEntryDelta);
}
HeapFree(hHeap, 0, pBuffer);
return TRUE;
}
int main() {
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 1892);
if (!hProcess)
return -1;
if (ProcessHandle2ProcessName(hProcess))
_tprintf(“%s\n”, g_szProcessName);
else
_tprintf(“Error!\n”);
CloseHandle(hProcess);
return 0;
}
/----------------------------------------CUT LINE ------------------------------------------------/
My question is what equals to HeapAlloc and HeapFree
may I use in kernel mode ? I guess it’s ExAllocatePool
and ExFreePool, but it doesn’t work with them.
----- Original Message -----
From: “Don Burn”
To: “Windows System Software Devs Interest List”
Sent: Saturday, November 29, 2003 2:54 PM
Subject: [ntdev] Re: Process name in kernel mode
The first call to PsSetLoadImageNotify for a process ID appears to allways
be the executable. You still want to use PsSetProcessNotifyRoutine so you
have a way of cleaning up the mapping.
Of course the above did not solve the OP’s goal, he wanted the “process
name” form the EPROCESS structure, and I know of no kernel interface to get
that.
–
Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting</conio.h></windows.h></tchar.h>