views:

112

answers:

1

Hi,

I am implementing IQueryCancelAutoPlay COM interface and registering it with the Running Objects Table from a Windows Service*.

My problem is that it never gets called when I insert a mass storage device (or any device really). Here's some more information:

My code for registering with the ROT:

Text::string clsIdString = Text::to_string(Com::CLSID_QCAListener);
// remove curly braces
clsIdString = clsIdString.substr(1, clsIdString.length() - 2);

// set registry key to make sure we get notifications from windows
Reg::SetValue(HKEY_LOCAL_MACHINE, 
_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoplayHandlers\\CancelAutoplay\\CLSID"),
clsIdString, _T(""));

HRESULT result = S_OK;

// create class moniker ...
CComPtr<IMoniker> moniker;
result = CreateClassMoniker(Com::CLSID_QCAListener, &moniker);
if( !ValidateResult(result, "Error creating class moniker") )
return;

DBG << _T("Getting IRunningObjectTable pointer ...") << std::endl;

// get running oject table ... 
CComPtr<IRunningObjectTable> runningObjectTable;
result = GetRunningObjectTable(0, &runningObjectTable);
if( !ValidateResult(result, "Error getting running object table") )
return;

// create an instance of the QCAListener class ...
Com::QCAListener * listenerInstance = new Com::QCAListener();
if(!ValidateResult( listenerInstance != 0,
"Error creating QueryCancelAutoplayListener"))
return;
// ... and set the pointer in the _qcaListener variable
CComPtr<IQueryCancelAutoPlay> qcaListener;
listenerInstance->QueryInterface(IID_IQueryCancelAutoPlay, reinterpret_cast<void**>(&qcaListener));

DBG << _T("Registering IQueryCancelAutoPlay with ROT ...") << std::endl;
result = runningObjectTable->Register(
ROTFLAGS_REGISTRATIONKEEPSALIVE,
listenerInstance,
moniker,
&_qcaRegistration);
ValidateResult(result, "Error registering QueryCancelAutoplayListener with the ROT");

runningObjectTable->Register returns S_OK, and at the end of the code block's execution the ref-count for listenerInstance is 1 (if I remove the call to runningObjectTable->Register completely, the ref-count remains 0 when qcaListener goes out of scope so this means an instance of my class remains active in the ROT).

More details: In development, my service runs with my account credentials (local administrator). Although this will probably change, it should work as it is with the current configuration.

Can anyone shed any light on this?


*- I know the documentation says I shouldn't implement IQueryCancelAutoPlay in a service but I need to do this for various reasons (business requirement, etc).

A: 

I figured it out (for those who stumble upon this answer when having a similar problem):

The service runs under a different window station and a different desktop. When the IQueryCalcelAutoPlay implementation is registered in the ROT this is done for a different desktop.

The current user's desktop shell (explorer) will not find this registration when a new USB device is inserted (as it is not registered with the current desktop).

utnapistim