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.

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