Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2327 lines
71 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. inflogcf.c
  5. Abstract:
  6. Routines to parse logical configuration sections in
  7. win95-style INF files, and place the output in the registry.
  8. Author:
  9. Ted Miller (tedm) 8-Mar-1995
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. PCTSTR pszHexDigits = TEXT("0123456789ABCDEF");
  15. #define INFCHAR_SIZE_SEP TEXT('@')
  16. #define INFCHAR_RANGE_SEP TEXT('-')
  17. #define INFCHAR_ALIGN_SEP TEXT('%')
  18. #define INFCHAR_ATTR_START TEXT('(')
  19. #define INFCHAR_ATTR_END TEXT(')')
  20. #define INFCHAR_MEMATTR_READ TEXT('R')
  21. #define INFCHAR_MEMATTR_WRITE TEXT('W')
  22. #define INFCHAR_MEMATTR_PREFETCH TEXT('F')
  23. #define INFCHAR_MEMATTR_COMBINEDWRITE TEXT('C')
  24. #define INFCHAR_MEMATTR_CACHEABLE TEXT('H')
  25. #define INFCHAR_MEMATTR_DWORD TEXT('D')
  26. #define INFCHAR_MEMATTR_ATTRIBUTE TEXT('A')
  27. #define INFCHAR_DECODE_START TEXT('(')
  28. #define INFCHAR_DECODE_END TEXT(')')
  29. #define INFCHAR_DECODE_SEP TEXT(':')
  30. #define INFCHAR_IRQATTR_SEP TEXT(':')
  31. #define INFCHAR_IRQATTR_SHARE TEXT('S')
  32. #define INFCHAR_IRQATTR_LEVEL TEXT('L')
  33. #define INFCHAR_DMAWIDTH_NARROW TEXT('N') // i.e., 8-bit
  34. #define INFCHAR_DMAWIDTH_WORD TEXT('W') // i.e., 16-bit
  35. #define INFCHAR_DMAWIDTH_DWORD TEXT('D') // i.e., 32-bit
  36. #define INFCHAR_DMA_BUSMASTER TEXT('M')
  37. #define INFCHAR_DMATYPE_A TEXT('A')
  38. #define INFCHAR_DMATYPE_B TEXT('B')
  39. #define INFCHAR_DMATYPE_F TEXT('F')
  40. #define INFCHAR_IOATTR_MEMORY TEXT('M')
  41. #define INFCHAR_PCCARD_IOATTR_WORD TEXT('W')
  42. #define INFCHAR_PCCARD_IOATTR_BYTE TEXT('B')
  43. #define INFCHAR_PCCARD_IOATTR_SRC TEXT('S')
  44. #define INFCHAR_PCCARD_IOATTR_Z8 TEXT('Z')
  45. #define INFCHAR_PCCARD_ATTR_WAIT TEXT('X')
  46. #define INFCHAR_PCCARD_ATTR_WAITI TEXT('I')
  47. #define INFCHAR_PCCARD_ATTR_WAITM TEXT('M')
  48. #define INFCHAR_PCCARD_MEMATTR_WORD TEXT('M')
  49. #define INFCHAR_PCCARD_MEM_ISATTR TEXT('A')
  50. #define INFCHAR_PCCARD_MEM_ISCOMMON TEXT('C')
  51. #define INFCHAR_PCCARD_SEP TEXT(':')
  52. #define INFCHAR_PCCARD_ATTR_SEP TEXT(' ')
  53. #define INFCHAR_MFCARD_AUDIO_ATTR TEXT('A')
  54. #define INFLOGCONF_IOPORT_10BIT_DECODE 0x000003ff
  55. #define INFLOGCONF_IOPORT_12BIT_DECODE 0x00000fff
  56. #define INFLOGCONF_IOPORT_16BIT_DECODE 0x0000ffff
  57. #define INFLOGCONF_IOPORT_POSITIVE_DECODE 0x00000000
  58. #define DEFAULT_IOPORT_DECODE INFLOGCONF_IOPORT_10BIT_DECODE
  59. #define DEFAULT_MEMORY_ALIGNMENT 0xfffffffffffff000 // 4K-aligned (a'la Win9x)
  60. #define DEFAULT_IOPORT_ALIGNMENT 0xffffffffffffffff // byte-aligned
  61. #define DEFAULT_IRQ_AFFINITY 0xffffffff // use any processor
  62. //
  63. // Mapping between registry key specs in an inf file
  64. // and predefined registry handles.
  65. //
  66. STRING_TO_DATA InfPrioritySpecToPriority[] = { INFSTR_CFGPRI_HARDWIRED , LCPRI_HARDWIRED,
  67. INFSTR_CFGPRI_DESIRED , LCPRI_DESIRED,
  68. INFSTR_CFGPRI_NORMAL , LCPRI_NORMAL,
  69. INFSTR_CFGPRI_SUBOPTIMAL , LCPRI_SUBOPTIMAL,
  70. INFSTR_CFGPRI_DISABLED , LCPRI_DISABLED,
  71. INFSTR_CFGPRI_RESTART , LCPRI_RESTART,
  72. INFSTR_CFGPRI_REBOOT , LCPRI_REBOOT,
  73. INFSTR_CFGPRI_POWEROFF , LCPRI_POWEROFF,
  74. INFSTR_CFGPRI_HARDRECONFIG, LCPRI_HARDRECONFIG,
  75. INFSTR_CFGPRI_FORCECONFIG , LCPRI_FORCECONFIG,
  76. NULL , 0
  77. };
  78. STRING_TO_DATA InfConfigSpecToConfig[] = { INFSTR_CFGTYPE_BASIC , BASIC_LOG_CONF,
  79. INFSTR_CFGTYPE_FORCED , FORCED_LOG_CONF,
  80. INFSTR_CFGTYPE_OVERRIDE, OVERRIDE_LOG_CONF,
  81. NULL , 0
  82. };
  83. //
  84. // Declare strings used in processing INF LogConfigs.
  85. //
  86. // These strings are defined in infstr.h:
  87. //
  88. CONST TCHAR pszMemConfig[] = INFSTR_KEY_MEMCONFIG,
  89. pszIOConfig[] = INFSTR_KEY_IOCONFIG,
  90. pszIRQConfig[] = INFSTR_KEY_IRQCONFIG,
  91. pszDMAConfig[] = INFSTR_KEY_DMACONFIG,
  92. pszPcCardConfig[] = INFSTR_KEY_PCCARDCONFIG,
  93. pszMfCardConfig[] = INFSTR_KEY_MFCARDCONFIG,
  94. pszConfigPriority[] = INFSTR_KEY_CONFIGPRIORITY,
  95. pszDriverVer[] = INFSTR_DRIVERVERSION_SECTION;
  96. BOOL
  97. pHexToScalar(
  98. IN PCTSTR FieldStart,
  99. IN PCTSTR FieldEnd,
  100. OUT PDWORDLONG Value,
  101. IN BOOL Want64Bits
  102. )
  103. {
  104. UINT DigitCount;
  105. UINT i;
  106. DWORDLONG Accum;
  107. WORD Types[16];
  108. //
  109. // Make sure the number is in range by checking the number
  110. // of hex digits.
  111. //
  112. DigitCount = (UINT)(FieldEnd - FieldStart);
  113. if((DigitCount == 0)
  114. || (DigitCount > (UINT)(Want64Bits ? 16 : 8))
  115. || !GetStringTypeEx(LOCALE_SYSTEM_DEFAULT,CT_CTYPE1,FieldStart,DigitCount,Types)) {
  116. return(FALSE);
  117. }
  118. Accum = 0;
  119. for(i=0; i<DigitCount; i++) {
  120. if(!(Types[i] & C1_XDIGIT)) {
  121. return(FALSE);
  122. }
  123. Accum *= 16;
  124. Accum += _tcschr(pszHexDigits,(TCHAR)CharUpper((PTSTR)FieldStart[i])) - pszHexDigits;
  125. }
  126. *Value = Accum;
  127. return(TRUE);
  128. }
  129. BOOL
  130. pHexToUlong(
  131. IN PCTSTR FieldStart,
  132. IN PCTSTR FieldEnd,
  133. OUT PDWORD Value
  134. )
  135. /*++
  136. Routine Description:
  137. Convert a sequence of unicode hex digits into an
  138. unsigned 32-bit number. Digits are validated.
  139. Arguments:
  140. FieldStart - supplies pointer to unicode digit sequence.
  141. FieldEnd - supplies pointer to first character beyond the
  142. digit sequence.
  143. Value - receives 32-bit number
  144. Return Value:
  145. TRUE if the number is in range and valid. FALSE otherwise.
  146. --*/
  147. {
  148. DWORDLONG x;
  149. BOOL b;
  150. if(b = pHexToScalar(FieldStart,FieldEnd,&x,FALSE)) {
  151. *Value = (DWORD)x;
  152. }
  153. return(b);
  154. }
  155. BOOL
  156. pHexToUlonglong(
  157. IN PCTSTR FieldStart,
  158. IN PCTSTR FieldEnd,
  159. OUT PDWORDLONG Value
  160. )
  161. /*++
  162. Routine Description:
  163. Convert a sequence of unicode hex digits into an
  164. unsigned 64-bit number. Digits are validated.
  165. Arguments:
  166. FieldStart - supplies pointer to unicode digit sequence.
  167. FieldEnd - supplies pointer to first character beyond the
  168. digit sequence.
  169. Value - receives 64-bit number
  170. Return Value:
  171. TRUE if the number is in range and valid. FALSE otherwise.
  172. --*/
  173. {
  174. return(pHexToScalar(FieldStart,FieldEnd,Value,TRUE));
  175. }
  176. BOOL
  177. pDecimalToUlong(
  178. IN PCTSTR Field,
  179. OUT PDWORD Value
  180. )
  181. /*++
  182. Routine Description:
  183. Convert a nul-terminated sequence of unicode decimal digits into an
  184. unsigned 32-bit number. Digits are validated.
  185. Arguments:
  186. Field - supplies pointer to unicode digit sequence.
  187. Value - receives DWORD number
  188. Return Value:
  189. TRUE if the number is in range and valid. FALSE otherwise.
  190. --*/
  191. {
  192. UINT DigitCount;
  193. UINT i;
  194. DWORDLONG Accum;
  195. WORD Types[10];
  196. DigitCount = lstrlen(Field);
  197. if((DigitCount == 0) || (DigitCount > 10)
  198. || !GetStringTypeEx(LOCALE_SYSTEM_DEFAULT,CT_CTYPE1,Field,DigitCount,Types)) {
  199. return(FALSE);
  200. }
  201. Accum = 0;
  202. for(i=0; i<DigitCount; i++) {
  203. if(!(Types[i] & C1_DIGIT)) {
  204. return(FALSE);
  205. }
  206. Accum *= 10;
  207. Accum += _tcschr(pszHexDigits,(TCHAR)CharUpper((PTSTR)Field[i])) - pszHexDigits;
  208. //
  209. // Check overflow
  210. //
  211. if(Accum > 0xffffffff) {
  212. return(FALSE);
  213. }
  214. }
  215. *Value = (DWORD)Accum;
  216. return(TRUE);
  217. }
  218. DWORD
  219. pSetupProcessMemConfig(
  220. IN LOG_CONF LogConfig,
  221. IN PINFCONTEXT InfLine,
  222. IN HMACHINE hMachine
  223. )
  224. /*++
  225. Routine Description:
  226. Process a MemConfig line in a Win95 INF. Such lines specify
  227. memory requirements for a device. Each line is expected to be
  228. in the form
  229. MemConfig = <start>-<end>[(<attr>)],<start>-<end>[(<attr>)],...
  230. <start> is the start of a memory range (64-bit hex)
  231. <end> is the end of a memory range (64-bit hex)
  232. <attr> if present is a string of 0 or more chars from
  233. C - memory is combined-write
  234. D - memory is 32-bit, otherwise 24-bit.
  235. F - memory is prefetchable
  236. H - memory is cacheable
  237. R - memory is read-only
  238. W - memory is write-only
  239. (If R and W are specified or neither is specified the memory
  240. is read/write)
  241. or
  242. MemConfig = <size>@<min>-<max>[%align][(<attr>)],...
  243. <size> is the size of a memory range (32-bit hex)
  244. <min> is the minimum address where the memory range can be (64-bit hex)
  245. <max> is the maximum address where the memory range can be (64-bit hex)
  246. <align> (if specified) is the alignment mask for the addresses (32-bit hex)
  247. <attr> as above.
  248. ie, 8000@C0000-D7FFF%F0000 says the device needs a 32K memory window
  249. starting at any 64K-aligned address between C0000 and D7FFF.
  250. The default memory alignment is 4K (FFFFF000).
  251. Arguments:
  252. Return Value:
  253. --*/
  254. {
  255. UINT FieldCount,i;
  256. PCTSTR Field;
  257. DWORD d;
  258. PTCHAR p;
  259. INT u;
  260. UINT Attributes;
  261. DWORD RangeSize;
  262. ULARGE_INTEGER Align;
  263. DWORDLONG Start,End;
  264. PMEM_RESOURCE MemRes;
  265. PMEM_RANGE MemRange;
  266. RES_DES ResDes;
  267. PVOID q;
  268. BOOL bReadFlag = FALSE, bWriteFlag = FALSE;
  269. FieldCount = SetupGetFieldCount(InfLine);
  270. if (!FieldCount && GetLastError() != NO_ERROR) {
  271. return GetLastError();
  272. }
  273. if(MemRes = MyMalloc(offsetof(MEM_RESOURCE,MEM_Data))) {
  274. ZeroMemory(MemRes,offsetof(MEM_RESOURCE,MEM_Data));
  275. MemRes->MEM_Header.MD_Type = MType_Range;
  276. d = NO_ERROR;
  277. } else {
  278. d = ERROR_NOT_ENOUGH_MEMORY;
  279. }
  280. for(i=1; (d==NO_ERROR) && (i<=FieldCount); i++) {
  281. Field = pSetupGetField(InfLine,i);
  282. Attributes = 0;
  283. RangeSize = 0;
  284. Align.QuadPart = DEFAULT_MEMORY_ALIGNMENT;
  285. //
  286. // See if this is in the start-end or size@min-max format.
  287. // If we have a size, use it.
  288. //
  289. if(p = _tcschr(Field,INFCHAR_SIZE_SEP)) {
  290. if(pHexToUlong(Field,p,&RangeSize)) {
  291. Field = ++p;
  292. } else {
  293. d = ERROR_INVALID_INF_LOGCONFIG;
  294. }
  295. }
  296. //
  297. // We should now have a x-y which is either start/end or min/max.
  298. //
  299. if((d == NO_ERROR) // no err so far
  300. && (p = _tcschr(Field,INFCHAR_RANGE_SEP)) // Field: start of min; p: end of min
  301. && pHexToUlonglong(Field,p,&Start) // get min
  302. && (Field = p+1) // Field: start of max
  303. && ( (p = _tcschr(Field,INFCHAR_ALIGN_SEP))
  304. || (p = _tcschr(Field,INFCHAR_ATTR_START))
  305. || (p = _tcschr(Field,0))) // p: end of max
  306. && pHexToUlonglong(Field,p,&End)) { // get max
  307. //
  308. // If we get here Field is pointing either at the end of the field,
  309. // at the % that starts the alignment mask spec, or at the
  310. // ( that starts the attributes spec.
  311. //
  312. Field = p;
  313. if(*Field == INFCHAR_ALIGN_SEP) {
  314. Field++;
  315. p = _tcschr(Field,INFCHAR_ATTR_START);
  316. if(!p) {
  317. p = _tcschr(Field,0);
  318. }
  319. if(pHexToUlonglong(Field, p, &(Align.QuadPart))) {
  320. //
  321. // NOTE: Since these mask values are actually stored in a WDM
  322. // resource list (i.e., IO_RESOURCE_REQUIREMENTS_LIST), there's
  323. // no way to specify an alignment greater than 32 bits. However,
  324. // since the alignment value was implemented as a mask (for
  325. // compatibility with Win9x), we must specify it as a 64-bit
  326. // quantity, since it is applied to a 64-bit value. We will check
  327. // below to ensure that the most significant DWORD is all ones.
  328. //
  329. // Also, we must handle alignment values such as 000F0000, 00FF0000,
  330. // 0FFF0000, and FFFF0000. These all specify 64K alignment (depending
  331. // on the min and max addresses, the INF writer might not need to
  332. // specify all the 1 bits in the 32-bit value).
  333. // Thus we perform an ersatz sign extension of sorts -- we
  334. // find the highest 1 bit and replicate it into all the
  335. // more significant bits in the value.
  336. //
  337. for(u=31; u>=0; u--) {
  338. if(Align.HighPart & (1 << u)) {
  339. break;
  340. }
  341. Align.HighPart |= (1 << u);
  342. }
  343. //
  344. // Make sure that all the bits in the most-significant DWORD are set,
  345. // because we can't express this alignment otherwise (as discussed
  346. // above). Also, make sure that if we encountered a '1' in the high
  347. // dword, then the high bit of the low dword is '1' as well.
  348. //
  349. if((Align.HighPart ^ 0xffffffff) ||
  350. ((u >= 0) && !(Align.LowPart & 0x80000000))) {
  351. d = ERROR_INVALID_INF_LOGCONFIG;
  352. } else {
  353. //
  354. // Do the sign extension for the low dword.
  355. //
  356. for(u=31; u>=0; u--) {
  357. if(Align.LowPart & (1 << u)) {
  358. break;
  359. }
  360. Align.LowPart |= (1 << u);
  361. }
  362. }
  363. } else {
  364. d = ERROR_INVALID_INF_LOGCONFIG;
  365. }
  366. }
  367. //
  368. // See if we have attributes.
  369. //
  370. if((d == NO_ERROR) && (*p == INFCHAR_ATTR_START)) {
  371. Field = ++p;
  372. if(p = _tcschr(Field,INFCHAR_ATTR_END)) {
  373. //
  374. // C for combined-write
  375. // D for 32-bit memory
  376. // F for prefetchable
  377. // H for cacheable
  378. // R for readable
  379. // W for writeable
  380. // RW (or neither) means read/write
  381. //
  382. while((d == NO_ERROR) && (Field < p)) {
  383. switch((TCHAR)CharUpper((PTSTR)(*Field))) {
  384. case INFCHAR_MEMATTR_READ:
  385. bReadFlag = TRUE;
  386. break;
  387. case INFCHAR_MEMATTR_WRITE:
  388. bWriteFlag = TRUE;
  389. break;
  390. case INFCHAR_MEMATTR_PREFETCH:
  391. Attributes |= fMD_PrefetchAllowed;
  392. break;
  393. case INFCHAR_MEMATTR_COMBINEDWRITE:
  394. Attributes |= fMD_CombinedWriteAllowed;
  395. break;
  396. case INFCHAR_MEMATTR_DWORD:
  397. Attributes |= fMD_32;
  398. break;
  399. case INFCHAR_MEMATTR_CACHEABLE:
  400. Attributes |= fMD_Cacheable;
  401. break;
  402. default:
  403. d = ERROR_INVALID_INF_LOGCONFIG;
  404. break;
  405. }
  406. Field++;
  407. }
  408. } else {
  409. d = ERROR_INVALID_INF_LOGCONFIG;
  410. }
  411. }
  412. } else {
  413. d = ERROR_INVALID_INF_LOGCONFIG;
  414. }
  415. if(d == NO_ERROR) {
  416. //
  417. // If no range size was specified, then calculate it from
  418. // the given start and end addresses. Since this happens
  419. // when the memory requirement was an absolute start/end,
  420. // there is no alignment requirement.
  421. //
  422. if(RangeSize == 0) {
  423. RangeSize = (DWORD)(End-Start)+1;
  424. Align.QuadPart = DEFAULT_MEMORY_ALIGNMENT;
  425. }
  426. //
  427. // Slam values into the header part of the memory descriptor.
  428. // These will be ignored unless we're setting a forced config.
  429. // Note that the inf had better have specified forced mem configs
  430. // in a 'simple' form, since we throw away alignment, etc.
  431. //
  432. if (bWriteFlag && bReadFlag) {
  433. Attributes |= fMD_ReadAllowed | fMD_RAM; // read-write
  434. } else if (bWriteFlag && !bReadFlag) {
  435. Attributes |= fMD_ReadDisallowed | fMD_RAM; // write only
  436. } else if (!bWriteFlag && bReadFlag) {
  437. Attributes |= fMD_ReadAllowed | fMD_ROM; // read-only
  438. } else {
  439. Attributes |= fMD_ReadAllowed | fMD_RAM; // read-write
  440. }
  441. MemRes->MEM_Header.MD_Alloc_Base = Start;
  442. MemRes->MEM_Header.MD_Alloc_End = Start + RangeSize - 1;
  443. MemRes->MEM_Header.MD_Flags = Attributes;
  444. //
  445. // Add this guy into the descriptor we're building up.
  446. //
  447. q = MyRealloc(
  448. MemRes,
  449. offsetof(MEM_RESOURCE,MEM_Data)
  450. + (sizeof(MEM_RANGE)*(MemRes->MEM_Header.MD_Count+1))
  451. );
  452. if(q) {
  453. MemRes = q;
  454. MemRange = &MemRes->MEM_Data[MemRes->MEM_Header.MD_Count++];
  455. MemRange->MR_Align = Align.QuadPart;
  456. MemRange->MR_nBytes = RangeSize;
  457. MemRange->MR_Min = Start;
  458. MemRange->MR_Max = End;
  459. MemRange->MR_Flags = Attributes;
  460. MemRange->MR_Reserved = 0;
  461. } else {
  462. d = ERROR_NOT_ENOUGH_MEMORY;
  463. }
  464. }
  465. }
  466. if((d == NO_ERROR) && MemRes->MEM_Header.MD_Count) {
  467. d = CM_Add_Res_Des_Ex(
  468. &ResDes,
  469. LogConfig,
  470. ResType_Mem,
  471. MemRes,
  472. offsetof(MEM_RESOURCE,MEM_Data) + (sizeof(MEM_RANGE) * MemRes->MEM_Header.MD_Count),
  473. 0,
  474. hMachine);
  475. d = MapCrToSpError(d, ERROR_INVALID_DATA);
  476. if(d == NO_ERROR) {
  477. CM_Free_Res_Des_Handle(ResDes);
  478. }
  479. }
  480. if(MemRes) {
  481. MyFree(MemRes);
  482. }
  483. return(d);
  484. }
  485. DWORD
  486. pSetupProcessIoConfig(
  487. IN LOG_CONF LogConfig,
  488. IN PINFCONTEXT InfLine,
  489. IN HMACHINE hMachine
  490. )
  491. /*++
  492. Routine Description:
  493. Process an IOConfig line in a Win95 INF. Such lines specify
  494. IO port requirements for a device. Each line is expected to be
  495. in the form
  496. IOConfig = <start>-<end>[(<decodemask>:<aliasoffset>:<attr>)],...
  497. <start> is the start of a port range (64-bit hex)
  498. <end> is the end of a port range (64-bit hex)
  499. <decodemask> defines the alias type, and may be one of the following combinations:
  500. 3ff 10-bit decode, IOR_Alias is 0x04
  501. fff 12-bit decode, IOR_Alias is 0x10
  502. ffff 16-bit decode, IOR_Alias is 0x00
  503. 0 positive decode, IOR_Alias is 0xFF
  504. <aliasoffset> is ignored.
  505. <attr> if 'M', specifies port is a memory address, otherwise port is an IO address.
  506. or
  507. IOConfig = <size>@<min>-<max>[%align][(<decodemask>:<aliasoffset>:<attr>)],...
  508. <size> is the size of a port range (32-bit hex)
  509. <min> is the minimum port where the memory range can be (64-bit hex)
  510. <max> is the maximum port where the memory range can be (64-bit hex)
  511. <align> (if specified) is the alignment mask for the ports (32-bit hex)
  512. <decodemask>, <aliasoffset>,<attr> as above
  513. ie, IOConfig = 1F8-1FF(3FF::),2F8-2FF(3FF::),3F8-3FF(3FF::)
  514. IOConfig = 8@300-32F%FF8(3FF::)
  515. IOConfig = 2E8-2E8(3FF:8000:)
  516. Arguments:
  517. Return Value:
  518. --*/
  519. {
  520. UINT FieldCount,i;
  521. PCTSTR Field;
  522. DWORD d;
  523. PTCHAR p;
  524. INT u;
  525. DWORD RangeSize;
  526. ULARGE_INTEGER Align;
  527. DWORDLONG Decode;
  528. DWORDLONG Start,End;
  529. BOOL GotSize;
  530. PIO_RESOURCE IoRes;
  531. PIO_RANGE IoRange;
  532. RES_DES ResDes;
  533. PVOID q;
  534. UINT Attributes = 0;
  535. PTCHAR Attr;
  536. FieldCount = SetupGetFieldCount(InfLine);
  537. if (!FieldCount && GetLastError() != NO_ERROR) {
  538. return GetLastError();
  539. }
  540. if(IoRes = MyMalloc(offsetof(IO_RESOURCE,IO_Data))) {
  541. ZeroMemory(IoRes,offsetof(IO_RESOURCE,IO_Data));
  542. IoRes->IO_Header.IOD_Type = IOType_Range;
  543. d = NO_ERROR;
  544. } else {
  545. d = ERROR_NOT_ENOUGH_MEMORY;
  546. }
  547. for(i=1; (d==NO_ERROR) && (i<=FieldCount); i++) {
  548. Field = pSetupGetField(InfLine,i);
  549. Attributes = fIOD_IO;
  550. Decode = DEFAULT_IOPORT_DECODE;
  551. RangeSize = 0;
  552. Align.QuadPart = DEFAULT_IOPORT_ALIGNMENT;
  553. //
  554. // See if this is in the start-end or size@min-max format.
  555. // If we have a size, use it.
  556. //
  557. if(p = _tcschr(Field,INFCHAR_SIZE_SEP)) {
  558. if(pHexToUlong(Field,p,&RangeSize)) {
  559. Field = ++p;
  560. } else {
  561. d = ERROR_INVALID_INF_LOGCONFIG;
  562. }
  563. }
  564. //
  565. // We should now have a x-y which is either start/end or min/max.
  566. //
  567. if((d == NO_ERROR) // no err so far
  568. && (p = _tcschr(Field,INFCHAR_RANGE_SEP)) // Field: start of min; p: end of min
  569. && pHexToUlonglong(Field,p,&Start) // get min
  570. && (Field = p+1) // Field: start of max
  571. && ( (p = _tcschr(Field,INFCHAR_ALIGN_SEP))
  572. || (p = _tcschr(Field,INFCHAR_DECODE_START))
  573. || (p = _tcschr(Field,0))) // p: end of max
  574. && pHexToUlonglong(Field,p,&End)) { // get max
  575. //
  576. // If we get here Field is pointing either at the end of the field,
  577. // or at the % that starts the alignment mask spec,
  578. // or at the ( that starts the decode stuff.
  579. //
  580. Field = p;
  581. switch(*Field) {
  582. case INFCHAR_ALIGN_SEP:
  583. Field++;
  584. p = _tcschr(Field,INFCHAR_ATTR_START);
  585. if(!p) {
  586. p = _tcschr(Field,0);
  587. }
  588. if(pHexToUlonglong(Field, p, &(Align.QuadPart))) {
  589. //
  590. // NOTE: Since these mask values are actually stored in a WDM
  591. // resource list (i.e., IO_RESOURCE_REQUIREMENTS_LIST), there's
  592. // no way to specify an alignment greater than 32 bits. However,
  593. // since the alignment value was implemented as a mask (for
  594. // compatibility with Win9x), we must specify it as a 64-bit
  595. // quantity, since it is applied to a 64-bit value. We will check
  596. // below to ensure that the most significant DWORD is all ones.
  597. //
  598. // Also, we must handle alignment values such as 000F0000, 00FF0000,
  599. // 0FFF0000, and FFFF0000. These all specify 64K alignment (depending
  600. // on the min and max addresses, the INF writer might not need to
  601. // specify all the 1 bits in the 32-bit value).
  602. // Thus we perform an ersatz sign extension of sorts -- we
  603. // find the highest 1 bit and replicate it into all the
  604. // more significant bits in the value.
  605. //
  606. for(u=31; u>=0; u--) {
  607. if(Align.HighPart & (1 << u)) {
  608. break;
  609. }
  610. Align.HighPart |= (1 << u);
  611. }
  612. //
  613. // Make sure that all the bits in the most-significant DWORD are set,
  614. // because we can't express this alignment otherwise (as discussed
  615. // above). Also, make sure that if we encountered a '1' in the high
  616. // dword, then the high bit of the low dword is '1' as well.
  617. //
  618. if((Align.HighPart ^ 0xffffffff) ||
  619. ((u >= 0) && !(Align.LowPart & 0x80000000))) {
  620. d = ERROR_INVALID_INF_LOGCONFIG;
  621. } else {
  622. //
  623. // Do the sign extension for the low dword.
  624. //
  625. for(u=31; u>=0; u--) {
  626. if(Align.LowPart & (1 << u)) {
  627. break;
  628. }
  629. Align.LowPart |= (1 << u);
  630. }
  631. }
  632. } else {
  633. d = ERROR_INVALID_INF_LOGCONFIG;
  634. }
  635. break;
  636. case INFCHAR_DECODE_START:
  637. //
  638. // Get decode value (this determines the IOR_Alias that gets filled
  639. // in for the resdes.
  640. //
  641. Field++;
  642. p = _tcschr(Field,INFCHAR_DECODE_SEP);
  643. if (p) {
  644. if (Field != p) {
  645. pHexToUlonglong(Field,p,&Decode); // got decode value
  646. }
  647. Field = p+1;
  648. p = _tcschr(Field,INFCHAR_DECODE_SEP);
  649. if (p) {
  650. //
  651. // Ignore alias field.
  652. //
  653. Field = p+1;
  654. p = _tcschr(Field,INFCHAR_DECODE_END);
  655. if (p) {
  656. if (Field != p) {
  657. if (*Field == INFCHAR_IOATTR_MEMORY) {
  658. Attributes = fIOD_Memory; // got attribute value
  659. }
  660. }
  661. } else {
  662. d = ERROR_INVALID_INF_LOGCONFIG;
  663. }
  664. } else {
  665. d = ERROR_INVALID_INF_LOGCONFIG;
  666. }
  667. } else {
  668. d = ERROR_INVALID_INF_LOGCONFIG;
  669. }
  670. break;
  671. }
  672. } else {
  673. d = ERROR_INVALID_INF_LOGCONFIG;
  674. }
  675. if(d == NO_ERROR) {
  676. //
  677. // If no range size was specified, then calculate it from
  678. // the given start and end addresses. Since this happens
  679. // when the port requirement was an absolute start/end,
  680. // there is no alignment requirement (i.e., the default
  681. // byte-alignment should be specified).
  682. //
  683. if(RangeSize == 0) {
  684. RangeSize = (DWORD)(End-Start)+1;
  685. Align.QuadPart = DEFAULT_IOPORT_ALIGNMENT;
  686. }
  687. //
  688. // Create an alternate decode flag
  689. //
  690. switch(Decode) {
  691. case INFLOGCONF_IOPORT_10BIT_DECODE:
  692. Attributes |= fIOD_10_BIT_DECODE;
  693. break;
  694. case INFLOGCONF_IOPORT_12BIT_DECODE:
  695. Attributes |= fIOD_12_BIT_DECODE;
  696. break;
  697. case INFLOGCONF_IOPORT_16BIT_DECODE:
  698. Attributes |= fIOD_16_BIT_DECODE;
  699. break;
  700. case INFLOGCONF_IOPORT_POSITIVE_DECODE:
  701. Attributes |= fIOD_POSITIVE_DECODE;
  702. break;
  703. }
  704. //
  705. // Slam values into the header part of the i/o descriptor.
  706. // These will be ignored unless we're setting a forced config.
  707. // Note that the inf had better have specified forced i/o configs
  708. // in a 'simple' form, since we throw away alignment, etc.
  709. //
  710. IoRes->IO_Header.IOD_Alloc_Base = Start;
  711. IoRes->IO_Header.IOD_Alloc_End = Start + RangeSize - 1;
  712. IoRes->IO_Header.IOD_DesFlags = Attributes;
  713. //
  714. // Add this guy into the descriptor we're building up.
  715. //
  716. q = MyRealloc(
  717. IoRes,
  718. offsetof(IO_RESOURCE,IO_Data)
  719. + (sizeof(IO_RANGE)*(IoRes->IO_Header.IOD_Count+1))
  720. );
  721. if(q) {
  722. IoRes = q;
  723. IoRange = &IoRes->IO_Data[IoRes->IO_Header.IOD_Count++];
  724. IoRange->IOR_Align = Align.QuadPart;
  725. IoRange->IOR_nPorts = RangeSize;
  726. IoRange->IOR_Min = Start;
  727. IoRange->IOR_Max = End;
  728. IoRange->IOR_RangeFlags = Attributes;
  729. switch(Decode) {
  730. case INFLOGCONF_IOPORT_10BIT_DECODE:
  731. IoRange->IOR_Alias = IO_ALIAS_10_BIT_DECODE;
  732. break;
  733. case INFLOGCONF_IOPORT_12BIT_DECODE:
  734. IoRange->IOR_Alias = IO_ALIAS_12_BIT_DECODE;
  735. break;
  736. case INFLOGCONF_IOPORT_16BIT_DECODE:
  737. IoRange->IOR_Alias = IO_ALIAS_16_BIT_DECODE;
  738. break;
  739. case INFLOGCONF_IOPORT_POSITIVE_DECODE:
  740. IoRange->IOR_Alias = IO_ALIAS_POSITIVE_DECODE;
  741. break;
  742. default:
  743. d = ERROR_INVALID_INF_LOGCONFIG;
  744. break;
  745. }
  746. } else {
  747. d = ERROR_NOT_ENOUGH_MEMORY;
  748. }
  749. }
  750. }
  751. if((d == NO_ERROR) && IoRes->IO_Header.IOD_Count) {
  752. d = CM_Add_Res_Des_Ex(
  753. &ResDes,
  754. LogConfig,
  755. ResType_IO,
  756. IoRes,
  757. offsetof(IO_RESOURCE,IO_Data) + (sizeof(IO_RANGE) * IoRes->IO_Header.IOD_Count),
  758. 0,
  759. hMachine);
  760. d = MapCrToSpError(d, ERROR_INVALID_DATA);
  761. if(d == NO_ERROR) {
  762. CM_Free_Res_Des_Handle(ResDes);
  763. }
  764. }
  765. if(IoRes) {
  766. MyFree(IoRes);
  767. }
  768. return(d);
  769. }
  770. DWORD
  771. pSetupProcessIrqConfig(
  772. IN LOG_CONF LogConfig,
  773. IN PINFCONTEXT InfLine,
  774. IN HMACHINE hMachine
  775. )
  776. /*++
  777. Routine Description:
  778. Process an IRQConfig line in a Win95 INF. Such lines specify
  779. IRQ requirements for a device. Each line is expected to be
  780. in the form
  781. IRQConfig = [[S][L]:]<IRQNum>,...
  782. S: if present indicates that the interrupt is shareable
  783. L: if present indicates that the interrupt is Level sensitive,
  784. otherwise it is assumed to be edge sensitive.
  785. IRQNum is the IRQ number in decimal.
  786. Arguments:
  787. Return Value:
  788. --*/
  789. {
  790. UINT FieldCount,i;
  791. PCTSTR Field;
  792. DWORD d;
  793. BOOL Shareable;
  794. BOOL Level;
  795. DWORD Irq;
  796. PIRQ_RESOURCE IrqRes;
  797. PIRQ_RANGE IrqRange;
  798. RES_DES ResDes;
  799. PVOID q;
  800. FieldCount = SetupGetFieldCount(InfLine);
  801. if (!FieldCount && GetLastError() != NO_ERROR) {
  802. return GetLastError();
  803. }
  804. if(IrqRes = MyMalloc(offsetof(IRQ_RESOURCE,IRQ_Data))) {
  805. ZeroMemory(IrqRes,offsetof(IRQ_RESOURCE,IRQ_Data));
  806. IrqRes->IRQ_Header.IRQD_Type = IRQType_Range;
  807. d = NO_ERROR;
  808. } else {
  809. d = ERROR_NOT_ENOUGH_MEMORY;
  810. }
  811. Shareable = FALSE;
  812. Level = FALSE;
  813. for(i=1; (d==NO_ERROR) && (i<=FieldCount); i++) {
  814. Field = pSetupGetField(InfLine,i);
  815. //
  816. // For first field, see if we have S: by itself...
  817. //
  818. if((i == 1)
  819. &&((TCHAR)CharUpper((PTSTR)Field[0]) == INFCHAR_IRQATTR_SHARE)
  820. && (Field[1] == INFCHAR_IRQATTR_SEP)) {
  821. Shareable = TRUE;
  822. Field+=2;
  823. }
  824. //
  825. // ... see if we have an L: by itself...
  826. //
  827. if((i == 1)
  828. &&((TCHAR)CharUpper((PTSTR)Field[0]) == INFCHAR_IRQATTR_LEVEL)
  829. && (Field[1] == INFCHAR_IRQATTR_SEP)) {
  830. Level = TRUE;
  831. Field+=2;
  832. }
  833. //
  834. // ... see if we have both attributes.
  835. //
  836. if((i == 1)
  837. && (Field[2] == INFCHAR_IRQATTR_SEP)) {
  838. if (((TCHAR)CharUpper((PTSTR)Field[0]) == INFCHAR_IRQATTR_SHARE)
  839. || (TCHAR)CharUpper((PTSTR)Field[1]) == INFCHAR_IRQATTR_SHARE) {
  840. Shareable = TRUE;
  841. }
  842. if (((TCHAR)CharUpper((PTSTR)Field[0]) == INFCHAR_IRQATTR_LEVEL)
  843. || (TCHAR)CharUpper((PTSTR)Field[1]) == INFCHAR_IRQATTR_LEVEL) {
  844. Level = TRUE;
  845. }
  846. Field+=3;
  847. }
  848. if(pDecimalToUlong(Field,&Irq)) {
  849. //
  850. // Slam values into the header part of the irq descriptor.
  851. // These will be ignored unless we're setting a forced config.
  852. //
  853. IrqRes->IRQ_Header.IRQD_Flags = Shareable ? fIRQD_Share : fIRQD_Exclusive;
  854. IrqRes->IRQ_Header.IRQD_Flags |= Level ? fIRQD_Level : fIRQD_Edge;
  855. IrqRes->IRQ_Header.IRQD_Alloc_Num = Irq;
  856. IrqRes->IRQ_Header.IRQD_Affinity = DEFAULT_IRQ_AFFINITY;
  857. //
  858. // Add this guy into the descriptor we're building up.
  859. //
  860. q = MyRealloc(
  861. IrqRes,
  862. offsetof(IRQ_RESOURCE,IRQ_Data)
  863. + (sizeof(IRQ_RANGE)*(IrqRes->IRQ_Header.IRQD_Count+1))
  864. );
  865. if(q) {
  866. IrqRes = q;
  867. IrqRange = &IrqRes->IRQ_Data[IrqRes->IRQ_Header.IRQD_Count++];
  868. IrqRange->IRQR_Min = Irq;
  869. IrqRange->IRQR_Max = Irq;
  870. IrqRange->IRQR_Flags = Shareable ? fIRQD_Share : fIRQD_Exclusive;
  871. IrqRange->IRQR_Flags |= Level ? fIRQD_Level : fIRQD_Edge;
  872. } else {
  873. d = ERROR_NOT_ENOUGH_MEMORY;
  874. }
  875. } else {
  876. d = ERROR_INVALID_INF_LOGCONFIG;
  877. }
  878. }
  879. if((d == NO_ERROR) && IrqRes->IRQ_Header.IRQD_Count) {
  880. d = CM_Add_Res_Des_Ex(
  881. &ResDes,
  882. LogConfig,
  883. ResType_IRQ,
  884. IrqRes,
  885. offsetof(IRQ_RESOURCE,IRQ_Data) + (sizeof(IRQ_RANGE) * IrqRes->IRQ_Header.IRQD_Count),
  886. 0,
  887. hMachine);
  888. d = MapCrToSpError(d, ERROR_INVALID_DATA);
  889. if(d == NO_ERROR) {
  890. CM_Free_Res_Des_Handle(ResDes);
  891. }
  892. }
  893. if(IrqRes) {
  894. MyFree(IrqRes);
  895. }
  896. return(d);
  897. }
  898. DWORD
  899. pSetupProcessDmaConfig(
  900. IN LOG_CONF LogConfig,
  901. IN PINFCONTEXT InfLine,
  902. IN HMACHINE hMachine
  903. )
  904. /*++
  905. Routine Description:
  906. Process a DMAConfig line in a Win95 INF. Such lines specify
  907. DMA requirements for a device. Each line is expected to be
  908. in the form
  909. DMAConfig = [<attrs>:]<DMANum>,...
  910. if <attrs> is present it can be
  911. D - 32-bit DMA channel
  912. W - 16-bit DMA channel
  913. N - 8-bit DMA channel (default). Specify both W and N if 8- and 16-bit DMA is supported.
  914. M - Bus Mastering
  915. A - Type-A DMA channel
  916. B - Type-B DMA channel
  917. F - Type-F DMA channel
  918. (If none of A, B, or F are specified, then standard DMA is assumed)
  919. DMANum is the DMA channel number in decimal.
  920. Arguments:
  921. Return Value:
  922. --*/
  923. {
  924. UINT FieldCount,i;
  925. PCTSTR Field;
  926. DWORD d;
  927. DWORD Dma;
  928. INT ChannelSize; // fDD_ xxx flags for channel width
  929. INT DmaType; // fDD_ xxx flags for DMA type
  930. PDMA_RESOURCE DmaRes;
  931. PDMA_RANGE DmaRange;
  932. RES_DES ResDes;
  933. PVOID q;
  934. PTCHAR p;
  935. BOOL BusMaster;
  936. ULONG DmaFlags;
  937. ChannelSize = -1;
  938. BusMaster = FALSE;
  939. DmaType = -1;
  940. FieldCount = SetupGetFieldCount(InfLine);
  941. if (!FieldCount && GetLastError() != NO_ERROR) {
  942. return GetLastError();
  943. }
  944. if(DmaRes = MyMalloc(offsetof(DMA_RESOURCE,DMA_Data))) {
  945. ZeroMemory(DmaRes,offsetof(DMA_RESOURCE,DMA_Data));
  946. DmaRes->DMA_Header.DD_Type = DType_Range;
  947. d = NO_ERROR;
  948. } else {
  949. d = ERROR_NOT_ENOUGH_MEMORY;
  950. }
  951. for(i=1; (d==NO_ERROR) && (i<=FieldCount); i++) {
  952. Field = pSetupGetField(InfLine,i);
  953. //
  954. // For first field, see if we have attribute spec.
  955. //
  956. if(i == 1) {
  957. if(p = _tcschr(Field, INFCHAR_IRQATTR_SEP)) {
  958. for( ;((d == NO_ERROR) && (Field < p)); Field++) {
  959. switch((TCHAR)CharUpper((PTSTR)(*Field))) {
  960. //
  961. // Channel size can be both 8 and 16 (i.e., both 'W' and 'N'), but
  962. // you can't mix these with 'D'.
  963. //
  964. case INFCHAR_DMAWIDTH_WORD:
  965. if(ChannelSize == fDD_DWORD) {
  966. d = ERROR_INVALID_INF_LOGCONFIG;
  967. } else if(ChannelSize == fDD_BYTE) {
  968. ChannelSize = fDD_BYTE_AND_WORD;
  969. } else {
  970. ChannelSize = fDD_WORD;
  971. }
  972. break;
  973. case INFCHAR_DMAWIDTH_DWORD:
  974. if((ChannelSize != -1) && (ChannelSize != fDD_DWORD)) {
  975. d = ERROR_INVALID_INF_LOGCONFIG;
  976. } else {
  977. ChannelSize = fDD_DWORD;
  978. }
  979. break;
  980. case INFCHAR_DMAWIDTH_NARROW:
  981. if(ChannelSize == fDD_DWORD) {
  982. d = ERROR_INVALID_INF_LOGCONFIG;
  983. } else if(ChannelSize == fDD_WORD) {
  984. ChannelSize = fDD_BYTE_AND_WORD;
  985. } else {
  986. ChannelSize = fDD_BYTE;
  987. }
  988. break;
  989. case INFCHAR_DMA_BUSMASTER:
  990. BusMaster = TRUE;
  991. break;
  992. //
  993. // The DMA types are mutually exclusive...
  994. //
  995. case INFCHAR_DMATYPE_A:
  996. if((DmaType != -1) && (DmaType != fDD_TypeA)) {
  997. d = ERROR_INVALID_INF_LOGCONFIG;
  998. } else {
  999. DmaType = fDD_TypeA;
  1000. }
  1001. break;
  1002. case INFCHAR_DMATYPE_B:
  1003. if((DmaType != -1) && (DmaType != fDD_TypeB)) {
  1004. d = ERROR_INVALID_INF_LOGCONFIG;
  1005. } else {
  1006. DmaType = fDD_TypeB;
  1007. }
  1008. break;
  1009. case INFCHAR_DMATYPE_F:
  1010. if((DmaType != -1) && (DmaType != fDD_TypeF)) {
  1011. d = ERROR_INVALID_INF_LOGCONFIG;
  1012. } else {
  1013. DmaType = fDD_TypeF;
  1014. }
  1015. break;
  1016. default:
  1017. d = ERROR_INVALID_INF_LOGCONFIG;
  1018. break;
  1019. }
  1020. }
  1021. Field++; // skip over separator character
  1022. }
  1023. if(ChannelSize == -1) {
  1024. DmaFlags = fDD_BYTE; // default is 8-bit DMA
  1025. } else {
  1026. DmaFlags = (ULONG)ChannelSize;
  1027. }
  1028. if(BusMaster) {
  1029. DmaFlags |= fDD_BusMaster;
  1030. }
  1031. if(DmaType != -1) {
  1032. DmaFlags |= DmaType;
  1033. }
  1034. }
  1035. if(d == NO_ERROR) {
  1036. if(pDecimalToUlong(Field,&Dma)) {
  1037. //
  1038. // Slam values into the header part of the dma descriptor.
  1039. // These will be ignored unless we're setting a forced config.
  1040. //
  1041. DmaRes->DMA_Header.DD_Flags = DmaFlags;
  1042. DmaRes->DMA_Header.DD_Alloc_Chan = Dma;
  1043. //
  1044. // Add this guy into the descriptor we're building up.
  1045. //
  1046. q = MyRealloc(
  1047. DmaRes,
  1048. offsetof(DMA_RESOURCE,DMA_Data)
  1049. + (sizeof(DMA_RANGE)*(DmaRes->DMA_Header.DD_Count+1))
  1050. );
  1051. if(q) {
  1052. DmaRes = q;
  1053. DmaRange = &DmaRes->DMA_Data[DmaRes->DMA_Header.DD_Count++];
  1054. DmaRange->DR_Min = Dma;
  1055. DmaRange->DR_Max = Dma;
  1056. DmaRange->DR_Flags = DmaFlags;
  1057. } else {
  1058. d = ERROR_NOT_ENOUGH_MEMORY;
  1059. }
  1060. } else {
  1061. d = ERROR_INVALID_INF_LOGCONFIG;
  1062. }
  1063. }
  1064. }
  1065. if((d == NO_ERROR) && DmaRes->DMA_Header.DD_Count) {
  1066. d = CM_Add_Res_Des_Ex(
  1067. &ResDes,
  1068. LogConfig,
  1069. ResType_DMA,
  1070. DmaRes,
  1071. offsetof(DMA_RESOURCE,DMA_Data) + (sizeof(DMA_RANGE) * DmaRes->DMA_Header.DD_Count),
  1072. 0,
  1073. hMachine);
  1074. d = MapCrToSpError(d, ERROR_INVALID_DATA);
  1075. if(d == NO_ERROR) {
  1076. CM_Free_Res_Des_Handle(ResDes);
  1077. }
  1078. }
  1079. if(DmaRes) {
  1080. MyFree(DmaRes);
  1081. }
  1082. return(d);
  1083. }
  1084. DWORD
  1085. pSetupProcessPcCardConfig(
  1086. IN LOG_CONF LogConfig,
  1087. IN PINFCONTEXT InfLine,
  1088. IN HMACHINE hMachine
  1089. )
  1090. /*++
  1091. Routine Description:
  1092. Process a PcCardConfig line in a Win95 INF. Such lines specify
  1093. PC Card (PCMCIA) configuration information necessary for a device.
  1094. Each line is expected to be in the form
  1095. PcCardConfig = <ConfigIndex>[:[<MemoryCardBase1>][:<MemoryCardBase2>]][(<attrs>)]
  1096. where
  1097. <ConfigIndex> is the 8-bit PCMCIA configuration index
  1098. <MemoryCardBase1> is the (optional) 32-bit 1st memory base address
  1099. <MemoryCardBase2> is the (optional) 32-bit 2nd memory base address
  1100. <attrs> is a combination of attribute specifiers optionally separated by
  1101. spaces. The attribute string is processed from left to right,
  1102. and an invalid attribute specifier aborts the entire PcCardConfig
  1103. directive. Attributes may be specified in any order except for the
  1104. positional attributes 'A' and 'C', which are described below.
  1105. Accepted attribute specifiers are as follows:
  1106. W - 16-bit I/O data path (default: 16-bit)
  1107. B - 8-bit I/O data path (default: 16-bit)
  1108. Sn - ~IOCS16 source. If n is zero, ~IOCS16 is based on the value of
  1109. the datasize bit. If n is one, ~IOCS16 is based on the ~IOIS16
  1110. signal from the device. (default: 1)
  1111. Zn - I/O 8-bit zero wait state. If n is one, 8-bit I/O accesses occur
  1112. with zero additional wait states. If n is zero, access will
  1113. occur with additional wait states. This flag has no meaning for
  1114. 16-bit I/O. (default: 0)
  1115. XIn - I/O wait states. If n is one, 16-bit system accesses occur with
  1116. 1 additional wait state. (default: 1)
  1117. M - 16-bit Memory (default: 8-bit)
  1118. M8 - 8-bit Memory (default: 8-bit)
  1119. XMn - Memory wait states, where n can be 0, 1, 2 or 3. This value
  1120. determines the number of additional wait states for 16-bit
  1121. accesses to a memory window. (default: 3)
  1122. NOTE: The following two attributes relate positionally to memory
  1123. windows resources. That is, the first 'A' or 'C' specified in the
  1124. attribute string (reading from left to right) corresponds to the
  1125. first memory resource in the device's resource list. The next
  1126. 'A' or 'C' corresponds to the second memory resource. Subsequent
  1127. attribute/common memory specifiers are ignored.
  1128. A - Memory range to be mapped as Attribute memory
  1129. C - Memory range to be mapped as Common Memory (default)
  1130. Example:
  1131. (W CA M XM1 XI0) translates to:
  1132. I/O 16bit
  1133. 1st memory window is common
  1134. 2nd memory window is attribute
  1135. Memory 16 bit
  1136. one wait state on memory windows
  1137. zero wait states on i/o windows
  1138. All numeric values are assumed to be in hexadecimal format.
  1139. Arguments:
  1140. Return Value:
  1141. --*/
  1142. {
  1143. PCCARD_RESOURCE PcCardResource;
  1144. PCTSTR Field, p;
  1145. DWORD ConfigIndex, i, d;
  1146. DWORD MemoryCardBase[PCD_MAX_MEMORY] = {0};
  1147. DWORD Flags;
  1148. UINT memAttrIndex = 0, memWaitIndex = 0, memWidthIndex = 0;
  1149. UINT ioSourceIndex = 0, ioZeroWait8Index = 0, ioWaitState16Index = 0, ioWidthIndex = 0;
  1150. UINT index;
  1151. RES_DES ResDes;
  1152. //
  1153. // Assume failure
  1154. //
  1155. d = ERROR_INVALID_INF_LOGCONFIG;
  1156. //
  1157. // We should have one field (not counting the line's key)
  1158. //
  1159. if(SetupGetFieldCount(InfLine) != 1) {
  1160. goto clean0;
  1161. } else {
  1162. Field = pSetupGetField(InfLine, 1);
  1163. }
  1164. //
  1165. // Retrieve the ConfigIndex. It may be terminated by either a colon ':',
  1166. // an open paren '(', or eol.
  1167. //
  1168. if(!(p = _tcschr(Field, INFCHAR_PCCARD_SEP)) && !(p = _tcschr(Field, INFCHAR_ATTR_START))) {
  1169. p = Field + lstrlen(Field);
  1170. }
  1171. if(!pHexToUlong(Field, p, &ConfigIndex) || (ConfigIndex > 255)) {
  1172. goto clean0;
  1173. }
  1174. //
  1175. // Process the (optional) memory card base addresses
  1176. //
  1177. for(i = 0; i < PCD_MAX_MEMORY; i++) {
  1178. if(*p == INFCHAR_PCCARD_SEP) {
  1179. Field = p + 1;
  1180. if(!(p = _tcschr(Field, INFCHAR_PCCARD_SEP)) && !(p = _tcschr(Field, INFCHAR_ATTR_START))) {
  1181. p = Field + lstrlen(Field);
  1182. }
  1183. //
  1184. // Allow an empty field.
  1185. //
  1186. if(Field == p) {
  1187. MemoryCardBase[i] = 0;
  1188. } else if(!pHexToUlong(Field, p, &(MemoryCardBase[i]))) {
  1189. goto clean0;
  1190. }
  1191. } else {
  1192. MemoryCardBase[i] = 0;
  1193. }
  1194. }
  1195. //
  1196. // Initialize the flags
  1197. //
  1198. Flags = fPCD_ATTRIBUTES_PER_WINDOW |
  1199. fPCD_MEM1_WS_THREE | fPCD_MEM2_WS_THREE |
  1200. fPCD_IO1_SRC_16 | fPCD_IO2_SRC_16 |
  1201. fPCD_IO1_WS_16 | fPCD_IO2_WS_16;
  1202. if(*p && (*p == INFCHAR_ATTR_START)) {
  1203. //
  1204. // Read the attributes.
  1205. // W - 16-bit I/O data path
  1206. // B - 8-bit I/O data path
  1207. // Sn - ~IOCS16 source.
  1208. // Zn - I/O 8-bit zero wait state.
  1209. // XIn - I/O wait states.
  1210. // M - 16-bit Memory
  1211. // M8 - 8-bit Memory
  1212. // XMn - Memory wait states
  1213. // A - Attribute Memory
  1214. // C - Common Memory
  1215. //
  1216. Field = ++p;
  1217. if(!(p = _tcschr(Field,INFCHAR_ATTR_END))) {
  1218. goto clean0;
  1219. }
  1220. while(Field < p) {
  1221. switch((TCHAR)CharUpper((PTSTR)(*Field))) {
  1222. case INFCHAR_PCCARD_IOATTR_WORD:
  1223. if (ioWidthIndex >= PCD_MAX_IO) {
  1224. goto clean0;
  1225. }
  1226. Flags |= (ioWidthIndex++ ? fPCD_IO2_16
  1227. : (fPCD_IO1_16 | fPCD_IO2_16));
  1228. break;
  1229. case INFCHAR_PCCARD_IOATTR_BYTE:
  1230. if (ioWidthIndex >= PCD_MAX_IO) {
  1231. goto clean0;
  1232. }
  1233. Flags &= (ioWidthIndex++ ? ~fPCD_IO2_16
  1234. : ~(fPCD_IO1_16 | fPCD_IO2_16));
  1235. break;
  1236. case INFCHAR_PCCARD_MEMATTR_WORD:
  1237. if (memWidthIndex >= PCD_MAX_MEMORY) {
  1238. goto clean0;
  1239. }
  1240. if (++Field < p) {
  1241. if (*Field == TEXT('8')) {
  1242. Flags &= (memWidthIndex++ ? ~fPCD_MEM2_16
  1243. : ~(fPCD_MEM1_16 | fPCD_MEM2_16));
  1244. break;
  1245. }
  1246. // not an 8, back up 1
  1247. --Field;
  1248. }
  1249. Flags |= (memWidthIndex++ ? fPCD_MEM2_16
  1250. : (fPCD_MEM1_16 | fPCD_MEM2_16));
  1251. break;
  1252. case INFCHAR_PCCARD_MEM_ISATTR:
  1253. if (memAttrIndex >= PCD_MAX_MEMORY) {
  1254. goto clean0;
  1255. }
  1256. Flags |= (memAttrIndex++ ? fPCD_MEM2_A
  1257. : (fPCD_MEM1_A | fPCD_MEM2_A));
  1258. break;
  1259. case INFCHAR_PCCARD_MEM_ISCOMMON:
  1260. if (memAttrIndex >= PCD_MAX_MEMORY) {
  1261. goto clean0;
  1262. }
  1263. Flags &= (memAttrIndex++ ? ~fPCD_MEM2_A
  1264. : ~(fPCD_MEM1_A | fPCD_MEM2_A));
  1265. break;
  1266. case INFCHAR_PCCARD_IOATTR_SRC:
  1267. if (ioSourceIndex >= PCD_MAX_IO) {
  1268. goto clean0;
  1269. }
  1270. if (++Field < p) {
  1271. if (*Field == TEXT('0')) {
  1272. Flags &= (ioSourceIndex++ ? ~fPCD_IO2_SRC_16
  1273. : ~(fPCD_IO1_SRC_16 | fPCD_IO2_SRC_16));
  1274. } else if (*Field == TEXT('1')) {
  1275. Flags |= (ioSourceIndex++ ? fPCD_IO2_SRC_16
  1276. : (fPCD_IO1_SRC_16 | fPCD_IO2_SRC_16));
  1277. } else {
  1278. goto clean0;
  1279. }
  1280. }
  1281. break;
  1282. case INFCHAR_PCCARD_IOATTR_Z8:
  1283. if (ioZeroWait8Index >= PCD_MAX_IO) {
  1284. goto clean0;
  1285. }
  1286. if (++Field < p) {
  1287. if (*Field == TEXT('0')) {
  1288. Flags &= (ioZeroWait8Index++ ? ~fPCD_IO2_ZW_8
  1289. : ~(fPCD_IO1_ZW_8 | fPCD_IO2_ZW_8));
  1290. } else if (*Field == TEXT('1')) {
  1291. Flags |= (ioZeroWait8Index++ ? fPCD_IO2_ZW_8
  1292. : (fPCD_IO1_ZW_8 | fPCD_IO2_ZW_8));
  1293. } else {
  1294. goto clean0;
  1295. }
  1296. }
  1297. break;
  1298. case INFCHAR_PCCARD_ATTR_WAIT:
  1299. if (++Field < p) {
  1300. switch((TCHAR)CharUpper((PTSTR)(*Field))) {
  1301. case INFCHAR_PCCARD_ATTR_WAITI:
  1302. if (ioWaitState16Index >= PCD_MAX_IO) {
  1303. goto clean0;
  1304. }
  1305. if (++Field < p) {
  1306. if (*Field == TEXT('0')) {
  1307. Flags &= (ioWaitState16Index++ ? ~fPCD_IO2_WS_16
  1308. : ~(fPCD_IO1_WS_16 | fPCD_IO2_WS_16));
  1309. } else if (*Field == TEXT('1')) {
  1310. Flags |= (ioWaitState16Index++ ? fPCD_IO2_WS_16
  1311. : (fPCD_IO1_WS_16 | fPCD_IO2_WS_16));
  1312. } else {
  1313. goto clean0;
  1314. }
  1315. }
  1316. break;
  1317. case INFCHAR_PCCARD_ATTR_WAITM:
  1318. if (memWaitIndex >= PCD_MAX_MEMORY) {
  1319. goto clean0;
  1320. }
  1321. if (++Field < p) {
  1322. Flags &= (memWaitIndex ? ~mPCD_MEM2_WS
  1323. : ~(mPCD_MEM1_WS | mPCD_MEM2_WS));
  1324. if (*Field == TEXT('0')) {
  1325. memWaitIndex++;
  1326. } else if (*Field == TEXT('1')) {
  1327. Flags |= (memWaitIndex++ ? fPCD_MEM2_WS_ONE
  1328. : (fPCD_MEM1_WS_ONE | fPCD_MEM2_WS_ONE));
  1329. } else if (*Field == TEXT('2')) {
  1330. Flags |= (memWaitIndex++ ? fPCD_MEM2_WS_TWO
  1331. : (fPCD_MEM1_WS_TWO | fPCD_MEM2_WS_TWO));
  1332. } else if (*Field == TEXT('3')) {
  1333. Flags |= (memWaitIndex++ ? fPCD_MEM2_WS_THREE
  1334. : (fPCD_MEM1_WS_THREE | fPCD_MEM2_WS_THREE));
  1335. } else {
  1336. goto clean0;
  1337. }
  1338. }
  1339. break;
  1340. default:
  1341. goto clean0;
  1342. }
  1343. }
  1344. break;
  1345. case INFCHAR_PCCARD_ATTR_SEP:
  1346. break;
  1347. default:
  1348. // unknown character
  1349. goto clean0;
  1350. }
  1351. if (Field < p) {
  1352. Field++;
  1353. }
  1354. }
  1355. }
  1356. //
  1357. // If we get to here, then we've successfully retrieved all the necessary information
  1358. // needed to initialize the PC Card configuration resource descriptor.
  1359. //
  1360. ZeroMemory(&PcCardResource, sizeof(PcCardResource));
  1361. PcCardResource.PcCard_Header.PCD_Count = 1;
  1362. PcCardResource.PcCard_Header.PCD_Flags = Flags;
  1363. PcCardResource.PcCard_Header.PCD_ConfigIndex = (BYTE)ConfigIndex;
  1364. PcCardResource.PcCard_Header.PCD_MemoryCardBase1 = MemoryCardBase[0];
  1365. PcCardResource.PcCard_Header.PCD_MemoryCardBase2 = MemoryCardBase[1];
  1366. d = CM_Add_Res_Des_Ex(
  1367. &ResDes,
  1368. LogConfig,
  1369. ResType_PcCardConfig,
  1370. &PcCardResource,
  1371. sizeof(PcCardResource),
  1372. 0,
  1373. hMachine);
  1374. d = MapCrToSpError(d, ERROR_INVALID_DATA);
  1375. if(d == NO_ERROR) {
  1376. CM_Free_Res_Des_Handle(ResDes);
  1377. }
  1378. clean0:
  1379. return d;
  1380. }
  1381. DWORD
  1382. pSetupProcessMfCardConfig(
  1383. IN LOG_CONF LogConfig,
  1384. IN PINFCONTEXT InfLine,
  1385. IN HMACHINE hMachine
  1386. )
  1387. /*++
  1388. Routine Description:
  1389. Process a MfCardConfig line in a Win95 INF. Such lines specify
  1390. PCMCIA Multifunction card configuration information necessary for a device.
  1391. There should normally be one MfCardConfig line per function. Each line is expected
  1392. to be in the form:
  1393. MfCardConfig = <ConfigRegBase>:<ConfigOptions>[:<IoResourceIndex>][(<attrs>)]
  1394. where
  1395. <ConfigRegBase> is the attribute offset of this function's
  1396. configuration registers
  1397. <ConfigOptions> is the 8-bit PCMCIA configuration option register
  1398. <IoResourceIndex> is the (optional) index to the Port Io resource descriptor
  1399. which will be used to program the configuration I/O base
  1400. and limit registers
  1401. <attrs> is the optional set of attribute flags which can consist of:
  1402. A - Audio enable should be set on in the configuration and status register
  1403. All numeric values are assumed to be in hexadecimal format.
  1404. Arguments:
  1405. Return Value:
  1406. --*/
  1407. {
  1408. MFCARD_RESOURCE MfCardResource;
  1409. PCTSTR Field, p;
  1410. DWORD ConfigOptions, i;
  1411. DWORD ConfigRegisterBase, IoResourceIndex;
  1412. DWORD Flags = 0;
  1413. DWORD d = NO_ERROR;
  1414. RES_DES ResDes;
  1415. //
  1416. // We should have one field (not counting the line's key)
  1417. //
  1418. if(SetupGetFieldCount(InfLine) != 1) {
  1419. d = ERROR_INVALID_INF_LOGCONFIG;
  1420. }
  1421. if (d == NO_ERROR) {
  1422. //
  1423. // Retrieve the ConfigRegisterBase. It must be terminated by a colon.
  1424. //
  1425. Field = pSetupGetField(InfLine, 1);
  1426. p = _tcschr(Field, INFCHAR_PCCARD_SEP);
  1427. if(!p || !pHexToUlong(Field, p, &ConfigRegisterBase)) {
  1428. d = ERROR_INVALID_INF_LOGCONFIG;
  1429. }
  1430. }
  1431. if (d == NO_ERROR) {
  1432. //
  1433. // Retrieve the ConfigOptions. It may be terminated by either a colon ':',
  1434. // an open paren '(', or eol.
  1435. //
  1436. Field = p + 1;
  1437. if(!(p = _tcschr(Field, INFCHAR_PCCARD_SEP)) && !(p = _tcschr(Field, INFCHAR_ATTR_START))) {
  1438. p = Field + lstrlen(Field);
  1439. }
  1440. if(!pHexToUlong(Field, p, &ConfigOptions) || (ConfigOptions > 255)) {
  1441. d = ERROR_INVALID_INF_LOGCONFIG;
  1442. }
  1443. }
  1444. if ((d == NO_ERROR) && (*p == INFCHAR_PCCARD_SEP)) {
  1445. //
  1446. // Retrieve the IoResourceIndex. It may be terminated by either
  1447. // an open paren '(', or eol.
  1448. //
  1449. Field = p + 1;
  1450. if(!(p = _tcschr(Field, INFCHAR_ATTR_START))) {
  1451. p = Field + lstrlen(Field);
  1452. }
  1453. if(!pHexToUlong(Field, p, &IoResourceIndex) || (IoResourceIndex > 255)) {
  1454. d = ERROR_INVALID_INF_LOGCONFIG;
  1455. }
  1456. }
  1457. if ((d == NO_ERROR) && (*p == INFCHAR_ATTR_START)) {
  1458. //
  1459. // Retrieve the attributes.
  1460. //
  1461. while (TRUE) {
  1462. p++;
  1463. if (!*p) {
  1464. // Didn't find a close paren
  1465. d = ERROR_INVALID_INF_LOGCONFIG;
  1466. break;
  1467. }
  1468. if (*p == INFCHAR_ATTR_END) {
  1469. if (*(p+1)) {
  1470. // found garbage after the close paren
  1471. d = ERROR_INVALID_INF_LOGCONFIG;
  1472. }
  1473. break;
  1474. }
  1475. if ((TCHAR)CharUpper((PTSTR)*p) == INFCHAR_MFCARD_AUDIO_ATTR) {
  1476. Flags |= fPMF_AUDIO_ENABLE;
  1477. } else {
  1478. // bad flag
  1479. d = ERROR_INVALID_INF_LOGCONFIG;
  1480. break;
  1481. }
  1482. }
  1483. }
  1484. if(d == NO_ERROR) {
  1485. //
  1486. // If we get to here, then we've successfully retrieved all the necessary information
  1487. // needed to initialize the multifunction PC Card configuration resource descriptor.
  1488. //
  1489. ZeroMemory(&MfCardResource, sizeof(MfCardResource));
  1490. MfCardResource.MfCard_Header.PMF_Count = 1;
  1491. MfCardResource.MfCard_Header.PMF_Flags = Flags;
  1492. MfCardResource.MfCard_Header.PMF_ConfigOptions = (BYTE)ConfigOptions;
  1493. MfCardResource.MfCard_Header.PMF_IoResourceIndex = (BYTE)IoResourceIndex;
  1494. MfCardResource.MfCard_Header.PMF_ConfigRegisterBase = ConfigRegisterBase;
  1495. d = CM_Add_Res_Des_Ex(
  1496. &ResDes,
  1497. LogConfig,
  1498. ResType_MfCardConfig,
  1499. &MfCardResource,
  1500. sizeof(MfCardResource),
  1501. 0,
  1502. hMachine);
  1503. d = MapCrToSpError(d, ERROR_INVALID_DATA);
  1504. if(d == NO_ERROR) {
  1505. CM_Free_Res_Des_Handle(ResDes);
  1506. }
  1507. }
  1508. return d;
  1509. }
  1510. #if 0
  1511. DWORD
  1512. pSetupProcessLogConfigLines(
  1513. IN PVOID Inf,
  1514. IN PCTSTR SectionName,
  1515. IN PCTSTR KeyName,
  1516. IN DWORD (*CallbackFunc)(LOG_CONFIG,PINFCONTEXT,HMACHINE),
  1517. IN LOG_CONF LogConfig,
  1518. IN HMACHINE hMachine
  1519. )
  1520. {
  1521. BOOL b;
  1522. DWORD d;
  1523. INFCONTEXT InfLine;
  1524. b = SetupFindFirstLine(Inf,SectionName,KeyName,&InfLine);
  1525. d = NO_ERROR;
  1526. //
  1527. // Process each line with a key that matches.
  1528. //
  1529. while(b && (d == NO_ERROR)) {
  1530. d = CallbackFunc(LogConfig,&InfLine, hMachine);
  1531. if(d == NO_ERROR) {
  1532. b = SetupFindNextMatchLine(&InfLine,KeyName,&InfLine);
  1533. }
  1534. }
  1535. return(d);
  1536. }
  1537. #endif
  1538. DWORD
  1539. pSetupProcessConfigPriority(
  1540. IN PVOID Inf,
  1541. IN PCTSTR SectionName,
  1542. IN LOG_CONF LogConfig,
  1543. OUT PRIORITY *PriorityValue,
  1544. OUT DWORD *ConfigType,
  1545. IN DWORD Flags
  1546. )
  1547. {
  1548. INFCONTEXT InfLine;
  1549. PCTSTR PrioritySpec;
  1550. PCTSTR ConfigSpec;
  1551. DWORD d = NO_ERROR;
  1552. INT_PTR v;
  1553. //
  1554. // We only need to fetch one of these lines and look at the
  1555. // first value on it.
  1556. //
  1557. if(SetupFindFirstLine(Inf,SectionName,pszConfigPriority,&InfLine)
  1558. && (PrioritySpec = pSetupGetField(&InfLine,1))) {
  1559. if(!LookUpStringInTable(InfPrioritySpecToPriority,PrioritySpec,&v)) {
  1560. d = ERROR_INVALID_INF_LOGCONFIG;
  1561. } else {
  1562. *PriorityValue = (PRIORITY)v;
  1563. //
  1564. // The second value is optional and specifies whether the config is forced,
  1565. // standard (i.e., basic), or override. If the value isn't specified then
  1566. // assume basic, unless the Flags tell us otherwise.
  1567. //
  1568. ConfigSpec = pSetupGetField(&InfLine,2);
  1569. if(!ConfigSpec || !*ConfigSpec) {
  1570. if(Flags & SPINST_LOGCONFIG_IS_FORCED) {
  1571. *ConfigType = FORCED_LOG_CONF;
  1572. } else if(Flags & SPINST_LOGCONFIGS_ARE_OVERRIDES) {
  1573. *ConfigType = OVERRIDE_LOG_CONF;
  1574. } else {
  1575. *ConfigType = BASIC_LOG_CONF;
  1576. }
  1577. } else {
  1578. if(LookUpStringInTable(InfConfigSpecToConfig, ConfigSpec, &v)) {
  1579. *ConfigType = (DWORD)v;
  1580. //
  1581. // A valid ConfigType was specified. Let's make sure it doesn't disagree
  1582. // with any flags that were passed in to this routine.
  1583. //
  1584. if(Flags & SPINST_LOGCONFIG_IS_FORCED) {
  1585. if(*ConfigType != FORCED_LOG_CONF) {
  1586. d = ERROR_INVALID_INF_LOGCONFIG;
  1587. }
  1588. } else if(Flags & SPINST_LOGCONFIGS_ARE_OVERRIDES) {
  1589. if(*ConfigType != OVERRIDE_LOG_CONF) {
  1590. d = ERROR_INVALID_INF_LOGCONFIG;
  1591. }
  1592. }
  1593. } else {
  1594. d = ERROR_INVALID_INF_LOGCONFIG;
  1595. }
  1596. }
  1597. }
  1598. //
  1599. // If we successfully determined the LogConfig type as FORCED_LOG_CONF, then
  1600. // set the priority to LCPRI_FORCECONFIG.
  1601. //
  1602. if((d == NO_ERROR) && (*ConfigType == FORCED_LOG_CONF)) {
  1603. *PriorityValue = LCPRI_FORCECONFIG;
  1604. }
  1605. } else {
  1606. *PriorityValue = (Flags & SPINST_LOGCONFIG_IS_FORCED) ? LCPRI_FORCECONFIG : LCPRI_NORMAL;
  1607. if(Flags & SPINST_LOGCONFIG_IS_FORCED) {
  1608. *ConfigType = FORCED_LOG_CONF;
  1609. } else if(Flags & SPINST_LOGCONFIGS_ARE_OVERRIDES) {
  1610. *ConfigType = OVERRIDE_LOG_CONF;
  1611. } else {
  1612. *ConfigType = BASIC_LOG_CONF;
  1613. }
  1614. }
  1615. return d;
  1616. }
  1617. DWORD
  1618. pSetupProcessLogConfigSection(
  1619. IN PVOID Inf,
  1620. IN PCTSTR SectionName,
  1621. IN DEVINST DevInst,
  1622. IN DWORD Flags,
  1623. IN HMACHINE hMachine
  1624. )
  1625. {
  1626. DWORD d;
  1627. LOG_CONF LogConfig;
  1628. PRIORITY Priority;
  1629. DWORD ConfigType;
  1630. CONFIGRET cr;
  1631. DWORD LineIndex = 0;
  1632. INFCONTEXT InfLine;
  1633. TCHAR Key[MAX_LOGCONFKEYSTR_LEN];
  1634. //
  1635. // Process config priority values.
  1636. //
  1637. //
  1638. // LogConfig is used before initialized in following call.
  1639. // It doesn't matter to function being called, but 6.0 compiler
  1640. // doesn't like it, so init to 0.
  1641. //
  1642. LogConfig = 0;
  1643. d = pSetupProcessConfigPriority(Inf,SectionName,LogConfig,&Priority,&ConfigType,Flags);
  1644. if(d != NO_ERROR) {
  1645. goto c0;
  1646. }
  1647. //
  1648. // Now that we know the priority we can create an empty log config.
  1649. //
  1650. d = MapCrToSpError(CM_Add_Empty_Log_Conf_Ex(&LogConfig,DevInst,Priority,ConfigType,hMachine),
  1651. ERROR_INVALID_DATA
  1652. );
  1653. if(d != NO_ERROR) {
  1654. goto c0;
  1655. }
  1656. //
  1657. // Iterate over the lines in the section adding entries to the log config in
  1658. // the same order as they are found.
  1659. //
  1660. if (SetupFindFirstLine(Inf,SectionName,NULL,&InfLine)) {
  1661. do {
  1662. //
  1663. // Get the key.
  1664. //
  1665. if (!SetupGetStringField(&InfLine,
  1666. 0, // Index 0 is the key field
  1667. Key,
  1668. MAX_LOGCONFKEYSTR_LEN,
  1669. NULL
  1670. )) {
  1671. //
  1672. // Either we didn't have a key or its longer than the longest
  1673. // valid key - either way its invalid
  1674. //
  1675. d = ERROR_INVALID_INF_LOGCONFIG;
  1676. goto c1;
  1677. }
  1678. if (!lstrcmpi(Key, pszMemConfig)) {
  1679. //
  1680. // Process MemConfig lines
  1681. //
  1682. d = pSetupProcessMemConfig(LogConfig, &InfLine, hMachine);
  1683. } else if (!lstrcmpi(Key, pszIOConfig)) {
  1684. //
  1685. // Process IoConfig lines
  1686. //
  1687. d = pSetupProcessIoConfig(LogConfig, &InfLine, hMachine);
  1688. } else if (!lstrcmpi(Key, pszIRQConfig)) {
  1689. //
  1690. // Process IRQConfig lines
  1691. //
  1692. d = pSetupProcessIrqConfig(LogConfig, &InfLine, hMachine);
  1693. } else if (!lstrcmpi(Key, pszDMAConfig)) {
  1694. //
  1695. // Process DMAConfig lines
  1696. //
  1697. d = pSetupProcessDmaConfig(LogConfig, &InfLine, hMachine);
  1698. } else if (!lstrcmpi(Key, pszPcCardConfig)) {
  1699. //
  1700. // Process PcCardConfig lines
  1701. //
  1702. d = pSetupProcessPcCardConfig(LogConfig, &InfLine, hMachine);
  1703. } else if (!lstrcmpi(Key, pszMfCardConfig)) {
  1704. //
  1705. // Process MfCardConfig lines
  1706. //
  1707. d = pSetupProcessMfCardConfig(LogConfig, &InfLine, hMachine);
  1708. } else {
  1709. //
  1710. // If we don't understand the line skip it
  1711. //
  1712. d = NO_ERROR;
  1713. }
  1714. } while (d == NO_ERROR && SetupFindNextMatchLine(&InfLine,NULL,&InfLine));
  1715. }
  1716. #if 0
  1717. //
  1718. // Process MemConfig lines
  1719. //
  1720. d = pSetupProcessLogConfigLines(
  1721. Inf,
  1722. SectionName,
  1723. pszMemConfig,
  1724. pSetupProcessMemConfig,
  1725. LogConfig,
  1726. hMachine
  1727. );
  1728. if(d != NO_ERROR) {
  1729. goto c1;
  1730. }
  1731. //
  1732. // Process IOConfig lines
  1733. //
  1734. d = pSetupProcessLogConfigLines(
  1735. Inf,
  1736. SectionName,
  1737. pszIOConfig,
  1738. pSetupProcessIoConfig,
  1739. LogConfig,
  1740. hMachine
  1741. );
  1742. if(d != NO_ERROR) {
  1743. goto c1;
  1744. }
  1745. //
  1746. // Process IRQConfig lines
  1747. //
  1748. d = pSetupProcessLogConfigLines(
  1749. Inf,
  1750. SectionName,
  1751. pszIRQConfig,
  1752. pSetupProcessIrqConfig,
  1753. LogConfig,
  1754. hMachine
  1755. );
  1756. if(d != NO_ERROR) {
  1757. goto c1;
  1758. }
  1759. //
  1760. // Process DMAConfig lines
  1761. //
  1762. d = pSetupProcessLogConfigLines(
  1763. Inf,
  1764. SectionName,
  1765. pszDMAConfig,
  1766. pSetupProcessDmaConfig,
  1767. LogConfig,
  1768. hMachine
  1769. );
  1770. if(d != NO_ERROR) {
  1771. goto c1;
  1772. }
  1773. //
  1774. // Process PcCardConfig lines
  1775. //
  1776. d = pSetupProcessLogConfigLines(
  1777. Inf,
  1778. SectionName,
  1779. pszPcCardConfig,
  1780. pSetupProcessPcCardConfig,
  1781. LogConfig,
  1782. hMachine
  1783. );
  1784. #endif
  1785. c1:
  1786. if(d != NO_ERROR) {
  1787. CM_Free_Log_Conf(LogConfig,0);
  1788. }
  1789. CM_Free_Log_Conf_Handle(LogConfig);
  1790. c0:
  1791. return(d);
  1792. }
  1793. DWORD
  1794. pSetupInstallLogConfig(
  1795. IN HINF Inf,
  1796. IN PCTSTR SectionName,
  1797. IN DEVINST DevInst,
  1798. IN DWORD Flags,
  1799. IN HMACHINE hMachine
  1800. )
  1801. /*++
  1802. Routine Description:
  1803. Look for logical configuration directives within an inf section
  1804. and parse them. Each value on the LogConf= line is taken to be
  1805. the name of a logical config section.
  1806. Arguments:
  1807. Inf - supplies inf handle for inf containing the section indicated
  1808. by SectionName.
  1809. SectionName - supplies name of install section.
  1810. DevInst - device instance handle for log configs.
  1811. Flags - supplies flags that modify the behavior of this routine. The
  1812. following flags are payed attention to, everything else is ignored:
  1813. SPINST_SINGLESECTION - if this bit is set, then the specified section
  1814. is a LogConf section, instead of an install
  1815. section containing LogConf entries.
  1816. SPINST_LOGCONFIG_IS_FORCED - if this bit is set, then the LogConfigs
  1817. to be written out are forced configs.
  1818. If the ConfigType field of the ConfigPriority
  1819. entry is present, and specifies something
  1820. other than FORCED, this routine will fail
  1821. with ERROR_INVALID_INF_LOGCONFIG.
  1822. SPINST_LOGCONFIGS_ARE_OVERRIDES - if this bit is set, then the LogConfigs
  1823. to be written out are override configs.
  1824. If the ConfigType field of the ConfigPriority
  1825. entry is present, and specifies something
  1826. other than OVERRIDE, this routine will fail
  1827. with ERROR_INVALID_INF_LOGCONFIG.
  1828. Return Value:
  1829. Win32 error code indicating outcome.
  1830. --*/
  1831. {
  1832. INFCONTEXT LineContext;
  1833. DWORD rc = NO_ERROR;
  1834. DWORD FieldCount;
  1835. DWORD Field;
  1836. PCTSTR SectionSpec;
  1837. if(Flags & SPINST_SINGLESECTION) {
  1838. //
  1839. // Process the specific LogConf section the caller specified.
  1840. //
  1841. if(SetupGetLineCount(Inf, SectionName) == -1) {
  1842. rc = ERROR_SECTION_NOT_FOUND;
  1843. } else {
  1844. rc = pSetupProcessLogConfigSection(Inf, SectionName, DevInst, Flags,hMachine);
  1845. }
  1846. } else {
  1847. //
  1848. // Find the relevant line in the given install section.
  1849. // If not present then we're done with this operation.
  1850. //
  1851. if(SetupFindFirstLine(Inf,SectionName,SZ_KEY_LOGCONFIG,&LineContext)) {
  1852. do {
  1853. //
  1854. // Each value on the line in the given install section
  1855. // is the name of a logical config section.
  1856. //
  1857. FieldCount = SetupGetFieldCount(&LineContext);
  1858. for(Field=1; (rc==NO_ERROR) && (Field<=FieldCount); Field++) {
  1859. if((SectionSpec = pSetupGetField(&LineContext,Field))
  1860. && (SetupGetLineCount(Inf,SectionSpec) > 0)) {
  1861. rc = pSetupProcessLogConfigSection(Inf,SectionSpec,DevInst,Flags,hMachine);
  1862. } else {
  1863. rc = ERROR_SECTION_NOT_FOUND;
  1864. }
  1865. if (rc != NO_ERROR) {
  1866. pSetupLogSectionError(Inf,NULL,NULL,NULL,SectionSpec,MSG_LOG_SECT_ERROR,rc,SZ_KEY_LOGCONFIG);
  1867. }
  1868. }
  1869. } while((rc == NO_ERROR) && SetupFindNextMatchLine(&LineContext,SZ_KEY_LOGCONFIG,&LineContext));
  1870. }
  1871. }
  1872. return rc;
  1873. }