test: ex/callback.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# callback.c File Reference

`#include "exp.h"`

Go to the source code of this file.

## Classes

struct | _CALLBACK_OBJECT
struct | _CALLBACK_REGISTRATION

## Defines

#define | CALLBACK_MODIFY_STATE 0x0001
#define | CALLBACK_ALL_ACCESS

## Typedefs

typedef _CALLBACK_OBJECT | CALLBACK_OBJECT
typedef _CALLBACK_OBJECT * | PCALLBACK_OBJECT
typedef _CALLBACK_REGISTRATION | CALLBACK_REGISTRATION
typedef _CALLBACK_REGISTRATION * | PCALLBACK_REGISTRATION

## Functions

VOID | ExpDeleteCallback (IN PCALLBACK_OBJECT CallbackObject)
BOOLEAN | ExpInitializeCallbacks ()
NTSTATUS | ExCreateCallback (OUT PCALLBACK_OBJECT *CallbackObject, IN POBJECT_ATTRIBUTES ObjectAttributes, IN BOOLEAN Create, IN BOOLEAN AllowMultipleCallbacks)
PVOID | ExRegisterCallback (IN PCALLBACK_OBJECT CallbackObject, IN PCALLBACK_FUNCTION CallbackFunction, IN PVOID CallbackContext)
VOID | ExUnregisterCallback (IN PVOID CbRegistration)
VOID | ExNotifyCallback (IN PCALLBACK_OBJECT CallbackObject, IN PVOID Argument1, IN PVOID Argument2)

## Variables

POBJECT_TYPE | ExCallbackObjectType
KEVENT | ExpCallbackEvent
GENERIC_MAPPING | ExpCallbackMapping

## Define Documentation

#define CALLBACK_ALL_ACCESS

Value:

    (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|\
                                 CALLBACK_MODIFY_STATE )

Definition at line 35 of file ex/callback.c.

Referenced by ExpInitializeCallbacks().

#define CALLBACK_MODIFY_STATE 0x0001

| Definition at line 33 of file ex/callback.c.

## Typedef Documentation

typedef struct _CALLBACK_OBJECT CALLBACK_OBJECT

typedef struct _CALLBACK_REGISTRATION CALLBACK_REGISTRATION

typedef struct _CALLBACK_OBJECT * PCALLBACK_OBJECT

| Referenced by ExCreateCallback(), and ExUnregisterCallback().

typedef struct _CALLBACK_REGISTRATION * PCALLBACK_REGISTRATION

| Referenced by ExNotifyCallback(), ExRegisterCallback(), and ExUnregisterCallback().

## Function Documentation

NTSTATUS ExCreateCallback | ( | OUT PCALLBACK_OBJECT * | CallbackObject,
|  | IN POBJECT_ATTRIBUTES | ObjectAttributes,
|  | IN BOOLEAN | Create,
|  | IN BOOLEAN | AllowMultipleCallbacks
| ) |

Definition at line 222 of file ex/callback.c.

References Create(), ExCallbackObjectType, Handle, KeInitializeSpinLock(), KernelMode, NT_SUCCESS, NTSTATUS(), NULL, ObCreateObject(), ObInsertObject(), ObjectAttributes, ObOpenObjectByName(), ObReferenceObjectByHandle(), PAGED_CODE, PCALLBACK_OBJECT, and Status.

Referenced by ExpInitializeCallbacks().

    00231                    :
    00232
    00233     This function opens a callback object with the specified callback
    00234     object. If the callback object does not exist or it is a NULL then
    00235     a callback object will be created if create is TRUE. If a callbackobject
    00236     is created it will only support mulitiple registered callbacks if
    00237     AllowMulitipleCallbacks is TRUE.
    00238
    00239 Arguments:
    00240
    00241     CallbackObject - Supplies a pointer to a variable that will receive the
    00242         Callback object.
    00243
    00244     CallbackName  - Supplies a pointer to a object name that will receive the
    00245
    00246     Create - Supplies a flag which indicates whether a callback object will
    00247         be created or not .
    00248
    00249     AllowMultipleCallbacks - Supplies a flag which indicates only support
    00250         mulitiple registered callbacks.
    00251
    00252 Return Value:
    00253
    00254     Returns STATUS_SUCESS unless fali...
    00255
    00256 --*/
    00257
    00258 {
    00259     PCALLBACK_OBJECT cbObject;
    00260     NTSTATUS Status;
    00261     HANDLE Handle;
    00262
    00263     PAGED_CODE();
    00264
    00265     //
    00266     // If named callback, open handle to it
    00267     //
    00268
    00269     if (ObjectAttributes->ObjectName) {
    00270         Status = ObOpenObjectByName(ObjectAttributes,
    00271                                     ExCallbackObjectType,
    00272                                     KernelMode,
    00273                                     NULL,
    00274                                     0,   // DesiredAccess,
    00275                                     NULL,
    00276                                     &Handle);
    00277     } else {
    00278         Status = STATUS_UNSUCCESSFUL;
    00279     }
    00280
    00281     //
    00282     // If not opened, check if callback should be created
    00283     //
    00284
    00285     if(!NT_SUCCESS(Status) && Create ) {
    00286         Status = ObCreateObject(KernelMode,
    00287                                 ExCallbackObjectType,
    00288                                 ObjectAttributes,
    00289                                 KernelMode,
    00290                                 NULL,
    00291                                 sizeof(CALLBACK_OBJECT),
    00292                                 0,
    00293                                 0,
    00294                                 (PVOID *)&cbObject );
    00295
    00296         if(NT_SUCCESS(Status)){
    00297
    00298             //
    00299             // Fill in structure signature
    00300             //
    00301
    00302             cbObject->Signature = 'llaC';
    00303
    00304             //
    00305             // It will support multiple registered callbacks if
    00306             // AllowMultipleCallbacks is TRUE.
    00307             //
    00308
    00309             cbObject->AllowMultipleCallbacks = AllowMultipleCallbacks;
    00310
    00311             //
    00312             // Initialize CallbackObject queue.
    00313             //
    00314
    00315             InitializeListHead( &cbObject->RegisteredCallbacks );
    00316
    00317             //
    00318             // Initialize spinlock
    00319             //
    00320
    00321             KeInitializeSpinLock (&cbObject->Lock);
    00322
    00323
    00324             //
    00325             // Put the object in the root directory
    00326             //
    00327
    00328             Status = ObInsertObject (
    00329                      cbObject,
    00330                      NULL,
    00331                      FILE_READ_DATA,
    00332                      0,
    00333                      NULL,
    00334                      &Handle );
    00335
    00336         }
    00337
    00338     }
    00339
    00340     if(NT_SUCCESS(Status)){
    00341
    00342         //
    00343         // Add one to callback object reference count
    00344         //
    00345
    00346         Status = ObReferenceObjectByHandle (
    00347                     Handle,
    00348                     0,          // DesiredAccess
    00349                     ExCallbackObjectType,
    00350                     KernelMode,
    00351                     &cbObject,
    00352                     NULL
    00353                     );
    00354
    00355         ZwClose (Handle);
    00356     }
    00357
    00358     //
    00359     // If SUCEESS , returns a referenced pointer to the CallbackObject.
    00360     //
    00361
    00362     if (NT_SUCCESS(Status)) {
    00363         *CallbackObject = cbObject;
    00364     }
    00365
    00366     return Status;
    00367 }

VOID ExNotifyCallback | ( | IN PCALLBACK_OBJECT | CallbackObject,
|  | IN PVOID | Argument1,
|  | IN PVOID | Argument2
| ) |

Definition at line 563 of file ex/callback.c.

References _CALLBACK_REGISTRATION::Busy, _CALLBACK_REGISTRATION::CallbackContext, _CALLBACK_REGISTRATION::CallbackFunction, DISPATCH_LEVEL, ExpCallbackEvent, FALSE, KeAcquireSpinLock, KeReleaseSpinLock(), KeSetEvent(), NULL, PCALLBACK_REGISTRATION, and _CALLBACK_REGISTRATION::UnregisterWaiting.

    00571                    :
    00572
    00573     This function notifies all registered callbacks .
    00574
    00575 Arguments:
    00576
    00577     CallbackObject - supplies a pointer to the callback object should be
    00578             notified.
    00579
    00580     SystemArgument1 - supplies a pointer will be passed to callback function.
    00581
    00582     SystemArgument2 - supplies a pointer will be passed to callback function.
    00583
    00584 Return Value:
    00585
    00586     None.
    00587
    00588 --*/
    00589
    00590 {
    00591     PLIST_ENTRY             Link;
    00592     PCALLBACK_REGISTRATION  CallbackRegistration;
    00593     KIRQL                   OldIrql;
    00594
    00595     if (CallbackObject == NULL) {
    00596         return ;
    00597     }
    00598
    00599     //
    00600     // Synchronize with callback object
    00601     //
    00602
    00603     KeAcquireSpinLock (&CallbackObject->Lock, &OldIrql);
    00604
    00605     //
    00606     // call registered callbacks at callers IRQL level
    00607     // ( done if FIFO order of registration )
    00608     //
    00609
    00610     if (OldIrql == DISPATCH_LEVEL) {
    00611
    00612         //
    00613         // OldIrql is DISPATCH_LEVEL, just invoke all callbacks without
    00614         // releasing the lock
    00615         //
    00616
    00617         for (Link = CallbackObject->RegisteredCallbacks.Flink;
    00618              Link != &CallbackObject->RegisteredCallbacks;
    00619              Link = Link->Flink) {
    00620
    00621             //
    00622             // Get current registration to notify
    00623             //
    00624
    00625             CallbackRegistration = CONTAINING_RECORD (Link,
    00626                                                       CALLBACK_REGISTRATION,
    00627                                                       Link);
    00628
    00629             //
    00630             // Notify reigstration
    00631             //
    00632
    00633             CallbackRegistration->CallbackFunction(
    00634                        CallbackRegistration->CallbackContext,
    00635                        Argument1,
    00636                        Argument2
    00637                        );
    00638
    00639         }   // next registration
    00640
    00641     } else {
    00642
    00643         //
    00644         // OldIrql is < DISPATCH_LEVEL, the code being called may be pagable
    00645         // and the callback object spinlock needs to be released around
    00646         // each registration callback.
    00647         //
    00648
    00649         for (Link = CallbackObject->RegisteredCallbacks.Flink;
    00650              Link != &CallbackObject->RegisteredCallbacks;
    00651              Link = Link->Flink ) {
    00652
    00653             //
    00654             // Get current registration to notify
    00655             //
    00656
    00657             CallbackRegistration = CONTAINING_RECORD (Link,
    00658                                                       CALLBACK_REGISTRATION,
    00659                                                       Link);
    00660
    00661             //
    00662             // If registration is being removed, don't bothing calling it
    00663             //
    00664
    00665             if (!CallbackRegistration->UnregisterWaiting) {
    00666
    00667                 //
    00668                 // Set registration busy
    00669                 //
    00670
    00671                 CallbackRegistration->Busy += 1;
    00672
    00673                 //
    00674                 // Release SpinLock and notify this callback
    00675                 //
    00676
    00677                 KeReleaseSpinLock (&CallbackObject->Lock, OldIrql);
    00678
    00679                 CallbackRegistration->CallbackFunction(
    00680                            CallbackRegistration->CallbackContext,
    00681                            Argument1,
    00682                            Argument2
    00683                            );
    00684
    00685                 //
    00686                 // Synchronize with CallbackObject
    00687                 //
    00688
    00689                 KeAcquireSpinLock (&CallbackObject->Lock, &OldIrql);
    00690
    00691                 //
    00692                 // Remove our busy count
    00693                 //
    00694
    00695                 CallbackRegistration->Busy -= 1;
    00696
    00697                 //
    00698                 // If the registriation removal is pending, kick global
    00699                 // event let unregister conitnue
    00700                 //
    00701
    00702                 if (CallbackRegistration->UnregisterWaiting  &&
    00703                     CallbackRegistration->Busy == 0) {
    00704                     KeSetEvent (&ExpCallbackEvent, 0, FALSE);
    00705                 }
    00706             }
    00707         }
    00708     }
    00709
    00710
    00711     //
    00712     // Release callback
    00713     //
    00714
    00715     KeReleaseSpinLock (&CallbackObject->Lock, OldIrql);
    00716 }
    }

VOID ExpDeleteCallback | ( | IN PCALLBACK_OBJECT | CallbackObject | ) |

Definition at line 370 of file ex/callback.c.

References ASSERT.

Referenced by ExpInitializeCallbacks().

    00373 {
    00374     ASSERT (IsListEmpty(&CallbackObject->RegisteredCallbacks));
    00375 }

BOOLEAN ExpInitializeCallbacks | ( |  | ) |

Definition at line 101 of file ex/callback.c.

References CALLBACK_ALL_ACCESS, EXP_INITIALIZE_GLOBAL_CALLBACKS::CallBackObject, ExCallbackObjectType, ExCreateCallback(), ExpCallbackEvent, ExpCallbackMapping, ExpDeleteCallback(), ExpInitializeCallback, ExpWstrCallback, FALSE, KeInitializeEvent, L, NonPagedPool, NT_SUCCESS, NtClose(), NtCreateDirectoryObject(), NTSTATUS(), NULL, ObCreateObjectType(), OBJECT_TYPE_INITIALIZER, ObjectAttributes, RtlInitUnicodeString(), SePublicDefaultSd, Status, and TRUE.

    00106                    :
    00107
    00108     This function creates the callback object type descriptor at system
    00109     initialization and stores the address of the object type descriptor
    00110     in local static storage.
    00111
    00112 Arguments:
    00113
    00114     None.
    00115
    00116 Return Value:
    00117
    00118     A value of TRUE is returned if the timer object type descriptor is
    00119     successfully initialized. Otherwise a value of FALSE is returned.
    00120
    00121 --*/
    00122
    00123 {
    00124     OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
    00125     OBJECT_ATTRIBUTES ObjectAttributes;
    00126     NTSTATUS Status;
    00127     UNICODE_STRING unicodeString;
    00128     ULONG           i;
    00129     HANDLE          handle;
    00130
    00131     //
    00132     // Initialize string descriptor.
    00133     //
    00134
    00135     RtlInitUnicodeString(&unicodeString, L"Callback");
    00136
    00137     //
    00138     // Create timer object type descriptor.
    00139     //
    00140
    00141     RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
    00142     ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
    00143     ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
    00144     ObjectTypeInitializer.GenericMapping = ExpCallbackMapping;
    00145     ObjectTypeInitializer.DeleteProcedure = ExpDeleteCallback;
    00146     ObjectTypeInitializer.PoolType = NonPagedPool;
    00147     ObjectTypeInitializer.ValidAccessMask = CALLBACK_ALL_ACCESS;
    00148     Status = ObCreateObjectType(&unicodeString,
    00149                                 &ObjectTypeInitializer,
    00150                                 (PSECURITY_DESCRIPTOR)NULL,
    00151                                 &ExCallbackObjectType);
    00152
    00153     if (!NT_SUCCESS(Status)) {
    00154         return FALSE;
    00155     }
    00156
    00157     RtlInitUnicodeString( &unicodeString, ExpWstrCallback );
    00158     InitializeObjectAttributes(
    00159         &ObjectAttributes,
    00160         &unicodeString,
    00161         OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
    00162         NULL,
    00163         SePublicDefaultSd
    00164         );
    00165
    00166     Status = NtCreateDirectoryObject(
    00167                 &handle,
    00168                 DIRECTORY_ALL_ACCESS,
    00169                 &ObjectAttributes
    00170             );
    00171
    00172     if (!NT_SUCCESS(Status)) {
    00173         return FALSE;
    00174     }
    00175
    00176     NtClose (handle);
    00177
    00178     //
    00179     // Initialize event to wait on for Unregisters which occur while
    00180     // notifications are in progress
    00181     //
    00182
    00183     KeInitializeEvent (&ExpCallbackEvent, NotificationEvent, 0);
    00184
    00185     //
    00186     // Initialize NT global callbacks
    00187     //
    00188
    00189     for (i=0; ExpInitializeCallback[i].CallBackObject; i++) {
    00190
    00191         //
    00192         // Create named calledback
    00193         //
    00194
    00195         RtlInitUnicodeString(&unicodeString, ExpInitializeCallback[i].CallbackName);
    00196
    00197
    00198         InitializeObjectAttributes(
    00199             &ObjectAttributes,
    00200             &unicodeString,
    00201             OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
    00202             NULL,
    00203             NULL
    00204         );
    00205
    00206         Status = ExCreateCallback (
    00207                         ExpInitializeCallback[i].CallBackObject,
    00208                         &ObjectAttributes,
    00209                         TRUE,
    00210                         TRUE
    00211                         );
    00212
    00213         if (!NT_SUCCESS(Status)) {
    00214             return FALSE;
    00215         }
    00216     }
    00217
    00218     return TRUE;
    00219 }

PVOID ExRegisterCallback | ( | IN PCALLBACK_OBJECT | CallbackObject,
|  | IN PCALLBACK_FUNCTION | CallbackFunction,
|  | IN PVOID | CallbackContext
| ) |

Definition at line 378 of file ex/callback.c.

References ASSERT, _CALLBACK_REGISTRATION::Busy, _CALLBACK_REGISTRATION::CallbackContext, _CALLBACK_REGISTRATION::CallbackFunction, _CALLBACK_REGISTRATION::CallbackObject, DISPATCH_LEVEL, ExAllocatePoolWithTag, ExFreePool(), FALSE, KeAcquireSpinLock, KeReleaseSpinLock(), _CALLBACK_REGISTRATION::Link, NonPagedPool, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObject, PCALLBACK_FUNCTION, PCALLBACK_REGISTRATION, Status, TRUE, and _CALLBACK_REGISTRATION::UnregisterWaiting.

    00386                    :
    00387
    00388     This routine allows a caller to register that it would like to have its
    00389     callback Function invoked when the callback notification call occurs.
    00390
    00391 Arguments:
    00392
    00393     CallbackObject - Supplies a pointer to a CallbackObject.
    00394
    00395     CallbackFunction - Supplies a pointer to a function which is to
    00396         be executed when the Callback notification occures.
    00397
    00398     CallbackContext - Supplies a pointer to an arbitrary data structure
    00399         that will be passed to the function specified by the CallbackFunction
    00400         parameter.
    00401
    00402 Return Value:
    00403
    00404     Returns handle to callback registration.
    00405
    00406 --*/
    00407 {
    00408     PCALLBACK_REGISTRATION  CallbackRegistration;
    00409     BOOLEAN                 Inserted;
    00410     KIRQL                   OldIrql;
    00411     NTSTATUS                Status;
    00412
    00413     ASSERT (CallbackFunction);
    00414     ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
    00415
    00416     //
    00417     // Add reference to object
    00418     //
    00419
    00420     ObReferenceObject (CallbackObject);
    00421
    00422     //
    00423     // Begin by attempting to allocate storage for the CallbackRegistration.
    00424     // one cannot be allocated, return the error status.
    00425     //
    00426
    00427     CallbackRegistration = ExAllocatePoolWithTag(
    00428                                 NonPagedPool,
    00429                                 sizeof( CALLBACK_REGISTRATION ),
    00430                                 'eRBC'
    00431                                 );
    00432
    00433
    00434     if( !CallbackRegistration ) {
    00435        ObDereferenceObject (CallbackObject);
    00436        return NULL;
    00437     }
    00438
    00439
    00440     //
    00441     // Initialize the callback packet
    00442     //
    00443
    00444     CallbackRegistration->CallbackObject    = CallbackObject;
    00445     CallbackRegistration->CallbackFunction  = CallbackFunction;
    00446     CallbackRegistration->CallbackContext   = CallbackContext;
    00447     CallbackRegistration->Busy              = 0;
    00448     CallbackRegistration->UnregisterWaiting = FALSE;
    00449
    00450
    00451     Inserted = FALSE;
    00452     KeAcquireSpinLock (&CallbackObject->Lock, &OldIrql);
    00453
    00454     if( CallbackObject->AllowMultipleCallbacks ||
    00455         IsListEmpty( &CallbackObject->RegisteredCallbacks ) ) {
    00456
    00457        //
    00458        // add CallbackRegistration to tail
    00459        //
    00460
    00461
    00462        Inserted = TRUE;
    00463        InsertTailList( &CallbackObject->RegisteredCallbacks,
    00464                        &CallbackRegistration->Link )
    00465     }
    00466
    00467     KeReleaseSpinLock (&CallbackObject->Lock, OldIrql);
    00468
    00469     if (!Inserted) {
    00470        ExFreePool (CallbackRegistration);
    00471        CallbackRegistration = NULL;
    00472     }
    00473
    00474     return (PVOID) CallbackRegistration;
    00475 }

VOID ExUnregisterCallback | ( | IN PVOID | CbRegistration | ) |

Definition at line 479 of file ex/callback.c.

References ASSERT, _CALLBACK_REGISTRATION::Busy, _CALLBACK_REGISTRATION::CallbackObject, DISPATCH_LEVEL, Executive, ExFreePool(), ExpCallbackEvent, FALSE, KeAcquireSpinLock, KeClearEvent, KeReleaseSpinLock(), KernelMode, KeWaitForSingleObject(), _CALLBACK_REGISTRATION::Link, _CALLBACK_OBJECT::Lock, NULL, ObDereferenceObject, PCALLBACK_OBJECT, PCALLBACK_REGISTRATION, TRUE, and _CALLBACK_REGISTRATION::UnregisterWaiting.

    00485                    :
    00486
    00487     This function removes the callback registration for the callbacks
    00488     from the list of callback object .
    00489
    00490 Arguments:
    00491
    00492     CallbackRegistration - Pointer to device object for the file system.
    00493
    00494 Return Value:
    00495
    00496     None.
    00497
    00498 --*/
    00499
    00500 {
    00501     PCALLBACK_REGISTRATION  CallbackRegistration;
    00502     PCALLBACK_OBJECT        CallbackObject;
    00503     KIRQL                   OldIrql;
    00504
    00505     ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
    00506
    00507     CallbackRegistration = (PCALLBACK_REGISTRATION) CbRegistration;
    00508     CallbackObject = CallbackRegistration->CallbackObject;
    00509
    00510     KeAcquireSpinLock (&CallbackObject->Lock, &OldIrql);
    00511
    00512     //
    00513     // Wait for registration
    00514     //
    00515
    00516     while (CallbackRegistration->Busy) {
    00517
    00518         //
    00519         // Set waiting flag, then wait.  (not performance critical - use
    00520         // single global event to wait for any and all unregister waits)
    00521         //
    00522
    00523         CallbackRegistration->UnregisterWaiting = TRUE;
    00524         KeClearEvent (&ExpCallbackEvent);
    00525         KeReleaseSpinLock (&CallbackObject->Lock, OldIrql);
    00526
    00527         KeWaitForSingleObject (
    00528             &ExpCallbackEvent,
    00529             Executive,
    00530             KernelMode,
    00531             FALSE,
    00532             NULL
    00533         );
    00534
    00535         //
    00536         // Synchronize with callback object and recheck registration busy
    00537         //
    00538
    00539         KeAcquireSpinLock (&CallbackObject->Lock, &OldIrql);
    00540     }
    00541
    00542     //
    00543     // Registration not busy, remove it from the callback object
    00544     //
    00545
    00546     RemoveEntryList (&CallbackRegistration->Link);
    00547     KeReleaseSpinLock (&CallbackObject->Lock, OldIrql);
    00548
    00549     //
    00550     // Free memory used for CallbackRegistration
    00551     //
    00552
    00553     ExFreePool (CallbackRegistration);
    00554
    00555     //
    00556     // Remove reference count on CallbackObject
    00557     //
    00558
    00559     ObDereferenceObject (CallbackObject);
    00560 }

## Variable Documentation

POBJECT_TYPE ExCallbackObjectType

| Definition at line 43 of file ex/callback.c. Referenced by ExCreateCallback(), and ExpInitializeCallbacks().

KEVENT ExpCallbackEvent

| Definition at line 49 of file ex/callback.c. Referenced by ExNotifyCallback(), ExpInitializeCallbacks(), and ExUnregisterCallback().

GENERIC_MAPPING ExpCallbackMapping

Initial value:

     {
        STANDARD_RIGHTS_READ ,
        STANDARD_RIGHTS_WRITE | CALLBACK_MODIFY_STATE,
        STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
        CALLBACK_ALL_ACCESS
    }

Definition at line 56 of file ex/callback.c.

Referenced by ExpInitializeCallbacks().