windows-nt/Source/XPSP1/NT/shell/osshell/accessib/accwiz/accwiz.cpp
2020-09-26 16:20:57 +08:00

653 lines
17 KiB
C++

//Copyright (c) 1997-2000 Microsoft Corporation
#include "pch.hxx" // PCH
#pragma hdrstop
#include "AccWiz.h"
#include "resource.h"
#include "pgfinish.h"
#include "pgGenric.h"
// Welcome page
#include "pgnWelCome.h"
#include "pgWelcom.h"
#include "pgWelco2.h"
// Options page
#include "pgWizOpt.h"
// Color pages
#include "pgLokPrv.h"
// Mouse pages
#include "pgMseCur.h"
#include "pgMseBut.h"
#include "pgcaret.h"
#include "pgTmeOut.h"
#include "pgSveDef.h"
#include "pgSveFil.h"
#include "pgExtras.h"
#include "LookPrev.h"
#include "Select.h"
#include "w95trace.h"
EXTERN_C BOOL WINAPI LinkWindow_RegisterClass() ;
// Declaration of the global options variable
CAccWizOptions g_Options;
HINSTANCE g_hInstDll = NULL; // DLL instance handle.
BOOL g_bHACKHACKSavedOptions = FALSE;
HANDLE g_hAccwizRunning;
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // pointer to command line
int nCmdShow // show state of window
)
{
g_hInstDll = hInstance;
SetLastError(0);
// Allow only ONE instance of the program to run.
// The mutex is automatically destroyed when Accwiz exits
g_hAccwizRunning = CreateMutex(NULL, TRUE, TEXT("AK:AccwizRunning:KHALI"));
if ( (g_hAccwizRunning == NULL) ||
(GetLastError() == ERROR_ALREADY_EXISTS) )
{
return 0;
}
// Required for Link Window OLE marshalling :AK
DBPRINTF(TEXT("Calling CoInitialize\r\n"));
if (FAILED(CoInitialize(NULL)))
return 0; // Prefix #113783 (quit if CoInitialize fails)
g_Options.InitAccWizOptions();
InitCommonControls();
// for the Link Window in finish page...
LinkWindow_RegisterClass();
VERIFY(CLookPrev::sm_Globals.Initialize()); // Make sure this has been initialized
// VERIFY(CSelection::Initialize()); // Make sure this has been initialized: chnage this!
// Get the commandline so that it works for MUI/Unicode
LPTSTR lpCmdLineW = GetCommandLine();
if ( *lpCmdLineW == TEXT('\"') ) {
/*
* Scan, and skip over, subsequent characters until
* another double-quote or a null is encountered.
*/
while ( *++lpCmdLineW && (*lpCmdLineW
!= TEXT('\"')) );
/*
* If we stopped on a double-quote (usual case), skip
* over it.
*/
if ( *lpCmdLineW == TEXT('\"') )
lpCmdLineW++;
}
else {
while (*lpCmdLineW > TEXT(' '))
lpCmdLineW++;
}
/*
* Skip past any white space preceeding the second token.
*/
while (*lpCmdLineW && (*lpCmdLineW <= TEXT(' '))) {
lpCmdLineW++;
}
if(NULL != lpCmdLineW && lstrlen(lpCmdLineW))
{
TCHAR szFileName[_MAX_PATH];
lstrcpy(szFileName, lpCmdLineW);
StrTrim(szFileName, TEXT("\"\0"));
// Load the settings file back in.
HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
// declare structs for each scheme we might encounter
WIZSCHEME_LEGACY_STRUCT(WIZSCHEME_WIN9X, schemeLegacyWin9x, COLOR_MAX_WIN9X) /* Win9x & Millen */
WIZSCHEME_LEGACY_STRUCT(WIZSCHEME_NT400, schemeLegacyNT400, COLOR_MAX_NT400) /* WinNT 4.0 */
WIZSCHEME_LEGACY_STRUCT(WIZSCHEME_NT500, schemeLegacyNT500, COLOR_MAX_NT500) /* Win2K */
WIZSCHEME_LEGACY_STRUCT(WIZSCHEME_NT401, schemeLegacyNT501, COLOR_MAX_NT501) /* WinXP */
// see if we can find the right scheme in order of ascending size
#define OLD2NEW_SCHEME(scheme) \
{ \
DWORD dwRead; \
ReadFile(hFile, (LPVOID)&scheme, sizeof(scheme), &dwRead, NULL); \
if (dwRead != scheme.m_cbSize) \
{ \
StringTableMessageBox(NULL, IDS_WIZERRORLOADINGFILETEXT, IDS_WIZERRORLOADINGFILETITLE, MB_OK); \
return 0; \
} \
WIZSCHEME_COPY_LEGACY(g_Options.m_schemePreview, scheme) \
/* legacy schemes wouldn't have theme or wallpaper set */ \
g_Options.m_schemePreview.ClearTheme(); \
g_Options.m_schemePreview.ClearWallpaper(); \
/* figure out what the legacy scheme's SelectedStyle and SelectedSize is */ \
g_Options.m_schemePreview.SetStyleNSize(); \
}
DWORD dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize == schemeLegacyWin9x.m_cbSize)
{
OLD2NEW_SCHEME(schemeLegacyWin9x)
}
else if (dwFileSize == schemeLegacyNT400.m_cbSize)
{
OLD2NEW_SCHEME(schemeLegacyNT400)
}
else if (dwFileSize == schemeLegacyNT500.m_cbSize)
{
OLD2NEW_SCHEME(schemeLegacyNT500)
}
else if (dwFileSize == schemeLegacyNT501.m_cbSize)
{
OLD2NEW_SCHEME(schemeLegacyNT501)
}
else
{
StringTableMessageBox(NULL, IDS_WIZERRORLOADINGFILETEXT, IDS_WIZERRORLOADINGFILETITLE, MB_OK);
return 0;
}
// IMPORTANT: For loaded schemes, we always want to change to the windows default font
g_Options.m_schemePreview.m_PortableNonClientMetrics.m_nFontFaces = 1;
g_bHACKHACKSavedOptions = TRUE;
g_Options.ApplyPreview();
}
else
{
StringTableMessageBox(NULL, IDS_WIZERRORLOADINGFILETEXT, IDS_WIZERRORLOADINGFILETITLE, MB_OK);
return 0;
}
}
#ifdef UNICODE
AccWiz_RunDllW(NULL, hInstance, lpCmdLineW, nCmdShow);
#else
AccWiz_RunDllA(NULL, hInstance, lpCmdLineW, nCmdShow);
#endif
return 0;
}
HRESULT
CreateAndRunWizard(
HWND hwndParent);
HRESULT
CreateAndRunWizard2(
HWND hwndParent);
HRESULT
OnProcessAttach(
HINSTANCE hInstDll);
HRESULT
OnProcessDetach(
VOID);
INT
PropSheetCallback(
HWND hwnd,
UINT uMsg,
LPARAM lParam);
VOID WINAPI AccWiz_RunDllA(HWND hwnd, HINSTANCE hInstance, LPSTR pszCmdLineA, INT nCmdShow)
{
if (NULL != pszCmdLineA)
{
LPWSTR pszCmdLineW = NULL;
INT cchCmdLine = MultiByteToWideChar(CP_ACP,
0,
pszCmdLineA,
-1,
NULL,
0);
pszCmdLineW = new WCHAR[cchCmdLine];
if (NULL != pszCmdLineW)
{
MultiByteToWideChar(CP_ACP,
0,
pszCmdLineA,
-1,
pszCmdLineW,
cchCmdLine);
AccWiz_RunDllW(hwnd, hInstance, pszCmdLineW, nCmdShow);
delete[] pszCmdLineW;
}
}
}
VOID WINAPI AccWiz_RunDllW(HWND hwnd, HINSTANCE hInstance, LPWSTR pszCmdLineW, INT nCmdShow)
{
HWND hwndParent = GetDesktopWindow();
HRESULT hResult;
if(!g_bHACKHACKSavedOptions)
hResult = CreateAndRunWizard(hwndParent);
else
hResult = CreateAndRunWizard2(hwndParent);
if(!SUCCEEDED(hResult))
{
// TODO: Put out of memory message here
_ASSERTE(FALSE);
#pragma message("Put Out of Memory message here")
}
}
const INT MAX_PAGES = 26;
HRESULT
CreateAndRunWizard(
HWND hwndParent)
{
HRESULT hResult = E_OUTOFMEMORY;
PROPSHEETPAGE psp[MAX_PAGES];
WizardPage *rgpwp[MAX_PAGES];
// Zero init the arrays
memset(&psp, 0, sizeof(psp));
memset(&rgpwp, 0, sizeof(rgpwp));
// ///////////////////////
// Create Pages Here - NOTE: Order does not matter - we'll control it with our own list
//
int nCountPages = 0;
rgpwp[nCountPages++] = new CWizWelcomePg(psp + nCountPages);
rgpwp[nCountPages++] = new CWelcomePg(psp + nCountPages);
rgpwp[nCountPages++] = new CWelcome2Pg(psp + nCountPages);
rgpwp[nCountPages++] = new CWizardOptionsPg(psp + nCountPages);
rgpwp[nCountPages++] = new CScrollBarPg(psp + nCountPages);
rgpwp[nCountPages++] = new CIconSizePg(psp + nCountPages);
// Color
rgpwp[nCountPages++] = new CLookPreviewColorPg(psp + nCountPages);
// Sound
rgpwp[nCountPages++] = new CSoundSentryPg(psp + nCountPages);
rgpwp[nCountPages++] = new CShowSoundsPg(psp + nCountPages);
// Keyboard
rgpwp[nCountPages++] = new CStickyKeysPg(psp + nCountPages);
rgpwp[nCountPages++] = new CFilterKeysPg(psp + nCountPages);
rgpwp[nCountPages++] = new CFilterKeysSettingsPg(psp + nCountPages);
rgpwp[nCountPages++] = new CToggleKeysPg(psp + nCountPages);
rgpwp[nCountPages++] = new CShowKeyboardHelpPg(psp + nCountPages);
// Mouse
rgpwp[nCountPages++] = new CMouseKeysPg(psp + nCountPages);
rgpwp[nCountPages++] = new CMouseKeysSettingsPg(psp + nCountPages);
rgpwp[nCountPages++] = new CMouseTrailsPg(psp + nCountPages);
rgpwp[nCountPages++] = new CMouseCursorPg(psp + nCountPages);
rgpwp[nCountPages++] = new CMouseButtonPg(psp + nCountPages);
rgpwp[nCountPages++] = new CMouseSpeedPg(psp + nCountPages);
rgpwp[nCountPages++] = new CCaretPg(psp + nCountPages);
// Standard Wizard pages
rgpwp[nCountPages++] = new CGenericWizPg(psp + nCountPages, IDD_WIZNOOPTIONSSELECTED, IDS_WIZNOOPTIONSSELECTEDTITLE, IDS_WIZNOOPTIONSSELECTEDSUBTITLE);
rgpwp[nCountPages++] = new CAccessTimeOutPg(psp + nCountPages);
rgpwp[nCountPages++] = new CSaveForDefaultUserPg(psp + nCountPages);
rgpwp[nCountPages++] = new CSaveToFilePg(psp + nCountPages);
rgpwp[nCountPages++] = new FinishWizPg(psp + nCountPages);
// Make sure we have the correct number of pages in our wizard
_ASSERTE(MAX_PAGES == nCountPages);
// Make sure pages were created
for (int i = 0; i < nCountPages; i++)
{
if (NULL == rgpwp[i])
break;
}
if(i<nCountPages)
{
// We didn't have enough memory to create all the pages
// Clean out allocated pages and return
for(int i=0;i<nCountPages;i++)
if(rgpwp[i])
delete rgpwp[i];
return E_OUTOFMEMORY;
}
// Create the orders for the pages to be run
DWORD rgdwMainPath[] = {
IDD_WIZNEWWELCOME,
IDD_WIZWELCOME,
IDD_WIZWELCOME2,
IDD_WIZOPTIONS,
IDD_WIZFINISH // We need this placeholder here so we get a 'NEXT' button on IDD_WIZOPTIONS
};
if(!WizardPage::sm_WizPageOrder.AddPages(0xFFFFFFFF, rgdwMainPath, ARRAYSIZE(rgdwMainPath)))
return E_OUTOFMEMORY;
/////////////////////////////////////////////
// See if we need the 16 or 256 color bitmap
BOOL bUse256ColorBmp = FALSE;
HDC hdc = GetDC(NULL);
if(hdc)
{
if(GetDeviceCaps(hdc,BITSPIXEL) >= 8)
bUse256ColorBmp = TRUE;
ReleaseDC(NULL, hdc);
}
////////////////////////////////
// Do the property sheet
PROPSHEETHEADER psh;
memset(&psh, 0, sizeof(psh));
psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_USECALLBACK | PSH_WIZARD | PSH_PROPSHEETPAGE
| PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER /*| *//*PSH_STRETCHWATERMARK*/;
psh.hwndParent = hwndParent;
psh.hInstance = g_hInstDll;
psh.pszIcon = NULL;
psh.pszCaption = NULL;
psh.nPages = MAX_PAGES;
psh.nStartPage = 54331; // We will actually set it in PropSheetCallback to rgdwMainPath[0]
// NOTE: Bug - This only works if nStartPage is non-zero
psh.ppsp = psp;
psh.pfnCallback = PropSheetCallback;
#if 0
psh.nStartPage = 0; // We will actually set it in PropSheetCallback to rgdwMainPath[0]
psh.pfnCallback = NULL;
psh.dwFlags = PSH_WIZARD | PSH_PROPSHEETPAGE;
#endif
psh.pszbmWatermark = MAKEINTRESOURCE(IDB_ACCWIZ);
psh.pszbmHeader = MAKEINTRESOURCE(IDB_ACCMARK);
#if 0 // Right now, no watermarks
psh.pszbmWatermark = bUse256ColorBmp?MAKEINTRESOURCE(IDB_WATERMARK256):MAKEINTRESOURCE(IDB_WATERMARK16);
psh.pszbmHeader = bUse256ColorBmp?MAKEINTRESOURCE(IDB_BANNER256):MAKEINTRESOURCE(IDB_BANNER16);
#endif
if (-1 != PropertySheet(&psh))
hResult = NO_ERROR;
else
hResult = E_FAIL;
// Clean up memory allocated for WizardPage's
for(i=0;i<nCountPages;i++)
if(rgpwp[i])
delete rgpwp[i];
return hResult;
}
HRESULT
CreateAndRunWizard2(
HWND hwndParent)
{
HRESULT hResult = E_OUTOFMEMORY;
PROPSHEETPAGE psp[1];
WizardPage *rgpwp[1];
// Zero init the arrays
memset(&psp, 0, sizeof(psp));
memset(&rgpwp, 0, sizeof(rgpwp));
// ///////////////////////
// Create Pages Here - NOTE: Order does not matter - we'll control it with our own list
//
int nCountPages = 0;
rgpwp[nCountPages++] = new FinishWizPg(psp + nCountPages);
// Make sure pages were created
for (int i = 0; i < nCountPages; i++)
{
if (NULL == rgpwp[i])
break;
}
if(i<nCountPages)
{
// We didn't have enough memory to create all the pages
// Clean out allocated pages and return
for(int i=0;i<nCountPages;i++)
if(rgpwp[i])
delete rgpwp[i];
return E_OUTOFMEMORY;
}
// Create the orders for the pages to be run
DWORD rgdwMainPath[] = {
IDD_WIZFINISH // We need this placeholder here so we get a 'NEXT' button on IDD_WIZOPTIONS
};
if(!WizardPage::sm_WizPageOrder.AddPages(0xFFFFFFFF, rgdwMainPath, ARRAYSIZE(rgdwMainPath)))
return E_OUTOFMEMORY;
/////////////////////////////////////////////
// See if we need the 16 or 256 color bitmap
BOOL bUse256ColorBmp = FALSE;
HDC hdc = GetDC(NULL);
if(hdc)
{
if(GetDeviceCaps(hdc,BITSPIXEL) >= 8)
bUse256ColorBmp = TRUE;
ReleaseDC(NULL, hdc);
}
////////////////////////////////
// Do the property sheet
PROPSHEETHEADER psh;
memset(&psh, 0, sizeof(psh));
psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_USECALLBACK | PSH_WIZARD | PSH_PROPSHEETPAGE
| PSH_WIZARD97 | PSH_WATERMARK |PSH_HEADER /*| *//*PSH_STRETCHWATERMARK*/;
psh.hwndParent = hwndParent;
psh.hInstance = g_hInstDll;
psh.pszIcon = NULL;
psh.pszCaption = NULL;
psh.nPages = 1;
psh.nStartPage = 54331; // We will actually set it in PropSheetCallback to rgdwMainPath[0]
// NOTE: Bug - This only works if nStartPage is non-zero
psh.ppsp = psp;
psh.pfnCallback = PropSheetCallback;
#if 0
psh.nStartPage = 0; // We will actually set it in PropSheetCallback to rgdwMainPath[0]
psh.pfnCallback = NULL;
psh.dwFlags = PSH_WIZARD | PSH_PROPSHEETPAGE;
#endif
psh.pszbmWatermark = MAKEINTRESOURCE(IDB_ACCWIZ);
psh.pszbmHeader = MAKEINTRESOURCE(IDB_ACCMARK);
#if 0 // Right now, no watermarks
psh.pszbmWatermark = bUse256ColorBmp?MAKEINTRESOURCE(IDB_WATERMARK256):MAKEINTRESOURCE(IDB_WATERMARK16);
psh.pszbmHeader = bUse256ColorBmp?MAKEINTRESOURCE(IDB_BANNER256):MAKEINTRESOURCE(IDB_BANNER16);
#endif
if (-1 != PropertySheet(&psh))
hResult = NO_ERROR;
else
hResult = E_FAIL;
// Clean up memory allocated for WizardPage's
for(i=0;i<nCountPages;i++)
if(rgpwp[i])
delete rgpwp[i];
return hResult;
}
INT
PropSheetCallback(
HWND hwnd,
UINT uMsg,
LPARAM lParam
)
{
switch(uMsg)
{
case PSCB_PRECREATE:
break;
case PSCB_INITIALIZED:
{
// Set the first page according to are global list of page orders
// PropSheet_SetCurSelByID(hwnd, WizardPage::sm_WizPageOrder.GetFirstPage());
// HACK - Set TO Options page since we added WIZWIZ page
// HACK. Remove Context Sensitive help
LONG Style = GetWindowLong(hwnd, GWL_EXSTYLE);
if(0 == Style)
{
// DbgTrace((DEBUG_ERROR, "GetWindowLong failed. WizDlgs.cpp\n"));
// DbgTraceSystemError(GetLastError());
}
if(0 == SetWindowLong(hwnd, GWL_EXSTYLE, Style & ~WS_EX_CONTEXTHELP))
{
// DbgTrace((DEBUG_ERROR, "SetWindowLong failed. WizDlgs.cpp\n"));
// DbgTraceSystemError(GetLastError());
}
#ifdef WIZWIZ
_ASSERTE(IDD_WIZWIZ == WizardPage::sm_WizPageOrder.GetFirstPage()); // Change this if we remove the wiz wiz page
PropSheet_SetCurSelByID(hwnd, IDD_WIZWELCOME);
#endif
}
break;
}
return 0;
}
// Helper functions
// Helper function
void LoadArrayFromStringTable(int nIdString, int *rgnValues, int *pnCountValues)
{
// This function load the allowed value array from the string table
// If the values are not stored in the string table, the function
// can be overridden in a derived class
// Load in allowed sizes for scroll bar from string table
_ASSERTE(nIdString); // Make sure we were passed a string
TCHAR szArray[255];
LoadString(g_hInstDll, nIdString, szArray, ARRAYSIZE(szArray));
// Assume at most MAX_DISTINCT_VALUES sizes
LPTSTR szCurrentLocation = szArray;
for(int i=0;i<MAX_DISTINCT_VALUES;i++)
{
if(!szCurrentLocation)
break;
int cFlds = _stscanf(szCurrentLocation, __TEXT("%i"), &rgnValues[i]);
_ASSERTE(cFlds);
if (!cFlds)
break; // Prefix #113775 (no more fields)
// Find the next space
// NOTE: If there are more than one spaces between characters, this will read the same entry twice
szCurrentLocation = _tcschr(++szCurrentLocation, __TEXT(' '));
}
*pnCountValues = i;
_ASSERTE(*pnCountValues);
}
// This function is prototyped in the pre-compiled header
int StringTableMessageBox(HWND hWnd, int nText, int nCaption, UINT uType)
{
TCHAR szTitle[1024];
TCHAR szText[1024];
LoadString(g_hInstDll, nCaption, szTitle, ARRAYSIZE(szTitle));
LoadString(g_hInstDll, nText, szText, ARRAYSIZE(szText));
return MessageBox(hWnd, szText, szTitle, uType);
}
void CAccWizOptions::ApplyWindowsDefault()
{
HKEY hkey;
DWORD dwDisposition;
DWORD len;
m_schemeCurrent.ApplyChanges(m_schemeWindowsDefault);
// BUG: Update the preview scheme. Else will put back the old
// color scheme if something changes
m_schemePreview = m_schemeWindowsDefault;
}