////////////////////////////////////////////////////////////////////////////// // // WIZARD.CPP / Tuneup // // Microsoft Confidential // Copyright (c) Microsoft Corporation 1998 // All rights reserved // // Wizard creation and common functions. // // 7/98 - Jason Cohen (JCOHEN) // ////////////////////////////////////////////////////////////////////////////// // // Include file(s). // #include "main.h" #include #include #include #include "startup.h" #include "schedwiz.h" #include "tasks.h" #include "timeschm.h" #include "cleanup.h" #include "summary.h" #include "runnow.h" // // Internal structure(s). // typedef struct _WIZPAGE { INT iDialog; LPTSTR lpTitle; LPTSTR lpSubTitle; struct _WIZPAGE * lpNext; } WIZPAGE, *PWIZPAGE, *LPWIZPAGE; // // Inernal function prototype(s). // // Wizard proc. // static INT_PTR APIENTRY WizardPageProc(HWND, UINT, WPARAM, LPARAM); // Message proccessing functions. // static BOOL OnInit(HWND, INT); static VOID OnDestroy(HWND, INT); static VOID OnCommand(HWND, INT, HWND, UINT); static BOOL OnNotify(HWND, INT, INT); static BOOL OnDrawItem(HWND, const DRAWITEMSTRUCT *); // Other common wizard functions. // static VOID InitBoldFont(HWND); static VOID FreeWizPages(LPWIZPAGE); static LPWIZPAGE CreateWizPage(LPWIZPAGE, INT, LPTSTR, LPTSTR); INT CreateWizard(HINSTANCE hInstance, HWND hWndParent) { LPPROPSHEETPAGE lppsPage; PROPSHEETHEADER psHeader; DWORD dwPages = 0; INT iReturn; LPWIZPAGE lpWizPageHead, lpWizPageBuffer; LPTASKDATA lpTasks; // Make sure the common constrols are loaded and ready to use. // InitCommonControls(); // Set the current job pointer to the begining of // or global list of jobs. // g_CurrentTask = g_Tasks; // We always have the welcome dialog in the wizard. // If the first memory allocation fails, we have to bail. // if ( lpWizPageHead = (LPWIZPAGE) MALLOC(sizeof(WIZPAGE)) ) { lpWizPageBuffer = lpWizPageHead; lpWizPageBuffer->iDialog = IDD_WELCOME; } else return -1; // Add the time page. // lpWizPageBuffer = CreateWizPage(lpWizPageBuffer, IDD_TIME, MAKEINTRESOURCE(IDS_TITLE_TIME), MAKEINTRESOURCE(IDS_SUBTITLE_TIME)); // Add the startup group page. // if ( IsUserAdmin() || UserHasStartupItems() ) lpWizPageBuffer = CreateWizPage(lpWizPageBuffer, IDD_STARTMENU, MAKEINTRESOURCE(IDS_TITLE_STARTMENU), MAKEINTRESOURCE(IDS_SUBTITLE_STARTMENU)); // Create all the task pages. // for (lpTasks = g_Tasks; lpTasks; lpTasks = lpTasks->lpNext) lpWizPageBuffer = CreateWizPage(lpWizPageBuffer, lpTasks->nPageID, lpTasks->lpTitle, lpTasks->lpSubTitle); // Add the backup group page. // //lpWizPageBuffer = CreateWizPage(lpWizPageBuffer, IDD_BACKUP, MAKEINTRESOURCE(IDS_TITLE_BACKUP), MAKEINTRESOURCE(IDS_SUBTITLE_BACKUP)); // We always have the summary page. // If this memory allocation fails, we must // free the others and bail out. // if ( lpWizPageBuffer->lpNext = (LPWIZPAGE) MALLOC(sizeof(WIZPAGE)) ) { lpWizPageBuffer = lpWizPageBuffer->lpNext; lpWizPageBuffer->iDialog = IDD_SUMMARY; lpWizPageBuffer->lpNext = NULL; } else { lpWizPageBuffer->lpNext = NULL; FreeWizPages(lpWizPageHead); return -1; } // Get the number of pages. // for (lpWizPageBuffer = lpWizPageHead; lpWizPageBuffer; lpWizPageBuffer = lpWizPageBuffer->lpNext) dwPages++; // Alocate all the memory needed for all the wizard pages. // if ( (psHeader.ppsp = (LPCPROPSHEETPAGE) MALLOC(dwPages * sizeof(PROPSHEETPAGE))) == NULL ) { FreeWizPages(lpWizPageHead); return -1; } // Setup the property sheet header. // psHeader.dwSize = sizeof(PROPSHEETHEADER); psHeader.hwndParent = hWndParent; psHeader.nPages = dwPages; psHeader.nStartPage = 0; psHeader.hInstance = hInstance; psHeader.pszIcon = MAKEINTRESOURCE(IDI_TUNEUP); #ifdef OLDWIZ psHeader.dwFlags = PSH_USEICONID | PSH_PROPSHEETPAGE | PSH_WIZARD; #else // Wizard 97 only info. // psHeader.dwFlags = PSH_USEICONID | PSH_PROPSHEETPAGE | PSH_WIZARD97 | PSH_HEADER | PSH_WATERMARK; psHeader.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK); psHeader.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER); #endif // Setup all the page sheet structures. // for ( lppsPage = (LPPROPSHEETPAGE) psHeader.ppsp, lpWizPageBuffer = lpWizPageHead; lppsPage - psHeader.ppsp < (INT) dwPages && lpWizPageBuffer; lppsPage++, lpWizPageBuffer = lpWizPageBuffer->lpNext) { // Assign all the values for this property sheet. // lppsPage->dwSize = sizeof(PROPSHEETPAGE); lppsPage->hInstance = hInstance; lppsPage->pszTemplate = MAKEINTRESOURCE(lpWizPageBuffer->iDialog); lppsPage->pfnDlgProc = WizardPageProc; lppsPage->pszTitle = MAKEINTRESOURCE(IDS_TUNEUP); lppsPage->lParam = lpWizPageBuffer->iDialog; #ifndef OLDWIZ // Wizard 97 only info. // switch (lpWizPageBuffer->iDialog) { case IDD_WELCOME: case IDD_SUMMARY: lppsPage->dwFlags = PSP_USETITLE | PSP_HIDEHEADER; break; default: lppsPage->dwFlags = PSP_USETITLE | PSP_USEHEADERSUBTITLE | PSP_USEHEADERTITLE; lppsPage->pszHeaderTitle = lpWizPageBuffer->lpTitle; lppsPage->pszHeaderSubTitle = lpWizPageBuffer->lpSubTitle; } #endif } // Create the wizard and save the return code. // iReturn = (INT)PropertySheet(&psHeader); // Free the memory for the property sheet wizard pages. // FREE(psHeader.ppsp); FreeWizPages(lpWizPageHead); // Return positive value if successfull. // return(iReturn); } static INT_PTR APIENTRY WizardPageProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { // LPPROPSHEETPAGE lpsp; // PAINTSTRUCT ps; switch (message) { // Message cracking macros. // HANDLE_MSG(hDlg, WM_COMMAND, OnCommand); // Other messages to handle. // case WM_INITDIALOG: return OnInit(hDlg, (INT) (((LPPROPSHEETPAGE) lParam)->lParam)); case WM_NOTIFY: return OnNotify(hDlg, (INT) GetWindowLongPtr(hDlg, DWLP_USER), ((NMHDR *) lParam)->code); case WM_DRAWITEM: return OnDrawItem(hDlg, (const DRAWITEMSTRUCT *) lParam); case WM_DESTROY: OnDestroy(hDlg, (INT) GetWindowLongPtr(hDlg, DWLP_USER)); return FALSE; case WM_VKEYTOITEM: switch ( LOWORD(wParam) ) { case _T(' '): StartupSelectItem(GetDlgItem(hDlg, IDC_STARTUP)); return -2; default: return -1; } break; /* if ( g_hBoldFont && GetDlgItem(hDlg, IDC_HIGHTEXT) ) SendDlgItemMessage(hDlg, IDC_HIGHTEXT, WM_SETFONT, (WPARAM) g_hBoldFont, MAKELPARAM(TRUE, 0)); InitWizardPage(hDlg, lpsp->lParam); if (g_hStdPal == NULL) // We don't need to handle the bitmap in this environment. SendDlgItemMessage(hDlg, IDB_WIZBMP, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) (HANDLE) BmpData.hDib); break; case WM_DRAWITEM: PaintLine((DRAWITEMSTRUCT *) lParam); break; case WM_MEASUREITEM: OnMeasureItem((MEASUREITEMSTRUCT *) lParam, hDlg); break; case WM_PAINT: if (g_hStdPal) { BeginPaint(hDlg, &ps); PaintBitmap(&ps); EndPaint(hDlg, &ps); } else DefWindowProc(hDlg, message, wParam, lParam); break; case WM_ACTIVATE: if (g_hStdPal) InvalidateRect(hDlg, &BmpData.rect, FALSE); break; case WM_PALETTECHANGED: WmPaletteChanged(hDlg, wParam); break; case WM_QUERYNEWPALETTE: return WmQueryNewPalette(hDlg); */ default: return FALSE; } return TRUE; } static BOOL OnInit(HWND hDlg, INT nPageId) { BOOL bTaskInit = FALSE; // Store page dialog resource in the window data for later. // That way we can tell what page we are on when we get a // notification message. // SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM) nPageId); // Now init the individule pages. // switch (nPageId) { case IDD_WELCOME: InitBoldFont(GetDlgItem(hDlg, IDC_STATIC_TITLE)); CheckRadioButton(hDlg, IDC_EXPRESS, IDC_MANUAL, (g_dwFlags & TUNEUP_CUSTOM) ? IDC_MANUAL : IDC_EXPRESS); CenterWindow(GetParent(hDlg), NULL); break; case IDD_TIME: break; case IDD_STARTMENU: InitStartupMenu(hDlg); break; case IDD_CLEANUP: // Init the list box with the disk cleanup settings. // GetCleanupSettings(GetDlgItem(hDlg, IDC_LISTSET)); bTaskInit = TRUE; break; case IDD_TASK: bTaskInit = TRUE; InitGenericTask(hDlg); break; case IDD_SUMMARY: InitBoldFont(GetDlgItem(hDlg, IDC_STATIC_TITLE)); break; } // Do task init now. // if (bTaskInit) { if ( g_CurrentTask->dwOptions & TASK_SCHEDULED ) CheckRadioButton(hDlg, IDC_YES, IDC_DENY, IDC_YES); else { CheckRadioButton(hDlg, IDC_YES, IDC_DENY, IDC_DENY); EnableWindow(GetDlgItem(hDlg, IDC_RESCHED), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_SETTING), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_SCHEDTEXT), FALSE); } SetDlgItemText(hDlg, IDC_TASKDESC, g_CurrentTask->lpDescription); } return FALSE; } ////////////////////////////////////////////////////////////////////////////// // // INTERNAL: // OnDestroy() // - This function is called for every wizard dialog page when // the wizard is terminated either by finishing or canceling. // This should be used to free up any resources associated with // any of the wizard pages. // // ENTRY: // hDlg - Window handle to the wizard dialog being destroyed. // nPageId - Dialog resource ID for the dialog being destroyed. // // EXIT: // VOID // ////////////////////////////////////////////////////////////////////////////// static VOID OnDestroy(HWND hDlg, INT nPageId) { switch (nPageId) { case IDD_WELCOME: case IDD_SUMMARY: // Release the font we created for the welcome and summary pages. // InitBoldFont(NULL); break; case IDD_STARTMENU: // Need to release the data associated with the items in the combo box. // ReleaseStartupMenu(hDlg); break; } } static VOID OnCommand(HWND hDlg, INT id, HWND hwndCtl, UINT codeNotify) { LPTSTR lpBuffer; switch (id) { // Welcome page: // case IDC_EXPRESS: g_dwFlags &= ~TUNEUP_CUSTOM; break; case IDC_MANUAL: g_dwFlags |= TUNEUP_CUSTOM; break; // Time page: // case IDC_CURRENT: case IDC_RESET: EnableWindow(GetDlgItem(hDlg, IDC_NIGHT), (id == IDC_RESET)); EnableWindow(GetDlgItem(hDlg, IDC_DAY), (id == IDC_RESET)); EnableWindow(GetDlgItem(hDlg, IDC_EVENING), (id == IDC_RESET)); break; // Startup start menu group page: // #if 0 // No advanced button anymore. case IDC_ADVANCED: // Get the profiles directory and Shell Execute it. // if ( ( (lpBuffer = RegGetString(HKLM, g_szRegKeyProfiles, g_szRegValProfileDir)) == NULL ) || ( (DWORD) ShellExecute(hDlg, _T("explore"), lpBuffer, NULL, NULL, SW_SHOWNORMAL) <= 32 ) ) { // Error showing the folder. // // TODO: } // Free the buffer returned by RegGetString. // Macro automatically checks for NULL case before freeing. // FREE(lpBuffer); break; #endif case IDC_USERS: switch (codeNotify) { case CBN_SELCHANGE: InitStartupList(hDlg); break; } break; case IDC_STARTUP: if ( codeNotify == LBN_DBLCLK ) StartupSelectItem(hwndCtl); break; // Disk space cleanup page: // case IDC_CUSETTING: ExecAndWait(GetParent(hDlg), g_CurrentTask->lpSetName ? g_CurrentTask->lpSetName : g_CurrentTask->lpFullPathName, g_CurrentTask->lpSetParam, NULL); SendDlgItemMessage(hDlg, IDC_LISTSET, LB_RESETCONTENT, 0, 0); GetCleanupSettings(GetDlgItem(hDlg, IDC_LISTSET)); break; // Common controls to all pages: // case IDC_YES: case IDC_DENY: g_CurrentTask->dwOptions ^= TASK_SCHEDULED; EnableWindow(GetDlgItem(hDlg, IDC_RESCHED), id == IDC_YES); EnableWindow(GetDlgItem(hDlg, IDC_SETTING), ( id == IDC_YES ) && ( (g_CurrentTask->lpSetName != NULL) || (g_CurrentTask->lpSetParam != NULL) )); EnableWindow(GetDlgItem(hDlg, IDC_SCHEDTEXT), id == IDC_YES); break; case IDC_RESCHED: // Display the reschedule property sheet. // if ( JobReschedule(hDlg, g_CurrentTask->pTask) ) { // If the schedule change update the display with // the new trigger string. // if ( lpBuffer = GetTaskTriggerText(g_CurrentTask->pTask) ) { SetWindowText(GetDlgItem(hDlg, IDC_SCHEDTEXT), lpBuffer); FREE(lpBuffer); } } break; case IDC_SETTING: ExecAndWait(GetParent(hDlg), g_CurrentTask->lpSetName ? g_CurrentTask->lpSetName : g_CurrentTask->lpFullPathName, g_CurrentTask->lpSetParam, NULL); break; /* case IDC_SETTING: nItem = PageContents[g_nPageIdx].nTaskID; WideCharToMultiByte(CP_ACP, 0, ItemData[nItem].pwFullPathName, -1, szTemp, MAX_PATH, NULL, NULL); if (nItem == TASK_SMARTTIDY) SetSmartTidyOption(hDlg); else { wsprintf(szParameters, (nItem == TASK_CLEANUP) ? "/TUNEUP:%d" : "/SAGESET:%d", ItemData[PageContents[g_nPageIdx].nTaskID].nSageID); ExecAndWait(szTemp, szParameters, g_pWinDir, GetParent(hDlg), TRUE); } SetFocus(hDlg); if (nItem == TASK_CLEANUP) { } break; */ } } static BOOL OnDrawItem(HWND hWnd, const DRAWITEMSTRUCT * lpDrawItem) { BOOL bReturn; switch (lpDrawItem->CtlID) { case IDC_STARTUP: bReturn = StartupDrawItem(hWnd, lpDrawItem); break; case IDC_SUMLIST: bReturn = SummaryDrawItem(hWnd, lpDrawItem); break; default: bReturn = FALSE; } SetWindowLongPtr(hWnd, DWLP_MSGRESULT, bReturn); return bReturn; } static BOOL OnNotify(HWND hDlg, INT nPageId, INT nCode) { BOOL bTest; LPTSTR lpBuffer; switch (nCode) { case PSN_SETACTIVE: // Set Back, Next, Finish correctly. // PropSheet_SetWizButtons(GetParent(hDlg), (nPageId == IDD_WELCOME ? 0 : PSWIZB_BACK) | ( (nPageId == IDD_SUMMARY) ? PSWIZB_FINISH : PSWIZB_NEXT) ); switch (nPageId) { case IDD_WELCOME: case IDD_BACKUP: case IDD_STARTMENU: break; case IDD_TIME: EnableWindow(GetDlgItem(hDlg, IDC_CURRENT), !(g_dwFlags & TUNEUP_NOSCHEDULE)); EnableWindow(GetDlgItem(hDlg, IDC_NIGHT), (g_dwFlags & TUNEUP_NOSCHEDULE)); EnableWindow(GetDlgItem(hDlg, IDC_DAY), (g_dwFlags & TUNEUP_NOSCHEDULE)); EnableWindow(GetDlgItem(hDlg, IDC_EVENING), (g_dwFlags & TUNEUP_NOSCHEDULE)); if ( g_dwFlags & TUNEUP_NOSCHEDULE ) CheckRadioButton(hDlg, IDC_CURRENT, IDC_RESET, IDC_RESET); else CheckRadioButton(hDlg, IDC_CURRENT, IDC_RESET, IDC_CURRENT); CheckRadioButton(hDlg, IDC_NIGHT, IDC_EVENING, g_nTimeScheme); break; case IDD_SUMMARY: bTest = ( TasksScheduled(g_Tasks) > 0); ShowEnableWindow(GetDlgItem(hDlg, IDC_SUMTEXT), bTest); ShowEnableWindow(GetDlgItem(hDlg, IDC_SUMLIST), bTest); ShowEnableWindow(GetDlgItem(hDlg, IDC_RUNNOW), bTest); ShowEnableWindow(GetDlgItem(hDlg, IDC_NOTASKS), !bTest); if (bTest) InitSummaryList(GetDlgItem(hDlg, IDC_SUMLIST), g_Tasks); //LoadString(g_hInst, IDS_REM_NIGHT + g_nTimeScheme - IDC_NIGHT, szTemp, 256); //SetDlgItemText(hDlg, IDC_REMIND, szTemp); //InitSummaryList(GetDlgItem(hDlg, IDC_SUMMARYLIST3), nPage); break; default: // Update the task trigger text. // if ( lpBuffer = GetTaskTriggerText(g_CurrentTask->pTask) ) { SetWindowText(GetDlgItem(hDlg, IDC_SCHEDTEXT), lpBuffer); FREE(lpBuffer); } } break; case PSN_WIZBACK: switch (nPageId) { case IDD_SUMMARY: if ( !(g_dwFlags & TUNEUP_CUSTOM) ) SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_TIME); break; case IDD_WELCOME: case IDD_TIME: break; default: if (g_CurrentTask->lpBack) g_CurrentTask = g_CurrentTask->lpBack; } break; case PSN_WIZNEXT: switch (nPageId) { case IDD_TIME: // Change the time scheme if needed. // if ( IsDlgButtonChecked(hDlg, IDC_RESET) ) UpdateTimeScheme(hDlg); // Set this so that the next time this page is displayed, // we know there is already a schedule. // g_dwFlags &= ~TUNEUP_NOSCHEDULE; // Jump right to the summary page if we are in // express mode. // if ( !(g_dwFlags & TUNEUP_CUSTOM) ) SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_SUMMARY); break; case IDD_WELCOME: case IDD_STARTMENU: case IDD_SUMMARY: break; default: if (g_CurrentTask->lpNext) g_CurrentTask = g_CurrentTask->lpNext; } break; case PSN_WIZFINISH: // Set this flag so that we know to save settings (like // cleaning up the startup groups). // g_dwFlags |= TUNEUP_FINISHED; ReleaseJobs(g_Tasks, g_dwFlags & TUNEUP_FINISHED); // Save the registry settings. // RegSetString(HKLM, g_szTuneupKey, g_szRegValFirstTime, _T("1")); RegSetDword(HKLM, g_szTuneupKey, g_szRegValTime, g_nTimeScheme); RegSetString(HKLM, g_szTuneupKey, g_szRegValCustom, (g_dwFlags & TUNEUP_CUSTOM) ? _T("1") : _T("0")); // Run the tasks now if the box is checked. // if ( IsDlgButtonChecked(hDlg, IDC_RUNNOW) && (TasksScheduled(g_Tasks) > 0) ) RunTasksNow(GetParent(hDlg), g_Tasks); // Launch backup if we wanted to. // if ( g_dwFlags & TUNEUP_RUNBACKUP ) ExecAndWait(GetParent(hDlg), g_szBackupExe, NULL, NULL); break; case PSN_QUERYCANCEL: // Now release the jobs, saving each one if we fell // through the above PSN_WIZFINISH. // ReleaseJobs(g_Tasks, g_dwFlags & TUNEUP_FINISHED); break; /* if ( (nPage == PAGE_TIME) && (g_nTimeScheme != IDC_CUSTOM) ) // keep the init status; we may need to reset the time scheme when leave this page, nOrgTimeScheme = g_nTimeScheme = GetTimeScheme(); ActivateWizardPage(hDlg, nPage); g_nPageIdx = nPage; case PSN_WIZFINISH: // start Task Scheduler if any item is scheduled if (IsAnythingScheduled()) { // Add the Key for restarting computer static TCHAR szKey[] = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunServices"; HKEY hKey; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) { RegSetValueEx(hKey, (LPCTSTR)"SchedulingAgent", 0, REG_SZ, (LPBYTE)"mstask.exe", 11); RegCloseKey(hKey); } StartScheduler(); } // do all non-scheduled stuff, or run now... PerformAction(hDlg, IsDlgButtonChecked(hDlg, IDC_RUN_NOW)); // release all TaskScheduler interface/method, cal IPersist->save to write it ReleaseJob(TRUE); break; */ default: return FALSE; } return TRUE; } static VOID InitBoldFont(HWND hWndCtrl) { static HFONT hBigFont = NULL; TCHAR szFontName[32]; DWORD dwFontSize; // If NULL is passed in, we should free the font handle. // if ( hWndCtrl == NULL ) { // Free the font handle. // if (hBigFont) DeleteObject(hBigFont); } else { // We may already have the handle to the font we need, // but if not, we need to get it. // if ( hBigFont == NULL ) { // Get the font size. // if ( LoadString(NULL, IDS_TITLEFONTSIZE, szFontName, sizeof(szFontName) / sizeof(TCHAR)) ) dwFontSize = _tcstoul(szFontName, NULL, 10); else dwFontSize = 12; // Get the font name. // if ( !LoadString(NULL, IDS_TITLEFONTNAME, szFontName, sizeof(szFontName) / sizeof(TCHAR)) ) lstrcpy(szFontName, _T("Verdana")); hBigFont = GetFont(hWndCtrl, szFontName, dwFontSize, FW_BOLD); } // Now send the font to the control. // if ( hBigFont ) SendMessage(hWndCtrl, WM_SETFONT, (WPARAM) hBigFont, MAKELPARAM(TRUE, 0)); } } static VOID FreeWizPages(LPWIZPAGE lpWizPage) { if (lpWizPage) { FreeWizPages(lpWizPage->lpNext); FREE(lpWizPage); } } static LPWIZPAGE CreateWizPage(LPWIZPAGE lpWizPage, INT iDialog, LPTSTR lpTitle, LPTSTR lpSubTitle) { if ( lpWizPage->lpNext = (LPWIZPAGE) MALLOC(sizeof(WIZPAGE)) ) { lpWizPage = lpWizPage->lpNext; lpWizPage->iDialog = iDialog; lpWizPage->lpTitle = lpTitle; lpWizPage->lpSubTitle = lpSubTitle; } return lpWizPage; }