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.

619 lines
16 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. For Internal use only!
  4. Module Name:
  5. INFSCAN
  6. verinfo.cpp
  7. Abstract:
  8. Platform version matching
  9. WARNING! WARNING!
  10. All of this implementation relies on intimate knowledge of
  11. SetupAPI parsing of INF files. Particularly processing
  12. of [Manufacturer] seciton.
  13. It is re-implemented here for speed due to having to process
  14. 700+ INF's in a single go at the cost of having to maintain
  15. this.
  16. DO NOT (I repeat) DO NOT re-implement the code here without
  17. consultation with SetupAPI owner.
  18. History:
  19. Created July 2001 - JamieHun
  20. --*/
  21. #include "precomp.h"
  22. #pragma hdrstop
  23. BasicVerInfo::BasicVerInfo()
  24. /*++
  25. Routine Description:
  26. Initialize BasicVerInfo data
  27. Arguments:
  28. NONE
  29. Return Value:
  30. NONE
  31. --*/
  32. {
  33. PlatformMask = PLATFORM_MASK_ALL;
  34. VersionHigh = 0;
  35. VersionLow = 0;
  36. ProductType = 0;
  37. ProductSuite = 0;
  38. }
  39. int BasicVerInfo::Parse(PTSTR verString)
  40. /*++
  41. Routine Description:
  42. Parse a (modifiable) verString
  43. determining range of platforms supported
  44. version supported
  45. product type supported
  46. range of product suites supported
  47. and a bitmap of what was specified
  48. syntax currently:
  49. <plat>.<maj>.<min>.<typ>.<suite>
  50. WARNING! This can be extended by SetupAPI
  51. MAINTAINANCE: format must correlate with SetupAPI manufacturer/models version syntax
  52. MAINTAINANCE: add all supported platforms
  53. Arguments:
  54. Version string, eg "ntx86.5.1"
  55. Return Value:
  56. 0 if success
  57. --*/
  58. {
  59. PlatformMask = 0;
  60. int i;
  61. PTSTR nn = verString;
  62. for (i = 0;i<5;i++) {
  63. PCTSTR n = nn;
  64. while((*nn) && (*nn != TEXT('.'))) {
  65. nn++;
  66. }
  67. TCHAR c = *nn;
  68. *nn = TEXT('\0');
  69. switch(i) {
  70. case 0: // platform
  71. if(!n[0]) {
  72. PlatformMask |= PLATFORM_MASK_ALL_ARCHITECTS;
  73. break;
  74. }
  75. if(_tcsicmp(n,TEXT("win"))==0) {
  76. PlatformMask = (PlatformMask & ~PLATFORM_MASK_ALL_ARCHITECTS) | PLATFORM_MASK_WIN;
  77. break;
  78. }
  79. if(_tcsicmp(n,TEXT("NTx86"))==0) {
  80. PlatformMask = (PlatformMask & ~PLATFORM_MASK_ALL_ARCHITECTS) | PLATFORM_MASK_NTX86;
  81. break;
  82. }
  83. if(_tcsicmp(n,TEXT("NTia64"))==0) {
  84. PlatformMask = (PlatformMask & ~PLATFORM_MASK_ALL_ARCHITECTS) | PLATFORM_MASK_NTIA64;
  85. break;
  86. }
  87. if(_tcsicmp(n,TEXT("NTamd64"))==0) {
  88. PlatformMask = (PlatformMask & ~PLATFORM_MASK_ALL_ARCHITECTS) | PLATFORM_MASK_NTAMD64;
  89. break;
  90. }
  91. if(_tcsicmp(n,TEXT("NT"))==0) {
  92. PlatformMask = (PlatformMask & ~PLATFORM_MASK_ALL_ARCHITECTS) | PLATFORM_MASK_NT;
  93. break;
  94. }
  95. return 4;
  96. case 1: // major
  97. if(!n[0]) {
  98. PlatformMask |= PLATFORM_MASK_ALL_MAJOR_VER;
  99. break;
  100. }
  101. PlatformMask &= ~PLATFORM_MASK_ALL_MAJOR_VER;
  102. VersionHigh = _tcstoul(n,NULL,0);
  103. break;
  104. case 2: // minor
  105. if(!n[0]) {
  106. PlatformMask |= PLATFORM_MASK_ALL_MINOR_VER;
  107. break;
  108. }
  109. PlatformMask &= ~PLATFORM_MASK_ALL_MINOR_VER;
  110. VersionLow = _tcstoul(n,NULL,0);
  111. break;
  112. case 3: // type
  113. if(!n[0]) {
  114. PlatformMask |= PLATFORM_MASK_ALL_TYPE;
  115. break;
  116. }
  117. PlatformMask &= ~PLATFORM_MASK_ALL_TYPE;
  118. ProductType = _tcstoul(n,NULL,0);
  119. break;
  120. case 4: // suite
  121. if(!n[0]) {
  122. PlatformMask |= PLATFORM_MASK_ALL_SUITE;
  123. break;
  124. }
  125. PlatformMask &= ~PLATFORM_MASK_ALL_SUITE;
  126. ProductSuite = _tcstoul(n,NULL,0);
  127. break;
  128. }
  129. if(c) {
  130. *nn = c;
  131. nn++;
  132. }
  133. }
  134. return 0;
  135. }
  136. bool BasicVerInfo::IsCompatibleWith(BasicVerInfo & other)
  137. /*++
  138. Routine Description:
  139. Determine if given version is compatible with other (actual) version
  140. To put into context,
  141. this: version of a model decoration
  142. other: information about target OS
  143. note that A.IsCompatibleWith(B)
  144. does not imply B.IsCompatibleWith(A)
  145. Arguments:
  146. BasicVerInfo to compare against (usually GlobalScan::Version)
  147. Return Value:
  148. true if they are (loosely) compatible
  149. false if mutually exclusive
  150. ie. NTx86 is compatible with NTx86.5.1
  151. NTx86 is mutually exclusive with NTia64
  152. --*/
  153. {
  154. //
  155. // first match the platform architecture
  156. //
  157. if(!((other.PlatformMask & PlatformMask) & PLATFORM_MASK_ALL_ARCHITECTS)) {
  158. //
  159. // mutually exclusive platform
  160. //
  161. return FALSE;
  162. }
  163. //
  164. // Version
  165. //
  166. if(!((other.PlatformMask | PlatformMask) & PLATFORM_MASK_ALL_MAJOR_VER)) {
  167. //
  168. // explicit major version required
  169. //
  170. if(other.VersionHigh < VersionHigh) {
  171. //
  172. // this entry is not compatible with target
  173. //
  174. return FALSE;
  175. }
  176. if(other.VersionHigh == VersionHigh) {
  177. //
  178. // need to check VersionLow
  179. //
  180. if(!((other.PlatformMask | PlatformMask) & PLATFORM_MASK_ALL_MINOR_VER)) {
  181. //
  182. // explicit minor version required
  183. //
  184. if(other.VersionLow < VersionLow) {
  185. //
  186. // this entry is not compatible with target
  187. //
  188. return FALSE;
  189. }
  190. }
  191. }
  192. }
  193. //
  194. // Product Type - must be explicit or wild-carded
  195. //
  196. if(!((other.PlatformMask | PlatformMask) & PLATFORM_MASK_ALL_TYPE)) {
  197. if(other.ProductType != ProductType) {
  198. //
  199. // this entry is not compatible with target
  200. //
  201. return FALSE;
  202. }
  203. }
  204. //
  205. // Product Suite - must be mask or wild-carded
  206. //
  207. if(!((other.PlatformMask | PlatformMask) & PLATFORM_MASK_ALL_SUITE)) {
  208. if(!(other.ProductSuite & ProductSuite)) {
  209. //
  210. // this entry is not compatible with target
  211. //
  212. return FALSE;
  213. }
  214. }
  215. return TRUE;
  216. }
  217. int BasicVerInfo::IsBetter(BasicVerInfo & other,BasicVerInfo & filter)
  218. /*++
  219. Routine Description:
  220. More complex check between this & other
  221. filter is target OS version (GlobalScan::Version)
  222. Arguments:
  223. BasicVerInfo to compare against (usually another model version)
  224. Return Value:
  225. if 'other' is definately better than primary, return 1
  226. if 'other' and this likely are both just as good/bad (but not same), return 0
  227. if 'other' is exactly the same as primary, return -1
  228. if 'other' is definately worse than primary, return -2
  229. --*/
  230. {
  231. //
  232. //
  233. // for a field:
  234. //
  235. // if field is filtered as not testable, then both primary and other are
  236. // either 'same' or 'likely'
  237. //
  238. int testres;
  239. int suggest;
  240. //
  241. // check platform
  242. //
  243. if((PlatformMask ^ other.PlatformMask) & PLATFORM_MASK_ALL_ARCHITECTS) {
  244. //
  245. // the two platform matches are different
  246. // result will be 1/0/-2
  247. //
  248. DWORD o_plat = other.PlatformMask & filter.PlatformMask & PLATFORM_MASK_ALL_ARCHITECTS;
  249. DWORD t_plat = PlatformMask & filter.PlatformMask & PLATFORM_MASK_ALL_ARCHITECTS;
  250. if(o_plat == t_plat) {
  251. //
  252. // both are in the same realm
  253. //
  254. // a more generic one is allowable if a more specific one
  255. // could get rejected for other reasons
  256. // so mark this as a suggestion at this moment
  257. //
  258. if((o_plat ^ other.PlatformMask) & PLATFORM_MASK_ALL_ARCHITECTS) {
  259. //
  260. // 'other' is less specific
  261. //
  262. testres = -2;
  263. } else {
  264. //
  265. // 'other' is more specific
  266. //
  267. testres = 1;
  268. }
  269. } else {
  270. //
  271. // consider both
  272. //
  273. return 0;
  274. }
  275. } else {
  276. //
  277. // they are exactly the same
  278. //
  279. testres = -1;
  280. }
  281. if(PlatformMask & PLATFORM_MASK_ALL_MAJOR_VER) {
  282. //
  283. // we have generic version
  284. //
  285. if(other.PlatformMask & PLATFORM_MASK_ALL_MAJOR_VER) {
  286. //
  287. // other also has generic version
  288. //
  289. suggest = -1;
  290. } else {
  291. //
  292. // 'other' has specific version, so it wins
  293. //
  294. suggest = 1;
  295. }
  296. } else {
  297. //
  298. // we have specific version
  299. //
  300. if(other.PlatformMask & PLATFORM_MASK_ALL_MAJOR_VER) {
  301. //
  302. // 'other' has generic version, so we win
  303. //
  304. suggest = -2;
  305. } else {
  306. //
  307. // both have specific major version
  308. //
  309. if(other.VersionHigh > VersionHigh) {
  310. //
  311. // 'other' has higher version, it wins
  312. //
  313. suggest = 1;
  314. } else if(VersionHigh > other.VersionHigh) {
  315. //
  316. // we have higher version, we win
  317. //
  318. suggest = -2;
  319. } else {
  320. //
  321. // version-high matches, need to check version low
  322. //
  323. if(PlatformMask & PLATFORM_MASK_ALL_MINOR_VER) {
  324. //
  325. // we have generic version
  326. //
  327. if(other.PlatformMask & PLATFORM_MASK_ALL_MINOR_VER) {
  328. //
  329. // other also has generic version, draw
  330. //
  331. suggest = -1;
  332. } else {
  333. //
  334. // 'other' has specific version, so it wins
  335. //
  336. suggest = 1;
  337. }
  338. } else {
  339. //
  340. // we have specific version
  341. //
  342. if(other.PlatformMask & PLATFORM_MASK_ALL_MINOR_VER) {
  343. //
  344. // 'other' has generic version, so we win
  345. //
  346. suggest = -2;
  347. } else {
  348. //
  349. // both have specific minor version, higher version wins
  350. //
  351. if(other.VersionLow > VersionLow) {
  352. suggest = 1;
  353. } else if(VersionLow > other.VersionLow) {
  354. suggest = -2;
  355. } else {
  356. //
  357. // draw
  358. //
  359. suggest = -1;
  360. }
  361. }
  362. }
  363. }
  364. }
  365. }
  366. if(suggest != -1) {
  367. //
  368. // if we suggested anything other than a draw
  369. //
  370. if(filter.PlatformMask & PLATFORM_MASK_ALL_MINOR_VER) {
  371. //
  372. // consider as two possible outcomes
  373. //
  374. return 0;
  375. } else if (testres == -1) {
  376. //
  377. // the two are no longer identical
  378. //
  379. testres = suggest;
  380. }
  381. }
  382. if((PlatformMask ^other.PlatformMask) & PLATFORM_MASK_ALL_TYPE) {
  383. //
  384. // product types are different (one generic, one specific)
  385. //
  386. if(filter.PlatformMask & PLATFORM_MASK_ALL_TYPE) {
  387. //
  388. // consider both outcomes
  389. //
  390. return 0;
  391. } else if (testres == -1) {
  392. //
  393. // we're keying off type
  394. //
  395. if(PlatformMask & PLATFORM_MASK_ALL_TYPE) {
  396. //
  397. // 'other' has specific suite
  398. //
  399. testres = 1;
  400. } else {
  401. //
  402. // we have specific suite
  403. //
  404. testres = -2;
  405. }
  406. }
  407. } else if(! (PlatformMask & other.PlatformMask & PLATFORM_MASK_ALL_TYPE)) {
  408. //
  409. // both specified type
  410. //
  411. if (ProductType != other.ProductType) {
  412. //
  413. // if types are different, consider both
  414. //
  415. return 0;
  416. }
  417. }
  418. if((PlatformMask ^other.PlatformMask) & PLATFORM_MASK_ALL_SUITE) {
  419. //
  420. // product suites are different (one generic, one 'specific')
  421. //
  422. if(filter.PlatformMask & PLATFORM_MASK_ALL_SUITE) {
  423. //
  424. // consider both outcomes
  425. //
  426. return 0;
  427. } else if (testres == -1) {
  428. //
  429. // we're keying off suite
  430. //
  431. if(PlatformMask & PLATFORM_MASK_ALL_SUITE) {
  432. //
  433. // 'other' has specific suite
  434. //
  435. testres = 1;
  436. } else {
  437. //
  438. // we have specific suite
  439. //
  440. testres = -2;
  441. }
  442. }
  443. } else if(! (PlatformMask & other.PlatformMask & PLATFORM_MASK_ALL_SUITE)) {
  444. //
  445. // both specified suite
  446. //
  447. if (ProductSuite != other.ProductSuite) {
  448. return 0;
  449. }
  450. }
  451. return testres;
  452. }
  453. //
  454. //
  455. // NodeVerInfo - adaptation of BasicVerInfo
  456. // where a decoration string needs to be kept
  457. // for selecting what decorations to consider
  458. //
  459. NodeVerInfo::NodeVerInfo()
  460. /*++
  461. Routine Description:
  462. Initialize NodeVerInfo data
  463. Arguments:
  464. NONE
  465. Return Value:
  466. NONE
  467. --*/
  468. {
  469. Rejected = false;
  470. }
  471. int NodeVerInfo::Parse(PTSTR verString)
  472. /*++
  473. Routine Description:
  474. Parse a (modifiable) verString
  475. and also save a copy as Decoration
  476. Arguments:
  477. Version string, eg "ntx86.5.1"
  478. Return Value:
  479. 0 if success
  480. --*/
  481. {
  482. //
  483. // copy it before it's modified
  484. //
  485. Decoration = verString;
  486. return BasicVerInfo::Parse(verString);
  487. }
  488. int NodeVerInfo::Parse(const SafeString & str)
  489. /*++
  490. Routine Description:
  491. Parse an unmodifiable verString
  492. Arguments:
  493. Version string, eg "ntx86.5.1"
  494. Return Value:
  495. 0 if success
  496. --*/
  497. {
  498. PTSTR buf;
  499. buf = new TCHAR[str.length()+1];
  500. lstrcpy(buf,str.c_str());
  501. int res = Parse(buf);
  502. delete [] buf;
  503. return res;
  504. }
  505. int NodeVerInfo::IsBetter(NodeVerInfo & other,BasicVerInfo & filter)
  506. /*++
  507. Routine Description:
  508. Specific variation of 'IsBetter'
  509. Arguments:
  510. Same as BasicVersion::IsBetter
  511. Return Value:
  512. Same as BasicVersion::IsBetter
  513. --*/
  514. {
  515. int testres = BasicVerInfo::IsBetter(other,filter);
  516. if(testres == -1) {
  517. //
  518. // we considered both equally ranked
  519. // compare the strings. If the strings are
  520. // different, consider both
  521. //
  522. if(Decoration.length() != other.Decoration.length()) {
  523. return 0;
  524. }
  525. if(_tcsicmp(Decoration.c_str(),other.Decoration.c_str())!=0) {
  526. return 0;
  527. }
  528. }
  529. return testres;
  530. }