Я написал приложение C#, которое внедряет DLL в сторонний исполняемый файл (который, как оказалось, был создан с использованием фреймворка Qt). Эта DLL использует EasyHook для перехвата вызовов ряда определенных функций. Когда мой внедренный код вызывается, я пытаюсь проверить некоторые объекты, являющиеся параметрами этих функций.
Например, я перехватил вызов, сделанный для разбора некоторого XML:
virtual bool __thiscall QXmlSimpleReader::parse(class QXmlInputSource const &)
В моем коде C# у меня есть подпись PInvoke, соответствующая этому:
static extern bool XmlParse(IntPtr Reader, IntPtr Source)
Я хотел бы вызвать функцию "data()", которая является членом класса "Source". То есть QXmlSimpleReader анализирует необработанный XML из QXmlInputSource, но перед этим я пытаюсь проверить необработанный XML с помощью этой функции «data()».
По совету одного из экспертов здесь я попытался использовать C++/CLI для исходного доступа к объекту (см. party-dlls">Вызов методов в сторонних DLL). Я создал объект-оболочку на C++, который принимает IntPtr из кода C#:
Заголовок:
public ref class QXmlInputSource
{
public:
// Constructor must be called with C# IntPtr
QXmlInputSource(IntPtr Ptr);
bool LoadQt(void);
bool UnloadQt(void);
String^ Data();
private:
// Pointer to the native Qt object
void * Native;
HINSTANCE DllHandle;
// SIGNATURE: virtual QString QXmlInputSource::data() const
typedef void * (__thiscall *QXmlInputSource_Data)(void *);
QXmlInputSource_Data fpData;
};
СРР-файл:
QXmlInputSource::QXmlInputSource(IntPtr Ptr)
{
LoadQt();
Native = Ptr.ToPointer();
}
bool QXmlInputSource::LoadQt(void)
{
FARPROC Addr;
/* get handle to dll */
std::wstring LibName = QtPath + QtXml;
DllHandle = LoadLibrary(LibName.c_str());
/* get pointer to the function in the dll*/
Addr = GetProcAddress(HMODULE (DllHandle), "?data@QXmlInputSource@@UBE?AVQString@@XZ");
fpData = QXmlInputSource_Data(Addr);
return true;
}
bool QXmlInputSource::UnloadQt()
{
/* Release the Dll */
FreeLibrary(DllHandle);
return true;
}
String^ QXmlInputSource::Data()
{
void* Ptr = fpData(Native);
return "EPIC FAIL";
}
Приложение на основе Qt аварийно завершает работу, когда я пытаюсь вызвать указатель функции fpData(). Помощь: Р
Некоторая дополнительная информация, которая может помочь или не помочь:
Я успешно вызывал функции для «более простых» объектов, таких как QString.count() и QString.data(), используя ту же методологию. (QString кажется просто легкой оболочкой для стандартной строки Unicode).
В файле QtXml4.dll, содержащем интересующие меня XML-функции, на самом деле есть ДВА метода parse(); в одном источник является константой &, а в другом источник является константой *. Я понятия не имею, должен ли я использовать один или другой. Я не думаю, что мои подписи изменятся в любом случае.
Пока я пытался поиграться, я попытался разыменовать IntPtr в коде C# и передать его на C++:
IntPtr DerefSrc = (IntPtr)Marshal.PtrToStructure(Source, typeof(IntPtr));
Если я распечатаю значения этих двух IntPtr, Source имеет значение около 3,5 МБ, а DerefSrc имеет значение 1,6 ГБ, что примерно соответствует адресу QtXml4.dll в памяти. Я предполагаю, что 3,5 Мб — это относительное смещение, а DerefSrc — явно абсолютная ссылка. Стоит ли пытаться преобразовать DerefSrc в относительный адрес и вместо этого передать его на С++...?