2012-08-16 88 views
1

我想挂钩CopyItems函数,它的工作正常,但是当我试图在Callback函数中调用Real CopyItems函数时,它正在崩溃,我的代码如下,请帮助我。CopyItems函数挂钩崩溃

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功能我正在显示的消息框只是为了确认天气的功能越来越钩R值不要里面上面的代码,所以我得到了我打电话房地产CopyItems功能后,该消息框,但它就在那里得到崩溃,所以请检查我的代码有什么问题。

回答

1

IFileOperation :: CopyItems是一个COM方法,而不是一个普通的Win32函数,因此您需要对它进行与CoCreateInstance(它是一个普通的Win32 API)不同的对待。

当您使用C++语法调用COM方法时,您看不到的是作为隐藏参数在幕后传递的“this”指针(与接口指针相同)。但是如果你想用C风格的代码调用COM方法,你必须手动处理。

所以你的CopyItems函数的定义应该不是这个样子:

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

...而当你通过打电话向“真正的”一个,你必须传递pThis作为第一个参数。

请注意,这个技巧是特定于COM,你不能通过这种方式来对待C++方法。它恰好发生COM被设计为可以从普通C使用,所以COM需要'this'指针正常传递。 (COM方法用STDMETHODCALLTYPE标记,这是告诉编译器将它们对待的方式与没有这种方法的方法不同)。但是,对于非COM C++类,编译器可能会执行其他操作,例如将此指针传递到寄存器中。

-

顺便说一句,请注意您的GetInterfaceMethod的DWORD将只能在32位Windows工作;如果您想要一个始终是指针大小的类型,然后使用32位或64位代码,请使用DWORD_PTR。

+0

真棒回复BrendanMcK,它帮助我很多,谢谢你这么多.... – 2012-08-17 07:38:45