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.

900 lines
30 KiB

  1. //=================================================================
  2. //
  3. // Confgmgr.cpp
  4. //
  5. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  6. //
  7. // History:
  8. // 10/17/97 jennymc Created
  9. //
  10. /////////////////////////////////////////////////////////////////////////
  11. #define INITGUID
  12. #include "precomp.h"
  13. #include <cregcls.h>
  14. #include <assertbreak.h>
  15. #include "refptr.h"
  16. #include "poormansresource.h"
  17. #include "resourcedesc.h"
  18. #include "cfgmgrdevice.h"
  19. #include "irqdesc.h"
  20. #include "DllUtils.h"
  21. #include "dmadesc.h"
  22. #include <brodcast.h>
  23. #include <lockwrap.h>
  24. #include "strings.h"
  25. #include <smartptr.h>
  26. #include <devguid.h>
  27. static CCritSec map;
  28. STRING2GUID CConfigManager::s_ClassMap;
  29. BOOL CConfigManager::s_ClassIsValid = FALSE;
  30. CConfigManager::CConfigManager( DWORD dwTypeToGet )
  31. {
  32. m_dwTypeToGet = dwTypeToGet;
  33. if (!s_ClassIsValid)
  34. {
  35. CLockWrapper t_lockMap( map ) ;
  36. // Check again now that we have the lock
  37. if (!s_ClassIsValid)
  38. {
  39. s_ClassMap[_T("1394")] = GUID_DEVCLASS_1394;
  40. s_ClassMap[_T("ADAPTER")] = GUID_DEVCLASS_ADAPTER;
  41. s_ClassMap[_T("APMSUPPORT")] = GUID_DEVCLASS_APMSUPPORT;
  42. s_ClassMap[_T("BATTERY")] = GUID_DEVCLASS_BATTERY;
  43. s_ClassMap[_T("CDROM")] = GUID_DEVCLASS_CDROM;
  44. s_ClassMap[_T("COMPUTER")] = GUID_DEVCLASS_COMPUTER;
  45. s_ClassMap[_T("DECODER")] = GUID_DEVCLASS_DECODER;
  46. s_ClassMap[_T("DISKDRIVE")] = GUID_DEVCLASS_DISKDRIVE;
  47. s_ClassMap[_T("DISPLAY")] = GUID_DEVCLASS_DISPLAY;
  48. s_ClassMap[_T("FDC")] = GUID_DEVCLASS_FDC;
  49. s_ClassMap[_T("FLOPPYDISK")] = GUID_DEVCLASS_FLOPPYDISK;
  50. s_ClassMap[_T("GPS")] = GUID_DEVCLASS_GPS;
  51. s_ClassMap[_T("HDC")] = GUID_DEVCLASS_HDC;
  52. s_ClassMap[_T("HIDCLASS")] = GUID_DEVCLASS_HIDCLASS;
  53. s_ClassMap[_T("IMAGE")] = GUID_DEVCLASS_IMAGE;
  54. s_ClassMap[_T("INFRARED")] = GUID_DEVCLASS_INFRARED;
  55. s_ClassMap[_T("KEYBOARD")] = GUID_DEVCLASS_KEYBOARD;
  56. s_ClassMap[_T("LEGACYDRIVER")] = GUID_DEVCLASS_LEGACYDRIVER;
  57. s_ClassMap[_T("MEDIA")] = GUID_DEVCLASS_MEDIA;
  58. s_ClassMap[_T("MODEM")] = GUID_DEVCLASS_MODEM;
  59. s_ClassMap[_T("MONITOR")] = GUID_DEVCLASS_MONITOR;
  60. s_ClassMap[_T("MOUSE")] = GUID_DEVCLASS_MOUSE;
  61. s_ClassMap[_T("MTD")] = GUID_DEVCLASS_MTD;
  62. s_ClassMap[_T("MULTIFUNCTION")] = GUID_DEVCLASS_MULTIFUNCTION;
  63. s_ClassMap[_T("MULTIPORTSERIAL")] = GUID_DEVCLASS_MULTIPORTSERIAL;
  64. s_ClassMap[_T("NET")] = GUID_DEVCLASS_NET;
  65. s_ClassMap[_T("NETCLIENT")] = GUID_DEVCLASS_NETCLIENT;
  66. s_ClassMap[_T("NETSERVICE")] = GUID_DEVCLASS_NETSERVICE;
  67. s_ClassMap[_T("NETTRANS")] = GUID_DEVCLASS_NETTRANS;
  68. s_ClassMap[_T("NODRIVER")] = GUID_DEVCLASS_NODRIVER;
  69. s_ClassMap[_T("PCMCIA")] = GUID_DEVCLASS_PCMCIA;
  70. s_ClassMap[_T("PORTS")] = GUID_DEVCLASS_PORTS;
  71. s_ClassMap[_T("PRINTER")] = GUID_DEVCLASS_PRINTER;
  72. s_ClassMap[_T("PRINTERUPGRADE")] = GUID_DEVCLASS_PRINTERUPGRADE;
  73. s_ClassMap[_T("SCSIADAPTER")] = GUID_DEVCLASS_SCSIADAPTER;
  74. s_ClassMap[_T("SMARTCARDREADER")] = GUID_DEVCLASS_SMARTCARDREADER;
  75. s_ClassMap[_T("SOUND")] = GUID_DEVCLASS_SOUND;
  76. s_ClassMap[_T("SYSTEM")] = GUID_DEVCLASS_SYSTEM;
  77. s_ClassMap[_T("TAPEDRIVE")] = GUID_DEVCLASS_TAPEDRIVE;
  78. s_ClassMap[_T("UNKNOWN")] = GUID_DEVCLASS_UNKNOWN;
  79. s_ClassMap[_T("USB")] = GUID_DEVCLASS_USB;
  80. s_ClassMap[_T("VOLUME")] = GUID_DEVCLASS_VOLUME;
  81. s_ClassIsValid = TRUE;
  82. }
  83. }
  84. }
  85. ////////////////////////////////////////////////////////////////////////
  86. //
  87. // Reads the config manager registry keys for win98 and win95
  88. //
  89. ////////////////////////////////////////////////////////////////////////
  90. BOOL CConfigManager::BuildListsForThisDevice(CConfigMgrDevice *pDevice)
  91. {
  92. CResourceCollection resourceList;
  93. CHString sDeviceName, sClass, sKey(_T("Enum\\"));
  94. BOOL fRc = FALSE;
  95. CRegistry RegInfo;
  96. // Extract the device name
  97. sDeviceName = pDevice->GetDeviceDesc();
  98. // Pull the resource list out and enumerate it.
  99. pDevice->GetResourceList( resourceList );
  100. sKey += pDevice->GetHardwareKey();
  101. if (RegInfo.Open(HKEY_LOCAL_MACHINE, sKey, KEY_READ) == ERROR_SUCCESS) {
  102. RegInfo.GetCurrentKeyValue(L"Class", sClass);
  103. }
  104. REFPTR_POSITION pos;
  105. if ( resourceList.BeginEnum( pos ) ){
  106. PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor = NULL;// Watch the scoping on this guy!
  107. DWORD dwCount = 0;
  108. #if NTONLY >= 5
  109. // Go find the resource descriptor for this device
  110. CHString sRegKeyName;
  111. CRegistry Reg;
  112. CSmartBuffer Buffer; // Watch the scoping on this guy!
  113. if ( (Reg.Open(HKEY_LOCAL_MACHINE, L"hardware\\resourcemap\\PnP Manager\\PNPManager", KEY_QUERY_VALUE) == ERROR_SUCCESS) &&
  114. pDevice->GetPhysicalDeviceObjectName(sRegKeyName) )
  115. {
  116. sRegKeyName += L".raw";
  117. DWORD dwValueType;
  118. DWORD dwValueDataSize = Reg.GetLongestValueData() + 2 ;
  119. Buffer = new BYTE[dwValueDataSize];
  120. if ((LPBYTE)Buffer == NULL)
  121. {
  122. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  123. }
  124. if(RegQueryValueEx(Reg.GethKey(), sRegKeyName, NULL,
  125. &dwValueType, (LPBYTE)Buffer, &dwValueDataSize) == ERROR_SUCCESS)
  126. {
  127. if(dwValueType == REG_FULL_RESOURCE_DESCRIPTOR)
  128. {
  129. dwCount = 1 ;
  130. pFullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) (LPBYTE)Buffer ;// Watch the scoping on this guy!
  131. }
  132. else if(dwValueType == REG_RESOURCE_LIST)
  133. {
  134. dwCount = ((PCM_RESOURCE_LIST) (LPBYTE)Buffer)->Count ;
  135. pFullDescriptor = ((PCM_RESOURCE_LIST) (LPBYTE)Buffer)->List ;// Watch the scoping on this guy!
  136. }
  137. }
  138. }
  139. #endif
  140. CHString sResource;
  141. //=========================================================
  142. // For each descriptor we find, if it's not ignored,
  143. // we should get the string data, and place it in the
  144. // appropriate list based on Type.
  145. //=========================================================
  146. CResourceDescriptorPtr pResDesc;
  147. for( pResDesc.Attach(resourceList.GetNext( pos ));
  148. NULL != pResDesc;
  149. pResDesc.Attach(resourceList.GetNext( pos )) )
  150. {
  151. DWORD t_dwResType = pResDesc->GetResourceType();
  152. if ( (!pResDesc->IsIgnored()) &&
  153. ((m_dwTypeToGet == ResType_All) || (m_dwTypeToGet == t_dwResType) ) )
  154. {
  155. switch ( t_dwResType )
  156. {
  157. case ResType_DMA:
  158. DMA_INFO *pDMA_Info;
  159. DMA_DES *pTmp;
  160. pDMA_Info = new DMA_INFO;
  161. if (pDMA_Info != NULL)
  162. {
  163. try
  164. {
  165. DWORD dwChannelWidth;
  166. pTmp = (DMA_DES*) pResDesc->GetResource();
  167. dwChannelWidth = (pTmp->DD_Flags) & 0x0003;
  168. pDMA_Info->ChannelWidth = 0;
  169. if( dwChannelWidth == 0 )
  170. {
  171. pDMA_Info->ChannelWidth = 8;
  172. }
  173. else if( dwChannelWidth == 1 )
  174. {
  175. pDMA_Info->ChannelWidth = 16;
  176. }
  177. else if( dwChannelWidth == 2 )
  178. {
  179. pDMA_Info->ChannelWidth = 32;
  180. }
  181. pDMA_Info->DeviceType = sClass;
  182. pDMA_Info->Channel = pTmp->DD_Alloc_Chan;
  183. pResDesc->GetOwnerDeviceID(pDMA_Info->OwnerDeviceId);
  184. pResDesc->GetOwnerName(pDMA_Info->OwnerName);
  185. pDMA_Info->OEMNumber = pResDesc->GetOEMNumber();
  186. pDMA_Info->Port = GetDMAPort(pFullDescriptor, dwCount, pTmp->DD_Alloc_Chan);
  187. }
  188. catch ( ... )
  189. {
  190. delete pDMA_Info;
  191. throw ;
  192. }
  193. // real DMA channels are in the range 0-7
  194. // sometimes the confug mugger reports channels
  195. // with great big numbers - we don't care
  196. if (pDMA_Info->Channel < 8)
  197. {
  198. try
  199. {
  200. m_List.Add(pDMA_Info);
  201. }
  202. catch ( ... )
  203. {
  204. delete pDMA_Info;
  205. throw ;
  206. }
  207. }
  208. else
  209. {
  210. delete pDMA_Info;
  211. }
  212. }
  213. else
  214. {
  215. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  216. }
  217. break;
  218. case ResType_IRQ:
  219. IRQ_INFO *pIRQ_Info;
  220. IRQ_DES *pTmpIrq;
  221. pIRQ_Info = new IRQ_INFO;
  222. if (pIRQ_Info != NULL)
  223. {
  224. try
  225. {
  226. pTmpIrq = (IRQ_DES*) pResDesc->GetResource();
  227. pIRQ_Info->Shareable = pTmpIrq->IRQD_Flags;
  228. pIRQ_Info->IRQNumber = pTmpIrq->IRQD_Alloc_Num; // Allocated IRQ number
  229. pIRQ_Info->DeviceType = sClass;
  230. pResDesc->GetOwnerDeviceID(pIRQ_Info->OwnerDeviceId);
  231. pResDesc->GetOwnerName(pIRQ_Info->OwnerName);
  232. pIRQ_Info->OEMNumber = pResDesc->GetOEMNumber();
  233. pIRQ_Info->Vector = GetIRQVector(pFullDescriptor, dwCount, pTmpIrq->IRQD_Alloc_Num);
  234. m_List.Add(pIRQ_Info);
  235. }
  236. catch ( ... )
  237. {
  238. delete pIRQ_Info;
  239. throw ;
  240. }
  241. }
  242. else
  243. {
  244. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  245. }
  246. break;
  247. case ResType_IO:
  248. IO_INFO *pIO_Info;
  249. IOWBEM_DES *pTmpIO;
  250. pIO_Info = new IO_INFO;
  251. if (pIO_Info != NULL)
  252. {
  253. try
  254. {
  255. pTmpIO = (IOWBEM_DES*) pResDesc->GetResource();
  256. pIO_Info->DeviceType = sClass;
  257. pIO_Info->StartingAddress = pTmpIO->IOD_Alloc_Base;
  258. pIO_Info->EndingAddress = pTmpIO->IOD_Alloc_End;
  259. pIO_Info->Alias = pTmpIO->IOD_Alloc_Alias;
  260. pIO_Info->Decode = pTmpIO->IOD_Alloc_Decode;
  261. pResDesc->GetOwnerName(pIO_Info->OwnerName);
  262. m_List.Add(pIO_Info);
  263. }
  264. catch ( ... )
  265. {
  266. delete pIO_Info;
  267. throw ;
  268. }
  269. }
  270. else
  271. {
  272. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  273. }
  274. break;
  275. case ResType_Mem:
  276. MEM_INFO *pMem_Info;
  277. MEM_DES *pTmpMem;
  278. pMem_Info = new MEM_INFO;
  279. if (pMem_Info != NULL)
  280. {
  281. try
  282. {
  283. pTmpMem = (MEM_DES*) pResDesc->GetResource();
  284. pMem_Info->DeviceType = sClass;
  285. pMem_Info->StartingAddress = pTmpMem->MD_Alloc_Base;
  286. pMem_Info->EndingAddress = pTmpMem->MD_Alloc_End;
  287. pResDesc->GetOwnerName(pMem_Info->OwnerName);
  288. pMem_Info->MemoryType = GetMemoryType(pFullDescriptor, dwCount, pTmpMem->MD_Alloc_Base);
  289. m_List.Add(pMem_Info);
  290. }
  291. catch ( ... )
  292. {
  293. delete pMem_Info;
  294. throw ;
  295. }
  296. }
  297. else
  298. {
  299. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  300. }
  301. break;
  302. } // SWITCH
  303. } // IF !IsIgnored
  304. } // For EnumResources
  305. resourceList.EndEnum();
  306. } // IF BeginEnum()
  307. return fRc;
  308. }
  309. ////////////////////////////////////////////////////////////////////////
  310. void CConfigManager::ResetList()
  311. {
  312. IO_INFO *pIOInfo;
  313. IRQ_INFO *pIRQInfo;
  314. DMA_INFO *pDMAInfo;
  315. MEM_INFO *pMemInfo;
  316. int nNum = m_List.GetSize();
  317. for( int i=0; i < nNum; i++ ){
  318. switch (m_dwTypeToGet) {
  319. case ResType_DMA:
  320. pDMAInfo = ( DMA_INFO *) m_List.GetAt(i);
  321. delete pDMAInfo;
  322. break;
  323. case ResType_IRQ:
  324. pIRQInfo = ( IRQ_INFO *) m_List.GetAt(i);
  325. delete pIRQInfo;
  326. break;
  327. case ResType_IO:
  328. pIOInfo = ( IO_INFO *) m_List.GetAt(i);
  329. delete pIOInfo;
  330. break;
  331. case ResType_Mem:
  332. pMemInfo = ( MEM_INFO *) m_List.GetAt(i);
  333. delete pMemInfo;
  334. break;
  335. default:
  336. ASSERT_BREAK(0);
  337. break;
  338. }
  339. }
  340. m_List.RemoveAll();
  341. }
  342. ////////////////////////////////////////////////////////////////////////
  343. BOOL CConfigManager::RefreshList()
  344. {
  345. BOOL bRc = FALSE;
  346. //===========================================================
  347. // Reset lists
  348. //===========================================================
  349. ResetList();
  350. // Get all the available devices and check each of them for resources used
  351. CDeviceCollection deviceList;
  352. if ( GetDeviceList( deviceList ) )
  353. {
  354. REFPTR_POSITION pos;
  355. if ( deviceList.BeginEnum( pos ) )
  356. {
  357. CConfigMgrDevicePtr pDevice;
  358. for ( pDevice.Attach(deviceList.GetNext( pos )) ;
  359. pDevice != NULL;
  360. pDevice.Attach(deviceList.GetNext( pos )))
  361. {
  362. BuildListsForThisDevice(pDevice);
  363. }
  364. // For every begin, there is an End
  365. deviceList.EndEnum();
  366. } // BeginEnum
  367. bRc = TRUE;
  368. }
  369. return bRc;
  370. /*
  371. //===========================================================
  372. // Enumerate all
  373. //===========================================================
  374. CRegistry Reg;
  375. CHString sDevice;
  376. if( ERROR_SUCCESS == Reg.OpenAndEnumerateSubKeys(HKEY_DYN_DATA, "Config Manager\\Enum", KEY_READ )){
  377. while( ERROR_SUCCESS == Reg.GetCurrentSubKeyName(sDevice) ){
  378. //===========================================================
  379. // Since we're keeping back pointers to the Device Object,
  380. // new him, rather than keeping him on the stack so we're
  381. // not dependent on the order of destruction as to how
  382. // safe we are.
  383. //===========================================================
  384. CConfigMgrDevice *pDevice = new CConfigMgrDevice(sDevice,m_dwTypeToGet);
  385. if ( NULL != pDevice ){
  386. if( !BuildListsForThisDevice(pDevice) ){
  387. // We're done with this pointer
  388. delete pDevice;
  389. }
  390. // otherwise ptr is deleted after device is added to list
  391. } // IF NULL != pDevice
  392. bRc = TRUE;
  393. if( Reg.NextSubKey() != ERROR_SUCCESS ){
  394. break;
  395. }
  396. }
  397. }
  398. return bRc;
  399. */
  400. }
  401. // valid properties for filtering
  402. //#define CM_DRP_DEVICEDESC (0x00000001) // DeviceDesc REG_SZ property (RW)
  403. //#define CM_DRP_SERVICE (0x00000005) // Service REG_SZ property (RW)
  404. //#define CM_DRP_CLASS (0x00000008) // Class REG_SZ property (RW)
  405. //#define CM_DRP_CLASSGUID (0x00000009) // ClassGUID REG_SZ property (RW)
  406. //#define CM_DRP_DRIVER (0x0000000A) // Driver REG_SZ property (RW)
  407. //#define CM_DRP_MFG (0x0000000C) // Mfg REG_SZ property (RW)
  408. //#define CM_DRP_FRIENDLYNAME (0x0000000D) // FriendlyName REG_SZ property (RW)
  409. //#define CM_DRP_LOCATION_INFORMATION (0x0000000E) // LocationInformation REG_SZ property (RW)
  410. //#define CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME (0x0000000F) // PhysicalDeviceObjectName REG_SZ property (R)
  411. //#define CM_DRP_MIN (0x00000001)
  412. //#define CM_DRP_MAX (0x00000017)
  413. BOOL CConfigManager::GetDeviceList( CDeviceCollection& deviceList, LPCWSTR pszFilter/*=NULL*/, ULONG ulProperty/*=CM_DRP_MAX*/ )
  414. {
  415. CONFIGRET cr = CR_INVALID_POINTER;
  416. // Dump the list first
  417. deviceList.Empty();
  418. DEVNODE dnRoot;
  419. CConfigMgrAPI* t_pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ;
  420. try
  421. {
  422. if ( t_pconfigmgr )
  423. {
  424. if ( t_pconfigmgr->IsValid () )
  425. {
  426. if ( CR_SUCCESS == ( cr = t_pconfigmgr->CM_Locate_DevNode( &dnRoot, NULL, 0 ) ) )
  427. {
  428. DEVNODE dnFirst;
  429. if ( CR_SUCCESS == ( cr = t_pconfigmgr->CM_Get_Child( &dnFirst, dnRoot, 0 ) ) )
  430. {
  431. // This should only fail in case we are unable to allocate a device
  432. if ( !WalkDeviceTree( dnFirst, deviceList, pszFilter, ulProperty, t_pconfigmgr ) )
  433. {
  434. cr = CR_OUT_OF_MEMORY;
  435. }
  436. }
  437. }
  438. CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, t_pconfigmgr ) ;
  439. t_pconfigmgr = NULL ;
  440. }
  441. else
  442. {
  443. ::SetLastError ( t_pconfigmgr->GetCreationError () );
  444. }
  445. }
  446. }
  447. catch ( ... )
  448. {
  449. if ( t_pconfigmgr )
  450. {
  451. CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, t_pconfigmgr ) ;
  452. t_pconfigmgr = NULL ;
  453. }
  454. throw ;
  455. }
  456. return ( CR_SUCCESS == cr );
  457. }
  458. // This device MUST be Released!
  459. BOOL CConfigManager::LocateDevice( LPCWSTR pszDeviceID, CConfigMgrDevicePtr & pCfgMgrDevice )
  460. {
  461. CONFIGRET cr = CR_INVALID_POINTER;
  462. if ( (pszDeviceID != NULL) && (pszDeviceID[0] != L'\0') )
  463. {
  464. CConfigMgrAPI* t_pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ;
  465. try
  466. {
  467. if ( t_pconfigmgr )
  468. {
  469. if ( t_pconfigmgr->IsValid () )
  470. {
  471. DEVNODE dnRoot;
  472. if ( CR_SUCCESS == ( cr = t_pconfigmgr->CM_Locate_DevNode( &dnRoot, bstr_t(pszDeviceID), 0 ) ) )
  473. {
  474. pCfgMgrDevice.Attach(new CConfigMgrDevice( dnRoot, m_dwTypeToGet ));
  475. }
  476. CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, t_pconfigmgr ) ;
  477. t_pconfigmgr = NULL ;
  478. }
  479. else
  480. {
  481. ::SetLastError ( t_pconfigmgr->GetCreationError () );
  482. }
  483. }
  484. }
  485. catch ( ... )
  486. {
  487. if ( t_pconfigmgr )
  488. {
  489. CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, t_pconfigmgr ) ;
  490. t_pconfigmgr = NULL ;
  491. }
  492. throw ;
  493. }
  494. }
  495. return ( CR_SUCCESS == cr );
  496. }
  497. BOOL CConfigManager::WalkDeviceTree( DEVNODE dn, CDeviceCollection& deviceList, LPCWSTR pszFilter, ULONG ulFilterProperty, CConfigMgrAPI *a_pconfigmgr )
  498. {
  499. BOOL fReturn = TRUE;
  500. // While it would make more sense to check the filter in WalkDeviceTree2,
  501. // we can't. Config manager sometimes has a loop in its nodes. As a result,
  502. // we need to be checking the entire list for a loop, so we need to apply
  503. // the filter here.
  504. if ( NULL == pszFilter)
  505. {
  506. // Load ALL the nodes
  507. fReturn = WalkDeviceTree2(dn, deviceList, a_pconfigmgr );
  508. }
  509. else
  510. {
  511. CDeviceCollection deviceList2;
  512. CConfigMgrDevicePtr pDevice;
  513. fReturn = WalkDeviceTree2(dn, deviceList2, a_pconfigmgr );
  514. if (fReturn)
  515. {
  516. // Walk all the nodes looking for ones that match the filter. Copy the matches
  517. // to the passed in array.
  518. CHString strFilterValue;
  519. DWORD dwSize = deviceList2.GetSize();
  520. for (int x=0; x < dwSize; x++)
  521. {
  522. pDevice.Attach(deviceList2.GetAt(x));
  523. // Apply our filter, and save the device pointer to the list only
  524. // if the device property value is the same as the filter.
  525. if ( pDevice->GetStringProperty( ulFilterProperty, strFilterValue ) )
  526. {
  527. if ( strFilterValue.CompareNoCase( pszFilter ) == 0 )
  528. {
  529. fReturn = deviceList.Add( pDevice );
  530. }
  531. }
  532. }
  533. }
  534. }
  535. return fReturn;
  536. }
  537. BOOL CConfigManager::WalkDeviceTree2( DEVNODE dn, CDeviceCollection& deviceList, CConfigMgrAPI *a_pconfigmgr )
  538. {
  539. BOOL fReturn = TRUE; // Assume TRUE, the only failure is where we
  540. // beef allocating a device.
  541. BOOL fIsLoop = FALSE; // Config manager has a bug that causes a loop in device lists<sigh>
  542. CConfigMgrDevicePtr pDevice;
  543. // CHString strFilterValue;
  544. DEVNODE dnSibling,
  545. dnChild;
  546. // We're walking the list for siblings and children. Waliing for siblings
  547. // is done in the context of the following loop, since siblings are at
  548. // the same level in the tree. Walking for children is, of course, recursive.
  549. do
  550. {
  551. // Store siblings, since we will proceed from it to the next
  552. // sibling.
  553. if ( CR_SUCCESS != a_pconfigmgr->CM_Get_Sibling( &dnSibling, dn, 0 ) )
  554. {
  555. dnSibling = NULL;
  556. }
  557. // Allocate a new device, and if it passes through our filter, or if
  558. // there is no filter, go ahead and store the device in the device collection.
  559. pDevice.Attach(new CConfigMgrDevice( dn, m_dwTypeToGet ));
  560. if ( NULL != pDevice )
  561. {
  562. if (deviceList.GetSize() > CFGMGR_WORRY_SIZE)
  563. {
  564. fIsLoop = CheckForLoop(deviceList, pDevice);
  565. }
  566. if (!fIsLoop)
  567. {
  568. // While it would make more sense to check the filter in WalkDeviceTree2,
  569. // we can't. Config manager sometimes has a loop in its nodes. As a result,
  570. // we need to be checking the entire list for a loop, so we need to apply
  571. // the filter here.
  572. fReturn = deviceList.Add( pDevice );
  573. }
  574. } // IF NULL != pszDevice
  575. else
  576. {
  577. // We just beefed on memory, so bail out while the gettin's good
  578. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  579. }
  580. // If we have a child, we must walk recursively.
  581. // Note that fReturn of FALSE supercedes all of this.
  582. if ( fReturn && !fIsLoop && CR_SUCCESS == a_pconfigmgr->CM_Get_Child( &dnChild, dn, 0 ) )
  583. {
  584. fReturn = WalkDeviceTree2( dnChild, deviceList, a_pconfigmgr );
  585. }
  586. // The new active node will be our sibling.
  587. dn = dnSibling;
  588. } while ( fReturn && NULL != dn && !fIsLoop );
  589. return fReturn;
  590. }
  591. // Check to see if pInDevice already exists in deviceList
  592. BOOL CConfigManager::CheckForLoop(CDeviceCollection& deviceList, CConfigMgrDevice *pInDevice)
  593. {
  594. DWORD dwSize, x, y;
  595. BOOL bIsLoop = FALSE;
  596. CConfigMgrDevicePtr pDevice1;
  597. CConfigMgrDevicePtr pDevice2;
  598. // Get the list size
  599. dwSize = deviceList.GetSize()-1;
  600. // If it is in here, it is probably close to the end, let's walk backward
  601. for (x = dwSize; ((x > 0) && (!bIsLoop)); x--)
  602. {
  603. pDevice1.Attach(deviceList.GetAt(x));
  604. // This compares the device nodes (see CConfigMgrDevice)
  605. if (*pDevice1 == *pInDevice)
  606. {
  607. // Yup, there's a loop
  608. bIsLoop = TRUE;
  609. }
  610. }
  611. // If there is a loop, let's drop off the duplicated elements
  612. if (bIsLoop)
  613. {
  614. // Remember, x get decremented one more time from the last loop
  615. y = dwSize;
  616. do {
  617. pDevice1.Attach(deviceList.GetAt(x--));
  618. pDevice2.Attach(deviceList.GetAt(y--));
  619. } while ((*pDevice1 == *pDevice2) && (x > 0));
  620. // Delete all the duplicate elements
  621. y++;
  622. for (x = dwSize; x > y; x--)
  623. {
  624. deviceList.Remove(x);
  625. }
  626. }
  627. return bIsLoop;
  628. }
  629. BOOL CConfigManager::GetDeviceListFilterByClass( CDeviceCollection& deviceList, LPCWSTR pszFilter )
  630. {
  631. #ifdef NTONLY
  632. if (IsWinNT5())
  633. {
  634. CHString sClassName(pszFilter);
  635. sClassName.MakeUpper();
  636. WCHAR cGuid[128];
  637. StringFromGUID2(s_ClassMap[sClassName], cGuid, sizeof(cGuid)/sizeof(WCHAR));
  638. return GetDeviceList( deviceList, cGuid, CM_DRP_CLASSGUID );
  639. }
  640. else
  641. {
  642. return GetDeviceList( deviceList, pszFilter, CM_DRP_CLASS );
  643. }
  644. #else
  645. return GetDeviceList( deviceList, pszFilter, CM_DRP_CLASS );
  646. #endif
  647. }
  648. // Given a FULL_RESOURCE_DESCRIPTOR, find the specified IRQ number, and return its vector
  649. DWORD CConfigManager::GetIRQVector(PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor, DWORD dwFullCount, DWORD dwIRQNum)
  650. {
  651. if (NULL != pFullDescriptor)
  652. {
  653. PCM_PARTIAL_RESOURCE_LIST pPartialList ;
  654. for (DWORD x=0; x < dwFullCount; x++)
  655. {
  656. pPartialList = &pFullDescriptor->PartialResourceList ;
  657. for (DWORD y = 0; y < pPartialList->Count; y++)
  658. {
  659. PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor = &pPartialList->PartialDescriptors[y];
  660. if ( (CmResourceTypeInterrupt == pDescriptor->Type) &&
  661. ( pDescriptor->u.Interrupt.Level == dwIRQNum)
  662. )
  663. {
  664. return pDescriptor->u.Interrupt.Vector;
  665. }
  666. }
  667. pFullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) &pPartialList->PartialDescriptors[pPartialList->Count] ;
  668. }
  669. ASSERT_BREAK(0);
  670. }
  671. return 0xffffffff;
  672. }
  673. // Given a FULL_RESOURCE_DESCRIPTOR, find the specified DMA channel, and return its port
  674. DWORD CConfigManager::GetDMAPort(PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor, DWORD dwFullCount, DWORD dwChannel)
  675. {
  676. if (NULL != pFullDescriptor)
  677. {
  678. PCM_PARTIAL_RESOURCE_LIST pPartialList ;
  679. for (DWORD x=0; x < dwFullCount; x++)
  680. {
  681. pPartialList = &pFullDescriptor->PartialResourceList ;
  682. for (DWORD y = 0; y < pPartialList->Count; y++)
  683. {
  684. PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor = &pPartialList->PartialDescriptors[y];
  685. if ( (CmResourceTypeDma == pDescriptor->Type) &&
  686. ( pDescriptor->u.Dma.Channel == dwChannel)
  687. )
  688. {
  689. return pDescriptor->u.Dma.Port;
  690. }
  691. }
  692. pFullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) &pPartialList->PartialDescriptors[pPartialList->Count] ;
  693. }
  694. ASSERT_BREAK(0);
  695. }
  696. return 0xffffffff;
  697. }
  698. // Given a FULL_RESOURCE_DESCRIPTOR, find the specified startingaddress, and return its MemoryType
  699. LPCWSTR CConfigManager::GetMemoryType(PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor, DWORD dwCount, ULONGLONG ulStartAddress)
  700. {
  701. if (NULL != pFullDescriptor)
  702. {
  703. PCM_PARTIAL_RESOURCE_LIST pPartialList ;
  704. for (DWORD x=0; x < dwCount; x++)
  705. {
  706. pPartialList = &pFullDescriptor->PartialResourceList ;
  707. for (DWORD y = 0; y < pPartialList->Count; y++)
  708. {
  709. PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor = &pPartialList->PartialDescriptors[y];
  710. LARGE_INTEGER liTemp; // Used to avoid 64bit alignment problems
  711. liTemp.HighPart = pDescriptor->u.Memory.Start.HighPart;
  712. liTemp.LowPart = pDescriptor->u.Memory.Start.LowPart;
  713. if ( (CmResourceTypeMemory == pDescriptor->Type) &&
  714. ( liTemp.QuadPart == ulStartAddress)
  715. )
  716. {
  717. switch(pDescriptor->Flags)
  718. {
  719. case CM_RESOURCE_MEMORY_READ_WRITE :
  720. {
  721. return IDS_MTReadWrite;
  722. }
  723. case CM_RESOURCE_MEMORY_READ_ONLY:
  724. {
  725. return IDS_MTReadOnly;
  726. }
  727. case CM_RESOURCE_MEMORY_WRITE_ONLY:
  728. {
  729. return IDS_MTWriteOnly;
  730. }
  731. case CM_RESOURCE_MEMORY_PREFETCHABLE:
  732. {
  733. return IDS_MTPrefetchable;
  734. }
  735. }
  736. return L"";
  737. }
  738. }
  739. pFullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) &pPartialList->PartialDescriptors[pPartialList->Count] ;
  740. }
  741. ASSERT_BREAK(0);
  742. }
  743. return L"";
  744. }