|
|
//////////////////////////////////////////////////////////////////////////////
//
// 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 <windowsx.h>
#include <commctrl.h>
#include <prsht.h>
#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; }
|