1
0
Fork 0

Compare commits

...

17 Commits

Author SHA1 Message Date
Duncan Ogilvie 17621d845c
Merge pull request #3133 from Bluefissure/log-commands
Add Commands: LogSave, LogRedirect, LogRedirectStop
2023-08-01 13:47:49 +02:00
Duncan Ogilvie ea631d4539 Move currentDateTime suffix to isoDateTime in StringUtil.h 2023-08-01 13:47:23 +02:00
Duncan Ogilvie dd76320156 Fix some naming inconsistencies 2023-08-01 13:38:30 +02:00
Bluefissure 4c713b08f4 fix: update log commands 2023-08-01 13:32:34 +02:00
Bluefissure 956072ad02 feat: logsave, logredirect, logredirectstop 2023-08-01 13:32:31 +02:00
Duncan Ogilvie 6575efc266
Merge pull request #3155 from m417z/dbg-set-encoded-type-oob
Fix a DbgSetEncodeType crash if an out-of-date db file is used
2023-08-01 13:24:05 +02:00
Duncan Ogilvie f62323765d
Merge pull request #3154 from torusrxxx/patch000000f3
Add accessible names
2023-08-01 13:17:13 +02:00
Duncan Ogilvie 8cd3e1df5a
Merge pull request #3156 from P1tt1cus/gzip-decompression
Adding gzip decompression to downlibs
2023-08-01 13:15:58 +02:00
pitticus 3b8f95adfa Amended formatting 2023-07-30 17:13:12 +10:00
pitticus 8f06703061 Updated downslib
- Added support for GZIP decompression
- Increased chunk_size for the buffer to 8kb
- Changed how header information is queried using HttpQueryInfoA using
HTTP_QUERY_FLAG_NUMBER rather than copying it into the char buffer
2023-07-30 16:41:04 +10:00
pitticus 4d725925d0 Get metrics regarding symbol download time 2023-07-30 16:40:02 +10:00
Michael Maltsev 1515a5a5fc Fix a DbgSetEncodeType crash if an out-of-date db file is used 2023-07-29 21:08:40 +03:00
torusrxxx ec86ad10d3
Add accessible names 2023-07-29 10:21:26 +08:00
Duncan Ogilvie de494c1fc7
Merge pull request #3147 from torusrxxx/patch000000f1
add isdebuggerfocused() to determine if x64dbg is focused
2023-07-28 09:20:38 +02:00
Duncan Ogilvie 4451b33515
Merge pull request #3152 from torusrxxx/patch000000f2
Setting buddy for labels
2023-07-28 09:09:09 +02:00
torusrxxx 2240fbd223
Setting buddy for labels 2023-07-28 11:44:44 +08:00
torusrxxx 415ee4235b
add isdebuggerfocused() to determine if x64dbg is focused 2023-07-24 22:25:41 +08:00
27 changed files with 374 additions and 87 deletions

View File

@ -1361,6 +1361,21 @@ BRIDGE_IMPEXP void GuiLogClear()
_gui_sendmessage(GUI_CLEAR_LOG, 0, 0);
}
BRIDGE_IMPEXP void GuiLogSave(const char* filename)
{
_gui_sendmessage(GUI_SAVE_LOG, (void*)filename, 0);
}
BRIDGE_IMPEXP void GuiLogRedirect(const char* filename)
{
_gui_sendmessage(GUI_REDIRECT_LOG, (void*)filename, 0);
}
BRIDGE_IMPEXP void GuiLogRedirectStop()
{
_gui_sendmessage(GUI_STOP_REDIRECT_LOG, 0, 0);
}
BRIDGE_IMPEXP void GuiUpdateEnable(bool updateNow)
{
bDisableGUIUpdate = false;
@ -1997,6 +2012,11 @@ BRIDGE_IMPEXP DWORD GuiGetMainThreadId()
return (DWORD)(duint)_gui_sendmessage(GUI_GET_MAIN_THREAD_ID, nullptr, nullptr);
}
BRIDGE_IMPEXP bool GuiIsDebuggerFocused()
{
return (bool)(duint)_gui_sendmessage(GUI_IS_DEBUGGER_FOCUSED, nullptr, nullptr);
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
hInst = hinstDLL;

View File

@ -1126,6 +1126,7 @@ BRIDGE_IMPEXP void DbgGetSymbolInfo(const SYMBOLPTR* symbolptr, SYMBOLINFO* info
BRIDGE_IMPEXP DEBUG_ENGINE DbgGetDebugEngine();
BRIDGE_IMPEXP bool DbgGetSymbolInfoAt(duint addr, SYMBOLINFO* info);
BRIDGE_IMPEXP duint DbgXrefAddMulti(const XREF_EDGE* edges, duint count);
BRIDGE_IMPEXP bool GuiIsDebuggerFocused();
//Gui defines
typedef enum
@ -1274,6 +1275,10 @@ typedef enum
GUI_GET_MAIN_THREAD_ID, // param1=unused, param2=unused
GUI_ADD_MSG_TO_LOG_HTML, // param1=(const char*)msg, param2=unused
GUI_IS_LOG_ENABLED, // param1=unused, param2=unused
GUI_IS_DEBUGGER_FOCUSED, // param1=unused, param2=unused
GUI_SAVE_LOG, // param1=const char* file name,param2=unused
GUI_REDIRECT_LOG, // param1=const char* file name,param2=unused
GUI_STOP_REDIRECT_LOG, // param1=unused, param2=unused
} GUIMSG;
//GUI Typedefs
@ -1343,6 +1348,9 @@ BRIDGE_IMPEXP void GuiSetDebugStateFast(DBGSTATE state);
BRIDGE_IMPEXP void GuiAddLogMessage(const char* msg);
BRIDGE_IMPEXP void GuiAddLogMessageHtml(const char* msg);
BRIDGE_IMPEXP void GuiLogClear();
BRIDGE_IMPEXP void GuiLogSave(const char* filename);
BRIDGE_IMPEXP void GuiLogRedirect(const char* filename);
BRIDGE_IMPEXP void GuiLogRedirectStop();
BRIDGE_IMPEXP void GuiUpdateAllViews();
BRIDGE_IMPEXP void GuiUpdateRegisterView();
BRIDGE_IMPEXP void GuiUpdateDisassemblyView();

View File

@ -27,6 +27,10 @@ downslib_error downslib_download(const char* url,
HINTERNET hInternet = nullptr;
HINTERNET hUrl = nullptr;
HANDLE hFile = nullptr;
DWORD dwBufferSize = 0;
const char* headers = nullptr;
DWORD dwHeaderslen = 0;
const DWORD chunk_size = 8192;
Cleanup cleanup([&]()
{
@ -51,6 +55,7 @@ downslib_error downslib_download(const char* url,
SetLastError(dwLastError);
});
// Create the PDB file that will be written to
hFile = CreateFileW(filename, GENERIC_WRITE | FILE_READ_ATTRIBUTES, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
return downslib_error::createfile;
@ -64,57 +69,66 @@ downslib_error downslib_download(const char* url,
if(!hInternet)
return downslib_error::inetopen;
// Set a time-out value in milliseconds
InternetSetOptionA(hInternet,
INTERNET_OPTION_RECEIVE_TIMEOUT,
&timeout,
sizeof(timeout));
// Attempt to enable content decoding if the option is supported
DWORD gzipDecoding = true;
if(InternetSetOptionA(hInternet,
INTERNET_OPTION_HTTP_DECODING,
&gzipDecoding,
sizeof(gzipDecoding)))
{
// Add the required request headers
headers = "Accept-Encoding: gzip\r\n";
dwHeaderslen = static_cast<DWORD>(strlen(headers));
}
DWORD dwFlags = INTERNET_FLAG_RELOAD;
if(strncmp(url, "https://", 8) == 0)
dwFlags |= INTERNET_FLAG_SECURE;
hUrl = InternetOpenUrlA(hInternet, url, NULL, 0, dwFlags, 0);
// Make the HTTP request
hUrl = InternetOpenUrlA(hInternet, url, headers, dwHeaderslen, dwFlags, 0);
if(!hUrl)
return downslib_error::openurl;
// Get HTTP content length
char buffer[2048];
memset(buffer, 0, sizeof(buffer));
DWORD dwLen = sizeof(buffer);
unsigned long long total_bytes = 0;
if(HttpQueryInfoA(hUrl, HTTP_QUERY_CONTENT_LENGTH, buffer, &dwLen, 0))
{
if(sscanf_s(buffer, "%llu", &total_bytes) != 1)
total_bytes = 0;
}
// Get HTTP status code
dwLen = sizeof(buffer);
if(HttpQueryInfoA(hUrl, HTTP_QUERY_STATUS_CODE, buffer, &dwLen, 0))
DWORD dwStatusCode;
dwBufferSize = sizeof(dwStatusCode);
if(HttpQueryInfoA(hUrl, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwStatusCode, &dwBufferSize, 0))
{
int status_code = 0;
if(sscanf_s(buffer, "%d", &status_code) != 1)
status_code = 500;
if(status_code != 200)
if(dwStatusCode != 200)
{
SetLastError(status_code);
SetLastError(dwStatusCode);
return downslib_error::statuscode;
}
}
// Get HTTP content length
unsigned long long contentLength = 0;
dwBufferSize = sizeof(contentLength);
HttpQueryInfoA(hUrl, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &contentLength, &dwBufferSize, 0);
// Receive the data from the HINTERNET handle
char buffer[chunk_size];
DWORD dwRead = 0;
DWORD dwWritten = 0;
unsigned long long read_bytes = 0;
unsigned long long readBytes = 0;
unsigned long long totalBytes = contentLength;
while(InternetReadFile(hUrl, buffer, sizeof(buffer), &dwRead))
{
read_bytes += dwRead;
readBytes += dwRead;
// We are done if nothing more to read, so now we can report total size in our final cb call
if(dwRead == 0)
total_bytes = read_bytes;
totalBytes = readBytes;
// Call the callback to report progress and cancellation
if(cb && !cb(userdata, read_bytes, total_bytes))
if(cb && !cb(userdata, readBytes, totalBytes))
{
SetLastError(ERROR_OPERATION_ABORTED);
return downslib_error::cancel;
@ -124,10 +138,19 @@ downslib_error downslib_download(const char* url,
if(dwRead == 0)
break;
// Write buffer to PDB file
WriteFile(hFile, buffer, dwRead, &dwWritten, nullptr);
// Check WriteFile successfully wrote the entire buffer
if(dwWritten != dwRead)
{
SetLastError(ERROR_IO_INCOMPLETE);
return downslib_error::incomplete;
}
}
if(total_bytes > 0 && read_bytes != total_bytes)
if(totalBytes > 0 && readBytes != totalBytes)
{
SetLastError(ERROR_IO_INCOMPLETE);
return downslib_error::incomplete;

View File

@ -82,7 +82,31 @@ struct EncodeMap : AddrInfoHashMap<LockEncodeMaps, ENCODEMAP, EncodeMapSerialize
static EncodeMap encmaps;
static bool EncodeMapGetorCreate(duint addr, ENCODEMAP & map, bool* created = nullptr)
static bool EncodeMapValidateModuleInfo(duint key, ENCODEMAP & map, duint segsize)
{
// The map size might be smaller if it was loaded from cache for another
// version of the module. Adjust the size in this case.
if(map.size < segsize)
{
byte* newData = (byte*)VirtualAlloc(NULL, segsize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if(newData == NULL) return false;
memcpy(newData, map.data, map.size);
DecreaseReferenceCount(map.data);
VirtualFree(map.data, 0, MEM_RELEASE);
encmaps.Delete(key);
map.size = segsize;
map.data = newData;
IncreaseReferenceCount(map.data);
encmaps.Add(map);
}
return true;
}
static bool EncodeMapGet(duint addr, ENCODEMAP & map, duint* baseOut = nullptr)
{
duint base, segsize;
@ -90,8 +114,32 @@ static bool EncodeMapGetorCreate(duint addr, ENCODEMAP & map, bool* created = nu
if(!base)
return false;
if(baseOut)
*baseOut = base;
duint key = EncodeMap::VaKey(base);
if(!encmaps.Contains(key))
if(!encmaps.Get(key, map))
return false;
if(!EncodeMapValidateModuleInfo(key, map, segsize))
return false;
return true;
}
static bool EncodeMapGetorCreate(duint addr, ENCODEMAP & map, duint* baseOut = nullptr, bool* created = nullptr)
{
duint base, segsize;
base = MemFindBaseAddr(addr, &segsize);
if(!base)
return false;
if(baseOut)
*baseOut = base;
duint key = EncodeMap::VaKey(base);
if(!encmaps.Get(key, map))
{
if(created)
*created = true;
@ -104,7 +152,9 @@ static bool EncodeMapGetorCreate(duint addr, ENCODEMAP & map, bool* created = nu
}
else
{
if(!encmaps.Get(key, map))
if(created)
*created = false;
if(!EncodeMapValidateModuleInfo(key, map, segsize))
return false;
}
return true;
@ -112,10 +162,9 @@ static bool EncodeMapGetorCreate(duint addr, ENCODEMAP & map, bool* created = nu
void* EncodeMapGetBuffer(duint addr, duint* size, bool create)
{
auto base = MemFindBaseAddr(addr);
ENCODEMAP map;
if(create ? EncodeMapGetorCreate(addr, map) : encmaps.Get(EncodeMap::VaKey(base), map))
duint base;
if(create ? EncodeMapGetorCreate(addr, map, &base) : EncodeMapGet(addr, map, &base))
{
auto offset = addr - base;
if(offset < map.size)
@ -188,11 +237,9 @@ static bool IsCodeType(ENCODETYPE type)
ENCODETYPE EncodeMapGetType(duint addr, duint codesize)
{
duint size;
auto base = MemFindBaseAddr(addr, &size);
ENCODEMAP map;
if(base && encmaps.Get(EncodeMap::VaKey(base), map))
duint base;
if(EncodeMapGet(addr, map, &base))
{
auto offset = addr - base;
if(offset >= map.size)
@ -205,12 +252,9 @@ ENCODETYPE EncodeMapGetType(duint addr, duint codesize)
duint EncodeMapGetSize(duint addr, duint codesize)
{
auto base = MemFindBaseAddr(addr, nullptr);
if(!base)
return codesize;
ENCODEMAP map;
if(encmaps.Get(EncodeMap::VaKey(base), map))
duint base;
if(EncodeMapGet(addr, map, &base))
{
auto offset = addr - base;
if(offset >= map.size)
@ -227,14 +271,9 @@ duint EncodeMapGetSize(duint addr, duint codesize)
bool EncodeMapSetType(duint addr, duint size, ENCODETYPE type, bool* created)
{
auto base = MemFindBaseAddr(addr, nullptr);
if(!base)
return false;
ENCODEMAP map;
if(created)
*created = false;
if(!EncodeMapGetorCreate(base, map, created))
duint base;
if(!EncodeMapGetorCreate(addr, map, &base, created))
return false;
auto offset = addr - base;
size = min(map.size - offset, size);

View File

@ -152,6 +152,9 @@ void ExpressionFunctions::Init()
//Undocumented
RegisterEasy("bpgoto", bpgoto);
//Other
RegisterEasy("isdebuggerfocused", isdebuggerfocused);
// Strings
ExpressionFunctions::Register("utf8", ValueTypeString, { ValueTypeNumber }, Exprfunc::utf8, nullptr);
ExpressionFunctions::Register("utf16", ValueTypeString, { ValueTypeNumber }, Exprfunc::utf16, nullptr);

View File

@ -600,6 +600,11 @@ namespace Exprfunc
return getLastExceptionInfo().ExceptionRecord.ExceptionInformation[index];
}
duint isdebuggerfocused()
{
return GuiIsDebuggerFocused();
}
bool streq(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
{
assert(argc == 2);

View File

@ -86,6 +86,8 @@ namespace Exprfunc
duint exinfocount();
duint exinfo(duint index);
duint isdebuggerfocused();
bool streq(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
bool strieq(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
bool strstr(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);

View File

@ -286,6 +286,7 @@ bool SymDownloadSymbol(duint Base, const char* SymbolStore)
symprintf(QT_TRANSLATE_NOOP("DBG", "Downloading symbol %s\n Signature: %s\n Destination: %s\n URL: %s\n"), pdbBaseFile, pdbSignature.c_str(), StringUtils::Utf16ToUtf8(symbolPath).c_str(), symbolUrl.c_str());
DWORD lineDownloadStart = GetTickCount();
auto result = downslib_download(symbolUrl.c_str(), symbolPath.c_str(), "x64dbg", 1000, [](void* userdata, unsigned long long read_bytes, unsigned long long total_bytes)
{
if(total_bytes)
@ -324,6 +325,10 @@ bool SymDownloadSymbol(duint Base, const char* SymbolStore)
__debugbreak();
}
DWORD ms = GetTickCount() - lineDownloadStart;
double secs = (double)ms / 1000.0;
symprintf(QT_TRANSLATE_NOOP("DBG", "Finished downloading symbol %s in %.03fs\n"), pdbBaseFile, secs);
{
EXCLUSIVE_ACQUIRE(LockModules);
auto info = ModInfoFromAddr(Base);

View File

@ -50,6 +50,29 @@ static bool cbClearLog(int argc, char* argv[])
return true;
}
static bool cbSaveLog(int argc, char* argv[])
{
if(argc < 2)
GuiLogSave(nullptr);
else
GuiLogSave(argv[1]);
return true;
}
static bool cbRedirectLog(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 2))
return false;
GuiLogRedirect(argv[1]);
return true;
}
static bool cbStopRedirectLog(int argc, char* argv[])
{
GuiLogRedirectStop();
return true;
}
static bool cbPrintf(int argc, char* argv[])
{
if(argc < 2)
@ -406,6 +429,9 @@ static void registercommands()
dbgcmdnew("EnableLog,LogEnable", cbInstrEnableLog, false); //enable log
dbgcmdnew("DisableLog,LogDisable", cbInstrDisableLog, false); //disable log
dbgcmdnew("ClearLog,cls,lc,lclr", cbClearLog, false); //clear the log
dbgcmdnew("SaveLog,LogSave", cbSaveLog, false); //save the log
dbgcmdnew("RedirectLog,LogRedirect", cbRedirectLog, false); //redirect the log
dbgcmdnew("StopRedirectLog,LogRedirectStop", cbStopRedirectLog, false); //stop redirecting the log
dbgcmdnew("AddFavouriteTool", cbInstrAddFavTool, false); //add favourite tool
dbgcmdnew("AddFavouriteCommand", cbInstrAddFavCmd, false); //add favourite command
dbgcmdnew("AddFavouriteToolShortcut,SetFavouriteToolShortcut", cbInstrSetFavToolShortcut, false); //set favourite tool shortcut

View File

@ -62,7 +62,9 @@ SearchListView::SearchListView(QWidget* parent, AbstractSearchList* abstractSear
QHBoxLayout* horzLayout = new QHBoxLayout();
horzLayout->setContentsMargins(4, 0, (enableRegex || enableLock) ? 0 : 4, 0);
horzLayout->setSpacing(2);
horzLayout->addWidget(new QLabel(tr("Search: ")));
QLabel* label = new QLabel(tr("Search: "), this);
label->setBuddy(mSearchBox);
horzLayout->addWidget(label);
horzLayout->addWidget(mSearchBox);
horzLayout->addWidget(mLockCheckbox);
horzLayout->addWidget(mRegexCheckbox);

View File

@ -127,6 +127,21 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
emit clearLog();
break;
case GUI_SAVE_LOG:
if(!param1)
emit saveLog();
else
emit saveLogToFile(QString((const char*)param1));
break;
case GUI_REDIRECT_LOG:
emit redirectLogToFile(QString((const char*)param1));
break;
case GUI_STOP_REDIRECT_LOG:
emit redirectLogStop();
break;
case GUI_UPDATE_REGISTER_VIEW:
emit updateRegisters();
break;
@ -905,6 +920,9 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
case GUI_GET_MAIN_THREAD_ID:
return (void*)dwMainThreadId;
case GUI_IS_DEBUGGER_FOCUSED:
return (void*)!!QApplication::activeWindow();
}
return nullptr;

View File

@ -53,6 +53,10 @@ signals:
void addMsgToLog(QByteArray msg);
void addMsgToLogHtml(QByteArray msg);
void clearLog();
void saveLog();
void saveLogToFile(QString file);
void redirectLogStop();
void redirectLogToFile(QString filename);
void shutdown();
void updateRegisters();
void updateBreakpoints();

View File

@ -28,6 +28,9 @@
<property name="text">
<string>Path:</string>
</property>
<property name="buddy">
<cstring>lineEdit</cstring>
</property>
</widget>
</item>
<item>

View File

@ -87,6 +87,14 @@ CPUWidget::CPUWidget(QWidget* parent) : QWidget(parent), ui(new Ui::CPUWidget)
ui->mBotRightFrameLayout->addWidget(mStack);
connect(mDisas, SIGNAL(selectionChanged(dsint)), mStack, SLOT(disasmSelectionChanged(dsint)));
mDisas->setAccessibleName(tr("Disassembly"));
mStack->setAccessibleName(tr("Stack"));
upperScrollArea->setAccessibleName(tr("Registers"));
mDump->setAccessibleName(tr("Dump"));
mArgumentWidget->setAccessibleName(tr("Arguments"));
mSideBar->setAccessibleName(tr("Sidebar"));
mInfo->setAccessibleName(tr("InfoBox"));
// load column config
mDisas->loadColumnFromConfig("CPUDisassembly");
mStack->loadColumnFromConfig("CPUStack");

View File

@ -31,6 +31,9 @@
<property name="text">
<string>Signed:</string>
</property>
<property name="buddy">
<cstring>txtSignedDec</cstring>
</property>
</widget>
</item>
<item row="3" column="0">
@ -38,6 +41,9 @@
<property name="text">
<string>Unsigned:</string>
</property>
<property name="buddy">
<cstring>txtUnsignedDec</cstring>
</property>
</widget>
</item>
<item row="10" column="0">
@ -45,6 +51,9 @@
<property name="text">
<string>Unicode:</string>
</property>
<property name="buddy">
<cstring>txtUnicode</cstring>
</property>
</widget>
</item>
<item row="5" column="0">
@ -52,6 +61,9 @@
<property name="text">
<string>Octal:</string>
</property>
<property name="buddy">
<cstring>txtOct</cstring>
</property>
</widget>
</item>
<item row="0" column="0">
@ -59,6 +71,9 @@
<property name="text">
<string>Expression:</string>
</property>
<property name="buddy">
<cstring>txtExpression</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
@ -102,6 +117,9 @@
<property name="text">
<string>Binary:</string>
</property>
<property name="buddy">
<cstring>txtBin</cstring>
</property>
</widget>
</item>
<item row="9" column="0">
@ -109,6 +127,9 @@
<property name="text">
<string>ASCII:</string>
</property>
<property name="buddy">
<cstring>txtAscii</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
@ -222,6 +243,9 @@
<property name="text">
<string>Hexadecimal:</string>
</property>
<property name="buddy">
<cstring>txtHex</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
@ -260,6 +284,9 @@
<property name="text">
<string>Bytes:</string>
</property>
<property name="buddy">
<cstring>txtBytes</cstring>
</property>
</widget>
</item>
</layout>

View File

@ -30,6 +30,9 @@
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>editStart</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
@ -46,6 +49,9 @@
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>editEnd</cstring>
</property>
</widget>
</item>
<item row="1" column="1">

View File

@ -137,6 +137,11 @@ HandlesView::HandlesView(QWidget* parent) : QWidget(parent)
mTcpConnectionsTable->reloadData();
}
mWindowsTable->setAccessibleName(tr("Windows"));
mHandlesTable->setAccessibleName(tr("Handles"));
mTcpConnectionsTable->setAccessibleName(tr("TCP Connections"));
mPrivilegesTable->setAccessibleName(tr("Privileges"));
reloadData();
refreshShortcuts();
}

View File

@ -406,6 +406,9 @@
<property name="text">
<string>Items per line:</string>
</property>
<property name="buddy">
<cstring>spinBox</cstring>
</property>
</widget>
</item>
<item>

View File

@ -36,8 +36,12 @@ LogView::LogView(QWidget* parent) : QTextBrowser(parent), logRedirection(NULL)
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(updateStyle()));
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(updateStyle()));
connect(Bridge::getBridge(), SIGNAL(addMsgToLog(QByteArray)), this, SLOT(addMsgToLogSlot(QByteArray)));
connect(Bridge::getBridge(), SIGNAL(addMsgToLogHtml(QByteArray)), this, SLOT(addMsgToLogSlotHtml(QByteArray)));
connect(Bridge::getBridge(), SIGNAL(addMsgToLogHtml(QByteArray)), this, SLOT(addMsgToLogHtmlSlot(QByteArray)));
connect(Bridge::getBridge(), SIGNAL(clearLog()), this, SLOT(clearLogSlot()));
connect(Bridge::getBridge(), SIGNAL(saveLog()), this, SLOT(saveSlot()));
connect(Bridge::getBridge(), SIGNAL(saveLogToFile(QString)), this, SLOT(saveToFileSlot(QString)));
connect(Bridge::getBridge(), SIGNAL(redirectLogToFile(QString)), this, SLOT(redirectLogToFileSlot(QString)));
connect(Bridge::getBridge(), SIGNAL(redirectLogStop()), this, SLOT(stopRedirectLogSlot()));
connect(Bridge::getBridge(), SIGNAL(setLogEnabled(bool)), this, SLOT(setLoggingEnabled(bool)));
connect(Bridge::getBridge(), SIGNAL(flushLog()), this, SLOT(flushLogSlot()));
connect(this, SIGNAL(anchorClicked(QUrl)), this, SLOT(onAnchorClicked(QUrl)));
@ -56,9 +60,9 @@ LogView::LogView(QWidget* parent) : QTextBrowser(parent), logRedirection(NULL)
*/
LogView::~LogView()
{
if(logRedirection != NULL)
if(logRedirection != nullptr)
fclose(logRedirection);
logRedirection = NULL;
logRedirection = nullptr;
}
void LogView::updateStyle()
@ -148,7 +152,7 @@ void LogView::contextMenuEvent(QContextMenuEvent* event)
wMenu.addAction(actionFindInLog);
wMenu.addAction(actionFindNext);
wMenu.addAction(actionFindPrevious);
if(logRedirection == NULL)
if(logRedirection == nullptr)
actionRedirectLog->setText(tr("&Redirect Log..."));
else
actionRedirectLog->setText(tr("Stop &Redirection"));
@ -230,10 +234,10 @@ void LogView::linkify(QString & msg)
}
/**
* @brief LogView::addMsgToLogSlotHtml Adds a HTML message to the log view. This function is a slot for Bridge::addMsgToLogHtml.
* @brief LogView::addMsgToLogHtmlSlot Adds a HTML message to the log view. This function is a slot for Bridge::addMsgToLogHtml.
* @param msg The log message (Which is assumed to contain HTML)
*/
void LogView::addMsgToLogSlotHtml(QByteArray msg)
void LogView::addMsgToLogHtmlSlot(QByteArray msg)
{
LogView::addMsgToLogSlotRaw(msg, false);
}
@ -265,7 +269,7 @@ void LogView::addMsgToLogSlotRaw(QByteArray msg, bool encodeHTML)
// redirect the log
QString msgUtf16;
bool redirectError = false;
if(logRedirection != NULL)
if(logRedirection != nullptr)
{
if(utf16Redirect)
{
@ -274,7 +278,7 @@ void LogView::addMsgToLogSlotRaw(QByteArray msg, bool encodeHTML)
if(!fwrite(msgUtf16.utf16(), msgUtf16.length(), 2, logRedirection))
{
fclose(logRedirection);
logRedirection = NULL;
logRedirection = nullptr;
redirectError = true;
}
}
@ -306,7 +310,7 @@ void LogView::addMsgToLogSlotRaw(QByteArray msg, bool encodeHTML)
if(!fwrite(data, buffersize, 1, logRedirection))
{
fclose(logRedirection);
logRedirection = NULL;
logRedirection = nullptr;
redirectError = true;
}
if(loggingEnabled)
@ -375,30 +379,56 @@ void LogView::clearLogSlot()
this->clear();
}
void LogView::redirectLogSlot()
void LogView::stopRedirectLogSlot()
{
if(logRedirection != NULL)
if(logRedirection != nullptr)
{
fclose(logRedirection);
logRedirection = NULL;
logRedirection = nullptr;
GuiAddLogMessage(tr("Log redirection is stopped.\n").toUtf8().constData());
}
else
{
GuiAddLogMessage(tr("Log is not redirected.\n").toUtf8().constData());
}
}
void LogView::redirectLogToFileSlot(QString filename)
{
if(logRedirection != nullptr)
{
fclose(logRedirection);
logRedirection = nullptr;
GuiAddLogMessage(tr("Log redirection is stopped.\n").toUtf8().constData());
}
logRedirection = _wfopen(filename.toStdWString().c_str(), L"ab");
if(logRedirection == nullptr)
GuiAddLogMessage(tr("_wfopen() failed. Log will not be redirected to %1.\n").arg(QString::fromWCharArray(BridgeUserDirectory())).toUtf8().constData());
else
{
if(utf16Redirect && ftell(logRedirection) == 0)
{
unsigned short BOM = 0xfeff;
fwrite(&BOM, 2, 1, logRedirection);
}
GuiAddLogMessage(tr("Log will be redirected to %1.\n").arg(filename).toUtf8().constData());
}
}
void LogView::redirectLogSlot()
{
if(logRedirection != nullptr)
{
fclose(logRedirection);
logRedirection = nullptr;
GuiAddLogMessage(tr("Log redirection is stopped.\n").toUtf8().constData());
}
else
{
BrowseDialog browse(this, tr("Redirect log to file"), tr("Enter the file to which you want to redirect log messages."), tr("Log files (*.txt);;All files (*.*)"), QString::fromWCharArray(BridgeUserDirectory()), true);
if(browse.exec() == QDialog::Accepted)
{
logRedirection = _wfopen(browse.path.toStdWString().c_str(), L"ab");
if(logRedirection == NULL)
GuiAddLogMessage(tr("_wfopen() failed. Log will not be redirected to %1.\n").arg(browse.path).toUtf8().constData());
else
{
if(utf16Redirect && ftell(logRedirection) == 0)
{
unsigned short BOM = 0xfeff;
fwrite(&BOM, 2, 1, logRedirection);
}
GuiAddLogMessage(tr("Log will be redirected to %1.\n").arg(browse.path).toUtf8().constData());
}
redirectLogToFileSlot(browse.path);
}
}
}
@ -427,13 +457,8 @@ void LogView::autoScrollSlot()
autoScroll = !autoScroll;
}
/**
* @brief LogView::saveSlot Called by "save" action
*/
void LogView::saveSlot()
void LogView::saveToFileSlot(QString fileName)
{
QString fileName;
fileName = QString("log-%1.txt").arg(QDateTime::currentDateTime().toString().replace(QChar(':'), QChar('-')));
QFile savedLog(fileName);
savedLog.open(QIODevice::Append | QIODevice::Text);
if(savedLog.error() != QFile::NoError)
@ -448,6 +473,16 @@ void LogView::saveSlot()
}
}
/**
* @brief LogView::saveSlot Called by "save" action
*/
void LogView::saveSlot()
{
QString fileName;
fileName = QString("log-%1.txt").arg(isoDateTime());
saveToFileSlot(fileName);
}
void LogView::toggleLoggingSlot()
{
setLoggingEnabled(!getLoggingEnabled());

View File

@ -21,7 +21,9 @@ public slots:
void refreshShortcutsSlot();
void updateStyle();
void addMsgToLogSlot(QByteArray msg); /* Non-HTML Log Function*/
void addMsgToLogSlotHtml(QByteArray msg); /* HTML accepting Log Function */
void addMsgToLogHtmlSlot(QByteArray msg); /* HTML accepting Log Function */
void stopRedirectLogSlot();
void redirectLogToFileSlot(QString filename);
void redirectLogSlot();
void setLoggingEnabled(bool enabled);
void autoScrollSlot();
@ -35,6 +37,7 @@ public slots:
void onAnchorClicked(const QUrl & link);
void clearLogSlot();
void saveToFileSlot(QString filename);
void saveSlot();
void toggleLoggingSlot();
void flushTimerSlot();

View File

@ -34,6 +34,9 @@
<property name="text">
<string>Messages:</string>
</property>
<property name="buddy">
<cstring>cboxMessages</cstring>
</property>
</widget>
</item>
<item>

View File

@ -451,6 +451,9 @@
<property name="text">
<string>Animation per-step interval (ms)</string>
</property>
<property name="buddy">
<cstring>spinAnimateInterval</cstring>
</property>
</widget>
</item>
<item>
@ -503,6 +506,9 @@
<property name="text">
<string>Exception Filters:</string>
</property>
<property name="buddy">
<cstring>listExceptions</cstring>
</property>
</widget>
</item>
<item>
@ -986,6 +992,9 @@
<property name="text">
<string>Symbol Store:</string>
</property>
<property name="buddy">
<cstring>editSymbolStore</cstring>
</property>
</widget>
</item>
<item>
@ -993,6 +1002,9 @@
<property name="text">
<string>Symbol Path:</string>
</property>
<property name="buddy">
<cstring>editSymbolCache</cstring>
</property>
</widget>
</item>
</layout>
@ -1023,6 +1035,9 @@
<property name="text">
<string>JIT:</string>
</property>
<property name="buddy">
<cstring>editJIT</cstring>
</property>
</widget>
</item>
<item>

View File

@ -63,6 +63,7 @@ int MHTabWidget::addTabEx(QWidget* widget, const QIcon & icon, const QString & l
{
mNativeNames.append(nativeName);
mHistory.push_back((MIDPKey)widget);
widget->setAccessibleName(label);
return this->addTab(widget, icon, label);
}

View File

@ -31,6 +31,9 @@
<property name="text">
<string>Expression:</string>
</property>
<property name="buddy">
<cstring>expressionLineEdit</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
@ -92,6 +95,9 @@
<property name="text">
<string>Bytes:</string>
</property>
<property name="buddy">
<cstring>hexLineEdit</cstring>
</property>
</widget>
</item>
<item row="3" column="0">
@ -99,6 +105,9 @@
<property name="text">
<string>Unsigned:</string>
</property>
<property name="buddy">
<cstring>unsignedLineEdit</cstring>
</property>
</widget>
</item>
<item row="4" column="0">
@ -106,6 +115,9 @@
<property name="text">
<string>ASCII:</string>
</property>
<property name="buddy">
<cstring>asciiLineEdit</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
@ -113,6 +125,9 @@
<property name="text">
<string>Signed:</string>
</property>
<property name="buddy">
<cstring>signedLineEdit</cstring>
</property>
</widget>
</item>
<item row="3" column="1">

View File

@ -374,15 +374,7 @@ QString getDbPath(const QString & filename, bool addDateTimeSuffix)
{
extensionIdx = path.length();
}
auto now = QDateTime::currentDateTime();
auto suffix = QString().sprintf("-%04d%02d%02d-%02d%02d%02d",
now.date().year(),
now.date().month(),
now.date().day(),
now.time().hour(),
now.time().minute(),
now.time().second()
);
auto suffix = "-" + isoDateTime();
path.insert(extensionIdx, suffix);
}
}

View File

@ -219,6 +219,19 @@ QString GetDataTypeString(const void* buffer, duint size, ENCODETYPE type)
}
}
QString isoDateTime()
{
auto now = QDateTime::currentDateTime();
return QString().sprintf("%04d%02d%02d-%02d%02d%02d",
now.date().year(),
now.date().month(),
now.date().day(),
now.time().hour(),
now.time().minute(),
now.time().second()
);
}
QString ToDateString(const QDate & date)
{
static const char* months[] =

View File

@ -104,6 +104,9 @@ inline QString ToDoubleString(const void* buffer, int precision = std::numeric_l
QString ToLongDoubleString(const void* buffer);
// yyyyMMdd-HHmmss (useful for file suffix)
QString isoDateTime();
QString ToDateString(const QDate & date);
QString fillValue(const char* value, int valsize = 2, bool bFpuRegistersLittleEndian = false);