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.
593 lines
19 KiB
593 lines
19 KiB
// --------------------------------------------------------------------------
|
|
// Module Name: WarningDialog.cpp
|
|
//
|
|
// Copyright (c) 2000, Microsoft Corporation
|
|
//
|
|
// Class to manage dialog presentation for warnings and errors on termination
|
|
// of bad applications.
|
|
//
|
|
// History: 2000-08-31 vtan created
|
|
// 2000-11-06 vtan moved from fusapi to fussrv
|
|
// --------------------------------------------------------------------------
|
|
|
|
#ifdef _X86_
|
|
|
|
#include "StandardHeader.h"
|
|
#include "WarningDialog.h"
|
|
|
|
#include <commctrl.h>
|
|
#include <shlwapi.h>
|
|
#include <shlwapip.h>
|
|
|
|
#include "resource.h"
|
|
|
|
#include "ContextActivation.h"
|
|
|
|
static const int TEMP_STRING_SIZE = 512;
|
|
static const int PROGRESS_TIMER_ID = 48517;
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CWarningDialog::CWarningDialog
|
|
//
|
|
// Arguments: hInstance = HINSTANCE of the hosting DLL.
|
|
// hwndParent = HWND of the parenting window/dialog.
|
|
// pszApplication = Path to the application known to be bad.
|
|
// pszUser = User of the application known to be bad.
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Constructor for CWarningDialog. This stores the static
|
|
// parameters and converts the path to a friendly display name
|
|
// using shlwapi!SHGetFileDescriptionW. If the friendly display
|
|
// name cannot be obtained the executable name is used.
|
|
//
|
|
// History: 2000-08-31 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
CWarningDialog::CWarningDialog (HINSTANCE hInstance, HWND hwndParent, const WCHAR *pszApplication, const WCHAR *pszUser) :
|
|
_hInstance(hInstance),
|
|
_hModuleComctlv6(NULL),
|
|
_hwndParent(hwndParent),
|
|
_hwnd(NULL),
|
|
_fCanShutdownApplication(false),
|
|
_uiTimerID(0),
|
|
_dwTickStart(0),
|
|
_dwTickRefresh(0),
|
|
_dwTickMaximum(0),
|
|
_pszUser(pszUser)
|
|
|
|
{
|
|
UINT uiDisplayNameCount;
|
|
WCHAR szTemp[MAX_PATH];
|
|
|
|
// Borrow winlogon's manifest. This needs to be changed to a resource
|
|
// within the server dll.
|
|
|
|
static const TCHAR s_szLogonManifest[] = TEXT("WindowsLogon.manifest");
|
|
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
if (GetSystemDirectory(szPath, ARRAYSIZE(szPath)) != 0)
|
|
{
|
|
if ((lstrlen(szPath) + sizeof('\\') + lstrlen(s_szLogonManifest)) < ARRAYSIZE(szPath))
|
|
{
|
|
lstrcat(szPath, TEXT("\\"));
|
|
lstrcat(szPath, s_szLogonManifest);
|
|
CContextActivation::Create(szPath);
|
|
}
|
|
}
|
|
|
|
uiDisplayNameCount = ARRAYSIZE(_szApplication);
|
|
|
|
// If the path is quoted then remove the quotes.
|
|
|
|
if (pszApplication[0] == L'\"')
|
|
{
|
|
int i, iStart;
|
|
|
|
iStart = i = sizeof('\"');
|
|
while ((pszApplication[i] != L'\"') && (pszApplication[i] != L'\0'))
|
|
{
|
|
++i;
|
|
}
|
|
lstrcpyW(szTemp, pszApplication + iStart);
|
|
szTemp[i - iStart] = L'\0';
|
|
}
|
|
|
|
// Otherwise just copy the path as is.
|
|
|
|
else
|
|
{
|
|
lstrcpyW(szTemp, pszApplication);
|
|
}
|
|
if (SHGetFileDescriptionW(szTemp, NULL, NULL, _szApplication, &uiDisplayNameCount) == FALSE)
|
|
{
|
|
const WCHAR *pszFileName;
|
|
|
|
pszFileName = PathFindFileNameW(szTemp);
|
|
if (pszFileName == NULL)
|
|
{
|
|
pszFileName = pszApplication;
|
|
}
|
|
(WCHAR*)lstrcpynW(_szApplication, pszFileName, ARRAYSIZE(_szApplication));
|
|
}
|
|
|
|
// Bring in comctl32.dll while the manifest is active. This will
|
|
// bring in comctlv6.dll which will register its window classes so
|
|
// the dialogs can be themed.
|
|
|
|
if (CContextActivation::HasContext())
|
|
{
|
|
CContextActivation context;
|
|
|
|
_hModuleComctlv6 = LoadLibrary(TEXT("comctl32.dll"));
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CWarningDialog::~CWarningDialog
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Destructor for CWarningDialog. Releases used resources.
|
|
//
|
|
// History: 2000-08-31 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
CWarningDialog::~CWarningDialog (void)
|
|
|
|
{
|
|
if (_hModuleComctlv6 != NULL)
|
|
{
|
|
TBOOL(FreeLibrary(_hModuleComctlv6));
|
|
_hModuleComctlv6 = NULL;
|
|
}
|
|
CContextActivation::Destroy();
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CWarningDialog::ShowPrompt
|
|
//
|
|
// Arguments: fCanShutdownApplication = Decides which dialog to show.
|
|
//
|
|
// Returns: INT_PTR
|
|
//
|
|
// Purpose: Displays the appropriate warning dialog to the user based
|
|
// on their privilege level (fCanShutdownApplication).
|
|
//
|
|
// History: 2000-08-31 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
INT_PTR CWarningDialog::ShowPrompt (bool fCanShutdownApplication)
|
|
|
|
{
|
|
CContextActivation context;
|
|
|
|
_fCanShutdownApplication = fCanShutdownApplication;
|
|
return(DialogBoxParam(_hInstance,
|
|
MAKEINTRESOURCE(fCanShutdownApplication ? IDD_BADAPP_CLOSE : IDD_BADAPP_STOP),
|
|
_hwndParent,
|
|
PromptDialogProc,
|
|
reinterpret_cast<LPARAM>(this)));
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CWarningDialog::ShowFailure
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Shows the failure to shut down the application dialog on the
|
|
// assumption that the process cannot be terminated.
|
|
//
|
|
// History: 2000-09-01 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
void CWarningDialog::ShowFailure (void)
|
|
|
|
{
|
|
WCHAR *pszTemp;
|
|
|
|
pszTemp = static_cast<TCHAR*>(LocalAlloc(LMEM_FIXED, TEMP_STRING_SIZE * 3 * sizeof(TCHAR)));
|
|
if (pszTemp != NULL)
|
|
{
|
|
WCHAR *pszText, *pszCaption;
|
|
|
|
pszText = pszTemp + TEMP_STRING_SIZE;
|
|
pszCaption = pszText + TEMP_STRING_SIZE;
|
|
if ((LoadString(_hInstance,
|
|
IDS_TERMINATEPROCESS_FAILURE,
|
|
pszTemp,
|
|
TEMP_STRING_SIZE) != 0) &&
|
|
(LoadString(_hInstance,
|
|
IDS_WARNING_CAPTION,
|
|
pszCaption,
|
|
TEMP_STRING_SIZE) != 0))
|
|
{
|
|
LPCTSTR pszArray[2];
|
|
CContextActivation context;
|
|
|
|
pszArray[0] = _szApplication;
|
|
pszArray[1] = _pszUser;
|
|
(DWORD)FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
pszTemp,
|
|
0,
|
|
0,
|
|
pszText,
|
|
TEMP_STRING_SIZE,
|
|
reinterpret_cast<va_list*>(&pszArray));
|
|
(int)MessageBox(_hwndParent, pszText, pszCaption, MB_OK | MB_ICONERROR);
|
|
}
|
|
(HLOCAL)LocalFree(pszTemp);
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CWarningDialog::ShowProgress
|
|
//
|
|
// Arguments: dwTickRefresh = Number of ticks for each refresh.
|
|
// dwTickMaximum = Number of ticks for the progress dialog.
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Initializes the comctl32 progress control and invokes the
|
|
// dialogs for the progress. It's self terminating after the
|
|
// maximum number of ticks have been reached.
|
|
//
|
|
// History: 2000-11-04 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
void CWarningDialog::ShowProgress (DWORD dwTickRefresh, DWORD dwTickMaximum)
|
|
|
|
{
|
|
CContextActivation context;
|
|
|
|
INITCOMMONCONTROLSEX iccEx;
|
|
|
|
// Init comctl32 to get the progress control.
|
|
|
|
iccEx.dwSize = sizeof(iccEx);
|
|
iccEx.dwICC = ICC_PROGRESS_CLASS;
|
|
if (InitCommonControlsEx(&iccEx) != FALSE)
|
|
{
|
|
_dwTickRefresh = dwTickRefresh;
|
|
_dwTickMaximum = dwTickMaximum;
|
|
(INT_PTR)DialogBoxParam(_hInstance,
|
|
MAKEINTRESOURCE(IDD_PROGRESS),
|
|
_hwndParent,
|
|
ProgressDialogProc,
|
|
reinterpret_cast<LPARAM>(this));
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CWarningDialog::CloseDialog
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Ends the current dialog (with IDCANCEL) if being shown. If
|
|
// there was a timing mechanism on the dialog then make sure it
|
|
// is visible for at least 2 seconds.
|
|
//
|
|
// History: 2000-11-04 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
void CWarningDialog::CloseDialog (void)
|
|
|
|
{
|
|
if (_hwnd != NULL)
|
|
{
|
|
if (_dwTickStart != 0)
|
|
{
|
|
DWORD dwTickElapsed;
|
|
|
|
dwTickElapsed = GetTickCount() - _dwTickStart;
|
|
if (dwTickElapsed < 2000)
|
|
{
|
|
Sleep(2000 - dwTickElapsed);
|
|
}
|
|
}
|
|
TBOOL(EndDialog(_hwnd, IDCANCEL));
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CWarningDialog::CenterWindow
|
|
//
|
|
// Arguments: hwnd = HWND to center.
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Centers the given (assumed top level) window on the primary
|
|
// monitor.
|
|
//
|
|
// History: 2000-08-31 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
void CWarningDialog::CenterWindow (HWND hwnd)
|
|
|
|
{
|
|
RECT rc;
|
|
|
|
TBOOL(GetWindowRect(hwnd, &rc));
|
|
rc.left = (GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2;
|
|
rc.top = (GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) / 3;
|
|
TBOOL(SetWindowPos(hwnd, HWND_TOP, rc.left, rc.top, 0, 0, SWP_NOSIZE));
|
|
TBOOL(SetForegroundWindow(hwnd));
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CWarningDialog::Handle_Prompt_WM_INITDIALOG
|
|
//
|
|
// Arguments: hwnd = HWND of the dialog.
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Initializes the strings in the text fields of the dialog. It
|
|
// uses the correct dialog for the access level.
|
|
//
|
|
// History: 2000-08-31 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
void CWarningDialog::Handle_Prompt_WM_INITDIALOG (HWND hwnd)
|
|
|
|
{
|
|
TCHAR *pszTemp1;
|
|
|
|
_hwnd = hwnd;
|
|
pszTemp1 = static_cast<TCHAR*>(LocalAlloc(LMEM_FIXED, TEMP_STRING_SIZE * 2 * sizeof(TCHAR)));
|
|
if (pszTemp1 != NULL)
|
|
{
|
|
TCHAR *pszTemp2;
|
|
LPCTSTR pszArray[5];
|
|
|
|
pszTemp2 = pszTemp1 + TEMP_STRING_SIZE;
|
|
if (_fCanShutdownApplication)
|
|
{
|
|
(UINT)GetDlgItemText(hwnd, IDC_BADAPP_CLOSE, pszTemp1, TEMP_STRING_SIZE);
|
|
pszArray[0] = pszArray[2] = pszArray[3] = pszArray[4] = _pszUser;
|
|
pszArray[1] = _szApplication;
|
|
(DWORD)FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
pszTemp1,
|
|
0,
|
|
0,
|
|
pszTemp2,
|
|
TEMP_STRING_SIZE,
|
|
reinterpret_cast<va_list*>(&pszArray));
|
|
TBOOL(SetDlgItemText(hwnd, IDC_BADAPP_CLOSE, pszTemp2));
|
|
}
|
|
else
|
|
{
|
|
(UINT)GetDlgItemText(hwnd, IDC_BADAPP_STOP, pszTemp1, TEMP_STRING_SIZE);
|
|
pszArray[0] = pszArray[2] = _pszUser;
|
|
pszArray[1] = _szApplication;
|
|
(DWORD)FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
pszTemp1,
|
|
0,
|
|
0,
|
|
pszTemp2,
|
|
TEMP_STRING_SIZE,
|
|
reinterpret_cast<va_list*>(&pszArray));
|
|
TBOOL(SetDlgItemText(hwnd, IDC_BADAPP_STOP, pszTemp2));
|
|
}
|
|
(HLOCAL)LocalFree(pszTemp1);
|
|
}
|
|
_dwTickStart = 0;
|
|
CenterWindow(hwnd);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CWarningDialog::PromptDialogProc
|
|
//
|
|
// Arguments: See the platform SDK under DlgProc.
|
|
//
|
|
// Returns: See the platform SDK under DlgProc.
|
|
//
|
|
// Purpose: Handles messages to the dialog. IDOK and IDCANCEL are treated
|
|
// as IDCANCEL when incoming. IDC_BADAPP_CLOSEPROGRAM is treated
|
|
// as IDOK back to the caller. You must tab to the button or
|
|
// click on it to get the desired effect.
|
|
//
|
|
// History: 2000-08-31 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
INT_PTR CALLBACK CWarningDialog::PromptDialogProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
INT_PTR iResult;
|
|
CWarningDialog *pThis;
|
|
|
|
pThis = reinterpret_cast<CWarningDialog*>(GetWindowLongPtr(hwnd, DWLP_USER));
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
pThis = reinterpret_cast<CWarningDialog*>(lParam);
|
|
(LONG_PTR)SetWindowLongPtr(hwnd, DWLP_USER, lParam);
|
|
pThis->Handle_Prompt_WM_INITDIALOG(hwnd);
|
|
iResult = TRUE;
|
|
break;
|
|
case WM_DESTROY:
|
|
pThis->_hwnd = NULL;
|
|
iResult = TRUE;
|
|
break;
|
|
case WM_COMMAND:
|
|
switch (wParam)
|
|
{
|
|
case IDCANCEL:
|
|
case IDOK:
|
|
TBOOL(EndDialog(hwnd, IDCANCEL));
|
|
break;
|
|
case IDC_BADAPP_CLOSEPROGRAM:
|
|
TBOOL(EndDialog(hwnd, IDOK));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
iResult = TRUE;
|
|
break;
|
|
default:
|
|
iResult = FALSE;
|
|
break;
|
|
}
|
|
return(iResult);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CWarningDialog::Handle_Progress_WM_INITDIALOG
|
|
//
|
|
// Arguments: hwnd = HWND of the dialog.
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Initializes the strings in the text fields of the dialog.
|
|
//
|
|
// History: 2000-11-04 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
void CWarningDialog::Handle_Progress_WM_INITDIALOG (HWND hwnd)
|
|
|
|
{
|
|
HWND hwndProgress;
|
|
TCHAR *pszTemp1;
|
|
|
|
_hwnd = hwnd;
|
|
pszTemp1 = static_cast<TCHAR*>(LocalAlloc(LMEM_FIXED, 2048 * sizeof(TCHAR)));
|
|
if (pszTemp1 != NULL)
|
|
{
|
|
TCHAR *pszTemp2;
|
|
LPCTSTR pszArray[2];
|
|
|
|
pszTemp2 = pszTemp1 + TEMP_STRING_SIZE;
|
|
(UINT)GetDlgItemText(hwnd, IDC_PROGRESS_CLOSE, pszTemp1, TEMP_STRING_SIZE);
|
|
pszArray[0] = _szApplication;
|
|
pszArray[1] = _pszUser;
|
|
(DWORD)FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
pszTemp1,
|
|
0,
|
|
0,
|
|
pszTemp2,
|
|
TEMP_STRING_SIZE,
|
|
reinterpret_cast<va_list*>(&pszArray));
|
|
TBOOL(SetDlgItemText(hwnd, IDC_PROGRESS_CLOSE, pszTemp2));
|
|
(HLOCAL)LocalFree(pszTemp1);
|
|
}
|
|
CenterWindow(hwnd);
|
|
hwndProgress = GetDlgItem(hwnd, IDC_PROGRESS_PROGRESSBAR);
|
|
if (hwndProgress != NULL)
|
|
{
|
|
(LRESULT)SendMessage(hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, _dwTickMaximum));
|
|
_uiTimerID = SetTimer(hwnd, PROGRESS_TIMER_ID, _dwTickRefresh, ProgressTimerProc);
|
|
_dwTickStart = GetTickCount();
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CWarningDialog::Handle_Progress_WM_DESTROY
|
|
//
|
|
// Arguments: hwnd = HWND of the dialog.
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Removes the timer from the associated progress dialog if one
|
|
// was created for the dialog.
|
|
//
|
|
// History: 2000-11-04 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
void CWarningDialog::Handle_Progress_WM_DESTROY (HWND hwnd)
|
|
|
|
{
|
|
if (_uiTimerID != 0)
|
|
{
|
|
TBOOL(KillTimer(hwnd, _uiTimerID));
|
|
_uiTimerID = 0;
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CWarningDialog::ProgressTimerProc
|
|
//
|
|
// Arguments: See the platform SDK under TimerProc.
|
|
//
|
|
// Returns: See the platform SDK under TimerProc.
|
|
//
|
|
// Purpose: Timer procedure that it called back periodically. This
|
|
// function animates the progress bar by setting it's completion
|
|
// state to the amount of time that has elapsed. The progress
|
|
// bar is based purely on time.
|
|
//
|
|
// If the time elapsed exceeds the maximum time then end the
|
|
// dialog.
|
|
//
|
|
// History: 2000-11-04 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
void CALLBACK CWarningDialog::ProgressTimerProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
|
|
|
{
|
|
UNREFERENCED_PARAMETER(uMsg);
|
|
UNREFERENCED_PARAMETER(idEvent);
|
|
|
|
HWND hwndProgress;
|
|
CWarningDialog *pThis;
|
|
|
|
pThis = reinterpret_cast<CWarningDialog*>(GetWindowLongPtr(hwnd, DWLP_USER));
|
|
hwndProgress = GetDlgItem(hwnd, IDC_PROGRESS_PROGRESSBAR);
|
|
if (hwndProgress != NULL)
|
|
{
|
|
(LRESULT)SendMessage(hwndProgress, PBM_SETPOS, dwTime - pThis->_dwTickStart, 0);
|
|
if ((dwTime - pThis->_dwTickStart) > pThis->_dwTickMaximum)
|
|
{
|
|
TBOOL(EndDialog(hwnd, IDCANCEL));
|
|
}
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CWarningDialog::ProgressDialogProc
|
|
//
|
|
// Arguments: See the platform SDK under DlgProc.
|
|
//
|
|
// Returns: See the platform SDK under DlgProc.
|
|
//
|
|
// Purpose: Handles messages for the progress dialog.
|
|
//
|
|
// History: 2000-11-04 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
INT_PTR CALLBACK CWarningDialog::ProgressDialogProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
UNREFERENCED_PARAMETER(wParam);
|
|
|
|
INT_PTR iResult;
|
|
CWarningDialog *pThis;
|
|
|
|
pThis = reinterpret_cast<CWarningDialog*>(GetWindowLongPtr(hwnd, DWLP_USER));
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
pThis = reinterpret_cast<CWarningDialog*>(lParam);
|
|
(LONG_PTR)SetWindowLongPtr(hwnd, DWLP_USER, lParam);
|
|
pThis->Handle_Progress_WM_INITDIALOG(hwnd);
|
|
iResult = TRUE;
|
|
break;
|
|
case WM_DESTROY:
|
|
pThis->Handle_Progress_WM_DESTROY(hwnd);
|
|
pThis->_hwnd = NULL;
|
|
iResult = TRUE;
|
|
break;
|
|
default:
|
|
iResult = FALSE;
|
|
break;
|
|
}
|
|
return(iResult);
|
|
}
|
|
|
|
#endif /* _X86_ */
|
|
|