windows - Hvorfor forårsager CallGroupPolicyEx-tilbagekaldelse en adgangsfejl?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg forsøger at hjælpe en kollega med en kode i en klientsideforlængelse. Siden jeg tilføjede et opkald til tilbagekaldelsen, synes funktionen at være ok, men en begivenhed i Windows Event loggen klager over en adgangsfejl under behandling af gruppen politisk objekt.


Efter at have fjernet eksisterende kode, med netop det tilføjede opkald til tilbagekaldelsen, rapporterer det stadig denne adgangsfejl.


Kan du venligst hjælpe med at identificere, hvad vi mangler?


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


Denne kode er blevet forsøgt ved hjælp af en statisk streng, en række byte på stakken, en række byte, der er 'nye' d og bevidst lækket - hvis metoden var at tage ejerskab af hukommelsen. Også været CoTaskMemAlloc 'd, bare i tilfælde. Alle producerer det samme problem.


Den (redacted) fejl i eventloggen er:


Windows kan ikke behandle gruppepolitisk klient sideudvidelsesundtagelse 0xc0000005.


Windows kan ikke behandle Group Policy Client Side Extension Exception 0xc0000005.


For at gøre tingene interessante, er dette kun på nogle OS'er, fuldt patched XP 32bit er et af de konkrete problemer. 2008R2 fungerer fint.


Ja - vi har brug for det til at arbejde på XP 32bit.


Andet underligt opførsel, der kan have betydning her:
Hvis vi kalder denne funktion flere gange, fejler den ikke på det tredje opkald. Ingen undtagelse kastes, ingen tekst vises, ingen af ​​vores kode efter at opkaldet er udført, ingen yderligere fejl i hændelsesloggen. Timing er ikke en faktor her: Det sker, hvis du kalder det 3 gange i træk, eller 3 gange over 5 minutter.
Dette sker ikke, hvis vi samler opkaldene i en generisk prøve/fangstblok. Ingen undtagelse er fanget - hele teksten vises. Alle koden køres.
Vi får dog stadig fejlen i hændelsesloggen.

Bedste reference


Det ser ud som om vi har fundet problemet med dette.


Problemet er, at tilbagekaldelsen skal foretages med \_\_stdcall calling convention.
Som standard opretter Visual Studio projekter med \_\_cdecl-opkaldskonventionen.
Hvis du tilføjer/Gz-flag til dit projekt, vil det \_\_stdcall som standard bruge. Det kunne vi imidlertid ikke, da vi trækker i andre moduler med forskellige kaldkonventioner.


Det underliggende problem er, at UserEnv.h definerer tilbagekaldelsen som denne:


typedef DWORD (*PFNSTATUSMESSAGECALLBACK)(\_\_in BOOL bVerbose, \_\_in LPWSTR lpMessage);


Dette er en mærkelig definition. Alle andre vinduer tilbagekald er defineret som dette:


typedef INT\_PTR (CALLBACK* DLGPROC)(HWND, UINT, WPARAM, LPARAM);


At CALLBACK er vigtigt, det udvider sig således:


#define CALLBACK    \_\_stdcall


Dette betyder, at alle Windows-tilbagekaldelser som standard er defineret til at bruge \_\_stdcall-kaldkonventioner, undtagen denne, af en eller anden grund.


Hvis vi opretter vores egen tilbagekaldelsesdefinition:


typedef DWORD (CALLBACK *PFNSTATUSMESSAGECALLBACK\_STDCALL)(\_\_in BOOL bVerbose, \_\_in LPWSTR lpMessage);


Og tildel vores funktionspeger til det:


PFNSTATUSMESSAGECALLBACK\_STDCALL pStatusCallback = (PFNSTATUSMESSAGECALLBACK\_STDCALL)pRawStatusCallback;


Derefter kan vi bruge pStatusCallback-funktionspekeren med \_\_stdcall-kaldkonventionen og få tingene til at fungere korrekt.