我試圖通過注入我的DLL並將QPainter::drawText
函數繞到我自己的應用程序中來掛鉤另一個應用程序中的QPainter::drawText
函數。我這樣做是因爲其他應用程序沒有公開可用的API,我想對我得到的數據做一些基本的統計分析。如何將C++ QString參數轉換爲C#字符串
所有工作正常:我看到QPainter::drawText
函數被調用,但我無法將QString
參數轉換爲任何有用的參數。當我將Marshall的QString
參數設爲LPWStr
時,我得到的只有兩個字符。
我不是C++的超級英雄,所以我有點失落。我想我正在看一些指針或參考,因爲每次打電話都會收到兩個字符,但我不確定。經過幾個晚上試圖理解它,我接近放棄的地步。
我demangled的QPainter::drawText
功能(發現使用依賴沃克:[email protected]@@[email protected]@[email protected]@[email protected]@Z
)與https://demangler.com/並將其與該函數聲明出現:
public: void __thiscall QPainter::drawText(class QRect const &,int,class QString const &,class QRect *)
我已經轉換成以下的DllImport這個(I取代的QRect
和Qstring
類到IntPtr
,因爲我不知道如何將它們轉換爲C#)。
[DllImport("Qt5Gui.dll", SetLastError = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.ThisCall, EntryPoint = "[email protected]@@[email protected]@HABVQSt[email protected]@[email protected]@Z")]
public static extern void QPainter_drawText(IntPtr obj, IntPtr p1, int p2, IntPtr p3, IntPtr p4);
這是我到目前爲止有:
迂迴的Qt的QPainter ::的drawText
LocalHook QPainter_drawTextHook;
[DllImport("Qt5Gui.dll", SetLastError = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.ThisCall, EntryPoint = "[email protected]@@[email protected]@[email protected]@[email protected]@Z")]
public static extern void QPainter_drawText(IntPtr obj, IntPtr p1, int p2, IntPtr p3, IntPtr p4);
[UnmanagedFunctionPointer(CallingConvention.ThisCall, CharSet = CharSet.Unicode, SetLastError = true)]
delegate void TQPainter_drawText(IntPtr obj, IntPtr p1, int p2, IntPtr p3, IntPtr p4);
static void QPainter_drawText_Hooked(IntPtr obj, IntPtr p1, int p2, IntPtr p3, IntPtr p4)
{
var qs3 = (QString)Marshal.PtrToStructure(p3, typeof(QString));
try
{
((Main)HookRuntimeInfo.Callback).Interface.GotQPainter_drawText(qs3.ToString());
QPainter_drawText(obj, p1, p2, p3, p4);
}
catch (Exception ex)
{
((Main)HookRuntimeInfo.Callback).Interface.ErrorHandler(ex);
}
}
創建的QPainter ::繞道的drawText
QPainter_drawTextHook = LocalHook.Create(
LocalHook.GetProcAddress("Qt5Gui.dll", "[email protected]@@[email protected]@[email protected]@[email protected]@Z"),
new TQPainter_drawText(QPainter_drawText_Hooked),
this);
QPainter_drawTextHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
更新2016-1-31 到目前爲止我找到了這個(見https://github.com/mono/cxxi/blob/master/examples/qt/src/QString.cs)。但現在我在Marshal.PtrToStringUni
上獲得AccessViolationException
。
[StructLayout(LayoutKind.Sequential)]
public unsafe struct QString
{
[StructLayout(LayoutKind.Sequential)]
public struct Data
{
public int @ref;
public int alloc, size;
public IntPtr data;
public ushort clean;
public ushort simpletext;
public ushort righttoleft;
public ushort asciiCache;
public ushort capacity;
public ushort reserved;
public IntPtr array;
}
public Data* d;
#endregion
public override string ToString()
{
try
{
return Marshal.PtrToStringUni(d->array, d->alloc * 2);
}
catch (Exception ex)
{
return ex.Message;
}
}
}
另外,我知道我在尋找的方向是正確的,因爲在鉤省略了原來'drawText'函數調用導致無在目標應用程序中渲染文本。它可能是我之前發佈的結構的一些重新配置,以獲取字符串存儲的內存地址。 QPoint.d.alloc包含字符串在屏幕上顯示的字符數。 –