Leaked source code of windows server 2003
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.
 
 
 
 
 
 

807 lines
24 KiB

// **************************************************************************
//
// Status.C
//
// Microsoft Confidential
// Copyright (c) Microsoft Corporation 1999-2001
// All rights reserved
//
// This application implements a common status dialog for factory functions.
//
// 04/01/2001 Stephen Lodwick
// Project started
//
//
// *************************************************************************/
//
// Includes
//
#include "factoryp.h"
typedef struct _STATUSWINDOWS
{
HWND hStatusWindow;
LPSTATUSNODE lpCurrent;
struct _STATUSWINDOWS*lpNext;
} STATUSWINDOWS, *LPSTATUSWINDOWS, **LPLPSTATUSWINDOWS;
typedef struct _DIALOGPARAM
{
LPSTATUSWINDOW lpswParam;
LPSTATUSNODE lpsnParam;
HWND hStatusWindow;
HANDLE hEvent;
} DIALOGPARAM, *LPDIALOGPARAM, **LPLPDIALOGPARAM;
//
// Internal Function Prototype(s):
//
LRESULT CALLBACK StatusDlgProc(HWND, UINT, WPARAM, LPARAM);
DWORD StatusDisplayList(HWND, LPSTATUSNODE);
BOOL StatusAddWindow(HWND, LPLPSTATUSWINDOWS, LPSTATUSNODE, BOOL);
VOID StatusCreateDialogThread(LPDIALOGPARAM);
//
// Internal Define(s):
//
#define FIRST_SPACING 7 // Spacing (pixel) between the title and the first app
#define LINE_SPACING 7 // Spacing (pixel) between additional applcations
#define WM_FINISHED (WM_USER + 0x0001) // User defined message to indicate the dialog should be destroyed
#define WM_PROGRESS (WM_USER + 0x0002) // User defined message to indicate that we are progressing to the next app
/*++
Routine:
StatusAddNode
Routine Description:
This routine takes a string and adds that string onto the end of our
linked list.
Arguments:
lpszNodeText - Pointer to string of text that you would like to add to list
lplpsnHead - Pointer to a LPSTATUSNODE list
Return Value:
TRUE - Node was added to list
FALSE - If the Node was not added to list
--*/
BOOL StatusAddNode(
LPTSTR lpszNodeText, // Text that you would like to add to the current list
LPLPSTATUSNODE lplpsnHead // List that we will be adding status node to
)
{
LPSTATUSNODE lpsnTemp = NULL;
if ( lpszNodeText && *lpszNodeText == NULLCHR )
return FALSE;
// Go to the end of the list
//
while ( lplpsnHead && *lplpsnHead )
lplpsnHead=&((*lplpsnHead)->lpNext);
if ( (lpsnTemp = (LPSTATUSNODE)MALLOC(sizeof(STATUSNODE)) ) && lpszNodeText )
{
lstrcpyn(lpsnTemp->szStatusText, lpszNodeText, AS( lpsnTemp->szStatusText ) );
lpsnTemp->lpNext = NULL;
// Make sure the previous node points to the new node
//
if ( lplpsnHead )
*lplpsnHead = lpsnTemp;
return TRUE;
}
else
return FALSE;
}
/*++
Routine:
StatusIncrement
Routine Description:
This routine increments the status to the next node in the list
Arguments:
hStatusDialog - Handle of the StatusDialog
bLastResult - Result of the last node (whether it succeeded or failed)
Return Value:
TRUE - Message sent to status dialog
FALSE - Message was not sent to status dialog
--*/
BOOL StatusIncrement(
HWND hStatusDialog,
BOOL bLastResult
)
{
// We must have a valid handle to the status dialog
//
if ( IsWindow(hStatusDialog) )
{
// Send a message to the dialog proc to go to the next caption
//
SendMessage(hStatusDialog, WM_PROGRESS,(WPARAM) NULL,(LPARAM) bLastResult);
return TRUE;
}
return FALSE;
}
/*++
Routine:
StatusEndDialog
Routine Description:
This routine sends a message to a status dialog to end.
Arguments:
hStatusDialog - Handle of the StatusDialog
Return Value:
TRUE - Message sent to status dialog
FALSE - Message was not sent to status dialog
--*/
BOOL StatusEndDialog(
HWND hStatusDialog // handle to status dialog
)
{
// We must have a valid handle to the status dialog
//
if ( IsWindow(hStatusDialog) )
{
// Send a message to the dialog proc to end the dialog
//
SendMessage(hStatusDialog, WM_FINISHED,(WPARAM) NULL,(LPARAM) NULL);
return TRUE;
}
return FALSE;
}
/*++
Routine:
StatusCreateDialogThread
Routine Description:
This routine creates the dialog for the status window and processes until the window is ended.
Arguments:
lpDialog - Pointer to structure that contains information to create thread/dialog
Return Value:
None.
--*/
VOID StatusCreateDialogThread(LPDIALOGPARAM lpDialog)
{
MSG msg;
HWND hWnd;
HANDLE hEvent = lpDialog->hEvent;
hWnd = CreateDialogParam(g_hInstance, MAKEINTRESOURCE(IDD_RUN), NULL, StatusDlgProc, (LPARAM) lpDialog);
while (GetMessage(&msg, hWnd, 0, 0) != 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Event has not been been signaled, null out the hwnd and signal event
//
if ( WaitForSingleObject(hEvent, 0) == WAIT_TIMEOUT )
{
// Reset the status window handle to null, and set the event
//
lpDialog->hStatusWindow = NULL;
SetEvent(lpDialog->hEvent);
}
else
{
// Close the event handle
//
CloseHandle(hEvent);
}
}
/*++
Routine:
StatusCreateDialog
Routine Description:
Main function that creates the status dialog
Arguments:
lpswStatus - Pointer to structure that contains information about Status Window
lpsnStatus - Pointer to struction that contains head node for status labels
Return Value:
HWND - Handle to window that was created, NULL if window was not created.
--*/
HWND StatusCreateDialog(
LPSTATUSWINDOW lpswStatus, // structure that contains information about the window
LPSTATUSNODE lpsnStatus // head node for status text
)
{
DIALOGPARAM dpStatus;
DWORD dwThread;
HANDLE hThread;
HANDLE hEvent;
// Determine if we have the required structures to continue, an hInstance, and some status text
//
if ( !lpswStatus || !lpsnStatus || !lpsnStatus->szStatusText[0])
return NULL;
// Zero out memory
//
ZeroMemory(&dpStatus, sizeof(dpStatus));
// Create an event, non-signaled to determine if dialog is initialized
//
if ( hEvent = CreateEvent(NULL, TRUE, FALSE, NULL) )
{
// Need a single variable for the dialog box parameter
//
dpStatus.lpswParam = lpswStatus;
dpStatus.lpsnParam = lpsnStatus;
dpStatus.hStatusWindow = NULL;
dpStatus.hEvent = hEvent;
// Create the thread to initialize the dialog
//
if (hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) StatusCreateDialogThread, (LPVOID) &dpStatus, 0, &dwThread) )
{
MSG msg;
// Wait for the event from WM_INITDIALOG
//
WaitForSingleObject(hEvent, INFINITE);
// Close the handle to the thread
//
CloseHandle(hThread);
}
// Reset and close the event only if we failed to create window, otherwise, StatusCreateDialogThread will close handle
//
if ( !dpStatus.hStatusWindow )
CloseHandle(hEvent);
}
// Return the handle to the StatusDialog
//
return ( dpStatus.hStatusWindow );
}
/*++
Routine:
StatusDlgProc
Routine Description:
Main dialog procedure for StatusCreateDialog.
Arguments:
hWnd - Handle to window
uMsg - Message being sent to window
uParam - Upper parameter being sent
lParam - Lower parameter being sent
Return Value:
LRESULT - Result of message that was processed
--*/
LRESULT CALLBACK StatusDlgProc(HWND hWnd, UINT uMsg, WPARAM uParam, LPARAM lParam)
{
static HFONT hNormFont = NULL;
static HFONT hBoldFont = NULL;
static HANDLE hIconSuccess = NULL;
static HANDLE hIconError = NULL;
static LPSTATUSWINDOWS lpStatusWindows;
switch (uMsg)
{
case WM_INITDIALOG:
{
LPSTATUSWINDOW lpswWindow = NULL;
LPSTATUSNODE lpHead = NULL,
lpWindowHead = NULL;
HANDLE hEvent = NULL;
if ( lParam )
{
// Determine the window, and current node
//
lpswWindow = ((LPDIALOGPARAM)lParam)->lpswParam;
lpHead = ((LPDIALOGPARAM)lParam)->lpsnParam;
hEvent = ((LPDIALOGPARAM)lParam)->hEvent;
// Check to make sure that we have pointers to the required structures
//
if ( !lpswWindow || !lpHead || !hEvent)
{
PostMessage(hWnd, WM_FINISHED,(WPARAM) NULL,(LPARAM) NULL);
return FALSE;
}
// Copy the list that was passed in, to our own buffer
//
while ( lpHead )
{
StatusAddNode(lpHead->szStatusText, &lpWindowHead);
lpHead = lpHead->lpNext;
}
// Add this window to our list of windows
//
StatusAddWindow(hWnd, &lpStatusWindows, lpWindowHead, FALSE);
// Set the status window if there is one specified
//
if (lpswWindow->szWindowText[0] )
SetWindowText(hWnd, lpswWindow->szWindowText);
// Set the status window description if there is one specified.
//
if ( lpswWindow->lpszDescription )
{
SetDlgItemText(hWnd, IDC_TITLE, lpswWindow->lpszDescription);
}
// Set the status window description if there is one specified.
//
if ( lpswWindow->hMainIcon )
{
SendDlgItemMessage(hWnd, IDC_STATUS_ICON, STM_SETICON, (WPARAM) lpswWindow->hMainIcon, 0L);
}
// Display the list
//
StatusDisplayList(hWnd, lpWindowHead);
// Move the window if a position was given
//
if ( lpswWindow->X || lpswWindow->Y )
{
// See if either coordinate is relative to the other
// side of the screen.
//
if ( ( lpswWindow->X < 0 ) ||
( lpswWindow->Y < 0 ) )
{
RECT rc;
// Need to get the size of our work area on the main monitor.
//
if ( SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0) )
{
RECT rcHwnd;
POINT point;
// This code will get the current window size/position,
// set the point structure to the upper left coordinate
// for the window if we wanted the lower right part of
// window to touch the lower right part of the desktop.
//
GetWindowRect(hWnd, &rcHwnd);
point.x = rc.right - (rcHwnd.right - rcHwnd.left);
point.y = rc.bottom - (rcHwnd.bottom - rcHwnd.top);
MapWindowPoints(NULL, hWnd, &point, 1);
// Now if they passed in negative coordinates, add those
// to our point structure so the window moves away from
// the bottom or right part of the screen by the number
// of units they specifed.
//
if ( lpswWindow->X < 0 )
{
lpswWindow->X += point.x;
}
if ( lpswWindow->Y < 0 )
{
lpswWindow->Y += point.y;
}
}
}
// Now move the window.
//
SetWindowPos(hWnd, 0, lpswWindow->X, lpswWindow->Y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
// Build the new fonts
//
if(!hNormFont)
hNormFont = GetFont((HWND) GetDlgItem(hWnd, IDC_TITLE), NULL, 0, FW_NORMAL, FALSE);
if(!hBoldFont)
hBoldFont = GetFont((HWND) GetDlgItem(hWnd, IDC_TITLE), NULL, 0, FW_BOLD, FALSE);
// Bold the first item in the list
//
if ( lpWindowHead && hBoldFont)
SendMessage((HWND)lpWindowHead->hLabelWin, WM_SETFONT, (WPARAM) hBoldFont, MAKELPARAM(TRUE, 0));
// Now make sure we show the window now.
//
ShowWindow(hWnd, SW_SHOW);
((LPDIALOGPARAM)lParam)->hStatusWindow = hWnd;
// Set event stating that dialog is initialized
//
SetEvent(hEvent);
}
else
PostMessage(hWnd, WM_FINISHED,(WPARAM) NULL,(LPARAM) NULL);
}
break;
case WM_PROGRESS:
{
// Progress to the next item, if there are no items, end the dialog
//
LPSTATUSWINDOWS lpswNext = lpStatusWindows;
BOOL bFound = FALSE;
LPSTATUSNODE lpsnTemp = NULL;
// Locate the current node given a window handle
//
while ( lpswNext && !bFound)
{
if ( lpswNext->hStatusWindow == hWnd )
bFound = TRUE;
else
lpswNext = lpswNext->lpNext;
}
// If there is a current node, lets unbold it, increment and bold the next item
//
if ( bFound && lpswNext && lpswNext->lpCurrent )
{
if ( hNormFont )
SendMessage((HWND)lpswNext->lpCurrent->hLabelWin, WM_SETFONT, (WPARAM) hNormFont, MAKELPARAM(TRUE, 0));
if ( !hIconSuccess )
hIconSuccess = LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_STATUSSUCCESS), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
if ( !hIconError )
hIconError = LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_STATUSERROR), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
if ( hIconSuccess && hIconError )
SendMessage(lpswNext->lpCurrent->hIconWin,STM_SETIMAGE, (WPARAM)IMAGE_ICON, (BOOL)lParam ? (LPARAM)hIconSuccess : (LPARAM)hIconError );
// Increment to the next node in the list
//
lpsnTemp = lpswNext->lpCurrent;
lpswNext->lpCurrent = lpswNext->lpCurrent->lpNext;
// Free this memory since we allocated it
//
FREE(lpsnTemp);
// If there is not a current node, end the dialog, otherwise, bold the item
//
if ( lpswNext->lpCurrent && hBoldFont)
SendMessage(lpswNext->lpCurrent->hLabelWin, WM_SETFONT, (WPARAM) hBoldFont, MAKELPARAM(TRUE, 0));
}
}
break;
case WM_FINISHED:
{
// Destroy the dialog
//
if ( hWnd )
{
// If there are status windows, let's remove the one that we are ending
//
if ( lpStatusWindows )
StatusAddWindow(hWnd, &lpStatusWindows, NULL, TRUE);
// Check to see if there are any windows left, if not, do some clean up
//
if ( !lpStatusWindows )
{
// Delete fonts static to dlgproc
//
if (hNormFont)
{
DeleteObject(hNormFont);
hNormFont = NULL;
}
if (hBoldFont)
{
DeleteObject(hBoldFont);
hBoldFont = NULL;
}
}
// Quit and end the dialog
//
EndDialog(hWnd, 1);
}
return FALSE;
}
break;
default:
return FALSE;
}
return FALSE;
}
/*++
Routine:
StatusDisplayList
Routine Description:
Function that displays list to user interface
Arguments:
hWnd - Handle to Status window
lpsnList - List to head Status Node
Return Value:
DWORD - Number of entries that were added to the dialog
--*/
DWORD StatusDisplayList(HWND hWnd, LPSTATUSNODE lpsnList)
{
LPSTATUSNODE lpsnTempList = lpsnList;
HWND hWndLabel,
hWndIcon;
RECT Rect,
WindowRect;
POINT Point;
DWORD dwEntries = 0;
HFONT hNormFont = NULL;
LPTSTR lpTempRunName;
HDC hdc;
SIZE size = { 0, 0 };
LONG nWidestControl;
GetWindowRect(GetDlgItem(hWnd, IDC_TITLE), &Rect);
Rect.right -= Rect.left; // The width of the control.
Rect.bottom -= Rect.top; // The height of the control.
Point.x = Rect.left;
Point.y = Rect.top;
nWidestControl = Rect.right;
MapWindowPoints(NULL, hWnd, &Point, 1);
Point.y += FIRST_SPACING;
while(lpsnTempList)
{
// Calculate the point of the first label window
//
Point.y += Rect.bottom + LINE_SPACING;
// Get the size of the text in pixels
//
if (hdc = GetWindowDC(hWnd))
{
GetTextExtentPoint32(hdc, lpsnTempList->szStatusText, lstrlen(lpsnTempList->szStatusText), &size);
if (size.cx > nWidestControl)
nWidestControl = size.cx;
ReleaseDC(hWnd, hdc);
}
// Create the label window
//
hWndIcon = CreateWindow(_T("STATIC"), _T(""), WS_CHILD | WS_VISIBLE | SS_ICON | SS_CENTERIMAGE, Point.x - 16, Point.y - 2, 16, 16, hWnd, NULL, g_hInstance, NULL);
hWndLabel = CreateWindow(_T("STATIC"), _T(""), WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, Point.x, Point.y, (Rect.right > size.cx ? Rect.right : size.cx) , Rect.bottom, hWnd, NULL, g_hInstance, NULL);
// If the font is NULL, get a font
//
if ( hNormFont == NULL )
hNormFont = (HFONT) SendDlgItemMessage(hWnd, IDC_TITLE, WM_GETFONT, 0, 0L);
// Set the font to the same font as the title
//
SendMessage(hWndLabel, WM_SETFONT, (WPARAM) hNormFont, MAKELPARAM(FALSE, 0));
// Set the Window text to the name of the program
//
SetWindowText(hWndLabel, lpsnTempList->szStatusText);
// Set the hWndTemp (created from CreateWindow) in the list
//
lpsnTempList->hLabelWin = hWndLabel;
lpsnTempList->hIconWin = hWndIcon;
// Goto the next item in the list
//
lpsnTempList = lpsnTempList->lpNext;
// Increment for each of the applications in the list
//
dwEntries++;
}
GetWindowRect(hWnd, &WindowRect);
WindowRect.right = WindowRect.right - WindowRect.left + nWidestControl - Rect.right; // The width of the winodw.
WindowRect.bottom -= WindowRect.top; // The height of the window.
// Resize the dialog to fit the label text.
//
SetWindowPos(hWnd, 0, 0, 0, WindowRect.right, WindowRect.bottom + ((Rect.bottom + LINE_SPACING)*dwEntries), SWP_NOMOVE | SWP_SHOWWINDOW | SWP_NOZORDER );
return dwEntries;
}
/*++
===============================================================================
Routine Description:
StatusAddWindow
Adds a new window to the list. This function is used internally for the status
dialog.
Arguments:
hStatusWindow - Handle to Status Window
lplpswHead - Head of the Windows list
lpsnHead - Current head node for Status Window
bRemove - Indicates wheter we add or remove the window from the list
Return Value:
None
===============================================================================
--*/
BOOL StatusAddWindow(
HWND hStatusWindow, // Text that you would like to add to the current list
LPLPSTATUSWINDOWS lplpswHead, // List that we will be adding status window to
LPSTATUSNODE lpsnHead, // Head of the STATUSNODE structure
BOOL bRemove // Indicates if we are removing the window from our list
)
{
LPLPSTATUSWINDOWS lplpswNext = lplpswHead;
LPSTATUSWINDOWS lpswTemp = NULL;
LPSTATUSNODE lpsnTemp = NULL;
BOOL bFound = FALSE;
// If there is no status window we have nothing to add
//
if ( !hStatusWindow )
return FALSE;
// Attempt to find the window passed in, if not, we are at the end of the list
//
while ( *lplpswNext && !bFound)
{
if ( (*lplpswNext)->hStatusWindow == hStatusWindow )
bFound = TRUE;
else
lplpswNext=&((*lplpswNext)->lpNext);
}
// If we are adding it and we didn't find it in the list go ahead an add the new node
//
if ( !bRemove && !bFound)
{
if ( lpswTemp = (LPSTATUSWINDOWS)MALLOC(sizeof(STATUSWINDOWS)) )
{
lpswTemp->hStatusWindow = hStatusWindow;
lpswTemp->lpNext = NULL;
lpswTemp->lpCurrent = lpsnHead;
// Make sure the previous node points to the new node
//
*lplpswNext = lpswTemp;
}
else
return FALSE;
}
else if ( bRemove && bFound && *lplpswNext)
{
// If there are nodes left in for the window, lets clean them up
//
if ( (*lplpswNext)->lpCurrent )
StatusDeleteNodes((*lplpswNext)->lpCurrent);
// Free the window node
//
lpswTemp = (*lplpswNext);
(*lplpswNext) = (*lplpswNext)->lpNext;
FREE(lpswTemp);
}
else
{
return FALSE;
}
return TRUE;
}
/*++
===============================================================================
Routine Description:
VOID StatusDeleteNodes
Deletes all the Nodes in a STATUSNODE list
Arguments:
lpsnHead - current head of the list
Return Value:
None
===============================================================================
--*/
VOID StatusDeleteNodes(
LPSTATUSNODE lpsnHead
)
{
LPSTATUSNODE lpsnTemp = NULL;
while ( lpsnHead )
{
lpsnTemp = lpsnHead;
lpsnHead = lpsnHead->lpNext;
FREE(lpsnTemp);
}
}