BOOLEAN KrnGetProcessPath(HANDLE hProcessId)
// ProcessID handle can be get using PsGetCurrentProcessId(),
// or by using process callback routines such as PsSetCreateProcessNotifyRoutine()
{
	HANDLE hProcess = NULL;
	OBJECT_ATTRIBUTES obj_attr;
	CLIENT_ID cid;

	cid.UniqueProcess = hProcessId; 
	cid.UniqueThread = NULL;
	InitializeObjectAttributes(&obj_attr, NULL, 0, NULL, NULL);
	ZwOpenProcess(&hProcess, GENERIC_READ, &obj_attr, &cid);

	// When the ProcessInformationClass parameter is ProcessImageFileName, 
	//	the buffer pointed to by the ProcessInformation parameter should be large enough to hold a UNICODE_STRING structure, 
	//	as well as the string itself.
	WCHAR ustrBuffer[(sizeof(UNICODE_STRING) / sizeof(WCHAR)) + 260];
	UNICODE_STRING ustrPath;

	// Initialize UNICODE_STRING
	ustrPath.Buffer = ustrBuffer;
	ustrPath.Length = 0x0;
	ustrPath.MaximumLength = sizeof(ustrBuffer);

	// Process path will be saved inside the unicode string.
	NTSTATUS ret = ZwQueryInformationProcess(hProcess, ProcessImageFileName, &ustrPath, sizeof(ustrBuffer), NULL);

	if (NT_SUCCESS(ret))
	{
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "[DEBUG] process path: %wZ\n", ustrPath);
		return TRUE;
	}
	else
	{
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "[ERROR] error getting process path: %x\n", ret);
		return FALSE;
	}
}