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.

1334 lines
30 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #undef ASSERT
  5. #include "cmmn.h"
  6. #include <shlwapi.h>
  7. #include "hwdev.h"
  8. #include "hnotif.h"
  9. #include "vol.h"
  10. #include "mtpts.h"
  11. #include "miscdev.h"
  12. #include "drvbase.h"
  13. #include "regnotif.h"
  14. #include "users.h"
  15. #include "logging.h"
  16. #include "sfstr.h"
  17. #include "dbg.h"
  18. #include "tfids.h"
  19. #include <setupapi.h>
  20. #pragma warning(disable: 4201)
  21. #include <winioctl.h>
  22. #pragma warning(default: 4201)
  23. #define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
  24. ///////////////////////////////////////////////////////////////////////////////
  25. //
  26. const GUID guidVolumeClass =
  27. {0x53f5630d, 0xb6bf, 0x11d0,
  28. {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}};
  29. const GUID guidDiskClass =
  30. {0x53f56307, 0xb6bf, 0x11d0,
  31. {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}};
  32. const GUID guidCdRomClass =
  33. {0x53f56308L, 0xb6bf, 0x11d0,
  34. {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}};
  35. const GUID guidImagingDeviceClass =
  36. {0x6bdd1fc6L, 0x810f, 0x11d0,
  37. {0xbe, 0xc7, 0x08, 0x00, 0x2b, 0xe2, 0x09, 0x2f}};
  38. const GUID guidVideoCameraClass =
  39. {0x6994AD05L, 0x93EF, 0x11D0,
  40. {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
  41. const GUID guidInvalid =
  42. {0xFFFFFFFFL, 0xFFFF, 0xFFFF,
  43. {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
  44. ///////////////////////////////////////////////////////////////////////////////
  45. //
  46. BOOL CHWEventDetectorHelper::_fDiagnosticAppPresent = FALSE;
  47. DWORD CHWEventDetectorHelper::_dwDiagAppLastCheck = (DWORD)-1;
  48. SERVICE_STATUS_HANDLE CHWEventDetectorHelper::_ssh = NULL;
  49. BOOL CHWEventDetectorHelper::_fListCreated = FALSE;
  50. CNamedElemList* CHWEventDetectorHelper::
  51. _rgpnel[HWEDLIST_COUNT_OF_LISTS] = {0};
  52. // For the debugger extension
  53. DWORD CHWEventDetectorHelper::_cpnel =
  54. ARRAYSIZE(CHWEventDetectorHelper::_rgpnel);
  55. BOOL CHWEventDetectorHelper::_fDocked = FALSE;
  56. CImpersonateEveryone* CHWEventDetectorHelper::_pieo = NULL;
  57. CCriticalSection CHWEventDetectorHelper::_cs;
  58. BOOL CHWEventDetectorHelper::_fInited = FALSE;
  59. #ifdef DEBUG
  60. DWORD _cDbgDeviceHandle = 0;
  61. #endif
  62. ///////////////////////////////////////////////////////////////////////////////
  63. //
  64. HRESULT _DeviceInstIsRemovable(DEVINST devinst, BOOL* pfRemovable)
  65. {
  66. DWORD dwCap;
  67. DWORD cbCap = sizeof(dwCap);
  68. CONFIGRET cr = CM_Get_DevNode_Registry_Property_Ex(devinst,
  69. CM_DRP_CAPABILITIES, NULL, &dwCap, &cbCap, 0, NULL);
  70. if (CR_SUCCESS == cr)
  71. {
  72. if (CM_DEVCAP_REMOVABLE & dwCap)
  73. {
  74. *pfRemovable = TRUE;
  75. }
  76. else
  77. {
  78. *pfRemovable = FALSE;
  79. }
  80. }
  81. else
  82. {
  83. *pfRemovable = FALSE;
  84. }
  85. return S_OK;
  86. }
  87. HANDLE _GetDeviceHandle(LPCTSTR psz, DWORD dwDesiredAccess)
  88. {
  89. HANDLE hDevice = CreateFile(psz, dwDesiredAccess,
  90. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
  91. #ifdef DEBUG
  92. if (INVALID_HANDLE_VALUE != hDevice)
  93. {
  94. ++_cDbgDeviceHandle;
  95. TRACE(TF_LEAK, TEXT("_GetDeviceHandle: %d"), _cDbgDeviceHandle);
  96. }
  97. #endif
  98. return hDevice;
  99. }
  100. void _CloseDeviceHandle(HANDLE hDevice)
  101. {
  102. CloseHandle(hDevice);
  103. #ifdef DEBUG
  104. if (INVALID_HANDLE_VALUE != hDevice)
  105. {
  106. --_cDbgDeviceHandle;
  107. TRACE(TF_LEAK, TEXT("_CloseDeviceHandle: %d"), _cDbgDeviceHandle);
  108. }
  109. #endif
  110. }
  111. HRESULT _GetVolumeName(LPCWSTR pszDeviceID, LPWSTR pszVolumeName,
  112. DWORD cchVolumeName)
  113. {
  114. WCHAR szDeviceIDWithSlash[MAX_DEVICEID];
  115. LPWSTR pszNext;
  116. DWORD cchLeft;
  117. HRESULT hres = SafeStrCpyNEx(szDeviceIDWithSlash, pszDeviceID,
  118. ARRAYSIZE(szDeviceIDWithSlash), &pszNext, &cchLeft);
  119. if (SUCCEEDED(hres))
  120. {
  121. hres = SafeStrCpyN(pszNext, TEXT("\\"), cchLeft);
  122. if (SUCCEEDED(hres))
  123. {
  124. if (GetVolumeNameForVolumeMountPoint(szDeviceIDWithSlash,
  125. pszVolumeName, cchVolumeName))
  126. {
  127. hres = S_OK;
  128. }
  129. else
  130. {
  131. *pszVolumeName = 0;
  132. hres = S_FALSE;
  133. }
  134. }
  135. }
  136. return hres;
  137. }
  138. HRESULT _GetHWDeviceInstFromVolumeIntfID(LPCWSTR pszDeviceIntfID,
  139. CHWDeviceInst** pphwdevinst, CNamedElem** ppelemToRelease)
  140. {
  141. CNamedElemList* pnel;
  142. HRESULT hres = CHWEventDetectorHelper::GetList(HWEDLIST_VOLUME, &pnel);
  143. *pphwdevinst = NULL;
  144. *ppelemToRelease = NULL;
  145. if (S_OK == hres)
  146. {
  147. CNamedElem* pelem;
  148. hres = pnel->Get(pszDeviceIntfID, &pelem);
  149. if (SUCCEEDED(hres) && (S_FALSE != hres))
  150. {
  151. CVolume* pvol = (CVolume*)pelem;
  152. hres = pvol->GetHWDeviceInst(pphwdevinst);
  153. if (SUCCEEDED(hres) && (S_FALSE != hres))
  154. {
  155. *ppelemToRelease = pelem;
  156. }
  157. else
  158. {
  159. pelem->RCRelease();
  160. }
  161. }
  162. pnel->RCRelease();
  163. }
  164. return hres;
  165. }
  166. HRESULT _GetHWDeviceInstFromDeviceNode(LPCWSTR pszDeviceNode,
  167. CHWDeviceInst** pphwdevinst, CNamedElem** ppelemToRelease)
  168. {
  169. CNamedElemList* pnel;
  170. HRESULT hres = CHWEventDetectorHelper::GetList(HWEDLIST_MISCDEVNODE, &pnel);
  171. *pphwdevinst = NULL;
  172. *ppelemToRelease = NULL;
  173. if (S_OK == hres)
  174. {
  175. CNamedElem* pelem;
  176. hres = pnel->GetOrAdd(pszDeviceNode, &pelem);
  177. if (SUCCEEDED(hres))
  178. {
  179. CMiscDeviceNode* pmiscdevnode =
  180. (CMiscDeviceNode*)pelem;
  181. hres = pmiscdevnode->GetHWDeviceInst(pphwdevinst);
  182. if (SUCCEEDED(hres) && (S_FALSE != hres))
  183. {
  184. *ppelemToRelease = pelem;
  185. }
  186. else
  187. {
  188. pelem->RCRelease();
  189. }
  190. }
  191. pnel->RCRelease();
  192. }
  193. return hres;
  194. }
  195. HRESULT _GetHWDeviceInstFromDeviceIntfID(LPCWSTR pszDeviceIntfID,
  196. CHWDeviceInst** pphwdevinst, CNamedElem** ppelemToRelease)
  197. {
  198. CNamedElemList* pnel;
  199. HRESULT hres = CHWEventDetectorHelper::GetList(HWEDLIST_MISCDEVINTF, &pnel);
  200. *pphwdevinst = NULL;
  201. *ppelemToRelease = NULL;
  202. if (S_OK == hres)
  203. {
  204. CNamedElem* pelem;
  205. hres = pnel->Get(pszDeviceIntfID, &pelem);
  206. if (SUCCEEDED(hres) && (S_FALSE != hres))
  207. {
  208. CMiscDeviceInterface* pmiscdevintf =
  209. (CMiscDeviceInterface*)pelem;
  210. hres = pmiscdevintf->GetHWDeviceInst(pphwdevinst);
  211. if (SUCCEEDED(hres) && (S_FALSE != hres))
  212. {
  213. *ppelemToRelease = pelem;
  214. }
  215. else
  216. {
  217. pelem->RCRelease();
  218. }
  219. }
  220. pnel->RCRelease();
  221. }
  222. return hres;
  223. }
  224. HRESULT _GetHWDeviceInstFromDeviceOrVolumeIntfID(LPCWSTR pszDeviceIntfID,
  225. CHWDeviceInst** pphwdevinst, CNamedElem** ppelemToRelease)
  226. {
  227. HRESULT hres = _GetHWDeviceInstFromVolumeIntfID(pszDeviceIntfID,
  228. pphwdevinst, ppelemToRelease);
  229. if (S_FALSE == hres)
  230. {
  231. // Not a volume ID, try other devices
  232. hres = _GetHWDeviceInstFromDeviceIntfID(pszDeviceIntfID,
  233. pphwdevinst, ppelemToRelease);
  234. }
  235. return hres;
  236. }
  237. HRESULT _GetDeviceIDFromMtPtName(LPCWSTR pszMtPt, LPWSTR pszDeviceID,
  238. DWORD cchDeviceID)
  239. {
  240. CNamedElemList* pnel;
  241. HRESULT hres = CHWEventDetectorHelper::GetList(HWEDLIST_MTPT, &pnel);
  242. if (S_OK == hres)
  243. {
  244. CNamedElem* pelem;
  245. hres = pnel->Get(pszMtPt, &pelem);
  246. if (SUCCEEDED(hres) && (S_FALSE != hres))
  247. {
  248. CMtPt* pmtpt = (CMtPt*)pelem;
  249. hres = pmtpt->GetVolumeName(pszDeviceID, cchDeviceID);
  250. pelem->RCRelease();
  251. }
  252. pnel->RCRelease();
  253. }
  254. return hres;
  255. }
  256. HRESULT _GetDeviceIDFromHDevNotify(HDEVNOTIFY hdevnotify,
  257. LPWSTR pszDeviceID, DWORD cchDeviceID, DWORD* pcchRequired)
  258. {
  259. // This should be a drive not a volume. Cannot get Media arrival/removal
  260. // from volume.
  261. CNamedElemList* pnel;
  262. HRESULT hres = CHWEventDetectorHelper::GetList(HWEDLIST_HANDLENOTIF, &pnel);
  263. if (S_OK == hres)
  264. {
  265. CNamedElemEnum* penum;
  266. hres = pnel->GetEnum(&penum);
  267. if (SUCCEEDED(hres))
  268. {
  269. CNamedElem* pelem;
  270. BOOL fFoundIt = FALSE;
  271. while (!fFoundIt && SUCCEEDED(hres = penum->Next(&pelem)) &&
  272. (S_FALSE != hres))
  273. {
  274. CHandleNotif* phnotif = (CHandleNotif*)pelem;
  275. HDEVNOTIFY hdevnotifyLocal = phnotif->GetDeviceNotifyHandle();
  276. if (hdevnotifyLocal == hdevnotify)
  277. {
  278. // Found it
  279. hres = phnotif->GetName(pszDeviceID, cchDeviceID,
  280. pcchRequired);
  281. fFoundIt = TRUE;
  282. }
  283. pelem->RCRelease();
  284. }
  285. penum->RCRelease();
  286. }
  287. pnel->RCRelease();
  288. }
  289. return hres;
  290. }
  291. HRESULT _GetDeviceID(LPCWSTR pszName, LPWSTR pszDeviceID, DWORD cchDeviceID)
  292. {
  293. HRESULT hres;
  294. if (*pszName && (TEXT('\\') == *pszName) &&
  295. *(pszName + 1) && (TEXT('\\') == *(pszName + 1)) &&
  296. *(pszName + 2) && (TEXT('?') == *(pszName + 2)))
  297. {
  298. hres = SafeStrCpyN(pszDeviceID, pszName, cchDeviceID);
  299. }
  300. else
  301. {
  302. hres = _GetDeviceIDFromMtPtName(pszName, pszDeviceID, cchDeviceID);
  303. }
  304. return hres;
  305. }
  306. HRESULT _GetVolume(LPCWSTR pszVolume, CVolume** ppvol)
  307. {
  308. WCHAR szDeviceID[MAX_DEVICEID];
  309. HRESULT hr = _GetDeviceID(pszVolume, szDeviceID, ARRAYSIZE(szDeviceID));
  310. *ppvol = NULL;
  311. if (SUCCEEDED(hr) && (S_FALSE != hr))
  312. {
  313. CNamedElemList* pnel;
  314. hr = CHWEventDetectorHelper::GetList(HWEDLIST_VOLUME, &pnel);
  315. if (S_OK == hr)
  316. {
  317. CNamedElem* pelem;
  318. hr = pnel->Get(szDeviceID, &pelem);
  319. if (SUCCEEDED(hr) && (S_FALSE != hr))
  320. {
  321. *ppvol = (CVolume*)pelem;
  322. // Do not release
  323. }
  324. pnel->RCRelease();
  325. }
  326. }
  327. return hr;
  328. }
  329. HRESULT _GetAltDeviceID(LPCWSTR pszDeviceID, LPWSTR pszDeviceIDAlt,
  330. DWORD cchDeviceIDAlt)
  331. {
  332. CNamedElemList* pnel;
  333. HRESULT hres = CHWEventDetectorHelper::GetList(HWEDLIST_MTPT, &pnel);
  334. if (S_OK == hres)
  335. {
  336. CNamedElemEnum* penum;
  337. hres = pnel->GetEnum(&penum);
  338. if (SUCCEEDED(hres))
  339. {
  340. BOOL fFoundIt = FALSE;
  341. CNamedElem* pelem;
  342. while (!fFoundIt && SUCCEEDED(hres = penum->Next(&pelem)) &&
  343. (S_FALSE != hres))
  344. {
  345. CMtPt* pmtpt = (CMtPt*)pelem;
  346. WCHAR szDeviceIDVolume[MAX_DEVICEID];
  347. hres = pmtpt->GetVolumeName(szDeviceIDVolume,
  348. ARRAYSIZE(szDeviceIDVolume));
  349. if (SUCCEEDED(hres))
  350. {
  351. if (!lstrcmp(szDeviceIDVolume, pszDeviceID))
  352. {
  353. // Use me!
  354. DWORD cchReq;
  355. fFoundIt = TRUE;
  356. hres = pmtpt->GetName(pszDeviceIDAlt,
  357. cchDeviceIDAlt, &cchReq);
  358. }
  359. }
  360. pelem->RCRelease();
  361. }
  362. penum->RCRelease();
  363. }
  364. pnel->RCRelease();
  365. }
  366. return hres;
  367. }
  368. HRESULT _GetDeviceNumberInfoFromHandle(HANDLE hDevice, DEVICE_TYPE* pdevtype,
  369. ULONG* pulDeviceNumber, ULONG* pulPartitionNumber)
  370. {
  371. HRESULT hr;
  372. STORAGE_DEVICE_NUMBER sdn = {0};
  373. DWORD dwDummy;
  374. BOOL b = DeviceIoControl(hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER,
  375. NULL, 0, &sdn, sizeof(sdn), &dwDummy, NULL);
  376. if (b)
  377. {
  378. *pdevtype = sdn.DeviceType;
  379. *pulDeviceNumber = sdn.DeviceNumber;
  380. *pulPartitionNumber = sdn.PartitionNumber;
  381. hr = S_OK;
  382. }
  383. else
  384. {
  385. hr = S_FALSE;
  386. }
  387. return hr;
  388. }
  389. ///////////////////////////////////////////////////////////////////////////////
  390. //
  391. HRESULT _CoTaskMemCopy(LPCWSTR pszSrc, LPWSTR* ppszDest)
  392. {
  393. HRESULT hres = S_OK;
  394. *ppszDest = (LPWSTR)CoTaskMemAlloc((lstrlen(pszSrc) + 1) * sizeof(WCHAR));
  395. if (*ppszDest)
  396. {
  397. lstrcpy(*ppszDest, pszSrc);
  398. }
  399. else
  400. {
  401. *ppszDest = NULL;
  402. hres = E_OUTOFMEMORY;
  403. }
  404. return hres;
  405. }
  406. void _CoTaskMemFree(void* pv)
  407. {
  408. if (pv)
  409. {
  410. CoTaskMemFree(pv);
  411. }
  412. }
  413. HRESULT DupString(LPCWSTR pszSrc, LPWSTR* ppszDest)
  414. {
  415. HRESULT hres;
  416. *ppszDest = (LPWSTR)LocalAlloc(LPTR, (lstrlen(pszSrc) + 1) *
  417. sizeof(WCHAR));
  418. if (*ppszDest)
  419. {
  420. lstrcpy(*ppszDest, pszSrc);
  421. hres = S_OK;
  422. }
  423. else
  424. {
  425. hres = E_OUTOFMEMORY;
  426. }
  427. return hres;
  428. }
  429. ///////////////////////////////////////////////////////////////////////////////
  430. //
  431. HRESULT _GetDeviceInstance(LPCWSTR pszDeviceIntfID, DEVINST* pdevinst,
  432. GUID* pguidInterface)
  433. {
  434. HRESULT hres = S_FALSE;
  435. // not thread safe
  436. static WCHAR szDeviceIntfIDLast[MAX_DEVICEID] = TEXT("");
  437. static DEVINST devinstLast;
  438. static GUID guidInterfaceLast;
  439. // Cached
  440. if (!lstrcmpi(szDeviceIntfIDLast, pszDeviceIntfID))
  441. {
  442. // Yep
  443. *pdevinst = devinstLast;
  444. *pguidInterface = guidInterfaceLast;
  445. hres = S_OK;
  446. }
  447. else
  448. {
  449. // No
  450. HDEVINFO hdevinfo = SetupDiCreateDeviceInfoList(NULL, NULL);
  451. *pdevinst = NULL;
  452. if (INVALID_HANDLE_VALUE != hdevinfo)
  453. {
  454. SP_DEVICE_INTERFACE_DATA sdid = {0};
  455. sdid.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  456. if (SetupDiOpenDeviceInterface(hdevinfo, pszDeviceIntfID, 0, &sdid))
  457. {
  458. DWORD cbsdidd = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) +
  459. (MAX_DEVICE_ID_LEN * sizeof(WCHAR));
  460. SP_DEVINFO_DATA sdd = {0};
  461. SP_DEVICE_INTERFACE_DETAIL_DATA* psdidd =
  462. (SP_DEVICE_INTERFACE_DETAIL_DATA*)LocalAlloc(LPTR, cbsdidd);
  463. if (psdidd)
  464. {
  465. psdidd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  466. sdd.cbSize = sizeof(SP_DEVINFO_DATA);
  467. // SetupDiGetDeviceInterfaceDetail (below) requires that the
  468. // cbSize member of SP_DEVICE_INTERFACE_DETAIL_DATA be set
  469. // to the size of the fixed part of the structure, and to pass
  470. // the size of the full thing as the 4th param.
  471. if (SetupDiGetDeviceInterfaceDetail(hdevinfo, &sdid, psdidd,
  472. cbsdidd, NULL, &sdd))
  473. {
  474. *pdevinst = sdd.DevInst;
  475. *pguidInterface = sdid.InterfaceClassGuid;
  476. hres = S_OK;
  477. }
  478. LocalFree((HLOCAL)psdidd);
  479. }
  480. }
  481. SetupDiDestroyDeviceInfoList(hdevinfo);
  482. }
  483. if (SUCCEEDED(hres) && (S_FALSE != hres))
  484. {
  485. // Cache it
  486. if (SUCCEEDED(SafeStrCpyN(szDeviceIntfIDLast, pszDeviceIntfID,
  487. ARRAYSIZE(szDeviceIntfIDLast))))
  488. {
  489. devinstLast = *pdevinst;
  490. guidInterfaceLast = *pguidInterface;
  491. }
  492. else
  493. {
  494. szDeviceIntfIDLast[0] = 0;
  495. }
  496. }
  497. else
  498. {
  499. szDeviceIntfIDLast[0] = 0;
  500. }
  501. }
  502. return hres;
  503. }
  504. HRESULT _GetDeviceInstanceFromDevNode(LPCWSTR pszDeviceNode, DEVINST* pdevinst)
  505. {
  506. HRESULT hres = S_FALSE;
  507. HDEVINFO hdevinfo = SetupDiCreateDeviceInfoList(NULL, NULL);
  508. *pdevinst = NULL;
  509. if (INVALID_HANDLE_VALUE != hdevinfo)
  510. {
  511. SP_DEVINFO_DATA sdd = {0};
  512. sdd.cbSize = sizeof(SP_DEVINFO_DATA);
  513. if (SetupDiOpenDeviceInfo(hdevinfo, pszDeviceNode, NULL, 0, &sdd))
  514. {
  515. *pdevinst = sdd.DevInst;
  516. hres = S_OK;
  517. }
  518. SetupDiDestroyDeviceInfoList(hdevinfo);
  519. }
  520. return hres;
  521. }
  522. ///////////////////////////////////////////////////////////////////////////////
  523. //
  524. void CHWEventDetectorHelper::TraceDiagnosticMsg(LPWSTR pszMsg, ...)
  525. {
  526. // Big buffer, but there's no wvsnprintf, and device names can get
  527. // really big.
  528. WCHAR szBuf[2048];
  529. int cch;
  530. int cch2 = wsprintf(szBuf, TEXT("~0x%08X~"), GetCurrentThreadId());
  531. va_list vArgs;
  532. va_start(vArgs, pszMsg);
  533. cch = wvsprintf(szBuf + cch2, pszMsg, vArgs) + cch2;
  534. va_end(vArgs);
  535. if (cch < ARRAYSIZE(szBuf) - 2)
  536. {
  537. szBuf[cch] = TEXT('\r');
  538. szBuf[cch + 1] = TEXT('\n');
  539. szBuf[cch + 2] = 0;
  540. cch += 3;
  541. }
  542. #ifndef FEATURE_USELIVELOGGING
  543. WriteToLogFileW(szBuf);
  544. #else // FEATURE_USELIVELOGGING
  545. CallNamedPipe(TEXT("\\\\.\\pipe\\ShellService_Diagnostic"), szBuf,
  546. cch * sizeof(WCHAR), NULL, 0, NULL, NMPWAIT_NOWAIT);
  547. #endif // FEATURE_USELIVELOGGING
  548. }
  549. //static
  550. HRESULT CHWEventDetectorHelper::CheckDiagnosticAppPresence()
  551. {
  552. DWORD dwNow = GetTickCount();
  553. BOOL fPerformCheckNow = FALSE;
  554. if (dwNow < _dwDiagAppLastCheck)
  555. {
  556. // We wrapped, or init case of -1
  557. fPerformCheckNow = TRUE;
  558. }
  559. else
  560. {
  561. if (dwNow > (_dwDiagAppLastCheck + 15 * 1000))
  562. {
  563. fPerformCheckNow = TRUE;
  564. }
  565. }
  566. if (fPerformCheckNow)
  567. {
  568. #ifndef FEATURE_USELIVELOGGING
  569. DWORD dwType;
  570. DWORD dwUseLogFile = 0;
  571. DWORD cbSize = sizeof(dwUseLogFile);
  572. BOOL fReCheck = ((ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\ShellHWDetection"), TEXT("LogFile"), &dwType, (void *)&dwUseLogFile, &cbSize)) &&
  573. (REG_DWORD == dwType) &&
  574. (sizeof(dwUseLogFile) == cbSize) &&
  575. (0 != dwUseLogFile));
  576. #else // FEATURE_USELIVELOGGING
  577. HANDLE hEvent = OpenEvent(SYNCHRONIZE, FALSE,
  578. TEXT("ShellService_Diagnostic"));
  579. BOOL fReCheck = hEvent;
  580. CloseHandle(hEvent);
  581. #endif // FEATURE_USELIVELOGGING
  582. if (fReCheck)
  583. {
  584. // Yep, it's there!
  585. if (!_fDiagnosticAppPresent)
  586. {
  587. TRACE(TF_SHHWDTCTDTCT, TEXT("Diagnostic App appeared!"));
  588. }
  589. _fDiagnosticAppPresent = TRUE;
  590. }
  591. else
  592. {
  593. if (_fDiagnosticAppPresent)
  594. {
  595. TRACE(TF_SHHWDTCTDTCT, TEXT("Diagnostic App disappeared!"));
  596. }
  597. _fDiagnosticAppPresent = FALSE;
  598. }
  599. _dwDiagAppLastCheck = dwNow;
  600. }
  601. return S_OK;
  602. }
  603. //static
  604. HRESULT CHWEventDetectorHelper::SetServiceStatusHandle(
  605. SERVICE_STATUS_HANDLE ssh)
  606. {
  607. _ssh = ssh;
  608. return S_OK;
  609. }
  610. //static
  611. HRESULT CHWEventDetectorHelper::GetList(HWEDLIST hwedlist,
  612. CNamedElemList** ppnel)
  613. {
  614. HRESULT hres;
  615. CNamedElemList* pnel = _rgpnel[hwedlist];
  616. if (pnel)
  617. {
  618. pnel->RCAddRef();
  619. }
  620. *ppnel = pnel;
  621. hres = *ppnel ? S_OK : E_FAIL;
  622. if (S_FALSE == hres)
  623. {
  624. TRACE(TF_SHHWDTCTDTCT, TEXT("CHWEventDetectorHelper::GetList S_FALSE'd"));
  625. }
  626. return hres;
  627. }
  628. //static
  629. HRESULT CHWEventDetectorHelper::DeleteLists()
  630. {
  631. for (DWORD dw = 0; dw < ARRAYSIZE(_rgpnel); ++dw)
  632. {
  633. if (_rgpnel[dw])
  634. {
  635. _rgpnel[dw]->EmptyList();
  636. _rgpnel[dw]->RCRelease();
  637. _rgpnel[dw] = NULL;
  638. }
  639. }
  640. return S_OK;
  641. }
  642. //static
  643. HRESULT CHWEventDetectorHelper::CreateLists()
  644. {
  645. HRESULT hres = S_FALSE;
  646. if (!_fListCreated)
  647. {
  648. for (DWORD dw = 0; SUCCEEDED(hres) && (dw < ARRAYSIZE(_rgpnel)); ++dw)
  649. {
  650. _rgpnel[dw] = new CNamedElemList();
  651. if (!_rgpnel[dw])
  652. {
  653. hres = E_OUTOFMEMORY;
  654. // should RCRelease the already allocated ones
  655. }
  656. }
  657. if (SUCCEEDED(hres))
  658. {
  659. // Initialize them ALL first
  660. hres = _rgpnel[HWEDLIST_HANDLENOTIF]->Init(
  661. CHandleNotif::Create, NULL);
  662. if (SUCCEEDED(hres))
  663. {
  664. hres = _rgpnel[HWEDLIST_VOLUME]->Init(CVolume::Create,
  665. CVolume::GetFillEnum);
  666. }
  667. if (SUCCEEDED(hres))
  668. {
  669. hres = _rgpnel[HWEDLIST_DISK]->Init(
  670. CDisk::Create, CDisk::GetFillEnum);
  671. }
  672. if (SUCCEEDED(hres))
  673. {
  674. hres = _rgpnel[HWEDLIST_MISCDEVINTF]->Init(
  675. CMiscDeviceInterface::Create, NULL);
  676. }
  677. if (SUCCEEDED(hres))
  678. {
  679. hres = _rgpnel[HWEDLIST_MISCDEVNODE]->Init(
  680. CMiscDeviceNode::Create, NULL);
  681. }
  682. if (SUCCEEDED(hres))
  683. {
  684. hres = _rgpnel[HWEDLIST_MTPT]->Init(CMtPt::Create, NULL);
  685. }
  686. if (SUCCEEDED(hres))
  687. {
  688. hres = _rgpnel[HWEDLIST_ADVISECLIENT]->Init(CAdviseClient::Create, NULL);
  689. }
  690. #ifdef DEBUG
  691. if (SUCCEEDED(hres))
  692. {
  693. _rgpnel[HWEDLIST_HANDLENOTIF]->InitDebug(TEXT("CHandleNotif"));
  694. _rgpnel[HWEDLIST_VOLUME]->InitDebug(TEXT("CVolume"));
  695. _rgpnel[HWEDLIST_DISK]->InitDebug(TEXT("CDisk"));
  696. _rgpnel[HWEDLIST_MISCDEVINTF]->InitDebug(TEXT("CMiscDeviceInterface"));
  697. _rgpnel[HWEDLIST_MISCDEVNODE]->InitDebug(TEXT("CMiscDeviceNode"));
  698. _rgpnel[HWEDLIST_MTPT]->InitDebug(TEXT("CMtPt"));
  699. _rgpnel[HWEDLIST_ADVISECLIENT]->InitDebug(TEXT("CAdviseClient"));
  700. }
  701. #endif
  702. if (SUCCEEDED(hres))
  703. {
  704. _fListCreated = TRUE;
  705. TRACE(TF_SHHWDTCTDTCT, TEXT("CNamedElemList's created"));
  706. }
  707. }
  708. }
  709. return hres;
  710. }
  711. //static
  712. HRESULT CHWEventDetectorHelper::FillLists()
  713. {
  714. ASSERT(_fListCreated);
  715. // Enumerate those having an enumerator
  716. HRESULT hres = _rgpnel[HWEDLIST_DISK]->ReEnum();
  717. if (SUCCEEDED(hres))
  718. {
  719. hres = _rgpnel[HWEDLIST_VOLUME]->ReEnum();
  720. }
  721. return hres;
  722. }
  723. //static
  724. HRESULT CHWEventDetectorHelper::EmptyLists()
  725. {
  726. for (DWORD dw = 0; dw < HWEDLIST_COUNT_OF_LISTS; ++dw)
  727. {
  728. _rgpnel[dw]->EmptyList();
  729. }
  730. _fListCreated = FALSE;
  731. return S_OK;
  732. }
  733. ///////////////////////////////////////////////////////////////////////////////
  734. //
  735. // static
  736. HRESULT CHWEventDetectorHelper::InitDockState()
  737. {
  738. BOOL fDocked;
  739. HRESULT hr = _MachineIsDocked(&fDocked);
  740. if (SUCCEEDED(hr) && (S_FALSE != hr))
  741. {
  742. CHWEventDetectorHelper::_fDocked = fDocked;
  743. }
  744. return hr;
  745. }
  746. // static
  747. HRESULT CHWEventDetectorHelper::DockStateChanged(BOOL* pfDockStateChanged)
  748. {
  749. BOOL fDocked;
  750. HRESULT hr = _MachineIsDocked(&fDocked);
  751. if (SUCCEEDED(hr) && (S_FALSE != hr))
  752. {
  753. if (fDocked != _fDocked)
  754. {
  755. *pfDockStateChanged = TRUE;
  756. }
  757. // Update it too
  758. CHWEventDetectorHelper::_fDocked = fDocked;
  759. }
  760. return hr;
  761. }
  762. //static
  763. HRESULT CHWEventDetectorHelper::RegisterDeviceNotification(
  764. PVOID pvNotificationFilter, HDEVNOTIFY* phdevnotify,
  765. BOOL fAllInterfaceClasses)
  766. {
  767. HRESULT hres;
  768. DWORD dwFlags;
  769. ASSERT(_ssh);
  770. if (fAllInterfaceClasses)
  771. {
  772. dwFlags = DEVICE_NOTIFY_ALL_INTERFACE_CLASSES;
  773. }
  774. else
  775. {
  776. dwFlags = 0;
  777. }
  778. TRACE(TF_SHHWDTCTDTCTDETAILED,
  779. TEXT("Entered CHWEventDetectorImpl::RegisterDeviceNotification"));
  780. #ifndef DEBUG
  781. dwFlags |= DEVICE_NOTIFY_SERVICE_HANDLE;
  782. *phdevnotify = ::RegisterDeviceNotification(_ssh, pvNotificationFilter,
  783. dwFlags);
  784. #else
  785. if (IsWindow((HWND)_ssh))
  786. {
  787. dwFlags |= DEVICE_NOTIFY_WINDOW_HANDLE;
  788. *phdevnotify = ::RegisterDeviceNotification(_ssh, pvNotificationFilter,
  789. dwFlags);
  790. }
  791. else
  792. {
  793. dwFlags |= DEVICE_NOTIFY_SERVICE_HANDLE;
  794. *phdevnotify = ::RegisterDeviceNotification(_ssh, pvNotificationFilter,
  795. dwFlags);
  796. }
  797. #endif
  798. if (*phdevnotify)
  799. {
  800. TRACE(TF_SHHWDTCTDTCTDETAILED,
  801. TEXT("RegisterDeviceNotification SUCCEEDED: 0x%08X"),
  802. *phdevnotify);
  803. hres = S_OK;
  804. }
  805. else
  806. {
  807. hres = S_FALSE;
  808. }
  809. return hres;
  810. }
  811. // static
  812. HRESULT CHWEventDetectorHelper::Init()
  813. {
  814. _cs.Init();
  815. _fInited = TRUE;
  816. return S_OK;
  817. }
  818. // static
  819. HRESULT CHWEventDetectorHelper::Cleanup()
  820. {
  821. _cs.Enter();
  822. CloseLogFile();
  823. if (_pieo)
  824. {
  825. _pieo->RCRelease();
  826. _pieo = NULL;
  827. }
  828. _fInited = FALSE;
  829. _cs.Leave();
  830. _cs.Delete();
  831. return S_OK;
  832. }
  833. // static
  834. HRESULT CHWEventDetectorHelper::GetImpersonateEveryone(
  835. CImpersonateEveryone** ppieo)
  836. {
  837. HRESULT hr;
  838. *ppieo = NULL;
  839. if (_fInited)
  840. {
  841. _cs.Enter();
  842. if (!_pieo)
  843. {
  844. _pieo = new CImpersonateEveryone();
  845. }
  846. if (_pieo)
  847. {
  848. _pieo->RCAddRef();
  849. *ppieo = _pieo;
  850. hr = S_OK;
  851. }
  852. else
  853. {
  854. hr = E_OUTOFMEMORY;
  855. }
  856. _cs.Leave();
  857. }
  858. else
  859. {
  860. hr = E_UNEXPECTED;
  861. }
  862. return hr;
  863. }
  864. #ifdef DEBUG
  865. void CHWEventDetectorHelper::_DbgAssertValidState()
  866. {
  867. for (DWORD dw = 0; dw < ARRAYSIZE(_rgpnel); ++dw)
  868. {
  869. if (_rgpnel[dw])
  870. {
  871. // Need to disable this since there is 2 services using this data,
  872. // and it is now feasible to have a refcount diff than 1 at the end
  873. // of an operation.
  874. // _rgpnel[dw]->AssertAllElemsRefCount1();
  875. _rgpnel[dw]->AssertNoDuplicate();
  876. }
  877. }
  878. }
  879. #endif
  880. ///////////////////////////////////////////////////////////////////////////////
  881. //
  882. HRESULT CHandleNotifTarget::HNTInitSurpriseRemoval()
  883. {
  884. _fSurpriseRemovalAware = TRUE;
  885. return S_OK;
  886. }
  887. BOOL CHandleNotifTarget::HNTIsSurpriseRemovalAware()
  888. {
  889. return _fSurpriseRemovalAware;
  890. }
  891. CHandleNotifTarget::CHandleNotifTarget() : _fSurpriseRemovalAware(FALSE)
  892. {}
  893. CHandleNotifTarget::~CHandleNotifTarget()
  894. {}
  895. ///////////////////////////////////////////////////////////////////////////////
  896. // Interface enumerator
  897. HRESULT CIntfFillEnum::Next(LPWSTR pszElemName, DWORD cchElemName,
  898. DWORD* pcchRequired)
  899. {
  900. ASSERT (pszElemName && cchElemName && pcchRequired);
  901. HRESULT hr = S_FALSE;
  902. BOOL fFound = FALSE;
  903. while (SUCCEEDED(hr) && !fFound && _pszNextInterface && *_pszNextInterface)
  904. {
  905. // Do we have a filter?
  906. if (_iecb)
  907. {
  908. // Yep
  909. hr = (_iecb)(_pszNextInterface);
  910. }
  911. else
  912. {
  913. hr = S_OK;
  914. }
  915. if (SUCCEEDED(hr))
  916. {
  917. // Was it filtered out?
  918. if (S_FALSE != hr)
  919. {
  920. // No
  921. hr = SafeStrCpyNReq(pszElemName, _pszNextInterface,
  922. cchElemName, pcchRequired);
  923. if (SUCCEEDED(hr))
  924. {
  925. fFound = TRUE;
  926. _pszNextInterface += lstrlen(_pszNextInterface) + 1;
  927. }
  928. }
  929. else
  930. {
  931. // Yes, lopp again
  932. _pszNextInterface += lstrlen(_pszNextInterface) + 1;
  933. }
  934. }
  935. }
  936. return hr;
  937. }
  938. HRESULT CIntfFillEnum::_Init(const GUID* pguidInterface,
  939. INTERFACEENUMFILTERCALLBACK iecb)
  940. {
  941. HRESULT hr;
  942. HMACHINE hMachine = NULL;
  943. ULONG ulSize;
  944. ULONG ulFlags = CM_GET_DEVICE_INTERFACE_LIST_PRESENT;
  945. CONFIGRET cr = CM_Get_Device_Interface_List_Size_Ex(&ulSize,
  946. (GUID*)pguidInterface, NULL, ulFlags, hMachine);
  947. _iecb = iecb;
  948. if ((CR_SUCCESS == cr) && (ulSize > 1))
  949. {
  950. _pszNextInterface = _pszDeviceInterface =
  951. (LPTSTR)LocalAlloc(LPTR, ulSize * sizeof(TCHAR));
  952. if (_pszDeviceInterface)
  953. {
  954. cr = CM_Get_Device_Interface_List_Ex((GUID*)pguidInterface, NULL,
  955. _pszDeviceInterface, ulSize, ulFlags, hMachine);
  956. if (CR_SUCCESS == cr)
  957. {
  958. hr = S_OK;
  959. }
  960. else
  961. {
  962. hr = S_FALSE;
  963. }
  964. }
  965. else
  966. {
  967. hr = E_OUTOFMEMORY;
  968. }
  969. }
  970. else
  971. {
  972. hr = S_FALSE;
  973. }
  974. return hr;
  975. }
  976. CIntfFillEnum::CIntfFillEnum() : _pszDeviceInterface(NULL),
  977. _pszNextInterface(NULL)
  978. {}
  979. CIntfFillEnum::~CIntfFillEnum()
  980. {
  981. if (_pszDeviceInterface)
  982. {
  983. LocalFree((HLOCAL)_pszDeviceInterface);
  984. }
  985. }
  986. ///////////////////////////////////////////////////////////////////////////////
  987. //
  988. HRESULT _MachineIsDocked(BOOL* pfDocked)
  989. {
  990. HRESULT hr;
  991. HW_PROFILE_INFO hpi;
  992. if (GetCurrentHwProfile(&hpi))
  993. {
  994. DWORD dwDockInfo = hpi.dwDockInfo &
  995. (DOCKINFO_DOCKED | DOCKINFO_UNDOCKED);
  996. if ((DOCKINFO_DOCKED | DOCKINFO_UNDOCKED) == dwDockInfo)
  997. {
  998. // Not dockable
  999. *pfDocked = FALSE;
  1000. }
  1001. else
  1002. {
  1003. *pfDocked = (DOCKINFO_DOCKED & dwDockInfo);
  1004. #ifdef DEBUG
  1005. // Make sure we understand how this works
  1006. if (!(*pfDocked))
  1007. {
  1008. ASSERT(DOCKINFO_UNDOCKED & dwDockInfo);
  1009. }
  1010. #endif
  1011. }
  1012. hr = S_OK;
  1013. }
  1014. else
  1015. {
  1016. hr = S_FALSE;
  1017. }
  1018. return hr;
  1019. }
  1020. ///////////////////////////////////////////////////////////////////////////////
  1021. //
  1022. HRESULT _BuildMoniker(LPCWSTR /*pszEventHandler*/, REFCLSID rclsid,
  1023. DWORD dwSessionID, IMoniker** ppmoniker)
  1024. {
  1025. IMoniker* pmonikerClass;
  1026. HRESULT hr = CreateClassMoniker(rclsid, &pmonikerClass);
  1027. *ppmoniker = NULL;
  1028. if (SUCCEEDED(hr))
  1029. {
  1030. IMoniker* pmonikerSession;
  1031. WCHAR szSessionID[30];
  1032. // should be safe
  1033. wsprintf(szSessionID, TEXT("session:%d"), dwSessionID);
  1034. hr = CreateItemMoniker(TEXT("!"), szSessionID, &pmonikerSession);
  1035. if (SUCCEEDED(hr))
  1036. {
  1037. hr = pmonikerClass->ComposeWith(pmonikerSession, FALSE, ppmoniker);
  1038. // Do not Release, we return it!
  1039. pmonikerSession->Release();
  1040. }
  1041. pmonikerClass->Release();
  1042. }
  1043. return hr;
  1044. }
  1045. EXTERN_C HRESULT WINAPI CreateHardwareEventMoniker(REFCLSID clsid, LPCTSTR pszEventHandler, IMoniker **ppmoniker)
  1046. {
  1047. HRESULT hr;
  1048. if (ppmoniker)
  1049. {
  1050. if (pszEventHandler && *pszEventHandler)
  1051. {
  1052. DWORD dwSessionID = NtCurrentPeb()->SessionId;
  1053. hr = _BuildMoniker(pszEventHandler, clsid, dwSessionID, ppmoniker);
  1054. }
  1055. else
  1056. {
  1057. hr = E_INVALIDARG;
  1058. }
  1059. }
  1060. else
  1061. {
  1062. hr = E_POINTER;
  1063. }
  1064. return hr;
  1065. }