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.

718 lines
17 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. StringCchCopy( pszArch, dwSize, 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. static ArchMap aArchMap [] = {
  215. { PROCESSOR_ARCHITECTURE_INTEL, 0, IDS_ENVIRONMENT_WIN95 },
  216. { PROCESSOR_ARCHITECTURE_INTEL, 2, IDS_ENVIRONMENT_X86 },
  217. { PROCESSOR_ARCHITECTURE_INTEL, 3, IDS_ENVIRONMENT_X86 }};
  218. bStatus = FALSE;
  219. for( UINT i = 0; i < COUNTOF( aArchMap ); i++ ){
  220. //
  221. // If a version and architecture match.
  222. //
  223. if( aArchMap[i].dwVersion == *pdwVer &&
  224. aArchMap[i].dwArch == dwArch ){
  225. dwDriverEnvId = aArchMap[i].uId;
  226. bStatus = TRUE;
  227. break;
  228. }
  229. }
  230. }
  231. //
  232. // If Environment ID and version found.
  233. //
  234. if( !bStatus ){
  235. DBGMSG( DBG_WARN, ( "Failed to find architecture in map.\n" ) );
  236. return FALSE;
  237. }
  238. //
  239. // Load the environment string from our resource file.
  240. //
  241. if( !strDriverEnv.bLoadString( ghInst, dwDriverEnvId ) ){
  242. DBGMSG( DBG_WARN, ( "Failed to load driver name string resource with %d\n", GetLastError() ) );
  243. return FALSE;
  244. }
  245. //
  246. // Check the provided buffer is large enough.
  247. //
  248. if( (DWORD)lstrlen( strDriverEnv ) >= ( dwSize - 1 ) ){
  249. DBGMSG( DBG_WARN, ( "Insuffcient buffer provided to bGetArchUseReg.\n" ) );
  250. return FALSE;
  251. }
  252. //
  253. // Copy back environment string to provided buffer.
  254. //
  255. StringCchCopy( pszArch, dwSize, strDriverEnv );
  256. DBGMSG( DBG_TRACE, ( "CComputerInfo.GetInfo: Architecture " TSTR "\n" , pszArch ) );
  257. DBGMSG( DBG_TRACE, ( "CComputerInfo.GetInfo: MajorVersion %d\n" , *pdwVer ) );
  258. return TRUE;
  259. }
  260. BOOL
  261. bEncodeArchVersion(
  262. IN LPCTSTR pszArch,
  263. IN DWORD dwVer,
  264. OUT LPDWORD pdwVal
  265. )
  266. /*++
  267. Routine Description:
  268. Encode the Architecture and version into a DWORD.
  269. Arguments:
  270. pszArch - pointer to machine spooler defined environment string
  271. dwVer - machines driver version
  272. pdwVal - pointer where to store the encoded value
  273. Return Value:
  274. TRUE - remote information returned, FALSE - remote information not available.
  275. --*/
  276. {
  277. struct ArchMap {
  278. UINT uArchId;
  279. DWORD dwVersion;
  280. DWORD dwPUIVer;
  281. DWORD dwPUIArch;
  282. };
  283. static ArchMap aArchMap [] = {
  284. { IDS_ENVIRONMENT_WIN95, 0, VERSION_0, ARCH_WIN95 },
  285. { IDS_ENVIRONMENT_X86, 2, VERSION_2, ARCH_X86 },
  286. { IDS_ENVIRONMENT_X86, 3, VERSION_3, ARCH_X86 },
  287. { IDS_ENVIRONMENT_IA64, 3, VERSION_3, ARCH_IA64 }};
  288. BOOL bRetval = FALSE;
  289. TString strDriverEnv;
  290. for( UINT i = 0; i < COUNTOF( aArchMap ); i++ ){
  291. //
  292. // Attempt to load the driver environment string from our resource file.
  293. //
  294. if( !strDriverEnv.bLoadString( ghInst, aArchMap[i].uArchId ) ){
  295. DBGMSG( DBG_WARN, ( "Error loading environment string from resource.\n" ) );
  296. break;
  297. }
  298. //
  299. // If the environment and version match, then encode the environment
  300. // and version into a single dword.
  301. //
  302. if( !lstrcmpi( pszArch, (LPCTSTR)strDriverEnv ) &&
  303. aArchMap[i].dwVersion == dwVer ){
  304. *pdwVal = aArchMap[i].dwPUIVer + aArchMap[i].dwPUIArch;
  305. bRetval = TRUE;
  306. break;
  307. }
  308. }
  309. return bRetval;
  310. }
  311. BOOL
  312. bGetDriverEnv(
  313. IN DWORD dwDriverVersion,
  314. OUT TString &strDriverEnv
  315. )
  316. /*++
  317. Routine Description:
  318. Convert the Encoded the Architecture and version to a
  319. spooler defined environment string.
  320. Arguments:
  321. dwDriverVersion - encoded driver version
  322. strDriverEnv - string where to return the environment string.
  323. Return Value:
  324. TRUE - environment string found, FALSE - error occured.
  325. --*/
  326. {
  327. struct ArchMap {
  328. DWORD dwDrvVer;
  329. UINT uArchId;
  330. };
  331. static ArchMap aArchMap [] = {
  332. { DRIVER_IA64_3, IDS_ENVIRONMENT_IA64 },
  333. { DRIVER_X86_3, IDS_ENVIRONMENT_X86 },
  334. { DRIVER_X86_2, IDS_ENVIRONMENT_X86 },
  335. { DRIVER_WIN95, IDS_ENVIRONMENT_WIN95 }};
  336. UINT uId = 0;
  337. BOOL bRetval = FALSE;
  338. for( UINT i = 0; i < COUNTOF( aArchMap ); i++ ){
  339. if( aArchMap[i].dwDrvVer == dwDriverVersion ){
  340. uId = aArchMap[i].uArchId;
  341. bRetval = TRUE;
  342. break;
  343. }
  344. }
  345. if( bRetval ){
  346. //
  347. // Attempt to load the driver environment string from our resource file.
  348. //
  349. if( !strDriverEnv.bLoadString( ghInst, uId ) ){
  350. DBGMSG( DBG_WARN, ( "Error loading environment string from resource.\n" ) );
  351. bRetval = FALSE;
  352. }
  353. } else {
  354. DBGMSG( DBG_WARN, ( "Driver / Version not found, bGetDriverEnv.\n" ) );
  355. }
  356. return bRetval;
  357. }
  358. PLATFORM
  359. GetDriverPlatform(
  360. IN DWORD dwDriver
  361. )
  362. /*++
  363. Routine Description:
  364. Return the driver platform value (used by splsetup apis).
  365. Arguments:
  366. dwDriver - DWORD indicating driver platform/version.
  367. Return Value:
  368. PLATFORM.
  369. --*/
  370. {
  371. return (PLATFORM)( dwDriver % ARCH_MAX );
  372. }
  373. DWORD
  374. GetDriverVersion(
  375. IN DWORD dwDriver
  376. )
  377. /*++
  378. Routine Description:
  379. Return the driver version value (used by DRIVER_INFO_x).
  380. Arguments:
  381. dwDriver - DWORD indicating driver platform/version.
  382. Return Value:
  383. DWORD version.
  384. --*/
  385. {
  386. return dwDriver / ARCH_MAX;
  387. }
  388. BOOL
  389. bIsNativeDriver(
  390. IN LPCTSTR pszServerName,
  391. IN DWORD dwDriver
  392. )
  393. /*++
  394. Routine Description:
  395. Determines whether the platform/version is compatible with the
  396. current OS.
  397. Arguments:
  398. dwDriver - DWORD indicating driver platform/version.
  399. Return Value:
  400. TRUE - compatible, FALSE - not compatible.
  401. --*/
  402. {
  403. //
  404. // Get the current driver / version.
  405. //
  406. DWORD dwDrv;
  407. if( bGetCurrentDriver( pszServerName, &dwDrv ) ){
  408. return dwDrv == dwDriver;
  409. }
  410. return FALSE;
  411. }
  412. BOOL
  413. bIs3xDriver(
  414. IN DWORD dwDriver
  415. )
  416. /*++
  417. Routine Description:
  418. Returns TRUE iff driver works with 3.5x.
  419. Arguments:
  420. dwDriver - DWORD indicating driver platform/version.
  421. Return Value:
  422. --*/
  423. {
  424. return dwDriver < VERSION_2;
  425. }
  426. BOOL
  427. bGetArchName(
  428. IN DWORD dwDriver,
  429. OUT TString &strDrvArchName
  430. )
  431. /*++
  432. Routine Description:
  433. Retrieves the platform/version name from a driver platform/version.
  434. Arguments:
  435. dwDriver - DWORD indicating driver platform/version.
  436. strDrvArchName - String where to retun platform/version string.
  437. Return Value:
  438. TRUE strDrvArchName contains architecture name.
  439. FALSE error occurred reading string.
  440. --*/
  441. {
  442. TStatusB bStatus;
  443. //
  444. // Load the architecute / driver name.
  445. //
  446. bStatus DBGCHK = strDrvArchName.bLoadString( ghInst, IDS_DRIVER_BASE + dwDriver );
  447. return bStatus;
  448. }
  449. BOOL
  450. bIsCompatibleDriverVersion(
  451. IN DWORD dwDriver,
  452. IN DWORD dwVersion
  453. )
  454. /*++
  455. Routine Description:
  456. Checks if the specified drivers version is a compatible version.
  457. NOTE: This function MUST be re-rewritten if the drvier model changes.
  458. Arguments:
  459. dwDriver - DWORD indicating driver platform/version.
  460. dwVersion - DWORD version number to check.
  461. Return Value:
  462. TRUE version is compatible.
  463. FALSE verion is not compatible.
  464. --*/
  465. {
  466. DWORD dwDriverVersion = GetDriverVersion( dwDriver );
  467. //
  468. // If the version are equal then they are compatible.
  469. //
  470. if( dwVersion == dwDriverVersion )
  471. return TRUE;
  472. //
  473. // If current driver version is a version 3 (Win2K or above)
  474. // then version 2 (NT4 Kernel mode) are compatible drivers.
  475. //
  476. if( dwDriverVersion == 3 && dwVersion == 2 )
  477. return TRUE;
  478. return FALSE;
  479. }
  480. BOOL
  481. SpoolerGetVersionEx(
  482. IN LPCTSTR pszServerName,
  483. IN OUT OSVERSIONINFO *pOsVersionInfo
  484. )
  485. /*++
  486. Routine Description:
  487. Gets the osversion using spooler apis, thus it's remotable.
  488. Arguments:
  489. pszServerName - pointer to a string which contains the server name
  490. a NULL indicates the local machine.
  491. pOsVersionInf - pointer to osversion structure to fill in.
  492. Return Value:
  493. TRUE version structure was filled successfully.
  494. FALSE error occurred.
  495. --*/
  496. {
  497. SPLASSERT ( pOsVersionInfo );
  498. TStatusB bStatus;
  499. bStatus DBGNOCHK = FALSE;
  500. if( !pszServerName )
  501. {
  502. //
  503. // Get the osversion info structure size
  504. //
  505. bStatus DBGCHK = GetVersionEx( pOsVersionInfo );
  506. }
  507. else
  508. {
  509. //
  510. // Attempt to open print server with just read.
  511. //
  512. DWORD dwStatus = ERROR_SUCCESS;
  513. DWORD dwAccess = SERVER_READ;
  514. HANDLE hServer = NULL;
  515. DWORD dwNeeded = 0;
  516. DWORD dwType = REG_BINARY;
  517. //
  518. // Open the server for read access.
  519. //
  520. dwStatus = TPrinter::sOpenPrinter( pszServerName, &dwAccess, &hServer );
  521. //
  522. // Get the os version from the remote spooler.
  523. //
  524. if( dwStatus == ERROR_SUCCESS )
  525. {
  526. dwStatus = GetPrinterData( hServer,
  527. SPLREG_OS_VERSION,
  528. &dwType,
  529. (PBYTE)pOsVersionInfo,
  530. sizeof( OSVERSIONINFO ),
  531. &dwNeeded );
  532. if( dwStatus == ERROR_SUCCESS )
  533. {
  534. bStatus DBGCHK = TRUE;
  535. }
  536. }
  537. }
  538. return bStatus;
  539. }