Leaked source code of windows server 2003
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.

416 lines
13 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. _hEventInitCompleted = CreateEvent(NULL, TRUE, FALSE, NULL);
  34. if (_hEventInitCompleted)
  35. {
  36. if (DuplicateHandle(GetCurrentProcess(), _hEventInitCompleted,
  37. GetCurrentProcess(), &g_hEventInitCompleted, 0, FALSE,
  38. DUPLICATE_SAME_ACCESS))
  39. {
  40. hres = _RegisterFactories();
  41. if (SUCCEEDED(hres))
  42. {
  43. *pdwCtrlAccept = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN |
  44. SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SESSIONCHANGE;
  45. *pfWantsDeviceEvents = TRUE;
  46. }
  47. }
  48. else
  49. {
  50. CloseHandle(_hEventInitCompleted);
  51. _hEventInitCompleted = NULL;
  52. hres = E_FAIL;
  53. }
  54. }
  55. else
  56. {
  57. hres = E_FAIL;
  58. }
  59. }
  60. else
  61. {
  62. hres = E_FAIL;
  63. }
  64. }
  65. else
  66. {
  67. hres = E_INVALIDARG;
  68. }
  69. ASSERTVALIDSTATE();
  70. return hres;
  71. }
  72. STDMETHODIMP CHWEventDetectorImpl::InitDeviceEventHandler(
  73. SERVICE_STATUS_HANDLE ssh)
  74. {
  75. HRESULT hres = E_INVALIDARG;
  76. TRACE(TF_SHHWDTCTSVC, TEXT("Entered CHWEventDetectorImpl::InitDeviceEventHandler"));
  77. ASSERTVALIDSTATE();
  78. if (ssh)
  79. {
  80. hres = CHWEventDetectorHelper::SetServiceStatusHandle(ssh);
  81. }
  82. ASSERTVALIDSTATE();
  83. return hres;
  84. }
  85. STDMETHODIMP CHWEventDetectorImpl::InitFinal()
  86. {
  87. HRESULT hres;
  88. HANDLE hProcess = GetCurrentProcess();
  89. TRACE(TF_SHHWDTCTSVC, TEXT("Entered CHWEventDetectorImpl::InitFinal"));
  90. ASSERTVALIDSTATE();
  91. ASSERT(!g_hShellHWDetectionThread);
  92. if (DuplicateHandle(hProcess, GetCurrentThread(), hProcess,
  93. &g_hShellHWDetectionThread, 0, FALSE, DUPLICATE_SAME_ACCESS))
  94. {
  95. TRACE(TF_SVCSYNC,
  96. TEXT("About to set ShellHWDetection thread priority to LOWEST from itself"));
  97. if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST))
  98. {
  99. hres = CHWEventDetectorHelper::InitDockState();
  100. CHWEventDetectorHelper::Init();
  101. if (SUCCEEDED(hres))
  102. {
  103. hres = _RegisterForNotif();
  104. TRACE(TF_SVCSYNC,
  105. TEXT("Completed registration, about to set ShellHWDetection thread priority to NORMAL from itself"));
  106. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
  107. //
  108. // Load WIA's RPC library and initalize them
  109. //
  110. HMODULE hWiaRPC = LoadLibrary(TEXT("wiarpc.dll"));
  111. if(hWiaRPC) {
  112. HRESULT (WINAPI *WiaEventsInitialize)(void) = (HRESULT (WINAPI *)(void))
  113. GetProcAddress(hWiaRPC, "WiaEventsInitialize");
  114. if(WiaEventsInitialize) {
  115. WiaEventsInitialize();
  116. } else {
  117. TRACE(TF_SVCSYNC,
  118. TEXT("Failed to get WIARPC.DLL!WiaEventsInitialize entry point"));
  119. }
  120. } else {
  121. TRACE(TF_SVCSYNC,
  122. TEXT("Failed to load WIARPC.DLL"));
  123. }
  124. TRACE(TF_SVCSYNC,
  125. TEXT("Completed intialization, setting event"));
  126. SetEvent(_hEventInitCompleted);
  127. hres = S_OK;
  128. }
  129. }
  130. else
  131. {
  132. hres = E_FAIL;
  133. }
  134. }
  135. else
  136. {
  137. hres = E_FAIL;
  138. }
  139. ASSERTVALIDSTATE();
  140. TRACE(TF_SHHWDTCTSVC, TEXT("Exited CHWEventDetectorImpl::InitFinal: 0x%08X"),
  141. hres);
  142. return hres;
  143. }
  144. ///////////////////////////////////////////////////////////////////////////////
  145. //
  146. // return S_FALSE and a non-zero dwWaitHint if pending
  147. STDMETHODIMP CHWEventDetectorImpl::HandleServiceControl(DWORD dwControlCode,
  148. DWORD* pdwWaitHint)
  149. {
  150. HRESULT hres;
  151. ASSERTVALIDSTATE();
  152. *pdwWaitHint = 0;
  153. switch (dwControlCode)
  154. {
  155. case SERVICE_CONTROL_PAUSE:
  156. hres = _UnregisterForNotif();
  157. hres = _SuspendFactories();
  158. break;
  159. case SERVICE_CONTROL_STOP:
  160. case SERVICE_CONTROL_SHUTDOWN:
  161. {
  162. // In case _CompleteShellHWDetectionInitialization was never called
  163. HANDLE hTmp = InterlockedCompareExchangePointer(
  164. &g_hShellHWDetectionThread, NULL,
  165. g_hShellHWDetectionThread);
  166. if (hTmp)
  167. {
  168. CloseHandle(hTmp);
  169. }
  170. if (_hEventInitCompleted)
  171. {
  172. CloseHandle(_hEventInitCompleted);
  173. _hEventInitCompleted = NULL;
  174. }
  175. hres = _UnregisterForNotif();
  176. hres = CHWEventDetectorHelper::DeleteLists();
  177. hres = _UnregisterFactories();
  178. CHWEventDetectorHelper::Cleanup();
  179. if (_hEventRelinquishControl)
  180. {
  181. CloseHandle(_hEventRelinquishControl);
  182. }
  183. break;
  184. }
  185. case SERVICE_CONTROL_CONTINUE:
  186. hres = _RegisterForNotif();
  187. hres = _ResumeFactories();
  188. break;
  189. default:
  190. // do not return S_FALSE here
  191. hres = S_OK;
  192. break;
  193. }
  194. ASSERTVALIDSTATE();
  195. return hres;
  196. }
  197. STDMETHODIMP CHWEventDetectorImpl::HandleDeviceEvent(DWORD dwEventType,
  198. LPVOID pEventData)
  199. {
  200. HRESULT hres = S_FALSE;
  201. ASSERTVALIDSTATE();
  202. CHWEventDetectorHelper::CheckDiagnosticAppPresence();
  203. if (pEventData)
  204. {
  205. DEV_BROADCAST_HDR* dbhdr = (DEV_BROADCAST_HDR*)pEventData;
  206. if (DBT_DEVTYP_DEVICEINTERFACE == dbhdr->dbch_devicetype)
  207. {
  208. DEV_BROADCAST_DEVICEINTERFACE* pdbdi =
  209. (DEV_BROADCAST_DEVICEINTERFACE*)pEventData;
  210. WCHAR szGUID[MAX_GUIDSTRING];
  211. LPWSTR pszEventType = TEXT("Unknown");
  212. if (SUCCEEDED(_StringFromGUID(&(pdbdi->dbcc_classguid), szGUID,
  213. ARRAYSIZE(szGUID))))
  214. {
  215. switch (dwEventType)
  216. {
  217. case DBT_DEVICEARRIVAL:
  218. pszEventType = TEXT("DBT_DEVTYP_DEVICEINTERFACE + DBT_DEVICEARRIVAL");
  219. DIAGNOSTIC((TEXT("[0000]Processing Interface Arrival Event: %s, %s"), pszEventType, szGUID));
  220. break;
  221. case DBT_DEVICEREMOVECOMPLETE:
  222. pszEventType = TEXT("DBT_DEVTYP_DEVICEINTERFACE + DBT_DEVICEREMOVECOMPLETE");
  223. DIAGNOSTIC((TEXT("[0001]Processing Interface Removal Event: %s, %s"), pszEventType, szGUID));
  224. break;
  225. #ifdef DEBUG
  226. case DBT_DEVICEQUERYREMOVEFAILED: pszEventType = TEXT("DBT_DEVTYP_DEVICEINTERFACE + DBT_DEVICEQUERYREMOVEFAILED"); break;
  227. case DBT_DEVICEREMOVEPENDING: pszEventType = TEXT("DBT_DEVTYP_DEVICEINTERFACE + DBT_DEVICEREMOVEPENDING"); break;
  228. case DBT_DEVICEQUERYREMOVE: pszEventType = TEXT("DBT_DEVTYP_DEVICEINTERFACE + DBT_DEVICEQUERYREMOVE"); break;
  229. #endif
  230. }
  231. TRACE(TF_SHHWDTCTDTCT, TEXT("Processing Interface Event: %s, %s"),
  232. pszEventType, szGUID);
  233. }
  234. hres = _HandleInterfaceEvent(pdbdi, dwEventType);
  235. }
  236. else
  237. {
  238. if (DBT_DEVTYP_HANDLE == dbhdr->dbch_devicetype)
  239. {
  240. DEV_BROADCAST_HANDLE* pdbh = (DEV_BROADCAST_HANDLE*)pEventData;
  241. #ifdef DEBUG
  242. LPWSTR pszEventType = TEXT("Unknown");
  243. WCHAR szGUID[MAX_GUIDSTRING];
  244. if (DBT_CUSTOMEVENT == dwEventType)
  245. {
  246. HRESULT hrTmp = S_FALSE;
  247. if (GUID_IO_MEDIA_ARRIVAL == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_MEDIA_ARRIVAL");
  248. else if (GUID_IO_MEDIA_REMOVAL == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_MEDIA_REMOVAL");
  249. else if (GUID_IO_VOLUME_LOCK == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_VOLUME_LOCK");
  250. else if (GUID_IO_VOLUME_LOCK_FAILED == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_VOLUME_LOCK_FAILED");
  251. else if (GUID_IO_VOLUME_UNLOCK == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_VOLUME_UNLOCK");
  252. else if (GUID_IO_VOLUME_NAME_CHANGE == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_VOLUME_NAME_CHANGE");
  253. else if (GUID_IO_VOLUME_CHANGE == pdbh->dbch_eventguid) pszEventType = TEXT("GUID_IO_VOLUME_CHANGE");
  254. else
  255. {
  256. hrTmp = _StringFromGUID(&(pdbh->dbch_eventguid), szGUID, ARRAYSIZE(szGUID));
  257. pszEventType = szGUID;
  258. }
  259. if (SUCCEEDED(hrTmp))
  260. {
  261. TRACE(TF_SHHWDTCTDTCT,
  262. TEXT("Processing Broadcast Event: %s, hdevnotify = 0x%08X"),
  263. pszEventType, pdbh->dbch_hdevnotify);
  264. }
  265. }
  266. else
  267. {
  268. pszEventType = TEXT("unknown");
  269. switch (dwEventType)
  270. {
  271. case DBT_DEVICEARRIVAL: pszEventType = TEXT("DBT_DEVTYP_HANDLE + DBT_DEVICEARRIVAL"); break;
  272. case DBT_DEVICEQUERYREMOVE: pszEventType = TEXT("DBT_DEVTYP_HANDLE + DBT_DEVICEQUERYREMOVE"); break;
  273. case DBT_DEVICEQUERYREMOVEFAILED: pszEventType = TEXT("DBT_DEVTYP_HANDLE + DBT_DEVICEQUERYREMOVEFAILED"); break;
  274. case DBT_DEVICEREMOVEPENDING: pszEventType = TEXT("DBT_DEVTYP_HANDLE + DBT_DEVICEREMOVEPENDING"); break;
  275. case DBT_DEVICEREMOVECOMPLETE: pszEventType = TEXT("DBT_DEVTYP_HANDLE + DBT_DEVICEREMOVECOMPLETE"); break;
  276. }
  277. TRACE(TF_SHHWDTCTDTCT, TEXT("Processing Unknown Broadcast Event: %s, dwEventType = 0x%08X"), pszEventType, dwEventType);
  278. }
  279. #endif
  280. hres = _HandleBroadcastHandleEvent(pdbh, dwEventType);
  281. }
  282. else
  283. {
  284. }
  285. }
  286. }
  287. ASSERTVALIDSTATE();
  288. return hres;
  289. }
  290. STDMETHODIMP CHWEventDetectorImpl::Run()
  291. {
  292. ASSERTVALIDSTATE();
  293. // Nothing to do for now.
  294. return S_OK;
  295. }
  296. STDMETHODIMP CHWEventDetectorImpl::HandlePowerEvent(
  297. DWORD UNREF_PARAM(dwEventType), LPVOID UNREF_PARAM(pEventData))
  298. {
  299. HRESULT hres = E_UNEXPECTED;
  300. return hres;
  301. }
  302. STDMETHODIMP CHWEventDetectorImpl::HandleHWProfileEvent(
  303. DWORD UNREF_PARAM(dwEventType), LPVOID UNREF_PARAM(pEventData))
  304. {
  305. HRESULT hres = E_UNEXPECTED;
  306. return hres;
  307. }
  308. STDMETHODIMP CHWEventDetectorImpl::HandleSessionChange(
  309. DWORD dwEventType, LPVOID UNREF_PARAM(pvEventData))
  310. {
  311. HRESULT hres;
  312. switch (dwEventType)
  313. {
  314. case WTS_SESSION_LOGOFF:
  315. //
  316. // When this happens, we need to check our handles to see which
  317. // Explorer process went away and free its handle.
  318. //
  319. hres = CHardwareDevicesImpl::_AdviseCheckClients( );
  320. break;
  321. default:
  322. hres = S_OK;
  323. break;
  324. }
  325. return hres;
  326. }
  327. #ifdef DEBUG
  328. void CHWEventDetectorImpl::_DbgAssertValidState()
  329. {
  330. CHWEventDetectorHelper::_DbgAssertValidState();
  331. }
  332. #endif