windows-nt/Source/XPSP1/NT/base/ntsetup/syssetup/mainwind.c
2020-09-26 16:20:57 +08:00

524 lines
13 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
}