Почему вызов обратного вызова ProcessGroupPolicyEx вызывает нарушение прав доступа? - PullRequest
4 голосов
/ 16 марта 2012

Я пытаюсь помочь коллеге с некоторым кодом в клиентском расширении.После добавления вызова к обратному вызову функция, кажется, завершается нормально, но событие в журнале событий 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 32bit является одной из определенных проблем.2008R2 работает нормально.

Да - нам нужно, чтобы он работал на XP 32-битной версии.

Другое странное поведение, которое может иметь здесь значение: если мы вызываем эту функцию несколько раз, она завершается ошибкой 3-говызов.Никаких исключений не выдается, текст не отображается, ни один из нашего кода после выполнения вызова, никаких дополнительных ошибок в журнале событий.Время здесь не имеет значения: это происходит, если вы вызываете его 3 раза подряд или 3 раза за 5 минут.Этого не произойдет, если мы обернем вызовы в общий блок try / catch.Никаких исключений не ловится - весь текст отображается.Весь код запускается.Однако мы все равно получаем ошибку в журнале событий.

1 Ответ

4 голосов
/ 20 марта 2012

Похоже, мы нашли проблему с этим.

Проблема в том, что обратный вызов должен быть выполнен с соглашением о вызовах __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);

Этот ЗВОНОК важен, он расширяется так:

#define CALLBACK    __stdcall

Это означает, что по умолчанию все обратные вызовы окон определены для использования __stdcall соглашений о вызовах, кроме этой, по некоторым причинам.

Если мы создадим наше собственное определение обратного вызова:

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

И присвоить ему указатель нашей функции:

PFNSTATUSMESSAGECALLBACK_STDCALL pStatusCallback = (PFNSTATUSMESSAGECALLBACK_STDCALL)pRawStatusCallback;

Затем мы можем использовать указатель на функцию pStatusCallback с соглашением о вызовах __stdcall, и все будет работать правильно.

...