最简单的方法是将原始dll简单地重新定位,并创建一个新的dll,其中包含相同的导出项。这个dll会从备用位置LoadLibrary旧的dll。
但这并不适用于这里——dll正在导出c++类成员,这有两个后果:c++类必须静态加载,因为没有c++机制将c++函数指针(通过GetProcAddress获得)粘合到类实例中。
这意味着你的shim dll将不幸地处于既要导入又要导出相同一组符号的位置。
唯一的解决办法是将shim dll分为两部分:
Shim1:
一部分将获取原始dll的名称,并导出与原始dll相同的类定义。
Shim2:
第二部分将导入原始dll,并将其包装在一个类中,该类将公开所有原始dll的函数。
class __decldpec(dllexport) CCPCompressor {
...
Depends可以破解名称修饰,或者Undname.exe与Visual Studio一起分发。
这部分将使用显式路径加载shimdll2.dll,该dll位于其他文件夹中,并与原始dll一起使用。需要使用GetProcAddress()导入由shimdll2.dll导出的函数。
Shim2:
另一个shim dll将位于尝试拦截的dll所在的文件夹中。该dll必须从原始压缩器dll中导入类:
class __declspec(dllimport) CCPCompressor {
...
您可以使用第一个dll创建的dll导入库来实际链接符号。
然后,只需从shim2.dll导出函数,每当调用CCPCompressor方法时,shim1.dll将调用这些函数。
NB. 其他事项:您的CCPCompressor类版本至少需要有一个大型虚拟数组,因为您无法从dll导出中知道应用程序期望该类的大小(除非您恰好有描述该类的实际头文件)。
为了分解导出的名称以构建类定义:
从开始菜单 > 程序 > Visual Studio 20XX -> 工具菜单中打开Visual Studio 20XX命令提示符。
c:\...\VC>undname ?Clear@CCPCompressor@@QAEHXZ
Microsoft (R) C++ Name Undecorator
Undecoration of :- "?Clear@CCPCompressor@@QAEHXZ"
is :- "public: int __thiscall CCPCompressor:Clear(void)"
c:\...\VC>_
对于从原始dll导出的每个函数执行此操作(undname接受某种文本文件以加快此过程),以找出如何声明匹配的类定义。