|
|
#include "setupp.h"
#pragma hdrstop
#include <winuserp.h>
PCWSTR szWindowClass = L"$$$SetupBackground";
//
// Window longs for background window.
//
#define XWL_BITMAP (0)
#define XWL_LOGO (XWL_BITMAP + sizeof(PVOID))
#define XWL_BANNER (XWL_LOGO + sizeof(PVOID))
#define XWL_FONT (XWL_BANNER + sizeof(PVOID))
#define WL_COUNT (4 * sizeof(PVOID))
#define POINTSIZE_WASHTEXT 24
HANDLE SetupWindowThreadHandle = NULL;
VOID SetupMakeSureFontIsAvailable() { static BOOL DoneAlready = FALSE; LONG l; HKEY hKey; DWORD i; WCHAR Name[256]; WCHAR Data[256]; DWORD s1; DWORD s2; DWORD Type; DWORD Result;
if(DoneAlready) { return; }
//
// Want MS Serif but don't know which one serife.fon, seriffg.fon, etc.
//
l = RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", 0, KEY_QUERY_VALUE, &hKey );
if(l == NO_ERROR) {
i = 0; s1 = 256; s2 = 256; while(RegEnumValueW(hKey,i,Name,&s1,NULL,&Type,(LPBYTE) Data,&s2) == NO_ERROR) {
if(Type == REG_SZ) { CharUpper(Name); if(wcsstr(Name,L"MS SERIF")) { //
// Value data is filename.
//
GetWindowsDirectory(Name,256); lstrcat(Name,L"\\FONTS\\"); lstrcat(Name,Data); if(AddFontResource(Name)) { DoneAlready = TRUE; break; } } }
i++; s1 = 256; s2 = 256; }
RegCloseKey(hKey); }
//
// One last-ditch effort
//
if(!DoneAlready) { Result = GetWindowsDirectory(Name,256); if( Result == 0) { MYASSERT(FALSE); return; } lstrcat(Name,L"\\FONTS\\SERIFE.FON"); if(AddFontResource(Name)) { DoneAlready = TRUE; } } }
LRESULT SetupBackgroundWndProc( IN HWND hwnd, IN UINT msg, IN WPARAM wParam, IN LPARAM lParam ) { LRESULT l; HBITMAP hbm; LOGFONT LogFont; HFONT hFont; HDC hdc; HDC hdcMem; PAINTSTRUCT ps; RECT rc; COLORREF crBk,crTx; BITMAP bitmap; HBITMAP hbmOld; HFONT hFontOld; WCHAR Buffer[MAX_PATH]; int OldMode; int i; PWSTR p;
switch(msg) {
case WM_CREATE: //
// Load the default background bitmap and indicate no oem logo bitmap.
//
#if 0
hbm = LoadBitmap( MyModuleHandle, (ProductType == PRODUCT_WORKSTATION) ? MAKEINTRESOURCE(IDB_BACKGROUND_WORKSTATION) : MAKEINTRESOURCE(IDB_BACKGROUND_SERVER) ); #else
GetSystemDirectory( Buffer, MAX_PATH ); pSetupConcatenatePaths(Buffer,TEXT("setup.bmp"),MAX_PATH,NULL); hbm = (HBITMAP)LoadImage(NULL,Buffer,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); #endif
SetWindowLongPtr(hwnd,XWL_BITMAP,(LONG_PTR)hbm); SetWindowLongPtr(hwnd,XWL_LOGO,0);
#if 0 // Don't show any text for now.
//
// Load default banner text.
//
LoadString(MyModuleHandle,IDS_WINNT_SETUP,Buffer,sizeof(Buffer)/sizeof(WCHAR)); SetWindowLongPtr(hwnd,XWL_BANNER,(LONG_PTR)pSetupDuplicateString(Buffer)); #endif
//
// Create font used to display text in upper left corner.
//
hdc = GetDC(hwnd); if( hdc ) { i = GetDeviceCaps(hdc,LOGPIXELSY); ReleaseDC(hwnd,hdc); SetupMakeSureFontIsAvailable(); ZeroMemory(&LogFont,sizeof(LOGFONT)); LogFont.lfHeight = -1 * (i * POINTSIZE_WASHTEXT / 72); LogFont.lfWeight = FW_DONTCARE; LogFont.lfCharSet = DEFAULT_CHARSET; LogFont.lfQuality = PROOF_QUALITY; LogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_ROMAN; lstrcpy(LogFont.lfFaceName,L"MS Serif"); hFont = CreateFontIndirect(&LogFont); SetWindowLongPtr(hwnd,XWL_FONT,(LONG_PTR)hFont); } //
// Allow window creation to continue.
//
l = 0; break;
case WM_NEWBITMAP: //
// wParam tells us which bitmap; lParam is the bitmap handle
// (or pointer to a banner string).
//
switch(wParam) {
case SetupBmBackground:
if(hbmOld = (HBITMAP)GetWindowLongPtr(hwnd,XWL_BITMAP)) { DeleteObject(hbmOld); } SetWindowLongPtr(hwnd,XWL_BITMAP,lParam); break;
case SetupBmLogo:
if(hbmOld = (HBITMAP)GetWindowLongPtr(hwnd,XWL_LOGO)) { DeleteObject(hbmOld); } SetWindowLongPtr(hwnd,XWL_LOGO,lParam); break;
case SetupBmBanner:
if(p = (PWSTR)GetWindowLongPtr(hwnd,XWL_BANNER)) { MyFree(p); } SetWindowLongPtr(hwnd,XWL_BANNER,lParam); break; }
l = 0; break;
case WM_PAINT:
#define BANNER_OFFSET_X 5
#define BANNER_OFFSET_Y 5
//
// The window class has CS_OWNDC so BeginPaint will succeed.
//
BeginPaint(hwnd,&ps); GetClientRect(hwnd,&rc);
if(hdcMem = CreateCompatibleDC(ps.hdc)) {
crBk = SetBkColor(ps.hdc,RGB(0,0,128)); crTx = SetTextColor(ps.hdc,RGB(0,0,0));
if(hbm = (HBITMAP)GetWindowLongPtr(hwnd,XWL_BITMAP)) {
if(hbmOld = SelectObject(hdcMem,hbm)) {
GetObject(hbm,sizeof(BITMAP),&bitmap);
BitBlt( ps.hdc, rc.left + (((rc.right - rc.left) - bitmap.bmWidth) / 2), rc.top + (((rc.bottom - rc.top) - bitmap.bmHeight) / 2), bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0,0, SRCCOPY );
SelectObject(hdcMem,hbmOld); } }
if(hbm = (HBITMAP)GetWindowLongPtr(hwnd,XWL_LOGO)) {
SetBkColor(ps.hdc,RGB(255,255,255)); SetTextColor(ps.hdc,RGB(0,0,0));
if(hbmOld = SelectObject(hdcMem,hbm)) {
GetObject(hbm,sizeof(BITMAP),&bitmap);
BitBlt( ps.hdc, (rc.right - bitmap.bmWidth) - BANNER_OFFSET_X, rc.top + BANNER_OFFSET_Y, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0,0, SRCCOPY );
SelectObject(hdcMem,hbmOld); } }
SetBkColor(ps.hdc,crBk); SetTextColor(ps.hdc,crTx);
DeleteDC(hdcMem); }
hFont = (HFONT)GetWindowLongPtr(hwnd,XWL_FONT); if(hFont) { hFontOld = SelectObject(ps.hdc,hFont); } else { hFontOld = NULL; }
crTx = SetTextColor(ps.hdc,RGB(255,255,255)); OldMode = SetBkMode(ps.hdc,TRANSPARENT);
if(p = (PWSTR)GetWindowLongPtr(hwnd,XWL_BANNER)) { //
// Use this API so we get CR/LF to break a line
//
rc.left += BANNER_OFFSET_X; rc.top += BANNER_OFFSET_Y; DrawText(ps.hdc,p,-1,&rc,DT_NOPREFIX); }
SetTextColor(ps.hdc,crTx); if(OldMode) { SetBkMode(ps.hdc,OldMode); }
if(hFontOld) { SelectObject(ps.hdc,hFontOld); }
EndPaint(hwnd,&ps); l = 0; break;
case WM_DESTROY:
//
// Clean up.
//
if(hbm = (HBITMAP)GetWindowLongPtr(hwnd,XWL_BITMAP)) { DeleteObject(hbm); }
if(hbm = (HBITMAP)GetWindowLongPtr(hwnd,XWL_LOGO)) { DeleteObject(hbm); }
if(hFont = (HFONT)GetWindowLongPtr(hwnd,XWL_FONT)) { DeleteObject(hFont); } TerminateBillBoard();
PostQuitMessage(0); l = 0; break;
case WM_EXIT_SETUPWINDOW: DestroyWindow(hwnd); l = 0; break;
case WM_HOTKEY: if (wParam == 0x6969) { //
// Do this to make sure we get the correct cmd.exe, not whatever
// is in our current path.
//
WCHAR Path[MAX_PATH]; WCHAR CmdLine[MAX_PATH]; ExpandEnvironmentStrings( L"%SystemRoot%\\system32\\cmd.exe", Path, MAX_PATH);
wsprintf(CmdLine, L"/c start %s", Path); InvokeExternalApplication(Path,CmdLine,NULL); } else if (wParam == 0xC2C2) { // User pressed key to make the wizard visible.
// does not stop the billboard.
if (WizardHandle) { SendMessage(WizardHandle, WMX_BBTEXT, (WPARAM)FALSE, 0); } } l = 0; break;
default: l = DefWindowProc(hwnd,msg,wParam,lParam); break; }
return(l); }
DWORD SetupWindowThread( PVOID ThreadParam ) { WNDCLASS wc; HWND hwnd; HWND hwndBB = NULL; DWORD ThreadId; MSG msg; BOOL b; WCHAR Buffer[128]; HMODULE hmodSyssetup = NULL;
//
// The thread param is actually the thread id of the main thread.
//
ThreadId = (DWORD)((DWORD_PTR)ThreadParam);
hwnd = NULL;
wc.style = CS_NOCLOSE | CS_OWNDC; wc.lpfnWndProc = SetupBackgroundWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = WL_COUNT; wc.hInstance = MyModuleHandle; wc.hIcon = LoadIcon(MyModuleHandle,MAKEINTRESOURCE(IDI_SETUP)); wc.hCursor = LoadCursor(NULL,IDC_ARROW);
//
// Background will be erased to black, which is what we want.
//
wc.hbrBackground = GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL; wc.lpszClassName = szWindowClass;
if(RegisterClass(&wc)) { // add an extra dllref that holds syssetup.dll in process for the lifetime of the
// $$$SetupBackground window.
hmodSyssetup = LoadLibrary(TEXT("syssetup.dll"));
LoadString(MyModuleHandle,IDS_WINNT_SETUP,Buffer,sizeof(Buffer)/sizeof(WCHAR)); hwnd = CreateWindow( szWindowClass, Buffer, // L"Windows NT Setup",
WS_POPUP | WS_CLIPCHILDREN, 0,0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, MyModuleHandle, 0 );
SetupWindowHandle = hwnd; if(hwnd) { ShowWindow(hwnd,SW_SHOW); //
// Make this window bottommost.
//
SetShellWindow(hwnd); RegisterHotKey(hwnd,0x6969,MOD_SHIFT,VK_F10); RegisterHotKey(hwnd,0xC2C2,MOD_SHIFT,VK_F11); } }
if (!MiniSetup) { PrepareBillBoard(hwnd);
// If we have a Billboard, assign hwnd the windows handle.
// That way all dialogs have the billboard as the parent.
// hwnd is returned by CreateSetupWindow and assinged to MainWindowHandle
hwndBB = GetBBhwnd(); if (hwndBB != NULL) hwnd = hwndBB; }
if(ThreadId != (DWORD)(-1)) { //
// Called as a thread. Need to tell the main thread
// the window handle.
//
PostThreadMessage(ThreadId,WM_MY_STATUS,0,(LPARAM)hwnd);
//
// Pump the message queue for this thread.
//
while((b = GetMessage(&msg,NULL,0,0)) && (b != (BOOL)(-1))) { DispatchMessage(&msg); } }
if (hmodSyssetup) { FreeLibraryAndExitThread(hmodSyssetup, HandleToUlong(hwnd)); } return HandleToUlong(hwnd); }
HWND CreateSetupWindow( VOID ) { HANDLE ThreadHandle; DWORD ThreadId; HWND hwnd; MSG msg;
//
// Create a thread that will in turn create and own the window.
// This way, the window is always responsive and redraws correctly
// without special processing requirements.
//
SetupWindowThreadHandle = CreateThread( NULL, 0, SetupWindowThread, LongToPtr( GetCurrentThreadId() ), 0, &ThreadId );
if(SetupWindowThreadHandle) {
//
// Wait for the thread to tell us whether it could
// create the window or not.
//
do { WaitMessage(); } while(!PeekMessage(&msg,(HWND)(-1),WM_MY_STATUS,WM_MY_STATUS,PM_REMOVE));
hwnd = (HWND)msg.lParam;
} else { //
// Unable to create the thread. Do it the old fashioned way;
// this is better than nothing and at least setup will continue.
//
hwnd = (HWND)LongToHandle( SetupWindowThread((PVOID)(-1)) ); }
return(hwnd); }
|