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.

1357 lines
39 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. UTIL.CPP
  5. Abstract:
  6. Utility functions
  7. Author:
  8. Vlad Sadovsky (vlads) 4-20-97
  9. Revision History:
  10. --*/
  11. //
  12. // Headers
  13. //
  14. #include "precomp.h"
  15. #include "stiexe.h"
  16. #include <windowsx.h>
  17. #include <setupapi.h>
  18. #include <devguid.h>
  19. #include "device.h"
  20. #define PNP_WORKS 1
  21. CONFIGRET
  22. WINAPI
  23. PrivateLocateDevNode(
  24. DEVNODE *pDevNode,
  25. LPTSTR szDevDriver,
  26. LPCTSTR pszDeviceName
  27. );
  28. //
  29. // Code
  30. //
  31. BOOL
  32. IsStillImagePnPMessage(
  33. PDEV_BROADCAST_HDR pDev
  34. )
  35. /*++
  36. Routine Description:
  37. Returns TRUE if devnode is associated with StillImage class of devices
  38. Arguments:
  39. None.
  40. Return Value:
  41. None.
  42. --*/
  43. {
  44. CONFIGRET cr;
  45. TCHAR szClassString[MAX_PATH];
  46. PDEV_BROADCAST_DEVNODE pDevNode = (PDEV_BROADCAST_DEVNODE)pDev;
  47. PDEV_BROADCAST_DEVICEINTERFACE pDevInterface = (PDEV_BROADCAST_DEVICEINTERFACE)pDev;
  48. PDEV_BROADCAST_HANDLE pDevHandle = (PDEV_BROADCAST_HANDLE)pDev;
  49. HKEY hKeyDevice = NULL;
  50. DEVNODE dnDevNode = NULL;
  51. BOOL fRet = FALSE;
  52. ULONG ulType;
  53. DWORD dwSize = 0;
  54. if ( (pDev->dbch_devicetype == DBT_DEVTYP_DEVNODE) && pDevNode ) {
  55. DBG_TRC(("IsStillImagePnPMessage - DeviceType = DEVNODE, "
  56. "verifying if this is our device..."));
  57. dnDevNode = pDevNode->dbcd_devnode;
  58. //
  59. // Nb: CM APIs take number of bytes vs number of characters .
  60. //
  61. dwSize = sizeof(szClassString);
  62. *szClassString = TEXT('\0');
  63. cr = CM_Get_DevNode_Registry_PropertyA(dnDevNode,
  64. CM_DRP_CLASS,
  65. &ulType,
  66. szClassString,
  67. &dwSize,
  68. 0);
  69. DBG_TRC(("IsStillImagePnPMessage::Class name found :%S", szClassString));
  70. if ((CR_SUCCESS != cr) || ( lstrcmpi(szClassString,CLASSNAME) != 0 ) ) {
  71. DBG_WRN(("IsStillImagePnPMessage::Class name did not match"));
  72. return FALSE;
  73. }
  74. //
  75. // Now read class from software key
  76. //
  77. cr = CM_Open_DevNode_Key(dnDevNode,
  78. KEY_READ,
  79. 0,
  80. RegDisposition_OpenExisting,
  81. &hKeyDevice,
  82. CM_REGISTRY_SOFTWARE
  83. );
  84. if (CR_SUCCESS != cr) {
  85. DBG_ERR(("IsStillImagePnPMessage::Failed to open dev node key"));
  86. return FALSE;
  87. }
  88. dwSize = sizeof(szClassString);
  89. if (RegQueryValueEx(hKeyDevice,
  90. REGSTR_VAL_USD_CLASS,
  91. NULL,
  92. NULL,
  93. (UCHAR *)szClassString,
  94. &dwSize) == ERROR_SUCCESS) {
  95. fRet = TRUE;
  96. }
  97. RegCloseKey(hKeyDevice);
  98. /*
  99. if ((CR_SUCCESS != cr) ||
  100. lstrcmpi(STILLIMAGE,szDevNodeClass)
  101. ) {
  102. return FALSE;
  103. }
  104. */
  105. }
  106. else {
  107. fRet = FALSE;
  108. if ( (pDev->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) && pDevInterface) {
  109. DBG_TRC(("IsStillImagePnPMessage - DeviceType = DEVICEINTERFACE, "
  110. "verifying if this is our device..."));
  111. //
  112. // First check if it is our GUID
  113. //
  114. if ( IsEqualIID(pDevInterface->dbcc_classguid,GUID_DEVCLASS_IMAGE)) {
  115. DBG_TRC(("IsStillImagePnPMessage::Class GUID matched for device "
  116. "interface '%ls' - must be ours", pDevInterface->dbcc_name));
  117. return TRUE;
  118. }
  119. TCHAR *pszDevInstance = NULL;
  120. //
  121. // We have the interface name but we need the device instance
  122. // name to call CM_Locate_DevNode.
  123. //
  124. // Notice that this function will return a pointer to allocated
  125. // memory so it must be freed when you are finished using it.
  126. //
  127. ConvertDevInterfaceToDevInstance(&pDevInterface->dbcc_classguid,
  128. pDevInterface->dbcc_name,
  129. &pszDevInstance);
  130. if (pszDevInstance) {
  131. DBG_TRC(("IsStillImagePnPMessage, converted Device Interface '%ls' "
  132. "to Device Instance '%ls'",
  133. pDevInterface->dbcc_name, pszDevInstance));
  134. cr = CM_Locate_DevNode(&dnDevNode,
  135. pszDevInstance,
  136. CM_LOCATE_DEVNODE_NORMAL |
  137. CM_LOCATE_DEVNODE_PHANTOM);
  138. delete [] pszDevInstance;
  139. if (CR_SUCCESS != cr) {
  140. DBG_WRN(("LocateDevNode failed. cr=%x",cr));
  141. return FALSE;
  142. }
  143. else {
  144. DBG_TRC(("IsStillImagePnPMessage - found DevNode for device instance "));
  145. }
  146. }
  147. else {
  148. DBG_WRN(("Failed to Convert Dev Interface to Dev Instance, "
  149. "Last Error = %lu", GetLastError()));
  150. return FALSE;
  151. }
  152. dwSize = sizeof(szClassString);
  153. cr = CM_Get_DevNode_Registry_Property(dnDevNode,
  154. CM_DRP_CLASS,
  155. &ulType,
  156. szClassString,
  157. &dwSize,
  158. 0);
  159. if (CR_SUCCESS != cr) {
  160. DBG_WRN(("ReadRegValue failed for dev node : DevNode(%X) ValName(DRP_CLASS),cr(%X) ",
  161. dnDevNode,
  162. cr));
  163. }
  164. if ((CR_SUCCESS != cr) || (lstrcmpi(szClassString, TEXT("Image")) != 0)) {
  165. return FALSE;
  166. }
  167. else {
  168. DBG_TRC(("IsStillImagePnPMessage - found Class=Image for device "
  169. "interface '%ls'", pDevInterface->dbcc_name));
  170. }
  171. //
  172. // Now read subclass from software key
  173. //
  174. cr = CM_Open_DevNode_Key(dnDevNode,
  175. KEY_READ,
  176. 0,
  177. RegDisposition_OpenExisting,
  178. &hKeyDevice,
  179. CM_REGISTRY_SOFTWARE
  180. );
  181. if (CR_SUCCESS != cr) {
  182. DBG_WRN(("OpenDevNodeKey failed. cr=%x",cr));
  183. }
  184. if (CR_SUCCESS != cr) {
  185. return FALSE;
  186. }
  187. dwSize = sizeof(szClassString);
  188. if ((RegQueryValueEx(hKeyDevice,
  189. REGSTR_VAL_SUBCLASS,
  190. NULL,
  191. NULL,
  192. (UCHAR *)szClassString,
  193. &dwSize) == ERROR_SUCCESS) &&
  194. (lstrcmpi(szClassString, STILLIMAGE) == 0)) {
  195. fRet = TRUE;
  196. DBG_TRC(("IsStillImagePnPMessage - found SubClass=StillImage for "
  197. "device interface '%ls'. This is a still image device.",
  198. pDevInterface->dbcc_name));
  199. // Skip this one.
  200. //
  201. }
  202. RegCloseKey(hKeyDevice);
  203. return fRet;
  204. }
  205. else if ( (pDev->dbch_devicetype == DBT_DEVTYP_HANDLE ) && pDevHandle) {
  206. //
  207. // Targeted broadcasts are ours always because we don't register on service window
  208. // for any other targeted notifications.
  209. // Otherwise we would need to match embedded handle vs list of devices waiting for
  210. // notifications
  211. //
  212. DBG_TRC(("IsStillImagePnPMessage - DeviceType = HANDLE - this event "
  213. "is ours for sure"));
  214. return TRUE;
  215. }
  216. }
  217. return fRet;
  218. } // IsStillImageMessage
  219. BOOL
  220. GetDeviceNameFromDevBroadcast(
  221. DEV_BROADCAST_HEADER *psDevBroadcast,
  222. DEVICE_BROADCAST_INFO *pBufDevice
  223. )
  224. /*++
  225. Routine Description:
  226. Return device name , used for opening device , obtained from dev node
  227. Arguments:
  228. None.
  229. Return Value:
  230. None.
  231. Caveats:
  232. Relies on the fact that STI names are identical to internal device names
  233. used by PnP subsystem
  234. --*/
  235. {
  236. USES_CONVERSION;
  237. PDEV_BROADCAST_DEVICEINTERFACE pDevInterface = (PDEV_BROADCAST_DEVICEINTERFACE)psDevBroadcast;
  238. PDEV_BROADCAST_HANDLE pDevHandle = (PDEV_BROADCAST_HANDLE)psDevBroadcast;
  239. PDEV_BROADCAST_DEVNODE pDevNode = (PDEV_BROADCAST_DEVNODE)psDevBroadcast;
  240. TCHAR szDevNodeDriver[STI_MAX_INTERNAL_NAME_LENGTH] = {0};
  241. BOOL bSuccess = TRUE;
  242. CONFIGRET cr = CR_SUCCESS;
  243. ULONG ulType = 0;
  244. DEVNODE dnDevNode = NULL;
  245. DWORD dwSize = 0;
  246. TCHAR *pszDevInstance = NULL;
  247. HKEY hkDevice = NULL;
  248. LONG lResult = ERROR_SUCCESS;
  249. DWORD dwType = REG_SZ;
  250. ACTIVE_DEVICE *pDeviceObject = NULL;
  251. switch (psDevBroadcast->dbcd_devicetype) {
  252. case DBT_DEVTYP_DEVNODE:
  253. DBG_WRN(("GetDeviceNameFromDevBroadcast, devicetype = DEVNODE"));
  254. dnDevNode = pDevNode->dbcd_devnode;
  255. //
  256. // Get proper device ID from registry.
  257. //
  258. if (bSuccess) {
  259. cr = CM_Open_DevNode_Key_Ex(dnDevNode,
  260. KEY_READ,
  261. 0,
  262. RegDisposition_OpenExisting,
  263. &hkDevice,
  264. CM_REGISTRY_SOFTWARE,
  265. NULL);
  266. if ((cr != CR_SUCCESS) || (hkDevice == NULL)) {
  267. DBG_WRN(("CM_Open_DevNode_Key_Ex failed. cr=0x%x",cr));
  268. bSuccess = FALSE;
  269. }
  270. }
  271. if (bSuccess) {
  272. dwType = REG_SZ;
  273. dwSize = sizeof(szDevNodeDriver);
  274. lResult = RegQueryValueEx(hkDevice,
  275. REGSTR_VAL_DEVICE_ID,
  276. 0,
  277. &dwType,
  278. (LPBYTE) szDevNodeDriver,
  279. &dwSize);
  280. if (lResult != ERROR_SUCCESS) {
  281. DBG_WRN(("RegQueryValueExA failed. lResult=0x%x",lResult));
  282. bSuccess = FALSE;
  283. }
  284. }
  285. if (bSuccess) {
  286. pBufDevice->m_strDeviceName.CopyString(szDevNodeDriver);
  287. DBG_WRN(("GetDeviceNameFromDevBroadcast::returning device name %S",
  288. szDevNodeDriver));
  289. }
  290. //
  291. // Close device registry key first.
  292. //
  293. if (hkDevice) {
  294. RegCloseKey(hkDevice);
  295. hkDevice = NULL;
  296. }
  297. break;
  298. case DBT_DEVTYP_HANDLE:
  299. DBG_WRN(("GetDeviceNameFromDevBroadcast, devicetype = HANDLE"));
  300. //
  301. // This is directed device broadcast.
  302. // We need to locate device object by embedded handles and
  303. // extract STI name from it
  304. //
  305. if (bSuccess) {
  306. pDeviceObject = g_pDevMan->LookDeviceFromPnPHandles(pDevHandle->dbch_handle,
  307. pDevHandle->dbch_hdevnotify);
  308. if (pDeviceObject) {
  309. pBufDevice->m_strDeviceName.CopyString(W2T(pDeviceObject->GetDeviceID()));
  310. pDeviceObject->Release();
  311. bSuccess = TRUE;
  312. }
  313. else {
  314. bSuccess = FALSE;
  315. DBG_WRN(("GetDeviceNameFromDevBroadcast, DBT_DEVTYP_HANDLE: LookupDeviceByPnPHandles failed"));
  316. }
  317. }
  318. break;
  319. case DBT_DEVTYP_DEVICEINTERFACE:
  320. DBG_WRN(("GetDeviceNameFromDevBroadcast, devicetype = DEVICEINTERFACE"));
  321. //
  322. // We are given a device interface.
  323. // Convert this device interface into a device instance.
  324. //
  325. if (bSuccess) {
  326. ConvertDevInterfaceToDevInstance(&pDevInterface->dbcc_classguid,
  327. pDevInterface->dbcc_name,
  328. &pszDevInstance);
  329. if (pszDevInstance == NULL) {
  330. bSuccess = FALSE;
  331. DBG_WRN(("Failed to Convert Dev Interface to Dev Instance, "
  332. "Last Error = %lu", GetLastError()));
  333. }
  334. }
  335. if (bSuccess) {
  336. //
  337. // Given the device instance, locate the DevNode associated
  338. // with this device instace.
  339. //
  340. cr = CM_Locate_DevNode(&dnDevNode,
  341. pszDevInstance,
  342. CM_LOCATE_DEVNODE_NORMAL |
  343. CM_LOCATE_DEVNODE_PHANTOM);
  344. delete [] pszDevInstance;
  345. if (cr != CR_SUCCESS) {
  346. DBG_WRN(("LocateDevNode failed. cr=%x",cr));
  347. bSuccess = FALSE;
  348. }
  349. }
  350. //
  351. // Get proper device ID from registry. By the time we reach here,
  352. // we've already checked that our dnDevNode is valid.
  353. //
  354. if (bSuccess) {
  355. cr = CM_Open_DevNode_Key_Ex(dnDevNode,
  356. KEY_READ,
  357. 0,
  358. RegDisposition_OpenExisting,
  359. &hkDevice,
  360. CM_REGISTRY_SOFTWARE,
  361. NULL);
  362. if ((cr != CR_SUCCESS) || (hkDevice == NULL)) {
  363. DBG_WRN(("CM_Open_DevNode_Key_Ex failed. cr=0x%x",cr));
  364. bSuccess = FALSE;
  365. }
  366. }
  367. if (bSuccess) {
  368. dwType = REG_SZ;
  369. dwSize = sizeof(szDevNodeDriver);
  370. lResult = RegQueryValueEx(hkDevice,
  371. REGSTR_VAL_DEVICE_ID,
  372. 0,
  373. &dwType,
  374. (LPBYTE)szDevNodeDriver,
  375. &dwSize);
  376. if (lResult != ERROR_SUCCESS) {
  377. DBG_WRN(("RegQueryValueEx failed. lResult=0x%x", lResult));
  378. bSuccess = FALSE;
  379. }
  380. }
  381. if (bSuccess) {
  382. pBufDevice->m_strDeviceName.CopyString(szDevNodeDriver);
  383. DBG_TRC(("GetDeviceNameFromDevBroadcast, returning Driver ID '%ls'", szDevNodeDriver));
  384. }
  385. //
  386. // Close device registry key first.
  387. //
  388. if (hkDevice) {
  389. RegCloseKey(hkDevice);
  390. hkDevice = NULL;
  391. }
  392. break;
  393. default:
  394. DBG_WRN(("GetDeviceNameFromDevBroadcast, received unrecognized "
  395. "dbcd_devicetype = '%lu'", psDevBroadcast->dbcd_devicetype ));
  396. break;
  397. }
  398. return bSuccess;
  399. } // GetDeviceNameFromDevBroadcast
  400. BOOL
  401. ConvertDevInterfaceToDevInstance(const GUID *pClassGUID,
  402. const TCHAR *pszDeviceInterface,
  403. TCHAR **ppszDeviceInstance)
  404. {
  405. HDEVINFO hDevInfo = NULL;
  406. BOOL bSuccess = TRUE;
  407. SP_INTERFACE_DEVICE_DATA InterfaceDeviceData;
  408. SP_DEVINFO_DATA DevInfoData;
  409. DWORD dwDetailSize = 0;
  410. DWORD dwError = NOERROR;
  411. DWORD dwInstanceSize = 0;
  412. CONFIGRET ConfigResult = CR_SUCCESS;
  413. ASSERT(pClassGUID != NULL);
  414. ASSERT(pszDeviceInterface != NULL);
  415. ASSERT(ppszDeviceInstance != NULL);
  416. if ((pClassGUID == NULL) ||
  417. (pszDeviceInterface == NULL) ||
  418. (ppszDeviceInstance == NULL)) {
  419. return FALSE;
  420. }
  421. //
  422. // Create a devinfo list without any specific class.
  423. //
  424. hDevInfo = SetupDiGetClassDevs(pClassGUID,
  425. NULL,
  426. NULL,
  427. DIGCF_DEVICEINTERFACE);
  428. if (hDevInfo == INVALID_HANDLE_VALUE) {
  429. dwError = GetLastError();
  430. DBG_ERR(("ConvertDevInterfaceToDevInstance, SetupDiGetClassDevs "
  431. "returned an error, LastError = %lu", dwError));
  432. return FALSE;
  433. }
  434. memset(&InterfaceDeviceData, 0, sizeof(SP_INTERFACE_DEVICE_DATA));
  435. InterfaceDeviceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
  436. InterfaceDeviceData.Flags = DIGCF_DEVICEINTERFACE;
  437. if (bSuccess) {
  438. bSuccess = SetupDiOpenDeviceInterface(hDevInfo, pszDeviceInterface, 0, &InterfaceDeviceData);
  439. if (!bSuccess) {
  440. dwError = GetLastError();
  441. DBG_ERR(("ConvertDevInterfaceToDevInstance, SetupDiOpenDeviceInterface failed, "
  442. "Last Error = %lu", dwError));
  443. }
  444. }
  445. if (bSuccess) {
  446. memset(&DevInfoData, 0, sizeof(SP_DEVINFO_DATA));
  447. DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  448. bSuccess = SetupDiGetDeviceInterfaceDetail(hDevInfo,
  449. &InterfaceDeviceData,
  450. NULL,
  451. 0,
  452. &dwDetailSize,
  453. &DevInfoData);
  454. if (!bSuccess) {
  455. dwError = GetLastError();
  456. //
  457. // We don't care if we received an insufficient buffer. We are
  458. // only interested in the devinst field in this buffer anyway,
  459. // which is returned to us even on this error.
  460. //
  461. if (dwError == ERROR_INSUFFICIENT_BUFFER) {
  462. bSuccess = TRUE;
  463. dwError = NOERROR;
  464. }
  465. else {
  466. DBG_ERR(("ConvertDevInterfaceToDevInstance, SetupDiGetDeviceInterfaceDetail "
  467. "returned an error, LastError = %lu", dwError));
  468. }
  469. }
  470. }
  471. if (bSuccess) {
  472. ConfigResult = CM_Get_Device_ID_Size_Ex(&dwInstanceSize,
  473. DevInfoData.DevInst,
  474. 0,
  475. NULL);
  476. if (ConfigResult != CR_SUCCESS) {
  477. DBG_ERR(("ConvertDevInterfaceToDevInstance, CM_Get_DeviceID_Size_Ex "
  478. "returned an error, ConfigResult = %lu", ConfigResult));
  479. bSuccess = FALSE;
  480. }
  481. }
  482. if (bSuccess) {
  483. *ppszDeviceInstance = new TCHAR[(dwInstanceSize + 1) * sizeof(TCHAR)];
  484. if (*ppszDeviceInstance == NULL) {
  485. bSuccess = FALSE;
  486. DBG_ERR(("ConvertDevInterfaceToDevInstance, memory alloc failure"));
  487. }
  488. }
  489. if (bSuccess) {
  490. memset(*ppszDeviceInstance, 0, (dwInstanceSize + 1) * sizeof(TCHAR));
  491. ConfigResult = CM_Get_Device_ID(DevInfoData.DevInst,
  492. *ppszDeviceInstance,
  493. dwInstanceSize + 1,
  494. 0);
  495. if (ConfigResult == CR_SUCCESS) {
  496. DBG_WRN(("ConvertDevInterfaceToDevInstance successfully converted "
  497. "Interface '%ls' to Instance '%ls'",
  498. pszDeviceInterface, *ppszDeviceInstance));
  499. bSuccess = TRUE;
  500. }
  501. else {
  502. DBG_ERR(("ConvertDevInterfaceToDevInstance, CM_Get_Device_ID "
  503. "returned an error, ConfigResult = %lu", ConfigResult));
  504. delete [] *ppszDeviceInstance;
  505. *ppszDeviceInstance = NULL;
  506. bSuccess = FALSE;
  507. }
  508. }
  509. if (hDevInfo) {
  510. SetupDiDestroyDeviceInfoList(hDevInfo);
  511. }
  512. return bSuccess;
  513. }
  514. BOOL
  515. GetDeviceNameFromDevNode(
  516. DEVNODE dnDevNode,
  517. StiCString& strDeviceName
  518. )
  519. /*++
  520. Routine Description:
  521. Return device name , used for opening device , obtained from dev node
  522. Arguments:
  523. None.
  524. Return Value:
  525. None.
  526. Caveats:
  527. Relies on the fact that STI names are identical to internal device names
  528. used by PnP subsystem
  529. --*/
  530. {
  531. USES_CONVERSION;
  532. CONFIGRET cr = 1;
  533. DWORD cbLen,dwSize;
  534. CHAR szDevNodeDriver[MAX_PATH];
  535. ULONG ulType;
  536. #ifndef WINNT
  537. //
  538. // Get value from config manager
  539. //
  540. dwSize = sizeof(szDevNodeDriver);
  541. *szDevNodeDriver = TEXT('\0');
  542. cr = CM_Get_DevNode_Registry_PropertyA(dnDevNode,
  543. CM_DRP_DRIVER,
  544. &ulType,
  545. szDevNodeDriver,
  546. &dwSize,
  547. 0);
  548. if (CR_SUCCESS != cr) {
  549. return FALSE;
  550. }
  551. strDeviceName.CopyString(A2CT(szDevNodeDriver));
  552. return TRUE;
  553. #else
  554. #pragma message("Routine not implemented on NT!")
  555. return FALSE;
  556. #endif
  557. } // GetDeviceNameFromDevNode
  558. CONFIGRET
  559. WINAPI
  560. PrivateLocateDevNode(
  561. DEVNODE *pDevNode,
  562. LPTSTR szDevDriver,
  563. LPCTSTR pszDeviceName
  564. )
  565. /*++
  566. Routine Description:
  567. Locate internal STI name for device by broadcased name
  568. Arguments:
  569. Return Value:
  570. CR - defined return values
  571. Caveats:
  572. Relies on the fact that STI names are identical to internal device names
  573. used by PnP subsystem
  574. --*/
  575. {
  576. CONFIGRET cmRet = CR_NO_SUCH_DEVINST;
  577. #ifdef WINNT
  578. HANDLE hDevInfo;
  579. SP_DEVINFO_DATA spDevInfoData;
  580. SP_DEVICE_INTERFACE_DATA spDevInterfaceData;
  581. PSP_DEVICE_INTERFACE_DETAIL_DATA pspDevInterfaceDetailData;
  582. BUFFER bufDetailData;
  583. //char szDevClass[32];
  584. ULONG cbData;
  585. GUID guidClass = GUID_DEVCLASS_IMAGE;
  586. DWORD dwRequired;
  587. DWORD dwSize;
  588. DWORD Idx;
  589. DWORD dwError;
  590. BOOL fRet;
  591. dwRequired = 0;
  592. bufDetailData.Resize(sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) +
  593. MAX_PATH * sizeof(TCHAR) +
  594. 16
  595. );
  596. pspDevInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) bufDetailData.QueryPtr();
  597. if (!pspDevInterfaceDetailData) {
  598. return CR_OUT_OF_MEMORY;
  599. }
  600. hDevInfo = SetupDiGetClassDevs (&guidClass,
  601. NULL,
  602. NULL,
  603. //DIGCF_PRESENT |
  604. DIGCF_DEVICEINTERFACE
  605. );
  606. if (hDevInfo != INVALID_HANDLE_VALUE) {
  607. ZeroMemory(&spDevInfoData,sizeof(spDevInfoData));
  608. spDevInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
  609. spDevInfoData.ClassGuid = GUID_DEVCLASS_IMAGE;
  610. pspDevInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) bufDetailData.QueryPtr();
  611. for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++) {
  612. ZeroMemory(&spDevInterfaceData,sizeof(spDevInterfaceData));
  613. spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  614. spDevInterfaceData.InterfaceClassGuid = GUID_DEVCLASS_IMAGE;
  615. fRet = SetupDiEnumDeviceInterfaces (hDevInfo,
  616. NULL,
  617. &guidClass,
  618. Idx,
  619. &spDevInterfaceData);
  620. dwError = ::GetLastError();
  621. if (!fRet) {
  622. //
  623. // Failed - assume we are done with all devices of the class
  624. //
  625. break;
  626. }
  627. dwRequired = 0;
  628. pspDevInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  629. fRet = SetupDiGetDeviceInterfaceDetail(hDevInfo,
  630. &spDevInterfaceData,
  631. pspDevInterfaceDetailData,
  632. bufDetailData.QuerySize(),
  633. &dwRequired,
  634. &spDevInfoData);
  635. dwError = ::GetLastError();
  636. if (!fRet) {
  637. continue;
  638. }
  639. if (lstrcmpi(pspDevInterfaceDetailData->DevicePath,pszDeviceName) == 0 ) {
  640. *szDevDriver = TEXT('\0');
  641. dwSize = cbData = STI_MAX_INTERNAL_NAME_LENGTH;
  642. //
  643. *pDevNode =spDevInfoData.DevInst;
  644. fRet = SetupDiGetDeviceRegistryProperty (hDevInfo,
  645. &spDevInfoData,
  646. SPDRP_DRIVER,
  647. NULL,
  648. (LPBYTE)szDevDriver,
  649. STI_MAX_INTERNAL_NAME_LENGTH,
  650. &cbData
  651. );
  652. dwError = ::GetLastError();
  653. cmRet = ( fRet ) ? CR_SUCCESS : CR_OUT_OF_MEMORY;
  654. break;
  655. }
  656. }
  657. //
  658. SetupDiDestroyDeviceInfoList (hDevInfo);
  659. }
  660. #endif
  661. return cmRet;
  662. }
  663. /*
  664. < if (CM_Get_DevNode_Key( phwi -> dn, NULL, szDevNodeCfg,
  665. < sizeof( szDevNodeCfg ),
  666. < CM_REGISTRY_SOFTWARE ))
  667. */
  668. #define ctchGuid (1 + 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
  669. LPCTSTR
  670. _ParseHex(
  671. LPCTSTR ptsz,
  672. LPBYTE *ppb,
  673. int cb,
  674. TCHAR tchDelim
  675. )
  676. /*++
  677. Routine Description:
  678. Arguments:
  679. None.
  680. Return Value:
  681. None.
  682. --*/
  683. {
  684. if (ptsz) {
  685. int i = cb * 2;
  686. DWORD dwParse = 0;
  687. do {
  688. DWORD uch;
  689. uch = (TBYTE)*ptsz - TEXT('0');
  690. if (uch < 10) { /* a decimal digit */
  691. } else {
  692. uch = (*ptsz | 0x20) - TEXT('a');
  693. if (uch < 6) { /* a hex digit */
  694. uch += 10;
  695. } else {
  696. return 0; /* Parse error */
  697. }
  698. }
  699. dwParse = (dwParse << 4) + uch;
  700. ptsz++;
  701. } while (--i);
  702. if (tchDelim && *ptsz++ != tchDelim) return 0; /* Parse error */
  703. for (i = 0; i < cb; i++) {
  704. (*ppb)[i] = ((LPBYTE)&dwParse)[i];
  705. }
  706. *ppb += cb;
  707. }
  708. return ptsz;
  709. } // _ParseHex
  710. BOOL
  711. ParseGUID(
  712. LPGUID pguid,
  713. LPCTSTR ptsz
  714. )
  715. /*++
  716. Routine Description:
  717. Parses GUID value from strin representation
  718. Arguments:
  719. None.
  720. Return Value:
  721. None.
  722. --*/
  723. {
  724. if (lstrlen(ptsz) == ctchGuid - 1 && *ptsz == TEXT('{')) {
  725. ptsz++;
  726. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 4, TEXT('-'));
  727. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 2, TEXT('-'));
  728. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 2, TEXT('-'));
  729. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
  730. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, TEXT('-'));
  731. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
  732. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
  733. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
  734. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
  735. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
  736. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, TEXT('}'));
  737. return ( (ptsz == NULL ) ? FALSE : TRUE);
  738. } else {
  739. return 0;
  740. }
  741. } // ParseGUID
  742. BOOL
  743. IsSetupInProgressMode(
  744. BOOL *pUpgradeFlag // = NULL
  745. )
  746. /*++
  747. Routine Description:
  748. IsSetupInProgressMode
  749. Arguments:
  750. Pointer to the flag, receiving InUpgrade value
  751. Return Value:
  752. TRUE - setup is in progress
  753. FALSE - not
  754. Side effects:
  755. --*/
  756. {
  757. LPCTSTR szKeyName = TEXT("SYSTEM\\Setup");
  758. DWORD dwType, dwSize;
  759. HKEY hKeySetup;
  760. DWORD dwSystemSetupInProgress,dwUpgradeInProcess;
  761. LONG lResult;
  762. DBG_FN(IsSetupInProgressMode);
  763. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, szKeyName, 0,
  764. KEY_READ, &hKeySetup) == ERROR_SUCCESS) {
  765. dwSize = sizeof(DWORD);
  766. lResult = RegQueryValueEx (hKeySetup, TEXT("SystemSetupInProgress"), NULL,
  767. &dwType, (LPBYTE) &dwSystemSetupInProgress, &dwSize);
  768. if (lResult == ERROR_SUCCESS) {
  769. lResult = RegQueryValueEx (hKeySetup, TEXT("UpgradeInProgress"), NULL,
  770. &dwType, (LPBYTE) &dwUpgradeInProcess, &dwSize);
  771. if (lResult == ERROR_SUCCESS) {
  772. DBG_TRC(("[IsInSetupUpgradeMode] dwSystemSetupInProgress =%d, dwUpgradeInProcess=%d ",
  773. dwSystemSetupInProgress,dwUpgradeInProcess));
  774. if( pUpgradeFlag ) {
  775. *pUpgradeFlag = dwUpgradeInProcess ? TRUE : FALSE;
  776. }
  777. if (dwSystemSetupInProgress != 0) {
  778. return TRUE;
  779. }
  780. }
  781. }
  782. RegCloseKey (hKeySetup);
  783. }
  784. return FALSE ;
  785. }
  786. BOOL WINAPI
  787. AuxFormatStringV(
  788. IN LPTSTR lpszStr,
  789. ...
  790. )
  791. /*++
  792. Routine Description:
  793. Arguments:
  794. None.
  795. Return Value:
  796. None.
  797. --*/
  798. {
  799. DWORD cch;
  800. LPTSTR pchBuff = NULL;
  801. BOOL fRet = FALSE;
  802. DWORD dwErr;
  803. va_list va;
  804. va_start(va,lpszStr);
  805. pchBuff = (LPTSTR)::LocalAlloc(LPTR,1024);
  806. if (!pchBuff) {
  807. return FALSE;
  808. }
  809. cch = ::FormatMessage( //FORMAT_MESSAGE_ALLOCATE_BUFFER |
  810. FORMAT_MESSAGE_FROM_STRING,
  811. lpszStr,
  812. 0L,
  813. 0,
  814. (LPTSTR) pchBuff,
  815. 1024 / sizeof(TCHAR),
  816. &va);
  817. dwErr = ::GetLastError();
  818. if ( cch ) {
  819. ::lstrcpy(lpszStr,(LPCTSTR) pchBuff );
  820. }
  821. if (pchBuff) {
  822. ::LocalFree( (VOID*) pchBuff );
  823. }
  824. return fRet;
  825. } // AuxFormatStringV
  826. BOOL WINAPI
  827. IsPlatformNT()
  828. {
  829. OSVERSIONINFOA ver;
  830. BOOL bReturn = FALSE;
  831. ZeroMemory(&ver,sizeof(ver));
  832. ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
  833. // Just always call the ANSI function
  834. if(!GetVersionExA(&ver)) {
  835. bReturn = FALSE;
  836. }
  837. else {
  838. switch(ver.dwPlatformId) {
  839. case VER_PLATFORM_WIN32_WINDOWS:
  840. bReturn = FALSE;
  841. break;
  842. case VER_PLATFORM_WIN32_NT:
  843. bReturn = TRUE;
  844. break;
  845. default:
  846. bReturn = FALSE;
  847. break;
  848. }
  849. }
  850. return bReturn;
  851. } // endproc IsPlatformNT
  852. void
  853. WINAPI
  854. StiLogTrace(
  855. DWORD dwType,
  856. LPTSTR lpszMessage,
  857. ...
  858. )
  859. {
  860. va_list list;
  861. va_start (list, lpszMessage);
  862. if(g_StiFileLog) {
  863. g_StiFileLog->vReportMessage(dwType,lpszMessage,list);
  864. // NOTE : This will soon be replaced by WIA logging
  865. if(g_StiFileLog->QueryReportMode() & STI_TRACE_LOG_TOUI) {
  866. #ifdef SHOWMONUI
  867. vStiMonWndDisplayOutput(lpszMessage,list);
  868. #endif
  869. }
  870. }
  871. va_end(list);
  872. }
  873. void
  874. WINAPI
  875. StiLogTrace(
  876. DWORD dwType,
  877. DWORD idMessage,
  878. ...
  879. )
  880. {
  881. va_list list;
  882. va_start (list, idMessage);
  883. if (g_StiFileLog && (g_StiFileLog->IsValid()) ) {
  884. TCHAR *pchBuff = NULL;
  885. DWORD cch;
  886. pchBuff = NULL;
  887. cch = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  888. FORMAT_MESSAGE_MAX_WIDTH_MASK |
  889. FORMAT_MESSAGE_FROM_HMODULE,
  890. GetModuleHandle(NULL),
  891. idMessage,
  892. 0,
  893. (LPTSTR) &pchBuff,
  894. 1024,
  895. (va_list *)&list
  896. );
  897. if (cch) {
  898. g_StiFileLog->vReportMessage(dwType,pchBuff,list);
  899. }
  900. //
  901. // NOTE: This logging will be replaced shortly by WIA logging
  902. //
  903. if((g_StiFileLog->QueryReportMode() & STI_TRACE_LOG_TOUI) && pchBuff) {
  904. #ifdef SHOWMONUI
  905. vStiMonWndDisplayOutput(pchBuff,list);
  906. #endif
  907. }
  908. if (pchBuff) {
  909. LocalFree(pchBuff);
  910. }
  911. }
  912. va_end(list);
  913. }
  914. #ifdef MAXDEBUG
  915. BOOL
  916. WINAPI
  917. DumpTokenInfo(
  918. LPTSTR pszPrefix,
  919. HANDLE hToken
  920. )
  921. {
  922. BYTE buf[2*MAX_PATH];
  923. TCHAR TextualSid[2*MAX_PATH];
  924. TCHAR szDomain[MAX_PATH];
  925. PTOKEN_USER ptgUser = (PTOKEN_USER)buf;
  926. DWORD cbBuffer=MAX_PATH;
  927. BOOL bSuccess;
  928. PSID pSid;
  929. PSID_IDENTIFIER_AUTHORITY psia;
  930. SID_NAME_USE SidUse;
  931. DWORD dwSubAuthorities;
  932. DWORD dwCounter;
  933. DWORD cchSidCopy;
  934. DWORD cchSidSize = sizeof(TextualSid);
  935. DWORD cchDomSize = sizeof(szDomain);
  936. DBG_WRN((("Dumping token information for %S"),pszPrefix));
  937. if ((hToken == NULL) || ( hToken == INVALID_HANDLE_VALUE)) {
  938. return FALSE;
  939. }
  940. bSuccess = GetTokenInformation(
  941. hToken, // identifies access token
  942. TokenUser, // TokenUser info type
  943. ptgUser, // retrieved info buffer
  944. cbBuffer, // size of buffer passed-in
  945. &cbBuffer // required buffer size
  946. );
  947. if(!bSuccess) {
  948. DBG_WRN(("Failed to get token info"));
  949. return FALSE;
  950. }
  951. pSid = ptgUser->User.Sid;
  952. //
  953. // test if Sid passed in is valid
  954. //
  955. if(!IsValidSid(pSid)) {
  956. DBG_WRN(("SID is not valid"));
  957. return FALSE;
  958. }
  959. #if 0
  960. // obtain SidIdentifierAuthority
  961. psia = GetSidIdentifierAuthority(pSid);
  962. // obtain sidsubauthority count
  963. dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
  964. //
  965. // compute approximate buffer length
  966. // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL
  967. //
  968. cchSidCopy = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
  969. //
  970. // check provided buffer length.
  971. // If not large enough, indicate proper size and setlasterror
  972. //
  973. if(cchSidSize < cchSidCopy) {
  974. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  975. return FALSE;
  976. }
  977. //
  978. // prepare S-SID_REVISION-
  979. //
  980. cchSidCopy = wsprintf(TextualSid, TEXT("S-%lu-"), SID_REVISION );
  981. //
  982. // prepare SidIdentifierAuthority
  983. //
  984. if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) {
  985. cchSidCopy += wsprintf(TextualSid + cchSidCopy,
  986. TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
  987. (USHORT)psia->Value[0],
  988. (USHORT)psia->Value[1],
  989. (USHORT)psia->Value[2],
  990. (USHORT)psia->Value[3],
  991. (USHORT)psia->Value[4],
  992. (USHORT)psia->Value[5]);
  993. } else {
  994. cchSidCopy += wsprintf(TextualSid + cchSidCopy,
  995. TEXT("%lu"),
  996. (ULONG)(psia->Value[5] ) +
  997. (ULONG)(psia->Value[4] << 8) +
  998. (ULONG)(psia->Value[3] << 16) +
  999. (ULONG)(psia->Value[2] << 24) );
  1000. }
  1001. //
  1002. // loop through SidSubAuthorities
  1003. //
  1004. for(dwCounter = 0 ; dwCounter < dwSubAuthorities ; dwCounter++) {
  1005. cchSidCopy += wsprintf(TextualSid + cchSidCopy, TEXT("-%lu"),
  1006. *GetSidSubAuthority(pSid, dwCounter) );
  1007. }
  1008. DBG_WRN(("Textual SID: %s"),TextualSid);
  1009. #endif
  1010. cchSidSize = sizeof(TextualSid);
  1011. cchDomSize = sizeof(szDomain);
  1012. bSuccess = LookupAccountSid(NULL,
  1013. pSid,
  1014. TextualSid,
  1015. &cchSidSize,
  1016. szDomain,
  1017. &cchDomSize,
  1018. &SidUse
  1019. );
  1020. if (!bSuccess) {
  1021. DBG_WRN((("Failed to lookup SID . Lasterror: %d"), GetLastError()));
  1022. return FALSE;
  1023. }
  1024. DBG_WRN((("Looked up user account: Domain:%S User: %S Use:%d "), szDomain, TextualSid, SidUse));
  1025. return TRUE;
  1026. }
  1027. #endif