mirror of
https://github.com/hfiref0x/WinObjEx64
synced 2026-06-08 14:40:58 +00:00
754d18e71e
Integrate optional "View With WinDepends" support for viewing dependencies of drivers (Drivers dialog, SSDT/Shadow SSDT dialogs). This feature requires WinDepends installed somewhere on system and .sys file is associated with it through WinDepends file association configuration.
1923 lines
49 KiB
C
1923 lines
49 KiB
C
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT AUTHORS, 2016 - 2026
|
|
*
|
|
* TITLE: EXTRASDRIVERS.C
|
|
*
|
|
* VERSION: 2.10
|
|
*
|
|
* DATE: 07 Mar 2026
|
|
*
|
|
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
* PARTICULAR PURPOSE.
|
|
*
|
|
*******************************************************************************/
|
|
#include "global.h"
|
|
#include "extras.h"
|
|
|
|
#define DUMP_PROP L"dumpProp"
|
|
|
|
BOOLEAN DrvDlgShimsEnabled = FALSE;
|
|
|
|
#define ID_DRVLIST_REFRESH ID_VIEW_REFRESH
|
|
#define ID_DRVLIST_PROP ID_OBJECT_PROPERTIES
|
|
#define ID_DRVLIST_DUMP 40105
|
|
#define ID_DRVLIST_DUMPFIXED 40106
|
|
#define ID_DRVLIST_SAVE 40107
|
|
#define ID_DRVLIST_VIEW_WDX 40108
|
|
|
|
#define ID_CALC_HASH_MD5 6000
|
|
#define ID_CALC_HASH_SHA1 6001
|
|
#define ID_CALC_HASH_SHA256 6002
|
|
#define ID_CALC_HASH_SHA384 6003
|
|
#define ID_CALC_HASH_SHA512 6004
|
|
#define ID_CALC_HASH_PAGE_SHA1 6005
|
|
#define ID_CALC_HASH_PAGE_SHA256 6006
|
|
|
|
#define COLUMN_DRVLIST_LOAD_ORDER 0
|
|
#define COLUMN_DRVLIST_DRIVER_NAME 1
|
|
#define COLUMN_DRVLIST_DRIVER_ADDRESS 2
|
|
#define COLUMN_DRVLIST_SIZE 3
|
|
#define COLUMN_DRVLIST_MODULE_NAME 4
|
|
#define COLUMN_DRVLIST_SHIMMED 5
|
|
|
|
#define COLUMN_DRVLIST_UNLOADED_DRIVER_NAME 0
|
|
#define COLUMN_DRVLIST_UNLOADED_START_ADDRESS 1
|
|
#define COLUMN_DRVLIST_UNLOADED_END_ADDRESS 2
|
|
#define COLUMN_DRVLIST_UNLOADED_CURRENT_TIME 3
|
|
|
|
#define T_DUMPDRIVER L"Dump Driver (Raw)"
|
|
#define T_DUMPDRIVER_FIXED L"Dump Driver (Fix Sections)"
|
|
|
|
#define DRVLISTDLG_TRACKSIZE_MIN_X 640
|
|
#define DRVLISTDLG_TRACKSIZE_MIN_Y 480
|
|
|
|
static EXTRASCONTEXT DrvDlgContext[DrvModeMax];
|
|
static HANDLE DrvDlgThreadHandles[DrvModeMax] = { NULL, NULL };
|
|
static FAST_EVENT DrvDlgInitializedEvents[DrvModeMax] = { FAST_EVENT_INIT, FAST_EVENT_INIT };
|
|
static LIST_ENTRY g_DrvFilterListHead;
|
|
static ULONG g_cDrvShimmed = 0;
|
|
static ULONG g_cDrvFilters = 0;
|
|
|
|
WNDPROC g_OriginalListViewProc = NULL;
|
|
|
|
LPCWSTR CryptAlgoIdRef[] = {
|
|
BCRYPT_MD5_ALGORITHM,
|
|
BCRYPT_SHA1_ALGORITHM,
|
|
BCRYPT_SHA256_ALGORITHM,
|
|
BCRYPT_SHA384_ALGORITHM,
|
|
BCRYPT_SHA512_ALGORITHM
|
|
};
|
|
|
|
VOID DrvTooltipFreeBuffer(
|
|
_In_ EXTRASCONTEXT* Context
|
|
)
|
|
{
|
|
if (Context == NULL)
|
|
return;
|
|
|
|
if (Context->TooltipBuffer) {
|
|
supHeapFree(Context->TooltipBuffer);
|
|
Context->TooltipBuffer = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* DrvListCopyHash
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Copy hash menu handler.
|
|
*
|
|
*/
|
|
VOID DrvListCopyHash(
|
|
_In_ EXTRASCONTEXT* Context,
|
|
_In_ UINT MenuId
|
|
)
|
|
{
|
|
INT mark;
|
|
NTSTATUS ntStatus;
|
|
LPWSTR lpItem, lpszHash = NULL, lpWin32Name;
|
|
|
|
FILE_VIEW_INFO fvi;
|
|
|
|
if (ListView_GetSelectedCount(Context->ListView) == 0)
|
|
return;
|
|
|
|
mark = ListView_GetSelectionMark(Context->ListView);
|
|
if (mark < 0)
|
|
return;
|
|
|
|
lpItem = supGetItemText(Context->ListView, mark,
|
|
COLUMN_DRVLIST_MODULE_NAME, NULL);
|
|
|
|
if (lpItem == NULL)
|
|
return;
|
|
|
|
lpWin32Name = supGetWin32FileName(lpItem);
|
|
|
|
if (lpWin32Name) {
|
|
|
|
RtlSecureZeroMemory(&fvi, sizeof(fvi));
|
|
|
|
fvi.FileName = lpWin32Name;
|
|
|
|
ntStatus = HashLoadFile(&fvi, FALSE);
|
|
if (NT_SUCCESS(ntStatus)) {
|
|
|
|
if (MenuId >= ID_CALC_HASH_PAGE_SHA1 && MenuId <= ID_CALC_HASH_PAGE_SHA256) {
|
|
|
|
lpszHash = ComputeHashForFile(&fvi,
|
|
(MenuId == ID_CALC_HASH_PAGE_SHA1) ? BCRYPT_SHA1_ALGORITHM : BCRYPT_SHA256_ALGORITHM,
|
|
PAGE_SIZE,
|
|
g_obexHeap,
|
|
TRUE);
|
|
|
|
}
|
|
else if (MenuId >= ID_CALC_HASH_MD5 && MenuId <= ID_CALC_HASH_SHA512) {
|
|
|
|
lpszHash = ComputeHashForFile(&fvi,
|
|
CryptAlgoIdRef[MenuId - ID_CALC_HASH_MD5],
|
|
PAGE_SIZE,
|
|
g_obexHeap,
|
|
FALSE);
|
|
}
|
|
|
|
HashUnloadFile(&fvi);
|
|
}
|
|
else {
|
|
supShowNtStatus(Context->hwndDlg, TEXT("Error loading file, NTSTATUS: "), ntStatus);
|
|
}
|
|
|
|
supHeapFree(lpWin32Name);
|
|
}
|
|
|
|
supHeapFree(lpItem);
|
|
|
|
if (lpszHash) {
|
|
supClipboardCopy(lpszHash, _strlen(lpszHash) * sizeof(WCHAR));
|
|
supHeapFree(lpszHash);
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* DrvUpdateStatusBar
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Update status bar information.
|
|
*
|
|
*/
|
|
VOID DrvUpdateStatusBar(
|
|
_In_ EXTRASCONTEXT* Context,
|
|
_In_ INT iItem)
|
|
{
|
|
INT iSubItem;
|
|
INT sbParts[] = { 100, -1 };
|
|
WCHAR szBuffer[MAX_PATH];
|
|
|
|
_strcpy(szBuffer, TEXT("Total: "));
|
|
ultostr(ListView_GetItemCount(Context->ListView), _strend(szBuffer));
|
|
|
|
//
|
|
// Add "shimmed" drivers count for normal dialog mode.
|
|
//
|
|
if (Context->DialogMode == DrvModeNormal) {
|
|
if (g_cDrvShimmed) {
|
|
_strcat(szBuffer, TEXT(", Shimmed: "));
|
|
ultostr(g_cDrvShimmed, _strend(szBuffer));
|
|
sbParts[0] = 240;
|
|
}
|
|
}
|
|
|
|
SendMessage(Context->StatusBar, SB_SETPARTS, 2, (LPARAM)&sbParts);
|
|
supStatusBarSetText(Context->StatusBar, 0, (LPWSTR)&szBuffer);
|
|
|
|
if (iItem >= 0) {
|
|
|
|
if (Context->DialogMode == DrvModeNormal)
|
|
iSubItem = COLUMN_DRVLIST_DRIVER_NAME;
|
|
else
|
|
iSubItem = COLUMN_DRVLIST_UNLOADED_DRIVER_NAME;
|
|
|
|
supGetItemText2(
|
|
Context->ListView,
|
|
iItem,
|
|
iSubItem,
|
|
szBuffer,
|
|
MAX_PATH);
|
|
|
|
supStatusBarSetText(Context->StatusBar, 1, (LPWSTR)&szBuffer);
|
|
}
|
|
else {
|
|
supStatusBarSetText(Context->StatusBar, 1, (LPWSTR)T_EmptyString);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* DrvHandlePopupMenu
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Table list popup construction.
|
|
*
|
|
*/
|
|
VOID DrvHandlePopupMenu(
|
|
_In_ HWND hwndDlg,
|
|
_In_ LPPOINT lpPoint,
|
|
_In_ PVOID lpUserParam
|
|
)
|
|
{
|
|
HMENU hMenu;
|
|
UINT uPos = 0, i;
|
|
EXTRASCONTEXT* Context = (EXTRASCONTEXT*)lpUserParam;
|
|
WCHAR szMenuText[MAX_PATH + 1];
|
|
|
|
hMenu = CreatePopupMenu();
|
|
if (hMenu) {
|
|
|
|
if (supListViewAddCopyValueItem(hMenu,
|
|
Context->ListView,
|
|
ID_OBJECT_COPY,
|
|
uPos,
|
|
lpPoint,
|
|
&Context->lvItemHit,
|
|
&Context->lvColumnHit))
|
|
{
|
|
InsertMenu(hMenu, ++uPos, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
|
|
}
|
|
|
|
if (Context->DialogMode == DrvModeNormal) {
|
|
|
|
InsertMenu(hMenu, ++uPos, MF_BYCOMMAND, ID_DRVLIST_PROP, T_PROPERTIES);
|
|
InsertMenu(hMenu, ++uPos, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
|
|
if (kdConnectDriver()) {
|
|
InsertMenu(hMenu, ++uPos, MF_BYCOMMAND, ID_DRVLIST_DUMP, T_DUMPDRIVER);
|
|
InsertMenu(hMenu, ++uPos, MF_BYCOMMAND, ID_DRVLIST_DUMPFIXED, T_DUMPDRIVER_FIXED);
|
|
}
|
|
InsertMenu(hMenu, ++uPos, MF_BYCOMMAND, ID_JUMPTOFILE, T_JUMPTOFILE);
|
|
|
|
}
|
|
|
|
InsertMenu(hMenu, ++uPos, MF_BYCOMMAND, ID_DRVLIST_SAVE, T_EXPORTTOFILE);
|
|
InsertMenu(hMenu, ++uPos, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
|
|
InsertMenu(hMenu, ++uPos, MF_BYCOMMAND, ID_DRVLIST_REFRESH, T_VIEW_REFRESH);
|
|
|
|
if (Context->DialogMode == DrvModeNormal) {
|
|
//
|
|
// Hashes.
|
|
//
|
|
InsertMenu(hMenu, ++uPos, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
|
|
for (i = ID_CALC_HASH_MD5; i < ID_CALC_HASH_PAGE_SHA1; i++) {
|
|
RtlStringCchPrintfSecure(szMenuText,
|
|
MAX_PATH,
|
|
TEXT("Copy Authenticode %ws hash"),
|
|
CryptAlgoIdRef[i - ID_CALC_HASH_MD5]);
|
|
InsertMenu(hMenu, ++uPos, MF_BYCOMMAND, i, szMenuText);
|
|
}
|
|
|
|
InsertMenu(hMenu, ++uPos, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
|
|
|
|
RtlStringCchPrintfSecure(szMenuText,
|
|
MAX_PATH,
|
|
TEXT("Copy %ws page hash"),
|
|
BCRYPT_SHA1_ALGORITHM);
|
|
|
|
InsertMenu(hMenu, ++uPos, MF_BYCOMMAND, ID_CALC_HASH_PAGE_SHA1, szMenuText);
|
|
|
|
RtlStringCchPrintfSecure(szMenuText,
|
|
MAX_PATH,
|
|
TEXT("Copy %ws page hash"),
|
|
BCRYPT_SHA256_ALGORITHM);
|
|
|
|
InsertMenu(hMenu, ++uPos, MF_BYCOMMAND, ID_CALC_HASH_PAGE_SHA256, szMenuText);
|
|
|
|
//
|
|
// View With WinDepends
|
|
//
|
|
if (g_WinObj.WinDependsPresent)
|
|
InsertMenu(hMenu, ++uPos, MF_BYCOMMAND, ID_DRVLIST_VIEW_WDX, T_VIEWWITH_WDX);
|
|
|
|
}
|
|
|
|
//
|
|
// Track.
|
|
//
|
|
TrackPopupMenu(hMenu,
|
|
TPM_RIGHTBUTTON | TPM_LEFTALIGN,
|
|
lpPoint->x,
|
|
lpPoint->y,
|
|
0,
|
|
hwndDlg,
|
|
NULL);
|
|
|
|
DestroyMenu(hMenu);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* DrvListViewProperties
|
|
*
|
|
* Purpose:
|
|
*
|
|
* View selected driver file properties.
|
|
*
|
|
*/
|
|
VOID DrvListViewProperties(
|
|
_In_ EXTRASCONTEXT* Context
|
|
)
|
|
{
|
|
LPWSTR lpItem, lpWin32Name;
|
|
INT mark;
|
|
|
|
if (ListView_GetSelectedCount(Context->ListView)) {
|
|
mark = ListView_GetSelectionMark(Context->ListView);
|
|
if (mark >= 0) {
|
|
lpItem = supGetItemText(Context->ListView, mark,
|
|
COLUMN_DRVLIST_MODULE_NAME, NULL);
|
|
|
|
if (lpItem) {
|
|
lpWin32Name = supGetWin32FileName(lpItem);
|
|
if (lpWin32Name) {
|
|
supShowProperties(Context->hwndDlg, lpWin32Name);
|
|
supHeapFree(lpWin32Name);
|
|
}
|
|
supHeapFree(lpItem);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static HANDLE DumpDialogThreadHandle = NULL;
|
|
static FAST_EVENT DumpDialogInitializedEvent = FAST_EVENT_INIT;
|
|
HWND DumpWorkerWindow = NULL;
|
|
|
|
typedef struct _OBEX_DRVDUMP {
|
|
_In_ BOOL FixSections;
|
|
_In_ ULONG DumpSize;
|
|
_In_ ULONG_PTR DumpAddress;
|
|
_In_ PBYTE Buffer;
|
|
_In_ HWND ParentWindow;
|
|
_Out_ volatile LONGLONG ReadSize;
|
|
_Out_ NTSTATUS DumpStatus;
|
|
_In_ HANDLE hCancelEvent;
|
|
_In_ HANDLE hWorkerThread;
|
|
_In_ WCHAR FileName[MAX_PATH * 2];
|
|
} OBEX_DRVDUMP, * POBEX_DRVDUMP;
|
|
|
|
/*
|
|
* DrvDumpThread
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Dumper thread worker.
|
|
*
|
|
*/
|
|
DWORD DrvDumpThread(
|
|
_In_ PVOID Parameter
|
|
)
|
|
{
|
|
OBEX_DRVDUMP* dumpInfo = (POBEX_DRVDUMP)Parameter;
|
|
|
|
PBYTE buffer;
|
|
ULONG_PTR dumpAddress;
|
|
ULONG totalSize;
|
|
unsigned long long readBytes = 0;
|
|
ULONG i;
|
|
ULONG remainingBytes;
|
|
ULONG memIO = 0;
|
|
LONGLONG prev;
|
|
|
|
if (dumpInfo == NULL)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
totalSize = dumpInfo->DumpSize;
|
|
|
|
for (i = 0,
|
|
buffer = dumpInfo->Buffer,
|
|
dumpAddress = dumpInfo->DumpAddress;
|
|
(i < (totalSize / PAGE_SIZE));
|
|
i++,
|
|
dumpAddress += PAGE_SIZE,
|
|
buffer = (PBYTE)RtlOffsetToPointer(buffer, PAGE_SIZE))
|
|
{
|
|
if (dumpInfo->hCancelEvent && WaitForSingleObject(dumpInfo->hCancelEvent, 0) == WAIT_OBJECT_0) {
|
|
dumpInfo->DumpStatus = STATUS_CANCELLED;
|
|
PostMessage(dumpInfo->ParentWindow, WM_CLOSE, (WPARAM)0, (LPARAM)0);
|
|
return ERROR_CANCELLED;
|
|
}
|
|
|
|
kdReadSystemMemoryEx(dumpAddress, buffer, PAGE_SIZE, &memIO); // ignore read errors
|
|
prev = InterlockedExchangeAdd64(&dumpInfo->ReadSize, (LONGLONG)memIO);
|
|
readBytes = (unsigned long long)(prev + (LONGLONG)memIO);
|
|
}
|
|
|
|
remainingBytes = totalSize % PAGE_SIZE;
|
|
if (remainingBytes) {
|
|
if (dumpInfo->hCancelEvent && WaitForSingleObject(dumpInfo->hCancelEvent, 0) == WAIT_OBJECT_0) {
|
|
dumpInfo->DumpStatus = STATUS_CANCELLED;
|
|
PostMessage(dumpInfo->ParentWindow, WM_CLOSE, (WPARAM)0, (LPARAM)0);
|
|
return ERROR_CANCELLED;
|
|
}
|
|
kdReadSystemMemoryEx(dumpAddress, buffer, remainingBytes, &memIO);
|
|
prev = InterlockedExchangeAdd64(&dumpInfo->ReadSize, (LONGLONG)memIO);
|
|
readBytes = (unsigned long long)(prev + (LONGLONG)memIO);
|
|
}
|
|
|
|
if (readBytes == 0) {
|
|
dumpInfo->DumpStatus = STATUS_UNSUCCESSFUL;
|
|
}
|
|
else if (readBytes != totalSize) {
|
|
dumpInfo->DumpStatus = STATUS_PARTIAL_COPY;
|
|
}
|
|
else {
|
|
dumpInfo->DumpStatus = STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Signal dialog to close and let dialog-thread perform cleanup.
|
|
//
|
|
PostMessage(dumpInfo->ParentWindow, WM_CLOSE, (WPARAM)0, (LPARAM)0);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* DumpTerminateWorker
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Request worker cancellation and wait for worker thread to exit.
|
|
*
|
|
*/
|
|
VOID DumpTerminateWorker(
|
|
_In_ HWND hwndDlg
|
|
)
|
|
{
|
|
OBEX_DRVDUMP* dumpInfo;
|
|
|
|
if (hwndDlg == NULL)
|
|
return;
|
|
|
|
dumpInfo = (OBEX_DRVDUMP*)GetProp(hwndDlg, DUMP_PROP);
|
|
if (dumpInfo == NULL)
|
|
return;
|
|
|
|
if (dumpInfo->hWorkerThread) {
|
|
//
|
|
// Request cancellation.
|
|
//
|
|
if (dumpInfo->hCancelEvent)
|
|
SetEvent(dumpInfo->hCancelEvent);
|
|
|
|
WaitForSingleObject(dumpInfo->hWorkerThread, 20 * 1000);
|
|
|
|
CloseHandle(dumpInfo->hWorkerThread);
|
|
dumpInfo->hWorkerThread = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* DumpUpdateTimerProc
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Timer proc handler displaying dump progress.
|
|
*
|
|
*/
|
|
VOID DumpUpdateTimerProc(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
UINT_PTR idEvent,
|
|
DWORD dwTime)
|
|
{
|
|
UNREFERENCED_PARAMETER(uMsg);
|
|
UNREFERENCED_PARAMETER(idEvent);
|
|
UNREFERENCED_PARAMETER(dwTime);
|
|
|
|
OBEX_DRVDUMP* dumpInfo;
|
|
HWND hwndProgress = GetDlgItem(hwnd, IDC_PROGRESS);
|
|
WCHAR szBuffer[100];
|
|
|
|
dumpInfo = (OBEX_DRVDUMP*)GetProp(hwnd, DUMP_PROP);
|
|
if (dumpInfo) {
|
|
szBuffer[0] = 0;
|
|
RtlStringCchPrintfSecure(szBuffer,
|
|
RTL_NUMBER_OF(szBuffer),
|
|
TEXT("Reading %llu (%llu Kb) of %lu (%lu Kb)"),
|
|
(ULONGLONG)dumpInfo->ReadSize,
|
|
(ULONGLONG)(dumpInfo->ReadSize / 1024),
|
|
dumpInfo->DumpSize,
|
|
dumpInfo->DumpSize / 1024);
|
|
|
|
SetWindowText(hwndProgress, szBuffer);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* DrvDumpProgressDialogProc
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Driver dumping progress dialog proc.
|
|
*
|
|
*/
|
|
INT_PTR CALLBACK DrvDumpProgressDialogProc(
|
|
_In_ HWND hwndDlg,
|
|
_In_ UINT uMsg,
|
|
_In_ WPARAM wParam,
|
|
_In_ LPARAM lParam
|
|
)
|
|
{
|
|
OBEX_DRVDUMP* dumpInfo;
|
|
|
|
switch (uMsg) {
|
|
|
|
case WM_INITDIALOG:
|
|
dumpInfo = (POBEX_DRVDUMP)lParam;
|
|
if (dumpInfo) {
|
|
SetProp(hwndDlg, DUMP_PROP, (HANDLE)dumpInfo);
|
|
supCenterWindowSpecifyParent(hwndDlg, dumpInfo->ParentWindow);
|
|
dumpInfo->ParentWindow = hwndDlg;
|
|
_InterlockedExchange64(&dumpInfo->ReadSize, 0);
|
|
dumpInfo->hCancelEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
dumpInfo->hWorkerThread = supCreateThread(DrvDumpThread, (PVOID)dumpInfo, 0);
|
|
SetTimer(hwndDlg, 1, 300, DumpUpdateTimerProc);
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
PostQuitMessage(0);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
|
|
case IDCANCEL:
|
|
DumpTerminateWorker(hwndDlg);
|
|
RemoveProp(hwndDlg, DUMP_PROP);
|
|
KillTimer(hwndDlg, 1);
|
|
return DestroyWindow(hwndDlg);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* DumpDialogWorkerThread
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Driver dumping dialog proc.
|
|
*
|
|
*/
|
|
DWORD DumpDialogWorkerThread(
|
|
_In_ PVOID Parameter
|
|
)
|
|
{
|
|
BOOL bResult;
|
|
MSG message;
|
|
OBEX_DRVDUMP* dumpInfo = (POBEX_DRVDUMP)Parameter;
|
|
HWND hwndDlg, hwndParent = dumpInfo->ParentWindow;
|
|
HANDLE prev;
|
|
|
|
SIZE_T bytesIO;
|
|
WCHAR szBuffer[100];
|
|
|
|
hwndDlg = CreateDialogParam(g_WinObj.hInstance,
|
|
MAKEINTRESOURCE(IDD_DIALOG_PROGRESS),
|
|
0,
|
|
(DLGPROC)&DrvDumpProgressDialogProc,
|
|
(LPARAM)dumpInfo);
|
|
|
|
DumpWorkerWindow = hwndDlg;
|
|
|
|
SetWindowText(hwndDlg, TEXT("Driver dump"));
|
|
|
|
supSetFastEvent(&DumpDialogInitializedEvent);
|
|
|
|
if (hwndDlg) {
|
|
do {
|
|
|
|
bResult = GetMessage(&message, NULL, 0, 0);
|
|
if (bResult == -1)
|
|
break;
|
|
|
|
if (!IsDialogMessage(hwndDlg, &message)) {
|
|
TranslateMessage(&message);
|
|
DispatchMessage(&message);
|
|
}
|
|
|
|
} while (bResult != 0);
|
|
}
|
|
|
|
if (dumpInfo->hWorkerThread) {
|
|
WaitForSingleObject(dumpInfo->hWorkerThread, INFINITE);
|
|
CloseHandle(dumpInfo->hWorkerThread);
|
|
dumpInfo->hWorkerThread = NULL;
|
|
}
|
|
|
|
if ((NT_SUCCESS(dumpInfo->DumpStatus)
|
|
|| dumpInfo->DumpStatus == STATUS_PARTIAL_COPY)
|
|
&& (dumpInfo->Buffer != NULL))
|
|
{
|
|
if (dumpInfo->FixSections)
|
|
supImageFixSections(dumpInfo->Buffer);
|
|
|
|
bytesIO = supWriteBufferToFile(dumpInfo->FileName, dumpInfo->Buffer,
|
|
(SIZE_T)dumpInfo->DumpSize, FALSE, FALSE, NULL);
|
|
|
|
RtlStringCchPrintfSecure(szBuffer, RTL_NUMBER_OF(szBuffer),
|
|
TEXT("Read %llu (%llu Kb), Write %llu (%llu Kb), Requested %lu (%lu Kb)"),
|
|
(ULONGLONG)dumpInfo->ReadSize,
|
|
(ULONGLONG)(dumpInfo->ReadSize / 1024),
|
|
(ULONGLONG)bytesIO,
|
|
(ULONGLONG)(bytesIO / 1024),
|
|
dumpInfo->DumpSize,
|
|
dumpInfo->DumpSize / 1024);
|
|
|
|
}
|
|
else if (dumpInfo->DumpStatus == STATUS_CANCELLED) {
|
|
_strcpy(szBuffer, TEXT("Operation cancelled by user"));
|
|
}
|
|
else {
|
|
_strcpy(szBuffer, TEXT("Error while dumping memory"));
|
|
}
|
|
|
|
supStatusBarSetText(
|
|
GetDlgItem(hwndParent, ID_EXTRASLIST_STATUSBAR),
|
|
1,
|
|
szBuffer);
|
|
|
|
if (dumpInfo->hCancelEvent) {
|
|
CloseHandle(dumpInfo->hCancelEvent);
|
|
dumpInfo->hCancelEvent = NULL;
|
|
}
|
|
|
|
if (dumpInfo->Buffer) {
|
|
supHeapFree(dumpInfo->Buffer);
|
|
}
|
|
supHeapFree(dumpInfo);
|
|
|
|
supResetFastEvent(&DumpDialogInitializedEvent);
|
|
|
|
prev = InterlockedExchangePointer((PVOID*)&DumpDialogThreadHandle, NULL);
|
|
if (prev) CloseHandle(prev);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* DrvDumpDriver
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Read driver from memory and write to disk, ignore read errors
|
|
*
|
|
*/
|
|
VOID DrvDumpDriver(
|
|
_In_ EXTRASCONTEXT* Context,
|
|
_In_ BOOL FixSections
|
|
)
|
|
{
|
|
INT nSelected;
|
|
SIZE_T sz;
|
|
LPWSTR lpDriverName = NULL;
|
|
WCHAR szBuffer[MAX_PATH * 2], szDriverDumpInfo[MAX_TEXT_CONVERSION_ULONG64];
|
|
OBEX_DRVDUMP* DumpInfo;
|
|
ULONG_PTR dumpAddress;
|
|
ULONG dumpSize;
|
|
|
|
if (DumpDialogThreadHandle) {
|
|
return;
|
|
}
|
|
|
|
do {
|
|
|
|
//
|
|
// Remember selected index.
|
|
//
|
|
nSelected = ListView_GetNextItem(Context->ListView, -1, LVNI_SELECTED);
|
|
if (nSelected < 0)
|
|
break;
|
|
|
|
//
|
|
// Query selected driver name.
|
|
//
|
|
sz = 0;
|
|
lpDriverName = supGetItemText(Context->ListView, nSelected, 1, &sz);
|
|
if (lpDriverName == NULL)
|
|
break;
|
|
|
|
RtlSecureZeroMemory(&szBuffer, sizeof(szBuffer));
|
|
_strncpy(szBuffer, MAX_PATH, lpDriverName, sz / sizeof(WCHAR));
|
|
|
|
//
|
|
// Run Save As Dialog.
|
|
//
|
|
if (!supSaveDialogExecute(Context->hwndDlg, szBuffer, TEXT("All files\0*.*\0\0")))
|
|
break;
|
|
|
|
//
|
|
// Query driver address from listview.
|
|
//
|
|
RtlSecureZeroMemory(szDriverDumpInfo, sizeof(szDriverDumpInfo));
|
|
supGetItemText2(
|
|
Context->ListView,
|
|
nSelected,
|
|
COLUMN_DRVLIST_DRIVER_ADDRESS,
|
|
szDriverDumpInfo,
|
|
MAX_TEXT_CONVERSION_ULONG64);
|
|
|
|
if (!(szDriverDumpInfo[0] == L'0' && (szDriverDumpInfo[1] == L'x')))
|
|
break;
|
|
|
|
dumpAddress = hextou64(&szDriverDumpInfo[2]);
|
|
if (dumpAddress < g_kdctx.SystemRangeStart)
|
|
break;
|
|
|
|
//
|
|
// Query driver size from listview.
|
|
//
|
|
RtlSecureZeroMemory(szDriverDumpInfo, sizeof(szDriverDumpInfo));
|
|
supGetItemText2(
|
|
Context->ListView,
|
|
nSelected,
|
|
COLUMN_DRVLIST_SIZE,
|
|
szDriverDumpInfo,
|
|
MAX_TEXT_CONVERSION_ULONG64);
|
|
|
|
dumpSize = _strtoul(szDriverDumpInfo);
|
|
if (dumpSize == 0)
|
|
break;
|
|
|
|
// 1 GB cap.
|
|
if (dumpSize > 0x40000000) {
|
|
supStatusBarSetText(Context->StatusBar, 1, TEXT("Dump size too large"));
|
|
break;
|
|
}
|
|
|
|
DumpInfo = (OBEX_DRVDUMP*)supHeapAlloc(sizeof(OBEX_DRVDUMP));
|
|
if (DumpInfo == NULL)
|
|
break;
|
|
|
|
DumpInfo->Buffer = (PBYTE)supHeapAlloc(dumpSize);
|
|
if (DumpInfo->Buffer == NULL) {
|
|
supHeapFree(DumpInfo);
|
|
break;
|
|
}
|
|
DumpInfo->FixSections = FixSections;
|
|
_strcpy(DumpInfo->FileName, szBuffer);
|
|
DumpInfo->DumpAddress = dumpAddress;
|
|
DumpInfo->DumpSize = dumpSize;
|
|
DumpInfo->ParentWindow = Context->hwndDlg;
|
|
DumpInfo->ReadSize = 0;
|
|
DumpInfo->DumpStatus = STATUS_UNSUCCESSFUL;
|
|
DumpInfo->hCancelEvent = NULL;
|
|
DumpInfo->hWorkerThread = NULL;
|
|
|
|
DumpDialogThreadHandle = supCreateThread(DumpDialogWorkerThread, (PVOID)DumpInfo, 0);
|
|
if (DumpDialogThreadHandle == NULL) {
|
|
if (DumpInfo->Buffer) supHeapFree(DumpInfo->Buffer);
|
|
supHeapFree(DumpInfo);
|
|
break;
|
|
}
|
|
supWaitForFastEvent(&DumpDialogInitializedEvent, NULL);
|
|
|
|
} while (FALSE);
|
|
|
|
if (lpDriverName) supHeapFree(lpDriverName);
|
|
}
|
|
|
|
/*
|
|
* DrvDlgCompareFunc
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Drivers Dialog listview comparer function.
|
|
*
|
|
*/
|
|
INT CALLBACK DrvDlgCompareFunc(
|
|
_In_ LPARAM lParam1,
|
|
_In_ LPARAM lParam2,
|
|
_In_ LPARAM lParamSort
|
|
)
|
|
{
|
|
EXTRASCONTEXT* pDlgContext = (EXTRASCONTEXT*)lParamSort;
|
|
|
|
if (pDlgContext == NULL)
|
|
return 0;
|
|
|
|
if (pDlgContext->DialogMode == DrvModeNormal) {
|
|
|
|
switch (pDlgContext->lvColumnToSort) {
|
|
case COLUMN_DRVLIST_LOAD_ORDER: //Load Order
|
|
case COLUMN_DRVLIST_SIZE: //Size
|
|
return supGetMaxOfTwoULongFromString(
|
|
pDlgContext->ListView,
|
|
lParam1,
|
|
lParam2,
|
|
pDlgContext->lvColumnToSort,
|
|
pDlgContext->bInverseSort);
|
|
|
|
case COLUMN_DRVLIST_DRIVER_ADDRESS: //Address
|
|
return supGetMaxOfTwoU64FromHex(
|
|
pDlgContext->ListView,
|
|
lParam1,
|
|
lParam2,
|
|
pDlgContext->lvColumnToSort,
|
|
pDlgContext->bInverseSort);
|
|
|
|
case COLUMN_DRVLIST_DRIVER_NAME: //Name
|
|
case COLUMN_DRVLIST_MODULE_NAME: //Module
|
|
case COLUMN_DRVLIST_SHIMMED: //Shimmed
|
|
return supGetMaxCompareTwoFixedStrings(
|
|
pDlgContext->ListView,
|
|
lParam1,
|
|
lParam2,
|
|
pDlgContext->lvColumnToSort,
|
|
pDlgContext->bInverseSort);
|
|
}
|
|
|
|
}
|
|
else {
|
|
|
|
switch (pDlgContext->lvColumnToSort) {
|
|
case COLUMN_DRVLIST_UNLOADED_DRIVER_NAME: //Name
|
|
case COLUMN_DRVLIST_UNLOADED_CURRENT_TIME: //CurrentTime
|
|
return supGetMaxCompareTwoFixedStrings(
|
|
pDlgContext->ListView,
|
|
lParam1,
|
|
lParam2,
|
|
pDlgContext->lvColumnToSort,
|
|
pDlgContext->bInverseSort);
|
|
|
|
case COLUMN_DRVLIST_UNLOADED_START_ADDRESS: //StartAddress
|
|
case COLUMN_DRVLIST_UNLOADED_END_ADDRESS: //EndAddress
|
|
return supGetMaxOfTwoU64FromHex(
|
|
pDlgContext->ListView,
|
|
lParam1,
|
|
lParam2,
|
|
pDlgContext->lvColumnToSort,
|
|
pDlgContext->bInverseSort);
|
|
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* DrvListCbEnumerateUnloadedDrivers
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Unloaded drivers enumeration callback.
|
|
*
|
|
*/
|
|
BOOL DrvListCbEnumerateUnloadedDrivers(
|
|
_In_ PUNLOADED_DRIVERS Entry,
|
|
_In_ EXTRASCONTEXT* Context
|
|
)
|
|
{
|
|
INT lvItemIndex;
|
|
LPWSTR lpName;
|
|
HWND hwndList;
|
|
LVITEM lvitem;
|
|
WCHAR szBuffer[100];
|
|
|
|
hwndList = Context->ListView;
|
|
|
|
if (Entry->StartAddress && Entry->EndAddress) {
|
|
|
|
if (!NT_SUCCESS(ObIsValidUnicodeString(&Entry->Name)))
|
|
lpName = T_Unknown;
|
|
else
|
|
lpName = Entry->Name.Buffer;
|
|
|
|
RtlSecureZeroMemory(&lvitem, sizeof(lvitem));
|
|
lvitem.mask = LVIF_TEXT | LVIF_IMAGE;
|
|
lvitem.iItem = MAXINT;
|
|
lvitem.iImage = g_TypeDriver.ImageIndex;
|
|
lvitem.pszText = lpName;
|
|
|
|
lvItemIndex = ListView_InsertItem(hwndList, &lvitem);
|
|
if (lvItemIndex >= 0) {
|
|
lvitem.pszText = szBuffer;
|
|
|
|
//StartAddress
|
|
szBuffer[0] = L'0';
|
|
szBuffer[1] = L'x';
|
|
szBuffer[2] = 0;
|
|
u64tohex((ULONG_PTR)Entry->StartAddress, &szBuffer[2]);
|
|
lvitem.iSubItem = 1;
|
|
lvitem.iItem = lvItemIndex;
|
|
ListView_SetItem(hwndList, &lvitem);
|
|
|
|
//EndAddress
|
|
szBuffer[0] = L'0';
|
|
szBuffer[1] = L'x';
|
|
szBuffer[2] = 0;
|
|
u64tohex((ULONG_PTR)Entry->EndAddress, &szBuffer[2]);
|
|
lvitem.iSubItem = 2;
|
|
ListView_SetItem(hwndList, &lvitem);
|
|
|
|
//CurrentTime
|
|
szBuffer[0] = 0;
|
|
supPrintTimeConverted(&Entry->CurrentTime, szBuffer, RTL_NUMBER_OF(szBuffer));
|
|
lvitem.iSubItem = 3;
|
|
ListView_SetItem(hwndList, &lvitem);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* DrvListUnloadedDrivers
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Unloaded drivers query and list routine.
|
|
*
|
|
*/
|
|
VOID DrvListUnloadedDrivers(
|
|
_In_ EXTRASCONTEXT* Context,
|
|
_In_ BOOLEAN bRefresh
|
|
)
|
|
{
|
|
HWND hwndList = Context->ListView;
|
|
WCHAR szBuffer[100];
|
|
|
|
if (bRefresh) {
|
|
ListView_DeleteAllItems(hwndList);
|
|
}
|
|
|
|
supDisableRedraw(hwndList);
|
|
|
|
if (!kdEnumerateMmUnloadedDrivers(
|
|
(PENUMERATE_UNLOADED_DRIVERS_CALLBACK)DrvListCbEnumerateUnloadedDrivers,
|
|
(PVOID)Context))
|
|
{
|
|
_strcpy(szBuffer, TEXT("Could not resolve MmUnloadedDrivers"));
|
|
supStatusBarSetText(Context->StatusBar, 0, (LPWSTR)&szBuffer);
|
|
return;
|
|
}
|
|
|
|
DrvUpdateStatusBar(Context, -1);
|
|
|
|
ListView_SortItemsEx(hwndList,
|
|
&DrvDlgCompareFunc,
|
|
(LPARAM)Context);
|
|
|
|
supEnableRedraw(hwndList);
|
|
}
|
|
|
|
/*
|
|
* DrvListDrivers
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Drivers query and list routine.
|
|
*
|
|
*/
|
|
VOID DrvListDrivers(
|
|
_In_ EXTRASCONTEXT* Context,
|
|
_In_ BOOLEAN bRefresh
|
|
)
|
|
{
|
|
INT lvItemIndex;
|
|
ULONG i;
|
|
|
|
PCHAR lpDriverName;
|
|
HWND hwndList = Context->ListView;
|
|
|
|
LVITEM lvitem;
|
|
WCHAR szBuffer[MAX_PATH * 2];
|
|
|
|
GUID shimGUID;
|
|
SUP_SHIM_INFO* shimInfo;
|
|
|
|
RTL_PROCESS_MODULES* pModulesList = NULL;
|
|
PRTL_PROCESS_MODULE_INFORMATION pModule;
|
|
|
|
g_cDrvShimmed = 0;
|
|
|
|
if (bRefresh) {
|
|
ListView_DeleteAllItems(hwndList);
|
|
kdQueryKernelShims(&g_kdctx, TRUE);
|
|
}
|
|
|
|
pModulesList = (PRTL_PROCESS_MODULES)supGetLoadedModulesList(NULL);
|
|
if (pModulesList == NULL)
|
|
return;
|
|
|
|
if (g_cDrvFilters) {
|
|
supFilterDestroyList(&g_DrvFilterListHead);
|
|
}
|
|
else {
|
|
InitializeListHead(&g_DrvFilterListHead);
|
|
}
|
|
g_cDrvFilters = supFilterCreateList(&g_DrvFilterListHead);
|
|
|
|
supDisableRedraw(hwndList);
|
|
|
|
for (i = 0; i < pModulesList->NumberOfModules; i++) {
|
|
|
|
pModule = &pModulesList->Modules[i];
|
|
|
|
if ((ULONG_PTR)pModule->ImageBase < g_kdctx.SystemRangeStart)
|
|
continue;
|
|
|
|
RtlSecureZeroMemory(&lvitem, sizeof(lvitem));
|
|
|
|
//LoadOrder
|
|
szBuffer[0] = 0;
|
|
ultostr(pModule->LoadOrderIndex, szBuffer);
|
|
|
|
lvitem.mask = LVIF_TEXT | LVIF_IMAGE;
|
|
lvitem.iItem = MAXINT;
|
|
lvitem.iImage = g_TypeDriver.ImageIndex;
|
|
lvitem.pszText = szBuffer;
|
|
lvItemIndex = ListView_InsertItem(hwndList, &lvitem);
|
|
if (lvItemIndex == -1)
|
|
continue;
|
|
|
|
//Name
|
|
RtlSecureZeroMemory(szBuffer, sizeof(szBuffer));
|
|
|
|
//
|
|
// Handle malformed result.
|
|
//
|
|
if (pModule->OffsetToFileName > RTL_NUMBER_OF(pModule->FullPathName)) {
|
|
_strcpy(szBuffer, T_Unknown);
|
|
}
|
|
else {
|
|
lpDriverName = (PCHAR)&pModule->FullPathName[pModule->OffsetToFileName];
|
|
if (*lpDriverName == 0)
|
|
{
|
|
_strcpy(szBuffer, T_Unknown);
|
|
}
|
|
else {
|
|
MultiByteToWideChar(
|
|
CP_ACP, 0,
|
|
(LPCSTR)lpDriverName,
|
|
-1,
|
|
szBuffer,
|
|
MAX_PATH);
|
|
|
|
}
|
|
}
|
|
|
|
lvitem.mask = LVIF_TEXT;
|
|
lvitem.iSubItem = 1;
|
|
lvitem.pszText = szBuffer;
|
|
lvitem.iItem = lvItemIndex;
|
|
ListView_SetItem(hwndList, &lvitem);
|
|
|
|
//Address
|
|
szBuffer[0] = L'0';
|
|
szBuffer[1] = L'x';
|
|
szBuffer[2] = 0;
|
|
u64tohex((ULONG_PTR)pModule->ImageBase, &szBuffer[2]);
|
|
lvitem.iSubItem = 2;
|
|
ListView_SetItem(hwndList, &lvitem);
|
|
|
|
//Size
|
|
szBuffer[0] = 0;
|
|
ultostr(pModule->ImageSize, szBuffer);
|
|
lvitem.iSubItem = 3;
|
|
ListView_SetItem(hwndList, &lvitem);
|
|
|
|
//FullName
|
|
RtlSecureZeroMemory(szBuffer, sizeof(szBuffer));
|
|
|
|
MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
(LPCSTR)&pModule->FullPathName,
|
|
-1,
|
|
szBuffer,
|
|
MAX_PATH);
|
|
|
|
lvitem.iSubItem = 4;
|
|
ListView_SetItem(hwndList, &lvitem);
|
|
|
|
//Shimmed
|
|
if (DrvDlgShimsEnabled) {
|
|
|
|
szBuffer[0] = 0;
|
|
|
|
if (supIsDriverShimmed(
|
|
&g_kdctx.Data->KseEngineDump,
|
|
pModule->ImageBase,
|
|
&shimGUID))
|
|
{
|
|
g_cDrvShimmed += 1;
|
|
|
|
shimInfo = supGetDriverShimInformation(shimGUID);
|
|
if (shimInfo) {
|
|
|
|
RtlStringCchPrintfSecure(szBuffer,
|
|
RTL_NUMBER_OF(szBuffer),
|
|
L"%ws: %ws",
|
|
shimInfo->KseShimName,
|
|
shimInfo->OwnerModule);
|
|
|
|
}
|
|
else {
|
|
_strcpy(szBuffer, TEXT("Yes"));
|
|
}
|
|
}
|
|
|
|
lvitem.iSubItem = 5;
|
|
ListView_SetItem(hwndList, &lvitem);
|
|
|
|
}
|
|
}
|
|
|
|
supHeapFree(pModulesList);
|
|
DrvUpdateStatusBar(Context, -1);
|
|
|
|
ListView_SortItemsEx(hwndList,
|
|
&DrvDlgCompareFunc,
|
|
(LPARAM)Context);
|
|
|
|
supEnableRedraw(hwndList);
|
|
}
|
|
|
|
/*
|
|
* DrvDlgHandleNotify
|
|
*
|
|
* Purpose:
|
|
*
|
|
* WM_NOTIFY processing for Driver list dialogs.
|
|
*
|
|
*/
|
|
BOOL CALLBACK DrvDlgHandleNotify(
|
|
_In_ EXTRASCONTEXT* Context,
|
|
_In_ LPARAM lParam
|
|
)
|
|
{
|
|
INT nImageIndex;
|
|
LPNMLISTVIEW NMListView = (LPNMLISTVIEW)lParam;
|
|
|
|
if (NMListView->hdr.idFrom != ID_EXTRASLIST)
|
|
return FALSE;
|
|
|
|
switch (NMListView->hdr.code) {
|
|
|
|
case LVN_COLUMNCLICK:
|
|
|
|
Context->bInverseSort = (~Context->bInverseSort) & 1;
|
|
Context->lvColumnToSort = NMListView->iSubItem;
|
|
|
|
ListView_SortItemsEx(Context->ListView,
|
|
DrvDlgCompareFunc,
|
|
Context);
|
|
|
|
nImageIndex = ImageList_GetImageCount(g_ListViewImages);
|
|
if (Context->bInverseSort)
|
|
nImageIndex -= 2; //sort down/up images are always at the end of g_ListViewImages
|
|
else
|
|
nImageIndex -= 1;
|
|
|
|
supUpdateLvColumnHeaderImage(
|
|
Context->ListView,
|
|
Context->lvColumnCount,
|
|
Context->lvColumnToSort,
|
|
nImageIndex);
|
|
|
|
break;
|
|
|
|
case NM_DBLCLK:
|
|
DrvListViewProperties(Context);
|
|
break;
|
|
|
|
case NM_CLICK:
|
|
DrvUpdateStatusBar(Context, NMListView->iItem);
|
|
break;
|
|
|
|
case LVN_ITEMCHANGED:
|
|
|
|
if ((NMListView->uNewState & LVIS_SELECTED) &&
|
|
!(NMListView->uOldState & LVIS_SELECTED))
|
|
{
|
|
DrvUpdateStatusBar(Context, NMListView->iItem);
|
|
}
|
|
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* DrvDlgHandleWMCommand
|
|
*
|
|
* Purpose:
|
|
*
|
|
* WM_COMMAND handler.
|
|
*
|
|
*/
|
|
VOID DrvDlgHandleWMCommand(
|
|
_In_ HWND hwndDlg,
|
|
_In_ WPARAM wParam,
|
|
_In_ LPARAM lParam
|
|
)
|
|
{
|
|
EXTRASCONTEXT* pDlgContext = (EXTRASCONTEXT*)GetProp(hwndDlg, T_DLGCONTEXT);
|
|
LPWSTR lpFileName;
|
|
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
|
|
case ID_OBJECT_COPY:
|
|
|
|
if (pDlgContext) {
|
|
|
|
supListViewCopyItemValueToClipboard(pDlgContext->ListView,
|
|
pDlgContext->lvItemHit,
|
|
pDlgContext->lvColumnHit);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
SendMessage(hwndDlg, WM_CLOSE, 0, 0);
|
|
break;
|
|
|
|
case ID_DRVLIST_DUMP:
|
|
DrvDumpDriver(pDlgContext, FALSE);
|
|
break;
|
|
case ID_DRVLIST_DUMPFIXED:
|
|
DrvDumpDriver(pDlgContext, TRUE);
|
|
break;
|
|
|
|
case ID_JUMPTOFILE:
|
|
if (pDlgContext) {
|
|
supJumpToFileListView(pDlgContext->ListView, COLUMN_DRVLIST_MODULE_NAME);
|
|
}
|
|
break;
|
|
|
|
case ID_DRVLIST_SAVE:
|
|
|
|
if (pDlgContext) {
|
|
|
|
if (pDlgContext->DialogMode == DrvModeNormal)
|
|
lpFileName = TEXT("Drivers.csv");
|
|
else
|
|
lpFileName = TEXT("UnloadedDrivers.csv");
|
|
|
|
if (supListViewExportToFile(
|
|
lpFileName,
|
|
hwndDlg,
|
|
pDlgContext->ListView))
|
|
{
|
|
supStatusBarSetText(pDlgContext->StatusBar, 1, T_LIST_EXPORT_SUCCESS);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ID_DRVLIST_VIEW_WDX:
|
|
extrasViewWithWinDepends(pDlgContext, COLUMN_DRVLIST_MODULE_NAME);
|
|
break;
|
|
|
|
case ID_DRVLIST_PROP:
|
|
if (pDlgContext) {
|
|
DrvListViewProperties(pDlgContext);
|
|
}
|
|
break;
|
|
|
|
case ID_DRVLIST_REFRESH:
|
|
if (pDlgContext) {
|
|
|
|
if (pDlgContext->DialogMode == DrvModeNormal) {
|
|
|
|
DrvListDrivers(pDlgContext, TRUE);
|
|
|
|
}
|
|
else {
|
|
|
|
DrvListUnloadedDrivers(pDlgContext, TRUE);
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ID_CALC_HASH_MD5:
|
|
case ID_CALC_HASH_SHA1:
|
|
case ID_CALC_HASH_SHA256:
|
|
case ID_CALC_HASH_SHA384:
|
|
case ID_CALC_HASH_SHA512:
|
|
case ID_CALC_HASH_PAGE_SHA1:
|
|
case ID_CALC_HASH_PAGE_SHA256:
|
|
DrvListCopyHash(pDlgContext, LOWORD(wParam));
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
* DrvListSetTooltip
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Collect all information for tooltip and set it.
|
|
*
|
|
*/
|
|
VOID DrvListSetTooltip(
|
|
_In_ EXTRASCONTEXT* Context,
|
|
_In_ HWND ListViewHandle,
|
|
_In_ INT iItem
|
|
)
|
|
{
|
|
ULONG_PTR drvBase;
|
|
BOOL bShimmed;
|
|
GUID shimGUID;
|
|
SUP_SHIM_INFO* shimInfo;
|
|
SIZE_T cchText;
|
|
SIZE_T cchRemaining;
|
|
SIZE_T cchWritten;
|
|
int charsWritten;
|
|
WCHAR* lpText;
|
|
|
|
WCHAR szBuffer[MAX_PATH];
|
|
WCHAR szNameWithoutExt[MAX_PATH];
|
|
|
|
if (Context == NULL)
|
|
return;
|
|
|
|
DrvTooltipFreeBuffer(Context);
|
|
|
|
cchText = 4096;
|
|
lpText = (WCHAR*)supHeapAlloc(cchText * sizeof(WCHAR));
|
|
if (lpText == NULL)
|
|
return;
|
|
|
|
lpText[0] = 0;
|
|
cchWritten = 0;
|
|
|
|
//
|
|
// Name
|
|
//
|
|
RtlSecureZeroMemory(&szBuffer, sizeof(szBuffer));
|
|
supGetItemText2(ListViewHandle, iItem,
|
|
COLUMN_DRVLIST_DRIVER_NAME, szBuffer, MAX_PATH);
|
|
|
|
charsWritten = RtlStringCchPrintfSecure(&lpText[cchWritten],
|
|
cchText,
|
|
TEXT("%ws"),
|
|
szBuffer);
|
|
|
|
if (charsWritten > 0) {
|
|
cchWritten += charsWritten;
|
|
}
|
|
|
|
szNameWithoutExt[0] = 0;
|
|
_filename_noext(szNameWithoutExt, szBuffer);
|
|
|
|
//
|
|
// Base
|
|
//
|
|
szBuffer[0] = 0;
|
|
supGetItemText2(ListViewHandle, iItem,
|
|
COLUMN_DRVLIST_DRIVER_ADDRESS, szBuffer, 32);
|
|
|
|
cchRemaining = cchText - cchWritten;
|
|
if (cchRemaining) {
|
|
charsWritten = RtlStringCchPrintfSecure(&lpText[cchWritten],
|
|
cchRemaining,
|
|
TEXT("\n%ws\n"),
|
|
szBuffer);
|
|
|
|
if (charsWritten > 0) {
|
|
cchWritten += charsWritten;
|
|
}
|
|
}
|
|
|
|
drvBase = hextou64(&szBuffer[2]);
|
|
|
|
//
|
|
// Module name
|
|
//
|
|
szBuffer[0] = 0;
|
|
supGetItemText2(ListViewHandle, iItem,
|
|
COLUMN_DRVLIST_MODULE_NAME, szBuffer, MAX_PATH);
|
|
|
|
cchRemaining = cchText - cchWritten;
|
|
if (cchRemaining) {
|
|
charsWritten = RtlStringCchPrintfSecure(&lpText[cchWritten],
|
|
cchRemaining,
|
|
TEXT("%ws"),
|
|
szBuffer);
|
|
|
|
if (charsWritten > 0) {
|
|
cchWritten += charsWritten;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Filter driver mark
|
|
//
|
|
if (supFilterFindByName(&g_DrvFilterListHead, szNameWithoutExt)) {
|
|
|
|
cchRemaining = cchText - cchWritten;
|
|
if (cchRemaining) {
|
|
charsWritten = RtlStringCchPrintfSecure(&lpText[cchWritten],
|
|
cchRemaining,
|
|
TEXT("\nRegistered as filter"));
|
|
|
|
if (charsWritten > 0) {
|
|
cchWritten += charsWritten;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Shim desc
|
|
//
|
|
szBuffer[0] = 0;
|
|
supGetItemText2(ListViewHandle, iItem,
|
|
COLUMN_DRVLIST_SHIMMED, szBuffer, MAX_PATH);
|
|
|
|
if (szBuffer[0]) {
|
|
|
|
bShimmed = supIsDriverShimmed(&g_kdctx.Data->KseEngineDump, (PVOID)drvBase, &shimGUID);
|
|
if (bShimmed) {
|
|
|
|
shimInfo = supGetDriverShimInformation(shimGUID);
|
|
if (shimInfo) {
|
|
|
|
cchRemaining = cchText - cchWritten;
|
|
if (cchRemaining) {
|
|
charsWritten = RtlStringCchPrintfSecure(&lpText[cchWritten],
|
|
cchRemaining,
|
|
L"\n\n%ws\n%ws",
|
|
shimInfo->KseShimName,
|
|
shimInfo->Description);
|
|
|
|
if (charsWritten > 0) {
|
|
cchWritten += charsWritten;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
Context->TooltipBuffer = lpText;
|
|
}
|
|
|
|
/*
|
|
* DrvListViewHookProc
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Drivers Dialog listview hook handler.
|
|
*
|
|
*/
|
|
LRESULT CALLBACK DrvListViewHookProc(
|
|
_In_ HWND hwnd,
|
|
_In_ UINT uMsg,
|
|
_In_ WPARAM wParam,
|
|
_In_ LPARAM lParam
|
|
)
|
|
{
|
|
HWND hwndTT;
|
|
LVHITTESTINFO ht;
|
|
TOOLINFO toolInfo;
|
|
BOOL bCheckPass = FALSE;
|
|
static int oldX = -1, oldY = -1;
|
|
static int lastItem = -1;
|
|
INT currentItem;
|
|
|
|
hwndTT = (HWND)DrvDlgContext[DrvModeNormal].TooltipInfo;
|
|
|
|
switch (uMsg) {
|
|
|
|
case WM_MOUSEMOVE:
|
|
|
|
RtlSecureZeroMemory(&ht, sizeof(ht));
|
|
ht.pt.x = GET_X_LPARAM(lParam);
|
|
ht.pt.y = GET_Y_LPARAM(lParam);
|
|
|
|
if (ChildWindowFromPoint(hwnd, ht.pt) == hwnd) {
|
|
if (ListView_SubItemHitTest(hwnd, &ht) != -1) {
|
|
bCheckPass = (ht.iSubItem == COLUMN_DRVLIST_DRIVER_NAME);
|
|
}
|
|
}
|
|
|
|
//
|
|
// If tooltip window is not available, skip tooltip actions.
|
|
//
|
|
if (hwndTT == NULL || !IsWindow(hwndTT)) {
|
|
lastItem = -1;
|
|
oldX = oldY = -1;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Deactivate tooltip if not on the name column or no item.
|
|
//
|
|
if (!bCheckPass || !(ht.flags & LVHT_ONITEM)) {
|
|
|
|
if (lastItem != -1) {
|
|
RtlSecureZeroMemory(&toolInfo, sizeof(toolInfo));
|
|
toolInfo.cbSize = sizeof(toolInfo);
|
|
toolInfo.hwnd = DrvDlgContext[DrvModeNormal].hwndDlg;
|
|
toolInfo.uFlags = TTF_TRACK | TTF_ABSOLUTE | TTF_IDISHWND;
|
|
toolInfo.uId = (UINT_PTR)hwnd;
|
|
SendMessage(hwndTT, TTM_TRACKACTIVATE, FALSE, (LPARAM)&toolInfo);
|
|
}
|
|
|
|
lastItem = -1;
|
|
oldX = oldY = -1;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// At this point we are over a name subitem on an item.
|
|
// Only update tooltip when the hovered item changed or cursor moved sufficiently.
|
|
//
|
|
currentItem = ht.iItem;
|
|
if ((currentItem != lastItem) || (ht.pt.x != oldX) || (ht.pt.y != oldY)) {
|
|
oldX = ht.pt.x;
|
|
oldY = ht.pt.y;
|
|
|
|
DrvListSetTooltip(&DrvDlgContext[DrvModeNormal], hwnd, currentItem);
|
|
|
|
RtlSecureZeroMemory(&toolInfo, sizeof(toolInfo));
|
|
toolInfo.cbSize = sizeof(toolInfo);
|
|
toolInfo.hwnd = DrvDlgContext[DrvModeNormal].hwndDlg;
|
|
toolInfo.uFlags = TTF_TRACK | TTF_ABSOLUTE | TTF_IDISHWND;
|
|
toolInfo.uId = (UINT_PTR)hwnd;
|
|
|
|
GetCursorPos(&ht.pt);
|
|
SendMessage(hwndTT, TTM_TRACKACTIVATE, (WPARAM)TRUE, (LPARAM)&toolInfo);
|
|
ht.pt.x += 20;
|
|
ht.pt.y += 20;
|
|
SendMessage(hwndTT, TTM_TRACKPOSITION, 0, (LPARAM)MAKELONG(ht.pt.x, ht.pt.y));
|
|
SendMessage(hwndTT, TTM_UPDATE, 0, 0);
|
|
|
|
lastItem = currentItem;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return CallWindowProc(g_OriginalListViewProc, hwnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
/*
|
|
* DrvDlgOnInit
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Drivers Dialog WM_INITDIALOG handler.
|
|
*
|
|
*/
|
|
VOID DrvDlgOnInit(
|
|
_In_ HWND hwndDlg,
|
|
_In_ LPARAM lParam
|
|
)
|
|
{
|
|
INT iImage = ImageList_GetImageCount(g_ListViewImages) - 1, iColumn;
|
|
EXTRASCONTEXT* pDlgContext = (EXTRASCONTEXT*)lParam;
|
|
|
|
LVCOLUMNS_DATA* pvColumnsData;
|
|
ULONG columnsCount;
|
|
LPWSTR lpCaption;
|
|
|
|
LVCOLUMNS_DATA columnDataDrvList[] =
|
|
{
|
|
{ L"LoadOrder", 100, LVCFMT_LEFT | LVCFMT_BITMAP_ON_RIGHT, iImage },
|
|
{ L"Name", 150, LVCFMT_LEFT | LVCFMT_BITMAP_ON_RIGHT, I_IMAGENONE },
|
|
{ L"Address", 130, LVCFMT_LEFT | LVCFMT_BITMAP_ON_RIGHT, I_IMAGENONE },
|
|
{ L"Size", 80, LVCFMT_LEFT | LVCFMT_BITMAP_ON_RIGHT, I_IMAGENONE },
|
|
{ L"Image Path", 280, LVCFMT_LEFT | LVCFMT_BITMAP_ON_RIGHT, I_IMAGENONE }
|
|
};
|
|
|
|
LVCOLUMNS_DATA columnsDataUnloadedDrvList[] = {
|
|
{ L"Name", 150, LVCFMT_LEFT | LVCFMT_BITMAP_ON_RIGHT, iImage },
|
|
{ L"StartAddress", 140, LVCFMT_LEFT | LVCFMT_BITMAP_ON_RIGHT, I_IMAGENONE },
|
|
{ L"EndAddress", 140, LVCFMT_LEFT | LVCFMT_BITMAP_ON_RIGHT, I_IMAGENONE },
|
|
{ L"CurrentTime", 140, LVCFMT_LEFT | LVCFMT_BITMAP_ON_RIGHT, I_IMAGENONE }
|
|
};
|
|
|
|
SetProp(hwndDlg, T_DLGCONTEXT, (HANDLE)lParam);
|
|
supCenterWindowSpecifyParent(hwndDlg, g_hwndMain);
|
|
|
|
pDlgContext->hwndDlg = hwndDlg;
|
|
pDlgContext->lvColumnHit = -1;
|
|
pDlgContext->lvItemHit = -1;
|
|
|
|
switch (pDlgContext->DialogMode) {
|
|
case DrvModeUnloaded:
|
|
lpCaption = TEXT("Unloaded Drivers");
|
|
pvColumnsData = columnsDataUnloadedDrvList;
|
|
columnsCount = RTL_NUMBER_OF(columnsDataUnloadedDrvList);
|
|
break;
|
|
default:
|
|
lpCaption = TEXT("Drivers");
|
|
pvColumnsData = columnDataDrvList;
|
|
columnsCount = RTL_NUMBER_OF(columnDataDrvList);
|
|
break;
|
|
}
|
|
|
|
SetWindowText(hwndDlg, lpCaption);
|
|
|
|
pDlgContext->TooltipBuffer = NULL;
|
|
pDlgContext->StatusBar = GetDlgItem(hwndDlg, ID_EXTRASLIST_STATUSBAR);
|
|
|
|
extrasSetDlgIcon(pDlgContext);
|
|
|
|
pDlgContext->ListView = GetDlgItem(hwndDlg, ID_EXTRASLIST);
|
|
if (pDlgContext->ListView) {
|
|
|
|
pDlgContext->lvColumnHit = -1;
|
|
pDlgContext->lvItemHit = -1;
|
|
|
|
//
|
|
// Set listview imagelist, style flags and theme.
|
|
//
|
|
supSetListViewSettings(pDlgContext->ListView,
|
|
LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP | LVS_EX_LABELTIP,
|
|
FALSE,
|
|
TRUE,
|
|
g_ListViewImages,
|
|
LVSIL_SMALL);
|
|
|
|
if (pDlgContext->DialogMode == DrvModeNormal) {
|
|
|
|
pDlgContext->TooltipInfo = (PVOID)supCreateTrackingToolTip(ID_EXTRASLIST, hwndDlg);
|
|
if (pDlgContext->TooltipInfo) {
|
|
g_OriginalListViewProc = (WNDPROC)SetWindowLongPtr(pDlgContext->ListView,
|
|
GWLP_WNDPROC,
|
|
(LONG_PTR)&DrvListViewHookProc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// And columns and remember their count.
|
|
//
|
|
iColumn = supAddLVColumnsFromArray(
|
|
pDlgContext->ListView,
|
|
pvColumnsData,
|
|
columnsCount);
|
|
|
|
pDlgContext->lvColumnCount = iColumn;
|
|
|
|
if (pDlgContext->DialogMode == DrvModeNormal) {
|
|
|
|
//
|
|
// Add "Shimmed" column on supported Windows version.
|
|
//
|
|
if (g_NtBuildNumber >= NT_WIN10_THRESHOLD1) {
|
|
|
|
if (kdQueryKernelShims(&g_kdctx, FALSE)) {
|
|
|
|
supAddListViewColumn(pDlgContext->ListView,
|
|
iColumn,
|
|
iColumn,
|
|
iColumn,
|
|
I_IMAGENONE,
|
|
LVCFMT_CENTER | LVCFMT_BITMAP_ON_RIGHT,
|
|
TEXT("Shimmed"), 100);
|
|
|
|
DrvDlgShimsEnabled = TRUE;
|
|
pDlgContext->lvColumnCount += 1;
|
|
}
|
|
}
|
|
|
|
DrvListDrivers(pDlgContext, FALSE);
|
|
|
|
}
|
|
else {
|
|
|
|
DrvListUnloadedDrivers(pDlgContext, FALSE);
|
|
|
|
}
|
|
|
|
SendMessage(hwndDlg, WM_SIZE, 0, 0);
|
|
SetFocus(pDlgContext->ListView);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* DrvDlgProc
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Drivers Dialog window procedure.
|
|
*
|
|
*/
|
|
INT_PTR CALLBACK DrvDlgProc(
|
|
_In_ HWND hwndDlg,
|
|
_In_ UINT uMsg,
|
|
_In_ WPARAM wParam,
|
|
_In_ LPARAM lParam
|
|
)
|
|
{
|
|
EXTRASCONTEXT* pDlgContext;
|
|
|
|
if (uMsg == g_WinObj.SettingsChangeMessage) {
|
|
pDlgContext = (EXTRASCONTEXT*)GetProp(hwndDlg, T_DLGCONTEXT);
|
|
if (pDlgContext) {
|
|
extrasHandleSettingsChange(pDlgContext);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
switch (uMsg) {
|
|
|
|
case WM_INITDIALOG:
|
|
DrvDlgOnInit(hwndDlg, lParam);
|
|
break;
|
|
|
|
case WM_GETMINMAXINFO:
|
|
if (lParam) {
|
|
supSetMinMaxTrackSize((PMINMAXINFO)lParam,
|
|
DRVLISTDLG_TRACKSIZE_MIN_X,
|
|
DRVLISTDLG_TRACKSIZE_MIN_Y,
|
|
TRUE);
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
|
|
pDlgContext = (EXTRASCONTEXT*)GetProp(hwndDlg, T_DLGCONTEXT);
|
|
if (pDlgContext) {
|
|
DrvDlgHandleNotify(
|
|
pDlgContext,
|
|
lParam);
|
|
|
|
#pragma warning(push)
|
|
#pragma warning(disable: 26454)
|
|
if (((LPNMHDR)lParam)->code == TTN_GETDISPINFO) {
|
|
#pragma warning(pop)
|
|
LPNMTTDISPINFO lpnmtt;
|
|
|
|
lpnmtt = (LPNMTTDISPINFO)lParam;
|
|
|
|
if (pDlgContext->DialogMode == DrvModeNormal) {
|
|
|
|
if (pDlgContext->TooltipInfo &&
|
|
lpnmtt->hdr.hwndFrom == (HWND)pDlgContext->TooltipInfo)
|
|
{
|
|
if ((HWND)lpnmtt->hdr.idFrom == pDlgContext->ListView) {
|
|
lpnmtt->lpszText = pDlgContext->TooltipBuffer;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
extrasSimpleListResize(hwndDlg);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
PostQuitMessage(0);
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
pDlgContext = (EXTRASCONTEXT*)RemoveProp(hwndDlg, T_DLGCONTEXT);
|
|
if (pDlgContext) {
|
|
if (pDlgContext->TooltipInfo)
|
|
DestroyWindow((HWND)pDlgContext->TooltipInfo);
|
|
|
|
DrvTooltipFreeBuffer(pDlgContext);
|
|
|
|
extrasRemoveDlgIcon(pDlgContext);
|
|
|
|
if (pDlgContext->DialogMode == DrvModeNormal) {
|
|
kdDestroyShimmedDriversList(&g_kdctx.Data->KseEngineDump);
|
|
supFilterDestroyList(&g_DrvFilterListHead);
|
|
g_cDrvFilters = 0;
|
|
}
|
|
|
|
}
|
|
if (DumpWorkerWindow) {
|
|
SendMessage(DumpWorkerWindow, WM_CLOSE, 0, 0);
|
|
DumpWorkerWindow = NULL;
|
|
}
|
|
DestroyWindow(hwndDlg);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
|
|
DrvDlgHandleWMCommand(hwndDlg, wParam, lParam);
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
|
|
pDlgContext = (EXTRASCONTEXT*)GetProp(hwndDlg, T_DLGCONTEXT);
|
|
if (pDlgContext) {
|
|
supHandleContextMenuMsgForListView(hwndDlg,
|
|
wParam,
|
|
lParam,
|
|
pDlgContext->ListView,
|
|
(pfnPopupMenuHandler)DrvHandlePopupMenu,
|
|
pDlgContext);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* extrasDrvDlgWorkerThread
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Drivers Dialog worker thread.
|
|
*
|
|
*/
|
|
DWORD extrasDrvDlgWorkerThread(
|
|
_In_ PVOID Parameter
|
|
)
|
|
{
|
|
BOOL bResult;
|
|
HWND hwndDlg;
|
|
HACCEL acceleratorTable;
|
|
HANDLE prev;
|
|
EXTRASCONTEXT* pDlgContext = (EXTRASCONTEXT*)Parameter;
|
|
MSG message;
|
|
FAST_EVENT fastEvent;
|
|
|
|
hwndDlg = CreateDialogParam(g_WinObj.hInstance,
|
|
MAKEINTRESOURCE(IDD_DIALOG_EXTRASLIST),
|
|
0,
|
|
&DrvDlgProc,
|
|
(LPARAM)pDlgContext);
|
|
|
|
fastEvent = DrvDlgInitializedEvents[pDlgContext->DialogMode];
|
|
supSetFastEvent(&fastEvent);
|
|
|
|
acceleratorTable = LoadAccelerators(g_WinObj.hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
|
|
|
|
if (hwndDlg) {
|
|
do {
|
|
|
|
bResult = GetMessage(&message, NULL, 0, 0);
|
|
if (bResult == -1)
|
|
break;
|
|
|
|
if (IsDialogMessage(hwndDlg, &message)) {
|
|
TranslateAccelerator(hwndDlg, acceleratorTable, &message);
|
|
}
|
|
else {
|
|
TranslateMessage(&message);
|
|
DispatchMessage(&message);
|
|
}
|
|
|
|
} while (bResult != 0);
|
|
}
|
|
|
|
supResetFastEvent(&fastEvent);
|
|
|
|
if (acceleratorTable)
|
|
DestroyAcceleratorTable(acceleratorTable);
|
|
|
|
prev = InterlockedExchangePointer((PVOID*)&DrvDlgThreadHandles[pDlgContext->DialogMode], NULL);
|
|
if (prev) CloseHandle(prev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* extrasCreateDriversDialog
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Run Drivers Dialog worker thread.
|
|
*
|
|
*/
|
|
VOID extrasCreateDriversDialog(
|
|
_In_ DRIVERS_DLG_MODE Mode
|
|
)
|
|
{
|
|
if (Mode < 0 || Mode >= DrvModeMax)
|
|
return;
|
|
|
|
if (!DrvDlgThreadHandles[Mode]) {
|
|
RtlSecureZeroMemory(&DrvDlgContext[Mode], sizeof(EXTRASCONTEXT));
|
|
DrvDlgContext[Mode].DialogMode = Mode;
|
|
DrvDlgThreadHandles[Mode] = supCreateDialogWorkerThread(extrasDrvDlgWorkerThread, (PVOID)&DrvDlgContext[Mode], 0);
|
|
if (DrvDlgThreadHandles[Mode])
|
|
supWaitForFastEvent(&DrvDlgInitializedEvents[Mode], NULL);
|
|
}
|
|
}
|