694 lines
22 KiB
C
694 lines
22 KiB
C
/*
|
|
* Process Hacker Extra Plugins -
|
|
* Debug View Plugin
|
|
*
|
|
* Copyright (C) 2015 dmex
|
|
*
|
|
* This file is part of Process Hacker.
|
|
*
|
|
* Process Hacker is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Process Hacker is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "main.h"
|
|
|
|
static HANDLE DbgDialogThreadHandle = NULL;
|
|
static HWND DbgDialogHandle = NULL;
|
|
static PH_EVENT InitializedEvent = PH_EVENT_INIT;
|
|
|
|
VOID NTAPI DbgLoggedEventCallback(
|
|
_In_opt_ PVOID Parameter,
|
|
_In_opt_ PVOID Context
|
|
)
|
|
{
|
|
PPH_DBGEVENTS_CONTEXT context = (PPH_DBGEVENTS_CONTEXT)Context;
|
|
|
|
if (context->DialogHandle)
|
|
{
|
|
PostMessage(context->DialogHandle, WM_DEBUG_LOG_UPDATED, 0, 0);
|
|
}
|
|
}
|
|
|
|
VOID DbgUpdateLogList(
|
|
_Inout_ PPH_DBGEVENTS_CONTEXT Context
|
|
)
|
|
{
|
|
Context->ListViewCount = Context->LogMessageList->Count;
|
|
ListView_SetItemCountEx(Context->ListViewHandle, Context->ListViewCount, LVSICF_NOSCROLL);
|
|
|
|
if (Context->ListViewCount >= 2 && Button_GetCheck(Context->AutoScrollHandle) == BST_CHECKED)
|
|
{
|
|
if (ListView_IsItemVisible(Context->ListViewHandle, Context->ListViewCount - 2))
|
|
{
|
|
ListView_EnsureVisible(Context->ListViewHandle, Context->ListViewCount - 1, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
PPH_STRING DbgGetStringForSelectedLogEntries(
|
|
_Inout_ PPH_DBGEVENTS_CONTEXT Context,
|
|
_In_ BOOLEAN All
|
|
)
|
|
{
|
|
PH_STRING_BUILDER stringBuilder;
|
|
ULONG i;
|
|
|
|
if (Context->ListViewCount == 0)
|
|
return PhReferenceEmptyString();
|
|
|
|
PhInitializeStringBuilder(&stringBuilder, 0x100);
|
|
|
|
i = Context->ListViewCount - 1;
|
|
|
|
while (TRUE)
|
|
{
|
|
PDEBUG_LOG_ENTRY entry;
|
|
SYSTEMTIME systemTime;
|
|
PPH_STRING temp;
|
|
|
|
if (!All)
|
|
{
|
|
if (!(ListView_GetItemState(Context->ListViewHandle, i, LVIS_SELECTED) & LVIS_SELECTED))
|
|
{
|
|
goto ContinueLoop;
|
|
}
|
|
}
|
|
|
|
entry = Context->LogMessageList->Items[i];
|
|
|
|
if (!entry)
|
|
goto ContinueLoop;
|
|
|
|
PhLargeIntegerToLocalSystemTime(&systemTime, &entry->Time);
|
|
temp = PhFormatDateTime(&systemTime);
|
|
PhAppendStringBuilder(&stringBuilder, &temp->sr);
|
|
PhDereferenceObject(temp);
|
|
PhAppendStringBuilder2(&stringBuilder, L": ");
|
|
|
|
temp = PhFormatString(
|
|
L"%s (%lu): %s",
|
|
entry->ProcessName->Buffer, // entry->FilePath->Buffer;
|
|
HandleToUlong(entry->ProcessId),
|
|
entry->Message->Buffer
|
|
);
|
|
PhAppendStringBuilder(&stringBuilder, &temp->sr);
|
|
PhDereferenceObject(temp);
|
|
PhAppendStringBuilder2(&stringBuilder, L"\r\n");
|
|
|
|
ContinueLoop:
|
|
|
|
if (i == 0)
|
|
break;
|
|
|
|
i--;
|
|
}
|
|
|
|
return PhFinalStringBuilderString(&stringBuilder);
|
|
}
|
|
|
|
VOID ShowListViewMenu(
|
|
_Inout_ PPH_DBGEVENTS_CONTEXT Context
|
|
)
|
|
{
|
|
INT index;
|
|
PDEBUG_LOG_ENTRY entry;
|
|
|
|
index = PhFindListViewItemByFlags(Context->ListViewHandle, -1, LVNI_SELECTED);
|
|
|
|
if (index == -1)
|
|
return;
|
|
|
|
entry = Context->LogMessageList->Items[index];
|
|
|
|
if (entry)
|
|
{
|
|
POINT cursorPos;
|
|
PPH_EMENU menu;
|
|
PPH_EMENU_ITEM selectedItem;
|
|
|
|
GetCursorPos(&cursorPos);
|
|
|
|
menu = PhCreateEMenu();
|
|
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, 1, L"View Message", NULL, NULL), -1);
|
|
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
|
|
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, 2, L"Go to Owning &Process", NULL, NULL), -1);
|
|
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
|
|
PhInsertEMenuItem(menu, selectedItem = PhCreateEMenuItem(0, 0, L"E&xclude Process", NULL, NULL), -1);
|
|
PhInsertEMenuItem(selectedItem, PhCreateEMenuItem(0, 3, L"By PID", NULL, NULL), -1);
|
|
PhInsertEMenuItem(selectedItem, PhCreateEMenuItem(0, 4, L"By Name", NULL, NULL), -1);
|
|
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
|
|
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, 5, L"&Copy", NULL, NULL), -1);
|
|
|
|
selectedItem = PhShowEMenu(
|
|
menu,
|
|
Context->ListViewHandle,
|
|
PH_EMENU_SHOW_LEFTRIGHT,
|
|
PH_ALIGN_LEFT | PH_ALIGN_TOP,
|
|
cursorPos.x,
|
|
cursorPos.y
|
|
);
|
|
|
|
if (selectedItem && selectedItem->Id != -1)
|
|
{
|
|
switch (selectedItem->Id)
|
|
{
|
|
case 1:
|
|
{
|
|
DialogBoxParam(
|
|
PluginInstance->DllBase,
|
|
MAKEINTRESOURCE(IDD_MESSAGE_DIALOG),
|
|
Context->DialogHandle,
|
|
DbgPropDlgProc,
|
|
(LPARAM)entry
|
|
);
|
|
}
|
|
break;
|
|
case 2:
|
|
{
|
|
PPH_PROCESS_NODE processNode;
|
|
|
|
if (processNode = PhFindProcessNode(entry->ProcessId))
|
|
{
|
|
ProcessHacker_ToggleVisible(PhMainWndHandle, TRUE);
|
|
ProcessHacker_SelectTabPage(PhMainWndHandle, 0);
|
|
ProcessHacker_SelectProcessNode(PhMainWndHandle, processNode);
|
|
}
|
|
}
|
|
break;
|
|
case 3:
|
|
{
|
|
AddFilterType(Context, FilterByPid, entry->ProcessId, entry->ProcessName);
|
|
DbgUpdateLogList(Context);
|
|
}
|
|
break;
|
|
case 4:
|
|
{
|
|
AddFilterType(Context, FilterByName, entry->ProcessId, entry->ProcessName);
|
|
DbgUpdateLogList(Context);
|
|
}
|
|
break;
|
|
case 5:
|
|
{
|
|
PPH_STRING string;
|
|
|
|
string = DbgGetStringForSelectedLogEntries(Context, FALSE);
|
|
|
|
PhSetClipboardString(Context->DialogHandle, &string->sr);
|
|
PhDereferenceObject(string);
|
|
|
|
SetFocus(Context->ListViewHandle);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
PhDestroyEMenu(menu);
|
|
}
|
|
}
|
|
|
|
VOID ShowDropdownMenu(
|
|
_Inout_ PPH_DBGEVENTS_CONTEXT Context
|
|
)
|
|
{
|
|
RECT rect;
|
|
PPH_EMENU menu = NULL;
|
|
PPH_EMENU_ITEM selectedItem = NULL;
|
|
PPH_EMENU_ITEM resetMenuItem = NULL;
|
|
PPH_EMENU_ITEM captureMenuItem = NULL;
|
|
PPH_EMENU_ITEM captureGlobalMenuItem = NULL;
|
|
|
|
GetWindowRect(Context->OptionsHandle, &rect);
|
|
|
|
menu = PhCreateEMenu();
|
|
PhInsertEMenuItem(menu, captureMenuItem = PhCreateEMenuItem(0, ID_CAPTURE_WIN32, L"Capture Win32", NULL, NULL), -1);
|
|
PhInsertEMenuItem(menu, captureGlobalMenuItem = PhCreateEMenuItem(0, ID_CAPTURE_WIN32_GLOBAL, L"Capture Global Win32", NULL, NULL), -1);
|
|
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
|
|
PhInsertEMenuItem(menu, resetMenuItem = PhCreateEMenuItem(PH_EMENU_DISABLED, ID_RESET_FILTERS, L"Reset Filters", NULL, NULL), -1);
|
|
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
|
|
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, ID_CLEAR_EVENTS, L"Clear", NULL, NULL), -1);
|
|
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
|
|
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, ID_SAVE_EVENTS, L"Save", NULL, NULL), -1);
|
|
|
|
if (Context->ExcludeList->Count > 0)
|
|
{
|
|
resetMenuItem->Text = PhaFormatString(L"Reset Filters [%lu]", Context->ExcludeList->Count)->Buffer;
|
|
resetMenuItem->Flags &= ~PH_EMENU_DISABLED;
|
|
}
|
|
|
|
if (Context->CaptureLocalEnabled)
|
|
{
|
|
captureMenuItem->Flags |= PH_EMENU_CHECKED;
|
|
}
|
|
|
|
if (Context->CaptureGlobalEnabled)
|
|
{
|
|
captureGlobalMenuItem->Flags |= PH_EMENU_CHECKED;
|
|
}
|
|
|
|
selectedItem = PhShowEMenu(
|
|
menu,
|
|
Context->DialogHandle,
|
|
PH_EMENU_SHOW_LEFTRIGHT,
|
|
PH_ALIGN_LEFT | PH_ALIGN_TOP,
|
|
rect.left,
|
|
rect.bottom
|
|
);
|
|
|
|
if (selectedItem && selectedItem->Id != -1)
|
|
{
|
|
switch (selectedItem->Id)
|
|
{
|
|
case ID_CAPTURE_WIN32:
|
|
{
|
|
if (!Context->CaptureLocalEnabled)
|
|
DbgEventsCreate(Context, FALSE);
|
|
else
|
|
DbgEventsCleanup(Context, FALSE);
|
|
}
|
|
break;
|
|
case ID_CAPTURE_WIN32_GLOBAL:
|
|
{
|
|
if (!PhGetOwnTokenAttributes().Elevated)
|
|
{
|
|
PhShowInformation(Context->DialogHandle, L"This option requires elevation.");
|
|
break;
|
|
}
|
|
|
|
if (!Context->CaptureGlobalEnabled)
|
|
DbgEventsCreate(Context, TRUE);
|
|
else
|
|
DbgEventsCleanup(Context, TRUE);
|
|
}
|
|
break;
|
|
case ID_RESET_FILTERS:
|
|
{
|
|
ResetFilters(Context);
|
|
}
|
|
break;
|
|
case ID_CLEAR_EVENTS:
|
|
{
|
|
DbgClearLogEntries(Context);
|
|
DbgUpdateLogList(Context);
|
|
}
|
|
break;
|
|
case ID_SAVE_EVENTS:
|
|
{
|
|
static PH_FILETYPE_FILTER filters[] =
|
|
{
|
|
{ L"Text files (*.txt)", L"*.txt" },
|
|
{ L"All files (*.*)", L"*.*" }
|
|
};
|
|
|
|
PVOID fileDialog = PhCreateSaveFileDialog();
|
|
|
|
PhSetFileDialogFilter(fileDialog, filters, ARRAYSIZE(filters));
|
|
PhSetFileDialogFileName(fileDialog, L"DbgView.txt");
|
|
|
|
if (PhShowFileDialog(Context->DialogHandle, fileDialog))
|
|
{
|
|
NTSTATUS status;
|
|
PPH_STRING fileName;
|
|
PPH_FILE_STREAM fileStream;
|
|
PPH_STRING string;
|
|
|
|
fileName = PhGetFileDialogFileName(fileDialog);
|
|
PhAutoDereferenceObject(fileName);
|
|
|
|
if (NT_SUCCESS(status = PhCreateFileStream(
|
|
&fileStream,
|
|
fileName->Buffer,
|
|
FILE_GENERIC_WRITE,
|
|
FILE_SHARE_READ,
|
|
FILE_OVERWRITE_IF,
|
|
0
|
|
)))
|
|
{
|
|
PhWritePhTextHeader(fileStream);
|
|
|
|
string = DbgGetStringForSelectedLogEntries(Context, TRUE);
|
|
PhWriteStringAsUtf8FileStreamEx(fileStream, string->Buffer, string->Length);
|
|
PhDereferenceObject(string);
|
|
|
|
PhDereferenceObject(fileStream);
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
PhShowStatus(PhMainWndHandle, L"Unable to create the file", status, 0);
|
|
}
|
|
|
|
PhFreeFileDialog(fileDialog);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
PhDestroyEMenu(menu);
|
|
}
|
|
|
|
INT_PTR CALLBACK DbgViewDlgProc(
|
|
_In_ HWND hwndDlg,
|
|
_In_ UINT uMsg,
|
|
_In_ WPARAM wParam,
|
|
_In_ LPARAM lParam
|
|
)
|
|
{
|
|
PPH_DBGEVENTS_CONTEXT context;
|
|
|
|
if (uMsg == WM_INITDIALOG)
|
|
{
|
|
context = (PPH_DBGEVENTS_CONTEXT)PhAllocate(sizeof(PH_DBGEVENTS_CONTEXT));
|
|
memset(context, 0, sizeof(PH_DBGEVENTS_CONTEXT));
|
|
|
|
SetProp(hwndDlg, L"Context", (HANDLE)context);
|
|
}
|
|
else
|
|
{
|
|
context = (PPH_DBGEVENTS_CONTEXT)GetProp(hwndDlg, L"Context");
|
|
|
|
if (uMsg == WM_NCDESTROY)
|
|
{
|
|
RemoveProp(hwndDlg, L"Context");
|
|
PhFree(context);
|
|
}
|
|
}
|
|
|
|
if (!context)
|
|
return FALSE;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
PhCenterWindow(hwndDlg, PhMainWndHandle);
|
|
|
|
context->DialogHandle = hwndDlg;
|
|
context->ListViewHandle = GetDlgItem(hwndDlg, IDC_DEBUGLISTVIEW);
|
|
context->AutoScrollHandle = GetDlgItem(hwndDlg, IDC_AUTOSCROLL);
|
|
context->OptionsHandle = GetDlgItem(hwndDlg, IDC_OPTIONS);
|
|
|
|
context->LogMessageList = PhCreateList(1);
|
|
context->ExcludeList = PhCreateList(1);
|
|
|
|
PhRegisterDialog(hwndDlg);
|
|
PhSetListViewStyle(context->ListViewHandle, FALSE, TRUE);
|
|
PhSetControlTheme(context->ListViewHandle, L"explorer");
|
|
PhAddListViewColumn(context->ListViewHandle, 0, 0, 0, LVCFMT_LEFT, 140, L"Process");
|
|
PhAddListViewColumn(context->ListViewHandle, 1, 1, 1, LVCFMT_LEFT, 100, L"Timestamp");
|
|
PhAddListViewColumn(context->ListViewHandle, 2, 2, 2, LVCFMT_LEFT, 220, L"Message");
|
|
//PhSetExtendedListView(context->ListViewHandle);
|
|
|
|
if (context->ListViewImageList = ImageList_Create(19, 19, ILC_COLOR32 | ILC_MASK, 0, 40))
|
|
{
|
|
HICON defaultIcon = PhGetFileShellIcon(NULL, L".exe", TRUE);
|
|
ListView_SetImageList(context->ListViewHandle, context->ListViewImageList, LVSIL_SMALL);
|
|
ImageList_AddIcon(context->ListViewImageList, defaultIcon);
|
|
DestroyIcon(defaultIcon);
|
|
}
|
|
|
|
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
|
|
PhAddLayoutItem(&context->LayoutManager, context->ListViewHandle, NULL, PH_ANCHOR_ALL);
|
|
PhAddLayoutItem(&context->LayoutManager, context->OptionsHandle, NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
|
|
PhAddLayoutItem(&context->LayoutManager, context->AutoScrollHandle, NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
|
|
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ALWAYSONTOP), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
|
|
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDCLOSE), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
|
|
PhLoadWindowPlacementFromSetting(SETTING_NAME_WINDOW_POSITION, SETTING_NAME_WINDOW_SIZE, hwndDlg);
|
|
PhLoadListViewColumnsFromSetting(SETTING_NAME_COLUMNS, context->ListViewHandle);
|
|
|
|
if (PhGetIntegerSetting(SETTING_NAME_ALWAYSONTOP))
|
|
{
|
|
context->AlwaysOnTop = TRUE;
|
|
SetFocus(hwndDlg);
|
|
SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
|
|
Button_SetCheck(GetDlgItem(hwndDlg, IDC_ALWAYSONTOP), BST_CHECKED);
|
|
}
|
|
|
|
if (PhGetIntegerSetting(SETTING_NAME_AUTOSCROLL))
|
|
{
|
|
context->AutoScroll = TRUE;
|
|
Button_SetCheck(context->AutoScrollHandle, BST_CHECKED);
|
|
}
|
|
|
|
DbgCreateSecurityAttributes(context);
|
|
DbgUpdateLogList(context);
|
|
|
|
PhRegisterCallback(&DbgLoggedCallback, DbgLoggedEventCallback, context, &context->DebugLoggedRegistration);
|
|
}
|
|
return TRUE;
|
|
case WM_DESTROY:
|
|
{
|
|
DbgEventsCleanup(context, FALSE);
|
|
DbgEventsCleanup(context, TRUE);
|
|
DbgCleanupSecurityAttributes(context);
|
|
|
|
if (context->ListViewImageList)
|
|
ImageList_Destroy(context->ListViewImageList);
|
|
|
|
if (context->ExcludeList)
|
|
{
|
|
ResetFilters(context);
|
|
PhDereferenceObject(context->ExcludeList);
|
|
}
|
|
|
|
if (context->LogMessageList)
|
|
{
|
|
DbgClearLogEntries(context);
|
|
PhDereferenceObject(context->LogMessageList);
|
|
}
|
|
|
|
PhSaveWindowPlacementToSetting(SETTING_NAME_WINDOW_POSITION, SETTING_NAME_WINDOW_SIZE, hwndDlg);
|
|
PhSaveListViewColumnsToSetting(SETTING_NAME_COLUMNS, context->ListViewHandle);
|
|
|
|
PhDeleteLayoutManager(&context->LayoutManager);
|
|
|
|
PhUnregisterCallback(&DbgLoggedCallback, &context->DebugLoggedRegistration);
|
|
PhUnregisterDialog(hwndDlg);
|
|
|
|
PostQuitMessage(0);
|
|
}
|
|
break;
|
|
case WM_SIZE:
|
|
PhLayoutManagerLayout(&context->LayoutManager);
|
|
break;
|
|
case WM_SHOWDIALOG:
|
|
{
|
|
if (IsMinimized(hwndDlg))
|
|
ShowWindow(hwndDlg, SW_RESTORE);
|
|
else
|
|
ShowWindow(hwndDlg, SW_SHOW);
|
|
|
|
SetForegroundWindow(hwndDlg);
|
|
}
|
|
break;
|
|
case WM_COMMAND:
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_OPTIONS:
|
|
ShowDropdownMenu(context);
|
|
break;
|
|
case IDCLOSE:
|
|
case IDCANCEL:
|
|
DestroyWindow(hwndDlg);
|
|
break;
|
|
case IDC_AUTOSCROLL:
|
|
{
|
|
context->AutoScroll = !context->AutoScroll;
|
|
PhSetIntegerSetting(SETTING_NAME_AUTOSCROLL, context->AutoScroll);
|
|
Button_SetCheck(context->AutoScrollHandle, context->AutoScroll ? BST_CHECKED : BST_UNCHECKED);
|
|
}
|
|
break;
|
|
case IDC_ALWAYSONTOP:
|
|
{
|
|
context->AlwaysOnTop = !context->AlwaysOnTop;
|
|
SetWindowPos(hwndDlg, context->AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
|
|
0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
|
|
PhSetIntegerSetting(SETTING_NAME_ALWAYSONTOP, context->AlwaysOnTop);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case WM_NOTIFY:
|
|
{
|
|
LPNMHDR hdr = (LPNMHDR)lParam;
|
|
|
|
switch (hdr->code)
|
|
{
|
|
case NM_RCLICK:
|
|
{
|
|
if (hdr->hwndFrom == context->ListViewHandle)
|
|
{
|
|
ShowListViewMenu(context);
|
|
}
|
|
}
|
|
break;
|
|
case NM_DBLCLK:
|
|
{
|
|
PDEBUG_LOG_ENTRY entry;
|
|
INT index;
|
|
|
|
index = PhFindListViewItemByFlags(context->ListViewHandle, -1, LVNI_SELECTED);
|
|
|
|
if (index == -1)
|
|
break;
|
|
|
|
entry = context->LogMessageList->Items[index];
|
|
|
|
DialogBoxParam(
|
|
PluginInstance->DllBase,
|
|
MAKEINTRESOURCE(IDD_MESSAGE_DIALOG),
|
|
hwndDlg,
|
|
DbgPropDlgProc,
|
|
(LPARAM)entry
|
|
);
|
|
}
|
|
break;
|
|
case LVN_GETDISPINFO:
|
|
{
|
|
NMLVDISPINFO* dispInfo = (NMLVDISPINFO*)hdr;
|
|
PDEBUG_LOG_ENTRY entry;
|
|
|
|
entry = context->LogMessageList->Items[dispInfo->item.iItem];
|
|
|
|
if (dispInfo->item.mask & LVIF_IMAGE)
|
|
{
|
|
dispInfo->item.iImage = entry->ImageIndex;
|
|
}
|
|
|
|
if (dispInfo->item.iSubItem == 0)
|
|
{
|
|
if (dispInfo->item.mask & LVIF_TEXT)
|
|
{
|
|
wcsncpy_s(
|
|
dispInfo->item.pszText,
|
|
dispInfo->item.cchTextMax,
|
|
entry->ProcessName->Buffer,
|
|
_TRUNCATE
|
|
);
|
|
}
|
|
}
|
|
else if (dispInfo->item.iSubItem == 1)
|
|
{
|
|
if (dispInfo->item.mask & LVIF_TEXT)
|
|
{
|
|
SYSTEMTIME systemTime;
|
|
PPH_STRING dateTime;
|
|
PPH_STRING dateString;
|
|
|
|
PhLargeIntegerToLocalSystemTime(&systemTime, &entry->Time);
|
|
|
|
dateTime = PhFormatTime(&systemTime, L"hh:mm:ss");
|
|
dateString = PhFormatString(
|
|
L"%s.%u",
|
|
dateTime->Buffer,
|
|
systemTime.wMilliseconds
|
|
);
|
|
|
|
wcsncpy_s(
|
|
dispInfo->item.pszText,
|
|
dispInfo->item.cchTextMax,
|
|
dateString->Buffer,
|
|
_TRUNCATE
|
|
);
|
|
|
|
PhDereferenceObject(dateString);
|
|
PhDereferenceObject(dateTime);
|
|
}
|
|
}
|
|
else if (dispInfo->item.iSubItem == 2)
|
|
{
|
|
if (dispInfo->item.mask & LVIF_TEXT)
|
|
{
|
|
wcsncpy_s(
|
|
dispInfo->item.pszText,
|
|
dispInfo->item.cchTextMax,
|
|
entry->Message->Buffer,
|
|
_TRUNCATE
|
|
);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case WM_DEBUG_LOG_UPDATED:
|
|
DbgUpdateLogList(context);
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
NTSTATUS DbgViewDialogThread(
|
|
_In_ PVOID Parameter
|
|
)
|
|
{
|
|
BOOL result;
|
|
MSG message;
|
|
PH_AUTO_POOL autoPool;
|
|
|
|
PhInitializeAutoPool(&autoPool);
|
|
|
|
DbgDialogHandle = CreateDialog(
|
|
PluginInstance->DllBase,
|
|
MAKEINTRESOURCE(IDD_DBGVIEW_DIALOG),
|
|
NULL,
|
|
DbgViewDlgProc
|
|
);
|
|
|
|
PhSetEvent(&InitializedEvent);
|
|
|
|
while (result = GetMessage(&message, NULL, 0, 0))
|
|
{
|
|
if (result == -1)
|
|
break;
|
|
|
|
if (!IsDialogMessage(DbgDialogHandle, &message))
|
|
{
|
|
TranslateMessage(&message);
|
|
DispatchMessage(&message);
|
|
}
|
|
|
|
PhDrainAutoPool(&autoPool);
|
|
}
|
|
|
|
PhDeleteAutoPool(&autoPool);
|
|
PhResetEvent(&InitializedEvent);
|
|
|
|
if (DbgDialogThreadHandle)
|
|
{
|
|
NtClose(DbgDialogThreadHandle);
|
|
DbgDialogThreadHandle = NULL;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID ShowDebugEventsDialog(
|
|
VOID
|
|
)
|
|
{
|
|
if (!DbgDialogThreadHandle)
|
|
{
|
|
if (!(DbgDialogThreadHandle = PhCreateThread(0, DbgViewDialogThread, NULL)))
|
|
{
|
|
PhShowStatus(PhMainWndHandle, L"Unable to create the window.", 0, GetLastError());
|
|
return;
|
|
}
|
|
|
|
PhWaitForEvent(&InitializedEvent, NULL);
|
|
}
|
|
|
|
PostMessage(DbgDialogHandle, WM_SHOWDIALOG, 0, 0);
|
|
} |