CM_Unregister_Notification 函数 (cfgmgr32.h)

如果你的代码面向 Windows 7 或早期版本的 Windows,请使用 UnregisterDeviceNotification 而不是 CM_Unregister_Notification

CM_Unregister_Notification 函数关闭指定的 HCMNOTIFICATION 句柄。

语法

CMAPI CONFIGRET CM_Unregister_Notification(
  [in] HCMNOTIFICATION NotifyContext
);

参数

[in] NotifyContext

CM_Register_Notification 函数返回的 HCMNOTIFICATION 句柄。

返回值

如果操作成功,函数将返回CR_SUCCESS。 否则,它将返回 Cfgmgr32.h 中定义的CR_前缀错误代码之一。

注解

不要从通知回调调用 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. 线程池线程运行时,工作项调用 CM_Unregister_Notification
  7. 调用 CloseThreadpoolWork 释放工作对象。
如果已完成上下文结构,请不要忘记释放资源并释放结构。
谨慎 在工作 项调用CM_Unregister_Notification之前,不要释放上下文结构。 在提交线程池工作项后和工作项调用 之前,仍可以接收通知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)
Library Cfgmgr32.lib;Windows 10 上的 OneCoreUAP.lib
DLL CfgMgr32.dll

另请参阅

UnregisterDeviceNotification