Partager via


fonction CM_Unregister_Notification (cfgmgr32.h)

Utilisez UnregisterDeviceNotification au lieu de CM_Unregister_Notification si votre code cible Windows 7 ou les versions antérieures de Windows.

La fonction CM_Unregister_Notification ferme le handle HCMNOTIFICATION spécifié.

Syntaxe

CMAPI CONFIGRET CM_Unregister_Notification(
  [in] HCMNOTIFICATION NotifyContext
);

Paramètres

[in] NotifyContext

Handle HCMNOTIFICATION retourné par la fonction CM_Register_Notification .

Valeur retournée

Si l’opération réussit, la fonction retourne CR_SUCCESS. Sinon, il retourne l’un des codes d’erreur CR_ préfixés définis dans Cfgmgr32.h.

Remarques

N’appelez pas CM_Unregister_Notification à partir d’un rappel de notification. Cela peut entraîner un blocage, car CM_Unregister_Notification attend la fin des rappels en attente.

Au lieu de cela, si vous souhaitez annuler l’inscription à partir du rappel de notification, vous devez le faire de manière asynchrone. La séquence suivante montre une façon de procéder :

  1. Allouez une structure de contexte à utiliser avec vos notifications. Incluez un pointeur vers une structure de travail de threadpool (PTP_WORK) et toutes les autres informations que vous souhaitez transmettre au rappel de notification.
  2. Appelez CreateThreadpoolWork. Fournissez une fonction de rappel qui appelle CM_Unregister_Notification. Ajoutez la structure de travail retournée à la structure de contexte précédemment allouée.
  3. Appelez CM_Register_Notification et fournissez la structure de contexte comme paramètre pContext .
  4. Travaillez, recevez des notifications, etc.
  5. Appelez SubmitThreadpoolWork à partir du rappel de notification, en fournissant le pointeur vers une structure de travail threadpool (PTP_WORK) stockée dans votre structure de contexte.
  6. Lorsque le thread threadpool s’exécute, l’élément de travail appelle CM_Unregister_Notification.
  7. Appelez CloseThreadpoolWork pour libérer l’objet de travail.
Si vous avez terminé avec la structure de contexte, n’oubliez pas de libérer des ressources et de libérer la structure.
Attention Ne libérez pas la structure de contexte tant que l’élément de travail n’a pas appelé CM_Unregister_Notification. Vous pouvez toujours recevoir des notifications après avoir envoyé l’élément de travail du threadpool et avant que l’élément de travail n’appelle CM_Unregister_Notification.
 

Exemples

L’exemple suivant montre comment annuler l’inscription à partir du rappel de notification, comme décrit dans la section Remarques.

typedef struct _CALLBACK_CONTEXT {
    BOOL bUnregister;
    PTP_WORK pWork;
    HCMNOTIFICATION hNotify;
    CRITICAL_SECTION lock;
} CALLBACK_CONTEXT, *PCALLBACK_CONTEXT;

DWORD
WINAPI
EventCallback(
    __in HCMNOTIFICATION hNotification,
    __in PVOID Context,
    __in CM_NOTIFY_ACTION Action,
    __in PCM_NOTIFY_EVENT_DATA EventData,
    __in DWORD EventDataSize
    )
{
    PCALLBACK_CONTEXT pCallbackContext = (PCALLBACK_CONTEXT)Context;

   // unregister from the callback
    EnterCriticalSection(&(pCallbackContext->lock));

    // in case this callback fires before the registration call returns, make sure the notification handle is properly set
    Context->hNotify = hNotification;

    if (!pCallbackContext->bUnregister) {
        pCallbackContext->bUnregister = TRUE;
        SubmitThreadpoolWork(pCallbackContext->pWork);
    }

    LeaveCriticalSection(&(pCallbackContext->lock));

    return ERROR_SUCCESS;
};

VOID
CALLBACK
WorkCallback(
    _Inout_ PTP_CALLBACK_INSTANCE Instance,
    _Inout_opt_ PVOID Context,
    _Inout_ PTP_WORK pWork
    )
{
    PCALLBACK_CONTEXT pCallbackContext = (PCALLBACK_CONTEXT)Context;

    CM_Unregister_Notification(pCallbackContext->hNotify);
}

VOID NotificationFunction()
{
    CONFIGRET cr = CR_SUCCESS;
    HRESULT hr = S_OK;
    CM_NOTIFY_FILTER NotifyFilter = { 0 };
    BOOL bShouldUnregister = FALSE;
    PCALLBACK_CONTEXT context;

    context = (PCALLBACK_CONTEXT)HeapAlloc(GetProcessHeap(),
                                           HEAP_ZERO_MEMORY,
                                           sizeof(CALLBACK_CONTEXT));
    if (context == NULL) {
        goto end;
    }

    InitializeCriticalSection(&(context->lock));

    NotifyFilter.cbSize = sizeof(NotifyFilter);
    NotifyFilter.Flags = 0;
    NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINSTANCE;
    NotifyFilter.Reserved = 0;

    hr = StringCchCopy(NotifyFilter.u.DeviceInstance.InstanceId,
                       MAX_DEVICE_ID_LEN,
                       TEST_DEVICE_INSTANCE_ID);
    if (FAILED(hr)) {
        goto end;
    }

    context->pWork = CreateThreadpoolWork(WorkCallback, context, NULL);
    if (context->pWork == NULL) {
        goto end;
    }

    cr = CM_Register_Notification(&NotifyFilter,
                                  context,
                                  EventCallback,
                                  &context->hNotify);
   if (cr != CR_SUCCESS) {
        goto end;
    }

    // ... do work here ...

    EnterCriticalSection(&(context->lock));

    if (!context->bUnregister) {
        // unregister not from the callback
        bShouldUnregister = TRUE;
        context->bUnregister = TRUE;
    }

    LeaveCriticalSection(&(context->lock));

    if (bShouldUnregister) {
        cr = CM_Unregister_Notification(context->hNotify);
        if (cr != CR_SUCCESS) {
            goto end;
        }
    } else {
        // if the callback is the one performing the unregister, wait for the threadpool work item to complete the unregister
        WaitForThreadpoolWorkCallbacks(context->pWork, FALSE);
    }

end:

    if (context != NULL) {
        if (context->pWork != NULL) {
            CloseThreadpoolWork(context->pWork);
        }

        DeleteCriticalSection(&(context->lock));

        HeapFree(GetProcessHeap(), 0, context);
    }

    return;
}

Configuration requise

Condition requise Valeur
Client minimal pris en charge Disponible dans Microsoft Windows 8 et versions ultérieures de Windows.
Plateforme cible Universal
En-tête cfgmgr32.h (inclure Cfgmgr32.h)
Bibliothèque Cfgmgr32.lib ; OneCoreUAP.lib sur Windows 10
DLL CfgMgr32.dll

Voir aussi

UnregisterDeviceNotification