typedef struct tag_FyWorkQueueItem
{
WORK_QUEUE_ITEM WorkQueueItem;
PVOID lpParameter1;
PVOID lpParameter2;
PVOID lpParameter3;
KEVENT CompleteEvent;
BOOL bStatus;
} FyWorkQueueItem, *PFyWorkQueueItem;
PUNICODE_STRING QueryProcessObjectName(IN HANDLE ProcessId)
{
NTSTATUS Status = STATUS_SUCCESS;
PEPROCESS EProcess = NULL;
HANDLE hProcess = NULL;
ULONG ulRealSize = 0;
PUNICODE_STRING lpuniImageFileName = NULL;
BOOL bSuccess = FALSE;
if (KeGetCurrentIrql() <= APC_LEVEL)
{
Status = PsLookupProcessByProcessId(ProcessId, &EProcess);
if (NT_SUCCESS(Status) && EProcess)
{
Status = ObOpenObjectByPointer((PVOID)EProcess, OBJ_KERNEL_HANDLE, NULL,
PROCESS_ALL_ACCESS, NULL, KernelMode, &hProcess);
if (NT_SUCCESS(Status))
{
Status = ZwQueryInformationProcess(hProcess, ProcessImageFileName, NULL, 0, &ulRealSize);
if (Status == STATUS_INFO_LENGTH_MISMATCH)
{
lpuniImageFileName = (PUNICODE_STRING)ExAllocatePoolWithTag(NonPagedPool,
ulRealSize + sizeof(UNICODE_STRING), 'hiti');
if (lpuniImageFileName)
{
memset(lpuniImageFileName, 0, ulRealSize + sizeof(UNICODE_STRING));
Status = ZwQueryInformationProcess(hProcess, ProcessImageFileName,
lpuniImageFileName, ulRealSize + sizeof(UNICODE_STRING), &ulRealSize);
if (NT_SUCCESS(Status))
{
bSuccess = TRUE;
}
}
}
ZwClose(hProcess);
}
ObDereferenceObject(EProcess);
}
}
if (!bSuccess)
{
ExFreePool(lpuniImageFileName);
lpuniImageFileName = NULL;
}
return lpuniImageFileName;
}
BOOL GetProcessImageFileName(
IN HANDLE ProcessId,
OUT WCHAR* lpwzImageFileName,
IN ULONG uMaxSize)
{
NTSTATUS Status = STATUS_SUCCESS;
HANDLE FileHandle = NULL;
IO_STATUS_BLOCK IoStatusBlock = { 0 };
PUNICODE_STRING lpuniProcessObjectName = NULL;
OBJECT_ATTRIBUTES oa = { 0 };
PFILE_OBJECT FileObject = NULL;
POBJECT_NAME_INFORMATION ObjectNameInformation = NULL;
BOOL bStatus = FALSE;
if (KeGetCurrentIrql() > PASSIVE_LEVEL) {
return FALSE;
}
lpuniProcessObjectName = QueryProcessObjectName(ProcessId);
if (!lpuniProcessObjectName) {
return FALSE;
}
InitializeObjectAttributes(&oa, lpuniProcessObjectName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = IoCreateFile(
&FileHandle,
FILE_READ_ATTRIBUTES,
&oa,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE,
NULL,
0,
CreateFileTypeNone,
NULL,
IO_NO_PARAMETER_CHECKING);
if (!NT_SUCCESS(Status))
{
ExFreePool(lpuniProcessObjectName);
return FALSE;
}
Status = ObReferenceObjectByHandle(FileHandle, FILE_ANY_ACCESS, *IoFileObjectType,
KernelMode, (PVOID*)&FileObject, NULL);
if (NT_SUCCESS(Status) && FileObject)
{
Status = IoQueryFileDosDeviceName(FileObject, &ObjectNameInformation);
if (NT_SUCCESS(Status))
{
if (ObjectNameInformation)
{
if (ObjectNameInformation->Name.Length <= sizeof(WCHAR) * uMaxSize)
{
memset(lpwzImageFileName, 0, 2 * uMaxSize);
memcpy(lpwzImageFileName, ObjectNameInformation->Name.Buffer,
ObjectNameInformation->Name.Length);
bStatus = TRUE;
}
ExFreePool(ObjectNameInformation);
ObjectNameInformation = NULL;
}
}
ObDereferenceObject(FileObject);
}
ObCloseHandle(FileHandle, KernelMode);
FileHandle = NULL;
ExFreePool(lpuniProcessObjectName);
return bStatus;
}
VOID QueryProcessFileNameWorkItem(IN PFyWorkQueueItem lpFyWorkQueueItem)
{
lpFyWorkQueueItem->bStatus = GetProcessImageFileName(
(HANDLE)lpFyWorkQueueItem->lpParameter1,
(WCHAR*)lpFyWorkQueueItem->lpParameter2,
(ULONG)lpFyWorkQueueItem->lpParameter3);
KeSetEvent(&lpFyWorkQueueItem->CompleteEvent, IO_NO_INCREMENT, FALSE);
}
BOOL GetProcessImageFileNameSafeIrql(
IN HANDLE ProcessId,
OUT WCHAR* lpwzImageFileName,
IN ULONG uMaxSize)
{
BOOL bStatus;
FyWorkQueueItem WorkItem;
if (KeGetCurrentIrql() <= APC_LEVEL)
{
if (KeAreApcsDisabled() || KeGetCurrentIrql() == APC_LEVEL)
{
memset(&WorkItem, 0, sizeof(WorkItem));
KeInitializeEvent(&WorkItem.CompleteEvent, NotificationEvent, FALSE);
WorkItem.bStatus = FALSE;
WorkItem.WorkQueueItem.List.Flink = NULL;
WorkItem.WorkQueueItem.WorkerRoutine = (PWORKER_THREAD_ROUTINE)QueryProcessFileNameWorkItem;
WorkItem.lpParameter1 = (PVOID)ProcessId;
WorkItem.lpParameter2 = (PVOID)lpwzImageFileName;
WorkItem.lpParameter3 = (PVOID)uMaxSize;
WorkItem.WorkQueueItem.Parameter = &WorkItem;
ExQueueWorkItem(&WorkItem.WorkQueueItem, DelayedWorkQueue);
KeWaitForSingleObject(&WorkItem.CompleteEvent, Executive, KernelMode, FALSE, NULL);
bStatus = WorkItem.bStatus;
}
else
{
bStatus = GetProcessImageFileName(ProcessId, lpwzImageFileName, uMaxSize);
}
}
else
{
bStatus = FALSE;
}
return bStatus;
}