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.
 
 
 
 
 
 

971 lines
25 KiB

/*++
Copyright (C) Microsoft Corporation, 1995 - 1999
All rights reserved.
Module Name:
drvsetup.cxx
Abstract:
Printer Driver Setup class. This class is used to do various
types of printer driver installations.
Author:
Steve Kiraly (SteveKi) 01-Nov-1996
Revision History:
--*/
#include "precomp.hxx"
#pragma hdrstop
#include "psetup.hxx"
#include "drvver.hxx"
#include "splapip.h"
#include "compinfo.hxx"
#include "drvsetup.hxx"
/********************************************************************
Printer Driver installation class.
********************************************************************/
TPrinterDriverInstallation::
TPrinterDriverInstallation(
IN LPCTSTR pszServerName,
IN HWND hwnd
) : _strServerName( pszServerName ),
_bValid( FALSE ),
_hwnd( hwnd ),
_hSetupDrvSetupParams( INVALID_HANDLE_VALUE ),
_hSelectedDrvInfo( INVALID_HANDLE_VALUE ),
_pszServerName( NULL ),
_dwDriverVersion( (DWORD)kDefault ),
_dwInstallFlags( 0 )
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::ctor\n" ) );
//
// Initialize the os version info structure.
//
memset( &_OsVersionInfo, 0, sizeof( _OsVersionInfo ) );
//
// Check if the setup library is valid.
//
if( !VALID_OBJ( _PSetup ) || !VALID_OBJ( _strServerName ) )
{
return;
}
//
// A null server name is the local machine.
//
if( pszServerName )
{
DBGMSG( DBG_WARN, ( "Remote machine specified.\n" ) );
_pszServerName = const_cast<LPTSTR>( static_cast<LPCTSTR>( _strServerName ) );
}
//
// Get the setup driver parameter handle.
//
_hSetupDrvSetupParams = _PSetup.PSetupCreatePrinterDeviceInfoList( _hwnd );
if( _hSetupDrvSetupParams == INVALID_HANDLE_VALUE )
{
DBGMSG( DBG_WARN, ( "PSetup.PSetupCreatePrinterDeviceInfoList failed.\n" ) );
return;
}
//
// Get the current platform / driver version.
//
if( !bGetCurrentDriver( pszServerName, &_dwDriverVersion ) )
{
DBGMSG( DBG_WARN, ( "GetCurrentDriver failed with %d.\n", GetLastError() ) );
//
// If we are talking to a remote machine and the get current driver failed
// then instead of failing construnction use this platforms driver version.
//
if( !pszServerName )
{
//
// Unable to get the platform / driver version
// from the local spooler.
//
return;
}
//
// Try to get the driver version from the local spooler
//
if( !bGetCurrentDriver( NULL, &_dwDriverVersion ) )
{
DBGMSG( DBG_WARN, ( "GetCurrentDriver failed with %d.\n", GetLastError() ) );
return;
}
}
//
// We have a valid object.
//
_bValid = TRUE;
}
TPrinterDriverInstallation::
~TPrinterDriverInstallation(
VOID
)
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::dtor\n" ) );
//
// Release the selected driver information.
//
vReleaseSelectedDriver();
//
// Release the driver setup parameter handle.
//
if( _hSetupDrvSetupParams != INVALID_HANDLE_VALUE )
{
_PSetup.PSetupDestroyPrinterDeviceInfoList( _hSetupDrvSetupParams );
}
}
BOOL
TPrinterDriverInstallation::
bValid(
VOID
) const
{
return _bValid;
}
TPrinterDriverInstallation::EStatusCode
TPrinterDriverInstallation::
ePromptForDriverSelection(
VOID
)
{
SPLASSERT( bValid() );
TPrinterDriverInstallation::EStatusCode Retval = kError;
//
// Release any selected driver information.
//
vReleaseSelectedDriver();
//
// Display UI for the user to select a driver.
//
if( _PSetup.PSetupSelectDriver( _hSetupDrvSetupParams, _hwnd ) )
{
//
// Refresh the driver name with the currently selected driver.
//
if( bGetSelectedDriver() )
{
DBGMSG( DBG_TRACE, ( "Selected Driver " TSTR "\n", (LPCTSTR)_strDriverName ) );
Retval = kSuccess;
}
}
else
{
//
// Check if the user hit cancel, this is not
// an error just normal cancel request.
//
if( GetLastError() == ERROR_CANCELLED )
{
DBGMSG( DBG_TRACE, ( "Select driver user cancel request.\n" ) );
Retval = kCancel;
}
else
{
DBGMSG( DBG_TRACE, ( "PSetupSelectDriver failed %d\n", GetLastError() ) );
Retval = kError;
}
}
return Retval;
}
BOOL
TPrinterDriverInstallation::
bSetDriverName(
IN const TString &strDriverName
)
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::bSetDriverName\n" ) );
SPLASSERT( bValid() );
return _strDriverName.bUpdate( strDriverName );
}
BOOL
TPrinterDriverInstallation::
bGetDriverName(
IN TString &strDriverName
) const
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::bGetDriverName\n" ) );
SPLASSERT( bValid() );
return strDriverName.bUpdate( _strDriverName );
}
BOOL
TPrinterDriverInstallation::
bIsDriverInstalled(
IN const DWORD xdwDriverVersion,
IN const BOOL bKernelModeCompatible
) const
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::bIsDriverInstalled\n" ) );
SPLASSERT( bValid() );
TStatusB bStatus;
PLATFORM DriverPlatform;
DWORD dwDriverVersion;
//
// If the default was passed then then use the pre-fetched version value.
//
if( xdwDriverVersion == kDefault )
{
DriverPlatform = GetDriverPlatform( _dwDriverVersion );
dwDriverVersion = GetDriverVersion( _dwDriverVersion );
}
else
{
DriverPlatform = GetDriverPlatform( xdwDriverVersion );
dwDriverVersion = GetDriverVersion( xdwDriverVersion );
}
//
// If we want to check if this a kernel mode compatible driver
// then the printer setup api's will accept the kKernelModeDriver
// value and do the compatiblity check. Note if the driver version is
// less than version 2 the kernel mode compatibiltiy flag does not apply.
//
if( bKernelModeCompatible && ( _dwDriverVersion >= 2 ) )
{
dwDriverVersion = KERNEL_MODE_DRIVER_VERSION;
}
//
// Check if the selected printer is currently installed.
//
bStatus DBGNOCHK = _PSetup.PSetupIsDriverInstalled( _pszServerName,
_strDriverName,
DriverPlatform,
dwDriverVersion );
return bStatus;
}
INT
TPrinterDriverInstallation::
IsDriverInstalledForInf(
IN const DWORD xdwDriverVersion,
IN const BOOL bKernelModeCompatible
) const
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::iIsDriverInstalledForInf\n" ) );
SPLASSERT( bValid() );
INT iReturn = DRIVER_MODEL_NOT_INSTALLED;
DWORD dwDriverVersion = xdwDriverVersion == kDefault ? _dwDriverVersion : xdwDriverVersion;
//
// We must have a selected driver to call this API.
//
TStatusB bStatus;
bStatus DBGCHK = bIsDriverSelected( );
if( bStatus )
{
//
// If we want to check if this a kernel mode compatible driver
// then the printer setup api's will accept the kKernelModeDriver
// value and do the compatiblity check. Note if the driver version is
// less than version 2 the kernel mode compatibiltiy flag does not apply.
//
DWORD dwDriver = bKernelModeCompatible && ( dwDriverVersion >= 2 ) ? KERNEL_MODE_DRIVER_VERSION : GetDriverVersion( dwDriverVersion );
//
// Check if the selected printer is currently installed.
//
iReturn = _PSetup.PSetupIsTheDriverFoundInInfInstalled( _pszServerName,
_hSelectedDrvInfo,
GetDriverPlatform( dwDriverVersion ),
GetDriverVersion( dwDriverVersion ),
dwDriver );
}
return iReturn;
}
BOOL
TPrinterDriverInstallation::
bSetSourcePath(
IN const LPCTSTR pszSourcePath,
IN const BOOL bClearSourcePath
)
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::bSetSourcePath\n" ) );
SPLASSERT( bValid() );
DBGMSG( DBG_TRACE, ( "SourcePath " TSTR "\n", DBGSTR( pszSourcePath ) ) );
if( bClearSourcePath )
{
return _strSourcePath.bUpdate( NULL );
}
return bValidateSourcePath( pszSourcePath ) && _strSourcePath.bUpdate( pszSourcePath );
}
VOID
TPrinterDriverInstallation::
SetInstallFlags(
DWORD dwInstallFlags
)
{
_dwInstallFlags = dwInstallFlags;
}
DWORD
TPrinterDriverInstallation::
GetInstallFlags(
VOID
) const
{
return _dwInstallFlags;
}
BOOL
TPrinterDriverInstallation::
bInstallDriver(
OUT TString *pstrNewDriverName,
IN BOOL bOfferReplacement,
IN const BOOL xInstallFromWeb,
IN const HWND xhwnd,
IN const DWORD xdwDriverVersion,
IN const DWORD xdwAddDrvFlags,
IN const BOOL xbUpdateDriver,
IN const BOOL xbIgnoreSelectDriverFailure
)
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::bInstallDriver\n" ) );
SPLASSERT( bValid() );
SPLASSERT( !_strDriverName.bEmpty() );
TStatus Status;
TStatusB bStatus;
DWORD dwDriverVersion = xdwDriverVersion == kDefault ? _dwDriverVersion : xdwDriverVersion;
HWND hwnd = xhwnd == NULL ? _hwnd : xhwnd;
BOOL bInstallFromWeb = xInstallFromWeb == kDefault ? FALSE : xInstallFromWeb;
DWORD dwAddDrvFlags = xdwAddDrvFlags == kDefault ? APD_COPY_NEW_FILES : xdwAddDrvFlags;
BOOL bUseDriverName = FALSE;
//
// Assume success.
//
bStatus DBGNOCHK = TRUE;
//
// This is an optimization. Since getting the selected driver actually parses
// the inf file. In this routine we will execute the if statement the
// caller has set the driver name without selecting a driver.
//
if( !bIsDriverSelected( ) && xbUpdateDriver == kDefault )
{
//
// If a driver name was set then select a driver using this name.
//
BOOL bSelectFromName = _strDriverName.bEmpty() ? FALSE : TRUE;
//
// Select the driver.
//
bStatus DBGCHK = bSelectDriver( bSelectFromName );
//
// In the case the caller just wants to use the inf if one exists
// if an inf does not exist for this driver then prompt them. If
// the caller wants to prompt the user if an inf does not exist they
// should set the bIgnoreSelectDriverFailure to true.
//
if (bStatus == FALSE && xbIgnoreSelectDriverFailure == TRUE)
{
bStatus DBGCHK = TRUE;
bUseDriverName = TRUE;
}
}
if( bStatus )
{
//
// Get the driver architecture name.
//
TString strDrvArchName;
bStatus DBGCHK = bGetArchName(dwDriverVersion, strDrvArchName );
DBGMSG( DBG_TRACE, ( "Driver Architecture and version " TSTR "\n", static_cast<LPCTSTR>( strDrvArchName ) ) );
if( bStatus )
{
LPCTSTR pszSourcePath = _strSourcePath.bEmpty() ? NULL : (LPCTSTR)_strSourcePath;
if( bInstallFromWeb )
{
//
// Install the specified printer driver.
//
Status DBGCHK = _PSetup.PSetupInstallPrinterDriverFromTheWeb( _hSetupDrvSetupParams,
_hSelectedDrvInfo,
GetDriverPlatform( dwDriverVersion ),
_pszServerName,
pGetOsVersionInfo(),
hwnd,
pszSourcePath );
}
else
{
HANDLE hDriverInfo = _hSelectedDrvInfo;
LPCTSTR pszDriverName = _strDriverName;
//
// If we are not updating the driver then clear the driver name.
//
if( xbUpdateDriver == kDefault && bUseDriverName == FALSE )
{
pszDriverName = NULL;
}
else
{
hDriverInfo = NULL;
}
//
// Install the specified printer driver.
//
Status DBGCHK = _PSetup.PSetupInstallPrinterDriver( _hSetupDrvSetupParams,
hDriverInfo,
pszDriverName,
GetDriverPlatform( dwDriverVersion ),
GetDriverVersion( dwDriverVersion ),
_pszServerName,
hwnd,
strDrvArchName,
pszSourcePath,
_dwInstallFlags,
dwAddDrvFlags,
pstrNewDriverName,
bOfferReplacement );
}
//
// Set up the correct return value.
//
bStatus DBGNOCHK = Status == ERROR_SUCCESS ? TRUE : FALSE;
if( !bStatus )
{
SetLastError( Status );
}
}
}
return bStatus;
}
VOID
TPrinterDriverInstallation::
vPrinterAdded(
IN const TString &strFullPrinterName
)
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::vPrinterAdded\n" ) );
DBGMSG( DBG_TRACE, ( "strFullPrinterName " TSTR "\n", static_cast<LPCTSTR>( strFullPrinterName ) ) );
TStatusB bStatus;
bStatus DBGCHK = bIsDriverSelected( );
if( bStatus )
{
_PSetup.PSetupProcessPrinterAdded( _hSetupDrvSetupParams,
_hSelectedDrvInfo,
strFullPrinterName,
_hwnd );
}
}
BOOL
TPrinterDriverInstallation::
bGetDriverSetupPage(
IN OUT HPROPSHEETPAGE *pPage,
IN LPCTSTR pszTitle,
IN LPCTSTR pszSubTitle,
IN LPCTSTR pszInstrn
)
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::bGetDriverSetupPage\n" ) );
SPLASSERT( bValid() );
//
// Set the title and instructions if provided. Note that this function may fail
//
TStatusB bStatus;
bStatus DBGCHK = bSetDriverSetupPageTitle(pszTitle, pszSubTitle, pszInstrn);
if( bStatus )
{
//
// Get the select device page handle.
//
*pPage = _PSetup.PSetupCreateDrvSetupPage(_hSetupDrvSetupParams, _hwnd);
bStatus DBGCHK = ((*pPage) ? TRUE : FALSE);
}
return bStatus;
}
BOOL
TPrinterDriverInstallation::
bSetWebMode(
IN BOOL bWebButtonOn
)
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::bSetWebMode\n" ) );
SPLASSERT( bValid() );
//
// Set the web button state i.e. enabled|disbled, on the model manufacture dialog.
//
return _PSetup.PSetupSetWebMode( _hSetupDrvSetupParams, bWebButtonOn );
}
BOOL
TPrinterDriverInstallation::
bShowOem(
IN BOOL bShowOem
)
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::bShowOem\n" ) );
SPLASSERT( bValid() );
//
// Enable or Disable the have disk button.
//
return _PSetup.PSetupShowOem( _hSetupDrvSetupParams, bShowOem );
}
BOOL
TPrinterDriverInstallation::
bSetDriverSetupPageTitle(
IN LPCTSTR pszTitle,
IN LPCTSTR pszSubTitle,
IN LPCTSTR pszInstrn
)
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::bSetDriverSetupPageTitle\n" ) );
SPLASSERT( bValid() );
BOOL bReturn = FALSE;
//
// Set the title and instructions if provided.
//
if( ( pszTitle && *pszTitle ) || ( pszInstrn && *pszInstrn ) || ( pszSubTitle && *pszSubTitle ) )
{
bReturn = _PSetup.PSetupSetSelectDevTitleAndInstructions( _hSetupDrvSetupParams, pszTitle, pszSubTitle, pszInstrn );
}
return bReturn;
}
BOOL
TPrinterDriverInstallation::
bGetSelectedDriver(
const BOOL bForceReselection
)
{
SPLASSERT( bValid() );
TStatusB bStatus;
BOOL bSelectFromName = FALSE;
if( bForceReselection )
{
//
// Release the selected driver
//
vReleaseSelectedDriver();
//
// Set the reselect flag.
//
bSelectFromName = _strDriverName.bEmpty() ? FALSE : TRUE;
}
//
// Select the driver.
//
bStatus DBGCHK = bSelectDriver( bSelectFromName );
bStatus DBGCHK = bIsDriverSelected( );
if( bStatus )
{
if( !bSelectFromName )
{
//
// Update the selected driver name.
//
bStatus DBGCHK = _PSetup.bGetSelectedDriverName( _hSelectedDrvInfo,
_strDriverName,
GetDriverPlatform( _dwDriverVersion ) );
}
}
return bStatus;
}
BOOL
TPrinterDriverInstallation::
bSelectDriverFromInf(
IN LPCTSTR pszInfName,
IN BOOL bIsSingleInf
)
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::bInstallDriverFromInf\n" ) );
SPLASSERT( bValid() );
TStatusB bStatus;
bStatus DBGNOCHK = TRUE;
if( bStatus )
{
bStatus DBGCHK = _PSetup.PSetupBuildDriversFromPath( _hSetupDrvSetupParams, pszInfName, bIsSingleInf );
}
if( bStatus )
{
bStatus DBGCHK = _PSetup.PSetupPreSelectDriver( _hSetupDrvSetupParams, NULL, _strDriverName );
}
return bStatus;
}
//
// Return:
// TRUE CodeDownload is available, FALSE CodeDownload not available.
//
BOOL
TPrinterDriverInstallation::
bIsCodeDownLoadAvailable(
VOID
)
{
TLibrary Lib( gszCodeDownLoadDllName );
if( VALID_OBJ( Lib ) )
{
pfDownloadIsInternetAvailable pDownloadAvailable = NULL;
pDownloadAvailable = reinterpret_cast<pfDownloadIsInternetAvailable>( Lib.pfnGetProc( "DownloadIsInternetAvailable" ) );
if( pDownloadAvailable )
{
return pDownloadAvailable();
}
}
return FALSE;
}
//
// Return the selected print processor name.
//
BOOL
TPrinterDriverInstallation::
bGetPrintProcessor(
IN TString &strPrintProcessor
) const
{
TStatusB bStatus;
bStatus DBGCHK = bIsDriverSelected( );
if( bStatus )
{
bStatus DBGCHK = _PSetup.bGetSelectedPrintProcessorName( _hSelectedDrvInfo, strPrintProcessor, GetDriverPlatform( _dwDriverVersion ) );
}
return bStatus;
}
//
// Return the selected inf file name.
//
BOOL
TPrinterDriverInstallation::
bGetSelectedInfName(
IN TString &strInfName
) const
{
TStatusB bStatus;
bStatus DBGCHK = bIsDriverSelected( );
if( bStatus )
{
bStatus DBGCHK = _PSetup.bGetSelectedInfName( _hSelectedDrvInfo, strInfName, GetDriverPlatform( _dwDriverVersion ) );
}
return bStatus;
}
//
// Return if the currently selected driver is an oem driver.
//
BOOL
TPrinterDriverInstallation::
bIsOemDriver(
VOID
) const
{
TStatusB bStatus;
bStatus DBGCHK = bIsDriverSelected( );
BOOL bIsOemDriver = FALSE;
if( bStatus )
{
(VOID)_PSetup.PSetupIsOemDriver( _hSetupDrvSetupParams, _hSelectedDrvInfo, &bIsOemDriver );
}
return (bStatus && bIsOemDriver);
}
//
// Return the current driver encoding. This is useful because
// getting the current driver encode is very expensive accross
// a remote connetion, and this class only fetches the
// version once per instantiation.
//
BOOL
TPrinterDriverInstallation::
bGetCurrentDriverEncode(
IN DWORD *pdwEncode
) const
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::bGetCurrentDriverEncode\n" ) );
SPLASSERT( bValid() );
//
// The driver version should be initialized at this point.
//
SPLASSERT( _dwDriverVersion != (DWORD)kDefault );
*pdwEncode = _dwDriverVersion;
return TRUE;
}
//
// Return the current driver version. This is useful because
// getting the current driver encode is very expensive accross
// a remote connetion. This class only fetches the
// version once per instantiation.
//
DWORD
TPrinterDriverInstallation::
dwGetCurrentDriverVersion(
) const
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::bGetCurrentDriverVersion\n" ) );
SPLASSERT( bValid() );
//
// The driver version should be initialized at this point.
//
SPLASSERT( _dwDriverVersion != (DWORD)kDefault );
return GetDriverVersion( _dwDriverVersion );
}
//
// Restores the driver list to the default driver list.
//
BOOL
TPrinterDriverInstallation::
bRefreshDriverList(
VOID
)
{
return _PSetup.PSetupRefreshDriverList( _hSetupDrvSetupParams );
}
//
// Expose the original hwnd, user of the class need this
// to ensure they are using the same hwnd when displaying messages.
//
HWND
TPrinterDriverInstallation::
hGetHwnd(
VOID
) const
{
return _hwnd;
}
/********************************************************************
Private member functions.
********************************************************************/
BOOL
TPrinterDriverInstallation::
bValidateSourcePath(
IN LPCTSTR pszSourcePath
) const
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::bValidateSourcePath\n" ) );
SPLASSERT( bValid() );
TStatusB bStatus;
if( GetFileAttributes( pszSourcePath ) & FILE_ATTRIBUTE_DIRECTORY )
{
bStatus DBGNOCHK = TRUE;
}
else
{
SetLastError( ERROR_DIRECTORY );
bStatus DBGNOCHK = FALSE;
}
return bStatus;
}
BOOL
TPrinterDriverInstallation::
bIsDriverSelected(
VOID
) const
{
SPLASSERT( bValid() );
return _hSelectedDrvInfo != INVALID_HANDLE_VALUE;
}
BOOL
TPrinterDriverInstallation::
bSelectDriver(
IN BOOL bFromName
)
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::bGetSelectedDriverInfo\n" ) );
SPLASSERT( bValid() );
vReleaseSelectedDriver();
if( bFromName )
{
_hSelectedDrvInfo = _PSetup.PSetupDriverInfoFromName( _hSetupDrvSetupParams, _strDriverName );
}
else
{
_hSelectedDrvInfo = _PSetup.PSetupGetSelectedDriverInfo( _hSetupDrvSetupParams );
}
BOOL bRetval;
TStatusB bStatus;
bStatus DBGCHK = bIsDriverSelected( );
if( !bStatus )
{
DBGMSG( DBG_TRACE, ( "PSetupGetSelectedDriverInfo failed with %d\n", GetLastError() ) );
bRetval = FALSE;
}
else
{
bRetval = TRUE;
}
return bRetval;
}
VOID
TPrinterDriverInstallation::
vReleaseSelectedDriver(
VOID
)
{
//
// Release the selected driver information.
//
if( _hSelectedDrvInfo != INVALID_HANDLE_VALUE )
{
DBGMSG( DBG_TRACE, ( "TPrinterDriverInstallation::vReleaseSelectedDriverInfo\n" ) );
_PSetup.PSetupDestroySelectedDriverInfo( _hSelectedDrvInfo );
_hSelectedDrvInfo = INVALID_HANDLE_VALUE;
}
}
//
// Return the os version info structure.
//
OSVERSIONINFO *
TPrinterDriverInstallation::
pGetOsVersionInfo(
VOID
)
{
//
// If the os version was not iniaitlized.
//
if( !_OsVersionInfo.dwOSVersionInfoSize )
{
//
// Set the osversion info structure size.
//
_OsVersionInfo.dwOSVersionInfoSize = sizeof( _OsVersionInfo );
//
// Get the osversion info structure size
//
if( !SpoolerGetVersionEx( _pszServerName, &_OsVersionInfo ) )
{
//
// Indicate a failure occured.
//
_OsVersionInfo.dwOSVersionInfoSize = 0;
}
}
if( _OsVersionInfo.dwOSVersionInfoSize )
{
DBGMSG( DBG_TRACE, ("_OsVersionInfo.dwOSVersionInfoSize %d\n", _OsVersionInfo.dwOSVersionInfoSize ) );
DBGMSG( DBG_TRACE, ("_OsVersionInfo.dwMajorVersion %d\n", _OsVersionInfo.dwMajorVersion ) );
DBGMSG( DBG_TRACE, ("_OsVersionInfo.dwMinorVersion %d\n", _OsVersionInfo.dwMinorVersion ) );
DBGMSG( DBG_TRACE, ("_OsVersionInfo.dwBuildNumber %d\n", _OsVersionInfo.dwBuildNumber ) );
DBGMSG( DBG_TRACE, ("_OsVersionInfo.dwPlatformId %d\n", _OsVersionInfo.dwPlatformId ) );
DBGMSG( DBG_TRACE, ("_OsVersionInfo.szCSDVersion "TSTR"\n", _OsVersionInfo.szCSDVersion ) );
}
return &_OsVersionInfo;
}