1
0
mirror of https://github.com/UzixLS/KernelEx.git synced 2025-07-18 23:11:19 +03:00
Files
KernelEx/ApiHook/DebugWindow/DebugWindow.cpp
2018-11-03 16:23:39 +03:00

440 lines
10 KiB
C++
Executable File

/*
* KernelEx
* Copyright (C) 2009, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx 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; version 2 of the License.
*
* KernelEx 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 GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <windows.h>
#include <commctrl.h>
#include <malloc.h>
#include "DebugWindow.h"
#include "resource.h"
#define DEBUGMSG_MAXLEN 256
extern "C"
char* strtok_r(char* s, const char* delim, char** holder);
static bool apilog_enabled;
const unsigned short WM_KEXAPPENDLOG = 0x6eef;
HINSTANCE hInstance;
DebugWindow::DebugWindow()
{
hwnd = (HWND) -1;
//we're interested in everything
includes.push_back("*");
//these usually aren't interesting
excludes.push_back("Tls");
excludes.push_back("Heap");
excludes.push_back("CriticalSection");
excludes.push_back("Interlocked");
InitCommonControls();
}
DebugWindow::~DebugWindow()
{
}
BOOL CALLBACK DebugWindow::DebugDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
NMHDR* nmhdr;
DebugWindow* _this = (DebugWindow*) GetWindowLong(hwnd, GWL_USERDATA);
switch (msg)
{
case WM_INITDIALOG:
_this = (DebugWindow*) lParam;
SetWindowLong(hwnd, GWL_USERDATA, lParam);
_this->InitDialog(hwnd);
break;
case WM_SIZE:
MoveWindow(GetDlgItem(hwnd, IDC_LOG), 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
SendDlgItemMessage(hwnd, IDC_LOG, WM_VSCROLL, SB_BOTTOM, 0);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_KEXAPPENDLOG:
_this->append((const char*) lParam);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_NOTIFY:
nmhdr = (NMHDR*) lParam;
if (nmhdr->idFrom == IDC_LOG)
if (nmhdr->code == NM_RCLICK)
{
_this->HandleMenu(hwnd);
break;
}
else if (nmhdr->code == LVN_KEYDOWN)
{
LPNMLVKEYDOWN nm = (LPNMLVKEYDOWN) lParam;
if (nm->wVKey == VK_DELETE)
{
_this->DeleteSelItems();
break;
}
}
default:
return FALSE;
}
return TRUE;
}
void DebugWindow::InitDialog(HWND hwnd)
{
hList = GetDlgItem(hwnd, IDC_LOG);
MoveWindow(hwnd, 0, 0, 480, 200, TRUE);
SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE,
0, LVS_EX_FULLROWSELECT);
LV_COLUMN col;
memset(&col, 0, sizeof(col));
col.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH | LVCF_FMT;
col.cx = 20;
col.pszText = "Depth";
col.fmt = LVCFMT_RIGHT;
ListView_InsertColumn(hList, 0, &col);
col.cx = 60;
col.fmt = LVCFMT_LEFT;
col.pszText = "Thread";
ListView_InsertColumn(hList, 1, &col);
col.cx = 310;
col.pszText = "Info";
ListView_InsertColumn(hList, 2, &col);
col.cx = 60;
col.fmt = LVCFMT_RIGHT;
col.pszText = "Return";
ListView_InsertColumn(hList, 3, &col);
#define NUM_COLS 4
menu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_LOGMENU));
menu = GetSubMenu(menu, 0);
}
void DebugWindow::HandleMenu(HWND hwnd)
{
POINT p;
GetCursorPos(&p);
int res = TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD,
p.x, p.y, 0, hwnd, NULL);
switch (res)
{
case IDM_ENABLE:
apilog_enabled = !apilog_enabled;
CheckMenuItem(menu, IDM_ENABLE, apilog_enabled ? MF_CHECKED : MF_UNCHECKED);
break;
case IDM_TOFILE:
WriteToFile();
break;
case IDM_CLEAR:
//FIXME: when there is a lot of entries it takes very long to clear the list
//how to improve this?
ListView_DeleteAllItems(hList);
break;
case IDM_FILTER:
DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_DEBUGFILTER),
hwnd, FilterDlgProc, (LPARAM) this);
break;
}
}
void DebugWindow::DeleteSelItems()
{
if (ListView_GetSelectedCount(hList) == 0)
return;
for (int i = ListView_GetItemCount(hList) - 1 ; i >= 0 ; i--)
{
if (ListView_GetItemState(hList, i, LVIS_SELECTED))
ListView_DeleteItem(hList, i);
}
}
void DebugWindow::ListView_Append(char* msg)
{
LV_ITEM item;
int idx;
HWND hList = GetDlgItem(hwnd, IDC_LOG);
char* p;
char* pch;
memset(&item, 0, sizeof(item));
pch = strtok_r(msg, "|", &p);
if (!pch)
return;
int items = ListView_GetItemCount(hList);
if (items >= 1000)
{
ListView_DeleteItem(hList, 0);
items--;
}
item.mask = LVIF_TEXT;
item.iItem = items;
item.iSubItem = 0;
item.pszText = pch;
idx = ListView_InsertItem(hList, &item);
while ((pch = strtok_r(NULL, "|", &p)) != NULL)
{
item.iSubItem++;
item.pszText = pch;
ListView_SetItem(hList, &item);
}
}
BOOL CALLBACK DebugWindow::FilterDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
DebugWindow* _this = (DebugWindow*) GetWindowLong(hwnd, GWL_USERDATA);
int len1, len2;
char* buf;
char* pch;
char* p;
list<sstring>::const_iterator it;
switch (msg)
{
case WM_INITDIALOG:
_this = (DebugWindow*) lParam;
SetWindowLong(hwnd, GWL_USERDATA, lParam);
len1 = 0;
len2 = 0;
for (it = _this->includes.begin() ; it != _this->includes.end() ; it++)
len1 += it->length() + 1;
for (it = _this->excludes.begin() ; it != _this->excludes.end() ; it++)
len2 += it->length() + 1;
buf = (char*) alloca(max(len1, len2));
buf[0] = '\0';
for (it = _this->includes.begin() ; it != _this->includes.end() ; it++)
{
if (it != _this->includes.begin())
strcat(buf, ";");
strcat(buf, *it);
}
SetDlgItemText(hwnd, IDC_DFINCLUDE, buf);
buf[0] = '\0';
for (it = _this->excludes.begin() ; it != _this->excludes.end() ; it++)
{
if (it != _this->excludes.begin())
strcat(buf, ";");
strcat(buf, *it);
}
SetDlgItemText(hwnd, IDC_DFEXCLUDE, buf);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDCANCEL:
EndDialog(hwnd, 0);
break;
case IDOK:
len1 = GetWindowTextLength(GetDlgItem(hwnd, IDC_DFINCLUDE)) + 1;
len2 = GetWindowTextLength(GetDlgItem(hwnd, IDC_DFEXCLUDE)) + 1;
buf = (char*) alloca(max(len1, len2));
GetDlgItemText(hwnd, IDC_DFINCLUDE, buf, len1);
_this->includes.clear();
pch = strtok_r(buf, ";", &p);
if (pch)
{
_this->includes.push_back(pch);
while ((pch = strtok_r(NULL, ";", &p)) != NULL)
_this->includes.push_back(pch);
}
GetDlgItemText(hwnd, IDC_DFEXCLUDE, buf, len2);
_this->excludes.clear();
pch = strtok_r(buf, ";", &p);
if (pch)
{
_this->excludes.push_back(pch);
while ((pch = strtok_r(NULL, ";", &p)) != NULL)
_this->excludes.push_back(pch);
}
EndDialog(hwnd, 0);
break;
}
break;
case WM_CLOSE:
EndDialog(hwnd, 0);
break;
default:
return FALSE;
}
return TRUE;
}
void DebugWindow::WriteToFile()
{
char buf[DEBUGMSG_MAXLEN];
OPENFILENAME ofn;
int rows;
LV_COLUMN col;
char filename[MAX_PATH];
HANDLE hFile;
HMODULE hComDlg32;
BOOL (WINAPI* pGetSaveFileName)(OPENFILENAME*);
hComDlg32 = GetModuleHandle("COMDLG32.DLL");
if (!hComDlg32)
hComDlg32 = LoadLibrary("COMDLG32.DLL");
if (!hComDlg32)
return;
pGetSaveFileName = (BOOL (WINAPI*)(OPENFILENAME*))
GetProcAddress(hComDlg32, "GetSaveFileNameA");
if (!pGetSaveFileName)
return;
filename[0] = '\0';
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.hInstance = hInstance;
ofn.lpstrFilter = "Text file\0*.txt\0";
ofn.lpstrDefExt = ".txt";
ofn.lpstrFile = filename;
ofn.nMaxFile = sizeof(filename);
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
if (!pGetSaveFileName(&ofn))
return;
hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return;
//write column headers
col.mask = LVCF_TEXT;
col.pszText = buf;
col.cchTextMax = sizeof(buf);
DWORD wlen;
for (int j = 0 ; j < NUM_COLS ; j++)
{
DWORD len;
ListView_GetColumn(hList, j, &col);
len = strlen(buf);
if (j) WriteFile(hFile, " ", 1, &wlen, NULL);
WriteFile(hFile, buf, len, &wlen, NULL);
}
WriteFile(hFile, "\r\n", 2, &wlen, NULL);
//write rows
rows = ListView_GetItemCount(hList);
for (int i = 0 ; i < rows ; i++)
{
for (int j = 0 ; j < NUM_COLS ; j++)
{
DWORD len; DWORD wlen;
ListView_GetItemText(hList, i, j, buf, sizeof(buf));
len = strlen(buf);
if (j == 1 || j == 2) WriteFile(hFile, " ", 1, &wlen, NULL);
else if (j == 3 && len) WriteFile(hFile, " = ", 3, &wlen, NULL);
WriteFile(hFile, buf, len, &wlen, NULL);
}
WriteFile(hFile, "\r\n", 2, &wlen, NULL);
}
CloseHandle(hFile);
MessageBox(hwnd, "File written successfully", "Information", MB_ICONINFORMATION | MB_OK);
}
void DebugWindow::msgloop()
{
MSG msg;
hwnd = CreateDialogParam(hInstance, MAKEINTRESOURCE(IDD_DEBUG),
NULL, DebugDlgProc, (LPARAM) this);
ShowWindow(hwnd, SW_SHOW);
while (GetMessage(&msg, NULL, 0, 0))
DispatchMessage(&msg);
}
void DebugWindow::append(const char* str)
{
static char msg[DEBUGMSG_MAXLEN];
bool filter_out = true;
//filter out based on includes and excludes
if (includes.size() != 0)
{
if (includes.size() == 1 && strcmp(includes.front(), "*") == 0)
filter_out = false;
else
{
list<sstring>::const_iterator it;
for (it = includes.begin() ; it != includes.end() ; it++)
if (strstr(str, *it))
{
filter_out = false;
break;
}
}
}
if (!filter_out)
{
list<sstring>::const_iterator it;
for (it = excludes.begin() ; it != excludes.end() ; it++)
if (strstr(str, *it))
{
filter_out = true;
break;
}
}
if (filter_out)
return;
strncpy(msg, str, sizeof(msg));
msg[sizeof(msg) - 1] = '\0';
ListView_Append(msg);
SendMessage(hList, WM_VSCROLL, SB_BOTTOM, 0);
}
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
hInstance = hinstance;
DebugWindow dw;
dw.msgloop();
return 0;
}