加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

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

发布时间:2020-12-14 05:31:37 所属栏目:Windows 来源:网络整理
导读:我正在尝试帮助一位同事在客户端扩展中使用一些代码.由于添加了对回调的调用,该函数似乎完成正常,但 Windows事件日志中的事件在处理组策略对象时会抱怨访问冲突. 删除现有代码后,只需添加对回调的调用,它仍会报告此访问冲突. 你能帮忙找出我们可能缺少的东西
我正在尝试帮助一位同事在客户端扩展中使用一些代码.由于添加了对回调的调用,该函数似乎完成正常,但 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.

为了让事情变得有趣,这只是在一些操作系统上,完全修补的XP 32bit是一个明确的问题. 2008R2工作正常.

是的 – 我们需要它在XP 32bit上运行.

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

解决方法

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

问题是需要使用__stdcall调用约定来进行回调.
默认情况下,visual studio使用__cdecl调用约定创建项目.
如果将/ Gz标志添加到项目中,默认情况下将使用__stdcall.但是,我们无法做到这一点,因为我们正在使用不同的调用约定来引入其他模块.

根本问题是UserEnv.h定义了这样的回调:

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

这是一个奇怪的定义.所有其他Windows回调定义如下:

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调用约定一起使用,并使事情正常工作.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读