VDS(虚拟磁盘服务)COM接口通知 - 仅在取消注册期间调用回调(接收器)(Unadvise)

时间:2013-11-25 17:23:59

标签: c++ windows winapi com

我想在Windows中使用VDS COM接口获取有关磁盘添加/删除(PnP)的通知(需要支持Windows 7,因此我无法使用新的“Windows Storage Management API”)。

这是我的回调课程:

class SimpleNotifySink: public IVdsAdviseSink {
public:
    SimpleNotifySink() : ref(1) {}
    HRESULT OnNotify(
            LONG lNumberOfNotifications,
            VDS_NOTIFICATION *pNotificationArray
          )
    {
        printf("Got %d notifications:\n", lNumberOfNotifications);
        return S_OK;
    }
    ULONG AddRef() {
        InterlockedIncrement(&ref);
        return ref;
    }
    ULONG Release() {
        ULONG ulRefCount = InterlockedDecrement(&ref);
            if (0 == ref)
            {
                delete this;
            }
            return ulRefCount;
    }
    HRESULT QueryInterface(REFIID riid, void **ppvObj) {
        // Always set out parameter to NULL, validating it first.
            if (!ppvObj)
                return E_INVALIDARG;
            *ppvObj = NULL;
            if ((riid == IID_IUnknown) || (riid == IID_IVdsAdviseSink)) {
                // Increment the reference count and return the pointer.
                *ppvObj = (LPVOID)this;
                AddRef();
                return S_OK;
            }
            return E_NOINTERFACE;
    }
private:
    LONG ref;
};

这是回调注册(摘录):

IVdsAdviseSink *sink = new SimpleNotifySink();
DWORD cookie = 0;

hr = pService->Advise(sink, &cookie);

if (FAILED(hr)) {
    printf("sink registration (pService->Advise) failed with %X.\n", hr);
}

printf("press any key...\n");
getchar();

if (cookie != 0) {
    hr = pService->Unadvise(cookie);
}

要测试代码,在“按任意键...”期间,我禁用并启用虚拟磁盘(在VM中) - 但只有在pService->时才调用我的回调(我使用了windbg)。 Unadvise(...)被称为。

任何想法为什么?

由于

1 个答案:

答案 0 :(得分:1)

getchar不会传递消息,因此无法分派任何COM事件。用消息泵循环替换printf / getchar;像这样的东西:

HRESULT WaitAndPumpMessagesUntilKeyDown(DWORD dwMs)
{
    HRESULT hr = S_OK;
    BOOL fContinue = TRUE;
    HANDLE hTimer = NULL;
    LARGE_INTEGER liDueTime;

    liDueTime.QuadPart = -100000LL * dwMs;

    // Create an unnamed waitable timer.
    hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
    if (NULL == hTimer)
    {
        return HRESULT_FROM_WIN32(GetLastError());
    }

    // Set a timer to wait for 10 seconds.
    if (!SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0))
    {
        return HRESULT_FROM_WIN32(GetLastError());
    }
    while (fContinue)
    {
        DWORD dwWaitId = ::MsgWaitForMultipleObjectsEx(1, &hTimer, dwMs, QS_ALLINPUT, MWMO_INPUTAVAILABLE);
        switch (dwWaitId)
        {
        case WAIT_OBJECT_0:
            {
                fContinue = FALSE;
            }
            break;

        case WAIT_OBJECT_0 + 1:
            {
                MSG Msg;
                while (::PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
                {
                    ::TranslateMessage(&Msg);
                    if (Msg.message == WM_KEYDOWN)
                    {
                        fContinue = FALSE;
                        hr = S_OK;
                    }
                    else
                    {
                        ::DispatchMessage(&Msg);
                    }
                }
            }
            break;

        case WAIT_TIMEOUT:
            {
                hr = S_FALSE;
                fContinue = FALSE;
            }
            break;

        default:// Unexpected error
            {
                fContinue = FALSE;
                hr = E_FAIL;
            }
            break;
        }
    }
    return hr;
}
相关问题