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.
380 lines
9.3 KiB
380 lines
9.3 KiB
//
|
|
// Setup.C
|
|
//
|
|
// Copyright (C) Microsoft, 1994,1995 All Rights Reserved.
|
|
//
|
|
// History:
|
|
// ral 5/23/94 - First pass
|
|
// 3/20/95 [stevecat] - NT port & real clean up, unicode, etc.
|
|
//
|
|
//
|
|
#include "priv.h"
|
|
#include "appwiz.h"
|
|
|
|
|
|
|
|
void _inline InitSetupWiz(HWND hDlg, LPARAM lParam)
|
|
{
|
|
InitWizSheet(hDlg, lParam, 0);
|
|
}
|
|
|
|
|
|
//
|
|
// Loads the specified resource ID string and replaces all ';' characters
|
|
// with NULL. The end of the string will be doubly null-teminated.
|
|
//
|
|
|
|
BOOL LoadAndStrip(int id, LPTSTR lpsz, int cbstr)
|
|
{
|
|
ASSERT(lpsz);
|
|
ASSERT(cbstr != 0);
|
|
|
|
if (!LoadString(g_hinst, id, lpsz, cbstr-1))
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
while (*lpsz)
|
|
{
|
|
if (*lpsz == TEXT('@'))
|
|
{
|
|
*lpsz = 0;
|
|
lpsz++;
|
|
}
|
|
else
|
|
{
|
|
lpsz = CharNext(lpsz);
|
|
}
|
|
}
|
|
*(lpsz+1) = 0;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Skips to the first charcter of the next string in a list of null-terminated
|
|
// strings. The caller should check to see if the pointer returned points to
|
|
// a null. If so, the end of the table has been reached.
|
|
//
|
|
|
|
LPTSTR SkipStr(LPTSTR lpsz)
|
|
{
|
|
while (*lpsz)
|
|
{
|
|
lpsz = CharNext(lpsz);
|
|
}
|
|
lpsz++;
|
|
|
|
return(lpsz);
|
|
}
|
|
|
|
|
|
void SetStaticStr(HWND hCtl, int id)
|
|
{
|
|
TCHAR szText[MAX_PATH];
|
|
|
|
LoadString(g_hinst, id, szText, ARRAYSIZE(szText));
|
|
|
|
Static_SetText(hCtl, szText);
|
|
}
|
|
|
|
|
|
void FreeIcon(HWND hDlg)
|
|
{
|
|
HICON hicon = Static_SetIcon(GetDlgItem(hDlg, IDC_SEARCHICON), NULL);
|
|
|
|
if (hicon)
|
|
{
|
|
DestroyIcon(hicon);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// ProgramExists returns TRUE if the specified file exists. This function
|
|
// accepts wildcards, and if a file matches the specified name then
|
|
// the file name buffer will be updated to the actual name of the first
|
|
// matching file. This allows FindBestSetupPrg to pass in *setup to find
|
|
// programs such as WPSETUP.EXE.
|
|
//
|
|
// This function assumes that szFindName is of size MAX_PATH.
|
|
//
|
|
|
|
BOOL ProgramExists(LPTSTR lpszFindName, UINT cchFindName)
|
|
{
|
|
HANDLE hfind;
|
|
WIN32_FIND_DATA fd;
|
|
|
|
hfind = FindFirstFile(lpszFindName, &fd);
|
|
|
|
if (hfind == INVALID_HANDLE_VALUE)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
FindClose(hfind);
|
|
|
|
StringCchCopy(lpszFindName+3, cchFindName-3, fd.cFileName);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
//
|
|
// This function searches for the "best" setup program. Once a windows app
|
|
// with the appropriate name is found it stops. If it finds a install/setup
|
|
// program that is a DOS program, it remembers the first one, but continues
|
|
// searching for a Windows setup program.
|
|
// Games like Math Rabbit have a DOS Install.Exe and a Windows Setup.Exe.
|
|
//
|
|
|
|
BOOL FindBestSetupPrg(LPTSTR lpszExeName, UINT cchExeName, LPTSTR lpszDriveRoot, LPTSTR lpszSpecialCase,
|
|
LPTSTR lpszAppNames, LPTSTR lpszExtensions)
|
|
{
|
|
LPTSTR lpszCurApp, lpszCurExt;
|
|
TCHAR szThisOne[MAX_PATH];
|
|
|
|
*lpszExeName = 0;
|
|
|
|
//
|
|
// Look for special-case programs first
|
|
//
|
|
|
|
lpszCurApp = lpszSpecialCase;
|
|
|
|
while(*lpszCurApp)
|
|
{
|
|
StringCchPrintf(szThisOne, ARRAYSIZE(szThisOne), TEXT("%s%s"), lpszDriveRoot, lpszCurApp);
|
|
|
|
if (ProgramExists(szThisOne, ARRAYSIZE(szThisOne)))
|
|
{
|
|
StringCchCopy(lpszExeName, cchExeName, szThisOne);
|
|
return(TRUE);
|
|
}
|
|
|
|
lpszCurApp = SkipStr(lpszCurApp);
|
|
}
|
|
|
|
//
|
|
// Now look for generic setup program names
|
|
//
|
|
|
|
lpszCurApp = lpszAppNames;
|
|
|
|
while (*lpszCurApp)
|
|
{
|
|
lpszCurExt = lpszExtensions;
|
|
|
|
while (*lpszCurExt)
|
|
{
|
|
StringCchPrintf(szThisOne, ARRAYSIZE(szThisOne), TEXT("%s%s.%s"), lpszDriveRoot, lpszCurApp, lpszCurExt);
|
|
|
|
if (ProgramExists(szThisOne, ARRAYSIZE(szThisOne)))
|
|
{
|
|
BOOL fIsWinApp = HIWORD(SHGetFileInfo(szThisOne, 0, NULL,
|
|
0, SHGFI_EXETYPE)) > 0;
|
|
|
|
if (*lpszExeName == 0 || fIsWinApp)
|
|
{
|
|
StringCchCopy(lpszExeName, cchExeName, szThisOne);
|
|
}
|
|
|
|
if (fIsWinApp)
|
|
{
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
lpszCurExt = SkipStr(lpszCurExt);
|
|
}
|
|
|
|
lpszCurApp = SkipStr(lpszCurApp);
|
|
}
|
|
|
|
return(*lpszExeName != 0);
|
|
}
|
|
|
|
|
|
//
|
|
// Gets information about the specified file/drive root and sets the
|
|
// icon and description fields in the dialog.
|
|
//
|
|
|
|
void _inline UpdateFileInfo(LPWIZDATA lpwd, LPTSTR lpszFileName)
|
|
{
|
|
HWND hKiddie;
|
|
HICON hOldIcon;
|
|
SHFILEINFO fi;
|
|
DWORD_PTR pdwRes;
|
|
|
|
pdwRes = SHGetFileInfo(lpszFileName, 0, &fi, sizeof(fi),
|
|
SHGFI_ICON | SHGFI_DISPLAYNAME | SHGFI_LARGEICON);
|
|
|
|
if (pdwRes)
|
|
{
|
|
hKiddie = GetDlgItem(lpwd->hwnd, IDC_SEARCHICON);
|
|
|
|
hOldIcon = Static_SetIcon(hKiddie, fi.hIcon);
|
|
|
|
if (hOldIcon)
|
|
{
|
|
DestroyIcon(hOldIcon);
|
|
}
|
|
|
|
UpdateWindow(hKiddie);
|
|
|
|
hKiddie = GetDlgItem(lpwd->hwnd, IDC_SEARCHNAME);
|
|
|
|
Static_SetText(hKiddie, fi.szDisplayName);
|
|
|
|
UpdateWindow(hKiddie);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Search for the setup program
|
|
//
|
|
|
|
BOOL SetupNextPressed(LPWIZDATA lpwd)
|
|
{
|
|
int iDrive, iDrvType;
|
|
BOOL fFoundExe = FALSE;
|
|
HWND hMainMsg = GetDlgItem(lpwd->hwnd, IDC_SETUPMSG);
|
|
HWND hSetupName = GetDlgItem(lpwd->hwnd, IDC_SEARCHNAME);
|
|
TCHAR szAppNames[MAX_PATH];
|
|
TCHAR szExtensions[100];
|
|
TCHAR szSpecialCase[MAX_PATH];
|
|
TCHAR szDriveRoot[4];
|
|
|
|
HCURSOR hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
//BOOL fFoundDisk = FALSE;
|
|
|
|
lpwd->szExeName[0] = 0; // Reset any existing name
|
|
|
|
SetStaticStr(hMainMsg, IDS_SEARCHING);
|
|
|
|
LoadAndStrip(IDS_SETUPPRGNAMES, szAppNames, ARRAYSIZE(szAppNames));
|
|
LoadAndStrip(IDS_EXTENSIONS, szExtensions, ARRAYSIZE(szExtensions));
|
|
LoadAndStrip(IDS_SPECIALCASE, szSpecialCase, ARRAYSIZE(szSpecialCase));
|
|
|
|
for (iDrive = 0; (!fFoundExe) && (iDrive < 26); iDrive++)
|
|
{
|
|
iDrvType = DriveType(iDrive);
|
|
|
|
if ((iDrvType == DRIVE_REMOVABLE) || (iDrvType == DRIVE_CDROM))
|
|
{
|
|
|
|
PathBuildRoot(szDriveRoot, iDrive);
|
|
UpdateFileInfo(lpwd, szDriveRoot);
|
|
if (PathFileExists(szDriveRoot))
|
|
{
|
|
//fFoundDisk = TRUE;
|
|
|
|
fFoundExe = FindBestSetupPrg(lpwd->szExeName, ARRAYSIZE(lpwd->szExeName), szDriveRoot,
|
|
szSpecialCase,
|
|
szAppNames, szExtensions);
|
|
}
|
|
}
|
|
}
|
|
|
|
FreeIcon(lpwd->hwnd);
|
|
SetCursor(hcurOld);
|
|
|
|
return(fFoundExe);
|
|
}
|
|
|
|
|
|
void SetupSetToDefault(LPWIZDATA lpwd)
|
|
{
|
|
SetStaticStr(GetDlgItem(lpwd->hwnd, IDC_SETUPMSG), IDS_INSERTDISK);
|
|
|
|
Static_SetText(GetDlgItem(lpwd->hwnd, IDC_SEARCHNAME), NULL);
|
|
|
|
FreeIcon(lpwd->hwnd);
|
|
|
|
PropSheet_SetWizButtons(GetParent(lpwd->hwnd), PSWIZB_NEXT);
|
|
|
|
//
|
|
// To make sure that the next button always has the focus, we post
|
|
// this message that sets the wiz buttons AFTER we're active. We have
|
|
// to do the one above to make sure that Back is disabled to avoid any
|
|
// random window where the back button could be hit.
|
|
//
|
|
|
|
PostMessage(lpwd->hwnd, WMPRIV_POKEFOCUS, 0, 0);
|
|
}
|
|
|
|
|
|
|
|
BOOL_PTR CALLBACK SetupDlgProc(HWND hDlg, UINT message , WPARAM wParam, LPARAM lParam)
|
|
{
|
|
NMHDR FAR *lpnm = NULL;
|
|
LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
|
|
LPWIZDATA lpwd = NULL;
|
|
|
|
if (lpPropSheet)
|
|
{
|
|
lpwd = (LPWIZDATA)lpPropSheet->lParam;
|
|
}
|
|
|
|
switch(message)
|
|
{
|
|
case WM_NOTIFY:
|
|
lpnm = (NMHDR FAR *)lParam;
|
|
if(lpnm)
|
|
{
|
|
switch(lpnm->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
if(lpwd)
|
|
{
|
|
lpwd->hwnd = hDlg;
|
|
SetupSetToDefault(lpwd);
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
if(lpwd)
|
|
{
|
|
SetupNextPressed(lpwd);
|
|
SetDlgMsgResult(hDlg, WM_NOTIFY, 0);
|
|
}
|
|
break;
|
|
|
|
case PSN_RESET:
|
|
if(lpwd)
|
|
{
|
|
CleanUpWizData(lpwd);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WMPRIV_POKEFOCUS:
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
InitSetupWiz(hDlg, lParam);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
FreeIcon(hDlg);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
} // end of switch on message
|
|
|
|
return TRUE;
|
|
|
|
} // SetupdlgProc
|