2012-08-16 3 views
1

CopyItems 함수를 연결하려고합니다.하지만 콜백 함수에서 실제 CopyItems 함수를 호출하려고 할 때 충돌이 발생합니다. 코드가 아래와 같습니다.CopyItems Function 후크가 충돌합니다.

PVOID GetInterfaceMethod(PVOID intf, DWORD methodIndex) 
{ 
    return *(PVOID*)(*(DWORD*)intf + methodIndex * 4); 
} 

typedef HRESULT (WINAPI *CopyItemsNext)(IUnknown *punkItems,IShellItem *psiDestinationFolder); 
CopyItemsNext Real_CopyItems = NULL; 
CopyItemsNext Actual_CopyItems; 


HRESULT WINAPI CopyItemsCallback(IUnknown *punkItems,IShellItem *psiDestinationFolder) 
{ 

    MessageBoxW(NULL,L"CopyItems Function Called", L"HookedCopyItemS", MB_OK); 
    return Real_CopyItems(punkItems, psiDestinationFolder); 
} 


HRESULT WINAPI CoCreateInstanceCallback(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv) 
{ 
    const char *IFileOperation_GUID = "{3AD05575-8857-4850-9277-11B85BDB8E09}"; 
    char GUIDString[64]; 

    HRESULT HR = Real_CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv); 

    sprintf_s(GUIDString,64, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\0", 
    rclsid.Data1, rclsid.Data2, rclsid.Data3, 
    rclsid.Data4[0], rclsid.Data4[1], 
    rclsid.Data4[2], rclsid.Data4[3], 
    rclsid.Data4[4], rclsid.Data4[5], 
    rclsid.Data4[6], rclsid.Data4[7]); 

    if(strcmp(GUIDString, IFileOperation_GUID) == 0) 
    { 
     MessageBoxA(NULL, "IFileOperation_GUID Found", GUIDString, MB_OK); 

     if(Real_CopyItems == NULL) 
     { 
     Actual_CopyItems = (CopyItemsNext)GetInterfaceMethod(*ppv, 17); 
     MessageBoxA(NULL,"AFTER GetInterfaceMethod", "TEST", MB_OK); 

     if (MH_CreateHook(Actual_CopyItems, &CopyItemsCallback, reinterpret_cast<void**>(&Real_CopyItems)) != MH_OK) 
     { 
      MessageBoxW(NULL, L"Failed CreateHook Real_CopyItem", L"Info!", MB_ICONWARNING|MB_OK); 
     } 
     if (MH_EnableHook(Actual_CopyItems) != MH_OK) 
     { 
      MessageBoxW(NULL, L"Failed EnableHook Real_CopyItem", L"Info!", MB_ICONWARNING|MB_OK); 
     } 
    } 
} 
return HR; 
} 

//DllMain Function 
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 
{ 
switch (ul_reason_for_call) 
{ 
case DLL_PROCESS_ATTACH: 
    if (MH_Initialize() != MH_OK) 
    { 
     MessageBoxW(NULL, L"Failed Initialize", L"Info!", MB_ICONWARNING|MB_OK);  
    } 
    if (MH_CreateHook(&CoCreateInstance, &CoCreateInstanceCallback, reinterpret_cast<void**>(&Real_CoCreateInstance)) != MH_OK) 
    { 
     MessageBoxW(NULL,L"Failed MH_CreateHook CoCreateInstance",L"Info!",MB_ICONWARNING|MB_OK); 
    } 
    if (MH_EnableHook(&CoCreateInstance) != MH_OK) 
    { 
     MessageBoxW(NULL,L"Failed MH_EnableHook StartDocA",L"Info!",MB_ICONWARNING|MB_OK); 
    } 
    break; 

case DLL_PROCESS_DETACH: 
    if (MH_Uninitialize() != MH_OK) 
    {    
    } 
    if (MH_DisableHook(Actual_CopyItems) != MH_OK) 
    { 
    } 
    if (MH_DisableHook(&CoCreateInstance) != MH_OK) 
    { 
    } 

    break; 
} 
return TRUE; 
} 
난 그냥 함수가 후크 연구를하지 점점 날씨를 확인하는 메시지 상자를 표시하고있는 CopyItemsCallback 기능을 내부에 위의 코드에서

, 그래서 나는 내가 부르고 리얼 CopyItems 기능 후 해당 메시지 상자를 가지고 있지만, 거기이다 충돌이 발생하므로 내 코드의 문제점을 확인하십시오.

답변

1

IFileOperation :: CopyItems는 일반 Win32 함수가 아닌 COM 메서드이므로 일반 Win32 API 인 CoCreateInstance와 다르게 처리해야합니다.

C++ 구문을 사용하여 COM 메서드를 호출하면 보이지 않는 것은 숨겨진 매개 변수로 장면 뒤에서 전달되는 "this"포인터 (인터페이스 포인터와 동일)입니다. 그러나 C 스타일 코드를 사용하여 COM 메소드를 호출하려면 수동으로 처리해야합니다.

그래서 CopyItems 기능의 당신의 정의는 대신 같은 것을 보일 것입니다 :

typedef HRESULT (STDMETHODCALLTYPE *CopyItemsNext)(IFileOperation * pThis, IUnknown *punkItems, IShellItem *psiDestinationFolder); 

을 ... 그리고 당신은 '진짜'하나를 통해 호출 할 때, 당신은으로의 운영중인 것을 통과해야합니다 첫 번째 매개 변수.

이 트릭은 COM에만 해당하므로 일반적으로 C++ 방법을이 방법으로 처리 할 수는 없습니다. COM은 일반 C에서 사용할 수 있도록 설계되었으므로 COM에서는 'this'포인터가 일반 매개 변수처럼 전달되도록 요구합니다. (COM 메소드는 STDMETHODCALLTYPE으로 표시되어 있는데, 이는 컴파일러에게 그것이없는 메소드와 다르게 처리하도록 알려주는 것입니다.) 그러나 COM C++가 아닌 클래스의 경우, 컴파일러는이 포인터를 레지스터에 전달하는 것과 같은 다른 작업을 수행 할 수 있습니다.

- 그런데

, 당신의 GetInterfaceMethod의 DWORD는 32 비트 윈도우에서 작동 있습니다; 항상 포인터 크기이고 32 비트 또는 64 비트 코드로 작동하는 유형을 원하면 DWORD_PTR을 사용하십시오.

+0

멋진 답변 BrendanMcK, 정말 많이 감사합니다. –