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
718 lines
17 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1996 - 1997
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
drvrver.hxx
|
|
|
|
Abstract:
|
|
|
|
Driver version detection header.
|
|
|
|
Author:
|
|
|
|
Steve Kiraly (SteveKi) 21-Jan-1996
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include "psetup.hxx"
|
|
#include "drvver.hxx"
|
|
#include "splapip.h"
|
|
#include "compinfo.hxx"
|
|
|
|
BOOL
|
|
bGetCurrentDriver(
|
|
IN LPCTSTR pszServerName,
|
|
OUT LPDWORD pdwCurrentDriver
|
|
)
|
|
{
|
|
TCHAR szArch[kStrMax];
|
|
BOOL bRetval = FALSE;
|
|
DWORD dwVer = 0;
|
|
|
|
//
|
|
// Attempt to get the architecture / version from the machine.
|
|
// First attempt to get the information from the spooler.
|
|
//
|
|
bRetval = bGetArchUseSpooler( pszServerName, szArch, COUNTOF( szArch ), &dwVer );
|
|
|
|
//
|
|
// If spooler did not respond, this may be a downlevel
|
|
// print spooler. "Downlevel" meaning older version.
|
|
//
|
|
if( !bRetval )
|
|
{
|
|
//
|
|
// Attempt to get the information using the remote registry calls
|
|
// We only connect to the remote registry if a server name was passed.
|
|
//
|
|
if( pszServerName )
|
|
{
|
|
bRetval = bGetArchUseReg( pszServerName, szArch, COUNTOF( szArch ), &dwVer );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check for any retuned information.
|
|
//
|
|
if( bRetval )
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "Server " TSTR " Arch " TSTR " Ver %d\n", DBGSTR(pszServerName), szArch, dwVer ) );
|
|
|
|
//
|
|
// Encode the architecture / version into a dword.
|
|
//
|
|
if( bEncodeArchVersion( szArch, dwVer, pdwCurrentDriver ) )
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "Encoded Arch / Version %d\n", *pdwCurrentDriver ) );
|
|
bRetval = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DBGMSG( DBG_WARN, ( "Encode architecture and version failed.\n" ) );
|
|
bRetval = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBGMSG( DBG_WARN, ( "Fetching architecture and version failed.\n" ) );
|
|
bRetval = FALSE;
|
|
}
|
|
return bRetval;
|
|
}
|
|
|
|
BOOL
|
|
bGetArchUseSpooler(
|
|
IN LPCTSTR pName,
|
|
OUT LPTSTR pszArch,
|
|
IN DWORD dwSize,
|
|
IN OUT LPDWORD pdwVer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets the specified print server the architectue and
|
|
driver version using the spooler.
|
|
|
|
Arguments:
|
|
|
|
pName - pointer to print server name.
|
|
pszArch - pointer to a buffer where to return the machine architecture string
|
|
dwSize - Size in characters of the provided architecture string
|
|
pdwVersion - pointer where to return the remote machine driver version.
|
|
|
|
Return Value:
|
|
|
|
TRUE - remote information returned, FALSE - remote information not available.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Attempt to open print server with full access.
|
|
//
|
|
BOOL bReturn = FALSE;
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
DWORD dwAccess = SERVER_READ;
|
|
HANDLE hServer = NULL;
|
|
TStatus Status;
|
|
|
|
//
|
|
// Open the server for read access.
|
|
//
|
|
Status DBGCHK = TPrinter::sOpenPrinter( pName,
|
|
&dwAccess,
|
|
&hServer );
|
|
|
|
//
|
|
// Save administrator capability flag.
|
|
//
|
|
if( Status == ERROR_SUCCESS ){
|
|
|
|
//
|
|
// Get the remote spooler's architecture type and version.
|
|
//
|
|
TCHAR szArch[kStrMax];
|
|
memset( szArch, 0, sizeof( szArch ) );
|
|
|
|
DWORD dwNeeded = 0;
|
|
DWORD dwVer = 0;
|
|
DWORD dwVerType = REG_DWORD;
|
|
DWORD dwArchType = REG_SZ;
|
|
|
|
if( dwStatus == ERROR_SUCCESS ){
|
|
|
|
dwStatus = GetPrinterData( hServer,
|
|
SPLREG_ARCHITECTURE,
|
|
&dwArchType,
|
|
(PBYTE)szArch,
|
|
sizeof( szArch ),
|
|
&dwNeeded );
|
|
}
|
|
|
|
if( dwStatus == ERROR_SUCCESS ){
|
|
|
|
dwStatus = GetPrinterData( hServer,
|
|
SPLREG_MAJOR_VERSION,
|
|
&dwVerType,
|
|
(PBYTE)&dwVer,
|
|
sizeof( dwVer ),
|
|
&dwNeeded );
|
|
}
|
|
|
|
if( dwStatus == ERROR_SUCCESS ){
|
|
|
|
DBGMSG( DBG_TRACE, ( "GetPrinterData: Architecture " TSTR "\n" , szArch ) );
|
|
DBGMSG( DBG_TRACE, ( "GetPrinterData: MajorVersion %d\n" , dwVer ) );
|
|
|
|
//
|
|
// Only success if provided buffer is big enough.
|
|
//
|
|
if( (DWORD)lstrlen( szArch ) < dwSize ){
|
|
|
|
StringCchCopy( pszArch, dwSize, szArch );
|
|
*pdwVer = dwVer;
|
|
bReturn = TRUE;
|
|
|
|
} else {
|
|
dwStatus = ERROR_INSUFFICIENT_BUFFER;
|
|
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
|
bReturn = FALSE;
|
|
}
|
|
|
|
} else {
|
|
|
|
DBGMSG( DBG_WARN, ( "GetPrinterData failed with %d\n", dwStatus ) );
|
|
|
|
}
|
|
}
|
|
|
|
if( hServer ){
|
|
ClosePrinter( hServer );
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
BOOL
|
|
bGetArchUseReg(
|
|
IN LPCTSTR pName,
|
|
OUT LPTSTR pszArch,
|
|
IN DWORD dwSize,
|
|
OUT LPDWORD pdwVer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets the specified print server the architectue and
|
|
driver version using the remote registry.
|
|
|
|
Arguments:
|
|
|
|
pName - pointer to print server name.
|
|
pszArch - pointer to a buffer where to return the machine architecture string
|
|
dwSize - Size in characters of the provided architecture string
|
|
pdwVersion - pointer where to return the remote machine driver version.
|
|
|
|
Return Value:
|
|
|
|
TRUE - remote information returned, FALSE - remote information not available.
|
|
|
|
--*/
|
|
{
|
|
BOOL bStatus = TRUE;
|
|
DWORD dwDriverEnvId = 0;
|
|
DWORD dwArch = 0;
|
|
TString strDriverEnv;
|
|
|
|
//
|
|
// Create the computer information.
|
|
//
|
|
CComputerInfo CompInfo ( pName );
|
|
|
|
//
|
|
// Get the information from the remote machine.
|
|
//
|
|
if( !CompInfo.GetInfo() ){
|
|
|
|
DBGMSG( DBG_WARN, ( "CComputerInfo.GetInfo failed with %d\n", GetLastError() ) );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If this is a windows 95 machine set resource string
|
|
// id and set the version to zero.
|
|
//
|
|
if( CompInfo.IsRunningWindows95() ){
|
|
|
|
dwDriverEnvId = IDS_ENVIRONMENT_WIN95;
|
|
*pdwVer = 0;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Convert processor type to spooler defined environment string.
|
|
//
|
|
dwArch = CompInfo.GetProcessorArchitecture();
|
|
*pdwVer = CompInfo.GetSpoolerVersion();
|
|
|
|
struct ArchMap {
|
|
DWORD dwArch;
|
|
DWORD dwVersion;
|
|
UINT uId;
|
|
};
|
|
|
|
static ArchMap aArchMap [] = {
|
|
{ PROCESSOR_ARCHITECTURE_INTEL, 0, IDS_ENVIRONMENT_WIN95 },
|
|
{ PROCESSOR_ARCHITECTURE_INTEL, 2, IDS_ENVIRONMENT_X86 },
|
|
{ PROCESSOR_ARCHITECTURE_INTEL, 3, IDS_ENVIRONMENT_X86 }};
|
|
|
|
bStatus = FALSE;
|
|
for( UINT i = 0; i < COUNTOF( aArchMap ); i++ ){
|
|
|
|
//
|
|
// If a version and architecture match.
|
|
//
|
|
if( aArchMap[i].dwVersion == *pdwVer &&
|
|
aArchMap[i].dwArch == dwArch ){
|
|
|
|
dwDriverEnvId = aArchMap[i].uId;
|
|
bStatus = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If Environment ID and version found.
|
|
//
|
|
if( !bStatus ){
|
|
DBGMSG( DBG_WARN, ( "Failed to find architecture in map.\n" ) );
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Load the environment string from our resource file.
|
|
//
|
|
if( !strDriverEnv.bLoadString( ghInst, dwDriverEnvId ) ){
|
|
|
|
DBGMSG( DBG_WARN, ( "Failed to load driver name string resource with %d\n", GetLastError() ) );
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Check the provided buffer is large enough.
|
|
//
|
|
if( (DWORD)lstrlen( strDriverEnv ) >= ( dwSize - 1 ) ){
|
|
DBGMSG( DBG_WARN, ( "Insuffcient buffer provided to bGetArchUseReg.\n" ) );
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Copy back environment string to provided buffer.
|
|
//
|
|
StringCchCopy( pszArch, dwSize, strDriverEnv );
|
|
|
|
DBGMSG( DBG_TRACE, ( "CComputerInfo.GetInfo: Architecture " TSTR "\n" , pszArch ) );
|
|
DBGMSG( DBG_TRACE, ( "CComputerInfo.GetInfo: MajorVersion %d\n" , *pdwVer ) );
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
BOOL
|
|
bEncodeArchVersion(
|
|
IN LPCTSTR pszArch,
|
|
IN DWORD dwVer,
|
|
OUT LPDWORD pdwVal
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Encode the Architecture and version into a DWORD.
|
|
|
|
Arguments:
|
|
|
|
pszArch - pointer to machine spooler defined environment string
|
|
dwVer - machines driver version
|
|
pdwVal - pointer where to store the encoded value
|
|
|
|
Return Value:
|
|
|
|
TRUE - remote information returned, FALSE - remote information not available.
|
|
|
|
--*/
|
|
{
|
|
|
|
struct ArchMap {
|
|
UINT uArchId;
|
|
DWORD dwVersion;
|
|
DWORD dwPUIVer;
|
|
DWORD dwPUIArch;
|
|
};
|
|
|
|
static ArchMap aArchMap [] = {
|
|
{ IDS_ENVIRONMENT_WIN95, 0, VERSION_0, ARCH_WIN95 },
|
|
{ IDS_ENVIRONMENT_X86, 2, VERSION_2, ARCH_X86 },
|
|
{ IDS_ENVIRONMENT_X86, 3, VERSION_3, ARCH_X86 },
|
|
{ IDS_ENVIRONMENT_IA64, 3, VERSION_3, ARCH_IA64 }};
|
|
|
|
BOOL bRetval = FALSE;
|
|
TString strDriverEnv;
|
|
for( UINT i = 0; i < COUNTOF( aArchMap ); i++ ){
|
|
|
|
//
|
|
// Attempt to load the driver environment string from our resource file.
|
|
//
|
|
if( !strDriverEnv.bLoadString( ghInst, aArchMap[i].uArchId ) ){
|
|
DBGMSG( DBG_WARN, ( "Error loading environment string from resource.\n" ) );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If the environment and version match, then encode the environment
|
|
// and version into a single dword.
|
|
//
|
|
if( !lstrcmpi( pszArch, (LPCTSTR)strDriverEnv ) &&
|
|
aArchMap[i].dwVersion == dwVer ){
|
|
|
|
*pdwVal = aArchMap[i].dwPUIVer + aArchMap[i].dwPUIArch;
|
|
bRetval = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return bRetval;
|
|
}
|
|
|
|
BOOL
|
|
bGetDriverEnv(
|
|
IN DWORD dwDriverVersion,
|
|
OUT TString &strDriverEnv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert the Encoded the Architecture and version to a
|
|
spooler defined environment string.
|
|
|
|
Arguments:
|
|
|
|
dwDriverVersion - encoded driver version
|
|
strDriverEnv - string where to return the environment string.
|
|
|
|
Return Value:
|
|
|
|
TRUE - environment string found, FALSE - error occured.
|
|
|
|
--*/
|
|
{
|
|
struct ArchMap {
|
|
DWORD dwDrvVer;
|
|
UINT uArchId;
|
|
};
|
|
|
|
static ArchMap aArchMap [] = {
|
|
{ DRIVER_IA64_3, IDS_ENVIRONMENT_IA64 },
|
|
{ DRIVER_X86_3, IDS_ENVIRONMENT_X86 },
|
|
{ DRIVER_X86_2, IDS_ENVIRONMENT_X86 },
|
|
{ DRIVER_WIN95, IDS_ENVIRONMENT_WIN95 }};
|
|
|
|
UINT uId = 0;
|
|
BOOL bRetval = FALSE;
|
|
for( UINT i = 0; i < COUNTOF( aArchMap ); i++ ){
|
|
|
|
if( aArchMap[i].dwDrvVer == dwDriverVersion ){
|
|
uId = aArchMap[i].uArchId;
|
|
bRetval = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( bRetval ){
|
|
|
|
//
|
|
// Attempt to load the driver environment string from our resource file.
|
|
//
|
|
if( !strDriverEnv.bLoadString( ghInst, uId ) ){
|
|
DBGMSG( DBG_WARN, ( "Error loading environment string from resource.\n" ) );
|
|
bRetval = FALSE;
|
|
}
|
|
|
|
} else {
|
|
|
|
DBGMSG( DBG_WARN, ( "Driver / Version not found, bGetDriverEnv.\n" ) );
|
|
|
|
}
|
|
|
|
return bRetval;
|
|
}
|
|
|
|
|
|
PLATFORM
|
|
GetDriverPlatform(
|
|
IN DWORD dwDriver
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return the driver platform value (used by splsetup apis).
|
|
|
|
Arguments:
|
|
|
|
dwDriver - DWORD indicating driver platform/version.
|
|
|
|
Return Value:
|
|
|
|
PLATFORM.
|
|
|
|
--*/
|
|
{
|
|
return (PLATFORM)( dwDriver % ARCH_MAX );
|
|
}
|
|
|
|
DWORD
|
|
GetDriverVersion(
|
|
IN DWORD dwDriver
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return the driver version value (used by DRIVER_INFO_x).
|
|
|
|
Arguments:
|
|
|
|
dwDriver - DWORD indicating driver platform/version.
|
|
|
|
Return Value:
|
|
|
|
DWORD version.
|
|
|
|
--*/
|
|
|
|
{
|
|
return dwDriver / ARCH_MAX;
|
|
}
|
|
|
|
BOOL
|
|
bIsNativeDriver(
|
|
IN LPCTSTR pszServerName,
|
|
IN DWORD dwDriver
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determines whether the platform/version is compatible with the
|
|
current OS.
|
|
|
|
Arguments:
|
|
|
|
dwDriver - DWORD indicating driver platform/version.
|
|
|
|
Return Value:
|
|
|
|
TRUE - compatible, FALSE - not compatible.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Get the current driver / version.
|
|
//
|
|
DWORD dwDrv;
|
|
if( bGetCurrentDriver( pszServerName, &dwDrv ) ){
|
|
return dwDrv == dwDriver;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
bIs3xDriver(
|
|
IN DWORD dwDriver
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns TRUE iff driver works with 3.5x.
|
|
|
|
Arguments:
|
|
|
|
dwDriver - DWORD indicating driver platform/version.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
|
|
{
|
|
return dwDriver < VERSION_2;
|
|
}
|
|
|
|
BOOL
|
|
bGetArchName(
|
|
IN DWORD dwDriver,
|
|
OUT TString &strDrvArchName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieves the platform/version name from a driver platform/version.
|
|
|
|
Arguments:
|
|
|
|
dwDriver - DWORD indicating driver platform/version.
|
|
strDrvArchName - String where to retun platform/version string.
|
|
|
|
Return Value:
|
|
|
|
TRUE strDrvArchName contains architecture name.
|
|
FALSE error occurred reading string.
|
|
|
|
--*/
|
|
|
|
{
|
|
TStatusB bStatus;
|
|
|
|
//
|
|
// Load the architecute / driver name.
|
|
//
|
|
bStatus DBGCHK = strDrvArchName.bLoadString( ghInst, IDS_DRIVER_BASE + dwDriver );
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
|
|
BOOL
|
|
bIsCompatibleDriverVersion(
|
|
IN DWORD dwDriver,
|
|
IN DWORD dwVersion
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Checks if the specified drivers version is a compatible version.
|
|
|
|
NOTE: This function MUST be re-rewritten if the drvier model changes.
|
|
|
|
Arguments:
|
|
|
|
dwDriver - DWORD indicating driver platform/version.
|
|
dwVersion - DWORD version number to check.
|
|
|
|
Return Value:
|
|
|
|
TRUE version is compatible.
|
|
FALSE verion is not compatible.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwDriverVersion = GetDriverVersion( dwDriver );
|
|
|
|
//
|
|
// If the version are equal then they are compatible.
|
|
//
|
|
if( dwVersion == dwDriverVersion )
|
|
return TRUE;
|
|
|
|
//
|
|
// If current driver version is a version 3 (Win2K or above)
|
|
// then version 2 (NT4 Kernel mode) are compatible drivers.
|
|
//
|
|
if( dwDriverVersion == 3 && dwVersion == 2 )
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
SpoolerGetVersionEx(
|
|
IN LPCTSTR pszServerName,
|
|
IN OUT OSVERSIONINFO *pOsVersionInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets the osversion using spooler apis, thus it's remotable.
|
|
|
|
Arguments:
|
|
|
|
pszServerName - pointer to a string which contains the server name
|
|
a NULL indicates the local machine.
|
|
pOsVersionInf - pointer to osversion structure to fill in.
|
|
|
|
Return Value:
|
|
|
|
TRUE version structure was filled successfully.
|
|
FALSE error occurred.
|
|
|
|
--*/
|
|
|
|
{
|
|
SPLASSERT ( pOsVersionInfo );
|
|
|
|
TStatusB bStatus;
|
|
bStatus DBGNOCHK = FALSE;
|
|
|
|
if( !pszServerName )
|
|
{
|
|
//
|
|
// Get the osversion info structure size
|
|
//
|
|
bStatus DBGCHK = GetVersionEx( pOsVersionInfo );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Attempt to open print server with just read.
|
|
//
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
DWORD dwAccess = SERVER_READ;
|
|
HANDLE hServer = NULL;
|
|
DWORD dwNeeded = 0;
|
|
DWORD dwType = REG_BINARY;
|
|
|
|
//
|
|
// Open the server for read access.
|
|
//
|
|
dwStatus = TPrinter::sOpenPrinter( pszServerName, &dwAccess, &hServer );
|
|
|
|
//
|
|
// Get the os version from the remote spooler.
|
|
//
|
|
if( dwStatus == ERROR_SUCCESS )
|
|
{
|
|
dwStatus = GetPrinterData( hServer,
|
|
SPLREG_OS_VERSION,
|
|
&dwType,
|
|
(PBYTE)pOsVersionInfo,
|
|
sizeof( OSVERSIONINFO ),
|
|
&dwNeeded );
|
|
|
|
if( dwStatus == ERROR_SUCCESS )
|
|
{
|
|
bStatus DBGCHK = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bStatus;
|
|
}
|