【问题标题】:How to resolve access violation writing location when calling dll method调用dll方法时如何解决访问冲突写入位置
【发布时间】:2016-01-20 22:52:55
【问题描述】:

我正在使用 GetProcAddress 来访问标准的 Isapi 过滤器 DLL 方法 - GetFilterVersion 方法,它采用指向 HTTP_FILTER_VERSION 结构的指针。

https://msdn.microsoft.com/en-us/library/ms525822(v=vs.90).aspx

https://msdn.microsoft.com/en-us/library/ms525465(v=vs.90).aspx

我已经针对我编写的有效 Isapi 过滤器测试了代码,它运行良好。我针对来自供应商的 Isapi 过滤器调试代码(我无权访问源代码或 dll 本身之外的任何内容)并且我得到异常“访问冲突写入位置”。可能是什么问题? (两个 Isapi 过滤器都可以在 IIS 中使用。)

//Attempted to define function ptr several ways
typedef BOOL(__cdecl * TRIRIGAISAPIV)(PHTTP_FILTER_VERSION);
//typedef BOOL( * TRIRIGAISAPIV)(PHTTP_FILTER_VERSION);
//typedef BOOL(WINAPI * TRIRIGAISAPIV)(PHTTP_FILTER_VERSION);

void arbitraryMethod()
{
   HINSTANCE hDLL;               // Handle to DLL
   TRIRIGAISAPIV lpfnDllFunc2;    // Function pointer

   DWORD lastError;
   BOOL  uReturnVal2;

   hDLL = LoadLibrary(L"iisWASPlugin_http.dll");  //vendor's dll
   //hDLL = LoadLibrary(L"KLTWebIsapi.dll   //my dll

   if (hDLL != NULL)
   {
       lpfnDllFunc2 = (TRIRIGAISAPIV)GetProcAddress(hDLL, "GetFilterVersion");

       if (!lpfnDllFunc2)
       {
           lastError = GetLastError();
           // handle the error
           FreeLibrary(hDLL);
           //return 1;
       }
       else
       {            
           HTTP_FILTER_VERSION pVer = { 6 };

           //Call the function via pointer; Works with my dll, fails with vendor's
           uReturnVal2 = lpfnDllFunc2(&pVer);

           //................  HELP!!!!!!!!!!!!!
       }
   }
}

【问题讨论】:

  • BOOL(__cdecl 你确定这个函数的调用约定是__cdecl,而不是__stdcall?大多数 API 函数是 __stdcall,最值得注意的例外是 wsprintf(因为它需要一个可变参数列表)。
  • 我试过 __stdcall, __cdecl , WINAPI - 两者都不起作用......
  • 堆栈跟踪指向 0x000000007744F6C6 (ntdll.dll) RtlEnterCriticalSection() 处的未处理异常

标签: c++ dll getprocaddress


【解决方案1】:

我看到的一个问题是您的函数指针声明不正确。

根据 Microsoft 文档,GetFilterVersion 的原型为:

BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer);

WINAPI 是一个 Windows 宏,实际上定义为__stdcall,因此当您使用__cdecl 时,您错误地声明了函数指针。

What does WINAPI mean?

因此,您的声明应该是:

typedef BOOL(__stdcall * TRIRIGAISAPIV)(PHTTP_FILTER_VERSION);

【讨论】:

  • 我之前尝试过各种声明 - 不起作用。 ntdll.dll 中的堆栈跟踪失败。
【解决方案2】:

可能是自定义过滤器实际上填充了一些额外的结构字段。

您可以尝试增加结构的大小,看看是否可行,例如:

struct HTTP_FILTER_VERSION_EXTRA {
    HTTP_FILTER_VERSION v;
    char[1024] extra;
};

HTTP_FILTER_VERSION_EXTRA ver;
ver.v.dwServerFilterVersion = 6;
uReturnVal2 = lpfnDllFunc2(&ver.v);

WinAPI 结构有时允许版本控制,因此可以添加字段。如果函数不检查(或不知道)实际的结构版本,它可能会尝试使用可能与提供的不同的扩展版本 - 如果提供的结构的大小小于结构func 尝试使用的版本,可能会发生不好的事情。

还要检查 DLL 是 64 位还是 32 位。您不能通过 32 位应用程序使用 64 位 DLL,反之亦然(但我希望在 LoadLibrary 调用期间这已经失败)。

【讨论】:

    猜你喜欢
    • 2019-10-31
    • 1970-01-01
    • 2020-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-15
    • 2012-12-05
    相关资源
    最近更新 更多