Share via


CM_Unregister_Notification-Funktion (cfgmgr32.h)

Verwenden Sie UnregisterDeviceNotification anstelle von CM_Unregister_Notification , wenn Ihr Code auf Windows 7 oder frühere Versionen von Windows abzielt.

Die CM_Unregister_Notification-Funktion schließt das angegebene HCMNOTIFICATION-Handle.

Syntax

CMAPI CONFIGRET CM_Unregister_Notification(
  [in] HCMNOTIFICATION NotifyContext
);

Parameter

[in] NotifyContext

Das HCMNOTIFICATION-Handle, das von der CM_Register_Notification-Funktion zurückgegeben wird.

Rückgabewert

Wenn der Vorgang erfolgreich ist, gibt die Funktion CR_SUCCESS zurück. Andernfalls wird einer der CR_-Präfix-Fehlercodes zurückgegeben, die in Cfgmgr32.h definiert sind.

Hinweise

Rufen Sie CM_Unregister_Notification nicht über einen Benachrichtigungsrückruf auf. Dies kann zu einem Deadlock führen, da CM_Unregister_Notification wartet, bis ausstehende Rückrufe abgeschlossen sind.

Wenn Sie stattdessen die Registrierung vom Benachrichtigungsrückruf aufheben möchten, müssen Sie dies asynchron tun. Die folgende Sequenz zeigt eine Möglichkeit, dies zu tun:

  1. Ordnen Sie eine Kontextstruktur zu, die mit Ihren Benachrichtigungen verwendet werden soll. Fügen Sie einen Zeiger auf eine Threadpool-Arbeitsstruktur (PTP_WORK) und alle anderen Informationen ein, die Sie an den Benachrichtigungsrückruf übergeben möchten.
  2. Rufen Sie CreateThreadpoolWork auf. Stellen Sie eine Rückruffunktion bereit, die CM_Unregister_Notification aufruft. Fügen Sie die zurückgegebene Arbeitsstruktur der zuvor zugewiesenen Kontextstruktur hinzu.
  3. Rufen Sie CM_Register_Notification auf, und geben Sie die Kontextstruktur als pContext-Parameter an.
  4. Arbeiten Sie, erhalten Sie Benachrichtigungen usw.
  5. Rufen Sie SubmitThreadpoolWork innerhalb des Benachrichtigungsrückrufs auf, und geben Sie den Zeiger auf eine threadpool-Arbeitsstruktur (PTP_WORK) an, die in Ihrer Kontextstruktur gespeichert ist.
  6. Wenn der Threadpoolthread ausgeführt wird, ruft das Arbeitselement CM_Unregister_Notification auf.
  7. Rufen Sie CloseThreadpoolWork auf, um das Arbeitsobjekt freizugeben.
Wenn Sie mit der Kontextstruktur fertig sind, vergessen Sie nicht, Ressourcen freizugeben und die Struktur freizugeben.
Vorsicht Geben Sie die Kontextstruktur erst frei, nachdem das Arbeitselement CM_Unregister_Notification aufgerufen hat. Sie können weiterhin Benachrichtigungen erhalten, nachdem Sie das Arbeitselement des Threadpools übermittelt haben und bevor das Arbeitselement CM_Unregister_Notification aufruft.
 

Beispiele

Das folgende Beispiel zeigt, wie Sie die Registrierung vom Benachrichtigungsrückruf aufheben, wie im Abschnitt Hinweise beschrieben.

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

Anforderungen

Anforderung Wert
Unterstützte Mindestversion (Client) Verfügbar in Microsoft Windows 8 und höheren Versionen von Windows.
Zielplattform Universell
Header cfgmgr32.h (einschließlich Cfgmgr32.h)
Bibliothek Cfgmgr32.lib; OneCoreUAP.lib auf Windows 10
DLL CfgMgr32.dll

Weitere Informationen

Aufheben der RegistrierungDeviceNotification