2016-08-10 8 views
-1

Я пытаюсь подключить функцию SetRect с помощью Detours, но моя программа рушится сразу после подключения. Я попытался подключить другие функции, такие как DrawText, и все прошло отлично, и теперь я не уверен, есть ли проблема с моим кодом или что-то о SetRect (и других подобных функциях), о которых я не знаю, что вызвало крах.Сбой при сбоях приложения Detours 3.0 SetRect

Для тестирования я использую при условии Detours работать с программой длл:

withdll.exe -d:mydll.exe simpleprogram.exe 

Где simpleprogram.exe является простой одна кнопка C# приложение. Пробовал тестирование также на блокноте, calc, firefox, но все они тоже разбились.

Мой крючок DLL

#include <Windows.h> 
#include <detours.h> 
#include<string> 
#include<fstream> 
#include<iostream> 
using namespace std; 

wofstream out; 

BOOL(__stdcall * T14) 
(
_Out_ LPRECT lprc, 
_In_ int xLeft, 
_In_ int yTop, 
_In_ int xRight, 
_In_ int yBottom 

) = SetRect; 


__declspec(dllexport) BOOL M14 
(
_Out_ LPRECT lprc, 
_In_ int L, 
_In_ int T, 
_In_ int R, 
_In_ int B 
){ 

    out << "SetRect: " << L << " " << T << " " << R << " " << B << endl; 
    return T14(lprc, L, T, R, B); 
} 

BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) 
{ 
    if (dwReason == DLL_PROCESS_ATTACH) 
    { 
     out.open("out.txt"); 
     out << "Attached" << endl; 
     DetourRestoreAfterWith(); 
     DetourTransactionBegin(); 
     DetourUpdateThread(GetCurrentThread()); 
     DetourAttach(&(PVOID&)T14, M14); 
     DetourTransactionCommit(); 
    } 
    else if (dwReason == DLL_PROCESS_DETACH) 
    { 
     out << "detached" << endl; 
     out.close(); 
     DetourTransactionBegin(); 
     DetourUpdateThread(GetCurrentThread()); 
     DetourDetach(&(PVOID&)T14, M14); 
     DetourTransactionCommit(); 
    } 

    return TRUE; 
} 

Выход я получаю:

Прикрепленный

SetRect: 138 161 323 161

Так что программа рушится после того, как вызывается первая функция SetRect, любые идеи, почему это происходит?

+0

Делает ли 'DetourTransactionCommit() == NO_ERROR'? – dxiv

ответ

2

Вызывающее соглашение об отключенной функции неверно.

Проекты Visual C++ по умолчанию равны __cdecl, но ВСЕ API Windows использует WINAPI (__stdcall).

Вы разрушаете столбец из-за различий в соглашении о вызове. Эта проблема не существует в 64-битном программном обеспечении, так как существует только одно соглашение о вызове, но для x86 критически важно, чтобы вы соответствовали любому соглашению о вызовах, определенному в прототипе оригинальной функции.


__declspec(dllexport) BOOL WINAPI M14 
(
_Out_ LPRECT lprc, 
_In_ int L, 
_In_ int T, 
_In_ int R, 
_In_ int B 
){ 

    out << "SetRect: " << L << " " << T << " " << R << " " << B << endl; 
    return T14(lprc, L, T, R, B); 
} 

На другой, возможно, даже более серьезным и трудным для отладки нотой. Я бы воздержался от выполнения ввода/вывода потока C++ в DllMain (...). Если вы не статически связали свою DLL с MSVCRT, это приведет к зависимостям от других DLL, когда вы удерживаете блокировку загрузчика.

Вы можете отключить блокировку, если вы вызываете какую-либо функцию из DllMain, которая не статически связана, или часть kernel32.dll или user32.dll. Хорошей новостью является kernel32, а user32 имеет множество строковых функций - достаточно, чтобы вам даже не нужна стандартная библиотека C++;)

+0

Добавление WINAPI исправлено, спасибо! Также спасибо за примечание, я всегда тестирую свою программу без ввода/вывода C++, чтобы исключить эту возможность всякий раз, когда я получаю сообщение об ошибке. – Ibrahim

1

Я просто попытался подключить SetRect(), и я получил его, чтобы правильно наложить на Calc. Я поставлю код, который я использовал ниже для DLL.

static BOOL (WINAPI *TrueSetRect)(LPRECT, int, int, int, int) = SetRect; 
    ... 
    ... 
    BOOL WINAPI __stdcall MySetRect(LPRECT lprc, int L, int T, int R, int B) 
    { 
     printf("MySetRect: L = %i; T = %i; R = %i; B = %i", L, T, R, B); 
     return TrueSetRect(lprc, L, T, R, B); 
    } 

    __declspec(dllexport) 
    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 
    { 
     if(fdwReason == DLL_PROCESS_ATTACH) 
     { 
      DetourTransactionBegin(); 
      DetourUpdateThread(GetCurrentThread()); 
      DetourAttach(&reinterpret_cast<PVOID&>(TrueSetRect), MySetRect); 
      if(DetourTransactionCommit() == NO_ERROR) 
      { 
       //Detour successful 
      } 
     } 
     if(fdwReason == DLL_PROCESS_DETACH) 
     { 
      DetourTransactionBegin(); 
      DetourUpdateThread(GetCurrentThread()); 
      DetourDetach(&reinterpret_cast<PVOID&>(TrueSetRect), MySetRect); 
      if(DetourTransactionCommit() != NO_ERROR) 
      { 
       //Detach unsuccessful 
      } else { 
       //Detach successful 
      } 
     } 
    } 

Я подозреваю, что это может быть так, как вы инстанцировании SetRect() и YourSetRect(), потому что это единственное, что отличается от моего кода и вашим.

+0

Вопрос был ошибкой в ​​моей конвенции, как отметил Андон. Спасибо – Ibrahim