Author: dchapyshev Date: Tue Jun 3 08:20:41 2008 New Revision: 33837
URL: http://svn.reactos.org/svn/reactos?rev=33837&view=rev Log: - Implement EnumSystemLanguageGroupsA/W - Implement EnumSystemLocalesA - Reimplement EnumSystemLocalesW
Modified: trunk/reactos/dll/win32/kernel32/misc/lang.c
Modified: trunk/reactos/dll/win32/kernel32/misc/lang.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/misc/lan... ============================================================================== --- trunk/reactos/dll/win32/kernel32/misc/lang.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/misc/lang.c [iso-8859-1] Tue Jun 3 08:20:41 2008 @@ -53,6 +53,13 @@ '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 @@ 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 @@ 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 @@ }
-/* - * @unimplemented +/* 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; +} + + +/* + * @implemented */ BOOL STDCALL @@ -671,27 +822,21 @@ 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; - } - - if (!pLangGroupEnumProc) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} - - -/* - * @unimplemented + procs.procA = pLangGroupEnumProc; + procs.procW = NULL; + procs.dwFlags = dwFlags; + procs.lParam = lParam; + + return NLS_EnumSystemLanguageGroups( pLangGroupEnumProc ? &procs : NULL); +} + + +/* + * @implemented */ BOOL STDCALL @@ -700,27 +845,99 @@ 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; - } - - if (!pLangGroupEnumProc) + procs.procA = NULL; + procs.procW = pLangGroupEnumProc; + procs.dwFlags = dwFlags; + procs.lParam = lParam; + + 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; -} - - -/* - * @unimplemented + 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; +} + +/* + * @implemented */ BOOL STDCALL @@ -729,8 +946,15 @@ 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 @@ 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; - - //TODO: Combine with EnumSystemLocalesA - maybe by having one common part, driven by some - // unicode/non-unicode flag. - - //FIXME: dwFlags is really not used, sorry - - // 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; + ENUMSYSTEMLOCALES_CALLBACKS procs; + + DPRINT("(%p,0x%08X)\n", lpLocaleEnumProc, dwFlags); + + procs.procA = NULL; + procs.procW = lpLocaleEnumProc; + procs.dwFlags = dwFlags; + + return NLS_EnumSystemLocales(lpLocaleEnumProc ? &procs : NULL); }