Поделиться через


функция CM_Unregister_Notification (cfgmgr32.h)

Используйте UnregisterDeviceNotification вместо CM_Unregister_Notification , если ваш код предназначен для Windows 7 или более ранних версий Windows.

Функция CM_Unregister_Notification закрывает указанный дескриптор HCMNOTIFICATION.

Синтаксис

CMAPI CONFIGRET CM_Unregister_Notification(
  [in] HCMNOTIFICATION NotifyContext
);

Параметры

[in] NotifyContext

Дескриптор HCMNOTIFICATION, возвращаемый функцией CM_Register_Notification .

Возвращаемое значение

Если операция выполнена успешно, функция возвращает CR_SUCCESS. В противном случае возвращается один из кодов ошибок с префиксом CR_, определенных в Cfgmgr32.h.

Комментарии

Не вызывайте CM_Unregister_Notification из обратного вызова уведомления. Это может привести к взаимоблокировке , так как CM_Unregister_Notification ожидает завершения ожидающих обратных вызовов.

Вместо этого, если вы хотите отменить регистрацию в обратном вызове уведомления, это необходимо сделать асинхронно. В следующей последовательности показан один из способов сделать это:

  1. Выделите структуру контекста для использования с уведомлениями. Включите указатель на рабочую структуру пула потоков (PTP_WORK) и любые другие сведения, которые вы хотите передать обратному вызову уведомления.
  2. Вызовите CreateThreadpoolWork. Укажите функцию обратного вызова, которая вызывает CM_Unregister_Notification. Добавьте возвращенную рабочую структуру в ранее выделенную структуру контекста.
  3. Вызовите CM_Register_Notification и укажите структуру контекста в качестве параметра pContext .
  4. Работайте, получайте уведомления и т. д.
  5. Вызовите Метод SubmitThreadpoolWork из обратного вызова уведомления, предоставляя указатель на рабочую структуру пула потоков (PTP_WORK), хранящуюся в структуре контекста.
  6. При запуске потока threadpool рабочий элемент вызывает CM_Unregister_Notification.
  7. Вызовите CloseThreadpoolWork , чтобы освободить рабочий объект.
Если вы завершили работу со структурой контекста, не забудьте освободить ресурсы и освободить структуру.
Осторожностью Не освобождайте структуру контекста до тех пор, пока рабочий элемент не вызовет CM_Unregister_Notification. Вы по-прежнему можете получать уведомления после отправки рабочего элемента threadpool и до вызова рабочего элемента CM_Unregister_Notification.
 

Примеры

В следующем примере показано, как отменить регистрацию в обратном вызове уведомления, как описано в разделе Примечания.

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

Требования

Требование Значение
Минимальная версия клиента Доступно в Microsoft Windows 8 и более поздних версиях Windows.
Целевая платформа Универсальное
Верхняя часть cfgmgr32.h (включая Cfgmgr32.h)
Библиотека Cfgmgr32.lib; OneCoreUAP.lib в Windows 10
DLL CfgMgr32.dll

См. также раздел

UnregisterDeviceNotification