Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

377 lines
11 KiB

  1. #include "dtct.h"
  2. #include "svcsync.h"
  3. #include "cmmn.h"
  4. #include "misc.h"
  5. #include "str.h"
  6. #include "mischlpr.h"
  7. #include "dbg.h"
  8. #include "tfids.h"
  9. #include "regnotif.h"
  10. #include <ioevent.h>
  11. #define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
  12. ///////////////////////////////////////////////////////////////////////////////
  13. //
  14. // {5390E909-5BDF-4218-BB1F-9A41B3143214}
  15. extern const CLSID CLSID_HWEventDetector =
  16. {0x5390e909, 0x5bdf, 0x4218,
  17. {0xbb, 0x1f, 0x9a, 0x41, 0xb3, 0x14, 0x32, 0x14}};
  18. ///////////////////////////////////////////////////////////////////////////////
  19. //
  20. STDMETHODIMP CHWEventDetectorImpl::InitMinimum(DWORD UNREF_PARAM(cArg),
  21. LPWSTR* UNREF_PARAM(ppszArgs), LPCWSTR pszEventRelinquishControl,
  22. DWORD* pdwCtrlAccept, BOOL* pfWantsDeviceEvents)
  23. {
  24. HRESULT hres;
  25. ASSERTVALIDSTATE();
  26. if (pszEventRelinquishControl && *pszEventRelinquishControl &&
  27. pdwCtrlAccept && pfWantsDeviceEvents)
  28. {
  29. _hEventRelinquishControl = OpenEvent(SYNCHRONIZE, FALSE,
  30. pszEventRelinquishControl);
  31. if (_hEventRelinquishControl)
  32. {
  33. hres = _RegisterFactories();
  34. if (SUCCEEDED(hres))
  35. {
  36. *pdwCtrlAccept = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN |
  37. SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SESSIONCHANGE;
  38. *pfWantsDeviceEvents = TRUE;
  39. }
  40. }
  41. else
  42. {
  43. hres = E_FAIL;
  44. }
  45. }
  46. else
  47. {
  48. hres = E_INVALIDARG;
  49. }
  50. ASSERTVALIDSTATE();
  51. return hres;
  52. }
  53. STDMETHODIMP CHWEventDetectorImpl::InitDeviceEventHandler(
  54. SERVICE_STATUS_HANDLE ssh)
  55. {
  56. HRESULT hres = E_INVALIDARG;
  57. TRACE(TF_SHHWDTCTSVC, TEXT("Entered CHWEventDetectorImpl::InitDeviceEventHandler"));
  58. ASSERTVALIDSTATE();
  59. if (ssh)
  60. {
  61. hres = CHWEventDetectorHelper::SetServiceStatusHandle(ssh);
  62. }
  63. ASSERTVALIDSTATE();
  64. return hres;
  65. }
  66. STDMETHODIMP CHWEventDetectorImpl::InitFinal()
  67. {
  68. HRESULT hres;
  69. HANDLE hProcess = GetCurrentProcess();
  70. TRACE(TF_SHHWDTCTSVC, TEXT("Entered CHWEventDetectorImpl::InitFinal"));
  71. ASSERTVALIDSTATE();
  72. ASSERT(!g_hShellHWDetectionThread);
  73. if (DuplicateHandle(hProcess, GetCurrentThread(), hProcess,
  74. &g_hShellHWDetectionThread, 0, FALSE, DUPLICATE_SAME_ACCESS))
  75. {
  76. TRACE(TF_SVCSYNC,
  77. TEXT("About to set ShellHWDetection thread priority to LOWEST from itself"));
  78. if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST))
  79. {
  80. hres = CHWEventDetectorHelper::InitDockState();
  81. CHWEventDetectorHelper::Init();
  82. if (SUCCEEDED(hres))
  83. {
  84. hres = _RegisterForNotif();
  85. TRACE(TF_SVCSYNC,
  86. TEXT("Completed registration, about to set ShellHWDetection thread priority to NORMAL from itself"));
  87. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
  88. _hEventInitCompleted = CreateEvent(NULL, TRUE, FALSE,
  89. g_szShellHWDetectionInitCompleted);
  90. if (_hEventInitCompleted)
  91. {
  92. TRACE(TF_SVCSYNC,
  93. TEXT("Completed intialization, setting event"));
  94. hres = S_OK;
  95. SetEvent(_hEventInitCompleted);
  96. }
  97. }
  98. }
  99. else
  100. {
  101. hres = E_FAIL;
  102. }
  103. }
  104. else
  105. {
  106. hres = E_FAIL;
  107. }
  108. ASSERTVALIDSTATE();
  109. TRACE(TF_SHHWDTCTSVC, TEXT("Exited CHWEventDetectorImpl::InitFinal: 0x%08X"),
  110. hres);
  111. return hres;
  112. }
  113. ///////////////////////////////////////////////////////////////////////////////
  114. //
  115. // return S_FALSE and a non-zero dwWaitHint if pending
  116. STDMETHODIMP CHWEventDetectorImpl::HandleServiceControl(DWORD dwControlCode,
  117. DWORD* pdwWaitHint)
  118. {
  119. HRESULT hres;
  120. ASSERTVALIDSTATE();
  121. *pdwWaitHint = 0;
  122. switch (dwControlCode)
  123. {
  124. case SERVICE_CONTROL_PAUSE:
  125. hres = _UnregisterForNotif();
  126. hres = _SuspendFactories();
  127. break;
  128. case SERVICE_CONTROL_STOP:
  129. case SERVICE_CONTROL_SHUTDOWN:
  130. {
  131. // In case _CompleteShellHWDetectionInitialization was never called
  132. HANDLE hTmp = InterlockedCompareExchangePointer(
  133. &g_hShellHWDetectionThread, NULL,
  134. g_hShellHWDetectionThread);
  135. if (hTmp)
  136. {
  137. CloseHandle(hTmp);
  138. }
  139. if (_hEventInitCompleted)
  140. {
  141. CloseHandle(_hEventInitCompleted);
  142. _hEventInitCompleted = NULL;
  143. }
  144. hres = _UnregisterForNotif();
  145. hres = CHWEventDetectorHelper::DeleteLists();
  146. hres = _UnregisterFactories();
  147. CHWEventDetectorHelper::Cleanup();
  148. break;
  149. }
  150. case SERVICE_CONTROL_CONTINUE:
  151. hres = _RegisterForNotif();
  152. hres = _ResumeFactories();
  153. break;
  154. default:
  155. // do not return S_FALSE here
  156. hres = S_OK;
  157. break;
  158. }
  159. ASSERTVALIDSTATE();
  160. return hres;
  161. }
  162. STDMETHODIMP CHWEventDetectorImpl::HandleDeviceEvent(DWORD dwEventType,
  163. LPVOID pEventData)
  164. {
  165. HRESULT hres = S_FALSE;
  166. ASSERTVALIDSTATE();
  167. CHWEventDetectorHelper::CheckDiagnosticAppPresence();
  168. if (pEventData)
  169. {
  170. DEV_BROADCAST_HDR* dbhdr = (DEV_BROADCAST_HDR*)pEventData;
  171. if (DBT_DEVTYP_DEVICEINTERFACE == dbhdr->dbch_devicetype)
  172. {
  173. DEV_BROADCAST_DEVICEINTERFACE* pdbdi =
  174. (DEV_BROADCAST_DEVICEINTERFACE*)pEventData;
  175. WCHAR szGUID[MAX_GUIDSTRING];
  176. LPWSTR pszEventType = TEXT("Unknown");
  177. if (SUCCEEDED(_StringFromGUID(&(pdbdi->dbcc_classguid), szGUID,
  178. ARRAYSIZE(szGUID))))
  179. {
  180. switch (dwEventType)
  181. {
  182. case DBT_DEVICEARRIVAL:
  183. pszEventType = TEXT("DBT_DEVTYP_DEVICEINTERFACE + DBT_DEVICEARRIVAL");
  184. DIAGNOSTIC((TEXT("[0000]Processing Interface Arrival Event: %s, %s"), pszEventType, szGUID));
  185. break;
  186. case DBT_DEVICEREMOVECOMPLETE:
  187. pszEventType = TEXT("DBT_DEVTYP_DEVICEINTERFACE + DBT_DEVICEREMOVECOMPLETE");
  188. DIAGNOSTIC((TEXT("[0001]Processing Interface Removal Event: %s, %s"), pszEventType, szGUID));
  189. break;
  190. #ifdef DEBUG
  191. case DBT_DEVICEQUERYREMOVEFAILED: pszEventType = TEXT("DBT_DEVTYP_DEVICEINTERFACE + DBT_DEVICEQUERYREMOVEFAILED"); break;
  192. case DBT_DEVICEREMOVEPENDING: pszEventType = TEXT("DBT_DEVTYP_DEVICEINTERFACE + DBT_DEVICEREMOVEPENDING"); break;
  193. case DBT_DEVICEQUERYREMOVE: pszEventType = TEXT("DBT_DEVTYP_DEVICEINTERFACE + DBT_DEVICEQUERYREMOVE"); break;
  194. #endif
  195. }
  196. TRACE(TF_SHHWDTCTDTCT, TEXT("Processing Interface Event: %s, %s"),
  197. pszEventType, szGUID);
  198. }
  199. hres = _HandleInterfaceEvent(pdbdi, dwEventType);
  200. }
  201. else
  202. {
  203. if (DBT_DEVTYP_HANDLE == dbhdr->dbch_devicetype)
  204. {
  205. DEV_BROADCAST_HANDLE* pdbh = (DEV_BROADCAST_HANDLE*)pEventData;
  206. #ifdef DEBUG
  207. LPWSTR pszEventType = TEXT("Unknown");
  208. WCHAR szGUID[MAX_GUIDSTRING];
  209. if (DBT_CUSTOMEVENT == dwEventType)
  210. {
  211. HRESULT hrTmp = S_FALSE;
  212. if (GUID_IO_MEDIA_ARRIVAL == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_MEDIA_ARRIVAL");
  213. else if (GUID_IO_MEDIA_REMOVAL == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_MEDIA_REMOVAL");
  214. else if (GUID_IO_VOLUME_LOCK == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_VOLUME_LOCK");
  215. else if (GUID_IO_VOLUME_LOCK_FAILED == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_VOLUME_LOCK_FAILED");
  216. else if (GUID_IO_VOLUME_UNLOCK == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_VOLUME_UNLOCK");
  217. else if (GUID_IO_VOLUME_NAME_CHANGE == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_VOLUME_NAME_CHANGE");
  218. else if (GUID_IO_VOLUME_CHANGE == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_VOLUME_CHANGE");
  219. else
  220. {
  221. hrTmp = _StringFromGUID(&(pdbh->dbch_eventguid), szGUID, ARRAYSIZE(szGUID));
  222. pszEventType = szGUID;
  223. }
  224. if (SUCCEEDED(hrTmp))
  225. {
  226. TRACE(TF_SHHWDTCTDTCT,
  227. TEXT("Processing Broadcast Event: %s, hdevnotify = 0x%08X"),
  228. pszEventType, pdbh->dbch_hdevnotify);
  229. }
  230. }
  231. else
  232. {
  233. pszEventType = TEXT("unknown");
  234. switch (dwEventType)
  235. {
  236. case DBT_DEVICEARRIVAL: pszEventType = TEXT("DBT_DEVTYP_HANDLE + DBT_DEVICEARRIVAL"); break;
  237. case DBT_DEVICEQUERYREMOVE: pszEventType = TEXT("DBT_DEVTYP_HANDLE + DBT_DEVICEQUERYREMOVE"); break;
  238. case DBT_DEVICEQUERYREMOVEFAILED: pszEventType = TEXT("DBT_DEVTYP_HANDLE + DBT_DEVICEQUERYREMOVEFAILED"); break;
  239. case DBT_DEVICEREMOVEPENDING: pszEventType = TEXT("DBT_DEVTYP_HANDLE + DBT_DEVICEREMOVEPENDING"); break;
  240. case DBT_DEVICEREMOVECOMPLETE: pszEventType = TEXT("DBT_DEVTYP_HANDLE + DBT_DEVICEREMOVECOMPLETE"); break;
  241. }
  242. TRACE(TF_SHHWDTCTDTCT, TEXT("Processing Unknown Broadcast Event: %s, dwEventType = 0x%08X"), pszEventType, dwEventType);
  243. }
  244. #endif
  245. hres = _HandleBroadcastHandleEvent(pdbh, dwEventType);
  246. }
  247. else
  248. {
  249. }
  250. }
  251. }
  252. ASSERTVALIDSTATE();
  253. return hres;
  254. }
  255. STDMETHODIMP CHWEventDetectorImpl::Run()
  256. {
  257. ASSERTVALIDSTATE();
  258. // Nothing to do for now.
  259. return S_OK;
  260. }
  261. STDMETHODIMP CHWEventDetectorImpl::HandlePowerEvent(
  262. DWORD UNREF_PARAM(dwEventType), LPVOID UNREF_PARAM(pEventData))
  263. {
  264. HRESULT hres = E_UNEXPECTED;
  265. return hres;
  266. }
  267. STDMETHODIMP CHWEventDetectorImpl::HandleHWProfileEvent(
  268. DWORD UNREF_PARAM(dwEventType), LPVOID UNREF_PARAM(pEventData))
  269. {
  270. HRESULT hres = E_UNEXPECTED;
  271. return hres;
  272. }
  273. STDMETHODIMP CHWEventDetectorImpl::HandleSessionChange(
  274. DWORD dwEventType, LPVOID UNREF_PARAM(pvEventData))
  275. {
  276. HRESULT hres;
  277. switch (dwEventType)
  278. {
  279. case WTS_SESSION_LOGOFF:
  280. //
  281. // When this happens, we need to check our handles to see which
  282. // Explorer process went away and free its handle.
  283. //
  284. hres = CHardwareDevicesImpl::_AdviseCheckClients( );
  285. break;
  286. default:
  287. hres = S_OK;
  288. break;
  289. }
  290. return hres;
  291. }
  292. #ifdef DEBUG
  293. void CHWEventDetectorImpl::_DbgAssertValidState()
  294. {
  295. CHWEventDetectorHelper::_DbgAssertValidState();
  296. }
  297. #endif