4

私は、クライアント側の拡張機能のコードを使用して同僚を支援しようとしています。コールバックへの呼び出しを追加したため、関数は正常に完了したように見えますが、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も実行されました。すべて同じ問題が発生します。

イベントログの(編集済み)エラーは次のとおりです。

Windowsは、グループポリシークライアント側拡張機能例外0xc0000005を処理できません。

Windowsは、グループポリシークライアント側拡張機能例外0xc0000005を処理できません。

興味深いことに、これは一部のOSにのみ当てはまり、完全にパッチが適用されたXP32ビットは明確な問題の1つです。2008R2は正常に動作します。

はい-XP32ビットで動作するために必要です。

ここで関係があるかもしれない他の奇妙な振る舞い:この関数を複数回呼び出すと、3回目の呼び出しで失敗します。例外はスローされず、テキストも表示されず、呼び出しが実行された後のコードも、イベントログに追加のエラーもありません。ここではタイミングは重要ではありません。3回続けて呼び出すか、5分間に3回呼び出すと発生します。呼び出しを一般的なtry/catchブロックでラップする場合、これは発生しません。例外はキャッチされません-すべてのテキストが表示されます。すべてのコードが実行されます。ただし、イベントログには引き続きエラーが記録されます。

4

1 に答える 1

4

これで問題が見つかったようです。

問題は、コールバックを__stdcall呼び出し規約で行う必要があることです。デフォルトでは、VisualStudioは__cdecl呼び出し規約を使用してプロジェクトを作成します。プロジェクトに/Gzフラグを追加すると、デフォルトで__stdcallが使用されます。ただし、呼び出し規約が異なる他のモジュールをプルしているため、これを行うことはできませんでした。

根本的な問題は、UserEnv.hが次のようにコールバックを定義することです。

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

これは奇妙な定義です。他のすべてのWindowsコールバックは、次のように定義されます。

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

そのコールバックは重要です、それはこのように拡大します:

#define CALLBACK    __stdcall

これは、デフォルトでは、何らかの理由で、これを除いて、すべてのWindowsコールバックが__stdcall呼び出し規約を使用するように定義されていることを意味します。

独自のコールバック定義を作成する場合:

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

そして、それに関数ポインタを割り当てます。

PFNSTATUSMESSAGECALLBACK_STDCALL pStatusCallback = (PFNSTATUSMESSAGECALLBACK_STDCALL)pRawStatusCallback;

次に、pStatusCallback関数ポインターを__stdcall呼び出し規約で使用して、正常に動作させることができます。

于 2012-03-20T10:49:36.320 に答える