|
|
#include "dtct.h"
#include "svcsync.h"
#include "cmmn.h"
#include "misc.h"
#include "str.h"
#include "mischlpr.h"
#include "dbg.h"
#include "tfids.h"
#include "regnotif.h"
#include <ioevent.h>
#define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
///////////////////////////////////////////////////////////////////////////////
//
// {5390E909-5BDF-4218-BB1F-9A41B3143214}
extern const CLSID CLSID_HWEventDetector = {0x5390e909, 0x5bdf, 0x4218, {0xbb, 0x1f, 0x9a, 0x41, 0xb3, 0x14, 0x32, 0x14}};
///////////////////////////////////////////////////////////////////////////////
//
STDMETHODIMP CHWEventDetectorImpl::InitMinimum(DWORD UNREF_PARAM(cArg), LPWSTR* UNREF_PARAM(ppszArgs), LPCWSTR pszEventRelinquishControl, DWORD* pdwCtrlAccept, BOOL* pfWantsDeviceEvents) { HRESULT hres;
ASSERTVALIDSTATE();
if (pszEventRelinquishControl && *pszEventRelinquishControl && pdwCtrlAccept && pfWantsDeviceEvents) { _hEventRelinquishControl = OpenEvent(SYNCHRONIZE, FALSE, pszEventRelinquishControl);
if (_hEventRelinquishControl) { hres = _RegisterFactories();
if (SUCCEEDED(hres)) { *pdwCtrlAccept = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SESSIONCHANGE;
*pfWantsDeviceEvents = TRUE; } } else { hres = E_FAIL; } } else { hres = E_INVALIDARG; }
ASSERTVALIDSTATE();
return hres; }
STDMETHODIMP CHWEventDetectorImpl::InitDeviceEventHandler( SERVICE_STATUS_HANDLE ssh) { HRESULT hres = E_INVALIDARG;
TRACE(TF_SHHWDTCTSVC, TEXT("Entered CHWEventDetectorImpl::InitDeviceEventHandler"));
ASSERTVALIDSTATE();
if (ssh) { hres = CHWEventDetectorHelper::SetServiceStatusHandle(ssh); }
ASSERTVALIDSTATE();
return hres; }
STDMETHODIMP CHWEventDetectorImpl::InitFinal() { HRESULT hres; HANDLE hProcess = GetCurrentProcess();
TRACE(TF_SHHWDTCTSVC, TEXT("Entered CHWEventDetectorImpl::InitFinal"));
ASSERTVALIDSTATE();
ASSERT(!g_hShellHWDetectionThread);
if (DuplicateHandle(hProcess, GetCurrentThread(), hProcess, &g_hShellHWDetectionThread, 0, FALSE, DUPLICATE_SAME_ACCESS)) { TRACE(TF_SVCSYNC, TEXT("About to set ShellHWDetection thread priority to LOWEST from itself"));
if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST)) { hres = CHWEventDetectorHelper::InitDockState();
CHWEventDetectorHelper::Init();
if (SUCCEEDED(hres)) { hres = _RegisterForNotif();
TRACE(TF_SVCSYNC, TEXT("Completed registration, about to set ShellHWDetection thread priority to NORMAL from itself"));
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
_hEventInitCompleted = CreateEvent(NULL, TRUE, FALSE, g_szShellHWDetectionInitCompleted);
if (_hEventInitCompleted) { TRACE(TF_SVCSYNC, TEXT("Completed intialization, setting event"));
hres = S_OK;
SetEvent(_hEventInitCompleted); } } } else { hres = E_FAIL; } } else { hres = E_FAIL; }
ASSERTVALIDSTATE();
TRACE(TF_SHHWDTCTSVC, TEXT("Exited CHWEventDetectorImpl::InitFinal: 0x%08X"), hres);
return hres; } ///////////////////////////////////////////////////////////////////////////////
//
// return S_FALSE and a non-zero dwWaitHint if pending
STDMETHODIMP CHWEventDetectorImpl::HandleServiceControl(DWORD dwControlCode, DWORD* pdwWaitHint) { HRESULT hres;
ASSERTVALIDSTATE();
*pdwWaitHint = 0;
switch (dwControlCode) { case SERVICE_CONTROL_PAUSE: hres = _UnregisterForNotif(); hres = _SuspendFactories(); break;
case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: { // In case _CompleteShellHWDetectionInitialization was never called
HANDLE hTmp = InterlockedCompareExchangePointer( &g_hShellHWDetectionThread, NULL, g_hShellHWDetectionThread);
if (hTmp) { CloseHandle(hTmp); }
if (_hEventInitCompleted) { CloseHandle(_hEventInitCompleted); _hEventInitCompleted = NULL; }
hres = _UnregisterForNotif(); hres = CHWEventDetectorHelper::DeleteLists(); hres = _UnregisterFactories();
CHWEventDetectorHelper::Cleanup();
break; }
case SERVICE_CONTROL_CONTINUE: hres = _RegisterForNotif(); hres = _ResumeFactories(); break;
default: // do not return S_FALSE here
hres = S_OK; break; }
ASSERTVALIDSTATE();
return hres; }
STDMETHODIMP CHWEventDetectorImpl::HandleDeviceEvent(DWORD dwEventType, LPVOID pEventData) { HRESULT hres = S_FALSE;
ASSERTVALIDSTATE();
CHWEventDetectorHelper::CheckDiagnosticAppPresence();
if (pEventData) { DEV_BROADCAST_HDR* dbhdr = (DEV_BROADCAST_HDR*)pEventData;
if (DBT_DEVTYP_DEVICEINTERFACE == dbhdr->dbch_devicetype) { DEV_BROADCAST_DEVICEINTERFACE* pdbdi = (DEV_BROADCAST_DEVICEINTERFACE*)pEventData;
WCHAR szGUID[MAX_GUIDSTRING]; LPWSTR pszEventType = TEXT("Unknown");
if (SUCCEEDED(_StringFromGUID(&(pdbdi->dbcc_classguid), szGUID, ARRAYSIZE(szGUID)))) { switch (dwEventType) { case DBT_DEVICEARRIVAL: pszEventType = TEXT("DBT_DEVTYP_DEVICEINTERFACE + DBT_DEVICEARRIVAL"); DIAGNOSTIC((TEXT("[0000]Processing Interface Arrival Event: %s, %s"), pszEventType, szGUID)); break;
case DBT_DEVICEREMOVECOMPLETE: pszEventType = TEXT("DBT_DEVTYP_DEVICEINTERFACE + DBT_DEVICEREMOVECOMPLETE"); DIAGNOSTIC((TEXT("[0001]Processing Interface Removal Event: %s, %s"), pszEventType, szGUID)); break; #ifdef DEBUG
case DBT_DEVICEQUERYREMOVEFAILED: pszEventType = TEXT("DBT_DEVTYP_DEVICEINTERFACE + DBT_DEVICEQUERYREMOVEFAILED"); break; case DBT_DEVICEREMOVEPENDING: pszEventType = TEXT("DBT_DEVTYP_DEVICEINTERFACE + DBT_DEVICEREMOVEPENDING"); break; case DBT_DEVICEQUERYREMOVE: pszEventType = TEXT("DBT_DEVTYP_DEVICEINTERFACE + DBT_DEVICEQUERYREMOVE"); break; #endif
}
TRACE(TF_SHHWDTCTDTCT, TEXT("Processing Interface Event: %s, %s"), pszEventType, szGUID); } hres = _HandleInterfaceEvent(pdbdi, dwEventType); } else { if (DBT_DEVTYP_HANDLE == dbhdr->dbch_devicetype) { DEV_BROADCAST_HANDLE* pdbh = (DEV_BROADCAST_HANDLE*)pEventData;
#ifdef DEBUG
LPWSTR pszEventType = TEXT("Unknown"); WCHAR szGUID[MAX_GUIDSTRING];
if (DBT_CUSTOMEVENT == dwEventType) { HRESULT hrTmp = S_FALSE;
if (GUID_IO_MEDIA_ARRIVAL == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_MEDIA_ARRIVAL"); else if (GUID_IO_MEDIA_REMOVAL == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_MEDIA_REMOVAL"); else if (GUID_IO_VOLUME_LOCK == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_VOLUME_LOCK"); else if (GUID_IO_VOLUME_LOCK_FAILED == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_VOLUME_LOCK_FAILED"); else if (GUID_IO_VOLUME_UNLOCK == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_VOLUME_UNLOCK"); else if (GUID_IO_VOLUME_NAME_CHANGE == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_VOLUME_NAME_CHANGE"); else if (GUID_IO_VOLUME_CHANGE == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_VOLUME_CHANGE"); else { hrTmp = _StringFromGUID(&(pdbh->dbch_eventguid), szGUID, ARRAYSIZE(szGUID)); pszEventType = szGUID; }
if (SUCCEEDED(hrTmp)) { TRACE(TF_SHHWDTCTDTCT, TEXT("Processing Broadcast Event: %s, hdevnotify = 0x%08X"), pszEventType, pdbh->dbch_hdevnotify); } } else { pszEventType = TEXT("unknown");
switch (dwEventType) { case DBT_DEVICEARRIVAL: pszEventType = TEXT("DBT_DEVTYP_HANDLE + DBT_DEVICEARRIVAL"); break; case DBT_DEVICEQUERYREMOVE: pszEventType = TEXT("DBT_DEVTYP_HANDLE + DBT_DEVICEQUERYREMOVE"); break; case DBT_DEVICEQUERYREMOVEFAILED: pszEventType = TEXT("DBT_DEVTYP_HANDLE + DBT_DEVICEQUERYREMOVEFAILED"); break; case DBT_DEVICEREMOVEPENDING: pszEventType = TEXT("DBT_DEVTYP_HANDLE + DBT_DEVICEREMOVEPENDING"); break; case DBT_DEVICEREMOVECOMPLETE: pszEventType = TEXT("DBT_DEVTYP_HANDLE + DBT_DEVICEREMOVECOMPLETE"); break; } TRACE(TF_SHHWDTCTDTCT, TEXT("Processing Unknown Broadcast Event: %s, dwEventType = 0x%08X"), pszEventType, dwEventType); } #endif
hres = _HandleBroadcastHandleEvent(pdbh, dwEventType); } else { } } }
ASSERTVALIDSTATE();
return hres; }
STDMETHODIMP CHWEventDetectorImpl::Run() { ASSERTVALIDSTATE();
// Nothing to do for now.
return S_OK; }
STDMETHODIMP CHWEventDetectorImpl::HandlePowerEvent( DWORD UNREF_PARAM(dwEventType), LPVOID UNREF_PARAM(pEventData)) { HRESULT hres = E_UNEXPECTED;
return hres; }
STDMETHODIMP CHWEventDetectorImpl::HandleHWProfileEvent( DWORD UNREF_PARAM(dwEventType), LPVOID UNREF_PARAM(pEventData)) { HRESULT hres = E_UNEXPECTED;
return hres; }
STDMETHODIMP CHWEventDetectorImpl::HandleSessionChange( DWORD dwEventType, LPVOID UNREF_PARAM(pvEventData)) { HRESULT hres;
switch (dwEventType) { case WTS_SESSION_LOGOFF: //
// When this happens, we need to check our handles to see which
// Explorer process went away and free its handle.
//
hres = CHardwareDevicesImpl::_AdviseCheckClients( ); break;
default: hres = S_OK; break; }
return hres; }
#ifdef DEBUG
void CHWEventDetectorImpl::_DbgAssertValidState() { CHWEventDetectorHelper::_DbgAssertValidState(); } #endif
|