// // 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