mirror of https://github.com/lianthony/NT4.0
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.
1626 lines
44 KiB
1626 lines
44 KiB
/*++
|
|
|
|
Copyright (c) 1994-1995, Microsoft Corporation All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
regdlg.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the region property sheet for the Regional
|
|
Settings applet.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
|
|
//
|
|
// Include Files.
|
|
//
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
|
|
#include "intl.h"
|
|
#include <windowsx.h>
|
|
#include <tchar.h>
|
|
#include <stdlib.h>
|
|
#include <setupapi.h>
|
|
#include <syssetup.h>
|
|
#include <winuserp.h>
|
|
#include "mapctl.h"
|
|
#include "intlhlp.h"
|
|
#include "maxvals.h"
|
|
#include "locdlg.h"
|
|
|
|
|
|
|
|
|
|
//
|
|
// Context Help Ids.
|
|
//
|
|
|
|
static int aRegionHelpIds[] =
|
|
{
|
|
IDC_SAMPLELBL1, NO_HELP,
|
|
IDC_LOCALE, IDH_INTL_LOCALE,
|
|
IDC_DEFAULT_LOCALE, IDH_INTL_SYSTEM_DEFAULT,
|
|
// IDC_MAPCTL, IDH_INTL_BITMAP,
|
|
IDC_MAPCTL, NO_HELP,
|
|
|
|
0, 0
|
|
};
|
|
|
|
|
|
|
|
|
|
//
|
|
// Constant Declarations.
|
|
//
|
|
|
|
#define RMI_PRIMARY (0x1) // this one should win in event of conflict
|
|
|
|
#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
|
|
|
|
|
|
|
|
|
|
//
|
|
// Global Variables.
|
|
//
|
|
|
|
static const TCHAR c_szInstalledLocales[] =
|
|
TEXT("System\\CurrentControlSet\\Control\\Nls\\Language");
|
|
|
|
static const TCHAR c_szCPanelIntl[] =
|
|
TEXT("Control Panel\\International");
|
|
|
|
static const TCHAR c_szRegMapIdPath[] =
|
|
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Nls\\LocaleMapIDs");
|
|
|
|
|
|
|
|
|
|
//
|
|
// Typedef Declarations.
|
|
//
|
|
|
|
typedef struct
|
|
{
|
|
int sea; // color table index for sea in this region
|
|
int land; // color table index for land in this region
|
|
int left; // this region's leftmost point on map
|
|
int width; // this region's width on map
|
|
int combosel; // index of the combobox entry for this region
|
|
UINT flags;
|
|
|
|
} REGMAPINFO;
|
|
|
|
typedef struct
|
|
{
|
|
REGMAPINFO *info;
|
|
REGMAPINFO *lookup[MAPCTL_MAX_INDICES];
|
|
|
|
} REGMAPSTATE;
|
|
|
|
typedef struct
|
|
{
|
|
LPARAM Changes;
|
|
REGMAPSTATE mapstate;
|
|
DWORD dwCurLocale; // index of current locale setting in combo box
|
|
UINT SysDefault; // setting of system default locale check box
|
|
BOOL Admin_Privileges;
|
|
|
|
} REGDLGDATA;
|
|
|
|
typedef struct
|
|
{
|
|
HWND hDisplay;
|
|
HWND hHidden;
|
|
|
|
} SLLVPARAMS;
|
|
|
|
|
|
|
|
|
|
//
|
|
// Function Prototypes.
|
|
//
|
|
|
|
void
|
|
ParseMapInfo(
|
|
REGMAPINFO *info,
|
|
LPCTSTR mapid);
|
|
|
|
void
|
|
AssociateMapInfo(
|
|
REGMAPINFO **lookup,
|
|
REGMAPINFO *src,
|
|
LPCTSTR lcid,
|
|
HWND box);
|
|
|
|
BOOL
|
|
LoadMapInfo(
|
|
REGMAPSTATE *state,
|
|
HWND combo,
|
|
HWND map);
|
|
|
|
void
|
|
FreeMapInfo(
|
|
REGMAPSTATE *state,
|
|
HWND combo);
|
|
|
|
void
|
|
HighlightSection(
|
|
HWND map,
|
|
REGMAPINFO *info,
|
|
int highlight);
|
|
|
|
void
|
|
ChangeSectionHighlight(
|
|
HWND page,
|
|
REGMAPSTATE *state,
|
|
REGMAPINFO *info);
|
|
|
|
void
|
|
HotTrackSection(
|
|
HWND page,
|
|
REGDLGDATA *dlgdata,
|
|
int index);
|
|
|
|
VOID
|
|
RebootTheSystem(VOID);
|
|
|
|
BOOL
|
|
Region_InstallKeyboardLayout(
|
|
HWND hwnd,
|
|
LCID Locale,
|
|
LPTSTR pszLocale,
|
|
BOOL bAdmin);
|
|
|
|
BOOL
|
|
Region_SetupKeyboardLayout(
|
|
HWND hwnd,
|
|
LCID Locale);
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Set_Locale_List_Values
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Set_Locale_List_Values(
|
|
LPTSTR lpValueString,
|
|
SLLVPARAMS *init)
|
|
{
|
|
static SLLVPARAMS *sllv = NULL;
|
|
DWORD Locale_Value;
|
|
LONG Position;
|
|
TCHAR szBuf[SIZE_300];
|
|
TCHAR *EndPtr;
|
|
|
|
if (!lpValueString)
|
|
{
|
|
sllv = init;
|
|
}
|
|
else if (sllv)
|
|
{
|
|
//
|
|
// Retrieve the locale string associated with the string parameter
|
|
// from GetLocalInfo on LOCALE_SLANGUAGE and add this new String
|
|
// value to the list box.
|
|
//
|
|
EndPtr = &lpValueString[lstrlen(lpValueString)];
|
|
Locale_Value = (DWORD)_tcstoul(lpValueString, &EndPtr, 16);
|
|
GetLocaleInfo(Locale_Value, LOCALE_SLANGUAGE, szBuf, SIZE_300);
|
|
Position = SendMessage( sllv->hDisplay,
|
|
CB_ADDSTRING,
|
|
(WPARAM)0,
|
|
(LPARAM)szBuf );
|
|
SendMessage( sllv->hHidden,
|
|
CB_INSERTSTRING,
|
|
(WPARAM)Position,
|
|
(LPARAM)lpValueString );
|
|
}
|
|
else
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_EnumProc
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL CALLBACK Locale_EnumProc(
|
|
LPTSTR lpValueString)
|
|
{
|
|
return ( Set_Locale_List_Values(lpValueString, NULL) );
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Region_Set_Values
|
|
//
|
|
// Initialize all of the controls in the region property sheet page.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Region_Set_Values(
|
|
HWND hDlg,
|
|
REGDLGDATA *dlgdata)
|
|
{
|
|
REGMAPSTATE *state = (dlgdata ? &dlgdata->mapstate : NULL);
|
|
TCHAR szBuf[SIZE_128];
|
|
DWORD dwIndex;
|
|
SLLVPARAMS sllv;
|
|
|
|
sllv.hDisplay = GetDlgItem(hDlg, IDC_LOCALE);
|
|
sllv.hHidden = GetDlgItem(hDlg, IDC_LCID);
|
|
|
|
Set_Locale_List_Values(NULL, &sllv);
|
|
|
|
EnumSystemLocales(Locale_EnumProc, LCID_INSTALLED);
|
|
|
|
Set_Locale_List_Values(NULL, NULL);
|
|
|
|
if (UserLocaleID <= 0xFFFF)
|
|
{
|
|
wsprintf(szBuf, TEXT("%08x"), (DWORD)UserLocaleID);
|
|
|
|
dwIndex = SendDlgItemMessage( hDlg,
|
|
IDC_LCID,
|
|
CB_FINDSTRINGEXACT,
|
|
(WPARAM)-1,
|
|
(LPARAM)szBuf );
|
|
if (dwIndex != CB_ERR)
|
|
{
|
|
SendDlgItemMessage( hDlg,
|
|
IDC_LOCALE,
|
|
CB_SETCURSEL,
|
|
(WPARAM)dwIndex,
|
|
0L );
|
|
}
|
|
}
|
|
|
|
if (dlgdata)
|
|
{
|
|
dlgdata->dwCurLocale = SendDlgItemMessage( hDlg,
|
|
IDC_LOCALE,
|
|
CB_GETCURSEL,
|
|
0,
|
|
0L );
|
|
|
|
dlgdata->SysDefault = IsDlgButtonChecked(hDlg, IDC_DEFAULT_LOCALE);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Region_Apply_Settings
|
|
//
|
|
// If the Locale has changed, call Set_Locale_Values to update the user
|
|
// locale information. Notify the parent of changes and reset the
|
|
// change flag stored in the property sheet page structure appropriately.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Region_Apply_Settings(
|
|
HWND hDlg,
|
|
REGDLGDATA *dlgdata)
|
|
{
|
|
HKEY hKey = NULL;
|
|
TCHAR szLCID[25];
|
|
DWORD dwIndex;
|
|
TCHAR szMessage[150];
|
|
TCHAR szTitle[150];
|
|
LCID NewLocale;
|
|
HCURSOR OldCursor;
|
|
UINT SysDefault;
|
|
|
|
if (dlgdata->Changes <= RC_EverChg)
|
|
{
|
|
return (TRUE);
|
|
}
|
|
|
|
if (dlgdata->Changes & RC_Locale)
|
|
{
|
|
//
|
|
// Get the current selection.
|
|
//
|
|
dwIndex = SendDlgItemMessage(hDlg, IDC_LOCALE, CB_GETCURSEL, 0, 0);
|
|
SysDefault = IsDlgButtonChecked(hDlg, IDC_DEFAULT_LOCALE);
|
|
|
|
//
|
|
// See if the current selection is different from the original
|
|
// selection.
|
|
//
|
|
if ((dwIndex == dlgdata->dwCurLocale) &&
|
|
(SysDefault == dlgdata->SysDefault))
|
|
{
|
|
//
|
|
// Pointing to the same locale and the system default check
|
|
// box is the same, so no change is necessary.
|
|
//
|
|
PropSheet_UnChanged(GetParent(hDlg), hDlg);
|
|
dlgdata->Changes = RC_EverChg;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
//
|
|
// Get the text (locale id) for the current selection.
|
|
//
|
|
if ((dwIndex == CB_ERR) ||
|
|
(SendDlgItemMessage( hDlg,
|
|
IDC_LCID,
|
|
CB_GETLBTEXT,
|
|
(WPARAM)dwIndex,
|
|
(LPARAM)szLCID ) == CB_ERR))
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Save the new locale id.
|
|
//
|
|
NewLocale = (LCID)_tcstoul(szLCID, NULL, 16);
|
|
|
|
//
|
|
// See if the user has administrative privileges and if the
|
|
// locale is to be saved as the system default.
|
|
//
|
|
if ((dlgdata->Admin_Privileges) && (SysDefault == BST_CHECKED))
|
|
{
|
|
//
|
|
// Call setup to install the option.
|
|
//
|
|
OldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
if (SetupChangeLocale(hDlg, NewLocale))
|
|
{
|
|
//
|
|
// If Setup fails, put up a message and reset the
|
|
// original selection in the combobox.
|
|
//
|
|
SetCursor(OldCursor);
|
|
LoadString( hInstance,
|
|
IDS_SETUP_STRING,
|
|
szMessage,
|
|
ARRAYSIZE(szMessage) );
|
|
LoadString( hInstance,
|
|
IDS_TITLE_STRING,
|
|
szTitle,
|
|
ARRAYSIZE(szTitle) );
|
|
MessageBox(NULL, szMessage, szTitle, MB_OK | MB_ICONINFORMATION);
|
|
|
|
SendDlgItemMessage( hDlg,
|
|
IDC_LOCALE,
|
|
CB_SETCURSEL,
|
|
dlgdata->dwCurLocale,
|
|
0 );
|
|
return (FALSE);
|
|
}
|
|
SetCursor(OldCursor);
|
|
SysLocaleID = GetSystemDefaultLCID();
|
|
}
|
|
|
|
//
|
|
// Set the current locale value in the dlgdata structure.
|
|
//
|
|
dlgdata->dwCurLocale = dwIndex;
|
|
dlgdata->SysDefault = SysDefault;
|
|
|
|
//
|
|
// Set the locale value in the user's control panel international
|
|
// section of the registry.
|
|
//
|
|
if (RegOpenKeyEx( HKEY_CURRENT_USER,
|
|
c_szCPanelIntl,
|
|
0L,
|
|
KEY_READ | KEY_WRITE,
|
|
&hKey ) == ERROR_SUCCESS)
|
|
{
|
|
RegSetValueEx( hKey,
|
|
TEXT("Locale"),
|
|
0L,
|
|
REG_SZ,
|
|
(LPBYTE)szLCID,
|
|
(lstrlen(szLCID) + 1) * sizeof(TCHAR) );
|
|
}
|
|
UserLocaleID = NewLocale;
|
|
|
|
//
|
|
// When the locale changes, update ALL registry information.
|
|
//
|
|
Set_Locale_Values(0, LOCALE_SABBREVLANGNAME, 0, TEXT("sLanguage"), FALSE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_SCOUNTRY, 0, TEXT("sCountry"), FALSE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_ICOUNTRY, 0, TEXT("iCountry"), FALSE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_S1159, 0, TEXT("s1159"), FALSE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_S2359, 0, TEXT("s2359"), FALSE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_STIME, 0, TEXT("sTime"), FALSE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_ITIME, 0, TEXT("iTime"), FALSE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_ITLZERO, 0, TEXT("iTLZero"), FALSE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_SSHORTDATE, 0, TEXT("sShortDate"), FALSE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_IDATE, 0, TEXT("iDate"), TRUE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_SLONGDATE, 0, TEXT("sLongDate"), FALSE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_SDATE, 0, TEXT("sDate"), FALSE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_SCURRENCY, 0, TEXT("sCurrency"), FALSE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_ICURRENCY, 0, TEXT("iCurrency"), TRUE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_INEGCURR, 0, TEXT("iNegCurr"), TRUE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_ICURRDIGITS, 0, TEXT("iCurrDigits"), TRUE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_SDECIMAL, 0, TEXT("sDecimal"), FALSE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_SLIST, 0, TEXT("sList"), FALSE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_STHOUSAND, 0, TEXT("sThousand"), FALSE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_IDIGITS, 0, TEXT("iDigits"), TRUE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_ILZERO, 0, TEXT("iLzero"), TRUE, 0, 0);
|
|
Set_Locale_Values(0, LOCALE_IMEASURE, 0, TEXT("iMeasure"), TRUE, 0, 0);
|
|
|
|
//
|
|
// Set the user's default locale in the system so that any new
|
|
// process will use the new locale.
|
|
//
|
|
NtSetDefaultLocale(TRUE, NewLocale);
|
|
|
|
//
|
|
// Flush the International key to be sure all info is in the
|
|
// registry when we do the broadcast.
|
|
//
|
|
if (hKey != NULL)
|
|
{
|
|
RegFlushKey(hKey);
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
//
|
|
// Need to make sure the proper keyboard layout is installed.
|
|
//
|
|
Region_InstallKeyboardLayout( hDlg,
|
|
NewLocale,
|
|
szLCID,
|
|
dlgdata->Admin_Privileges );
|
|
|
|
//
|
|
// Broadcast the message that the international settings in the
|
|
// registry have changed.
|
|
//
|
|
SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, (LPARAM)szIntl);
|
|
}
|
|
|
|
//
|
|
// Register the regional change every time so that all other property
|
|
// sheets will be updated due to the locale settings change.
|
|
//
|
|
Verified_Regional_Chg = INTL_CHG;
|
|
|
|
PropSheet_UnChanged(GetParent(hDlg), hDlg);
|
|
dlgdata->Changes = RC_EverChg;
|
|
|
|
if ((dlgdata->Admin_Privileges) &&
|
|
(IsDlgButtonChecked(hDlg, IDC_DEFAULT_LOCALE) == BST_CHECKED))
|
|
{
|
|
LoadString(hInstance, IDS_REBOOT_STRING, szMessage, ARRAYSIZE(szMessage));
|
|
LoadString(hInstance, IDS_TITLE_STRING, szTitle, ARRAYSIZE(szTitle));
|
|
|
|
if (MessageBox( hDlg,
|
|
szMessage,
|
|
szTitle,
|
|
MB_YESNO | MB_ICONQUESTION ) == IDYES)
|
|
{
|
|
RebootTheSystem();
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Region_Clear_Values
|
|
//
|
|
// Reset each of the list boxes in the region property sheet page.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
#if 0
|
|
void Region_Clear_Values(
|
|
HWND hDlg)
|
|
{
|
|
SendDlgItemMessage(hDlg, IDC_LOCALE, CB_RESETCONTENT, 0, 0);
|
|
}
|
|
#endif
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Region_InitPropSheet
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Region_InitPropSheet(
|
|
HWND hDlg,
|
|
LPPROPSHEETPAGE psp)
|
|
{
|
|
HKEY hKey;
|
|
REGDLGDATA *dlgdata = (REGDLGDATA *)LocalAlloc(LPTR, sizeof(REGDLGDATA));
|
|
REGMAPSTATE *state = (dlgdata ? &dlgdata->mapstate : NULL);
|
|
HWND display = GetDlgItem(hDlg, IDC_LOCALE);
|
|
HWND hidden = GetDlgItem(hDlg, IDC_LCID);
|
|
|
|
psp->lParam = (LPARAM)dlgdata;
|
|
SetWindowLong(hDlg, DWL_USER, (LPARAM)psp);
|
|
|
|
//
|
|
// See if the user has Administrative privileges by checking for
|
|
// write permission to the registry key.
|
|
//
|
|
if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
c_szInstalledLocales,
|
|
0L,
|
|
KEY_WRITE,
|
|
&hKey ) == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// We can write to the HKEY_LOCAL_MACHINE key, so the user
|
|
// has Admin privileges.
|
|
//
|
|
dlgdata->Admin_Privileges = TRUE;
|
|
RegCloseKey(hKey);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The user does not have admin privileges, so disable the
|
|
// "Set as system default locale" check box.
|
|
//
|
|
dlgdata->Admin_Privileges = FALSE;
|
|
EnableWindow(GetDlgItem(hDlg, IDC_DEFAULT_LOCALE), FALSE);
|
|
}
|
|
|
|
Region_Set_Values(hDlg, dlgdata);
|
|
LoadMapInfo(state, hidden, GetDlgItem(hDlg, IDC_MAPCTL));
|
|
|
|
if (state)
|
|
{
|
|
int index = ComboBox_GetCurSel(display);
|
|
|
|
if (index >= 0)
|
|
{
|
|
REGMAPINFO *info =
|
|
(REGMAPINFO *)ComboBox_GetItemData(hidden, index);
|
|
|
|
if (info)
|
|
{
|
|
ChangeSectionHighlight(hDlg, state, info);
|
|
// CenterSection(hDlg, state, FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// RegionDlgProc
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL CALLBACK RegionDlgProc(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLong(hDlg, DWL_USER));
|
|
REGDLGDATA *dlgdata = lpPropSheet ? (REGDLGDATA *)lpPropSheet->lParam : NULL;
|
|
|
|
switch (message)
|
|
{
|
|
case ( WM_NOTIFY ) :
|
|
{
|
|
switch (((NMHDR *)lParam)->idFrom)
|
|
{
|
|
case ( 0 ) :
|
|
{
|
|
switch (((NMHDR *)lParam)->code)
|
|
{
|
|
case ( PSN_SETACTIVE ) :
|
|
{
|
|
break;
|
|
}
|
|
case ( PSN_KILLACTIVE ) :
|
|
{
|
|
//
|
|
// No input to validate. Region_Apply_Settings
|
|
// will typically return true. It will return
|
|
// false only if the registration of the new
|
|
// locale fails. Return the result of the apply.
|
|
//
|
|
if (dlgdata)
|
|
{
|
|
SetWindowLong( hDlg,
|
|
DWL_MSGRESULT,
|
|
!Region_Apply_Settings( hDlg,
|
|
dlgdata ) );
|
|
}
|
|
break;
|
|
}
|
|
case ( PSN_APPLY ) :
|
|
{
|
|
//
|
|
// All of the save dialog work is performed in
|
|
// the KILLACTIVE processing. But, if the user
|
|
// presses ApplyNow, we need to zero out the
|
|
// NC_EverChg bit so that CancelToClose will be
|
|
// sent if changes occur again.
|
|
//
|
|
if (dlgdata)
|
|
{
|
|
dlgdata->Changes = 0;
|
|
}
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_MAPCTL ) :
|
|
{
|
|
NFYMAPEVENT *event = (NFYMAPEVENT *)lParam;
|
|
switch (event->hdr.code)
|
|
{
|
|
case ( MAPN_TOUCH ) :
|
|
{
|
|
if (dlgdata)
|
|
{
|
|
HotTrackSection(hDlg, dlgdata, event->index);
|
|
}
|
|
break;
|
|
}
|
|
case ( MAPN_SELECT ) :
|
|
{
|
|
// if (dlgdata)
|
|
// {
|
|
// CenterSection(hDlg, &dlgdata->mapstate, TRUE);
|
|
// }
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case ( WM_INITDIALOG ) :
|
|
{
|
|
Region_InitPropSheet(hDlg, (LPPROPSHEETPAGE)lParam);
|
|
break;
|
|
}
|
|
case ( WM_DESTROY ) :
|
|
{
|
|
FreeMapInfo(&dlgdata->mapstate, GetDlgItem(hDlg, IDC_LCID));
|
|
if (dlgdata)
|
|
{
|
|
lpPropSheet->lParam = 0;
|
|
LocalFree((HANDLE)dlgdata);
|
|
}
|
|
break;
|
|
}
|
|
case ( WM_HELP ) :
|
|
{
|
|
WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
|
|
NULL,
|
|
HELP_WM_HELP,
|
|
(DWORD)(LPTSTR)aRegionHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_CONTEXTMENU ) : // right mouse click
|
|
{
|
|
WinHelp( (HWND)wParam,
|
|
NULL,
|
|
HELP_CONTEXTMENU,
|
|
(DWORD)(LPTSTR)aRegionHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_COMMAND ) :
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case ( IDC_LOCALE ) :
|
|
{
|
|
if (HIWORD(wParam) == CBN_SELCHANGE)
|
|
{
|
|
if (dlgdata)
|
|
{
|
|
REGMAPSTATE *state = ( dlgdata
|
|
? &dlgdata->mapstate
|
|
: NULL );
|
|
int index = ComboBox_GetCurSel((HWND)lParam);
|
|
HWND hidden = GetDlgItem(hDlg, IDC_LCID);
|
|
REGMAPINFO *info =
|
|
(REGMAPINFO *)ComboBox_GetItemData( hidden,
|
|
index );
|
|
|
|
ChangeSectionHighlight(hDlg, state, info);
|
|
// CenterSection(hDlg, state, TRUE);
|
|
|
|
dlgdata->Changes |= RC_Locale;
|
|
}
|
|
|
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_DEFAULT_LOCALE ) :
|
|
{
|
|
dlgdata->Changes |= RC_Locale;
|
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ParseField
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
static int ParseField(
|
|
const TCHAR **pp,
|
|
int defval)
|
|
{
|
|
int value;
|
|
|
|
if (**pp && (**pp != CHAR_HYPHEN))
|
|
{
|
|
value = 0;
|
|
|
|
while (**pp && (**pp != CHAR_COMMA))
|
|
{
|
|
value = (10 * value) + (**pp - CHAR_ZERO);
|
|
(*pp)++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
value = defval;
|
|
}
|
|
|
|
while (**pp && (**pp != CHAR_COMMA))
|
|
{
|
|
(*pp)++;
|
|
}
|
|
|
|
if (**pp == CHAR_COMMA)
|
|
{
|
|
(*pp)++;
|
|
}
|
|
|
|
return (value);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ParseMapInfo
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define BOGUS_MAP_REGION_WIDTH 500
|
|
|
|
void ParseMapInfo(
|
|
REGMAPINFO *info,
|
|
LPCTSTR mapid)
|
|
{
|
|
const TCHAR *p = mapid;
|
|
|
|
if (*p)
|
|
{
|
|
if (*p == CHAR_STAR)
|
|
{
|
|
info->flags |= RMI_PRIMARY;
|
|
p++;
|
|
}
|
|
|
|
info->sea = ParseField(&p, -1);
|
|
info->land = ParseField(&p, -1);
|
|
info->left = ParseField(&p, 0);
|
|
info->width = ParseField(&p, BOGUS_MAP_REGION_WIDTH);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// AssociateMapInfo
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void AssociateMapInfo(
|
|
REGMAPINFO **lookup,
|
|
REGMAPINFO *src,
|
|
LPCTSTR lcid,
|
|
HWND box)
|
|
{
|
|
int index = ComboBox_FindStringExact(box, -1, lcid);
|
|
|
|
if (index >= 0)
|
|
{
|
|
REGMAPINFO *info =
|
|
(REGMAPINFO *)LocalAlloc(LPTR, sizeof(REGMAPINFO));
|
|
|
|
if (info)
|
|
{
|
|
*info = *src;
|
|
info->combosel = index;
|
|
|
|
if (lookup)
|
|
{
|
|
if (info->sea >= 0)
|
|
{
|
|
REGMAPINFO **entry = lookup + info->sea;
|
|
|
|
if (!*entry || (info->flags & RMI_PRIMARY))
|
|
{
|
|
*entry = info;
|
|
}
|
|
}
|
|
|
|
if (info->land >= 0)
|
|
{
|
|
REGMAPINFO **entry = lookup + info->land;
|
|
|
|
if (!*entry || (info->flags & RMI_PRIMARY))
|
|
{
|
|
*entry = info;
|
|
}
|
|
}
|
|
}
|
|
|
|
ComboBox_SetItemData(box, index, (LPARAM)info);
|
|
|
|
//
|
|
// Copy back for caller to see.
|
|
//
|
|
*src = *info;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LoadMapInfo
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL LoadMapInfo(
|
|
REGMAPSTATE *state,
|
|
HWND combo,
|
|
HWND map)
|
|
{
|
|
BOOL result = TRUE;
|
|
HKEY root;
|
|
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szRegMapIdPath, &root) == ERROR_SUCCESS)
|
|
{
|
|
REGMAPINFO **lookup = (state ? state->lookup : NULL);
|
|
REGMAPINFO info;
|
|
int i = 0;
|
|
|
|
for (i = 0; ; i++)
|
|
{
|
|
TCHAR mapid[32];
|
|
TCHAR lcid[16];
|
|
DWORD len_mapid = sizeof(mapid) / sizeof(TCHAR);
|
|
DWORD len_lcid = sizeof(lcid) / sizeof(TCHAR);
|
|
DWORD type;
|
|
DWORD error = RegEnumValue( root,
|
|
i,
|
|
lcid,
|
|
&len_lcid,
|
|
NULL,
|
|
&type,
|
|
(LPBYTE)mapid,
|
|
&len_mapid );
|
|
|
|
if (error != ERROR_SUCCESS)
|
|
{
|
|
if (error == ERROR_MORE_DATA)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
if (type != REG_SZ)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
info.combosel = -1; // reset to -1
|
|
info.flags = 0; // clear flags
|
|
ParseMapInfo(&info, mapid);
|
|
AssociateMapInfo(lookup, &info, lcid, combo);
|
|
|
|
HighlightSection( map,
|
|
&info,
|
|
(info.combosel >= 0)
|
|
? MAPRGN_NORMAL
|
|
: MAPRGN_DISABLE );
|
|
}
|
|
|
|
RegCloseKey(root);
|
|
}
|
|
|
|
return (result);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// FreeMapInfo
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FreeMapInfo(
|
|
REGMAPSTATE *state,
|
|
HWND combo)
|
|
{
|
|
REGMAPINFO **lookup = state->lookup;
|
|
REGMAPINFO **entry = lookup;
|
|
int count, i;
|
|
|
|
count = sizeof(state->lookup) / sizeof(state->lookup[0]);
|
|
for (i = 0; i < count; i++, entry++)
|
|
{
|
|
*entry = NULL;
|
|
}
|
|
|
|
count = ComboBox_GetCount(combo);
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
REGMAPINFO *info = (REGMAPINFO *)ComboBox_GetItemData(combo, i);
|
|
|
|
if (info)
|
|
{
|
|
LocalFree((HANDLE)info);
|
|
ComboBox_SetItemData(combo, i, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HighlightSection
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void HighlightSection(
|
|
HWND map,
|
|
REGMAPINFO *info,
|
|
int highlight)
|
|
{
|
|
if (info)
|
|
{
|
|
//
|
|
// The oceans are just used for hit testing in this version, so
|
|
// it would look really twisted if we highlighted them...
|
|
// We allow unhighlighting mainly for intialization and debugging.
|
|
//
|
|
if ((info->sea >= 0) && (highlight != MAPRGN_HIGHLIGHT))
|
|
{
|
|
MapControlSetSeaRegionHighlight( map,
|
|
info->sea,
|
|
highlight,
|
|
info->left,
|
|
info->width );
|
|
}
|
|
|
|
if (info->land >= 0)
|
|
{
|
|
MapControlSetLandRegionHighlight( map,
|
|
info->land,
|
|
highlight,
|
|
info->left,
|
|
info->width );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ChangeSectionHighlight
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ChangeSectionHighlight(
|
|
HWND page,
|
|
REGMAPSTATE *state,
|
|
REGMAPINFO *info)
|
|
{
|
|
if (info || state->info)
|
|
{
|
|
HWND map = GetDlgItem(page, IDC_MAPCTL);
|
|
|
|
if (state->info)
|
|
{
|
|
HighlightSection(map, state->info, MAPRGN_NORMAL);
|
|
}
|
|
|
|
state->info = info;
|
|
|
|
if (state->info)
|
|
{
|
|
HighlightSection(map, state->info, MAPRGN_HIGHLIGHT);
|
|
}
|
|
|
|
MapControlInvalidateDirtyRegions(map);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HotTrackSection
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void HotTrackSection(
|
|
HWND page,
|
|
REGDLGDATA *dlgdata,
|
|
int index)
|
|
{
|
|
REGMAPSTATE *state = &dlgdata->mapstate;
|
|
REGMAPINFO *info = state->lookup[index];
|
|
|
|
if (info && (info != state->info))
|
|
{
|
|
ChangeSectionHighlight(page, state, info);
|
|
|
|
ComboBox_SetCurSel(GetDlgItem(page, IDC_LOCALE), info->combosel);
|
|
dlgdata->Changes |= RC_Locale;
|
|
PropSheet_Changed(GetParent(page), page);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CenterSection
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CenterSection(
|
|
HWND page,
|
|
REGMAPSTATE *state,
|
|
BOOL animate)
|
|
{
|
|
REGMAPINFO *info = state->info;
|
|
|
|
if (info)
|
|
{
|
|
HWND map = GetDlgItem(page, IDC_MAPCTL);
|
|
|
|
MapControlRotateTo(map, info->left + info->width / 2, animate);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// RebootTheSystem
|
|
//
|
|
// This routine enables all privileges in the token, calls ExitWindowsEx
|
|
// to reboot the system, and then resets all of the privileges to their
|
|
// old state.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID RebootTheSystem()
|
|
{
|
|
HANDLE Token = NULL;
|
|
ULONG ReturnLength, Index;
|
|
PTOKEN_PRIVILEGES NewState = NULL;
|
|
PTOKEN_PRIVILEGES OldState = NULL;
|
|
BOOL Result;
|
|
|
|
Result = OpenProcessToken( GetCurrentProcess(),
|
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
|
&Token );
|
|
if (Result)
|
|
{
|
|
ReturnLength = 4096;
|
|
NewState = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, ReturnLength);
|
|
OldState = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, ReturnLength);
|
|
Result = (BOOL)((NewState != NULL) && (OldState != NULL));
|
|
if (Result)
|
|
{
|
|
Result = GetTokenInformation( Token, // TokenHandle
|
|
TokenPrivileges, // TokenInformationClass
|
|
NewState, // TokenInformation
|
|
ReturnLength, // TokenInformationLength
|
|
&ReturnLength ); // ReturnLength
|
|
if (Result)
|
|
{
|
|
//
|
|
// Set the state settings so that all privileges are enabled...
|
|
//
|
|
if (NewState->PrivilegeCount > 0)
|
|
{
|
|
for (Index = 0; Index < NewState->PrivilegeCount; Index++)
|
|
{
|
|
NewState->Privileges[Index].Attributes = SE_PRIVILEGE_ENABLED;
|
|
}
|
|
}
|
|
|
|
Result = AdjustTokenPrivileges( Token, // TokenHandle
|
|
FALSE, // DisableAllPrivileges
|
|
NewState, // NewState
|
|
ReturnLength, // BufferLength
|
|
OldState, // PreviousState
|
|
&ReturnLength ); // ReturnLength
|
|
if (Result)
|
|
{
|
|
ExitWindowsEx(EWX_REBOOT, 0);
|
|
|
|
|
|
AdjustTokenPrivileges( Token,
|
|
FALSE,
|
|
OldState,
|
|
0,
|
|
NULL,
|
|
NULL );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NewState != NULL)
|
|
{
|
|
LocalFree(NewState);
|
|
}
|
|
if (OldState != NULL)
|
|
{
|
|
LocalFree(OldState);
|
|
}
|
|
if (Token != NULL)
|
|
{
|
|
CloseHandle(Token);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Region_InstallKeyboardLayout
|
|
//
|
|
// Adds the new input locale with its default layout if the input locale
|
|
// does not already exist in the list. Calls setup to get the new
|
|
// keyboard layout file (if necessary).
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Region_InstallKeyboardLayout(
|
|
HWND hwnd,
|
|
LCID Locale,
|
|
LPTSTR pszLocale,
|
|
BOOL bAdmin)
|
|
{
|
|
HKEY hKey;
|
|
HWND hwndIndicate;
|
|
TCHAR szValue[MAX_PATH];
|
|
TCHAR szData[MAX_PATH];
|
|
TCHAR szTemp[MAX_PATH];
|
|
DWORD dwIndex, cchValue, cbData;
|
|
DWORD dwValue, dwData;
|
|
DWORD dwPreloadNum = 1;
|
|
LONG rc;
|
|
|
|
|
|
//
|
|
// Open the HKCU\Keyboard Layout\Preload key.
|
|
//
|
|
if (RegOpenKeyEx( HKEY_CURRENT_USER,
|
|
szKbdPreloadKey,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hKey ) != ERROR_SUCCESS)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Enumerate the values in the Preload key.
|
|
//
|
|
dwIndex = 0;
|
|
cchValue = sizeof(szValue) / sizeof(TCHAR);
|
|
cbData = sizeof(szData);
|
|
rc = RegEnumValue( hKey,
|
|
dwIndex,
|
|
szValue,
|
|
&cchValue,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szData,
|
|
&cbData );
|
|
|
|
while (rc == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Look to see if the new input locale already exists in the list.
|
|
//
|
|
dwData = TransNum(szData);
|
|
if (LOWORD(dwData) == LOWORD(Locale))
|
|
{
|
|
//
|
|
// Don't care if 0xd000 is in the high word. Know that at
|
|
// least one instance of this input locale exists. We're done.
|
|
//
|
|
RegCloseKey(hKey);
|
|
return (TRUE);
|
|
}
|
|
|
|
//
|
|
// Save the preload number if it's higher than the highest one
|
|
// found so far.
|
|
//
|
|
dwValue = TransNum(szValue);
|
|
if (dwValue > dwPreloadNum)
|
|
{
|
|
dwPreloadNum = dwValue;
|
|
}
|
|
|
|
//
|
|
// Get the next enum value.
|
|
//
|
|
dwIndex++;
|
|
cchValue = sizeof(szValue) / sizeof(TCHAR);
|
|
szValue[0] = TEXT('\0');
|
|
cbData = sizeof(szData);
|
|
szData[0] = TEXT('\0');
|
|
rc = RegEnumValue( hKey,
|
|
dwIndex,
|
|
szValue,
|
|
&cchValue,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szData,
|
|
&cbData );
|
|
}
|
|
|
|
//
|
|
// If we get to this point, then the input locale does not exist.
|
|
// Need to create the input locale with the default layout. Simply
|
|
// add it to the list (do not make it the default).
|
|
//
|
|
|
|
//
|
|
// If the user has Admin privileges, then install the new keyboard
|
|
// files, if necessary.
|
|
//
|
|
// Don't worry about failure at this point.
|
|
//
|
|
if (bAdmin)
|
|
{
|
|
Region_SetupKeyboardLayout(hwnd, Locale);
|
|
}
|
|
|
|
//
|
|
// Set the value in the registry.
|
|
//
|
|
dwPreloadNum++;
|
|
wsprintf(szValue, TEXT("%d"), dwPreloadNum);
|
|
RegSetValueEx( hKey,
|
|
szValue,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)pszLocale,
|
|
(DWORD)(lstrlen(pszLocale) + 1) * sizeof(TCHAR) );
|
|
|
|
//
|
|
// Flush the registry key and close the handle.
|
|
//
|
|
RegFlushKey(hKey);
|
|
RegCloseKey(hKey);
|
|
|
|
//
|
|
// Load the new keyboard layout.
|
|
//
|
|
if (LoadKeyboardLayout( pszLocale,
|
|
KLF_SUBSTITUTE_OK | KLF_NOTELLSHELL ) == NULL)
|
|
{
|
|
//
|
|
// It's possible that the new layout files aren't installed,
|
|
// so try the input locale with the current layout.
|
|
//
|
|
// NOTE: This should always work.
|
|
//
|
|
|
|
//
|
|
// Add the substitute for the current layout.
|
|
//
|
|
if (RegOpenKeyEx( HKEY_CURRENT_USER,
|
|
szKbdSubstKey,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hKey ) == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwCurrent;
|
|
HKL hklCurrent;
|
|
|
|
//
|
|
// Get the current active keyboard layout.
|
|
//
|
|
dwCurrent = 0;
|
|
hklCurrent = GetKeyboardLayout(0);
|
|
if (HIWORD(hklCurrent) & 0xf000)
|
|
{
|
|
if (GetKeyboardLayoutName(szData))
|
|
{
|
|
dwCurrent = TransNum(szData);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwCurrent = (DWORD)HIWORD(hklCurrent);
|
|
}
|
|
|
|
if (dwCurrent && (Locale != dwCurrent))
|
|
{
|
|
wsprintf(szData, TEXT("%8.8x"), dwCurrent);
|
|
RegSetValueEx( hKey,
|
|
pszLocale,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)szData,
|
|
(DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
|
|
}
|
|
|
|
RegFlushKey(hKey);
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
//
|
|
// Try again.
|
|
//
|
|
if (LoadKeyboardLayout( pszLocale,
|
|
KLF_SUBSTITUTE_OK | KLF_NOTELLSHELL ) == NULL)
|
|
{
|
|
cbData = IDS_ML_LOADKBDFAILED;
|
|
LoadString(hInstance, cbData, szData, MAX_PATH);
|
|
GetLocaleInfo(Locale, LOCALE_SLANGUAGE, szTemp, MAX_PATH);
|
|
wsprintf(szValue, szData, szTemp);
|
|
MessageBox(hwnd, szValue, NULL, MB_OK_OOPS);
|
|
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update the task bar indicator if it's on.
|
|
//
|
|
hwndIndicate = FindWindow(szIndicator, NULL);
|
|
if (hwndIndicate && IsWindow(hwndIndicate))
|
|
{
|
|
SendMessage(hwndIndicate, WM_COMMAND, IDM_NEWSHELL, 0L);
|
|
}
|
|
|
|
//
|
|
// Update the active locales for the Input Locales property page
|
|
// if the page has been initialized.
|
|
//
|
|
PropSheet_QuerySiblings(GetParent(hwnd), 0, 0);
|
|
|
|
//
|
|
// Return success.
|
|
//
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Region_SetupKeyboardLayout
|
|
//
|
|
// Calls setup to get the new keyboard layout file.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Region_SetupKeyboardLayout(
|
|
HWND hwnd,
|
|
LCID Locale)
|
|
{
|
|
HINF hKbdInf;
|
|
HSPFILEQ FileQueue;
|
|
PVOID QueueContext;
|
|
UINT i;
|
|
int count;
|
|
TCHAR szSection[MAX_PATH];
|
|
DWORD d;
|
|
BOOL bRet = TRUE;
|
|
|
|
//
|
|
// Open the Inf file.
|
|
//
|
|
hKbdInf = SetupOpenInfFile(szKbdInf, NULL, INF_STYLE_WIN4, NULL);
|
|
if (hKbdInf == INVALID_HANDLE_VALUE)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
if (!SetupOpenAppendInfFile(NULL, hKbdInf, NULL))
|
|
{
|
|
SetupCloseInfFile(hKbdInf);
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Create a setup file queue and initialize default setup
|
|
// copy queue callback context.
|
|
//
|
|
FileQueue = SetupOpenFileQueue();
|
|
if ((!FileQueue) || (FileQueue == INVALID_HANDLE_VALUE))
|
|
{
|
|
SetupCloseInfFile(hKbdInf);
|
|
return (FALSE);
|
|
}
|
|
|
|
QueueContext = SetupInitDefaultQueueCallback(hwnd);
|
|
if (!QueueContext)
|
|
{
|
|
SetupCloseFileQueue(FileQueue);
|
|
SetupCloseInfFile(hKbdInf);
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Get the layout name.
|
|
//
|
|
wsprintf( szSection,
|
|
TEXT("%ws%8.8lx"),
|
|
szPrefixCopy,
|
|
Locale );
|
|
|
|
//
|
|
// Enqueue the keyboard layout files so that they may be
|
|
// copied. This only handles the CopyFiles entries in the
|
|
// inf file.
|
|
//
|
|
if (!SetupInstallFilesFromInfSection( hKbdInf,
|
|
NULL,
|
|
FileQueue,
|
|
szSection,
|
|
NULL,
|
|
SP_COPY_NEWER ))
|
|
{
|
|
//
|
|
// Setup failed to find the keyboard. Return an error.
|
|
//
|
|
// This shouldn't happen - the inf file is messed up.
|
|
//
|
|
bRet = FALSE;
|
|
goto Region_SetupError;
|
|
}
|
|
|
|
//
|
|
// See if we need to install any files.
|
|
//
|
|
// d = 0: User wants new files or some files were missing;
|
|
// Must commit queue.
|
|
//
|
|
// d = 1: User wants to use existing files and queue is empty;
|
|
// Can skip committing queue.
|
|
//
|
|
// d = 2: User wants to use existing files, but del/ren queues
|
|
// not empty. Must commit queue. The copy queue will
|
|
// have been emptied, so only del/ren functions will be
|
|
// performed.
|
|
//
|
|
if ((SetupScanFileQueue( FileQueue,
|
|
SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_INFORM_USER,
|
|
hwnd,
|
|
NULL,
|
|
NULL,
|
|
&d )) && (d != 1))
|
|
{
|
|
//
|
|
// Copy the files in the queue.
|
|
//
|
|
if (!SetupCommitFileQueue( hwnd,
|
|
FileQueue,
|
|
SetupDefaultQueueCallback,
|
|
QueueContext ))
|
|
{
|
|
//
|
|
// This can happen if the user hits Cancel from within
|
|
// the setup dialog.
|
|
//
|
|
bRet = FALSE;
|
|
goto Region_SetupError;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Execute all of the other entries in the inf file.
|
|
//
|
|
// Currently, there are no other entries within the inf file
|
|
// other than the CopyFiles entry. Therefore, this does
|
|
// nothing at the moment.
|
|
//
|
|
|
|
//
|
|
// Call setup to copy the keyboard layout file.
|
|
//
|
|
// If it fails, just continue on here. Some form of an input locale
|
|
// will be installed later on.
|
|
//
|
|
SetupInstallFromInfSection( hwnd,
|
|
hKbdInf,
|
|
szSection,
|
|
SPINST_ALL & ~SPINST_FILES,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
Region_SetupError:
|
|
//
|
|
// Terminate the Queue.
|
|
//
|
|
SetupTermDefaultQueueCallback(QueueContext);
|
|
|
|
//
|
|
// Close the file queue.
|
|
//
|
|
SetupCloseFileQueue(FileQueue);
|
|
|
|
//
|
|
// Close the Inf file.
|
|
//
|
|
SetupCloseInfFile(hKbdInf);
|
|
|
|
//
|
|
// Return success.
|
|
//
|
|
return (bRet);
|
|
}
|
|
|
|
|