windows-nt/Source/XPSP1/NT/ds/security/services/ca/certlib/progress.cpp
2020-09-26 16:20:57 +08:00

443 lines
12 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: progress.cpp
//
//--------------------------------------------------------------------------
// progress.cpp : implementation file
//
#include <pch.cpp>
#pragma hdrstop
#include "clibres.h"
#include "progress.h"
// defines
#ifdef _DEBUG
//#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
enum MYDIALOGBEHAVIORENUM
{
enumPERCENTCOMPLETEBEHAVIOR = 0,
enumPROGRESSBARWITHTIMEOUT,
};
typedef struct _PROGRESSPROC_LPARAM
{
HINSTANCE hInstance;
HWND hwndParent;
UINT iRscJobDescription;
MYDIALOGBEHAVIORENUM enumWhichBehavior;
DWORD dwTickerUpperRange;
DBBACKUPPROGRESS* pdbp;
} PROGRESSPROC_LPARAM, *PPROGRESSPROC_LPARAM;
static BOOL s_fDisableProgressDialogs = 0;
static BOOL s_fIKnow = 0;
BOOL FICanShowDialogs()
{
if (s_fIKnow != TRUE)
{
s_fIKnow = TRUE;
DWORD dwVal;
if (S_OK == myGetCertRegDWValue(
NULL,
NULL,
NULL,
L"DisableProgress",
&dwVal))
{
s_fDisableProgressDialogs = (dwVal != 0);
}
}
return ! s_fDisableProgressDialogs;
}
////////////////////////////////////////////////////////////////////////////////
// show a progress dialog
int g_iTimeoutTicks = 0;
BOOL g_fUseTimer;
INT_PTR CALLBACK dlgProcProgress(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
PPROGRESSPROC_LPARAM pLParam = NULL;
switch(uMsg)
{
case WM_INITDIALOG:
{
HWND hwndProgressBar;
pLParam = (PPROGRESSPROC_LPARAM)lParam;
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (ULONG_PTR)pLParam);
hwndProgressBar = GetDlgItem(hwndDlg, IDD_PROGRESS_BAR);
{
RECT rcParent, rcDlg, rcScreenArea;
GetWindowRect(pLParam->hwndParent, &rcParent);
GetWindowRect(hwndDlg, &rcDlg);
SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcScreenArea, NULL);
// calc centers
int xLeft = (rcParent.left + rcParent.right) / 2 - (rcDlg.right - rcDlg.left) / 2;
int yTop = (rcParent.top + rcParent.bottom) / 2 - (rcDlg.bottom - rcDlg.top) / 2;
// careful: if the dialog is outside the screen, move it inside
if (xLeft < rcScreenArea.left)
xLeft = rcScreenArea.left;
else if (xLeft + (rcDlg.right - rcDlg.left) > rcScreenArea.right)
xLeft = rcScreenArea.right - (rcDlg.right - rcDlg.left);
if (yTop < rcScreenArea.top)
yTop = rcScreenArea.top;
else if (yTop + (rcDlg.bottom - rcDlg.top) > rcScreenArea.bottom)
yTop = rcScreenArea.bottom - (rcDlg.bottom - rcDlg.top);
// map screen coordinates to child coordinates
SetWindowPos(hwndDlg, HWND_TOPMOST, xLeft, yTop, -1, -1,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
{
DWORD dwStyle;
dwStyle = GetWindowLong(hwndProgressBar, GWL_STYLE);
SetWindowLong(hwndProgressBar, GWL_STYLE, (dwStyle | PBS_SMOOTH));
}
// Set the range and increment of the progress bar.
if (pLParam->enumWhichBehavior == enumPROGRESSBARWITHTIMEOUT)
{
SendMessage(hwndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, pLParam->dwTickerUpperRange));
SendMessage(hwndProgressBar, PBM_SETSTEP, (WPARAM) 1, 0);
}
else
{
SendMessage(hwndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 300));
}
SendMessage(hwndProgressBar, PBM_SETPOS, (WPARAM)0, 0);
// set job description if specified
if (pLParam->iRscJobDescription != 0)
{
WCHAR szJobDesc[MAX_PATH];
if (0 != LoadString(
pLParam->hInstance,
pLParam->iRscJobDescription,
szJobDesc,
MAX_PATH))
SetDlgItemText(hwndDlg, IDC_JOB_DESCRIPTION, szJobDesc);
}
return 1;
}
case WM_DESTROY:
{
pLParam = (PPROGRESSPROC_LPARAM)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
if (NULL == pLParam)
break;
SetForegroundWindow(pLParam->hwndParent);
LocalFree(pLParam);
pLParam = NULL;
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, NULL);
}
case PBM_STEPIT:
{
pLParam = (PPROGRESSPROC_LPARAM)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
if (NULL == pLParam)
break;
HWND hwndProgressBar = GetDlgItem(hwndDlg, IDD_PROGRESS_BAR);
if (pLParam->enumWhichBehavior == enumPROGRESSBARWITHTIMEOUT)
SendMessage(hwndProgressBar, PBM_STEPIT, 0, 0);
else
{
DWORD wProgress = pLParam->pdbp->dwDBPercentComplete +
pLParam->pdbp->dwLogPercentComplete +
pLParam->pdbp->dwTruncateLogPercentComplete ;
DWORD wTop = (DWORD)SendMessage(hwndProgressBar,
PBM_GETRANGE,
FALSE,
NULL);
if (wProgress == wTop)
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, S_FALSE); // we're done!
return TRUE;
}
else
SendMessage(hwndProgressBar, PBM_SETPOS, wProgress, 0); // keep incrementing
}
break;
}
case PBM_SETPOS:
{
HWND hwndProgressBar = GetDlgItem(hwndDlg, IDD_PROGRESS_BAR);
LRESULT wTop = SendMessage(hwndProgressBar, PBM_GETRANGE, FALSE, NULL);
// if we're not yet at the top make it so
if (wTop != SendMessage(hwndProgressBar, PBM_GETPOS, 0, 0))
{
SendMessage(hwndProgressBar, PBM_SETPOS, (WPARAM)wTop, 0);
Sleep(400);
}
}
default:
break;
}
return 0;
}
#define PROGRESS_TICKS_PER_SEC 3
DWORD WINAPI StartTimerThread( LPVOID lpParameter )
{
if (FICanShowDialogs())
{
PPROGRESSPROC_LPARAM psParam = (PPROGRESSPROC_LPARAM)lpParameter;
HWND hwndProgressDlg = CreateDialogParam(
psParam->hInstance,
MAKEINTRESOURCE(IDD_PROGRESS_BOX),
NULL,
dlgProcProgress,
(LPARAM)lpParameter);
if (NULL == hwndProgressDlg)
return 0;
ShowWindow(hwndProgressDlg, SW_SHOW);
UpdateWindow(hwndProgressDlg);
// if not timer based, go forever
// if timer based, go while timersec is +
while ((!g_fUseTimer) ||
(g_iTimeoutTicks-- > 0))
{
SendMessage(hwndProgressDlg, PBM_STEPIT, 0, 0);
UpdateWindow(hwndProgressDlg);
Sleep(1000/PROGRESS_TICKS_PER_SEC);
}
// send "fill the indicator"
SendMessage(hwndProgressDlg, PBM_SETPOS, 0, 0);
DestroyWindow(hwndProgressDlg);
}
return 0;
}
// callable APIs: Start/End ProgressDlg
BOOL FProgressDlgRunning()
{
return (!g_fUseTimer || (g_iTimeoutTicks > 0));
}
HANDLE
StartProgressDlg(
HINSTANCE hInstance,
HWND hwndParent,
DWORD dwTickerSeconds,
DWORD dwTimeoutSeconds,
UINT iRscJobDescription)
{
HANDLE hProgressThread = NULL;
DWORD dwThread;
PPROGRESSPROC_LPARAM psParam = NULL;
INITCOMMONCONTROLSEX sCommCtrl;
sCommCtrl.dwSize = sizeof(sCommCtrl);
sCommCtrl.dwICC = ICC_PROGRESS_CLASS;
if (!InitCommonControlsEx(&sCommCtrl))
goto Ret;
g_fUseTimer = dwTimeoutSeconds != 0;
g_iTimeoutTicks = (dwTimeoutSeconds * PROGRESS_TICKS_PER_SEC);
// dialog frees this
psParam = (PPROGRESSPROC_LPARAM)LocalAlloc(LMEM_FIXED, sizeof(PROGRESSPROC_LPARAM));
if (psParam == NULL)
goto Ret;
psParam->hInstance = hInstance;
psParam->hwndParent = hwndParent;
psParam->enumWhichBehavior = enumPROGRESSBARWITHTIMEOUT;
psParam->dwTickerUpperRange = dwTickerSeconds * PROGRESS_TICKS_PER_SEC;
psParam->iRscJobDescription = iRscJobDescription;
psParam->pdbp = NULL;
hProgressThread =
CreateThread(
NULL,
0,
StartTimerThread,
(void*)psParam,
0,
&dwThread);
Ret:
if (NULL == hProgressThread)
LocalFree(psParam);
return hProgressThread;
}
void EndProgressDlg(HANDLE hProgressThread)
{
// end countdown immediately
g_iTimeoutTicks = 0;
if (!g_fUseTimer)
{
// make the controlling thread suddenly aware of the timer
g_fUseTimer = TRUE;
}
// don't return until we're certain the progress dlg is gone
while(TRUE)
{
DWORD dwExitCode;
// break on error
if (!GetExitCodeThread(hProgressThread, &dwExitCode) )
break;
// continue until goes away
if (STILL_ACTIVE != dwExitCode)
break;
Sleep(100);
}
CloseHandle(hProgressThread);
}
///////////////////////////////////////////////////////
// %age complete progress indicator
DWORD WINAPI StartPercentCompleteThread( LPVOID lpParameter )
{
if (FICanShowDialogs())
{
PPROGRESSPROC_LPARAM psParam = (PPROGRESSPROC_LPARAM)lpParameter;
HWND hwndProgressDlg = CreateDialogParam(
psParam->hInstance,
MAKEINTRESOURCE(IDD_PROGRESS_BOX),
NULL,
dlgProcProgress,
(LPARAM)lpParameter);
if (NULL == hwndProgressDlg) {GetLastError(); return 0;}
ShowWindow(hwndProgressDlg, SW_SHOW);
Sleep(0);
while (TRUE)
{
if (ERROR_SUCCESS != SendMessage(hwndProgressDlg, PBM_STEPIT, 0, 0))
break;
UpdateWindow(hwndProgressDlg);
Sleep(0);
Sleep(1000/PROGRESS_TICKS_PER_SEC);
}
// send "fill the indicator"
SendMessage(hwndProgressDlg, PBM_SETPOS, 0, 0);
DestroyWindow(hwndProgressDlg);
}
return 0;
}
HANDLE
StartPercentCompleteDlg(
HINSTANCE hInstance,
HWND hwndParent,
UINT iRscJobDescription,
DBBACKUPPROGRESS *pdbp)
{
HANDLE hProgressThread = NULL;
DWORD dwThread;
PPROGRESSPROC_LPARAM psParam = NULL;
g_fUseTimer = FALSE;
g_iTimeoutTicks = 0; // no timeout
INITCOMMONCONTROLSEX sCommCtrl;
sCommCtrl.dwSize = sizeof(sCommCtrl);
sCommCtrl.dwICC = ICC_PROGRESS_CLASS;
if (!InitCommonControlsEx(&sCommCtrl))
goto Ret;
// dialog frees this
psParam = (PPROGRESSPROC_LPARAM)LocalAlloc(LMEM_FIXED, sizeof(PROGRESSPROC_LPARAM));
if (psParam == NULL)
goto Ret;
psParam->hInstance = hInstance;
psParam->hwndParent = hwndParent;
psParam->enumWhichBehavior = enumPERCENTCOMPLETEBEHAVIOR;
psParam->dwTickerUpperRange = 300;
psParam->iRscJobDescription = iRscJobDescription;
psParam->pdbp = pdbp;
hProgressThread =
CreateThread(
NULL,
0,
StartPercentCompleteThread,
(void*)psParam,
0,
&dwThread);
Ret:
if (NULL == hProgressThread)
LocalFree(psParam);
return hProgressThread;
}
void EndPercentCompleteDlg(HANDLE hProgressThread)
{
// don't return until we're certain the progress dlg is gone
while(TRUE)
{
DWORD dwExitCode;
// break on error
if (!GetExitCodeThread(hProgressThread, &dwExitCode) )
break;
// continue until goes away
if (STILL_ACTIVE != dwExitCode)
break;
Sleep(100);
}
CloseHandle(hProgressThread);
}