Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1492 lines
44 KiB

/****************************************************************************
Copyright (c) Microsoft Corporation 1997
All rights reserved
***************************************************************************/
#include "pch.h"
#include <windowsx.h>
#include <prsht.h>
#include <shlobj.h>
#include <setupapi.h>
#include <pshpack2.h>
#include <poppack.h>
#include <commctrl.h> // includes the common control header
#include "setup.h"
DEFINE_MODULE("Dialogs");
#define WIZPAGE_FULL_PAGE_WATERMARK 0x00000001
#define WIZPAGE_SEPARATOR_CREATED 0x00000002
#define SMALL_BUFFER_SIZE 256
#define BITMAP_WIDTH 16
#define BITMAP_HEIGHT 16
#define LG_BITMAP_WIDTH 32
#define LG_BITMAP_HEIGHT 32
//
// Stuff used for watermarking
//
CONST BITMAPINFOHEADER *g_pbihWatermark;
PVOID g_pWatermarkBitmapBits;
HPALETTE g_hWatermarkPalette;
INT g_uWatermarkPaletteColorCount;
WNDPROC g_OldWizardProc;
//
// Enum for SetDialogFont().
//
typedef enum {
DlgFontTitle,
DlgFontBold
} MyDlgFont;
VOID
SetDialogFont(
IN HWND hdlg,
IN UINT ControlId,
IN MyDlgFont WhichFont
)
{
static HFONT BigBoldFont = NULL;
static HFONT BoldFont = NULL;
static HFONT NormalFont = NULL;
HFONT Font;
LOGFONT LogFont;
TCHAR FontSizeString[24];
int FontSize;
HDC hdc;
DWORD dw;
switch(WhichFont) {
case DlgFontTitle:
if(!BigBoldFont) {
if ( Font =
(HFONT) SendDlgItemMessage( hdlg, ControlId, WM_GETFONT, 0, 0) )
{
if ( GetObject( Font, sizeof(LOGFONT), &LogFont) )
{
dw = LoadString( g_hinstance,
IDS_LARGEFONTNAME,
LogFont.lfFaceName,
LF_FACESIZE);
Assert( dw );
LogFont.lfWeight = 700;
FontSize = 15;
if ( hdc = GetDC(hdlg) )
{
LogFont.lfHeight =
0 - (GetDeviceCaps(hdc,LOGPIXELSY) * FontSize / 72);
BigBoldFont = CreateFontIndirect(&LogFont);
ReleaseDC(hdlg,hdc);
}
}
}
}
Font = BigBoldFont;
break;
case DlgFontBold:
if ( !BoldFont )
{
if ( Font =
(HFONT) SendDlgItemMessage( hdlg, ControlId, WM_GETFONT, 0, 0 ))
{
if ( GetObject( Font, sizeof(LOGFONT), &LogFont ) )
{
LogFont.lfWeight = FW_BOLD;
if ( hdc = GetDC( hdlg ) )
{
BoldFont = CreateFontIndirect( &LogFont );
ReleaseDC( hdlg, hdc );
}
}
}
}
Font = BoldFont;
break;
default:
//
// Nothing to do here.
//
Font = NULL;
break;
}
if( Font )
{
SendDlgItemMessage( hdlg, ControlId, WM_SETFONT, (WPARAM) Font, 0 );
}
}
//
// Paints the watermark.
//
BOOL
PaintWatermark(
IN HWND hdlg,
IN HDC DialogDC,
IN UINT XOffset,
IN UINT YOffset,
IN UINT YHeight )
{
HPALETTE OldPalette;
RECT rect;
int Height;
int Width;
OldPalette = SelectPalette( DialogDC, g_hWatermarkPalette, TRUE );
Width = g_pbihWatermark->biWidth - ( 2 * XOffset );
Height = ( YHeight ? YHeight : g_pbihWatermark->biHeight ) - YOffset;
SetDIBitsToDevice(
DialogDC,
0,
0,
Width,
Height,
XOffset,
YHeight ? ( g_pbihWatermark->biHeight - YHeight ) : YHeight,
0, g_pbihWatermark->biHeight,
g_pWatermarkBitmapBits,
(BITMAPINFO *) g_pbihWatermark,
DIB_RGB_COLORS );
GetClientRect( hdlg, &rect );
if ( Height && Height < rect.bottom )
{
ExcludeClipRect( DialogDC, 0, 0, Width + 2 * XOffset, Height );
return FALSE;
}
return TRUE;
}
//
// Paints the watermark background within an HWND
//
BOOL
PaintBackgroundWithWatermark(
HWND hDlg,
HWND hwnd,
HDC hDC )
{
RECT rc1, rc2;
RECT rcDivider;
HWND hwndDivider = GetDlgItem( hDlg, IDC_DIVIDER );
GetClientRect( GetParent( hDlg ), &rc1 );
MapWindowPoints( GetParent( hDlg ), NULL, (POINT *) &rc1, 2 );
GetClientRect( hwnd, &rc2 );
MapWindowPoints( hwnd, NULL, (POINT *) &rc2, 2 );
if ( hwndDivider )
{
GetClientRect( hwndDivider, &rcDivider );
MapWindowPoints( hwndDivider, GetParent( hDlg ),
(POINT *) &rcDivider, 2 );
}
else
{
rcDivider.top = 0;
}
return PaintWatermark( hwnd, hDC, rc2.left-rc1.left,
rc2.top-rc1.top, rcDivider.top );
}
//
// Check to see if the directory exists. If not, ask the user if we
// should create it.
//
BOOL
CheckDirectory( HWND hDlg, LPTSTR pszPath, BOOL fAllowCreate )
{
BOOL fReturn = FALSE;
WIN32_FILE_ATTRIBUTE_DATA fad;
DWORD dwAttrib = GetFileAttributes( pszPath );
if ( dwAttrib == 0xFFFFffff )
{
if ( ERROR_FILE_NOT_FOUND == GetLastError( ) )
{
if ( fAllowCreate &&
IDYES == MessageBoxFromStrings( hDlg, IDS_CREATEDIRCAPTION, IDS_CREATEDIRTEXT, MB_YESNO ) )
{
g_Options.fCreateDirectory = TRUE;
fReturn = TRUE;
goto Cleanup;
}
else if ( !fAllowCreate )
{
MessageBoxFromStrings( hDlg, IDS_DIRDOESNOTEXISTCAPTION, IDS_DIRDOESNOTEXISTTEXT, MB_OK );
}
}
goto Cleanup;
}
fReturn = TRUE;
Cleanup:
SetWindowLong( hDlg, DWL_MSGRESULT, (fReturn ? 0 : -1 ) );
return fReturn;
}
//
// Adjusts and draws a bitmap transparently in the RECT prc.
//
void DrawBitmap(
HANDLE hBitmap,
LPDRAWITEMSTRUCT lpdis,
LPRECT prc )
{
BITMAP bm;
HDC hDCBitmap;
int dy;
GetObject( hBitmap, sizeof(bm), &bm );
hDCBitmap = CreateCompatibleDC( NULL );
SelectObject( hDCBitmap, hBitmap );
// center the image
dy = 2 + prc->bottom - bm.bmHeight;
StretchBlt( lpdis->hDC, prc->left, prc->top + dy, prc->right, prc->bottom,
hDCBitmap, 0, 0, bm.bmWidth, bm.bmHeight, SRCAND );
DeleteDC( hDCBitmap );
}
//
// Draws a bitmap transparently in reponse to a WM_DRAWITEM
//
void
DrawBitmap(
HANDLE hBitmap,
LPDRAWITEMSTRUCT lpdis )
{
HDC hDCBitmap;
hDCBitmap = CreateCompatibleDC( NULL );
SelectObject( hDCBitmap, hBitmap );
BitBlt( lpdis->hDC, 0, 0, lpdis->rcItem.right, lpdis->rcItem.bottom,
hDCBitmap, 0, 0, SRCAND );
DeleteDC( hDCBitmap );
}
//
// Verifies that the user wanted to cancel setup.
//
BOOL
VerifyCancel( HWND hParent )
{
TCHAR szText[ SMALL_BUFFER_SIZE ];
TCHAR szCaption[ SMALL_BUFFER_SIZE ];
dw = LoadString( g_hinstance, IDS_CANCELCAPTION, szCaption,
ARRAYSIZE( szCaption ));
Assert( dw );
dw = LoadString( g_hinstance, IDS_CANCELTEXT, szText,
ARRAYSIZE( szText ));
Assert( dw );
g_Options.fAbort =
( IDYES == MessageBoxFromStrings( hParent,
IDS_CANCELCAPTION,
IDS_CANCELTEXT,
MB_YESNO ) );
SetWindowLong( hParent, DWL_MSGRESULT, ( g_Options.fAbort ? 0 : - 1 ) );
return !g_Options.fAbort;
}
//
// Base dialog proc - all unhandled calls are passed here. If they are not
// handled here, then the default dialog proc will handle them.
//
BOOL CALLBACK
BaseDlgProc(
HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
NMHDR FAR *lpnmhdr;
switch ( uMsg )
{
case WM_INITDIALOG:
SetDialogFont( hDlg, IDC_S_TITLE1, DlgFontTitle );
//SetDialogFont( hDlg, IDC_S_TITLE2, DlgFontTitle );
//SetDialogFont( hDlg, IDC_S_TITLE3, DlgFontTitle );
SetDialogFont( hDlg, IDC_S_BOLD1, DlgFontBold );
SetDialogFont( hDlg, IDC_S_BOLD2, DlgFontBold );
SetDialogFont( hDlg, IDC_S_BOLD3, DlgFontBold );
break;
case WM_DRAWITEM:
if ( LOWORD( wParam ) >= IDC_I_BUTTON1 &&
LOWORD( wParam ) <= IDC_I_BUTTON7 )
DrawBitmap( g_hGraphic, (LPDRAWITEMSTRUCT) lParam );
break;
case WM_PALETTECHANGED:
if ((HWND)wParam != hDlg)
{
InvalidateRect(hDlg, NULL, NULL);
UpdateWindow(hDlg);
}
break;
case WM_ERASEBKGND:
return PaintBackgroundWithWatermark( hDlg, hDlg, (HDC) wParam );
case WM_CTLCOLORSTATIC:
if ( LOWORD( wParam ) == IDC_DIVIDER )
{
return FALSE;
}
else
{
// erase background
PaintBackgroundWithWatermark( hDlg, (HWND) lParam, (HDC) wParam );
// setup transparent mode
SetBkMode( (HDC) wParam, TRANSPARENT );
SetBkColor( (HDC) wParam, GetSysColor( COLOR_3DFACE ) );
return( (BOOL) GetStockObject( HOLLOW_BRUSH ) );
}
break;
default:
return FALSE;
}
return TRUE;
}
//
// "Welcome's" (the first page's) dialog proc.
//
BOOL CALLBACK
WelcomeDlgProc(
HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
NMHDR FAR *lpnmhdr;
static BOOL fFirstTime = FALSE;
switch ( uMsg )
{
case WM_INITDIALOG:
CenterDialog( GetParent( hDlg ) );
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
case WM_NOTIFY:
lpnmhdr = (NMHDR FAR *) lParam;
switch ( lpnmhdr->code )
{
// ignore these
case PSN_KILLACTIVE:
case PSN_WIZNEXT:
case PSN_WIZBACK:
case PSN_RESET:
SetWindowLong( hDlg, DWL_MSGRESULT, FALSE );
break;
case PSN_QUERYCANCEL:
return VerifyCancel( hDlg );
break;
case PSN_SETACTIVE:
PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_NEXT );
ClearMessageQueue( );
// eliminate flicker
if ( !fFirstTime )
{
fFirstTime = TRUE;
}
else
{
PostMessage( GetParent(hDlg), WMX_FORCEDREPAINT, 0, NULL );
}
break;
case PSN_HELP:
//
// TODO: Add help
//
break;
default:
AssertMsg( FALSE, "Unhandled PSN message" );
return FALSE;
}
break;
default:
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
}
return TRUE;
}
//
// Remote Boot Directory dialog proc.
//
BOOL CALLBACK
RemoteBootDlgProc(
HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
NMHDR FAR *lpnmhdr;
DWORD dw;
switch ( uMsg )
{
case WM_INITDIALOG:
Edit_SetText( GetDlgItem( hDlg, IDC_E_RBPATH), g_Options.szRemoteBootPath );
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
case WM_NOTIFY:
lpnmhdr = (NMHDR FAR *) lParam;
switch ( lpnmhdr->code )
{
// ignore these
case PSN_WIZBACK:
case PSN_KILLACTIVE:
case PSN_RESET:
SetWindowLong( hDlg, DWL_MSGRESULT, FALSE );
break;
case PSN_WIZNEXT:
Edit_GetText( GetDlgItem( hDlg, IDC_E_RBPATH ), g_Options.szRemoteBootPath, ARRAYSIZE( g_Options.szRemoteBootPath ));
g_Options.fCreateDirectory = FALSE;
CheckDirectory( hDlg, g_Options.szRemoteBootPath, TRUE );
break;
case PSN_QUERYCANCEL:
return VerifyCancel( hDlg );
break;
case PSN_SETACTIVE:
if ( g_Options.fError || g_Options.fKnowRBDirectory )
{
SetWindowLong( hDlg, DWL_MSGRESULT, -1 ); // do not show this page
}
else
{
DWORD dwLen = Edit_GetTextLength( GetDlgItem( hDlg, IDC_E_RBPATH) );
PropSheet_SetWizButtons( GetParent( hDlg ),
dwLen ? PSWIZB_BACK | PSWIZB_NEXT : PSWIZB_BACK );
ClearMessageQueue( );
PostMessage( GetParent(hDlg), WMX_FORCEDREPAINT, 0, (LPARAM) GetDlgItem( hDlg, IDC_DIVIDER ) );
}
break;
case PSN_HELP:
//
// TODO: Add help
//
break;
default:
AssertMsg( FALSE, "Unhandled PSN message" );
return FALSE;
}
break;
case WM_COMMAND:
switch( LOWORD( wParam))
{
case IDC_E_RBPATH:
{
if ( HIWORD(wParam) == EN_CHANGE )
{
DWORD dwLen = Edit_GetTextLength( GetDlgItem( hDlg, IDC_E_RBPATH) );
PropSheet_SetWizButtons( GetParent( hDlg ),
dwLen ? PSWIZB_BACK | PSWIZB_NEXT : PSWIZB_BACK );
}
}
break;
case IDC_B_BROWSE:
{
TCHAR szTitle[ SMALL_BUFFER_SIZE ];
BROWSEINFO bs;
ZeroMemory( &bs, sizeof(bs) );
bs.hwndOwner = hDlg;
dw = LoadString( g_hinstance, IDS_BROWSECAPTION_RBDIR, szTitle, ARRAYSIZE( szTitle ) );
Assert( dw );
bs.lpszTitle = (LPTSTR) &szTitle;
bs.ulFlags = BIF_RETURNONLYFSDIRS | BIF_RETURNFSANCESTORS;
LPITEMIDLIST pidl = SHBrowseForFolder( &bs );
SHGetPathFromIDList( pidl, g_Options.szRemoteBootPath );
Edit_SetText( GetDlgItem( hDlg, IDC_E_RBPATH ), g_Options.szRemoteBootPath );
}
break;
default:
break;
}
break;
default:
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
}
return TRUE;
}
//
// OS Name dialog proc.
//
BOOL CALLBACK
OSDlgProc(
HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
NMHDR FAR *lpnmhdr;
switch ( uMsg )
{
case WM_INITDIALOG:
Edit_SetText( GetDlgItem( hDlg, IDC_E_OSNAME ), g_Options.szName );
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
case WM_NOTIFY:
lpnmhdr = (NMHDR FAR *) lParam;
switch ( lpnmhdr->code )
{
// ignore these
case PSN_KILLACTIVE:
case PSN_WIZBACK:
case PSN_RESET:
SetWindowLong( hDlg, DWL_MSGRESULT, FALSE );
break;
case PSN_WIZNEXT:
Edit_GetText( GetDlgItem( hDlg, IDC_E_OSNAME ), g_Options.szName, ARRAYSIZE( g_Options.szName ) );
break;
case PSN_QUERYCANCEL:
return VerifyCancel( hDlg );
break;
case PSN_SETACTIVE:
{
if ( g_Options.fError )
{
SetWindowLong( hDlg, DWL_MSGRESULT, -1 ); // do not show this page
}
DWORD dwLen = Edit_GetTextLength( GetDlgItem( hDlg, IDC_E_OSNAME) );
PropSheet_SetWizButtons( GetParent( hDlg ),
dwLen ? PSWIZB_BACK | PSWIZB_NEXT : PSWIZB_BACK );
ClearMessageQueue( );
PostMessage( GetParent(hDlg), WMX_FORCEDREPAINT, 0, (LPARAM) GetDlgItem( hDlg, IDC_DIVIDER ) );
}
break;
case PSN_HELP:
//
// TODO: Add help
//
break;
default:
AssertMsg( FALSE, "Unhandled PSN message" );
return FALSE;
}
break;
case WM_COMMAND:
switch( LOWORD( wParam))
{
case IDC_E_OSNAME:
{
if ( HIWORD(wParam) == EN_CHANGE )
{
DWORD dwLen = Edit_GetTextLength( GetDlgItem( hDlg, IDC_E_OSNAME ) );
PropSheet_SetWizButtons( GetParent( hDlg ),
dwLen ? PSWIZB_BACK | PSWIZB_NEXT : PSWIZB_BACK );
}
}
break;
}
break;
default:
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
}
return TRUE;
}
//
// Remote Boot Directory dialog proc.
//
BOOL CALLBACK
SourceDlgProc(
HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
NMHDR FAR *lpnmhdr;
DWORD dw;
switch ( uMsg )
{
case WM_INITDIALOG:
Edit_SetText( GetDlgItem( hDlg, IDC_E_SOURCEPATH ), g_Options.szSourcePath );
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
case WM_NOTIFY:
lpnmhdr = (NMHDR FAR *) lParam;
switch ( lpnmhdr->code )
{
// ignore these
case PSN_KILLACTIVE:
case PSN_WIZBACK:
case PSN_RESET:
SetWindowLong( hDlg, DWL_MSGRESULT, FALSE );
break;
case PSN_WIZNEXT:
{
DWORD dwLen;
Edit_GetText( GetDlgItem( hDlg, IDC_E_SOURCEPATH ), g_Options.szSourcePath, ARRAYSIZE( g_Options.szSourcePath ) );
dwLen = lstrlen( g_Options.szSourcePath ) - 1;
if ( g_Options.szSourcePath[ dwLen ] == TEXT('\\') )
{
g_Options.szSourcePath[ dwLen ] = 0;
}
if ( CheckDirectory( hDlg, g_Options.szSourcePath, FALSE ) )
{
HANDLE hFile;
hFile = OpenLayoutInf( );
if ( hFile == INVALID_HANDLE_VALUE )
{
MessageBoxFromStrings( hDlg, IDS_INVALIDSOURCECAPTION, IDS_INVALIDSOURCETEXT, MB_OK );
SetWindowLong( hDlg, DWL_MSGRESULT, -1 );
}
else
{
SetupCloseInfFile( hFile );
}
}
g_Options.fIntel =
( ( 0x0003 & Button_GetState( GetDlgItem( hDlg, IDC_C_INTEL ) ) ) ==
BST_CHECKED );
g_Options.fAlpha =
( ( 0x0003 & Button_GetState( GetDlgItem( hDlg, IDC_C_ALPHA ) ) ) ==
BST_CHECKED );
}
break;
case PSN_QUERYCANCEL:
return VerifyCancel( hDlg );
break;
case PSN_SETACTIVE:
{
PostMessage( GetParent(hDlg), WMX_FORCEDREPAINT, 0, (LPARAM) GetDlgItem( hDlg, IDC_DIVIDER ) );
DWORD dwLen = Edit_GetTextLength( GetDlgItem( hDlg, IDC_E_SOURCEPATH) );
PropSheet_SetWizButtons( GetParent( hDlg ),
dwLen ? PSWIZB_BACK | PSWIZB_NEXT : PSWIZB_BACK );
ClearMessageQueue( );
}
break;
case PSN_HELP:
//
// TODO: Add help
//
break;
default:
AssertMsg( FALSE, "Unhandled PSN message" );
return FALSE;
}
break;
case WM_COMMAND:
switch( LOWORD( wParam))
{
case IDC_E_SOURCEPATH:
if ( HIWORD(wParam) != EN_CHANGE )
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
// fall thru...
case IDC_C_INTEL:
case IDC_C_ALPHA:
{
g_Options.fIntel =
( ( 0x0003 & Button_GetState( GetDlgItem( hDlg, IDC_C_INTEL ) ) ) ==
BST_CHECKED );
g_Options.fAlpha =
( ( 0x0003 & Button_GetState( GetDlgItem( hDlg, IDC_C_ALPHA ) ) ) ==
BST_CHECKED );
DWORD dwLen = Edit_GetTextLength( GetDlgItem( hDlg, IDC_E_SOURCEPATH ) );
PropSheet_SetWizButtons( GetParent( hDlg ),
( dwLen && ( g_Options.fIntel || g_Options.fAlpha )) ?
PSWIZB_BACK | PSWIZB_NEXT : PSWIZB_BACK );
}
break;
case IDC_B_BROWSE:
{
TCHAR szTitle[ SMALL_BUFFER_SIZE ];
BROWSEINFO bs;
ZeroMemory( &bs, sizeof(bs) );
bs.hwndOwner = hDlg;
dw = LoadString( g_hinstance, IDS_BROWSECAPTION_SOURCEDIR, szTitle, ARRAYSIZE( szTitle ) );
Assert( dw );
bs.lpszTitle = (LPTSTR) &szTitle;
bs.ulFlags = BIF_RETURNONLYFSDIRS | BIF_RETURNFSANCESTORS;
LPITEMIDLIST pidl = SHBrowseForFolder( &bs );
SHGetPathFromIDList( pidl, g_Options.szSourcePath );
Edit_SetText( GetDlgItem( hDlg, IDC_E_SOURCEPATH ), g_Options.szSourcePath );
}
break;
default:
break;
}
break;
case WM_CTLCOLORSTATIC:
if ( (HWND) lParam != GetDlgItem( hDlg, IDC_C_INTEL ) &&
(HWND) lParam != GetDlgItem( hDlg, IDC_C_ALPHA) )
{
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
}
return FALSE;
default:
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
}
return TRUE;
}
//
// Information dialog proc.
//
BOOL CALLBACK
InfoDlgProc(
HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
NMHDR FAR *lpnmhdr;
DWORD dw;
switch ( uMsg )
{
case WM_INITDIALOG:
{
TCHAR szText[ SMALL_BUFFER_SIZE ] = { 0 };
DWORD dwLen = 0;
if ( g_Options.fIntel )
{
dw = LoadString( g_hinstance, IDS_INTEL, szText, ARRAYSIZE( szText ) );
Assert( dw );
if ( g_Options.fAlpha )
{
dwLen = lstrlen( szText );
szText[ dwLen++ ] = TEXT(' ');
dw = LoadString( g_hinstance, IDS_AND, &szText[ dwLen ], ARRAYSIZE( szText ) - dwLen );
Assert( dw );
dwLen = lstrlen( szText );
szText[ dwLen++ ] = TEXT(' ');
}
}
if ( g_Options.fAlpha )
{
dw = LoadString( g_hinstance, IDS_ALPHA, &szText[ dwLen ], ARRAYSIZE( szText ) - dwLen );
Assert( dw );
}
SetDlgItemInt( hDlg, IDC_S_CLIENTS, 70, FALSE );
SetDlgItemText( hDlg, IDC_S_SOURCEPATH, g_Options.szSourcePath );
SetDlgItemText( hDlg, IDC_S_PLATFORM, szText );
SetDlgItemText( hDlg, IDC_S_REMOTEBOOT, g_Options.szRemoteBootPath );
}
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
case WM_NOTIFY:
lpnmhdr = (NMHDR FAR *) lParam;
switch ( lpnmhdr->code )
{
// ignore these
case PSN_KILLACTIVE:
case PSN_WIZNEXT:
case PSN_WIZBACK:
case PSN_RESET:
SetWindowLong( hDlg, DWL_MSGRESULT, FALSE );
break;
case PSN_QUERYCANCEL:
return VerifyCancel( hDlg );
break;
case PSN_SETACTIVE:
if ( g_Options.fError )
{
SetWindowLong( hDlg, DWL_MSGRESULT, -1 ); // do not show this page
}
PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_NEXT | PSWIZB_BACK);
ClearMessageQueue( );
PostMessage( GetParent(hDlg), WMX_FORCEDREPAINT, 0, (LPARAM) GetDlgItem( hDlg, IDC_DIVIDER ) );
break;
case PSN_HELP:
//
// TODO: Add help
//
break;
default:
AssertMsg( FALSE, "Unhandled PSN message" );
return FALSE;
}
break;
default:
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
}
return TRUE;
}
enum { STATE_NOTSTARTED, STATE_STARTED, STATE_DONE, STATE_ERROR };
typedef HRESULT (*PFNOPERATION)( HWND hDlg );
typedef struct {
HANDLE hChecked;
HANDLE hError;
HANDLE hArrow;
HANDLE hFontNormal;
HANDLE hFontBold;
int dwWidth;
int dwHeight;
} SETUPDLGDATA, *LPSETUPDLGDATA;
typedef struct {
UINT uState;
UINT rsrcId;
PFNOPERATION pfn;
TCHAR szText[ SMALL_BUFFER_SIZE ];
} LBITEMDATA, *LPLBITEMDATA;
LBITEMDATA items[] = {
{ STATE_NOTSTARTED, IDS_CREATINGDIRECTORYTREE, CreateDirectories, TEXT("") },
{ STATE_NOTSTARTED, IDS_COPYINGFILES, CopyFiles, TEXT("") },
{ STATE_NOTSTARTED, IDS_UPDATINGREGISTRY, ModifyRegistry, TEXT("") },
{ STATE_NOTSTARTED, IDS_STARTING_SERVICES, StartRemoteBootServices, TEXT("") },
{ STATE_NOTSTARTED, IDS_CREATINGSHARES, CreateRemoteBootShare, TEXT("") }
};
//
// Setup dialog proc.
//
BOOL CALLBACK
SetupDlgProc(
HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
static BOOL bDoneFirstPass;
LPSETUPDLGDATA psdd = (LPSETUPDLGDATA) GetWindowLong( hDlg, GWL_USERDATA );
DWORD dw;
switch ( uMsg )
{
case WM_INITDIALOG:
{
BITMAP bm;
// grab the bitmaps
psdd =
(LPSETUPDLGDATA) TraceAlloc( GMEM_FIXED, sizeof(SETUPDLGDATA) );
psdd->hChecked = LoadImage( g_hinstance,
MAKEINTRESOURCE( IDB_CHECK ),
IMAGE_BITMAP,
0, 0,
LR_DEFAULTSIZE | LR_LOADTRANSPARENT );
DebugMemoryAddHandle( psdd->hChecked );
GetObject( psdd->hChecked, sizeof(bm), &bm );
psdd->dwWidth = bm.bmWidth;
psdd->hError = LoadImage( g_hinstance,
MAKEINTRESOURCE( IDB_X ),
IMAGE_BITMAP,
0, 0,
LR_DEFAULTSIZE | LR_LOADTRANSPARENT );
DebugMemoryAddHandle( psdd->hError );
GetObject( psdd->hError, sizeof(bm), &bm );
psdd->dwWidth = ( psdd->dwWidth > bm.bmWidth ? psdd->dwWidth : bm.bmWidth );
psdd->hArrow = LoadImage( g_hinstance,
MAKEINTRESOURCE( IDB_ARROW ),
IMAGE_BITMAP,
0, 0,
LR_DEFAULTSIZE | LR_LOADTRANSPARENT );
DebugMemoryAddHandle( psdd->hArrow );
GetObject( psdd->hArrow, sizeof(bm), &bm );
psdd->dwWidth = ( psdd->dwWidth > bm.bmWidth ?
psdd->dwWidth :
bm.bmWidth );
HWND hwnd = GetDlgItem( hDlg, IDC_L_SETUP );
HFONT hFontOld = (HFONT) SendMessage( hwnd, WM_GETFONT, 0, 0);
if(hFontOld != NULL)
{
LOGFONT lf;
if ( GetObject( hFontOld, sizeof(LOGFONT), (LPSTR) &lf ) )
{
dw = LoadString( g_hinstance,
IDS_LARGEFONTNAME,
lf.lfFaceName,
LF_FACESIZE );
Assert( dw );
lf.lfWidth = 0;
lf.lfWeight = 400;
lf.lfHeight -= 4;
psdd->hFontNormal = CreateFontIndirect(&lf);
DebugMemoryAddHandle( psdd->hFontNormal );
lf.lfWeight = 700;
psdd->hFontBold = CreateFontIndirect(&lf);
DebugMemoryAddHandle( psdd->hFontBold );
}
}
HDC hDC = GetDC( NULL );
HANDLE hOldFont = SelectObject( hDC, psdd->hFontBold );
TEXTMETRIC tm;
GetTextMetrics( hDC, &tm );
psdd->dwHeight = tm.tmHeight + 2;
SelectObject( hDC, hOldFont );
ReleaseDC( NULL, hDC );
ListBox_SetItemHeight( hwnd, -1, psdd->dwHeight );
SetWindowLong( hDlg, GWL_USERDATA, (LONG) psdd );
for( int i = 0; i < ARRAYSIZE(items); i++ )
{
dw = LoadString( g_hinstance,
items[ i ].rsrcId,
items[ i ].szText,
ARRAYSIZE( items[ i ].szText ) );
Assert( dw );
ListBox_AddString( hwnd, &items[ i ] );
}
bDoneFirstPass = FALSE;
}
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
case WM_DESTROY:
{
Assert( psdd );
DeleteObject( psdd->hChecked );
DebugMemoryDelete( psdd->hChecked );
DeleteObject( psdd->hError );
DebugMemoryDelete( psdd->hError );
DeleteObject( psdd->hArrow );
DebugMemoryDelete( psdd->hArrow );
DeleteObject( psdd->hFontNormal );
DebugMemoryDelete( psdd->hFontNormal );
DeleteObject( psdd->hFontBold );
DebugMemoryDelete( psdd->hFontBold );
TraceFree( psdd );
SetWindowLong( hDlg, GWL_USERDATA, NULL );
}
break;
case WM_NOTIFY:
{
NMHDR FAR *lpnmhdr = (NMHDR FAR *) lParam;
switch ( lpnmhdr->code )
{
// ignore these
case PSN_KILLACTIVE:
case PSN_WIZNEXT:
case PSN_WIZBACK:
case PSN_RESET:
SetWindowLong( hDlg, DWL_MSGRESULT, FALSE );
break;
case PSN_QUERYCANCEL:
return VerifyCancel( hDlg );
break;
case PSN_SETACTIVE:
if ( g_Options.fError )
{
SetWindowLong( hDlg, DWL_MSGRESULT, -1 ); // do not show this page
}
PropSheet_SetWizButtons( GetParent( hDlg ), 0 );
PostMessage( GetParent(hDlg), WMX_FORCEDREPAINT, 0, (LPARAM) GetDlgItem( hDlg, IDC_DIVIDER ) );
ClearMessageQueue( );
break;
case PSN_HELP:
//
// TODO: Add help
//
break;
default:
//AssertMsg( FALSE, "Unhandled PSN message" );
return FALSE;
}
}
break;
case WM_STARTSETUP:
{
HWND hwnd = GetDlgItem( hDlg, IDC_L_SETUP );
RECT rc;
GetClientRect( hwnd, &rc );
for( int i = 0; i < ARRAYSIZE( items ) && !g_Options.fError; i++ )
{
items[ i ].uState = STATE_STARTED;
InvalidateRect( hwnd, &rc, TRUE );
items[ i ].uState = items[ i ].pfn( hDlg ) ?
STATE_ERROR : // not S_OK
STATE_DONE; // S_OK
InvalidateRect( hwnd, &rc, TRUE );
}
PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_FINISH );
}
break;
case WM_CTLCOLORLISTBOX:
// cheat by changing the message
return BaseDlgProc( hDlg, WM_CTLCOLORSTATIC, wParam, lParam );
case WM_CTLCOLORSTATIC:
if ( (HWND) lParam != GetDlgItem( hDlg, IDC_S_OPERATION ) &&
(HWND) lParam != GetDlgItem( hDlg, IDC_G_OPERATION ) )
{
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
}
return FALSE;
case WM_MEASUREITEM:
{
LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT) lParam;
RECT rc;
HWND hwnd = GetDlgItem( hDlg, IDC_L_SETUP );
GetClientRect( hwnd, &rc );
lpmis->itemWidth = rc.right - rc.left;
lpmis->itemHeight = 15;
}
break;
case WM_DRAWITEM:
{
Assert( psdd );
LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) lParam;
LPLBITEMDATA plbid = (LPLBITEMDATA) lpdis->itemData;
RECT rc = lpdis->rcItem;
HANDLE hOldFont = INVALID_HANDLE_VALUE;
rc.right = rc.bottom = psdd->dwWidth;
switch ( plbid->uState )
{
case STATE_NOTSTARTED:
hOldFont = SelectObject( lpdis->hDC, psdd->hFontNormal );
break;
case STATE_STARTED:
DrawBitmap( psdd->hArrow, lpdis, &rc );
hOldFont = SelectObject( lpdis->hDC, psdd->hFontBold );
break;
case STATE_DONE:
DrawBitmap( psdd->hChecked, lpdis, &rc );
hOldFont = SelectObject( lpdis->hDC, psdd->hFontNormal );
break;
case STATE_ERROR:
DrawBitmap( psdd->hError, lpdis, &rc );
hOldFont = SelectObject( lpdis->hDC, psdd->hFontNormal );
break;
}
rc = lpdis->rcItem;
rc.left += psdd->dwHeight;
DrawText( lpdis->hDC, plbid->szText, -1, &rc, DT_LEFT | DT_VCENTER );
if ( hOldFont != INVALID_HANDLE_VALUE )
{
SelectObject( lpdis->hDC, hOldFont );
}
if ( !bDoneFirstPass && lpdis->itemID == ARRAYSIZE( items ) - 1 )
{
// delay the message until we have painted at least once.
bDoneFirstPass = TRUE;
PostMessage( hDlg, WM_STARTSETUP, 0, 0 );
}
}
break;
default:
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
}
return TRUE;
}
//
// Finish dialog proc
//
BOOL CALLBACK
FinishDlgProc(
HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
NMHDR FAR *lpnmhdr;
DWORD dw;
switch ( uMsg )
{
case WM_NOTIFY:
lpnmhdr = (NMHDR FAR *) lParam;
switch ( lpnmhdr->code )
{
case PSN_SETACTIVE:
PostMessage( GetParent(hDlg), WMX_FORCEDREPAINT, 0, (LPARAM) GetDlgItem( hDlg, IDC_DIVIDER ) );
PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_FINISH );
ClearMessageQueue( );
if ( g_Options.fError )
{
TCHAR szText[ SMALL_BUFFER_SIZE ];
//dw = LoadString( g_hinstance, IDS_ERROR, szText, ARRAYSIZE( szText ) );
//Assert( dw );
//dw = SetWindowText( GetDlgItem( hDlg, IDC_S_FINISH ), szText );
//Assert( dw );
dw = LoadString( g_hinstance, IDS_CLOSE, szText, ARRAYSIZE( szText ) );
Assert( dw );
PropSheet_SetFinishText( GetParent( hDlg ), szText );
}
// fall thru
// ignore these
case PSN_KILLACTIVE:
case PSN_WIZFINISH:
case PSN_RESET:
SetWindowLong( hDlg, DWL_MSGRESULT, FALSE );
break;
case PSN_HELP:
//
// TODO: Add help
//
break;
default:
AssertMsg( FALSE, "Unhandled PSN message" );
return FALSE;
}
break;
default:
return BaseDlgProc( hDlg, uMsg, wParam, lParam );
}
return TRUE;
}
VOID
AdjustWatermarkBitmap(
IN HWND hdlg,
IN HDC hdc
)
{
static BOOL Adjusted = FALSE;
RECT rect;
RECT rect2;
HWND Separator;
PVOID Bits;
HBITMAP hDib;
HBITMAP hOldBitmap;
BITMAPINFO *BitmapInfo;
HDC MemDC;
int i;
BOOL b;
if(Adjusted) {
return;
}
//
// Determine whether the bitmap needs to be stretched.
// If the width is within 10 pixels and the height is within 5
// then we don't worry about stretching.
//
// Note that 0x3026 is the identifier of the bottom divider in
// the template. This is kind of slimy but it works.
//
Separator = GetDlgItem(hdlg,0x3026);
if(!Separator) {
goto c0;
}
GetClientRect(Separator,&rect2);
MapWindowPoints(Separator,hdlg,(LPPOINT)&rect2,2);
GetClientRect(hdlg,&rect);
b = TRUE;
i = rect.right - g_pbihWatermark->biWidth;
if((i < -10) || (i > 10)) {
b = FALSE;
}
i = rect2.top - g_pbihWatermark->biHeight;
if((i < -5) || (i > 5)) {
b = FALSE;
}
if(b) {
goto c0;
}
//
// Create a copy of the existing bitmap's header structure.
// We then modify the width and height and leave everything else alone.
//
BitmapInfo =
(LPBITMAPINFO) TraceAlloc(
GMEM_FIXED,
g_pbihWatermark->biSize +
(g_uWatermarkPaletteColorCount * sizeof(RGBQUAD)) );
if(!BitmapInfo) {
goto c0;
}
CopyMemory(
BitmapInfo,
g_pbihWatermark,
g_pbihWatermark->biSize + (g_uWatermarkPaletteColorCount * sizeof(RGBQUAD))
);
BitmapInfo->bmiHeader.biWidth = rect.right + 1;
BitmapInfo->bmiHeader.biHeight = rect2.top;
hDib = CreateDIBSection(NULL,BitmapInfo,DIB_RGB_COLORS,&Bits,NULL,0);
if(!hDib) {
goto c1;
}
//
// Create a "template" memory DC and select the DIB we created
// into it. Passing NULL to CreateCompatibleDC creates a DC into which
// any format bitmap can be selected. We don't want to use the dialog's
// DC because if the pixel depth of the watermark bitmap differs from
// the screen, we wouldn't be able to select the dib into the mem dc.
//
MemDC = CreateCompatibleDC(NULL);
if(!MemDC) {
goto c2;
}
hOldBitmap = (HBITMAP) SelectObject(MemDC,hDib);
if(!hOldBitmap) {
goto c3;
}
//
// Do the stretch operation from the source bitmap onto
// the dib.
//
SetStretchBltMode(MemDC,COLORONCOLOR);
i = StretchDIBits(
MemDC,
0,0,
rect.right+1,
rect2.top,
0,0,
g_pbihWatermark->biWidth,
g_pbihWatermark->biHeight,
g_pWatermarkBitmapBits,
(BITMAPINFO *)g_pbihWatermark,
DIB_RGB_COLORS,
SRCCOPY
);
if(i == GDI_ERROR) {
goto c4;
}
//
// Got everything we need, set up pointers to use new bitmap data.
//
g_pWatermarkBitmapBits = Bits;
g_pbihWatermark = (BITMAPINFOHEADER *)BitmapInfo;
b = TRUE;
c4:
SelectObject(MemDC,hOldBitmap);
c3:
DeleteDC(MemDC);
c2:
if(!b) {
DeleteObject(hDib);
}
c1:
if(!b) {
TraceFree(BitmapInfo);
}
DebugMemoryDelete(BitmapInfo); // don't track, we'll leak it on purpose.
c0:
Adjusted = TRUE;
return;
}
//
// Subclass WndProc for the wizard window.
//
// We do this so we can draw the watermark background.
//
BOOL
WizardDlgProc(
IN HWND hdlg,
IN UINT msg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
BOOL b;
static int iHeight = 0;
switch(msg) {
case WM_PALETTECHANGED:
//
// If this is our window we need to avoid selecting and realizing
// because doing so would cause an infinite loop between WM_QUERYNEWPALETTE
// and WM_PALETTECHANGED.
//
if((HWND)wParam == hdlg) {
return(FALSE);
}
//
// FALL THROUGH
//
case WM_QUERYNEWPALETTE:
{
HDC hdc;
HPALETTE pal;
hdc = GetDC( hdlg );
pal = SelectPalette( hdc, g_hWatermarkPalette, (msg == WM_PALETTECHANGED) );
RealizePalette( hdc );
InvalidateRect( hdlg, NULL, TRUE );
if( pal )
{
SelectPalette( hdc, pal, TRUE );
}
ReleaseDC( hdlg, hdc );
}
return(TRUE);
case WM_ERASEBKGND:
{
HWND CurrentPage;
AdjustWatermarkBitmap( hdlg, (HDC)wParam);
b = PaintWatermark( hdlg, (HDC)wParam, 0, 0, iHeight );
}
break;
case WMX_FORCEDREPAINT:
{
HWND hwndDivider = (HWND) lParam;
// Find where the divider is on this page
if ( hwndDivider )
{
RECT rcDivider;
GetClientRect( hwndDivider, &rcDivider );
MapWindowPoints( hwndDivider, hdlg, (POINT *)&rcDivider, 2 );
iHeight = rcDivider.top;
}
else
{
iHeight = 0;
}
InvalidateRect( hdlg, NULL, TRUE );
b = TRUE;
}
break;
default:
{
b = CallWindowProc( g_OldWizardProc, hdlg, msg, wParam, lParam );
}
break;
}
return(b);
}