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.

660 lines
19 KiB

  1. /*++
  2. Copyright (c) 1994 - 1995 Microsoft Corporation
  3. Module Name:
  4. version.c
  5. Abstract:
  6. This module contains code that determines what the driver major
  7. version is.
  8. Author:
  9. Krishna Ganugapati (KrishnaG) 15-Mar-1994
  10. Revision History:
  11. --*/
  12. #include <precomp.h>
  13. #define X86_ENVIRONMENT L"Windows NT x86"
  14. #define IA64_ENVIRONMENT L"Windows IA64"
  15. #define MIPS_ENVIRONMENT L"Windows NT R4000"
  16. #define ALPHA_ENVIRONMENT L"Windows NT Alpha_AXP"
  17. #define PPC_ENVIRONMENT L"Windows NT PowerPC"
  18. #define WIN95_ENVIRONMENT L"Windows 4.0"
  19. DWORD
  20. GetDriverMajorVersion(
  21. LPWSTR pFileName
  22. )
  23. {
  24. DWORD dwSize = 0;
  25. LPVOID pFileVersion;
  26. UINT uLen = 0;
  27. LPVOID pMem;
  28. DWORD dwFileOS;
  29. DWORD dwFileVersionMS;
  30. DWORD dwFileVersionLS;
  31. DWORD dwProductVersionMS;
  32. DWORD dwProductVersionLS;
  33. if (!(dwSize = GetFileVersionInfoSize(pFileName, 0))) {
  34. DBGMSG(DBG_TRACE, ("Error: GetFileVersionInfoSize failed with %d\n", GetLastError()));
  35. DBGMSG(DBG_TRACE, ("Returning back a version # 0\n"));
  36. return(0);
  37. }
  38. if (!(pMem = AllocSplMem(dwSize))) {
  39. DBGMSG(DBG_TRACE, ("AllocMem failed \n"));
  40. DBGMSG(DBG_TRACE, ("Returning back a version # 0\n"));
  41. return(0);
  42. }
  43. if (!GetFileVersionInfo(pFileName, 0, dwSize, pMem)) {
  44. FreeSplMem(pMem);
  45. DBGMSG(DBG_TRACE, ("GetFileVersionInfo failed\n"));
  46. DBGMSG(DBG_TRACE, ("Returning back a version # 0\n"));
  47. return(0);
  48. }
  49. if (!VerQueryValue(pMem, L"\\",
  50. &pFileVersion, &uLen)) {
  51. FreeSplMem(pMem);
  52. DBGMSG(DBG_TRACE, ("VerQueryValue failed \n"));
  53. DBGMSG(DBG_TRACE, ("Returning back a version # 0\n"));
  54. return(0);
  55. }
  56. //
  57. // We could determine the Version Information
  58. //
  59. DBGMSG(DBG_TRACE, ("dwFileVersionMS = %d\n", ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileVersionMS));
  60. DBGMSG(DBG_TRACE, ("dwFileVersionLS = %d\n", ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileVersionLS));
  61. DBGMSG(DBG_TRACE, ("dwProductVersionMS = %d\n", ((VS_FIXEDFILEINFO *)pFileVersion)->dwProductVersionMS));
  62. DBGMSG(DBG_TRACE, ("dwProductVersionLS = %d\n", ((VS_FIXEDFILEINFO *)pFileVersion)->dwProductVersionLS));
  63. dwFileOS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileOS;
  64. dwFileVersionMS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileVersionMS;
  65. dwFileVersionLS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileVersionLS;
  66. dwProductVersionMS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwProductVersionMS;
  67. dwProductVersionLS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwProductVersionLS;
  68. FreeSplMem(pMem);
  69. if (dwFileOS != VOS_NT_WINDOWS32) {
  70. DBGMSG(DBG_TRACE,("Returning back a version # 0\n"));
  71. return(0);
  72. }
  73. if (dwProductVersionMS == dwFileVersionMS) {
  74. //
  75. // This means this hold for all dlls Pre-Daytona
  76. // after Daytona, printer driver writers must support
  77. // version control or we'll dump them as Version 0
  78. // drivers
  79. DBGMSG(DBG_TRACE,("Returning back a version # 0\n"));
  80. return(0);
  81. }
  82. //
  83. // Bug-Bug: suppose a third-party vendor uses a different system
  84. // methinks we should use the lower dword to have specific value
  85. // which implies he/she supports spooler version -- check with MattFe
  86. DBGMSG(DBG_TRACE,("Returning back a version # %d\n", dwFileVersionMS));
  87. return(dwFileVersionMS);
  88. }
  89. BOOL
  90. GetPrintDriverVersion(
  91. IN LPCWSTR pszFileName,
  92. OUT LPDWORD pdwFileMajorVersion,
  93. OUT LPDWORD pdwFileMinorVersion
  94. )
  95. /*++
  96. Routine Name:
  97. GetPrintDriverVersion
  98. Routine Description:
  99. Gets version information about an executable file.
  100. If the file is not an executable, it will return 0
  101. for both major and minor version.
  102. Arguments:
  103. pszFileName - file name
  104. pdwFileMajorVersion - pointer to major version
  105. pdwFileMinorVersion - pointer to minor version
  106. Return Value:
  107. TRUE if success.
  108. --*/
  109. {
  110. DWORD dwSize = 0;
  111. LPVOID pFileVersion = NULL;
  112. UINT uLen = 0;
  113. LPVOID pMem = NULL;
  114. DWORD dwFileVersionLS;
  115. DWORD dwFileVersionMS;
  116. DWORD dwProductVersionMS;
  117. DWORD dwProductVersionLS;
  118. DWORD dwFileOS, dwFileType, dwFileSubType;
  119. BOOL bRetValue = FALSE;
  120. if (pdwFileMajorVersion)
  121. {
  122. *pdwFileMajorVersion = 0;
  123. }
  124. if (pdwFileMinorVersion)
  125. {
  126. *pdwFileMinorVersion = 0;
  127. }
  128. try
  129. {
  130. if (pszFileName && *pszFileName)
  131. {
  132. dwSize = GetFileVersionInfoSize((LPWSTR)pszFileName, 0);
  133. if (dwSize == 0)
  134. {
  135. //
  136. // Return version 0 for files without a version resource
  137. //
  138. bRetValue = TRUE;
  139. }
  140. else if ((pMem = AllocSplMem(dwSize)) &&
  141. GetFileVersionInfo((LPWSTR)pszFileName, 0, dwSize, pMem) &&
  142. VerQueryValue(pMem, L"\\", &pFileVersion, &uLen))
  143. {
  144. dwFileOS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileOS;
  145. dwFileType = ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileType;
  146. dwFileSubType = ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileSubtype;
  147. dwFileVersionMS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileVersionMS;
  148. dwFileVersionLS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileVersionLS;
  149. dwProductVersionMS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwProductVersionMS;
  150. dwProductVersionLS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwProductVersionLS;
  151. //
  152. // Return versions for drivers designed for Windows NT/Windows 2000,
  153. // marked as printer drivers.
  154. // Hold for all dlls Pre-Daytona.
  155. // After Daytona, printer driver writers must support
  156. // version control or we'll dump them as Version 0 drivers.
  157. //
  158. if (dwFileOS == VOS_NT_WINDOWS32)
  159. {
  160. if (dwFileType == VFT_DRV &&
  161. dwFileSubType == VFT2_DRV_VERSIONED_PRINTER)
  162. {
  163. if (pdwFileMinorVersion)
  164. {
  165. *pdwFileMinorVersion = dwFileVersionLS;
  166. }
  167. if (pdwFileMajorVersion)
  168. {
  169. *pdwFileMajorVersion = dwFileVersionMS;
  170. }
  171. }
  172. else
  173. {
  174. if (pdwFileMajorVersion)
  175. {
  176. if (dwProductVersionMS == dwFileVersionMS)
  177. {
  178. //
  179. // Hold for all dlls Pre-Daytona.
  180. // After Daytona, printer driver writers must support
  181. // version control or we'll dump them as Version 0
  182. // drivers.
  183. //
  184. *pdwFileMajorVersion = 0;
  185. }
  186. else
  187. {
  188. *pdwFileMajorVersion = dwFileVersionMS;
  189. }
  190. }
  191. }
  192. }
  193. bRetValue = TRUE;
  194. }
  195. }
  196. }
  197. finally
  198. {
  199. FreeSplMem(pMem);
  200. }
  201. return bRetValue;
  202. }
  203. BOOL
  204. CheckFilePlatform(
  205. IN LPWSTR pszFileName,
  206. IN LPWSTR pszEnvironment
  207. )
  208. {
  209. HANDLE hFile, hMapping;
  210. LPVOID BaseAddress = NULL;
  211. PIMAGE_NT_HEADERS pImgHdr;
  212. BOOL bRet = FALSE;
  213. try {
  214. hFile = CreateFile(pszFileName,
  215. GENERIC_READ,
  216. FILE_SHARE_READ | FILE_SHARE_WRITE,
  217. NULL,
  218. OPEN_EXISTING,
  219. FILE_ATTRIBUTE_NORMAL,
  220. NULL);
  221. if ( hFile == INVALID_HANDLE_VALUE )
  222. leave;
  223. hMapping = CreateFileMapping(hFile,
  224. NULL,
  225. PAGE_READONLY,
  226. 0,
  227. 0,
  228. NULL);
  229. if ( !hMapping )
  230. leave;
  231. BaseAddress = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
  232. CloseHandle(hMapping);
  233. if ( !BaseAddress )
  234. leave;
  235. pImgHdr = RtlImageNtHeader(BaseAddress);
  236. if ( !pImgHdr ) {
  237. //
  238. // This happens for Win95 drivers. The second part of || is for
  239. // any environments we may add in the future
  240. //
  241. bRet = !_wcsicmp(pszEnvironment, WIN95_ENVIRONMENT) ||
  242. !( _wcsicmp(pszEnvironment, X86_ENVIRONMENT) &&
  243. _wcsicmp(pszEnvironment, IA64_ENVIRONMENT) &&
  244. _wcsicmp(pszEnvironment, ALPHA_ENVIRONMENT) &&
  245. _wcsicmp(pszEnvironment, PPC_ENVIRONMENT) &&
  246. _wcsicmp(pszEnvironment, MIPS_ENVIRONMENT) );
  247. leave;
  248. }
  249. switch (pImgHdr->FileHeader.Machine) {
  250. case IMAGE_FILE_MACHINE_I386:
  251. bRet = !_wcsicmp(pszEnvironment, X86_ENVIRONMENT);
  252. break;
  253. case IMAGE_FILE_MACHINE_ALPHA:
  254. bRet = !_wcsicmp(pszEnvironment, ALPHA_ENVIRONMENT);
  255. break;
  256. case IMAGE_FILE_MACHINE_IA64:
  257. bRet = !_wcsicmp(pszEnvironment, IA64_ENVIRONMENT);
  258. break;
  259. case IMAGE_FILE_MACHINE_POWERPC:
  260. bRet = !_wcsicmp(pszEnvironment, PPC_ENVIRONMENT);
  261. break;
  262. case IMAGE_FILE_MACHINE_R3000:
  263. case IMAGE_FILE_MACHINE_R4000:
  264. case IMAGE_FILE_MACHINE_R10000:
  265. bRet = !_wcsicmp(pszEnvironment, MIPS_ENVIRONMENT);
  266. break;
  267. default:
  268. //
  269. // For any environments we may add in the future.
  270. //
  271. bRet = !(_wcsicmp(pszEnvironment, X86_ENVIRONMENT) &&
  272. _wcsicmp(pszEnvironment, IA64_ENVIRONMENT) &&
  273. _wcsicmp(pszEnvironment, ALPHA_ENVIRONMENT) &&
  274. _wcsicmp(pszEnvironment, PPC_ENVIRONMENT) &&
  275. _wcsicmp(pszEnvironment, MIPS_ENVIRONMENT) );
  276. }
  277. } finally {
  278. if ( hFile != INVALID_HANDLE_VALUE ) {
  279. if ( BaseAddress )
  280. UnmapViewOfFile(BaseAddress);
  281. CloseHandle(hFile);
  282. }
  283. }
  284. return bRet;
  285. }
  286. /*++
  287. Routine Name:
  288. GetBinaryVersion
  289. Routine Description:
  290. Gets version information about an executable file.
  291. If the file is not an executable, it will return 0
  292. for both major and minor version. This function does
  293. not are if the file is a printer driver or anything
  294. else as long as it has a resource.
  295. Arguments:
  296. pszFileName - file name
  297. pdwFileMajorVersion - pointer to major version
  298. pdwFileMinorVersion - pointer to minor version
  299. Return Value:
  300. TRUE if success.
  301. --*/
  302. BOOL
  303. GetBinaryVersion(
  304. IN PCWSTR pszFileName,
  305. OUT PDWORD pdwFileMajorVersion,
  306. OUT PDWORD pdwFileMinorVersion
  307. )
  308. {
  309. DWORD dwSize = 0;
  310. LPVOID pFileVersion = NULL;
  311. UINT uLen = 0;
  312. LPVOID pMem = NULL;
  313. DWORD dwFileVersionLS;
  314. DWORD dwFileVersionMS;
  315. BOOL bRetValue = FALSE;
  316. if (pdwFileMajorVersion && pdwFileMinorVersion && pszFileName && *pszFileName)
  317. {
  318. *pdwFileMajorVersion = 0;
  319. *pdwFileMinorVersion = 0;
  320. try
  321. {
  322. dwSize = GetFileVersionInfoSize((LPWSTR)pszFileName, 0);
  323. if (dwSize == 0)
  324. {
  325. //
  326. // Return version 0 for files without a version resource
  327. //
  328. bRetValue = TRUE;
  329. }
  330. else if ((pMem = AllocSplMem(dwSize)) &&
  331. GetFileVersionInfo((LPWSTR)pszFileName, 0, dwSize, pMem) &&
  332. VerQueryValue(pMem, L"\\", &pFileVersion, &uLen))
  333. {
  334. dwFileVersionMS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileVersionMS;
  335. dwFileVersionLS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileVersionLS;
  336. *pdwFileMinorVersion = dwFileVersionLS;
  337. *pdwFileMajorVersion = dwFileVersionMS;
  338. bRetValue = TRUE;
  339. }
  340. }
  341. finally
  342. {
  343. FreeSplMem(pMem);
  344. }
  345. }
  346. else
  347. {
  348. SetLastError(ERROR_INVALID_PARAMETER);
  349. }
  350. return bRetValue;
  351. }
  352. typedef struct
  353. {
  354. PCWSTR pszDriver;
  355. DWORD DrvMajor;
  356. DWORD DrvMinor;
  357. PCWSTR pszProc;
  358. DWORD ProcMajor;
  359. DWORD ProcMinor;
  360. } SPECIALDRIVER;
  361. typedef struct
  362. {
  363. PCWSTR pszPrintProcFile;
  364. DWORD PrintProcMajVer;
  365. DWORD PrintProcMinVer;
  366. } NOIMPERSONATEPRINTPROCS;
  367. NOIMPERSONATEPRINTPROCS NoImpPrintProcs[] =
  368. {
  369. {L"lxaspp.dll", 0x00010000, 0x00000001},
  370. {L"lxarpp.dll", 0x00010000, 0x00000001},
  371. {L"lxampp.dll", 0x00010000, 0x00000001},
  372. {L"lxaupp.dll", 0x00010000, 0x00000001},
  373. {L"lxatpp.dll", 0x00010000, 0x00000001},
  374. {L"lxacpp.dll", 0x00010000, 0x00000001},
  375. {L"lxaapp.dll", 0x00010000, 0x00000001},
  376. {L"lxaepp.dll", 0x00010000, 0x00000001},
  377. {L"lxadpp.dll", 0x00010000, 0x00000001},
  378. {L"lxcapp.dll", 0x00010000, 0x00000001},
  379. {L"lexepp.dll", 0x00010000, 0x00000001},
  380. {L"lexfpp.dll", 0x00010000, 0x00000001},
  381. {L"jw61pp.dll", 0x00010000, 0x00000001},
  382. {L"fxj4pp.dll", 0x00010000, 0x00000001},
  383. {L"lxalpp5c.dll", 0x00020000, 0x00020000},
  384. {L"lxalpp5c.dll", 0x00010000, 0x00060000},
  385. {L"lxalpp5c.dll", 0x00020000, 0x00010000},
  386. {L"lxalpp5c.dll", 0x00010000, 0x00050000},
  387. {L"lxakpp5c.dll", 0x00020000, 0x00010000},
  388. {L"lxakpp5c.dll", 0x00010000, 0x00050001},
  389. {L"lxazpp5c.dll", 0x00010000, 0x00040002},
  390. {L"lxazpp5c.dll", 0x00010000, 0x00050001},
  391. {L"lxaxpp5c.dll", 0x00010000, 0x00060008},
  392. {L"lxaipp5c.dll", 0x00020000, 0x00020002},
  393. {L"lxaipp5c.dll", 0x00030000, 0x00020001},
  394. {L"lxajpp5c.dll", 0x00030000, 0x00010000},
  395. {L"lxajpp5c.dll", 0x00010000, 0x00020001},
  396. {L"lxavpp5c.dll", 0x00010000, 0x000A0000},
  397. {L"lxavpp5c.dll", 0x00010000, 0x00060000},
  398. {L"lg24pp5c.dll", 0x00010000, 0x00010008},
  399. {L"lg24pp5c.dll", 0x00010000, 0x00070002},
  400. {L"lgl2pp5c.dll", 0x00010000, 0x00010006},
  401. {L"lgaxpp5c.dll", 0x00010000, 0x00020001},
  402. {L"smaxpp5c.dll", 0x00010000, 0x00030000},
  403. {L"smazpp5c.dll", 0x00010000, 0x00020000},
  404. {L"lxbhpp5c.dll", 0x00010000, 0x00050000},
  405. };
  406. PCWSTR ArraySpecialDriversInbox[] =
  407. {
  408. L"Lexmark 3200 Color Jetprinter",
  409. L"Lexmark 5700 Color Jetprinter",
  410. L"Lexmark Z11 Color Jetprinter",
  411. L"Lexmark Z12 Color Jetprinter",
  412. L"Lexmark Z22-Z32 Color Jetprinter",
  413. L"Lexmark Z31 Color Jetprinter",
  414. L"Lexmark Z42 Color Jetprinter",
  415. L"Lexmark Z51 Color Jetprinter",
  416. L"Lexmark Z52 Color Jetprinter",
  417. L"Compaq IJ300 Inkjet Printer",
  418. L"Compaq IJ600 Inkjet Printer",
  419. L"Compaq IJ700 Inkjet Printer",
  420. L"Compaq IJ750 Inkjet Printer",
  421. L"Compaq IJ900 Inkjet Printer",
  422. L"Compaq IJ1200 Inkjet Printer"
  423. };
  424. /*++
  425. Name:
  426. FillInVersionInfo
  427. Description:
  428. We have the following 2 DWORD fields in INIDRIVER: DriverFileMajorVersion and DriverFileMinorVersion
  429. They are not filled in when a driver is added or when the spooler starts. The reason for the
  430. existence of these 2 fields is that we cannot always rely on the informatin in dwlDriverVersion
  431. (part of driver-info_6). Not all driver packages supply this information.
  432. So when we print for the first time using a certain INIDRIVER, we call this function to look at
  433. the resource of the driver DLL and populate DriverFileMajorVersion and DriverFileMinorVersion.
  434. The numbers come from VS_FIXEDFILEINFO.FileVer
  435. Arguments:
  436. pIniDriver - pinidriver to fill in the major and minor versions
  437. pIniSpooler - pinispooler to which the driver belongs
  438. Return Value:
  439. Win32 error code
  440. --*/
  441. DWORD
  442. FillInVersionInfo(
  443. IN PINIDRIVER pIniDriver,
  444. IN PINISPOOLER pIniSpooler
  445. )
  446. {
  447. DWORD Error = ERROR_INVALID_ENVIRONMENT;
  448. WCHAR szPath[MAX_PATH];
  449. DWORD cbNeeded;
  450. PINIENVIRONMENT pIniEnvironment;
  451. EnterSplSem();
  452. pIniEnvironment = FindEnvironment(LOCAL_ENVIRONMENT, pIniSpooler);
  453. if (pIniEnvironment)
  454. {
  455. Error = StrNCatBuff(szPath,
  456. MAX_PATH,
  457. pIniSpooler->pDir,
  458. L"\\",
  459. szDriverDir,
  460. L"\\",
  461. pIniEnvironment->pDirectory,
  462. L"\\3\\",
  463. pIniDriver->pDriverFile,
  464. NULL);
  465. }
  466. LeaveSplSem();
  467. if (Error == ERROR_SUCCESS)
  468. {
  469. Error = GetBinaryVersion(szPath,
  470. &pIniDriver->DriverFileMajorVersion,
  471. &pIniDriver->DriverFileMinorVersion) ? ERROR_SUCCESS : GetLastError();
  472. }
  473. SPLASSERT(Error == ERROR_SUCCESS);
  474. return Error;
  475. }
  476. /*++
  477. Name:
  478. IsSpecialDriver
  479. Description:
  480. Checks whether a printer driver (and print processor) needs to be special
  481. cased. Some print processors want to be loaded in local system context.
  482. The are listed in the tables above. some are inbox, some are IHV.
  483. Arguments:
  484. pIniDriver - pinidriver for the current job
  485. pIniProc - piniprintproc for the current job
  486. pIniSpooler - pinispooler for current job
  487. Return Value:
  488. TRUE - this print processor needs to be loaded in local system context
  489. FALSE - load print processor in impersonation context
  490. --*/
  491. BOOL
  492. IsSpecialDriver(
  493. IN PINIDRIVER pIniDriver,
  494. IN PINIPRINTPROC pIniProc,
  495. IN PINISPOOLER pIniSpooler
  496. )
  497. {
  498. BOOL bSpecial = FALSE;
  499. DWORD i;
  500. //
  501. // Check if it is an inbox driver that needs to be special cased
  502. //
  503. for (i = 0; i < COUNTOF(ArraySpecialDriversInbox); i++)
  504. {
  505. if (!_wcsicmp(pIniDriver->pName, ArraySpecialDriversInbox[i]))
  506. {
  507. bSpecial = TRUE;
  508. break;
  509. }
  510. }
  511. //
  512. // Check if it is an IHV driver that needs to be special cased
  513. //
  514. if (!bSpecial)
  515. {
  516. if (pIniDriver->DriverFileMajorVersion == 0 && pIniDriver->DriverFileMinorVersion == 0)
  517. {
  518. //
  519. // We fill in on demand the major and minor file version
  520. //
  521. FillInVersionInfo(pIniDriver, pIniSpooler);
  522. }
  523. for (i = 0; i < COUNTOF(NoImpPrintProcs); i++)
  524. {
  525. if (!_wcsicmp(pIniProc->pDLLName, NoImpPrintProcs[i].pszPrintProcFile) &&
  526. pIniProc->FileMajorVersion == NoImpPrintProcs[i].PrintProcMajVer &&
  527. pIniProc->FileMinorVersion == NoImpPrintProcs[i].PrintProcMinVer)
  528. {
  529. bSpecial = TRUE;
  530. break;
  531. }
  532. }
  533. }
  534. return bSpecial;
  535. }