次の方法で共有


CM_Unregister_Notification関数 (cfgmgr32.h)

コードが Windows 7 以前のバージョンの Windows を対象とする場合は、CM_Unregister_Notificationの代わりに UnregisterDeviceNotification を使用します。

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 つの方法を示しています。

  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 で使用できます。
対象プラットフォーム ユニバーサル
Header cfgmgr32.h (Cfgmgr32.h を含む)
Library Cfgmgr32.lib;Windows 10の OneCoreUAP.lib
[DLL] CfgMgr32.dll

こちらもご覧ください

UnregisterDeviceNotification