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.

630 lines
18 KiB

  1. //====================================================================
  2. //
  3. // chwres.cpp -- Hardware resource access wrapper class implementation
  4. //
  5. // Copyright (c) 1996-2001 Microsoft Corporation, All Rights Reserved
  6. //
  7. // Revisions: 02/25/97 a-jmoon Adapted from original horrible
  8. // code -- only comments remain.
  9. //
  10. //====================================================================
  11. #include "precomp.h"
  12. #include <cregcls.h>
  13. #include "chwres.h"
  14. /*****************************************************************************
  15. *
  16. * FUNCTION : CHWResource::CHWResource
  17. *
  18. * DESCRIPTION : Constructor
  19. *
  20. * INPUTS : none
  21. *
  22. * OUTPUTS : none
  23. *
  24. * RETURNS : nothing
  25. *
  26. * COMMENTS : Initialization
  27. *
  28. *****************************************************************************/
  29. #ifdef NTONLY
  30. CHWResource::CHWResource()
  31. {
  32. // Zero out public structure
  33. //==========================
  34. memset(&_SystemResourceList, 0, sizeof(_SystemResourceList)) ;
  35. }
  36. /*****************************************************************************
  37. *
  38. * FUNCTION : CHWResource::~CHWResource
  39. *
  40. * DESCRIPTION : Destructor
  41. *
  42. * INPUTS : none
  43. *
  44. * OUTPUTS : none
  45. *
  46. * RETURNS : nothing
  47. *
  48. * COMMENTS : Cleanup
  49. *
  50. *****************************************************************************/
  51. CHWResource::~CHWResource()
  52. {
  53. // Make sure we've destroyed everything
  54. //=====================================
  55. DestroySystemResourceLists() ;
  56. }
  57. /*****************************************************************************
  58. *
  59. * FUNCTION : CHWResource::DestroySystemResourceLists
  60. *
  61. * DESCRIPTION : Walks list of devices & frees associated resource records
  62. *
  63. * INPUTS : none
  64. *
  65. * OUTPUTS : none
  66. *
  67. * RETURNS : nothing
  68. *
  69. * COMMENTS :
  70. *
  71. *****************************************************************************/
  72. void CHWResource::DestroySystemResourceLists()
  73. {
  74. LPDEVICE pDevice ;
  75. LPRESOURCE_DESCRIPTOR pResource ;
  76. while(_SystemResourceList.DeviceHead != NULL)
  77. {
  78. pDevice = _SystemResourceList.DeviceHead ;
  79. _SystemResourceList.DeviceHead = pDevice->Next ;
  80. delete pDevice->Name ;
  81. delete pDevice->KeyName ;
  82. while(pDevice->ResourceDescriptorHead != NULL)
  83. {
  84. pResource = pDevice->ResourceDescriptorHead ;
  85. pDevice->ResourceDescriptorHead = pResource->NextDiff ;
  86. delete pResource ;
  87. }
  88. delete pDevice ;
  89. }
  90. memset(&_SystemResourceList, 0, sizeof(_SystemResourceList)) ;
  91. }
  92. /*****************************************************************************
  93. *
  94. * FUNCTION : CHWResource::CreateSystemResourceLists
  95. * CHWResource::EnumerateResources
  96. * CHWResource::CreateResourceList
  97. * CHWResource::CreateResourceRecord
  98. *
  99. * DESCRIPTION : These four routines recursively enumerate device records
  100. * under HKEY_LOCAL_MACHINE\Hardware\ResourceMap and its
  101. * subkeys, creating a linked list of discovered devices.
  102. * Under each device, a linked list of resources owned by
  103. * the device is also created. Resource records are also
  104. * linked into chains specific to the type of resource.
  105. *
  106. * INPUTS : none
  107. *
  108. * OUTPUTS : none
  109. *
  110. * RETURNS : nothing
  111. *
  112. * COMMENTS : Initialization
  113. *
  114. *****************************************************************************/
  115. void CHWResource::CreateSystemResourceLists()
  116. {
  117. // Start w/clean slate
  118. //====================
  119. DestroySystemResourceLists() ;
  120. // Begin device enumeration at HKLM\Hardware\ResourceMap
  121. //======================================================
  122. EnumerateResources(_T("Hardware\\ResourceMap")) ;
  123. }
  124. void CHWResource::EnumerateResources(CHString sKeyName)
  125. {
  126. CRegistry Reg ;
  127. CHString sSubKeyName, sDeviceName ;
  128. int iFirst ;
  129. DWORD i, dwCount, dwValueType, dwValueNameSize, dwValueDataSize ;
  130. TCHAR *pValueName ;
  131. unsigned char *pValueData ;
  132. PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor ;
  133. // Open target key
  134. //================
  135. if(Reg.Open(HKEY_LOCAL_MACHINE, (LPCTSTR) sKeyName, KEY_READ) != ERROR_SUCCESS)
  136. {
  137. return ;
  138. }
  139. // First, enumerate subkeys
  140. //=========================
  141. for( ; ; )
  142. {
  143. if(Reg.GetCurrentSubKeyName(sSubKeyName) == ERROR_SUCCESS)
  144. {
  145. EnumerateResources(sKeyName + "\\" + sSubKeyName) ;
  146. }
  147. if(Reg.NextSubKey() != ERROR_SUCCESS)
  148. {
  149. break ;
  150. }
  151. }
  152. // Extract this subkey's name
  153. //===========================
  154. iFirst = sKeyName.ReverseFind('\\') ;
  155. sSubKeyName = sKeyName.Mid(iFirst + 1, sKeyName.GetLength() - iFirst) ;
  156. // Create name & data buffers
  157. //===========================
  158. pValueName = new TCHAR[Reg.GetLongestValueName() + 2] ;
  159. pValueData = new unsigned char[Reg.GetLongestValueData() + 2] ;
  160. if(pValueName == NULL || pValueData == NULL)
  161. {
  162. delete [] pValueName ;
  163. delete [] pValueData ;
  164. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  165. }
  166. // Enumerate subkeys
  167. //==================
  168. try
  169. {
  170. for(i = 0 ; i < Reg.GetValueCount() ; i++)
  171. {
  172. // We need type data, so can't use the CRegistry wrapper
  173. //======================================================
  174. dwValueNameSize = Reg.GetLongestValueName() + 2 ;
  175. dwValueDataSize = Reg.GetLongestValueData() + 2 ;
  176. if(RegEnumValue(Reg.GethKey(), i, pValueName, &dwValueNameSize,
  177. NULL, &dwValueType, pValueData, &dwValueDataSize) != ERROR_SUCCESS)
  178. {
  179. continue ;
  180. }
  181. // Only deal w/'Raw' data
  182. //=======================
  183. sDeviceName = pValueName ;
  184. if(sDeviceName.Right(4) != _T(".Raw")) {
  185. continue ;
  186. }
  187. // We've found some resource records -- extract device name
  188. //=========================================================
  189. iFirst = sDeviceName.ReverseFind('\\') ;
  190. if(iFirst == -1)
  191. {
  192. // No device in value name -- device is subkey
  193. //============================================
  194. sDeviceName = sSubKeyName ;
  195. }
  196. else
  197. {
  198. sDeviceName = sDeviceName.Mid(iFirst + 1, sDeviceName.GetLength() - 5 - iFirst) ;
  199. }
  200. if(sDeviceName.IsEmpty())
  201. {
  202. continue ;
  203. }
  204. // Based on returned type, set up for resource enumeration
  205. //========================================================
  206. if(dwValueType == REG_FULL_RESOURCE_DESCRIPTOR)
  207. {
  208. dwCount = 1 ;
  209. pFullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) pValueData ;
  210. }
  211. else if(dwValueType == REG_RESOURCE_LIST)
  212. {
  213. dwCount = ((PCM_RESOURCE_LIST) pValueData)->Count ;
  214. pFullDescriptor = ((PCM_RESOURCE_LIST) pValueData)->List ;
  215. }
  216. else
  217. {
  218. continue ;
  219. }
  220. // Add the device & resources to system lists
  221. //===========================================
  222. CreateResourceList(sDeviceName, dwCount, pFullDescriptor, sKeyName) ;
  223. }
  224. }
  225. catch ( ... )
  226. {
  227. delete [] pValueName ;
  228. delete [] pValueData ;
  229. throw;
  230. }
  231. delete [] pValueName ;
  232. delete [] pValueData ;
  233. Reg.Close() ;
  234. }
  235. void CHWResource::CreateResourceList(CHString sDeviceName, DWORD dwFullResourceCount,
  236. PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor, CHString sKeyName)
  237. {
  238. LPDEVICE pDevice ;
  239. DWORD i, j ;
  240. PCM_PARTIAL_RESOURCE_LIST pPartialList ;
  241. // Locate/create record for device
  242. //================================
  243. pDevice = _SystemResourceList.DeviceHead ;
  244. while(pDevice != NULL)
  245. {
  246. if(sDeviceName == pDevice->Name)
  247. {
  248. break ;
  249. }
  250. pDevice = pDevice->Next ;
  251. }
  252. if(pDevice == NULL)
  253. {
  254. // Device not found -- create new device record
  255. //=============================================
  256. pDevice = new DEVICE ;
  257. if(pDevice == NULL)
  258. {
  259. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  260. }
  261. memset(pDevice, 0, sizeof(DEVICE)) ;
  262. pDevice->Name = new TCHAR[sDeviceName.GetLength() + 2] ;
  263. if(pDevice->Name == NULL)
  264. {
  265. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  266. }
  267. try
  268. {
  269. _tcscpy(pDevice->Name, LPCTSTR(sDeviceName)) ;
  270. pDevice->KeyName = new TCHAR [sKeyName.GetLength() + 2] ;
  271. if(pDevice->KeyName == NULL)
  272. {
  273. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  274. }
  275. _tcscpy(pDevice->KeyName, LPCTSTR(sKeyName)) ;
  276. if(_SystemResourceList.DeviceHead == NULL)
  277. {
  278. _SystemResourceList.DeviceHead = pDevice ;
  279. }
  280. else
  281. {
  282. _SystemResourceList.DeviceTail->Next = pDevice ;
  283. }
  284. _SystemResourceList.DeviceTail = pDevice ;
  285. }
  286. catch ( ... )
  287. {
  288. delete pDevice;
  289. throw ;
  290. }
  291. }
  292. // Create record for each owned resource
  293. //======================================
  294. for(i = 0 ; i < dwFullResourceCount ; i++)
  295. {
  296. pPartialList = &pFullDescriptor->PartialResourceList ;
  297. for(j = 0 ; j < pPartialList->Count; j++)
  298. {
  299. CreateResourceRecord(pDevice, pFullDescriptor->InterfaceType, pFullDescriptor->BusNumber, &pPartialList->PartialDescriptors[j]) ;
  300. }
  301. // Point to next full descriptor
  302. //==============================
  303. pFullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) &pPartialList->PartialDescriptors[pPartialList->Count] ;
  304. }
  305. }
  306. void CHWResource::CreateResourceRecord(LPDEVICE pDevice, INTERFACE_TYPE InterfaceType, ULONG Bus, PCM_PARTIAL_RESOURCE_DESCRIPTOR pResource)
  307. {
  308. LPRESOURCE_DESCRIPTOR pNewResource, *pHead, *pTail, pCurrent, pLast ;
  309. // Only deal w/'known' resource types
  310. //===================================
  311. if(pResource->Type != CmResourceTypePort &&
  312. pResource->Type != CmResourceTypeInterrupt &&
  313. pResource->Type != CmResourceTypeMemory &&
  314. pResource->Type != CmResourceTypeDma )
  315. {
  316. return ;
  317. }
  318. // Create new record for resource & add to device's list
  319. //======================================================
  320. pNewResource = new RESOURCE_DESCRIPTOR ;
  321. if(pNewResource == NULL)
  322. {
  323. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  324. }
  325. try
  326. {
  327. memset(pNewResource, 0, sizeof(RESOURCE_DESCRIPTOR)) ;
  328. memcpy(&pNewResource->CmResourceDescriptor, pResource, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)) ;
  329. pNewResource->Owner = pDevice ;
  330. pNewResource->Bus = Bus;
  331. pNewResource->InterfaceType = InterfaceType;
  332. if(pDevice->ResourceDescriptorHead == NULL)
  333. {
  334. pDevice->ResourceDescriptorHead = pNewResource ;
  335. }
  336. else
  337. {
  338. pDevice->ResourceDescriptorTail->NextDiff = pNewResource ;
  339. }
  340. pDevice->ResourceDescriptorTail = pNewResource ;
  341. }
  342. catch ( ... )
  343. {
  344. delete pNewResource;
  345. throw ;
  346. }
  347. // Locate insertion point into sorted type-specific list
  348. //======================================================
  349. switch(pResource->Type)
  350. {
  351. case CmResourceTypePort :
  352. pHead = &_SystemResourceList.PortHead ;
  353. pTail = &_SystemResourceList.PortTail ;
  354. pCurrent = *pHead ;
  355. pLast = NULL ;
  356. LARGE_INTEGER liTemp; // Used to avoid 64bit alignment problems
  357. liTemp.HighPart = pResource->u.Port.Start.HighPart;
  358. liTemp.LowPart = pResource->u.Port.Start.LowPart;
  359. while(pCurrent != NULL)
  360. {
  361. LARGE_INTEGER liTemp2; // Used to avoid 64bit alignment problems
  362. liTemp2.HighPart = pCurrent->CmResourceDescriptor.u.Port.Start.HighPart;
  363. liTemp2.LowPart = pCurrent->CmResourceDescriptor.u.Port.Start.LowPart;
  364. if (liTemp2.QuadPart < liTemp.QuadPart)
  365. {
  366. pLast = pCurrent ;
  367. pCurrent = pCurrent->NextSame ;
  368. }
  369. else
  370. {
  371. break;
  372. }
  373. }
  374. break;
  375. case CmResourceTypeInterrupt :
  376. {
  377. pHead = &_SystemResourceList.InterruptHead ;
  378. pTail = &_SystemResourceList.InterruptTail ;
  379. pCurrent = *pHead ;
  380. pLast = NULL ;
  381. ULONGLONG iIRQ = pResource->u.Interrupt.Level;
  382. // If the IRQ to add is less than the current IRQ, OR
  383. // if the IRQ to add is the same as the current IRQ and the current
  384. // IRQ is not an internal one, put it after the current one. This
  385. // will make sure that internal IRQs are listed last in the list.
  386. while (pCurrent != NULL &&
  387. ( (pCurrent->CmResourceDescriptor.u.Interrupt.Level < iIRQ) ||
  388. ((pCurrent->CmResourceDescriptor.u.Interrupt.Level == iIRQ) &&
  389. (pCurrent->InterfaceType != Internal))
  390. ))
  391. {
  392. pLast = pCurrent ;
  393. pCurrent = pCurrent->NextSame ;
  394. }
  395. break;
  396. }
  397. case CmResourceTypeMemory :
  398. {
  399. pHead = &_SystemResourceList.MemoryHead ;
  400. pTail = &_SystemResourceList.MemoryTail ;
  401. pCurrent = *pHead ;
  402. pLast = NULL ;
  403. LARGE_INTEGER liTemp; // Used to avoid 64bit alignment problems
  404. liTemp.HighPart = pResource->u.Memory.Start.HighPart;
  405. liTemp.LowPart = pResource->u.Memory.Start.LowPart;
  406. while(pCurrent != NULL)
  407. {
  408. LARGE_INTEGER liTemp2; // Used to avoid 64bit alignment problems
  409. liTemp2.HighPart = pCurrent->CmResourceDescriptor.u.Memory.Start.HighPart;
  410. liTemp2.LowPart = pCurrent->CmResourceDescriptor.u.Memory.Start.LowPart;
  411. if (liTemp2.QuadPart < liTemp.QuadPart)
  412. {
  413. pLast = pCurrent ;
  414. pCurrent = pCurrent->NextSame ;
  415. }
  416. else
  417. {
  418. break;
  419. }
  420. }
  421. break;
  422. }
  423. case CmResourceTypeDma :
  424. pHead = &_SystemResourceList.DmaHead ;
  425. pTail = &_SystemResourceList.DmaTail ;
  426. pCurrent = *pHead ;
  427. pLast = NULL ;
  428. while(pCurrent != NULL &&
  429. pCurrent->CmResourceDescriptor.u.Dma.Channel < pResource->u.Dma.Channel)
  430. {
  431. pLast = pCurrent ;
  432. pCurrent = pCurrent->NextSame ;
  433. }
  434. break;
  435. }
  436. // Insert into...
  437. //===============
  438. if(*pHead == NULL)
  439. {
  440. // ...empty list
  441. //==========================
  442. (*pHead) = pNewResource ;
  443. (*pTail) = pNewResource ;
  444. }
  445. else if(pLast == NULL)
  446. {
  447. // ...beginning of list
  448. //=================================
  449. pNewResource->NextSame = pCurrent ;
  450. (*pHead) = pNewResource ;
  451. }
  452. else if(pCurrent == NULL)
  453. {
  454. // ...end of list
  455. //=========================
  456. pLast->NextSame = pNewResource ;
  457. (*pTail) = pNewResource ;
  458. }
  459. else
  460. {
  461. // ...middle of list
  462. //==============================
  463. pLast->NextSame = pNewResource ;
  464. pNewResource->NextSame = pCurrent ;
  465. }
  466. }
  467. #endif
  468. // Helper function for converting strings to resource types
  469. BOOL WINAPI StringFromInterfaceType( INTERFACE_TYPE it, CHString& strVal )
  470. {
  471. //BOOL fReturn = TRUE;
  472. //switch ( it )
  473. //{
  474. // case Internal: strVal = "INTERNAL"; break;
  475. // case Isa: strVal = "ISA"; break;
  476. // case Eisa: strVal = "EISA"; break;
  477. // case MicroChannel: strVal = "MICROCHANNEL"; break;
  478. // case TurboChannel: strVal = "TURBOCHANNEL"; break;
  479. // case PCIBus: strVal = "PCI"; break;
  480. // case VMEBus: strVal = "VME"; break;
  481. // case NuBus: strVal = "NU"; break;
  482. // case PCMCIABus: strVal = "PCMCIA"; break;
  483. // case CBus: strVal = "INTERNAL"; break;
  484. // case MPIBus: strVal = "INTERNAL"; break;
  485. // case MPSABus: strVal = "MPSA"; break;
  486. // case ProcessorInternal: strVal = "PROCESSORINTERNAL"; break;
  487. // case InternalPowerBus: strVal = "INTERNALPOWER"; break;
  488. // case PNPISABus: strVal = "PNPISA"; break;
  489. // case PNPBus: strVal = "PNP"; break;
  490. // default: fReturn = FALSE;
  491. //}
  492. if(it > InterfaceTypeUndefined && it < MaximumInterfaceType)
  493. {
  494. strVal = szBusType[it];
  495. return TRUE;
  496. }
  497. else
  498. {
  499. return FALSE;
  500. }
  501. }