windows - 为什么调用 ProcessGroupPolicyEx 回调会导致访问冲突?

标签 windows winapi group-policy

我正在尝试帮助同事处理客户端扩展中的一些代码。由于添加了对回调的调用,该函数似乎可以正常完成,但 Windows 事件日志中的一个事件提示在处理组策略对象时出现访问冲突。

删除现有代码后,仅添加对回调的调用,它仍然报告此访问冲突。

能否请您帮助确定我们可能遗漏了什么?

//
// Entry point for processing group policy objects.
//
// For full details, see http://msdn.microsoft.com/en-    us/library/windows/desktop/aa374383(v=vs.85).aspx.
//
extern "C" DWORD CALLBACK ProcessGroupPolicyEx (
  __in   DWORD dwFlags,
  __in   HANDLE hToken,
  __in   HKEY hKeyRoot,
  __in   PGROUP_POLICY_OBJECT pDeletedGPOList,
  __in   PGROUP_POLICY_OBJECT pChangedGPOList,
  __in   ASYNCCOMPLETIONHANDLE pHandle,
  __in   BOOL *pbAbort,
  __in   PFNSTATUSMESSAGECALLBACK pStatusCallback,
  __in   IWbemServices *pWbemServices,
  __out  HRESULT *pRsopStatus)
{

 if(pStatusCallback)
   pStatusCallback (FALSE, L"Aaaaargh!");

   return (0);
}

此代码已尝试使用静态字符串、堆栈上的字节数组、新的和故意泄漏的字节数组 - 以防该方法获得内存的所有权。也被 CoTaskMemAlloc'd,以防万一。都产生同样的问题。

事件日志中的(已编辑)错误是:

Windows 无法处理组策略客户端扩展异常 0xc0000005。

Windows cannot process Group Policy Client Side Extension Exception 0xc0000005.

有趣的是,这只是在某些操作系统上,完全修补的 XP 32 位是确定的问题之一。 2008R2 工作正常。

是的 - 我们需要它在 XP 32 位上工作。

其他可能与此有关的奇怪行为: 如果我们多次调用此函数,它会在第 3 次调用时失败。没有抛出异常,没有显示文本,执行调用后没有我们的代码,事件日志中没有其他错误。时间在这里不是一个因素:如果你连续调用它 3 次,或者在 5 分钟内调用 3 次,它就会发生。 如果我们将调用包装在通用的 try/catch block 中,则不会发生这种情况。没有捕获到异常 - 显示所有文本。所有代码都运行。 但是,我们仍然在事件日志中收到错误。

最佳答案

看来我们已经发现了这个问题。

问题在于回调需要使用 __stdcall 调用约定进行。 默认情况下,visual studio 使用 __cdecl 调用约定创建项目。 如果您将/Gz 标志添加到您的项目,它将默认使用 __stdcall。然而,我们不能这样做,因为我们正在引入具有不同调用约定的其他模块。

潜在的问题是 UserEnv.h 像这样定义回调:

typedef DWORD (*PFNSTATUSMESSAGECALLBACK)(__in BOOL bVerbose, __in LPWSTR lpMessage);

这是一个奇怪的定义。所有其他窗口回调都是这样定义的:

typedef INT_PTR (CALLBACK* DLGPROC)(HWND, UINT, WPARAM, LPARAM);

CALLBACK 很重要,它展开如下:

#define CALLBACK    __stdcall

这意味着默认情况下,出于某种原因,所有窗口回调都被定义为使用 __stdcall 调用约定,除了这个。

如果我们创建自己的回调定义:

typedef DWORD (CALLBACK *PFNSTATUSMESSAGECALLBACK_STDCALL)(__in BOOL bVerbose, __in LPWSTR lpMessage);

并将我们的函数指针分配给它:

PFNSTATUSMESSAGECALLBACK_STDCALL pStatusCallback = (PFNSTATUSMESSAGECALLBACK_STDCALL)pRawStatusCallback;

然后我们可以将 pStatusCallback 函数指针与 __stdcall 调用约定一起使用,并让一切正常工作。

关于windows - 为什么调用 ProcessGroupPolicyEx 回调会导致访问冲突?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9742091/

相关文章:

windows - 为什么另一个线程中的阻塞 IO 会阻止 CreateWindowEx() 返回

c++ - CMake 无法在 Clion 的 Windows 上找到 freeglut

windows - 如何以编程方式检查我运行的是 Windows 8.1?

c++ - 使用 struct 和 wifstream 非法调用非静态成员函数

windows - 使用VB脚本监控目录

c - c中的原始输入winapi,无法获取设备信息

c - 过于频繁地调用 Shell_NotifyIcon 后托盘图标停止出现

java - 在用户登录/注销时运行 Java 程序的批处理文件

C# 如何禁用本地用户帐户的交互式登录。类似于网络服务帐户

windows - DataStage 11.3 装配编辑器闪存弹出窗口