C++ 围绕变量';libName';加载msimg32.dll的loadlibrary和GetProcAddress时已损坏
我正在开发一个像MSN Plus这样的live messenger插件。 我将用proxyC++ 围绕变量';libName';加载msimg32.dll的loadlibrary和GetProcAddress时已损坏,c++,com,visual-c++,C++,Com,Visual C++,我正在开发一个像MSN Plus这样的live messenger插件。 我将用proxymsimg32.dll连接到MSN。 与internet中的代理msimg32.dll的其他示例不同,在这些示例中,导出的函数在DLLMain中检索,因为MSDN说调用LoadLibrary在DLLMain中是不安全的。 这通过测试得到确认,在自定义的msimg32.dll的DllMain中加载系统的msimg32.dll将导致访问冲突 我的方法是加载c:\windows\system32\msimg32.
msimg32.dll
连接到MSN。
与internet中的代理msimg32.dll
的其他示例不同,在这些示例中,导出的函数在DLLMain
中检索,因为MSDN说调用LoadLibrary
在DLLMain
中是不安全的。
这通过测试得到确认,在自定义的msimg32.dll
的DllMain
中加载系统的msimg32.dll将导致访问冲突
我的方法是加载c:\windows\system32\msimg32.dll
在一个导出的函数中,我在MSN plus的msimg32.dll
的disassamble中找到了这种方法。
但是我在函数GetMsimg32FnAddr
中面临一个严重错误,当GetMsimg32FnAddr
返回时,变量libName
已损坏
我的问题是如何避免源代码中的堆栈损坏。
此外,关于代理msimg32.dll
,我的想法行吗
我的开发环境是:
VS2005,win7企业版,32位。
最新版本的Live messenger。
MSN plus的最新版本
VS2005报告:
运行时检查失败#2-变量“libName”周围的堆栈已损坏
当GetMsimg32FnAddr
返回
下面是我的proxymsimg32.dll的源代码
msimgproxy.h
:
/*****************************************************************************/
#ifndef MSIMGPROXY_H
#define MSIMGPROXY_H
#include <windows.h>
#pragma warning( disable:4273 ) // Silence compiler
//
// Function pointer typedefs for exports we are forwarding
//
typedef BOOL (WINAPI *PFNTRANSPARENTBLT) (HDC,int,int,int,int,HDC,int,int,int,int,UINT);
typedef VOID (WINAPI *PFNVSETDDRAWFLAG) (VOID);
typedef BOOL (WINAPI *PFNALPHABLEND) (HDC,int,int,int,int,HDC,int,int,int,int,BLENDFUNCTION);
typedef BOOL (WINAPI *PFNGRADIENTFILL) (HDC,PTRIVERTEX,ULONG,PVOID,ULONG,ULONG);
typedef BOOL (WINAPI *PFNDLLINITIALIZE)(HINSTANCE, DWORD, LPVOID);
// Function pointer typedef to injected-DLL initialization
typedef void (*PFNINIT) (void);
#ifdef __cplusplus
extern "C"
{
#endif
//
// Function protoypes
//
BOOL WINAPI TransparentBlt(HDC, int, int, int, int, HDC, int, int, int, int, UINT);
BOOL WINAPI AlphaBlend (HDC, int , int, int, int, HDC, int , int, int, int, BLENDFUNCTION);
BOOL WINAPI GradientFill (HDC, PTRIVERTEX, ULONG, PVOID, ULONG, ULONG);
BOOL WINAPI DllInitialize (HINSTANCE, DWORD, LPVOID);
VOID WINAPI vSetDdrawflag (VOID);
#ifdef __cplusplus
}
#endif // __CPLUSPLUS
#endif // MSIMGPROXY_H
我建议您查看文档,特别是注意下面的评论:“从DllMain调用LoadLibrary是不安全的”。您应该在第一次使用时按需加载API,并由互斥锁或crit-section保护。那么“第一次使用时按需加载API”如何?这是否意味着我应该在本地msimg32.dll的DLLMain中加载系统msimg32.dll?它确实抛出了访问冲突的异常。我猜这是由相同的DLL名称引起的死锁:msimg32.DLL。因为我有另一个测试用例:在DLLMain中加载除msimg32.dll之外的另一个普通dll,一切正常。在MSDN DLLMain中可以找到以下内容:入口点函数应该只执行简单的初始化或终止任务。它不能调用LoadLibrary或LoadLibraryEx函数(或调用这些函数的函数),因为这可能会在DLL加载顺序中创建依赖项循环。这可能导致在系统执行其初始化代码之前使用DLL。如果您现在从一个API加载msimg32.dll,而不是从DllMain加载msimg32.dll,那么您的做法是正确的。在这一点上,另一个经常出错的事情是调用约定(当然,使用不同平台(即x64和x86)编译的可能性,但若出现这种情况,您的LoadLibrary将失败)。检查您的调用约定,确保它们与DLL所期望的内容相匹配。一种方法是在msimg32.dll中查找没有参数的函数。如果这样的话,你的通话习惯在其他通话中肯定是错误的。检查调用约定a>将msimg32.dll和dll主机(用于测试msimg32.dll的win32项目)的默认调用转换设置为uu stdcall。b>将“bool GetMsimg32FnAddr()”更改为“bool WINAPI GetMsimg32FnAddr()”,同时使用u stdcall。不幸的是,所有这些转换都不起作用。2.更改GetMsimg32FnAddr()中的部分代码找到根本原因。更改:_tcscat_s(libName,MAX_PATH*sizeof(TCHAR),TEXT(\\msimg32.dll));更改为:_tcscat(libName,_T(\\msimg32.dll));已修复!非常感谢。根本原因似乎不是调用约定,而是字符串。
#include "msimgproxy.h"
#include <tchar.h>
PFNTRANSPARENTBLT pfnTransparentBlt = NULL;
PFNALPHABLEND pfnAlphaBlend = NULL;
PFNDLLINITIALIZE pfnDllInitialize = NULL;
PFNGRADIENTFILL pfnGradientFill = NULL;
PFNVSETDDRAWFLAG pfnVSetDdrawFlag = NULL;
PFNINIT pfnInit = NULL;
bool GetMsimg32FnAddr();
HMODULE hMsimg32 = NULL;
HMODULE hPlugDll = NULL;
TCHAR pszInjDllName[] = TEXT("msg_plugin.dll");
/************************************************************************/
/* */
/* Proxy DLL Entry point */
/* */
/************************************************************************/
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call,
LPVOID lpReserved )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
/*
if (!GetMsimg32FnAddr())
{
OutputDebugString (TEXT("MSIMG32 Proxy: GetMsimg32FnAddr() failed\n"));
return FALSE;
}
*/
OutputDebugString(TEXT("MSIMG32 Proxy: DLL attached\n"));
// Load injected DLL and execute it's initialization function
if (! (hPlugDll = LoadLibrary(pszInjDllName)))
{
OutputDebugString (TEXT("MSIMG32 Proxy: Cannot load inject-DLL\n"));
//return FALSE;
}
if (! (pfnInit = (PFNINIT) GetProcAddress (hPlugDll, "Init")))
{
OutputDebugString (TEXT("MSIMG32 Proxy: No valid address for executing Init\n"));
//return FALSE;
}
if (pfnInit)
{
(*pfnInit)();
}
break;
}
case DLL_PROCESS_DETACH:
{
if (hMsimg32)
if (FreeLibrary(hMsimg32))
OutputDebugString (TEXT("MSIMG32 Proxy: DLL detached.\n"));
break;
}
}
return TRUE;
}
//
// Get original MSIMG32.DLL functions virtual addresses
//////////////////////////////////////////////////////////////////////////
bool GetMsimg32FnAddr()
{
TCHAR libName[MAX_PATH];
GetSystemDirectory (libName, MAX_PATH);
_tcscat_s (libName, MAX_PATH*sizeof(TCHAR), TEXT("\\msimg32.dll"));
hMsimg32 = LoadLibrary (libName);
if (!hMsimg32)
return false;
if ( (pfnVSetDdrawFlag = (PFNVSETDDRAWFLAG) GetProcAddress(hMsimg32, "vSetDdrawflag")) == NULL)
return false;
if ( (pfnAlphaBlend = (PFNALPHABLEND) GetProcAddress(hMsimg32, "AlphaBlend")) == NULL)
return false;
if ( (pfnDllInitialize = (PFNDLLINITIALIZE) GetProcAddress(hMsimg32, "DllInitialize")) == NULL)
return false;
if ( (pfnGradientFill = (PFNGRADIENTFILL) GetProcAddress(hMsimg32, "GradientFill")) == NULL)
return false;
if ( (pfnTransparentBlt = (PFNTRANSPARENTBLT) GetProcAddress(hMsimg32, "TransparentBlt")) == NULL)
return false;
return true;
}
//
// Exported function definition
//////////////////////////////////////////////////////////////////////////
BOOL WINAPI TransparentBlt(HDC p1, int p2, int p3, int p4, int p5, HDC p6, int p7, int p8,
int p9, int p10, UINT p11)
{
return pfnTransparentBlt (p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11);
}
BOOL WINAPI AlphaBlend(HDC p1, int p2, int p3, int p4, int p5, HDC p6, int p7 , int p8,
int p9, int p10, BLENDFUNCTION dw)
{
return pfnAlphaBlend (p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,dw);
}
BOOL WINAPI GradientFill (HDC p1, PTRIVERTEX p2, ULONG p3, PVOID p4, ULONG p5, ULONG p6)
{
return pfnGradientFill (p1, p2, p3, p4, p5, p6);
}
BOOL WINAPI DllInitialize (HINSTANCE d1,DWORD d2, LPVOID d3)
{
if (pfnDllInitialize == NULL)
{
GetMsimg32FnAddr();
}
return pfnDllInitialize (d1, d2, d3);
}
VOID WINAPI vSetDdrawflag (VOID)
{
(*pfnVSetDdrawFlag)();
}