mirror of
https://github.com/reactos/reactos.git
synced 2024-10-04 16:36:11 +00:00
- Implement EnumSystemLanguageGroupsA/W
- Implement EnumSystemLocalesA - Reimplement EnumSystemLocalesW svn path=/trunk/; revision=33837
This commit is contained in:
parent
1f7ff705dd
commit
6ed534a3b0
|
@ -53,6 +53,13 @@ static const WCHAR szLocaleKeyName[] =
|
|||
'C','o','n','t','r','o','l','\\','N','l','s','\\','L','o','c','a','l','e',0
|
||||
};
|
||||
|
||||
static const WCHAR szLangGroupsKeyName[] = {
|
||||
'M','a','c','h','i','n','e','\\','S','y','s','t','e','m','\\',
|
||||
'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
|
||||
'C','o','n','t','r','o','l','\\','N','l','s','\\',
|
||||
'L','a','n','g','u','a','g','e',' ','G','r','o','u','p','s',0
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* @implemented
|
||||
* RIPPED FROM WINE's dlls\kernel\locale.c rev 1.42
|
||||
|
@ -326,6 +333,47 @@ static BOOL NLS_RegGetDword(HANDLE hKey, LPCWSTR szValueName, DWORD *lpVal)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL NLS_GetLanguageGroupName(LGRPID lgrpid, LPWSTR szName, ULONG nameSize)
|
||||
{
|
||||
LANGID langId;
|
||||
LPCWSTR szResourceName = MAKEINTRESOURCEW(((lgrpid + 0x2000) >> 4) + 1);
|
||||
HRSRC hResource;
|
||||
BOOL bRet = FALSE;
|
||||
|
||||
/* FIXME: Is it correct to use the system default langid? */
|
||||
langId = GetSystemDefaultLangID();
|
||||
|
||||
if (SUBLANGID(langId) == SUBLANG_NEUTRAL)
|
||||
langId = MAKELANGID( PRIMARYLANGID(langId), SUBLANG_DEFAULT );
|
||||
|
||||
hResource = FindResourceExW( hCurrentModule, (LPWSTR)RT_STRING, szResourceName, langId );
|
||||
|
||||
if (hResource)
|
||||
{
|
||||
HGLOBAL hResDir = LoadResource( hCurrentModule, hResource );
|
||||
|
||||
if (hResDir)
|
||||
{
|
||||
ULONG iResourceIndex = lgrpid & 0xf;
|
||||
LPCWSTR lpResEntry = LockResource( hResDir );
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < iResourceIndex; i++)
|
||||
lpResEntry += *lpResEntry + 1;
|
||||
|
||||
if (*lpResEntry < nameSize)
|
||||
{
|
||||
memcpy( szName, lpResEntry + 1, *lpResEntry * sizeof(WCHAR) );
|
||||
szName[*lpResEntry] = '\0';
|
||||
bRet = TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
FreeResource( hResource );
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
/* Callback function ptrs for EnumLanguageGrouplocalesA/W */
|
||||
typedef struct
|
||||
|
@ -364,7 +412,10 @@ static BOOL NLS_EnumLanguageGroupLocales(ENUMLANGUAGEGROUPLOCALE_CALLBACKS *lpPr
|
|||
hKey = NLS_RegOpenKey( 0, szLocaleKeyName );
|
||||
|
||||
if (!hKey)
|
||||
DPRINT("NLS registry key not found. Please apply the default registry file 'wine.inf'\n");
|
||||
{
|
||||
DPRINT1("NLS_RegOpenKey() failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (bContinue)
|
||||
{
|
||||
|
@ -661,8 +712,108 @@ EnumSystemGeoID(
|
|||
}
|
||||
|
||||
|
||||
/* Callback function ptrs for EnumSystemLanguageGroupsA/W */
|
||||
typedef struct
|
||||
{
|
||||
LANGUAGEGROUP_ENUMPROCA procA;
|
||||
LANGUAGEGROUP_ENUMPROCW procW;
|
||||
DWORD dwFlags;
|
||||
LONG_PTR lParam;
|
||||
} ENUMLANGUAGEGROUP_CALLBACKS;
|
||||
|
||||
|
||||
/* Internal implementation of EnumSystemLanguageGroupsA/W */
|
||||
static BOOL NLS_EnumSystemLanguageGroups(ENUMLANGUAGEGROUP_CALLBACKS *lpProcs)
|
||||
{
|
||||
WCHAR szNumber[10], szValue[4];
|
||||
HANDLE hKey;
|
||||
BOOL bContinue = TRUE;
|
||||
ULONG ulIndex = 0;
|
||||
|
||||
if (!lpProcs)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (lpProcs->dwFlags)
|
||||
{
|
||||
case 0:
|
||||
/* Default to LGRPID_INSTALLED */
|
||||
lpProcs->dwFlags = LGRPID_INSTALLED;
|
||||
/* Fall through... */
|
||||
case LGRPID_INSTALLED:
|
||||
case LGRPID_SUPPORTED:
|
||||
break;
|
||||
default:
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hKey = NLS_RegOpenKey( 0, szLangGroupsKeyName );
|
||||
|
||||
if (!hKey)
|
||||
{
|
||||
DPRINT1("NLS_RegOpenKey() failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (bContinue)
|
||||
{
|
||||
if (NLS_RegEnumValue( hKey, ulIndex, szNumber, sizeof(szNumber),
|
||||
szValue, sizeof(szValue) ))
|
||||
{
|
||||
BOOL bInstalled = szValue[0] == '1' ? TRUE : FALSE;
|
||||
LGRPID lgrpid = wcstoul( szNumber, NULL, 16 );
|
||||
|
||||
DPRINT("grpid %s (%sinstalled)\n", szNumber,
|
||||
bInstalled ? "" : "not ");
|
||||
|
||||
if (lpProcs->dwFlags == LGRPID_SUPPORTED || bInstalled)
|
||||
{
|
||||
WCHAR szGrpName[48];
|
||||
|
||||
if (!NLS_GetLanguageGroupName( lgrpid, szGrpName, sizeof(szGrpName) / sizeof(WCHAR) ))
|
||||
szGrpName[0] = '\0';
|
||||
|
||||
if (lpProcs->procW)
|
||||
bContinue = lpProcs->procW( lgrpid, szNumber, szGrpName, lpProcs->dwFlags,
|
||||
lpProcs->lParam );
|
||||
else
|
||||
{
|
||||
char szNumberA[sizeof(szNumber)/sizeof(WCHAR)];
|
||||
char szGrpNameA[48];
|
||||
|
||||
/* FIXME: MSDN doesn't say which code page the W->A translation uses,
|
||||
* or whether the language names are ever localised. Assume CP_ACP.
|
||||
*/
|
||||
|
||||
WideCharToMultiByte(CP_ACP, 0, szNumber, -1, szNumberA, sizeof(szNumberA), 0, 0);
|
||||
WideCharToMultiByte(CP_ACP, 0, szGrpName, -1, szGrpNameA, sizeof(szGrpNameA), 0, 0);
|
||||
|
||||
bContinue = lpProcs->procA( lgrpid, szNumberA, szGrpNameA, lpProcs->dwFlags,
|
||||
lpProcs->lParam );
|
||||
}
|
||||
}
|
||||
|
||||
ulIndex++;
|
||||
}
|
||||
else
|
||||
bContinue = FALSE;
|
||||
|
||||
if (!bContinue)
|
||||
break;
|
||||
}
|
||||
|
||||
if (hKey)
|
||||
NtClose( hKey );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
STDCALL
|
||||
|
@ -671,27 +822,21 @@ EnumSystemLanguageGroupsA(
|
|||
DWORD dwFlags,
|
||||
LONG_PTR lParam)
|
||||
{
|
||||
ENUMLANGUAGEGROUP_CALLBACKS procs;
|
||||
|
||||
DPRINT("(%p,0x%08X,0x%08lX)\n", pLangGroupEnumProc, dwFlags, lParam);
|
||||
|
||||
if ((!dwFlags & LGRPID_INSTALLED)&&(!dwFlags & LGRPID_SUPPORTED))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
return FALSE;
|
||||
}
|
||||
procs.procA = pLangGroupEnumProc;
|
||||
procs.procW = NULL;
|
||||
procs.dwFlags = dwFlags;
|
||||
procs.lParam = lParam;
|
||||
|
||||
if (!pLangGroupEnumProc)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return 0;
|
||||
return NLS_EnumSystemLanguageGroups( pLangGroupEnumProc ? &procs : NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
STDCALL
|
||||
|
@ -700,27 +845,99 @@ EnumSystemLanguageGroupsW(
|
|||
DWORD dwFlags,
|
||||
LONG_PTR lParam)
|
||||
{
|
||||
ENUMLANGUAGEGROUP_CALLBACKS procs;
|
||||
|
||||
DPRINT("(%p,0x%08X,0x%08lX)\n", pLangGroupEnumProc, dwFlags, lParam);
|
||||
|
||||
if ((!dwFlags & LGRPID_INSTALLED)&&(!dwFlags & LGRPID_SUPPORTED))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
return FALSE;
|
||||
}
|
||||
procs.procA = NULL;
|
||||
procs.procW = pLangGroupEnumProc;
|
||||
procs.dwFlags = dwFlags;
|
||||
procs.lParam = lParam;
|
||||
|
||||
if (!pLangGroupEnumProc)
|
||||
return NLS_EnumSystemLanguageGroups( pLangGroupEnumProc ? &procs : NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Callback function ptrs for EnumSystemLocalesA/W */
|
||||
typedef struct
|
||||
{
|
||||
LOCALE_ENUMPROCA procA;
|
||||
LOCALE_ENUMPROCW procW;
|
||||
DWORD dwFlags;
|
||||
} ENUMSYSTEMLOCALES_CALLBACKS;
|
||||
|
||||
|
||||
/* Internal implementation of EnumSystemLocalesA/W */
|
||||
static BOOL NLS_EnumSystemLocales(ENUMSYSTEMLOCALES_CALLBACKS *lpProcs)
|
||||
{
|
||||
WCHAR szNumber[10], szValue[4];
|
||||
HANDLE hKey;
|
||||
BOOL bContinue = TRUE;
|
||||
ULONG ulIndex = 0;
|
||||
|
||||
if (!lpProcs)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return 0;
|
||||
switch (lpProcs->dwFlags)
|
||||
{
|
||||
case LCID_INSTALLED:
|
||||
case LCID_SUPPORTED:
|
||||
case LCID_ALTERNATE_SORTS:
|
||||
break;
|
||||
default:
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hKey = NLS_RegOpenKey(0, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Locale");
|
||||
|
||||
if (!hKey)
|
||||
{
|
||||
DPRINT1("NLS_RegOpenKey() failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (bContinue)
|
||||
{
|
||||
if (NLS_RegEnumValue( hKey, ulIndex, szNumber, sizeof(szNumber),
|
||||
szValue, sizeof(szValue)))
|
||||
{
|
||||
if ((lpProcs->dwFlags == LCID_SUPPORTED)||
|
||||
((lpProcs->dwFlags == LCID_INSTALLED)&&(wcslen(szValue) > 0)))
|
||||
{
|
||||
if (lpProcs->procW)
|
||||
{
|
||||
bContinue = lpProcs->procW(szNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
char szNumberA[sizeof(szNumber)/sizeof(WCHAR)];
|
||||
|
||||
WideCharToMultiByte(CP_ACP, 0, szNumber, -1, szNumberA, sizeof(szNumberA), 0, 0);
|
||||
bContinue = lpProcs->procA(szNumberA);
|
||||
}
|
||||
}
|
||||
|
||||
ulIndex++;
|
||||
}
|
||||
else
|
||||
bContinue = FALSE;
|
||||
|
||||
if (!bContinue)
|
||||
break;
|
||||
}
|
||||
|
||||
if (hKey)
|
||||
NtClose(hKey);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
STDCALL
|
||||
|
@ -729,8 +946,15 @@ EnumSystemLocalesA (
|
|||
DWORD dwFlags
|
||||
)
|
||||
{
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
ENUMSYSTEMLOCALES_CALLBACKS procs;
|
||||
|
||||
DPRINT("(%p,0x%08X)\n", lpLocaleEnumProc, dwFlags);
|
||||
|
||||
procs.procA = lpLocaleEnumProc;
|
||||
procs.procW = NULL;
|
||||
procs.dwFlags = dwFlags;
|
||||
|
||||
return NLS_EnumSystemLocales(lpLocaleEnumProc ? &procs : NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -744,89 +968,15 @@ EnumSystemLocalesW (
|
|||
DWORD dwFlags
|
||||
)
|
||||
{
|
||||
NTSTATUS result;
|
||||
HANDLE langKey;
|
||||
UNICODE_STRING langKeyName = RTL_CONSTANT_STRING(
|
||||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Locale");
|
||||
OBJECT_ATTRIBUTES objectAttributes;
|
||||
ULONG index, length;
|
||||
unsigned char fullInfo[sizeof(KEY_VALUE_FULL_INFORMATION)+255*2]; //FIXME: MAX_PATH*2
|
||||
PKEY_VALUE_FULL_INFORMATION pFullInfo;
|
||||
ENUMSYSTEMLOCALES_CALLBACKS procs;
|
||||
|
||||
//TODO: Combine with EnumSystemLocalesA - maybe by having one common part, driven by some
|
||||
// unicode/non-unicode flag.
|
||||
DPRINT("(%p,0x%08X)\n", lpLocaleEnumProc, dwFlags);
|
||||
|
||||
//FIXME: dwFlags is really not used, sorry
|
||||
procs.procA = NULL;
|
||||
procs.procW = lpLocaleEnumProc;
|
||||
procs.dwFlags = dwFlags;
|
||||
|
||||
// Check if enum proc is a real one
|
||||
if (lpLocaleEnumProc == NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Open language registry key
|
||||
//FIXME: Should we use critical section here?
|
||||
|
||||
InitializeObjectAttributes(&objectAttributes,
|
||||
&langKeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
result = NtOpenKey(&langKey,
|
||||
KEY_READ,
|
||||
&objectAttributes);
|
||||
|
||||
if (!NT_SUCCESS(result))
|
||||
return result;
|
||||
|
||||
DPRINT("Registry key succesfully opened\n");
|
||||
|
||||
length = sizeof(KEY_VALUE_FULL_INFORMATION) + 255*2;//MAX_PATH*sizeof(WCHAR);
|
||||
pFullInfo = (PKEY_VALUE_FULL_INFORMATION)&fullInfo;
|
||||
RtlZeroMemory(pFullInfo, length);
|
||||
|
||||
index = 0;
|
||||
|
||||
result = NtEnumerateValueKey(langKey,
|
||||
index,
|
||||
KeyValueFullInformation,
|
||||
pFullInfo,
|
||||
length,
|
||||
&length);
|
||||
|
||||
DPRINT("First enumerate call result=%x\n", result);
|
||||
while (result != STATUS_NO_MORE_ENTRIES)
|
||||
{
|
||||
int i;
|
||||
WCHAR lpLocale[9];
|
||||
|
||||
// TODO: Here we should check, in case dwFlags & LCID_INSTALLED is specified,
|
||||
// if this locale is really installed
|
||||
// but for now we skip it
|
||||
|
||||
for (i=0; i<8; i++)
|
||||
lpLocale[i] = pFullInfo->Name[i];
|
||||
|
||||
lpLocale[8]=0;
|
||||
|
||||
DPRINT("Locale=%S\n", lpLocale);
|
||||
|
||||
// Call Enum func
|
||||
if (!lpLocaleEnumProc((LPWSTR)lpLocale))
|
||||
break;
|
||||
|
||||
// Zero previous values
|
||||
RtlZeroMemory(pFullInfo, length);
|
||||
|
||||
index++;
|
||||
result = NtEnumerateValueKey(langKey, index,KeyValueFullInformation, pFullInfo, length, &length);
|
||||
}
|
||||
|
||||
NtClose(langKey);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return NLS_EnumSystemLocales(lpLocaleEnumProc ? &procs : NULL);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue