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.
954 lines
28 KiB
954 lines
28 KiB
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 2001, Microsoft Corporation All rights reserved.
|
|
//
|
|
// Module Name:
|
|
//
|
|
// euroconv.c
|
|
//
|
|
// Abstract:
|
|
//
|
|
// This file contains the entry point of the euroconv.exe utility.
|
|
//
|
|
// NOTE: If you want to add exception for new locale, please add it to the
|
|
// base list named gBaseEuroException. See the structure definition for more
|
|
// information. Empty string represented by "\0" means that we don't need
|
|
// to update the information. The chThousandSep member of gBaseEuroException
|
|
// should always be different from "\0".
|
|
//
|
|
// Revision History:
|
|
//
|
|
// 2001-07-30 lguindon Created.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Includes Files.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#include "euroconv.h"
|
|
#include "util.h"
|
|
#include "welcome.h"
|
|
#include "confirm.h"
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Global variable.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
EURO_EXCEPTION gBaseEuroException[] =
|
|
{
|
|
{0x00000403, "\0", "2", "."}, // Catalan - Spain
|
|
{0x00000407, "\0", "\0", "."}, // German - Germany
|
|
{0x00000c07, "\0", "\0", "."}, // German - Austria
|
|
{0x00001007, "\0", "\0", "."}, // German - Luzembourg
|
|
{0x00000408, "\0", "\0", "."}, // Greek - Greece
|
|
{0x00001809, ".", "\0", ","}, // English - Ireland
|
|
{0x0000040a, "\0", "2", "."}, // Spanish - Spain (traditional sort)
|
|
{0x00000c0a, "\0", "2", "."}, // Spanish - Spain (international sort)
|
|
{0x0000040b, "\0", "\0", " "}, // Finnish - Finland
|
|
{0x0000040c, "\0", "\0", " "}, // French - France
|
|
{0x0000080c, "\0", "\0", "."}, // French - Belgium
|
|
{0x0000140c, "\0", "\0", " "}, // French - Luxembourg
|
|
{0x0000180c, "\0", "\0", " "}, // French - Monaco
|
|
{0x00000410, ",", "2", "."}, // Italian - Italy
|
|
{0x00000413, "\0", "\0", "."}, // Dutch - Netherlands
|
|
{0x00000813, "\0", "\0", "."}, // Dutch - Belgium
|
|
{0x00000816, ",", "\0", "."}, // Portuguese - Portugal
|
|
{0x0000081d, "\0", "\0", " "}, // Swedish - Finland
|
|
{0x0000042d, "\0", "2", "."}, // Basque - Spain
|
|
{0x00000456, "\0", "\0", "."} // Galician - Spain
|
|
};
|
|
UINT gNbBaseEuroException = sizeof(gBaseEuroException)/sizeof(EURO_EXCEPTION);
|
|
|
|
UINT gNbOverrideEuroException = 0;
|
|
PEURO_EXCEPTION gOverrideEuroException;
|
|
HGLOBAL hOverrideEuroException = NULL;
|
|
|
|
HINSTANCE ghInstance = NULL;
|
|
|
|
BOOL gbSilence = FALSE;
|
|
BOOL gbAll = TRUE;
|
|
DWORD gdwVersion = (-1);
|
|
#ifdef DEBUG
|
|
BOOL gbPatchCheck = TRUE;
|
|
#endif // DEBUG
|
|
|
|
|
|
const CHAR c_szCPanelIntl[] = "Control Panel\\International";
|
|
const CHAR c_szCPanelIntl_DefUser[] = ".DEFAULT\\Control Panel\\International";
|
|
const CHAR c_szLocale[] = "Locale";
|
|
const CHAR c_szCurrencySymbol[] = "sCurrency";
|
|
const WCHAR c_wszCurrencySymbol[] = L"sCurrency";
|
|
const CHAR c_szCurrencyDecimalSep[] = "sMonDecimalSep";
|
|
const CHAR c_szCurrencyThousandSep[] = "sMonThousandSep";
|
|
const CHAR c_szCurrencyDigits[] = "iCurrDigits";
|
|
const CHAR c_szIntl[] = "intl";
|
|
|
|
HINSTANCE hUserenvDLL = NULL;
|
|
BOOL (*pfnGetProfilesDirectory)(LPSTR, LPDWORD) = NULL;
|
|
|
|
HINSTANCE hUser32DLL = NULL;
|
|
long (*pfnBroadcastSystemMessage)(DWORD, LPDWORD, UINT, WPARAM, LPARAM) = NULL;
|
|
|
|
HINSTANCE hNtdllDLL = NULL;
|
|
LONG (*pfnRtlAdjustPrivilege)(ULONG, BOOLEAN, BOOLEAN, PBOOLEAN) = NULL;
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Prototypes.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL ParseCmdLine(LPSTR argIndex);
|
|
DWORD ApplyEuroSettings();
|
|
DWORD ApplyEuroSettingsToRegistry();
|
|
DWORD ApplyEuroSettingsToFile();
|
|
BOOL UpdateFileLocaleInfo(LPCSTR szProfile, PEURO_EXCEPTION pInfo);
|
|
BOOL UpdateRegLocaleInfo(HKEY hKey, PEURO_EXCEPTION pInfo);
|
|
BOOL UpdateLocaleInfo(HKEY hKey, PEURO_EXCEPTION pInfo);
|
|
void Usage();
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Main entry point.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
INT APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
|
|
{
|
|
DWORD dwRecipients;
|
|
DWORD nbChanged;
|
|
|
|
//
|
|
// Save instance.
|
|
//
|
|
ghInstance = hInstance;
|
|
|
|
//
|
|
// Set language.
|
|
//
|
|
// SetThreadLocale((LCID)0x00001809); // English - Ireland
|
|
// SetThreadLocale((LCID)0x0000040c); // French - France
|
|
// SetThreadLocale((LCID)0x0000080c); // French - Belgium
|
|
// SetThreadLocale((LCID)0x0000140c); // French - Luxembourg
|
|
// SetThreadLocale((LCID)0x0000180c); // French - Monaco
|
|
// SetThreadLocale((LCID)0x00000410); // Italian - Italia
|
|
// SetThreadLocale((LCID)0x0000040b); // Finnish - Finland
|
|
// SetThreadLocale((LCID)0x00000408); // Greek - Greece
|
|
// SetThreadLocale((LCID)0x00000816); // Portuguese - Portugal
|
|
// SetThreadLocale((LCID)0x00000403); // Catalan - Spain
|
|
// SetThreadLocale((LCID)0x0000040a); // Spanish - Spain (traditional sort)
|
|
// SetThreadLocale((LCID)0x00000c0a); // Spanish - Spain (international sort)
|
|
// SetThreadLocale((LCID)0x0000042d); // Basque - Spain
|
|
// SetThreadLocale((LCID)0x00000456); // Galician - Spain
|
|
// SetThreadLocale((LCID)0x00000407); // German - Germany
|
|
// SetThreadLocale((LCID)0x00000c07); // German - Austria
|
|
// SetThreadLocale((LCID)0x00001007); // German - Luzembourg
|
|
// SetThreadLocale((LCID)0x0000081d); // Swedish - Finland
|
|
// SetThreadLocale((LCID)0x00000413); // Dutch - Netherlands
|
|
// SetThreadLocale((LCID)0x00000813); // Dutch - Belgium
|
|
|
|
//
|
|
// Parse command line arguments.
|
|
//
|
|
if (!ParseCmdLine(lpCmdLine))
|
|
{
|
|
return (-1);
|
|
}
|
|
|
|
//
|
|
// Install the patch. The path for UI and Non-UI cases are seperated for
|
|
// cleared understanding of both cases.
|
|
//
|
|
if (!gbSilence)
|
|
{
|
|
//
|
|
// Verify administrative privileges.
|
|
//
|
|
if (gbAll && !IsAdmin())
|
|
{
|
|
if (ShowMsg(NULL, IDS_NOADMIN, IDS_TITLE, MB_YN_OOPS) == IDYES)
|
|
{
|
|
gbAll = FALSE;
|
|
}
|
|
else
|
|
{
|
|
CleanUp(hOverrideEuroException);
|
|
return (0);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Verify if Euro patch is there.
|
|
//
|
|
if (!IsEuroPatchInstalled())
|
|
{
|
|
ShowMsg(NULL, IDS_PATCH, IDS_TITLE, MB_OK_OOPS);
|
|
CleanUp(hOverrideEuroException);
|
|
return (-1);
|
|
}
|
|
|
|
//
|
|
// Load needed library
|
|
//
|
|
if (!IsWindows9x() && gbAll)
|
|
{
|
|
if (!LoadLibraries())
|
|
{
|
|
ShowMsg(NULL, IDS_LIB_ERROR, IDS_TITLE, MB_OK_OOPS);
|
|
CleanUp(hOverrideEuroException);
|
|
return (-1);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Show welcome screen.
|
|
//
|
|
if (!WelcomeDialog())
|
|
{
|
|
CleanUp(hOverrideEuroException);
|
|
return (0);
|
|
}
|
|
|
|
//
|
|
// Show Confirmation dialog.
|
|
//
|
|
if (!ConfirmDialog())
|
|
{
|
|
CleanUp(hOverrideEuroException);
|
|
return (0);
|
|
}
|
|
|
|
//
|
|
// Apply EURO changes.
|
|
//
|
|
if ((nbChanged = ApplyEuroSettings()) != 0)
|
|
{
|
|
//
|
|
// Show success message.
|
|
//
|
|
if (IsWindows9x())
|
|
{
|
|
if (ShowMsg(NULL, IDS_SUCCESS, IDS_TITLE, MB_YESNO | MB_ICONQUESTION) == IDYES)
|
|
{
|
|
RebootTheSystem();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ShowMsg(NULL, IDS_SUCCESS_DEF, IDS_TITLE, MB_YESNO | MB_ICONQUESTION) == IDYES)
|
|
{
|
|
if (gbAll)
|
|
{
|
|
RebootTheSystem();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ShowMsg(NULL, IDS_NOTHING, IDS_TITLE, MB_OK_OOPS);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Verify administrative privileges.
|
|
//
|
|
if (!IsAdmin())
|
|
{
|
|
gbAll = FALSE;
|
|
}
|
|
|
|
//
|
|
// Load libraries.
|
|
//
|
|
if (!IsWindows9x() && gbAll)
|
|
{
|
|
LoadLibraries();
|
|
}
|
|
|
|
//
|
|
// Verify if the patch is installed.
|
|
//
|
|
if (IsEuroPatchInstalled())
|
|
{
|
|
//
|
|
// Apply Euro settings.
|
|
//
|
|
nbChanged = ApplyEuroSettings();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Broadcast the message that the international settings in the
|
|
// registry have changed.
|
|
//
|
|
if ((nbChanged != 0) &&
|
|
pfnBroadcastSystemMessage)
|
|
{
|
|
dwRecipients = BSM_APPLICATIONS | BSM_ALLDESKTOPS;
|
|
(*pfnBroadcastSystemMessage)( BSF_FORCEIFHUNG | BSF_IGNORECURRENTTASK |
|
|
BSF_NOHANG | BSF_NOTIMEOUTIFNOTHUNG,
|
|
&dwRecipients,
|
|
WM_WININICHANGE,
|
|
0,
|
|
(LPARAM)c_szIntl );
|
|
}
|
|
|
|
//
|
|
// Unload unneeded library
|
|
//
|
|
UnloadLibraries();
|
|
CleanUp(hOverrideEuroException);
|
|
|
|
// Make sure we return "failure" (non-zero) if no info was changed. This would
|
|
// apply to both (a) permission problems and (b) being outside the Euro zone.
|
|
return (((nbChanged != 0) ? 0 : -1));
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ParseCmdLine
|
|
//
|
|
// Parse the command line and search for supported argument.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL ParseCmdLine(LPSTR argIndex)
|
|
{
|
|
//
|
|
// Parse the command line.
|
|
//
|
|
while (argIndex = NextCommandArg(argIndex))
|
|
{
|
|
switch(*argIndex)
|
|
{
|
|
case('s'): // Silent mode
|
|
case('S'):
|
|
{
|
|
gbSilence = TRUE;
|
|
break;
|
|
}
|
|
case('c'): // Current user only
|
|
case('C'):
|
|
{
|
|
gbAll = FALSE;
|
|
break;
|
|
}
|
|
case('a'): // Exception
|
|
case('A'):
|
|
{
|
|
UINT nbException = 1;
|
|
UINT idx = 0;
|
|
LPSTR strPtrHead;
|
|
LPSTR strPtrTail;
|
|
BOOL bInsideQuote = FALSE;
|
|
|
|
//
|
|
// Change the separator used between each block in order to avoid
|
|
// mistake with the data itself inside the double quote.
|
|
//
|
|
strPtrHead = argIndex + 2;
|
|
while (*strPtrHead)
|
|
{
|
|
if (*strPtrHead == '"')
|
|
{
|
|
bInsideQuote = bInsideQuote ? FALSE : TRUE;
|
|
}
|
|
else if (*strPtrHead == ';')
|
|
{
|
|
if (!bInsideQuote)
|
|
{
|
|
*strPtrHead = '@';
|
|
}
|
|
}
|
|
strPtrHead++;
|
|
}
|
|
|
|
//
|
|
// Compute the number of exception override.
|
|
//
|
|
strPtrHead = argIndex + 2;
|
|
while (strPtrHead = strchr(strPtrHead, '@'))
|
|
{
|
|
strPtrHead++;
|
|
nbException++;
|
|
}
|
|
|
|
//
|
|
// Allocation a structure for exception override.
|
|
//
|
|
if (!(hOverrideEuroException = GlobalAlloc(GHND, sizeof(EURO_EXCEPTION)*nbException)))
|
|
{
|
|
return (FALSE);
|
|
}
|
|
gOverrideEuroException = GlobalLock(hOverrideEuroException);
|
|
gNbOverrideEuroException = nbException;
|
|
|
|
//
|
|
// Fill out the structure.
|
|
//
|
|
strPtrHead = argIndex + 2;
|
|
while (idx < nbException)
|
|
{
|
|
CHAR buffer[128];
|
|
UINT strLen;
|
|
//
|
|
// Extract the exception override information.
|
|
//
|
|
if (strPtrTail = strchr(strPtrHead, '@'))
|
|
{
|
|
strLen = (UINT)(strPtrTail - strPtrHead);
|
|
}
|
|
else
|
|
{
|
|
strLen = strlen(strPtrHead);
|
|
}
|
|
|
|
//
|
|
// Copy the triplet.
|
|
//
|
|
strncpy(buffer, strPtrHead, strLen + 1);
|
|
|
|
//
|
|
// Add to the exception override list.
|
|
//
|
|
AddExceptionOverride(&gOverrideEuroException[idx], buffer);
|
|
|
|
//
|
|
// Next triplet.
|
|
//
|
|
if (strPtrTail)
|
|
{
|
|
strPtrHead = strPtrTail + 1;
|
|
}
|
|
idx++;
|
|
}
|
|
|
|
break;
|
|
}
|
|
#ifdef DEBUG
|
|
case('z'): // private flag for disabling the patch detection.
|
|
case('Z'):
|
|
{
|
|
gbPatchCheck = FALSE;
|
|
break;
|
|
}
|
|
#endif // DEBUG
|
|
case('h'): // Usage
|
|
case('H'): // Usage
|
|
case('?'):
|
|
{
|
|
Usage();
|
|
return (FALSE);
|
|
}
|
|
default:
|
|
{
|
|
//
|
|
// Usage.
|
|
//
|
|
if (!gbSilence)
|
|
{
|
|
Usage();
|
|
}
|
|
return (FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ApplyEuroSettings
|
|
//
|
|
// Apply new Euro settings to the current user and/or to all user.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
DWORD ApplyEuroSettings()
|
|
{
|
|
HCURSOR hcurSave;
|
|
DWORD nbChanged;
|
|
|
|
//
|
|
// Show hour glass
|
|
//
|
|
hcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
//
|
|
// Update available registry information.
|
|
//
|
|
nbChanged = ApplyEuroSettingsToRegistry();
|
|
|
|
//
|
|
// This is not complete because Windows NT security don't
|
|
// allows to change other users because information in
|
|
// registry is not available
|
|
//
|
|
if (!IsWindows9x())
|
|
{
|
|
//
|
|
// Update all NTUSER.DAT file. This way we can update all users.
|
|
//
|
|
nbChanged += ApplyEuroSettingsToFile();
|
|
}
|
|
|
|
//
|
|
// Revert cursor and return number changed.
|
|
//
|
|
SetCursor(hcurSave);
|
|
return (nbChanged);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ApplyEuroSettingsToFile
|
|
//
|
|
// Apply new Euro settings to the current user and/or to all user.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
DWORD ApplyEuroSettingsToFile()
|
|
{
|
|
LCID locale;
|
|
PEURO_EXCEPTION pInfo;
|
|
DWORD nbAffected = 0;
|
|
|
|
//
|
|
// Proceed with all users if requested.
|
|
//
|
|
if (gbAll)
|
|
{
|
|
CHAR docFolder[MAX_PATH] = {0};
|
|
CHAR userFileData[MAX_PATH] = {0};
|
|
CHAR searchPattern[MAX_PATH] = {0};
|
|
WIN32_FIND_DATA fileData;
|
|
HANDLE hList;
|
|
|
|
//
|
|
// Get Documents and Settings folder
|
|
//
|
|
if (!GetDocumentAndSettingsFolder(docFolder))
|
|
{
|
|
return (nbAffected);
|
|
}
|
|
|
|
//
|
|
// Append a wildcard after the directory path to find
|
|
// out all files/folders under it.
|
|
//
|
|
|
|
//strcpy(searchPattern, docFolder);
|
|
//strcat(searchPattern, "\\*.*");
|
|
StringCbCopy(searchPattern, MAX_PATH, docFolder);
|
|
StringCbCatA(searchPattern, MAX_PATH, "\\*.*");
|
|
|
|
//
|
|
// List all files/folder under the profile directory
|
|
//
|
|
hList = FindFirstFile(searchPattern, &fileData);
|
|
if (hList == INVALID_HANDLE_VALUE)
|
|
{
|
|
return (nbAffected);
|
|
}
|
|
|
|
//
|
|
// Search through the Documents and settings folder for users.
|
|
//
|
|
do
|
|
{
|
|
//
|
|
// Check if it's a directory
|
|
//
|
|
if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
//
|
|
// Build a full path for the User data file.
|
|
//
|
|
//strcpy(userFileData, docFolder);
|
|
//strcat(userFileData, "\\");
|
|
//strcat(userFileData, fileData.cFileName);
|
|
//strcat(userFileData, "\\NTUSER.DAT");
|
|
StringCbCopy(userFileData, MAX_PATH, docFolder);
|
|
StringCbCatA(userFileData, MAX_PATH, "\\");
|
|
StringCbCatA(userFileData, MAX_PATH, fileData.cFileName);
|
|
StringCbCatA(userFileData, MAX_PATH, "\\NTUSER.DAT");
|
|
|
|
//
|
|
// Check if the file is associated to a valid user and
|
|
// get user locale from the user data file.
|
|
//
|
|
if (IsValidUserDataFile(userFileData) &&
|
|
(locale = GetLocaleFromFile(userFileData)))
|
|
{
|
|
//
|
|
// Search for an exception.
|
|
//
|
|
if ((pInfo = GetLocaleOverrideInfo(locale)) != NULL)
|
|
{
|
|
if( UpdateFileLocaleInfo(userFileData, pInfo))
|
|
{
|
|
nbAffected++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
while (FindNextFile(hList, &fileData));
|
|
|
|
//
|
|
// Close handle.
|
|
//
|
|
FindClose(hList);
|
|
}
|
|
|
|
return (nbAffected);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ApplyEuroSettingsToRegistry
|
|
//
|
|
// Apply new Euro settings to the current user and/or to all user.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
DWORD ApplyEuroSettingsToRegistry()
|
|
{
|
|
LCID locale;
|
|
PEURO_EXCEPTION pInfo;
|
|
DWORD nbAffected = 0;
|
|
|
|
//
|
|
// Proceed with all users if requested.
|
|
//
|
|
if (gbAll)
|
|
{
|
|
DWORD dwKeyLength, dwKeyIndex = 0;
|
|
CHAR szKey[REGSTR_MAX_VALUE_LENGTH]; // this should be dynamic.
|
|
HKEY hKey;
|
|
DWORD lRet;
|
|
LPSTR endPtr;
|
|
|
|
//
|
|
// Go through all users for registry settings.
|
|
//
|
|
for (;;)
|
|
{
|
|
dwKeyLength = REGSTR_MAX_VALUE_LENGTH;
|
|
lRet = RegEnumKeyEx( HKEY_USERS,
|
|
dwKeyIndex,
|
|
szKey,
|
|
&dwKeyLength,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
if (lRet == ERROR_NO_MORE_ITEMS)
|
|
{
|
|
lRet = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
else if (lRet == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Open the registry
|
|
//
|
|
if (RegOpenKeyEx( HKEY_USERS,
|
|
szKey,
|
|
0,
|
|
KEY_READ,
|
|
&hKey) == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Get user locale
|
|
//
|
|
if (locale = GetLocaleFromRegistry(hKey))
|
|
{
|
|
//
|
|
// Search for an exception.
|
|
//
|
|
if ((pInfo = GetLocaleOverrideInfo(locale)) != NULL)
|
|
{
|
|
if (UpdateRegLocaleInfo(hKey, pInfo))
|
|
{
|
|
nbAffected++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close handle
|
|
//
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Next keys
|
|
//
|
|
++dwKeyIndex;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Update current user settings.
|
|
//
|
|
locale = GetUserDefaultLCID();
|
|
if ((pInfo = GetLocaleOverrideInfo(locale)) != NULL)
|
|
{
|
|
if (UpdateRegLocaleInfo(HKEY_CURRENT_USER, pInfo))
|
|
{
|
|
nbAffected++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (nbAffected);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetLocaleOverrideInfo
|
|
//
|
|
// Search for locale information that need to be updated. First, search in
|
|
// the default table. Second, search in the override table for more locales.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
PEURO_EXCEPTION GetLocaleOverrideInfo(LCID locale)
|
|
{
|
|
UINT idx;
|
|
PEURO_EXCEPTION euroException = NULL;
|
|
|
|
//
|
|
// Search the base table. We still need to look in the second table even
|
|
// if found something in the first table because information can be
|
|
// overrided in the second table.
|
|
//
|
|
idx = 0;
|
|
while (idx < gNbBaseEuroException)
|
|
{
|
|
if (LANGIDFROMLCID(locale) == LANGIDFROMLCID(gBaseEuroException[idx].dwLocale))
|
|
{
|
|
euroException = &gBaseEuroException[idx];
|
|
break;
|
|
}
|
|
idx++;
|
|
}
|
|
|
|
//
|
|
// Search the override table.
|
|
//
|
|
idx = 0;
|
|
while (idx < gNbOverrideEuroException)
|
|
{
|
|
if (LANGIDFROMLCID(locale) == LANGIDFROMLCID(gOverrideEuroException[idx].dwLocale))
|
|
{
|
|
euroException = &gOverrideEuroException[idx];
|
|
break;
|
|
}
|
|
idx++;
|
|
}
|
|
|
|
return (euroException);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// UpdateRegLocaleInfo
|
|
//
|
|
// Update the registry values sCurrency, sMonDecimalSep and iCurrDigits if
|
|
// needed. Before applying the Decimal separator, we check is the Thousand
|
|
// separator is the same to the value in our table. In the case, we need to
|
|
// replacement also the the Thousand separator with our data.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL UpdateRegLocaleInfo(HKEY hKey, PEURO_EXCEPTION pInfo)
|
|
{
|
|
HKEY hIntlKey = NULL;
|
|
BOOL bRet;
|
|
|
|
//
|
|
// Open the International registry key.
|
|
//
|
|
if(RegOpenKeyEx( hKey,
|
|
c_szCPanelIntl,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hIntlKey) != ERROR_SUCCESS)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Update specific registry entries
|
|
//
|
|
bRet = UpdateLocaleInfo(hIntlKey, pInfo);
|
|
|
|
//
|
|
// Clean Up
|
|
//
|
|
RegCloseKey(hIntlKey);
|
|
return (bRet);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// UpdateFileLocaleInfo
|
|
//
|
|
// Update the registry values sCurrency, sMonDecimalSep and iCurrDigits if
|
|
// needed. Before applying the Decimal separator, we check is the Thousand
|
|
// separator is the same to the value in our table. In the case, we need to
|
|
// replacement also the the Thousand separator with our data.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL UpdateFileLocaleInfo(LPCSTR szProfile, PEURO_EXCEPTION pInfo)
|
|
{
|
|
HKEY hIntlKey = NULL;
|
|
BOOL bRet;
|
|
BOOLEAN wasEnabled;
|
|
|
|
//
|
|
// Load hive.
|
|
//
|
|
if ((hIntlKey = LoadHive( szProfile,
|
|
TEXT("TempKey"),
|
|
c_szCPanelIntl,
|
|
&wasEnabled )) == NULL)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Update specific registry entries
|
|
//
|
|
bRet = UpdateLocaleInfo(hIntlKey, pInfo);
|
|
|
|
//
|
|
// Unload hive
|
|
//
|
|
RegCloseKey(hIntlKey);
|
|
UnloadHive(TEXT("TempKey"), &wasEnabled);
|
|
return (bRet);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// UpdateLocaleInfo
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL UpdateLocaleInfo(HKEY hIntlKey, PEURO_EXCEPTION pInfo)
|
|
{
|
|
//
|
|
// Update the sCurrency value. We have to use the Unicode version for
|
|
// Windows NTx because the euro character doesn't have the same ANSI
|
|
// value depending of the System Locale and it's associated Code Page.
|
|
// using the Unicode value fixes the problem.
|
|
//
|
|
if (IsWindows9x())
|
|
{
|
|
//
|
|
// If the ACP code page is 1251, we need to store the proper value
|
|
// for the euro symbol.
|
|
//
|
|
if (GetACP() == 1251)
|
|
{
|
|
RegSetValueExA( hIntlKey,
|
|
c_szCurrencySymbol,
|
|
0L,
|
|
REG_SZ,
|
|
(CONST BYTE *)"\x88",
|
|
strlen("\x88") + 1);
|
|
}
|
|
else
|
|
{
|
|
RegSetValueExA( hIntlKey,
|
|
c_szCurrencySymbol,
|
|
0L,
|
|
REG_SZ,
|
|
(CONST BYTE *)"\x80",
|
|
strlen("\x80") + 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RegSetValueExW( hIntlKey,
|
|
c_wszCurrencySymbol,
|
|
0L,
|
|
REG_SZ,
|
|
(CONST BYTE *)L"\x20AC",
|
|
wcslen(L"\x20AC") + 1);
|
|
}
|
|
|
|
//
|
|
// Update the sMonDecimalSep value.
|
|
//
|
|
if( pInfo->chDecimalSep[0] != '\0' )
|
|
{
|
|
RegSetValueEx( hIntlKey,
|
|
c_szCurrencyDecimalSep,
|
|
0L,
|
|
REG_SZ,
|
|
(CONST BYTE *)pInfo->chDecimalSep,
|
|
strlen(pInfo->chDecimalSep)+1);
|
|
}
|
|
|
|
//
|
|
// Update the iCurrDigits value if needed.
|
|
//
|
|
if( pInfo->chDigits[0] != '\0' )
|
|
{
|
|
RegSetValueEx( hIntlKey,
|
|
c_szCurrencyDigits,
|
|
0L,
|
|
REG_SZ,
|
|
(CONST BYTE *)pInfo->chDigits,
|
|
strlen(pInfo->chDigits)+1);
|
|
}
|
|
|
|
//
|
|
// Update the SMonThousandSep value.
|
|
//
|
|
if( pInfo->chThousandSep[0] != '\0' )
|
|
{
|
|
RegSetValueEx( hIntlKey,
|
|
c_szCurrencyThousandSep,
|
|
0L,
|
|
REG_SZ,
|
|
(CONST BYTE *)pInfo->chThousandSep,
|
|
strlen(pInfo->chThousandSep)+1);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Usage
|
|
//
|
|
// Show command line Usage.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void Usage()
|
|
{
|
|
TCHAR szMsg[MAX_PATH*8];
|
|
|
|
if (LoadString(ghInstance, IDS_USAGE, szMsg, MAX_PATH*8))
|
|
{
|
|
ShowMsg(NULL, IDS_USAGE, IDS_TITLE, MB_OK);
|
|
}
|
|
}
|