1024 lines
24 KiB
C
1024 lines
24 KiB
C
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
Utildi.c
|
|
|
|
Abstract:
|
|
|
|
Driver Setup DeviceInstaller Utility functions
|
|
|
|
Author:
|
|
|
|
Muhunthan Sivapragasam (MuhuntS) 06-Sep-1995
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <devguid.h>
|
|
|
|
|
|
TCHAR cszOEMInfGen[] = TEXT("%s\\inf\\OEM%d.INF");
|
|
|
|
|
|
BOOL
|
|
SetSelectDevParams(
|
|
IN HDEVINFO hDevInfo,
|
|
IN BOOL bWin95,
|
|
IN LPCTSTR pszModel OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Sets the select device parameters by calling setup apis
|
|
|
|
Arguments:
|
|
hDevInfo : Handle to the printer class device information list
|
|
bWin95 : TRUE if selecting Win95 driver, else WinNT driver
|
|
pszModel : Printer model we are looking for -- only for Win95 case
|
|
|
|
Return Value:
|
|
TRUE on success
|
|
FALSE else
|
|
|
|
--*/
|
|
{
|
|
SP_SELECTDEVICE_PARAMS SelectDevParams;
|
|
LPTSTR pszWin95Instn;
|
|
|
|
SelectDevParams.ClassInstallHeader.cbSize
|
|
= sizeof(SelectDevParams.ClassInstallHeader);
|
|
SelectDevParams.ClassInstallHeader.InstallFunction
|
|
= DIF_SELECTDEVICE;
|
|
|
|
//
|
|
// Get current SelectDevice parameters, and then set the fields
|
|
// we want to be different from default
|
|
//
|
|
if ( !SetupDiGetClassInstallParams(
|
|
hDevInfo,
|
|
NULL,
|
|
&SelectDevParams.ClassInstallHeader,
|
|
sizeof(SelectDevParams),
|
|
NULL) ) {
|
|
|
|
if ( GetLastError() != ERROR_NO_CLASSINSTALL_PARAMS )
|
|
return FALSE;
|
|
|
|
ZeroMemory(&SelectDevParams, sizeof(SelectDevParams));
|
|
SelectDevParams.ClassInstallHeader.cbSize
|
|
= sizeof(SelectDevParams.ClassInstallHeader);
|
|
SelectDevParams.ClassInstallHeader.InstallFunction
|
|
= DIF_SELECTDEVICE;
|
|
}
|
|
|
|
//
|
|
// Set the strings to use on the select driver page ..
|
|
//
|
|
LoadString(ghInst,
|
|
IDS_PRINTERWIZARD,
|
|
SelectDevParams.Title,
|
|
sizeof(SelectDevParams.Title)/sizeof(SelectDevParams.Title[0]));
|
|
|
|
//
|
|
// For Win95 drivers instructions are different than NT drivers
|
|
//
|
|
if ( bWin95 ) {
|
|
|
|
pszWin95Instn = GetStringFromRcFile(IDS_WIN95DEV_INSTRUCT);
|
|
if ( !pszWin95Instn )
|
|
return FALSE;
|
|
|
|
if ( lstrlen(pszWin95Instn) + lstrlen(pszModel) + 1
|
|
> sizeof(SelectDevParams.Instructions) ) {
|
|
|
|
FreeStr(pszWin95Instn);
|
|
return FALSE;
|
|
}
|
|
|
|
wsprintf(SelectDevParams.Instructions, pszWin95Instn, pszModel);
|
|
FreeStr(pszWin95Instn);
|
|
} else {
|
|
|
|
LoadString(ghInst,
|
|
IDS_WINNTDEV_INSTRUCT,
|
|
SelectDevParams.Instructions,
|
|
sizeof(SelectDevParams.Instructions)/sizeof(SelectDevParams.Instructions[0]));
|
|
}
|
|
|
|
LoadString(ghInst,
|
|
IDS_SELECTDEV_LABEL,
|
|
SelectDevParams.ListLabel,
|
|
sizeof(SelectDevParams.ListLabel)/sizeof(SelectDevParams.ListLabel[0]));
|
|
|
|
return SetupDiSetClassInstallParams(
|
|
hDevInfo,
|
|
NULL,
|
|
&SelectDevParams.ClassInstallHeader,
|
|
sizeof(SelectDevParams));
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
SetDevInstallParams(
|
|
IN HDEVINFO hDevInfo,
|
|
IN HWND hwnd,
|
|
IN LPCTSTR pszDriverPath OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Sets the device installation parameters by calling setup apis
|
|
|
|
Arguments:
|
|
hDevInfo : Handle to the printer class device information list
|
|
hwnd : Window handle that owns the UI
|
|
pszDriverPath : Path where INF file should be searched
|
|
|
|
Return Value:
|
|
TRUE on success
|
|
FALSE else
|
|
|
|
--*/
|
|
{
|
|
SP_DEVINSTALL_PARAMS DevInstallParams;
|
|
|
|
//
|
|
// Get current SelectDevice parameters, and then set the fields
|
|
// we wanted changed from default
|
|
//
|
|
DevInstallParams.cbSize = sizeof(DevInstallParams);
|
|
if ( !SetupDiGetDeviceInstallParams(hDevInfo,
|
|
NULL,
|
|
&DevInstallParams) ) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Drivers are class drivers,
|
|
// ntprint.inf is sorted do not waste time sorting,
|
|
// show Have Disk button,
|
|
// use our strings on the select driver page
|
|
//
|
|
DevInstallParams.Flags |= DI_SHOWCLASS | DI_INF_IS_SORTED
|
|
| DI_SHOWOEM
|
|
| DI_USECI_SELECTSTRINGS;
|
|
|
|
if ( pszDriverPath && *pszDriverPath ) {
|
|
|
|
lstrcpy(DevInstallParams.DriverPath, pszDriverPath);
|
|
}
|
|
|
|
DevInstallParams.hwndParent = hwnd;
|
|
|
|
return SetupDiSetDeviceInstallParams(hDevInfo,
|
|
NULL,
|
|
&DevInstallParams);
|
|
}
|
|
|
|
|
|
BOOL
|
|
PSetupBuildDriversFromPath(
|
|
IN HANDLE h,
|
|
IN LPCTSTR pszDriverPath,
|
|
IN BOOL bEnumSingleInf
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Sets the device installation path (INF and driver dir) by calling setup apis
|
|
|
|
Arguments:
|
|
h : Handle from PSetupCreateDrvSetupParams
|
|
pszDriverPath : Path where INF file should be searched
|
|
bEnumSingleInf : Tells if pszDriverPath is a filename instead of path
|
|
|
|
Return Value:
|
|
TRUE on success
|
|
FALSE else
|
|
|
|
--*/
|
|
{
|
|
HDEVINFO hDevInfo = (HDEVINFO)h;
|
|
SP_DEVINSTALL_PARAMS DevInstallParams;
|
|
|
|
//
|
|
// Get current SelectDevice parameters, and then set the fields
|
|
// we wanted changed from default
|
|
//
|
|
DevInstallParams.cbSize = sizeof(DevInstallParams);
|
|
if ( !SetupDiGetDeviceInstallParams(hDevInfo,
|
|
NULL,
|
|
&DevInstallParams) ) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
DevInstallParams.Flags |= DI_INF_IS_SORTED;
|
|
|
|
if ( bEnumSingleInf )
|
|
DevInstallParams.Flags |= DI_ENUMSINGLEINF;
|
|
|
|
lstrcpy(DevInstallParams.DriverPath, pszDriverPath);
|
|
|
|
SetupDiDestroyDriverInfoList(hDevInfo,
|
|
NULL,
|
|
SPDIT_CLASSDRIVER);
|
|
|
|
return SetupDiSetDeviceInstallParams(hDevInfo,
|
|
NULL,
|
|
&DevInstallParams) &&
|
|
SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
|
|
}
|
|
|
|
|
|
VOID
|
|
PSetupDestroyDrvSetupParams(
|
|
IN HANDLE h
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This routine should be called at the end to destroy the driver setup
|
|
information
|
|
|
|
Arguments:
|
|
h : Handle which was created by calling PSetupCreateDrvSetupParams
|
|
|
|
Return Value:
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
|
|
if ( h ) {
|
|
|
|
SetupDiDestroyDeviceInfoList((HDEVINFO) h);
|
|
}
|
|
}
|
|
|
|
|
|
HDEVINFO
|
|
CreatePrinterDevInfo(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Creates a printer HDEVINFO by calling setup apis/
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Value:
|
|
Valid HDEVINFO on success, NULL on error
|
|
|
|
--*/
|
|
{
|
|
HDEVINFO hDevInfo;
|
|
|
|
hDevInfo = SetupDiCreateDeviceInfoList((LPGUID)&GUID_DEVCLASS_PRINTER, NULL);
|
|
|
|
return hDevInfo != INVALID_HANDLE_VALUE ? hDevInfo : NULL;
|
|
}
|
|
|
|
|
|
HANDLE
|
|
PSetupCreateDrvSetupParams(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This routine should be called at the beginning to do the initialization
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Value:
|
|
A handle which will be used on any subsequent calls to the driver setup
|
|
routines. Handle will be NULL on error
|
|
|
|
--*/
|
|
{
|
|
HDEVINFO hDevInfo;
|
|
|
|
hDevInfo = CreatePrinterDevInfo();
|
|
if ( !hDevInfo )
|
|
return NULL;
|
|
|
|
if ( !SetSelectDevParams(hDevInfo, FALSE, NULL) ) {
|
|
|
|
PSetupDestroyDrvSetupParams(hDevInfo);
|
|
return NULL;
|
|
}
|
|
|
|
return (HANDLE) hDevInfo;
|
|
}
|
|
|
|
|
|
HPROPSHEETPAGE
|
|
PSetupCreateDrvSetupPage(
|
|
IN HANDLE h,
|
|
IN HWND hwnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Returns the print driver selection property page
|
|
|
|
Arguments:
|
|
h : Handle from PSetupCreateDrvSetupParams
|
|
hwnd : Window handle that owns the UI
|
|
pszManufacturer : Manufacturer to preselect
|
|
pszModel : Model to preselect
|
|
|
|
Return Value:
|
|
Handle to the property page, NULL on failure -- use GetLastError()
|
|
|
|
--*/
|
|
{
|
|
HDEVINFO hDevInfo = (HDEVINFO) h;
|
|
SP_INSTALLWIZARD_DATA InstallWizardData;
|
|
|
|
if ( !SetDevInstallParams(hDevInfo, hwnd, NULL) ) {
|
|
|
|
return NULL;
|
|
}
|
|
|
|
ZeroMemory(&InstallWizardData, sizeof(InstallWizardData));
|
|
InstallWizardData.ClassInstallHeader.cbSize
|
|
= sizeof(InstallWizardData.ClassInstallHeader);
|
|
InstallWizardData.ClassInstallHeader.InstallFunction
|
|
= DIF_INSTALLWIZARD;
|
|
|
|
InstallWizardData.DynamicPageFlags = DYNAWIZ_FLAG_PAGESADDED;
|
|
InstallWizardData.hwndWizardDlg = hwnd;
|
|
|
|
return SetupDiGetWizardPage(hDevInfo,
|
|
NULL,
|
|
&InstallWizardData,
|
|
SPWPT_SELECTDEVICE,
|
|
0);
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
PSetupDestroySelectedDriverInfo(
|
|
IN PSELECTED_DRV_INFO pSelectedDrvInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Frees all memory allocated for the SELECTED_DRV_INFO structure and the
|
|
fields in it
|
|
|
|
Arguments:
|
|
pSelectedDrvInfo : Pointer to the structure to destory information
|
|
|
|
Return Value:
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
if ( pSelectedDrvInfo ) {
|
|
|
|
FreeStr(pSelectedDrvInfo->pszModelName);
|
|
FreeStr(pSelectedDrvInfo->pszDriverSection);
|
|
FreeStr(pSelectedDrvInfo->pszInfFile);
|
|
FreeMem(pSelectedDrvInfo);
|
|
}
|
|
}
|
|
|
|
|
|
PSELECTED_DRV_INFO
|
|
SelectedDriverInfoFromDrvInfo(
|
|
IN HDEVINFO hDevInfo,
|
|
IN PSP_DRVINFO_DATA pDrvInfoData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Gets the INF file, driver section name for a give driver info and builds
|
|
a SELECTED_DRV_INFO
|
|
|
|
Arguments:
|
|
hDevInfo - Handle to the printer class device information list
|
|
pDrvInfoData - Points to a SP_DRVINFO_DATA giving the driver model
|
|
to retrive information
|
|
|
|
Return Value:
|
|
On success -- A non null pointer value to SELECTED_DRV_INFO
|
|
On failure -- NULL, GetLastError to get error code
|
|
|
|
--*/
|
|
{
|
|
PSP_DRVINFO_DETAIL_DATA pDrvInfoDetailData;
|
|
PSELECTED_DRV_INFO pSelectedDrvInfo;
|
|
BOOL bRet = FALSE;
|
|
DWORD dwNeeded;
|
|
|
|
pSelectedDrvInfo = (PSELECTED_DRV_INFO)
|
|
AllocMem(sizeof(*pSelectedDrvInfo));
|
|
pDrvInfoDetailData = (PSP_DRVINFO_DETAIL_DATA)
|
|
AllocMem(sizeof(*pDrvInfoDetailData));
|
|
|
|
if ( !pSelectedDrvInfo || !pDrvInfoDetailData )
|
|
goto Cleanup;
|
|
|
|
ZeroMemory(pSelectedDrvInfo, sizeof(*pSelectedDrvInfo));
|
|
pDrvInfoDetailData->cbSize = sizeof(*pDrvInfoDetailData);
|
|
|
|
if ( !SetupDiGetDriverInfoDetail(hDevInfo,
|
|
NULL,
|
|
pDrvInfoData,
|
|
pDrvInfoDetailData,
|
|
sizeof(*pDrvInfoDetailData),
|
|
&dwNeeded) ) {
|
|
|
|
if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
FreeMem(pDrvInfoDetailData);
|
|
pDrvInfoDetailData = (PSP_DRVINFO_DETAIL_DATA) AllocMem(dwNeeded);
|
|
|
|
if ( !pDrvInfoDetailData )
|
|
goto Cleanup;
|
|
|
|
pDrvInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
|
|
|
|
if ( !SetupDiGetDriverInfoDetail(hDevInfo,
|
|
NULL,
|
|
pDrvInfoData,
|
|
pDrvInfoDetailData,
|
|
dwNeeded,
|
|
&dwNeeded) ) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get modelname, driversection, and inffile
|
|
//
|
|
pSelectedDrvInfo->pszModelName = AllocStr(pDrvInfoData->Description);
|
|
pSelectedDrvInfo->pszDriverSection = AllocStr(pDrvInfoDetailData->SectionName);
|
|
pSelectedDrvInfo->pszInfFile = AllocStr(pDrvInfoDetailData->InfFileName);
|
|
|
|
if ( pSelectedDrvInfo->pszModelName &&
|
|
pSelectedDrvInfo->pszDriverSection &&
|
|
pSelectedDrvInfo->pszInfFile ) {
|
|
|
|
bRet = TRUE;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if ( pDrvInfoDetailData ) {
|
|
|
|
FreeMem(pDrvInfoDetailData);
|
|
}
|
|
|
|
if ( !bRet ) {
|
|
|
|
PSetupDestroySelectedDriverInfo(pSelectedDrvInfo);
|
|
return NULL;
|
|
}
|
|
|
|
return pSelectedDrvInfo;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CopyOEMInfFileAndGiveUniqueName(
|
|
IN HANDLE h,
|
|
IN LPTSTR pszInfFile
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks if an OEM driver list is being used and if so
|
|
copies the OEM printer inf file to "<systemroot>\Inf\OEM<n>.INF".
|
|
Where n is the first unused file number.
|
|
|
|
Arguments:
|
|
|
|
h : Handle got by calling PSetupCreateDrvSetupParams
|
|
pszInfFile : Fully qualified path of OEM inf file
|
|
|
|
Return Value:
|
|
TRUE if no error, FALSE else
|
|
|
|
--*/
|
|
{
|
|
SP_DEVINSTALL_PARAMS DevInstallParams;
|
|
HANDLE hFile;
|
|
TCHAR szNewFileName[MAX_PATH], szSystemDir[MAX_PATH];
|
|
DWORD i;
|
|
|
|
DevInstallParams.cbSize = sizeof(DevInstallParams);
|
|
DevInstallParams.DriverPath[0] = 0;
|
|
|
|
//
|
|
// Check DeviceInstallParams to see if OEM driver list is built
|
|
//
|
|
if ( !SetupDiGetDeviceInstallParams((HDEVINFO)h,
|
|
NULL,
|
|
&DevInstallParams) ) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If DriverPath is clear then not an OEM driver
|
|
if ( !DevInstallParams.DriverPath[0] ) {
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
if ( !GetWindowsDirectory(szSystemDir,
|
|
sizeof(szSystemDir)/sizeof(szSystemDir[0])) ) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if ( lstrlen(szSystemDir) + lstrlen(cszOEMInfGen) + 5
|
|
> sizeof(szNewFileName)/sizeof(szNewFileName[0]) ) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
for ( i = 0 ; i < 10000 ; ++i ) {
|
|
|
|
wsprintf(szNewFileName, cszOEMInfGen, szSystemDir, i);
|
|
|
|
//
|
|
// By using the CREATE_NEW flag we reserve the file name and
|
|
// will not end up overwriting another file which gets created
|
|
// by another setup (some inf) thread
|
|
//
|
|
h = CreateFile(szNewFileName,
|
|
0,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
CREATE_NEW,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if ( h != INVALID_HANDLE_VALUE ) {
|
|
|
|
CloseHandle(h);
|
|
return CopyFile(pszInfFile,
|
|
szNewFileName,
|
|
FALSE);
|
|
} else if ( GetLastError() != ERROR_FILE_EXISTS ) {
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
PSELECTED_DRV_INFO
|
|
GetSelectedDriverInfo(
|
|
IN HDEVINFO hDevInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Gets the selected diver information by calling the setupapi routines
|
|
|
|
Arguments:
|
|
hDevInfo - Handle to the printer class device information list
|
|
|
|
Return Value:
|
|
On success -- A non null pointer value to SELECTED_DRV_INFO
|
|
On failure -- NULL, GetLastError to get error code
|
|
|
|
--*/
|
|
{
|
|
SP_DRVINFO_DATA DrvInfoData;
|
|
|
|
|
|
DrvInfoData.cbSize = sizeof(DrvInfoData);
|
|
|
|
if ( SetupDiGetSelectedDriver(hDevInfo, NULL, &DrvInfoData) ) {
|
|
|
|
|
|
return SelectedDriverInfoFromDrvInfo(hDevInfo, &DrvInfoData);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
PSELECTED_DRV_INFO
|
|
PSetupGetSelectedDriverInfo(
|
|
IN HANDLE h
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Gets the selected diver information by calling the setupapi routines
|
|
|
|
Arguments:
|
|
h : Handle got by calling PSetupCreateDrvSetupParams
|
|
|
|
Return Value:
|
|
On success -- A non null pointer value to SELECTED_DRV_INFO
|
|
On failure -- NULL, GetLastError to get error code
|
|
|
|
--*/
|
|
{
|
|
return GetSelectedDriverInfo((HDEVINFO)h);
|
|
}
|
|
|
|
|
|
BOOL
|
|
SelectDriver(
|
|
IN HDEVINFO hDevInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Display manufacturer/model information and have the user select a
|
|
printer driver. GetSelectedDriver will give the selected driver.
|
|
|
|
Arguments:
|
|
hDevInfo - Handle to the printer class device information list
|
|
|
|
Return Value:
|
|
TRUE on success, FALSE on error
|
|
|
|
--*/
|
|
{
|
|
|
|
return SetupDiSelectDevice(hDevInfo, NULL);
|
|
}
|
|
|
|
|
|
BOOL
|
|
PSetupSelectDriver(
|
|
IN HANDLE h,
|
|
IN HWND hwnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Display manufacturer/model information and have the user select a
|
|
printer driver. Use PSetupGetSelectedDriverInfo
|
|
|
|
Arguments:
|
|
h : Handle got by call to PSetupCreateDrvSetupParams
|
|
hwnd : Window handle
|
|
|
|
Return Value:
|
|
TRUE on success, FALSE on error
|
|
|
|
--*/
|
|
{
|
|
HDEVINFO hDevInfo = (HDEVINFO)h;
|
|
|
|
return SetDevInstallParams(hDevInfo,
|
|
hwnd,
|
|
NULL) &&
|
|
SelectDriver(hDevInfo);
|
|
}
|
|
|
|
|
|
VOID
|
|
GetDriverPath(
|
|
IN HANDLE h,
|
|
OUT LPTSTR pszDriverPath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Gets the path where driver files should be searched first to copy from
|
|
|
|
Arguments:
|
|
h : Handle got from call to PSetupCreateDrvSetupParams
|
|
pszDriverPath : buffer to copy the driver path to
|
|
|
|
Return Value:
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
LPTSTR *List;
|
|
DWORD dwCount;
|
|
SP_DEVINSTALL_PARAMS DevInstallParams;
|
|
|
|
//
|
|
// If we have hDevInfo for printer check if DeviceInstallParams have
|
|
// been set
|
|
//
|
|
DevInstallParams.cbSize = sizeof(DevInstallParams);
|
|
DevInstallParams.DriverPath[0] = 0;
|
|
|
|
//
|
|
// First call DeviceInstaller API to findout if we should be looking
|
|
// in a specific place for drivers (ex. HaveDisk case)
|
|
// Second try to get from mru
|
|
//
|
|
//
|
|
if ( SetupDiGetDeviceInstallParams((HDEVINFO)h,
|
|
NULL,
|
|
&DevInstallParams) &&
|
|
DevInstallParams.DriverPath[0] ) {
|
|
|
|
lstrcpy(pszDriverPath, DevInstallParams.DriverPath);
|
|
return;
|
|
}
|
|
|
|
if ( SetupQuerySourceList(SRCLIST_USER | SRCLIST_SYSTEM,
|
|
&List, &dwCount) ) {
|
|
|
|
lstrcpy(pszDriverPath, List[0]);
|
|
SetupFreeSourceList(&List, dwCount);
|
|
} else {
|
|
|
|
//
|
|
// Default put A:\ since we have to give something to setup
|
|
//
|
|
lstrcpy(pszDriverPath, TEXT("A:\\"));
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
BuildClassDriverList(
|
|
IN HDEVINFO hDevInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Build the class driver list.
|
|
|
|
Note: If driver list is already built this comes back immediately
|
|
|
|
Arguments:
|
|
hDevInfo : Handle to the printer class device information list
|
|
|
|
Return Value:
|
|
TRUE on success, FALSE on error
|
|
|
|
--*/
|
|
{
|
|
return SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
|
|
}
|
|
|
|
|
|
BOOL
|
|
PSetupRefreshDriverList(
|
|
IN HANDLE h
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Destroy current driver list and build new one
|
|
|
|
Arguments:
|
|
h : Handle got by calling PSetupCreateDrvSetupParams
|
|
|
|
Return Value:
|
|
TRUE on success, FALSE on error
|
|
|
|
--*/
|
|
{
|
|
HDEVINFO hDevInfo = (HDEVINFO) h;
|
|
SP_DEVINSTALL_PARAMS DevInstallParams;
|
|
|
|
DevInstallParams.cbSize = sizeof(DevInstallParams);
|
|
DevInstallParams.DriverPath[0] = 0;
|
|
|
|
//
|
|
// Check DeviceInstallParams to see if OEM driver list is built
|
|
//
|
|
if ( SetupDiGetDeviceInstallParams(hDevInfo,
|
|
NULL,
|
|
&DevInstallParams) &&
|
|
!DevInstallParams.DriverPath[0] ) {
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Destroy current list and build another one
|
|
//
|
|
SetupDiDestroyDriverInfoList(hDevInfo,
|
|
NULL,
|
|
SPDIT_CLASSDRIVER);
|
|
|
|
DevInstallParams.DriverPath[0] = sZero;
|
|
|
|
return SetupDiSetDeviceInstallParams(hDevInfo,
|
|
NULL,
|
|
&DevInstallParams) &&
|
|
|
|
BuildClassDriverList(hDevInfo);
|
|
}
|
|
|
|
|
|
PSELECTED_DRV_INFO
|
|
DriverInfoFromName(
|
|
IN HDEVINFO hDevInfo,
|
|
IN LPCTSTR pszModel
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Given a printer driver model name get the SELECTED_DRV_INFO for it
|
|
for a given device info set
|
|
|
|
Arguments:
|
|
hDeVInfo : Handle to the device information set
|
|
pszModel : Driver model name
|
|
|
|
Return Value:
|
|
Valid pointer to a SELECTED_DRV_INFO on success, NULL on error
|
|
|
|
--*/
|
|
{
|
|
SP_DRVINFO_DATA DrvInfoData;
|
|
DWORD dwIndex;
|
|
|
|
dwIndex = 0;
|
|
DrvInfoData.cbSize = sizeof(DrvInfoData);
|
|
|
|
while ( SetupDiEnumDriverInfo(hDevInfo, NULL, SPDIT_CLASSDRIVER,
|
|
dwIndex, &DrvInfoData) ) {
|
|
|
|
if ( !lstrcmp(pszModel, DrvInfoData.Description) ) {
|
|
|
|
return SelectedDriverInfoFromDrvInfo(hDevInfo, &DrvInfoData);
|
|
}
|
|
|
|
DrvInfoData.cbSize = sizeof(DrvInfoData);
|
|
++dwIndex;
|
|
}
|
|
|
|
SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
PSELECTED_DRV_INFO
|
|
PSetupDriverInfoFromName(
|
|
IN HANDLE h,
|
|
IN LPCTSTR pszModel
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Given a printer driver model name get the SELECTED_DRV_INFO for it
|
|
|
|
Arguments:
|
|
h : Handle got by calling PSetupCreateDrvSetupParams
|
|
pszModel : Driver model name
|
|
|
|
Return Value:
|
|
Valid pointer to SELECTED_DRV_INFO on success (finding model in an INF)
|
|
NULL else (do GetLastError() to get the last error)
|
|
|
|
--*/
|
|
{
|
|
HDEVINFO hDevInfo = (HDEVINFO)h;
|
|
|
|
if ( BuildClassDriverList(hDevInfo) )
|
|
return DriverInfoFromName(hDevInfo, pszModel);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
|
|
BOOL
|
|
PreSelectDriver(
|
|
IN HDEVINFO hDevInfo,
|
|
IN LPCTSTR pszManufacturer,
|
|
IN LPCTSTR pszModel
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Preselect a manufacturer and model for the driver dialog
|
|
|
|
If same model is found select it, else if a match in manufacturer is
|
|
found select first driver for the manufacturer.
|
|
|
|
Arguments:
|
|
hDevInfo : Handle to printer DeviceInfoSet
|
|
pszManufacturer : Manufacterer name to preselect
|
|
pszModel : Model name to preselect
|
|
|
|
Return Value:
|
|
TRUE on a model or manufacturer match
|
|
FALSE else
|
|
|
|
--*/
|
|
{
|
|
SP_DRVINFO_DATA DrvInfoData;
|
|
DWORD dwIndex, dwManf, dwMod;
|
|
|
|
if ( !BuildClassDriverList(hDevInfo) ) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
dwIndex = 0;
|
|
|
|
//
|
|
// If no model/manf given select first driver
|
|
//
|
|
if ( pszManufacturer && *pszManufacturer && pszModel && *pszModel ) {
|
|
|
|
dwManf = dwMod = MAX_DWORD;
|
|
DrvInfoData.cbSize = sizeof(DrvInfoData);
|
|
|
|
while ( SetupDiEnumDriverInfo(hDevInfo, NULL, SPDIT_CLASSDRIVER,
|
|
dwIndex, &DrvInfoData) ) {
|
|
|
|
if ( dwManf == MAX_DWORD &&
|
|
!lstrcmp(pszManufacturer, DrvInfoData.MfgName) ) {
|
|
|
|
dwManf = dwIndex;
|
|
}
|
|
|
|
if ( !lstrcmp(pszModel, DrvInfoData.Description) ) {
|
|
|
|
dwMod = dwIndex;
|
|
break; // the for loop
|
|
}
|
|
|
|
DrvInfoData.cbSize = sizeof(DrvInfoData);
|
|
++dwIndex;
|
|
}
|
|
|
|
if ( dwMod != MAX_DWORD ) {
|
|
|
|
dwIndex = dwMod;
|
|
} else if ( dwManf != MAX_DWORD ) {
|
|
|
|
dwIndex = dwManf;
|
|
} else {
|
|
|
|
SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
DrvInfoData.cbSize = sizeof(DrvInfoData);
|
|
if ( SetupDiEnumDriverInfo(hDevInfo, NULL, SPDIT_CLASSDRIVER,
|
|
dwIndex, &DrvInfoData) &&
|
|
SetupDiSetSelectedDriver(hDevInfo, NULL, &DrvInfoData) ) {
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
PSetupPreSelectDriver(
|
|
IN HANDLE h,
|
|
IN LPCTSTR pszManufacturer,
|
|
IN LPCTSTR pszModel
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Preselect a manufacturer and model for the driver dialog
|
|
|
|
If same model is found select it, else if a match in manufacturer is
|
|
found select first driver for the manufacturer.
|
|
|
|
Arguments:
|
|
hDevInfo : Handle to printer DeviceInfoSet
|
|
pszManufacturer : Manufacterer name to preselect
|
|
pszModel : Model name to preselect
|
|
|
|
Return Value:
|
|
TRUE on a model or manufacturer match
|
|
FALSE else
|
|
|
|
--*/
|
|
{
|
|
HDEVINFO hDevInfo = (HDEVINFO)h;
|
|
|
|
return PreSelectDriver(hDevInfo, pszManufacturer, pszModel);
|
|
}
|