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

858 lines
18 KiB
C

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
ntui.c
Abstract:
Processing indicator dialog shows percentage of completion
in a progress bar. The progress is updated by the caller.
Author:
Jim Schmidt (jimschm) 13-Aug-1996
Revision History:
jimschm 19-Oct-1998 Updated to use wizard status line
jimschm 23-Sep-1998 Redesigned domain account resolution
jimschm 02-Jul-1998 Finally rewrote progress bar
jimschm 18-Dec-1996 Moved to new lib, slated to be rewritten
--*/
#include "pch.h"
static PCTSTR g_LocalAccountString;
static PCTSTR g_SearchAgainString;
static HWND g_StatusPopup;
static OUR_CRITICAL_SECTION g_StatusPopupCs;
static HANDLE g_AbortDelayEvent;
static HANDLE g_DelayThread;
static BOOL g_ClassRegistered = FALSE;
static DWORD g_ThreadId;
#define WMX_SETTEXT (WM_USER+500)
#define S_STATUS_CLASS TEXT("StatusWnd")
typedef struct {
INT ConversionX;
INT ConversionY;
} CONVERSIONFACTORS, *PCONVERSIONFACTORS;
#define CONVERSION_RESOLUTION 100
VOID
pShowStatusPopup (
VOID
);
VOID
pKillDelayThread (
VOID
);
VOID
pUpdateDialog (
HWND hdlg,
PRESOLVE_ACCOUNTS_ARRAY Array,
BOOL UserList,
BOOL DomainList
)
{
HWND hwndUsers;
HWND hwndDomain;
UINT Count;
TCHAR Buf[256];
UINT Selection;
UINT Index;
UINT Item;
PCTSTR *DomainNamePtr;
PCTSTR Message;
PCTSTR ArgArray[1];
hwndUsers = GetDlgItem (hdlg, IDC_USER_LIST);
hwndDomain = GetDlgItem (hdlg, IDC_DOMAIN_LIST);
if (UserList) {
//
// Populate the list box with <user> logs onto <domain>
//
Selection = SendMessage (hwndUsers, LB_GETCURSEL, 0, 0);
if (Selection == LB_ERR) {
Selection = 0;
}
SendMessage (hwndUsers, LB_RESETCONTENT, 0, 0);
for (Count = 0 ; Array[Count].UserName ; Count++) {
if (Array[Count].RetryFlag) {
wsprintf (
Buf, TEXT("%s\t%s"),
Array[Count].UserName,
g_SearchAgainString
);
} else {
wsprintf (
Buf, TEXT("%s\t%s"),
Array[Count].UserName,
Array[Count].OutboundDomain ? Array[Count].OutboundDomain : g_LocalAccountString
);
}
Item = SendMessage (hwndUsers, LB_ADDSTRING, 0, (LPARAM) Buf);
SendMessage (hwndUsers, LB_SETITEMDATA, Item, Count);
}
SendMessage (hwndUsers, LB_SETCURSEL, Selection, 0);
}
if (DomainList) {
//
// Get the current user selection
//
Selection = SendMessage (hwndUsers, LB_GETCURSEL, 0, 0);
if (Selection == LB_ERR) {
Selection = 0;
}
Index = SendMessage (hwndUsers, LB_GETITEMDATA, Selection, 0);
//
// Fill the combo box
//
SendMessage (hwndDomain, CB_RESETCONTENT, 0, 0);
DomainNamePtr = Array[Index].DomainArray;
// Insert all domain names
while (*DomainNamePtr) {
Item = SendMessage (hwndDomain, CB_ADDSTRING, 0, (LPARAM) (*DomainNamePtr));
SendMessage (hwndDomain, CB_SETITEMDATA, Item, (LPARAM) (*DomainNamePtr));
DomainNamePtr++;
}
// Insert standard strings
Item = SendMessage (hwndDomain, CB_ADDSTRING, 0, (LPARAM) g_LocalAccountString);
SendMessage (hwndDomain, CB_SETITEMDATA, Item, (LPARAM) g_LocalAccountString);
Item = SendMessage (hwndDomain, CB_ADDSTRING, 0, (LPARAM) g_SearchAgainString);
SendMessage (hwndDomain, CB_SETITEMDATA, Item, (LPARAM) g_SearchAgainString);
// Restore selection
if (Array[Index].RetryFlag) {
Item = SendMessage (hwndDomain, CB_FINDSTRINGEXACT, 0, (LPARAM) g_SearchAgainString);
SendMessage (hwndDomain, CB_SETCURSEL, Item, 0);
} else if (Array[Index].OutboundDomain) {
Item = SendMessage (hwndDomain, CB_FINDSTRINGEXACT, 0, (LPARAM) (Array[Index].OutboundDomain));
SendMessage (hwndDomain, CB_SETCURSEL, Item, 0);
} else {
Item = SendMessage (hwndDomain, CB_FINDSTRINGEXACT, 0, (LPARAM) g_LocalAccountString);
SendMessage (hwndDomain, CB_SETCURSEL, Item, 0);
}
ArgArray[0] = Array[Index].UserName;
Message = ParseMessageID (MSG_USER_DOMAIN_LOGON_DLG, ArgArray);
SetDlgItemText (hdlg, IDC_DOMAIN_LIST_TITLE, Message);
FreeStringResource (Message);
}
}
VOID
pInitConversionFactors (
IN HWND hdlg,
OUT PCONVERSIONFACTORS Factors
)
{
RECT rect;
rect.left = 0;
rect.right = CONVERSION_RESOLUTION;
rect.top = 0;
rect.bottom = CONVERSION_RESOLUTION;
MapDialogRect (hdlg, &rect);
Factors->ConversionX = rect.right - rect.left;
Factors->ConversionY = rect.bottom - rect.top;
}
INT
pConvertPixelsToDialogX (
IN PCONVERSIONFACTORS Factors,
IN INT Pixels
)
{
return CONVERSION_RESOLUTION * Pixels / Factors->ConversionX;
}
INT
pConvertPixelsToDialogY (
IN PCONVERSIONFACTORS Factors,
IN INT Pixels
)
{
return CONVERSION_RESOLUTION * Pixels / Factors->ConversionY;
}
BOOL
CALLBACK
pResolveAccountsDlgProc (
HWND hdlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
/*++
Routine Description:
pResolveAccountsDlgProc prompts the user with a list of domain choices,
the local machine, or retry the network search.
Upon init, the lParam specifies the RESULT_ACCOUNTS_ARRAY pointer that
provides the user list and initial state. Upon exit, the array is
updated to reflect the user's choices.
Arguments:
hdlg - The dialog handle
uMsg - The message to process
wParam - The wParam for the message
lParam - The lParam for the message
Return value:
The dialog always ends with IDOK.
--*/
{
static PRESOLVE_ACCOUNTS_ARRAY Array;
static CONVERSIONFACTORS Factors;
RECT rect;
INT Tabs;
UINT Selection;
UINT Index;
HWND hwndList;
PCTSTR NewDomain;
switch (uMsg) {
case WM_INITDIALOG:
CenterWindow (hdlg, GetDesktopWindow());
Array = (PRESOLVE_ACCOUNTS_ARRAY) lParam;
MYASSERT (Array);
pInitConversionFactors (hdlg, &Factors);
//
// Get the strings
//
g_LocalAccountString = GetStringResource (MSG_LOCAL_ACCOUNT_DLG);
g_SearchAgainString = GetStringResource (MSG_DOMAIN_NOT_LISTED_DLG);
//
// Set the tab stops
//
GetWindowRect (GetDlgItem (hdlg, IDC_USER_TITLE), &rect);
Tabs = pConvertPixelsToDialogX (&Factors, (rect.right - rect.left) + 8);
SendMessage (GetDlgItem (hdlg, IDC_USER_LIST), LB_SETTABSTOPS, 1, (LPARAM) &Tabs);
//
// Clear the retry flag
//
for (Index = 0 ; Array[Index].UserName ; Index++) {
Array[Index].RetryFlag = FALSE;
}
//
// Fill the controls
//
pUpdateDialog (hdlg, Array, TRUE, TRUE);
return TRUE;
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDOK:
FreeStringResource (g_LocalAccountString);
g_LocalAccountString = NULL;
FreeStringResource (g_SearchAgainString);
g_SearchAgainString = NULL;
EndDialog (hdlg, IDOK);
return TRUE;
case IDC_USER_LIST:
if (HIWORD (wParam) == LBN_SELCHANGE) {
pUpdateDialog (hdlg, Array, FALSE, TRUE);
}
return TRUE;
case IDC_DOMAIN_LIST:
if (HIWORD (wParam) == CBN_SELCHANGE) {
hwndList = GetDlgItem (hdlg, IDC_USER_LIST);
Selection = SendMessage (hwndList, LB_GETCURSEL, 0, 0);
Index = SendMessage (hwndList, LB_GETITEMDATA, Selection, 0);
hwndList = GetDlgItem (hdlg, IDC_DOMAIN_LIST);
Selection = SendMessage (hwndList, CB_GETCURSEL, 0, 0);
NewDomain = (PCTSTR) SendMessage (hwndList, CB_GETITEMDATA, Selection, 0);
if (NewDomain == g_LocalAccountString) {
Array[Index].OutboundDomain = NULL;
Array[Index].RetryFlag = FALSE;
} else if (NewDomain == g_SearchAgainString) {
Array[Index].OutboundDomain = NULL;
Array[Index].RetryFlag = TRUE;
} else {
Array[Index].OutboundDomain = NewDomain;
Array[Index].RetryFlag = FALSE;
}
pUpdateDialog (hdlg, Array, TRUE, FALSE);
}
}
break;
}
return FALSE;
}
BOOL
CALLBACK
NetworkDownDlgProc (
HWND hdlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
/*++
Routine Description:
NetworkDownDlgProc asks the user if they want to:
(A) Continue searching with retry prompts
(B) Continue searching, skipping down domains
(C) Stop searching
Arguments:
hdlg - The dialog handle
uMsg - The message to process
wParam - The wParam for the message
lParam - The lParam for the message
Return value:
The call to DialogBox returns:
IDC_STOP - Stop searching
IDC_RETRY - Continue with retry
IDC_NO_RETRY - Continue without retry
--*/
{
switch (uMsg) {
case WM_INITDIALOG:
CenterWindow (hdlg, GetDesktopWindow());
CheckDlgButton (hdlg, IDC_RETRY, TRUE);
return TRUE;
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDOK:
if (IsDlgButtonChecked (hdlg, IDC_RETRY)) {
EndDialog (hdlg, IDC_RETRY);
} else if (IsDlgButtonChecked (hdlg, IDC_NO_RETRY)) {
EndDialog (hdlg, IDC_NO_RETRY);
} else if (IsDlgButtonChecked (hdlg, IDC_STOP)) {
EndDialog (hdlg, IDC_STOP);
}
return TRUE;
}
break;
}
return FALSE;
}
VOID
ResolveAccounts (
PRESOLVE_ACCOUNTS_ARRAY Array
)
{
DialogBoxParam (
g_hInst,
MAKEINTRESOURCE (IDD_CHOOSE_DOMAIN),
g_ParentWnd,
pResolveAccountsDlgProc,
(LPARAM) Array
);
}
LRESULT
CALLBACK
pStatusWndProc (
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
RECT Desktop;
RECT Client;
INT Top, Left;
INT Width, Height;
INT TextWidth, TextHeight;
static HWND StatusText;
PCTSTR InitialMsg;
TEXTMETRIC tm;
HDC hdc;
switch (uMsg) {
case WM_CREATE:
g_StatusPopup = hwnd;
InitialMsg = GetStringResource (MSG_INITIAL_STATUS_MSG);
MYASSERT (InitialMsg);
//
// Compute proper size
//
GetWindowRect (GetDesktopWindow(), &Desktop);
hdc = CreateDC (TEXT("DISPLAY"), NULL, NULL, NULL);
SelectObject (hdc, GetStockObject (DEFAULT_GUI_FONT));
GetTextMetrics (hdc, &tm);
DeleteDC (hdc);
Width = (Desktop.right - Desktop.left) / 2;
Height = (Desktop.bottom - Desktop.top) / 20;
TextWidth = tm.tmAveCharWidth * 3 * CharCount (InitialMsg);
TextHeight = tm.tmHeight * 3;
Width = min (Width, TextWidth);
Height = min (Height, TextHeight);
Top = Desktop.bottom - Height - tm.tmAveCharWidth;
Left = Desktop.right - Width - tm.tmHeight;
SetWindowPos (hwnd, HWND_TOPMOST, Left, Top, Width, Height, SWP_NOACTIVATE);
//
// Create text window
//
GetClientRect (hwnd, &Client);
Width = (Client.right - Client.left) * 7 / 8;
Height = (Client.bottom - Client.top) * 7 / 8;
Top = (Client.right - Client.left) / 16;
Left = (Client.bottom - Client.top) / 16;
StatusText = CreateWindow (
TEXT("STATIC"),
InitialMsg,
WS_CHILD|WS_VISIBLE|SS_NOPREFIX|SS_CENTERIMAGE,
Top, Left,
Width, Height,
hwnd,
(PVOID) 100,
g_hInst,
NULL
);
SendMessage (StatusText, WM_SETFONT, (WPARAM) GetStockObject (DEFAULT_GUI_FONT), 0);
//
// Make window initially hidden
//
HideStatusPopup (STATUS_DELAY);
FreeStringResource (InitialMsg);
return TRUE;
case WMX_SETTEXT:
SetWindowText (StatusText, (PCTSTR) lParam);
break;
case WM_DESTROY:
if (StatusText) {
DestroyWindow (StatusText);
StatusText = NULL;
}
break;
}
return DefWindowProc (hwnd, uMsg, wParam, lParam);
}
DWORD
WINAPI
pStatusDlgThread (
PVOID Arg
)
{
WNDCLASS wc;
HWND hwnd;
MSG msg;
if (!g_ClassRegistered) {
ZeroMemory (&wc, sizeof (wc));
wc.lpfnWndProc = pStatusWndProc;
wc.hInstance = g_hInst;
wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
wc.lpszClassName = S_STATUS_CLASS;
RegisterClass (&wc);
g_ClassRegistered = TRUE;
}
hwnd = CreateWindowEx (
0,
S_STATUS_CLASS,
TEXT(""),
WS_POPUP|WS_BORDER|WS_THICKFRAME,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
g_ParentWnd,
NULL,
g_hInst,
NULL
);
while (GetMessage (&msg, NULL, 0, 0)) {
if (msg.hwnd == NULL) {
if (msg.message == WM_CLOSE) {
break;
}
}
TranslateMessage (&msg);
DispatchMessage (&msg);
}
DestroyWindow (g_StatusPopup);
g_StatusPopup = NULL;
return 0;
}
VOID
CreateStatusPopup (
VOID
)
{
HWND Child;
PCTSTR InitialMsg;
g_StatusPopup = GetDlgItem (g_ParentWnd, IDC_PROGRESS_BAR_LABEL);
if (!g_StatusPopup) {
//
// Scan all children for IDC_PROGRESS_BAR_LABEL
//
Child = GetWindow (g_ParentWnd, GW_CHILD);
while (Child) {
g_StatusPopup = GetDlgItem (Child, IDC_PROGRESS_BAR_LABEL);
if (g_StatusPopup) {
break;
}
Child = GetWindow (Child, GW_HWNDNEXT);
}
}
MYASSERT (g_StatusPopup);
HideStatusPopup (STATUS_DELAY);
InitialMsg = GetStringResource (MSG_INITIAL_STATUS_MSG);
if (InitialMsg) {
SetWindowText (g_StatusPopup, InitialMsg);
FreeStringResource (InitialMsg);
}
#if 0
HANDLE Thread;
InitializeOurCriticalSection (&g_StatusPopupCs);
Thread = CreateThread (
NULL,
0,
pStatusDlgThread,
NULL,
0,
&g_ThreadId
);
MYASSERT (Thread);
CloseHandle (Thread);
#endif
}
VOID
DestroyStatusPopup (
VOID
)
{
pKillDelayThread();
EnterOurCriticalSection (&g_StatusPopupCs);
if (g_StatusPopup) {
ShowWindow (g_StatusPopup, SW_HIDE);
//PostThreadMessage (g_ThreadId, WM_CLOSE, 0, 0);
}
if (g_AbortDelayEvent) {
CloseHandle (g_AbortDelayEvent);
g_AbortDelayEvent = NULL;
}
LeaveOurCriticalSection (&g_StatusPopupCs);
DeleteOurCriticalSection (&g_StatusPopupCs);
}
VOID
UpdateStatusPopup (
PCTSTR NewMessage
)
{
EnterOurCriticalSection (&g_StatusPopupCs);
if (g_StatusPopup) {
SetWindowText (g_StatusPopup, NewMessage);
#if 0
SendMessage (g_StatusPopup, WMX_SETTEXT, 0, (LPARAM) NewMessage);
#endif
}
LeaveOurCriticalSection (&g_StatusPopupCs);
}
DWORD
WINAPI
pDelayThenShowStatus (
PVOID Arg
)
{
DWORD Result;
Result = WaitForSingleObject (g_AbortDelayEvent, (UINT) Arg);
if (WAIT_TIMEOUT == Result) {
EnterOurCriticalSection (&g_StatusPopupCs);
pShowStatusPopup();
LeaveOurCriticalSection (&g_StatusPopupCs);
}
EnterOurCriticalSection (&g_StatusPopupCs);
if (g_AbortDelayEvent) {
CloseHandle (g_AbortDelayEvent);
g_AbortDelayEvent = NULL;
}
LeaveOurCriticalSection (&g_StatusPopupCs);
return 0;
}
VOID
pKillDelayThread (
VOID
)
{
//
// This routine makes sure the delay thread is stopped,
// that the thread handle is closed, and that the show event
// is cleaned up.
//
// There is no affect on the visibility of the status dialog.
//
if (!g_DelayThread) {
return;
}
EnterOurCriticalSection (&g_StatusPopupCs);
if (g_AbortDelayEvent) {
SetEvent (g_AbortDelayEvent);
}
LeaveOurCriticalSection (&g_StatusPopupCs);
WaitForSingleObject (g_DelayThread, INFINITE);
EnterOurCriticalSection (&g_StatusPopupCs);
CloseHandle (g_DelayThread);
g_DelayThread = NULL;
LeaveOurCriticalSection (&g_StatusPopupCs);
}
VOID
HideStatusPopup (
UINT Timeout
)
{
pKillDelayThread();
EnterOurCriticalSection (&g_StatusPopupCs);
ShowWindow (g_StatusPopup, SW_HIDE);
if (Timeout != INFINITE) {
MYASSERT (!g_DelayThread);
MYASSERT (!g_AbortDelayEvent);
g_AbortDelayEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
g_DelayThread = StartThread (pDelayThenShowStatus, (PVOID) Timeout);
}
LeaveOurCriticalSection (&g_StatusPopupCs);
}
VOID
pShowStatusPopup (
VOID
)
{
//
// Caller handles mutex
//
if (g_StatusPopup) {
ShowWindow (g_StatusPopup, SW_SHOW);
UpdateWindow (g_StatusPopup);
}
#if 0
if (g_StatusPopup) {
SetWindowPos (
g_StatusPopup,
HWND_TOPMOST,
0, 0, 0, 0,
SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE
);
UpdateWindow (g_StatusPopup);
}
#endif
}
VOID
ShowStatusPopup (
VOID
)
{
pKillDelayThread();
EnterOurCriticalSection (&g_StatusPopupCs);
pShowStatusPopup();
LeaveOurCriticalSection (&g_StatusPopupCs);
}
BOOL
IsStatusPopupVisible (
VOID
)
{
BOOL b;
EnterOurCriticalSection (&g_StatusPopupCs);
b = IsWindowVisible (g_StatusPopup);
LeaveOurCriticalSection (&g_StatusPopupCs);
return b;
}