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.

760 lines
18 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1997
  3. All rights reserved.
  4. Module Name:
  5. drvrver.hxx
  6. Abstract:
  7. Driver version detection header.
  8. Author:
  9. Steve Kiraly (SteveKi) 21-Jan-1996
  10. Revision History:
  11. --*/
  12. #include "precomp.hxx"
  13. #pragma hdrstop
  14. #include "psetup.hxx"
  15. #include "drvver.hxx"
  16. #include "splapip.h"
  17. #include "compinfo.hxx"
  18. BOOL
  19. bGetCurrentDriver(
  20. IN LPCTSTR pszServerName,
  21. OUT LPDWORD pdwCurrentDriver
  22. )
  23. {
  24. TCHAR szArch[kStrMax];
  25. BOOL bRetval = FALSE;
  26. DWORD dwVer = 0;
  27. //
  28. // Attempt to get the architecture / version from the machine.
  29. // First attempt to get the information from the spooler.
  30. //
  31. bRetval = bGetArchUseSpooler( pszServerName, szArch, COUNTOF( szArch ), &dwVer );
  32. //
  33. // If spooler did not respond, this may be a downlevel
  34. // print spooler. "Downlevel" meaning older version.
  35. //
  36. if( !bRetval )
  37. {
  38. //
  39. // Attempt to get the information using the remote registry calls
  40. // We only connect to the remote registry if a server name was passed.
  41. //
  42. if( pszServerName )
  43. {
  44. bRetval = bGetArchUseReg( pszServerName, szArch, COUNTOF( szArch ), &dwVer );
  45. }
  46. }
  47. //
  48. // Check for any retuned information.
  49. //
  50. if( bRetval )
  51. {
  52. DBGMSG( DBG_TRACE, ( "Server " TSTR " Arch " TSTR " Ver %d\n", DBGSTR(pszServerName), szArch, dwVer ) );
  53. //
  54. // Encode the architecture / version into a dword.
  55. //
  56. if( bEncodeArchVersion( szArch, dwVer, pdwCurrentDriver ) )
  57. {
  58. DBGMSG( DBG_TRACE, ( "Encoded Arch / Version %d\n", *pdwCurrentDriver ) );
  59. bRetval = TRUE;
  60. }
  61. else
  62. {
  63. DBGMSG( DBG_WARN, ( "Encode architecture and version failed.\n" ) );
  64. bRetval = FALSE;
  65. }
  66. }
  67. else
  68. {
  69. DBGMSG( DBG_WARN, ( "Fetching architecture and version failed.\n" ) );
  70. bRetval = FALSE;
  71. }
  72. return bRetval;
  73. }
  74. BOOL
  75. bGetArchUseSpooler(
  76. IN LPCTSTR pName,
  77. OUT LPTSTR pszArch,
  78. IN DWORD dwSize,
  79. IN OUT LPDWORD pdwVer
  80. )
  81. /*++
  82. Routine Description:
  83. Gets the specified print server the architectue and
  84. driver version using the spooler.
  85. Arguments:
  86. pName - pointer to print server name.
  87. pszArch - pointer to a buffer where to return the machine architecture string
  88. dwSize - Size in characters of the provided architecture string
  89. pdwVersion - pointer where to return the remote machine driver version.
  90. Return Value:
  91. TRUE - remote information returned, FALSE - remote information not available.
  92. --*/
  93. {
  94. //
  95. // Attempt to open print server with full access.
  96. //
  97. BOOL bReturn = FALSE;
  98. DWORD dwStatus = ERROR_SUCCESS;
  99. DWORD dwAccess = SERVER_READ;
  100. HANDLE hServer = NULL;
  101. TStatus Status;
  102. //
  103. // Open the server for read access.
  104. //
  105. Status DBGCHK = TPrinter::sOpenPrinter( pName,
  106. &dwAccess,
  107. &hServer );
  108. //
  109. // Save administrator capability flag.
  110. //
  111. if( Status == ERROR_SUCCESS ){
  112. //
  113. // Get the remote spooler's architecture type and version.
  114. //
  115. TCHAR szArch[kStrMax];
  116. memset( szArch, 0, sizeof( szArch ) );
  117. DWORD dwNeeded = 0;
  118. DWORD dwVer = 0;
  119. DWORD dwVerType = REG_DWORD;
  120. DWORD dwArchType = REG_SZ;
  121. if( dwStatus == ERROR_SUCCESS ){
  122. dwStatus = GetPrinterData( hServer,
  123. SPLREG_ARCHITECTURE,
  124. &dwArchType,
  125. (PBYTE)szArch,
  126. sizeof( szArch ),
  127. &dwNeeded );
  128. }
  129. if( dwStatus == ERROR_SUCCESS ){
  130. dwStatus = GetPrinterData( hServer,
  131. SPLREG_MAJOR_VERSION,
  132. &dwVerType,
  133. (PBYTE)&dwVer,
  134. sizeof( dwVer ),
  135. &dwNeeded );
  136. }
  137. if( dwStatus == ERROR_SUCCESS ){
  138. DBGMSG( DBG_TRACE, ( "GetPrinterData: Architecture " TSTR "\n" , szArch ) );
  139. DBGMSG( DBG_TRACE, ( "GetPrinterData: MajorVersion %d\n" , dwVer ) );
  140. //
  141. // Only success if provided buffer is big enough.
  142. //
  143. if( (DWORD)lstrlen( szArch ) < dwSize ){
  144. lstrcpy( pszArch, szArch );
  145. *pdwVer = dwVer;
  146. bReturn = TRUE;
  147. } else {
  148. dwStatus = ERROR_INSUFFICIENT_BUFFER;
  149. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  150. bReturn = FALSE;
  151. }
  152. } else {
  153. DBGMSG( DBG_WARN, ( "GetPrinterData failed with %d\n", dwStatus ) );
  154. }
  155. }
  156. if( hServer ){
  157. ClosePrinter( hServer );
  158. }
  159. return bReturn;
  160. }
  161. BOOL
  162. bGetArchUseReg(
  163. IN LPCTSTR pName,
  164. OUT LPTSTR pszArch,
  165. IN DWORD dwSize,
  166. OUT LPDWORD pdwVer
  167. )
  168. /*++
  169. Routine Description:
  170. Gets the specified print server the architectue and
  171. driver version using the remote registry.
  172. Arguments:
  173. pName - pointer to print server name.
  174. pszArch - pointer to a buffer where to return the machine architecture string
  175. dwSize - Size in characters of the provided architecture string
  176. pdwVersion - pointer where to return the remote machine driver version.
  177. Return Value:
  178. TRUE - remote information returned, FALSE - remote information not available.
  179. --*/
  180. {
  181. BOOL bStatus = TRUE;
  182. DWORD dwDriverEnvId = 0;
  183. DWORD dwArch = 0;
  184. TString strDriverEnv;
  185. //
  186. // Create the computer information.
  187. //
  188. CComputerInfo CompInfo ( pName );
  189. //
  190. // Get the information from the remote machine.
  191. //
  192. if( !CompInfo.GetInfo() ){
  193. DBGMSG( DBG_WARN, ( "CComputerInfo.GetInfo failed with %d\n", GetLastError() ) );
  194. return FALSE;
  195. }
  196. //
  197. // If this is a windows 95 machine set resource string
  198. // id and set the version to zero.
  199. //
  200. if( CompInfo.IsRunningWindows95() ){
  201. dwDriverEnvId = IDS_ENVIRONMENT_WIN95;
  202. *pdwVer = 0;
  203. } else {
  204. //
  205. // Convert processor type to spooler defined environment string.
  206. //
  207. dwArch = CompInfo.GetProcessorArchitecture();
  208. *pdwVer = CompInfo.GetSpoolerVersion();
  209. struct ArchMap {
  210. DWORD dwArch;
  211. DWORD dwVersion;
  212. UINT uId;
  213. };
  214. //
  215. // disable MIPS & PPC drivers, since they are not supported from setup
  216. //
  217. static ArchMap aArchMap [] = {
  218. { PROCESSOR_ARCHITECTURE_INTEL, 0, IDS_ENVIRONMENT_WIN95 },
  219. //{ PROCESSOR_ARCHITECTURE_MIPS, 0, IDS_ENVIRONMENT_MIPS },
  220. { PROCESSOR_ARCHITECTURE_ALPHA, 0, IDS_ENVIRONMENT_ALPHA },
  221. { PROCESSOR_ARCHITECTURE_INTEL, 0, IDS_ENVIRONMENT_X86 },
  222. //{ PROCESSOR_ARCHITECTURE_MIPS, 1, IDS_ENVIRONMENT_MIPS },
  223. { PROCESSOR_ARCHITECTURE_ALPHA, 1, IDS_ENVIRONMENT_ALPHA },
  224. //{ PROCESSOR_ARCHITECTURE_PPC, 1, IDS_ENVIRONMENT_PPC },
  225. { PROCESSOR_ARCHITECTURE_INTEL, 1, IDS_ENVIRONMENT_X86 },
  226. //{ PROCESSOR_ARCHITECTURE_MIPS, 2, IDS_ENVIRONMENT_MIPS },
  227. { PROCESSOR_ARCHITECTURE_ALPHA, 2, IDS_ENVIRONMENT_ALPHA },
  228. //{ PROCESSOR_ARCHITECTURE_PPC, 2, IDS_ENVIRONMENT_PPC },
  229. { PROCESSOR_ARCHITECTURE_INTEL, 2, IDS_ENVIRONMENT_X86 },
  230. { PROCESSOR_ARCHITECTURE_ALPHA, 3, IDS_ENVIRONMENT_ALPHA },
  231. { PROCESSOR_ARCHITECTURE_INTEL, 3, IDS_ENVIRONMENT_X86 }};
  232. bStatus = FALSE;
  233. for( UINT i = 0; i < COUNTOF( aArchMap ); i++ ){
  234. //
  235. // If a version and architecture match.
  236. //
  237. if( aArchMap[i].dwVersion == *pdwVer &&
  238. aArchMap[i].dwArch == dwArch ){
  239. dwDriverEnvId = aArchMap[i].uId;
  240. bStatus = TRUE;
  241. break;
  242. }
  243. }
  244. }
  245. //
  246. // If Environment ID and version found.
  247. //
  248. if( !bStatus ){
  249. DBGMSG( DBG_WARN, ( "Failed to find architecture in map.\n" ) );
  250. return FALSE;
  251. }
  252. //
  253. // Load the environment string from our resource file.
  254. //
  255. if( !strDriverEnv.bLoadString( ghInst, dwDriverEnvId ) ){
  256. DBGMSG( DBG_WARN, ( "Failed to load driver name string resource with %d\n", GetLastError() ) );
  257. return FALSE;
  258. }
  259. //
  260. // Check the provided buffer is large enough.
  261. //
  262. if( (DWORD)lstrlen( strDriverEnv ) >= ( dwSize - 1 ) ){
  263. DBGMSG( DBG_WARN, ( "Insuffcient buffer provided to bGetArchUseReg.\n" ) );
  264. return FALSE;
  265. }
  266. //
  267. // Copy back environment string to provided buffer.
  268. //
  269. lstrcpy( pszArch, strDriverEnv );
  270. DBGMSG( DBG_TRACE, ( "CComputerInfo.GetInfo: Architecture " TSTR "\n" , pszArch ) );
  271. DBGMSG( DBG_TRACE, ( "CComputerInfo.GetInfo: MajorVersion %d\n" , *pdwVer ) );
  272. return TRUE;
  273. }
  274. BOOL
  275. bEncodeArchVersion(
  276. IN LPCTSTR pszArch,
  277. IN DWORD dwVer,
  278. OUT LPDWORD pdwVal
  279. )
  280. /*++
  281. Routine Description:
  282. Encode the Architecture and version into a DWORD.
  283. Arguments:
  284. pszArch - pointer to machine spooler defined environment string
  285. dwVer - machines driver version
  286. pdwVal - pointer where to store the encoded value
  287. Return Value:
  288. TRUE - remote information returned, FALSE - remote information not available.
  289. --*/
  290. {
  291. struct ArchMap {
  292. UINT uArchId;
  293. DWORD dwVersion;
  294. DWORD dwPUIVer;
  295. DWORD dwPUIArch;
  296. };
  297. //
  298. // disable MIPS & PPC drivers, since they are not supported from setup
  299. //
  300. static ArchMap aArchMap [] = {
  301. { IDS_ENVIRONMENT_ALPHA, 0, VERSION_0, ARCH_ALPHA },
  302. { IDS_ENVIRONMENT_X86, 0, VERSION_0, ARCH_X86 },
  303. //{ IDS_ENVIRONMENT_MIPS, 0, VERSION_0, ARCH_MIPS },
  304. { IDS_ENVIRONMENT_WIN95, 0, VERSION_0, ARCH_WIN95 },
  305. { IDS_ENVIRONMENT_ALPHA, 1, VERSION_1, ARCH_ALPHA },
  306. { IDS_ENVIRONMENT_X86, 1, VERSION_1, ARCH_X86 },
  307. //{ IDS_ENVIRONMENT_MIPS, 1, VERSION_1, ARCH_MIPS },
  308. //{ IDS_ENVIRONMENT_PPC, 1, VERSION_1, ARCH_PPC },
  309. { IDS_ENVIRONMENT_ALPHA, 2, VERSION_2, ARCH_ALPHA },
  310. { IDS_ENVIRONMENT_X86, 2, VERSION_2, ARCH_X86 },
  311. //{ IDS_ENVIRONMENT_MIPS, 2, VERSION_2, ARCH_MIPS },
  312. //{ IDS_ENVIRONMENT_PPC, 2, VERSION_2, ARCH_PPC },
  313. { IDS_ENVIRONMENT_ALPHA, 3, VERSION_3, ARCH_ALPHA },
  314. { IDS_ENVIRONMENT_X86, 3, VERSION_3, ARCH_X86 },
  315. { IDS_ENVIRONMENT_IA64, 3, VERSION_3, ARCH_IA64 }};
  316. BOOL bRetval = FALSE;
  317. TString strDriverEnv;
  318. for( UINT i = 0; i < COUNTOF( aArchMap ); i++ ){
  319. //
  320. // Attempt to load the driver environment string from our resource file.
  321. //
  322. if( !strDriverEnv.bLoadString( ghInst, aArchMap[i].uArchId ) ){
  323. DBGMSG( DBG_WARN, ( "Error loading environment string from resource.\n" ) );
  324. break;
  325. }
  326. //
  327. // If the environment and version match, then encode the environment
  328. // and version into a single dword.
  329. //
  330. if( !lstrcmpi( pszArch, (LPCTSTR)strDriverEnv ) &&
  331. aArchMap[i].dwVersion == dwVer ){
  332. *pdwVal = aArchMap[i].dwPUIVer + aArchMap[i].dwPUIArch;
  333. bRetval = TRUE;
  334. break;
  335. }
  336. }
  337. return bRetval;
  338. }
  339. BOOL
  340. bGetDriverEnv(
  341. IN DWORD dwDriverVersion,
  342. OUT TString &strDriverEnv
  343. )
  344. /*++
  345. Routine Description:
  346. Convert the Encoded the Architecture and version to a
  347. spooler defined environment string.
  348. Arguments:
  349. dwDriverVersion - encoded driver version
  350. strDriverEnv - string where to return the environment string.
  351. Return Value:
  352. TRUE - environment string found, FALSE - error occured.
  353. --*/
  354. {
  355. struct ArchMap {
  356. DWORD dwDrvVer;
  357. UINT uArchId;
  358. };
  359. //
  360. // disable MIPS & PPC drivers, since they are not supported from setup
  361. //
  362. static ArchMap aArchMap [] = {
  363. { DRIVER_IA64_3, IDS_ENVIRONMENT_IA64 },
  364. { DRIVER_X86_3, IDS_ENVIRONMENT_X86 },
  365. { DRIVER_ALPHA_3, IDS_ENVIRONMENT_ALPHA },
  366. { DRIVER_X86_2, IDS_ENVIRONMENT_X86 },
  367. //{ DRIVER_MIPS_2, IDS_ENVIRONMENT_MIPS },
  368. { DRIVER_ALPHA_2, IDS_ENVIRONMENT_ALPHA },
  369. //{ DRIVER_PPC_2, IDS_ENVIRONMENT_PPC },
  370. { DRIVER_X86_1, IDS_ENVIRONMENT_X86 },
  371. //{ DRIVER_MIPS_1, IDS_ENVIRONMENT_MIPS },
  372. { DRIVER_ALPHA_1, IDS_ENVIRONMENT_ALPHA },
  373. //{ DRIVER_PPC_1, IDS_ENVIRONMENT_PPC },
  374. { DRIVER_X86_0, IDS_ENVIRONMENT_X86 },
  375. //{ DRIVER_MIPS_0, IDS_ENVIRONMENT_MIPS },
  376. { DRIVER_ALPHA_0, IDS_ENVIRONMENT_ALPHA },
  377. { DRIVER_WIN95, IDS_ENVIRONMENT_WIN95 }};
  378. UINT uId = 0;
  379. BOOL bRetval = FALSE;
  380. for( UINT i = 0; i < COUNTOF( aArchMap ); i++ ){
  381. if( aArchMap[i].dwDrvVer == dwDriverVersion ){
  382. uId = aArchMap[i].uArchId;
  383. bRetval = TRUE;
  384. break;
  385. }
  386. }
  387. if( bRetval ){
  388. //
  389. // Attempt to load the driver environment string from our resource file.
  390. //
  391. if( !strDriverEnv.bLoadString( ghInst, uId ) ){
  392. DBGMSG( DBG_WARN, ( "Error loading environment string from resource.\n" ) );
  393. bRetval = FALSE;
  394. }
  395. } else {
  396. DBGMSG( DBG_WARN, ( "Driver / Version not found, bGetDriverEnv.\n" ) );
  397. }
  398. return bRetval;
  399. }
  400. PLATFORM
  401. GetDriverPlatform(
  402. IN DWORD dwDriver
  403. )
  404. /*++
  405. Routine Description:
  406. Return the driver platform value (used by splsetup apis).
  407. Arguments:
  408. dwDriver - DWORD indicating driver platform/version.
  409. Return Value:
  410. PLATFORM.
  411. --*/
  412. {
  413. return (PLATFORM)( dwDriver % ARCH_MAX );
  414. }
  415. DWORD
  416. GetDriverVersion(
  417. IN DWORD dwDriver
  418. )
  419. /*++
  420. Routine Description:
  421. Return the driver version value (used by DRIVER_INFO_x).
  422. Arguments:
  423. dwDriver - DWORD indicating driver platform/version.
  424. Return Value:
  425. DWORD version.
  426. --*/
  427. {
  428. return dwDriver / ARCH_MAX;
  429. }
  430. BOOL
  431. bIsNativeDriver(
  432. IN LPCTSTR pszServerName,
  433. IN DWORD dwDriver
  434. )
  435. /*++
  436. Routine Description:
  437. Determines whether the platform/version is compatible with the
  438. current OS.
  439. Arguments:
  440. dwDriver - DWORD indicating driver platform/version.
  441. Return Value:
  442. TRUE - compatible, FALSE - not compatible.
  443. --*/
  444. {
  445. //
  446. // Get the current driver / version.
  447. //
  448. DWORD dwDrv;
  449. if( bGetCurrentDriver( pszServerName, &dwDrv ) ){
  450. return dwDrv == dwDriver;
  451. }
  452. return FALSE;
  453. }
  454. BOOL
  455. bIs3xDriver(
  456. IN DWORD dwDriver
  457. )
  458. /*++
  459. Routine Description:
  460. Returns TRUE iff driver works with 3.5x.
  461. Arguments:
  462. dwDriver - DWORD indicating driver platform/version.
  463. Return Value:
  464. --*/
  465. {
  466. return dwDriver < VERSION_2;
  467. }
  468. BOOL
  469. bGetArchName(
  470. IN DWORD dwDriver,
  471. OUT TString &strDrvArchName
  472. )
  473. /*++
  474. Routine Description:
  475. Retrieves the platform/version name from a driver platform/version.
  476. Arguments:
  477. dwDriver - DWORD indicating driver platform/version.
  478. strDrvArchName - String where to retun platform/version string.
  479. Return Value:
  480. TRUE strDrvArchName contains architecture name.
  481. FALSE error occurred reading string.
  482. --*/
  483. {
  484. TStatusB bStatus;
  485. //
  486. // Load the architecute / driver name.
  487. //
  488. bStatus DBGCHK = strDrvArchName.bLoadString( ghInst, IDS_DRIVER_BASE + dwDriver );
  489. return bStatus;
  490. }
  491. BOOL
  492. bIsCompatibleDriverVersion(
  493. IN DWORD dwDriver,
  494. IN DWORD dwVersion
  495. )
  496. /*++
  497. Routine Description:
  498. Checks if the specified drivers version is a compatible version.
  499. NOTE: This function MUST be re-rewritten if the drvier model changes.
  500. Arguments:
  501. dwDriver - DWORD indicating driver platform/version.
  502. dwVersion - DWORD version number to check.
  503. Return Value:
  504. TRUE version is compatible.
  505. FALSE verion is not compatible.
  506. --*/
  507. {
  508. DWORD dwDriverVersion = GetDriverVersion( dwDriver );
  509. //
  510. // If the version are equal then they are compatible.
  511. //
  512. if( dwVersion == dwDriverVersion )
  513. return TRUE;
  514. //
  515. // If current driver version is a version 3 (Win2K or above)
  516. // then version 2 (NT4 Kernel mode) are compatible drivers.
  517. //
  518. if( dwDriverVersion == 3 && dwVersion == 2 )
  519. return TRUE;
  520. return FALSE;
  521. }
  522. BOOL
  523. SpoolerGetVersionEx(
  524. IN LPCTSTR pszServerName,
  525. IN OUT OSVERSIONINFO *pOsVersionInfo
  526. )
  527. /*++
  528. Routine Description:
  529. Gets the osversion using spooler apis, thus it's remotable.
  530. Arguments:
  531. pszServerName - pointer to a string which contains the server name
  532. a NULL indicates the local machine.
  533. pOsVersionInf - pointer to osversion structure to fill in.
  534. Return Value:
  535. TRUE version structure was filled successfully.
  536. FALSE error occurred.
  537. --*/
  538. {
  539. SPLASSERT ( pOsVersionInfo );
  540. TStatusB bStatus;
  541. bStatus DBGNOCHK = FALSE;
  542. if( !pszServerName )
  543. {
  544. //
  545. // Get the osversion info structure size
  546. //
  547. bStatus DBGCHK = GetVersionEx( pOsVersionInfo );
  548. }
  549. else
  550. {
  551. //
  552. // Attempt to open print server with just read.
  553. //
  554. DWORD dwStatus = ERROR_SUCCESS;
  555. DWORD dwAccess = SERVER_READ;
  556. HANDLE hServer = NULL;
  557. DWORD dwNeeded = 0;
  558. DWORD dwType = REG_BINARY;
  559. //
  560. // Open the server for read access.
  561. //
  562. dwStatus = TPrinter::sOpenPrinter( pszServerName, &dwAccess, &hServer );
  563. //
  564. // Get the os version from the remote spooler.
  565. //
  566. if( dwStatus == ERROR_SUCCESS )
  567. {
  568. dwStatus = GetPrinterData( hServer,
  569. SPLREG_OS_VERSION,
  570. &dwType,
  571. (PBYTE)pOsVersionInfo,
  572. sizeof( OSVERSIONINFO ),
  573. &dwNeeded );
  574. if( dwStatus == ERROR_SUCCESS )
  575. {
  576. bStatus DBGCHK = TRUE;
  577. }
  578. }
  579. }
  580. return bStatus;
  581. }