我想在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(...)被称为。
任何想法为什么?
由于
答案 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;
}