Why does calling ProcessGroupPolicyEx cause an access violation?

I am trying to help a colleague with some code to expand the client side. From the moment it is added to the callback, the function seems to complete normally, but the event in the Windows event log complains about an access violation while processing the GPO.

After deleting existing code with an added callback, it still reports this access violation.

Could you help determine what we can lose?

// // 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); } 

This code was tested using a static string, an array of bytes on the stack, an array of bytes that was new and deliberately leaked - in case the method claimed responsibility for the memory. Also was CoTaskMemAlloc'd, just in case. All produce the same problem.

Error (redacted) in the event log:

Windows cannot handle the 0xc0000005 Group Policy Client Side Failure exception.

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

To do something interesting, it's just on some OSs, the fully patched XP 32bit is one of the specific issues. 2008R2 works great.

Yes - we need it to work on XP 32bit.

Another strange behavior that may be relevant here: If we call this function several times, it fails in the third call. No exception is thrown, the text is not displayed, none of our code after making the call contains additional errors in the event log. Timing is not a factor here: it happens if you call it 3 times in a row, or 3 times in 5 minutes. This does not happen if we end calls in a common try / catch block. Excluded is not an exception - all text is displayed. All code is running. However, we still get an error in the event log.

+4
source share
1 answer

Looks like we found a problem with this.

The problem is that the callback must be done using the __stdcall calling convention. By default, visual studio creates projects using the __cdecl declaration convention. If you add the / Gz flag to your project, it will use __stdcall by default. However, we could not do this, since we deal with other modules with different calling conventions.

The main problem is that UserEnv.h defines the callback as follows:

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

This is a strange definition. All other window callbacks are defined as follows:

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

This callback is important, it expands as follows:

 #define CALLBACK __stdcall 

This means that by default, all Windows callbacks are defined to use __stdcall conditional calls, except for this, for some reason.

If we create our own callback check:

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

And assign us our function pointer:

 PFNSTATUSMESSAGECALLBACK_STDCALL pStatusCallback = (PFNSTATUSMESSAGECALLBACK_STDCALL)pRawStatusCallback; 

Then we can use the pStatusCallback function pointer with the __stdcall calling convention and work correctly.

+4
source

Source: https://habr.com/ru/post/1401872/


All Articles