Creating a Policy Callback Function
The system calls registered policy callback functions so they can apply policy. Each callback function receives a pointer to the list of deleted GPOs and a pointer to the list of changed GPOs. For more information, see ProcessGroupPolicy, ProcessGroupPolicyEx, and Registering a Policy Callback Function.
The dwFlags parameter to the policy callback function indicates whether user or computer policy is applied. If user policy is applied and the user logs off, the pbAbort parameter is set to TRUE and the callback function should stop applying policy. Similarly, if computer policy is applied and the computer is shutting down, pbAbort is set to TRUE and the callback function should stop applying policy.
Policy callback functions can apply policy either synchronously or asynchronously. The code sample in this topic demonstrates a callback function that applies policy synchronously. This is the recommended method for applying policy in a policy callback function.
To register this callback function, create a subkey under the following registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions
The subkey should be a GUID, so that it is unique. The following table lists subkey values.
Value | Meaning |
---|---|
DllName | A REG_EXPAND_SZ value that specifies the path to the DLL that contains the callback function. |
EnableAsynchronousProcessing | If this value is 1, the callback function will complete its processing asynchronously. When the callback function is finished, it should call the ProcessGroupPolicyCompletedEx function. |
ExtensionEventSource | A REG_MULTI_SZ value that specifies the (event source name, event log name) for client-side extensions. |
GenerateGroupPolicy | A REG_SZ value that specifies the name of the GenerateGroupPolicy callback function that generates RSoP data. |
MaxNoGPOListChangesInterval | Specifies the maximum time, in minutes, to skip the extension when policy has not changed. If the system is refreshing policy and this limit has been exceeded, the system calls the extension without specifying GPO_INFO_FLAG_NOCHANGES. |
NoBackgroundPolicy | If this value is 1, do not call the callback function when policy is applied in the background. |
NoGPOListChanges | If this value is 1, it indicates that it is not necessary to call the callback function when there has been no change in the GPO list. |
NoMachinePolicy | If this value is 1, do not call the callback function when computer policy is processed. |
NoSlowLink | If this value is 1, do not call the callback function over a slow link. |
NotifyLinkTransition | If this value is 1, call the callback function to notify the extension when a change in link speed is detected between policy applications. |
NoUserPolicy | If this value is 1, do not call the callback function when user policy is processed. |
PerUserLocalSettings | If this value is 1, user policy settings must be cached on a per-user and per-computer basis. |
ProcessGroupPolicy | A REG_SZ value that specifies the name of the application-defined ProcessGroupPolicy callback function. Be aware that this value has been superseded by the ProcessGroupPolicyEx value. |
ProcessGroupPolicyEx | A REG_SZ value that specifies the name of the application-defined ProcessGroupPolicyEx callback function. |
RequiresSuccessfulRegistry | If this value is 1, the callback function should be called only if the registry extension was successfully processed on the client. |
The following code example shows how to use a policy callback function to apply policy synchronously.
Note
This sample does not demonstrate RSoP support. For more information about an RSoP-enabled client-side extension, see ProcessGroupPolicyEx and Implementing RSoP Support for a Client-side Extension.
#include <windows.h>
#include <userenv.h>
DWORD CALLBACK ProcessGroupPolicy(
DWORD dwFlags,
HANDLE hToken,
HKEY hKeyRoot,
PGROUP_POLICY_OBJECT pDeletedGPOList,
PGROUP_POLICY_OBJECT pChangedGPOList,
ASYNCCOMPLETIONHANDLE pHandle,
BOOL *pbAbort,
PFNSTATUSMESSAGECALLBACK pStatusCallback
)
{
PGROUP_POLICY_OBJECT pCurGPO;
// Check dwFlags for settings.
// ...
// Process deleted GPOs.
for( pCurGPO = pDeletedGPOList; pCurGPO; pCurGPO = pCurGPO->pNext )
{
if( *pbAbort )
{
// Abort.
break;
}
// ...
}
// Process changed GPOs.
for( pCurGPO = pChangedGPOList; pCurGPO; pCurGPO = pCurGPO->pNext )
{
if( *pbAbort )
{
// Abort.
break;
}
// ...
}
return( ERROR_SUCCESS );
}
If your callback function processes policy asynchronously, your implementation of the ProcessGroupPolicy function will differ slightly. The callback function will create a thread to process the GPO lists. When the thread has finished processing the GPOs, the thread will call the ProcessGroupPolicyCompleted function to indicate that policy has been applied. In the case of an RSoP-enabled client-side extension, the callback function calls the ProcessGroupPolicyCompletedEx function instead of ProcessGroupPolicyCompleted.