我试图帮助同事在客户端扩展中使用一些代码。由于添加了对回调的调用,该函数似乎完成正常,但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块中,则不会发生这种情况。没有异常被捕获 - 显示所有文本。所有代码都运行完毕。 但是,我们仍然会在事件日志中收到错误。
答案 0 :(得分:4)
看起来我们已经发现了这个问题。
问题是需要使用__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
这意味着默认情况下,由于某种原因,所有Windows回调都被定义为使用__stdcall调用约定,除此之外。
如果我们创建自己的回调定义:
typedef DWORD (CALLBACK *PFNSTATUSMESSAGECALLBACK_STDCALL)(__in BOOL bVerbose, __in LPWSTR lpMessage);
并将我们的函数指针指定给它:
PFNSTATUSMESSAGECALLBACK_STDCALL pStatusCallback = (PFNSTATUSMESSAGECALLBACK_STDCALL)pRawStatusCallback;
然后我们可以将pStatusCallback函数指针与__stdcall调用约定一起使用,并使事情正常工作。