Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1342 lines
31 KiB

/*++
Copyright (c) 1990-1994 Microsoft Corporation
All rights reserved
Module Name:
SetupDlg.c
Abstract:
Handles the generic setup dialogs to setup drivers and monitors.
Author:
AlbertT [ported from printman]
Environment:
User Mode -Win32
Revision History:
--*/
#include "printman.h"
#include "pmdef.h"
#include <commdlg.h>
#include <stdarg.h>
#include <prsinf.h>
//
// Globals
//
INSTALLDRIVERDATA iddPrinter = {
IDS_PRINTER_INSTALL_TITLE,
IDS_PRINTER_SELECT_TITLE,
IDS_PRINTER_TYPE,
DLG_INSTALLDRIVER,
DLG_SELECTDRIVER,
TEXT("PRINTER.INF"),
TEXT("PRINTER"),
TEXT("OPTIONS"),
CB_INSERTSTRING,
CB_FINDSTRINGEXACT,
CB_SETCURSEL,
CB_RESETCONTENT,
sizeof(DRIVER_INFO_1),
(DWORD)&(((PDRIVER_INFO_1)0)->pName),
(PFNGETINSTALLED)GetInstalledDrivers
};
INSTALLDRIVERDATA iddMonitor = {
IDS_MONITOR_INSTALL_TITLE,
IDS_MONITOR_SELECT_TITLE,
IDS_MONITOR_TYPE,
DLG_INSTALLMONITOR,
DLG_SELECTMONITOR,
TEXT("MONITOR.INF"),
TEXT("MONITOR"),
TEXT("OPTIONS"),
LB_INSERTSTRING,
LB_FINDSTRINGEXACT,
LB_SETCURSEL,
LB_RESETCONTENT,
sizeof(MONITOR_INFO_1),
(DWORD)&(((PMONITOR_INFO_1)0)->pName),
(PFNGETINSTALLED)GetInstalledMonitors
};
//
// structs, private
//
typedef struct _INF_CACHE {
LPTSTR pszzDrivers;
UINT uDrivers; // uninstalled driver count
UINT uTotal; // total count
INFDRIVER aInfDriver[1]; // sorted list of installed/uninstalled drivers
} INFCACHE;
//
// Prototypes
//
VOID
Insert(
PINFCACHE pInfCache,
LPTSTR pszDriver,
BOOL bInstalled);
UINT
GetDriverCount(
LPTSTR pszzDriver,
PINFCACHE pInfCache);
HANDLE
OpenInfFileW(
PWCHAR szFileName,
PWCHAR szInfType);
PWCHAR
GetOptionListW(
HANDLE hndInf,
PWCHAR szOptionSection);
PTCHAR
GetOptionFromListSelection(
INT Selection,
PTCHAR pOption );
TCHAR LastChar(TCHAR *string);
void AppendChar(TCHAR *string, TCHAR ch);
//
// Procedures
//
VOID
DestroyInfParms(
PINFPARMS pInfParms)
/*++
Routine Description:
Frees information in pInfParms, BUT NOT pInfParms!
Arguments:
Return Value:
--*/
{
if (pInfParms->pInstalled)
FreeSplMem(pInfParms->pInstalled);
pInfParms->pInstalled = NULL;
pInfParms->cbInstalled = 0;
DestroyInfCache(pInfParms->pInfCache);
pInfParms->pInfCache = NULL;
}
VOID
DestroyInfCache(
PINFCACHE pInfCache)
{
if (pInfCache && pInfCache->pszzDrivers) {
LocalFree(pInfCache->pszzDrivers);
FreeSplMem(pInfCache);
}
}
BOOL
HandleSelChange(
HWND hwnd,
PINFPARMS pInfParms,
UINT uAddSel)
{
PINSTALLDRIVERDATA pInstallDriverData = pInfParms->pInstallDriverData;
PTCHAR pInstalledDriverOption;
BOOL OK;
DWORD cInstalledDrivers;
BOOL bReturnValue = FALSE;
//
// pInfParms->pOptions must be cleared since this dialog box
// may fail, and we want to know if pOptions is valid.
//
pInfParms->pOptions = NULL;
OK = DialogBoxParam(hInst,
MAKEINTRESOURCE(DLG_INSTALLDRIVER),
hwnd,
(DLGPROC)InstallDriverDlg,
(LONG)pInfParms);
//
// Remember, we are responsible for freeing
// pOptions since pOptionSelected points into it.
//
pInstalledDriverOption = pInfParms->pOptionSelected;
if( OK && pInstalledDriverOption )
{
//
// Refresh our list of things.
//
cInstalledDrivers = (*pInstallDriverData->pfnGetInstalled)(pInfParms);
/* Check whether the number of installed drivers has actually increased.
* This may not be the case if a driver was installed to update an
* already installed driver.
*/
if( cInstalledDrivers > pInfParms->cInstalled )
{
DBGMSG( DBG_INFO, ( "Total of %d installed drivers. Updating list.\n",
cInstalledDrivers ) );
//
// If so, we need to update the list of merged drivers too:
//
pInfParms->cInstalled = cInstalledDrivers;
SetupInfDlg(pInfParms);
}
else
{
DBGMSG( DBG_INFO, ( "A driver was updated. No new drivers installed.\n" ) );
}
//
// Select the new driver
//
pInfParms->uCurSel = SendMessage(pInfParms->hwnd,
pInstallDriverData->uFindMsg,
(WPARAM)-1,
(LPARAM)pInstalledDriverOption);
if (pInfParms->uCurSel == (UINT)-1) {
pInfParms->uCurSel = 0;
goto RestorePrevious;
}
SendMessage(pInfParms->hwnd,
pInstallDriverData->uSelectMsg,
pInfParms->uCurSel,
0L);
}
else
{
RestorePrevious:
DBGMSG( DBG_WARNING, ( "Driver was not installed or failed to find.\n" ) );
//
// If we didn't install a new driver, don't keep the "Other..."
// selection in the list box; return it to the previous one:
//
SendMessage(pInfParms->hwnd,
pInstallDriverData->uSelectMsg,
pInfParms->uCurSel,
0L);
/* Ensure that we do actually have a driver now.
* This is a fix for bug #16383, which happened
* when there were no drivers installed and PRINTER.INF
* was missing. The Create Printer dialog prompted
* for a source path, and the user canceled out,
* then typed a printer name and clicked OK.
* Only "Other..." was in the Drivers list, but the
* code assumed there was a driver.
*/
if (pInfParms->uCurSel == uAddSel)
{
Message( hwnd, MSG_ERROR, IDS_PRINTMANAGER,
IDS_NO_DRIVERS_INSTALLED, pInstallDriverData->pszInfFile );
goto Done;
}
}
bReturnValue = TRUE;
Done:
//
// Must be local free'd since allocated by inf code rather than
// spooler (Don't use FreeSplMem).
//
if (pInfParms->pOptions)
LocalFree(pInfParms->pOptions);
return TRUE;
}
PINFCACHE
SetupInfDlg(
PINFPARMS pInfParms)
/*++
Routine Description:
Sets up the window with the installed and installable drivers.
Arguments:
Return Value:
pInfCacheNew buffer must be freed by callee or used in pInfCache
on the next call. If cache used, then the return value is the cache.
NULL = Error, use GetLastError()
--*/
{
PINSTALLDRIVERDATA pInstallDriverData = pInfParms->pInstallDriverData;
LPTSTR pszzDrivers = NULL;
UINT uDrivers = 0;
HANDLE hInfFile;
TCHAR string[128];
PINFCACHE pInfCache = pInfParms->pInfCache;
HWND hwnd = pInfParms->hwnd;
UINT uInsertMsg = pInstallDriverData->uInsertMsg;
UINT uFindMsg = pInstallDriverData->uFindMsg;
UINT uSelectMsg = pInstallDriverData->uSelectMsg;
PBYTE pInstalled = pInfParms->pInstalled;
UINT uInstalled = pInfParms->cInstalled;
DWORD cbSize = pInstallDriverData->cbSize;
DWORD cbOffset = pInstallDriverData->cbOffset;
LPTSTR pszCurrentDriver = pInfParms->pszCurrentDriver;
UINT i;
//
// If pInfCache valid but hInfFile isn't, then we won't read
// in inf file until pInfCache is invalid.
//
if (!pInfCache) {
hInfFile = OpenInfFileW(pInstallDriverData->pszInfFile,
pInstallDriverData->pszInfType);
if (hInfFile != INVALID_HANDLE_VALUE) {
pszzDrivers = GetOptionListW(hInfFile, pInstallDriverData->pszSection);
CloseInfFile(hInfFile);
if (pszzDrivers) {
uDrivers = GetDriverCount(pszzDrivers, NULL);
}
}
} else {
uDrivers = pInfCache->uDrivers;
pszzDrivers = pInfCache->pszzDrivers;
FreeSplMem(pInfCache);
}
pInfCache = AllocSplMem(sizeof(INFCACHE) +
(uDrivers+uInstalled) * sizeof(INFDRIVER));
pInfParms->pInfCache = pInfCache;
if (!pInfCache) {
LocalFree(pszzDrivers);
return NULL;
}
//
// pInfCache->uTotal = 0;
//
pInfCache->uDrivers = uDrivers;
pInfCache->pszzDrivers = pszzDrivers;
//
// Reset the box
//
SendMessage(hwnd,
pInstallDriverData->uResetMsg,
0,
0L);
//
// Add in uninstalled drivers
//
GetDriverCount(pszzDrivers, pInfCache);
//
// Add in installed drivers
//
if (pInstalled) {
for(i=0, ((PBYTE)pInstalled) += cbOffset;
i<uInstalled;
i++, ((PBYTE)pInstalled) += cbSize) {
Insert(pInfCache, *((LPTSTR*)pInstalled), TRUE);
}
}
//
// pInstalled is now garbage
//
//
// Now everything is sorted and added (Insert removes dups)
// Do Insert!
//
for(i = 0; i < pInfCache->uTotal; i++) {
SendMessage(hwnd,
uInsertMsg,
i,
(LPARAM)pInfCache->aInfDriver[i].pszDriver);
}
if (pszCurrentDriver) {
pInfParms->uCurSel = SendMessage(hwnd,
uFindMsg,
0,
(LPARAM)pszCurrentDriver);
if (pInfParms->uCurSel == (DWORD)-1)
pInfParms->uCurSel = 0;
} else {
pInfParms->uCurSel = 0;
}
SendMessage(hwnd, uSelectMsg, pInfParms->uCurSel, 0L);
LoadString( hInst, IDS_OTHER, string,
sizeof( string ) / sizeof( *string ) );
i = SendMessage(hwnd,
uInsertMsg,
(WPARAM)-1,
(LPARAM)string );
//
// Use the combo box reserved user long to store the unlisted index:
//
SetWindowLong(hwnd, GWL_USERDATA, i);
return pInfCache;
}
VOID
Insert(
PINFCACHE pInfCache,
LPTSTR pszDriver,
BOOL bInstalled)
/*++
Routine Description:
Inserts a string and bInstalled option into pInfCache. Assume
string compares slow, moving items fast (true since NLS sorting
is enabled).
This does a binary sort in place, which causes a lot of item movement
(not pointers, but actual objects), so if INFDRIVER gets big,
rewrite this code.
Duplicates disallowed; bInstalled turned on if duplicate has it on.
Arguments:
pInfCache -- Structure to insert item into. Assumes uTotal is
accurate and there is enough space for the new item.
pszDriver -- Driver string to insert. Must not be freed until pInfCache
is no longer needed.
bInstalled -- Extra param for INFDRIVER.
Return Value:
--*/
{
INT iMax, iMin, iMid, j, iCompare;
PINFDRIVER pInfDriver = pInfCache->aInfDriver;
UINT uTotal = pInfCache->uTotal;
//
// Check if iMax is != 0. If so, must sort insert.
//
if (iMax = uTotal) {
iMin = 0;
//
// Quick hack for presorted lists
//
// Since they sort already (excepting strange chars/localization)
// do a quick check if it goes at the end of the list.
//
// Check if it DOESN'T, then insert
//
iCompare = lstrcmpi(pInfDriver[iMax-1].pszDriver, pszDriver);
if (!iCompare) {
//
// On match, just turn on bInstalled bit.
//
pInfDriver[iMax-1].bInstalled |= bInstalled;
return;
} else if (iCompare > 0) {
//
// do a binary insert
//
do {
iMid = (iMax + iMin) / 2;
iCompare = lstrcmpi(pInfDriver[iMid].pszDriver, pszDriver);
if (iCompare < 0)
iMin = iMid + 1;
else if (iCompare > 0)
iMax = iMid - 1;
else {
iMin = iMax = iMid;
}
} while (iMax > iMin);
if (iMax < 0)
iMax = 0;
//
// Insert after this item.
//
if ((iCompare=lstrcmpi(pInfDriver[iMax].pszDriver, pszDriver)) < 0) {
iMax++;
}
//
// If if not a duplicate
//
if (iCompare) {
if (iMax != (INT)uTotal) {
for (j = uTotal; j > iMax; j--)
pInfDriver[j] = pInfDriver[j-1];
}
}
}
//
// If its a duplicate, don't install it, just make sure
// to update the bInstalled flag.
//
if (!iCompare) {
pInfDriver[iMax].bInstalled |= bInstalled;
return;
}
}
//
// New driver, add it to the list
//
pInfDriver[iMax].pszDriver = pszDriver;
pInfDriver[iMax].bInstalled = bInstalled;
pInfCache->uTotal++;
}
UINT
GetDriverCount(
LPTSTR pszzDriver,
PINFCACHE pInfCache)
/*++
Routine Description:
Gets the number of strings in a list of strings (null term).
If ppszDriver is != NULL, fills it with pointers into the array.
Arguments:
pszzDriver -- List of strings, NULL terminated
Can be NULL.
pInfCache -- [OPTIONAL] pInfCache struct to update
These drivers are added to the structure as NOT_INSTALLED!
Return Value:
Number of strings in pOptions
--*/
{
UINT uCount = 0;
if (!pszzDriver)
return 0;
while( *pszzDriver ) {
if (pInfCache) {
Insert(pInfCache, pszzDriver, FALSE);
}
uCount++;
//
// Scan to the end of this option:
//
while( *pszzDriver )
pszzDriver++;
//
// Step over the null-terminator:
//
pszzDriver++;
}
return uCount;
}
PWCHAR
GetOptionListW(
HANDLE hndInf,
PWCHAR szOptionSection)
{
PCHAR szos;
PCHAR szList;
PCHAR p;
int cchos;
PWCHAR szReturn;
PWCHAR szPtr;
int size;
cchos = (lstrlenW(szOptionSection)+1)*sizeof(TCHAR);
szos = AllocSplMem(cchos);
WideCharToMultiByte( CP_ACP, 0,
szOptionSection, lstrlenW(szOptionSection)+1,
szos, cchos,
NULL, NULL );
szList = p = GetOptionList(hndInf, szos);
szReturn = AllocSplMem( LocalSize(szList) *sizeof(TCHAR) );
szPtr = szReturn;
while( *p ) {
size = lstrlenA(p)+1;
MultiByteToWideChar(CP_ACP,
MB_PRECOMPOSED,
p,
size,
szPtr,
size*sizeof(TCHAR) );
p += size;
szPtr += (lstrlenW(szPtr)+1);
}
LocalFree(szList);
FreeSplMem(szos);
return szReturn;
}
HANDLE
OpenInfFileW(
PWCHAR szFileName,
PWCHAR szInfType)
{
PCHAR szfn;
PCHAR szit;
int cchfn;
int cchit;
HANDLE h;
cchfn = (lstrlenW(szFileName)+1)*sizeof(TCHAR);
cchit = (lstrlenW(szInfType)+1)*sizeof(TCHAR);
szfn = AllocSplMem(cchfn);
szit = AllocSplMem(cchit);
WideCharToMultiByte( CP_ACP, 0,
szFileName, lstrlenW(szFileName)+1,
szfn, cchfn,
NULL, NULL );
WideCharToMultiByte( CP_ACP, 0,
szInfType, lstrlenW(szInfType)+1,
szit, cchit,
NULL, NULL );
h = OpenInfFile(szfn, szit);
FreeSplMem(szfn);
FreeSplMem(szit);
return h;
}
PINFDRIVER
GetInfDriver(
PINFCACHE pInfCache,
UINT uIndex)
{
return &pInfCache->aInfDriver[uIndex];
}
BOOL APIENTRY
SelectDriverDlg(
HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam)
{
PINFPARMS pInfParms;
switch(msg)
{
case WM_INITDIALOG:
return SelectDriverInitDialog(hwnd, (PINFPARMS)lparam);
case WM_COMMAND:
switch (LOWORD(wparam))
{
case IDOK:
return SelectDriverCommandOK(hwnd);
case IDCANCEL:
return SelectDriverCommandCancel(hwnd);
case IDD_SD_LB_PRINTERDRIVERS:
switch (HIWORD(wparam))
{
case CBN_DBLCLK:
return SelectDriverCommandOK(hwnd);
}
break;
case IDD_SD_PB_HELP:
goto DoHelp;
}
}
if( msg == WM_Help ) {
DoHelp:
pInfParms = (PINFPARMS)GetWindowLong(hwnd,
GWL_USERDATA);
ShowHelp(hwnd,
HELP_CONTEXT,
pInfParms->pInstallDriverData->dlgSelectHelp);
}
return FALSE;
}
BOOL
SelectDriverInitDialog(
HWND hwnd,
PINFPARMS pInfParms)
{
PINSTALLDRIVERDATA pInstallDriverData = pInfParms->pInstallDriverData;
PTCHAR pOptions;
LPTSTR pszTitle;
SetWindowLong(hwnd, GWL_USERDATA, (LONG)pInfParms);
// #ifndef JAPAN
if (!bJapan) {
SETDLGITEMFONT(hwnd, IDD_SD_EF_SOURCEDIRECTORY, hfontHelv);
SETDLGITEMFONT(hwnd, IDD_SD_LB_PRINTERDRIVERS, hfontHelv);
}
// #endif
SetDlgItemText(hwnd,
IDD_SD_EF_SOURCEDIRECTORY,
pInfParms->pInfDirectory);
SendDlgItemMessage(hwnd, IDD_SD_EF_SOURCEDIRECTORY, EM_LIMITTEXT, MAX_PATH, 0);
SendDlgItemMessage(hwnd, IDD_SD_EF_SOURCEDIRECTORY, WM_KEYDOWN, (WPARAM)VK_END, 0);
pOptions = pInfParms->pOptions;
pszTitle = GetString(pInstallDriverData->idsSelectTitle);
if (pszTitle) {
SetWindowText(hwnd, pszTitle);
FreeSplStr(pszTitle);
}
pszTitle = GetString(pInstallDriverData->idsType);
if (pszTitle) {
SetDlgItemText(hwnd, IDD_SD_TX_TYPE, pszTitle);
FreeSplStr(pszTitle);
}
/* Only continue as long as we get a valid option text.
* If GetOptionTextW returns NULL, we've probably got
* a corrupted INF file.
*/
while( *pOptions /*&& pOptionText*/ )
{
/* !!! What do we do with the language here ???
* IGNORE IT!
*/
SendDlgItemMessage( hwnd, IDD_SD_LB_PRINTERDRIVERS, LB_INSERTSTRING,
(UINT)-1, (LONG)(LPTSTR)pOptions);
while(*pOptions++);
}
SetFocus( GetDlgItem( hwnd, IDD_SD_LB_PRINTERDRIVERS ) );
SendMessage( GetDlgItem( hwnd, IDD_SD_LB_PRINTERDRIVERS ),
LB_SETCURSEL, 0, 0 );
return FALSE;
}
/*
*
*/
BOOL SelectDriverCommandOK(HWND hwnd)
{
PINFPARMS pInfParms;
TCHAR string[MAX_PATH];
PTCHAR pOptions;
int Selection;
pInfParms = (PINFPARMS)GetWindowLong( hwnd, GWL_USERDATA );
GetDlgItemText(hwnd,
IDD_SD_EF_SOURCEDIRECTORY,
string,
sizeof (string)/sizeof(TCHAR) );
// if(LastChar(string) != BACKSLASH)
// AppendChar(string, BACKSLASH);
ReallocSplStr( &pInfParms->pSetupDirectory, string );
Selection = GETLISTSELECT( hwnd, IDD_SD_LB_PRINTERDRIVERS );
GETLISTTEXT( hwnd, IDD_SD_LB_PRINTERDRIVERS, Selection, string );
pOptions = pInfParms->pOptions;
pInfParms->pOptionSelected = GetOptionFromListSelection( Selection,
pOptions );
EndDialog( hwnd, TRUE );
return TRUE;
}
/*
*
*/
BOOL SelectDriverCommandCancel(HWND hwnd)
{
EndDialog(hwnd, FALSE);
return TRUE;
}
/*
*
*/
PTCHAR
GetOptionFromListSelection(
INT Selection,
PTCHAR pOption)
{
int i = 0;
while( i < Selection )
{
while( *pOption ) /* Increment to null terminator */
pOption++;
pOption++; /* Increment to beginning of next option */
i++;
}
return pOption;
}
BOOL APIENTRY
InstallDriverDlg(
HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam)
/*++
Routine Description:
Dialog for user to type in a path for the in file. This dialog
then creates the select dialog to choose a new driver.
** NOTE ** Callee must free pOptions, since pOptionSelected
points into this buffer.
Arguments:
Return Value:
--*/
{
PINFPARMS pInfParms;
switch(msg)
{
case WM_INITDIALOG:
return InstallDriverInitDialog(hwnd, (PINFPARMS)lparam);
case WM_COMMAND:
switch (LOWORD(wparam))
{
case IDOK:
return InstallDriverCommandOK(hwnd);
case IDCANCEL:
return InstallDriverCommandCancel(hwnd);
case IDD_ID_HELP:
goto DoHelp;
}
}
if( msg == WM_Help ) {
DoHelp:
pInfParms = (PINFPARMS)GetWindowLong(hwnd,
GWL_USERDATA);
ShowHelp(hwnd,
HELP_CONTEXT,
pInfParms->pInstallDriverData->dlgInstallHelp);
}
return FALSE;
}
/*
*
*/
BOOL
InstallDriverInitDialog(
HWND hwnd,
PINFPARMS pInfParms)
{
LPTSTR pszTitle;
PINSTALLDRIVERDATA pInstallDriverData = pInfParms->pInstallDriverData;
SetWindowLong(hwnd, GWL_USERDATA, (LONG)pInfParms);
// #ifndef JAPAN
if (!bJapan) {
SETDLGITEMFONT(hwnd, IDD_ID_EF_DRIVERPATH, hfontHelv);
}
// #endif
pszTitle = GetString(pInstallDriverData->idsInstallTitle);
if (pszTitle) {
SetWindowText(hwnd, pszTitle);
FreeSplStr(pszTitle);
}
SendDlgItemMessage(hwnd, IDD_ID_EF_DRIVERPATH, EM_LIMITTEXT, MAX_PATH, 0);
SetDlgItemText(hwnd, IDD_ID_EF_DRIVERPATH, TEXT("A:\\"));
return TRUE;
}
/*
*
*/
BOOL InstallDriverCommandOK(HWND hwnd)
{
TCHAR FileName[MAX_PATH+1+1+11];
// Note maximum possible characters retrievable from
// the dialog box MAX_PATH + 1 char for the '\\' +
// 11 chars for the szSetupInf + 1 char null terminator
HANDLE hInfFile;
PTCHAR pOptions;
BOOL SetupOK;
DWORD ExitCode;
PINSTALLDRIVERDATA pInstallDriverData;
PINFPARMS pInfParms;
TCHAR FullPath[MAX_PATH+1+1+11];
BOOL OK = FALSE;
PTCHAR pFilePart;
pInfParms = (PINFPARMS)GetWindowLong( hwnd, GWL_USERDATA );
pInstallDriverData =pInfParms->pInstallDriverData;
//
// Get the path, which may or may not have been modified by the user:
//
memset(FileName, 0, MAX_PATH+13);
GetDlgItemText(hwnd, IDD_ID_EF_DRIVERPATH, FileName, MAX_PATH);
if(LastChar(FileName) != BACKSLASH) /* Ensure it's terminated with backslash */
AppendChar(FileName, BACKSLASH);
/* Append the setup filename to the path:
*/
_tcscat(FileName, pInstallDriverData->pszInfFile);
hInfFile = OpenInfFileW(FileName, pInstallDriverData->pszInfType);
if(hInfFile == INVALID_HANDLE_VALUE)
{
Message(hwnd, MSG_ERROR, IDS_PRINTMANAGER,
IDS_COULDNOTFINDINFFILE, FileName);
OK = FALSE;
}
else
{
GetDlgItemText(hwnd, IDD_ID_EF_DRIVERPATH, FileName, sizeof FileName/sizeof(TCHAR));
/* Now get a full path name which will be passed on to SETUP.
* We will give SETUP the full path name in case the user typed in
* a relative path. In this instance, SETUP will assume that the
* default directory is System32, but this might just possibly
* not correspond to Print Manager's default.
* We just found the .INF file in the directory, so it's safe to
* assume that GetFullPathname will succeed.
*/
if( GetFullPathName( FileName, sizeof FullPath/sizeof(TCHAR), FullPath, &pFilePart ) )
{
pOptions = GetOptionListW(hInfFile, pInstallDriverData->pszSection);
/* Assume the drivers are in the same directory as the INF file;
* this can be overridden by the user:
*/
pInfParms->pSetupDirectory = AllocSplStr(FullPath);
pInfParms->pInfDirectory = AllocSplStr(FullPath);
if(pOptions && pInfParms->pSetupDirectory
&& pInfParms->pInfDirectory)
{
pInfParms->pOptions = pOptions;
SetCursor( hcursorWait );
if( DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_SELECTDRIVER),
hwnd, (DLGPROC)SelectDriverDlg,
(DWORD)pInfParms) == IDOK )
{
SetupOK = InvokeSetup( hwnd,
pInstallDriverData->pszInfFile,
pInfParms->pSetupDirectory,
pInfParms->pInfDirectory,
pInfParms->pOptionSelected,
pInfParms->pServerName,
&ExitCode );
if( SetupOK && ( ExitCode == 0 ) )
{
DBGMSG( DBG_INFO, ( "%s was installed.\n",
pInfParms->pOptionSelected ) );
OK = TRUE;
}
else
{
DBGMSG( DBG_WARNING, ( "Setup failed: return code %d; exit code %d\n",
SetupOK, ExitCode ) );
}
}
FreeSplStr( pInfParms->pSetupDirectory );
FreeSplStr( pInfParms->pInfDirectory );
//
// Callee is responsible for LocalFree(pOptions);
// since pOptionSelected points into the buffer.
//
}
}
else
{
/* This should not happen.
*/
DBGMSG( DBG_WARNING, ("GetFullPathName( %s ) failed: Error %d\n",
FileName, GetLastError( ) ) );
}
CloseInfFile(hInfFile);
}
if( OK )
EndDialog(hwnd, TRUE);
return TRUE;
}
/*
*
*/
BOOL InstallDriverCommandCancel(HWND hwnd)
{
EndDialog(hwnd, FALSE);
return TRUE;
}
/*
*
*/
TCHAR LastChar(TCHAR *string)
{
while(*string) /* Increment to the null terminator */
string++;
return *(--string);
}
/*
*
*/
void AppendChar(TCHAR *string, TCHAR ch)
{
while(*string) /* Increment to the null terminator */
string++;
*string++ = ch;
*string = NULLC;
}
//
// InvokeSetup
//
// Call the SETUP.EXE program to install an option listed in an .INF file.
// The SETUP program will make the correct registry entries for this option
// under both HKEY_LOCAL_MACHINE and HKEY_CURRENT_USER. It will set the
// new default value for the USER (i.e. a new locale or keyboard layout).
//
BOOL InvokeSetup (HWND hwnd, LPTSTR pszInfFile, LPTSTR pszSetupDirectory,
LPTSTR pszInfDirectory, LPTSTR pszOption, LPTSTR pszServerName,
PDWORD pExitCode)
{
TCHAR *pszSetupString = TEXT("\\SETUP.EXE -f -s %s -i %s\\%s -c ExternalInstallOption \
/t STF_LANGUAGE = ENG /t OPTION = \"%s\" /t STF_PRINTSERVER = \"%s\" /t ADDCOPY = YES \
/t DOCOPY = YES /t DOCONFIG = YES /w %d");
int CmdSetupLength;
TCHAR pszSetup[200+MAX_PATH];
TCHAR *pszCmdSetup;
MSG Msg;
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInformation;
BOOL b;
// Create command line to invoke SETUP program
*pszSetup = NULLC;
GetSystemDirectory( pszSetup, sizeof pszSetup/sizeof(TCHAR) );
_tcscat( pszSetup, pszSetupString );
/* SLIGHT HACK:
*
* Currently we specify both setup and inf directories, or neither:
* We'll need to get more sophisticated if other combinations are needed.
*/
if( !pszSetupDirectory && !pszInfDirectory )
{
DeleteSubstring( pszSetup, TEXT("-s %s ") );
DeleteSubstring( pszSetup, TEXT("%s\\") );
}
/* Find out how much buffer we need for the command.
* Theoretically this could be enormous.
*
* The 20 is for the window handle passed in ascii.
*
*/
CmdSetupLength = ( _tcslen( pszSetup )+1
+ ( pszSetupDirectory ? _tcslen( pszSetupDirectory )+1 : 0 )
+ ( pszInfDirectory ? _tcslen( pszInfDirectory )+1 : 0 )
+ ( pszServerName ? _tcslen( pszServerName )+1 : 0 )
+ _tcslen( pszOption )+1
+ _tcslen( pszInfFile )+1 ) * sizeof(TCHAR)
+ 20;
if( !( pszCmdSetup = AllocSplMem( CmdSetupLength ) ) )
return FALSE;
if( !pszServerName )
pszServerName = TEXT("");
if( !pszSetupDirectory && !pszInfDirectory )
{
wsprintf (pszCmdSetup,
pszSetup,
pszInfFile,
pszOption,
pszServerName,
hwnd);
}
else
{
wsprintf (pszCmdSetup,
pszSetup,
pszSetupDirectory,
pszInfDirectory,
pszInfFile,
pszOption,
pszServerName,
hwnd);
}
// Create screen saver process
ZERO_OUT( &StartupInfo );
StartupInfo.cb = sizeof(StartupInfo);
StartupInfo.wShowWindow = SW_SHOW;
b = CreateProcess ( NULL,
pszCmdSetup,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&StartupInfo,
&ProcessInformation
);
// If process creation successful, wait for it to
// complete before continuing
if ( b )
{
EnableWindow (hwnd, FALSE);
while (MsgWaitForMultipleObjects (
1,
&ProcessInformation.hProcess,
FALSE,
(DWORD)-1,
QS_ALLINPUT) != 0)
{
// This message loop is a duplicate of main
// message loop with the exception of using
// PeekMessage instead of waiting inside of
// GetMessage. Process wait will actually
// be done in MsgWaitForMultipleObjects api.
//
while (PeekMessage (&Msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage (&Msg);
DispatchMessage (&Msg);
}
}
GetExitCodeProcess (ProcessInformation.hProcess, pExitCode);
CloseHandle (ProcessInformation.hProcess);
CloseHandle (ProcessInformation.hThread);
EnableWindow (hwnd, TRUE);
SetForegroundWindow (hwnd);
}
else
{
ReportFailure( hwnd, 0, IDS_ERRORRUNNINGSETUP );
}
FreeSplMem( pszCmdSetup );
return b;
}