Author: akhaldi
Date: Wed Oct 22 16:40:54 2014
New Revision: 64891
URL:
http://svn.reactos.org/svn/reactos?rev=64891&view=rev
Log:
[KERNEL32]
* Replace EnumSystemGeoID with the one from Wine 1.7.27.
* Fixes some kernel32:locale tests.
CORE-8540
Modified:
trunk/reactos/dll/win32/kernel32/winnls/string/lang.c
Modified: trunk/reactos/dll/win32/kernel32/winnls/string/lang.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/winnls/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/winnls/string/lang.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/winnls/string/lang.c [iso-8859-1] Wed Oct 22 16:40:54
2014
@@ -2272,420 +2272,6 @@
return TRUE;
}
-/******************************************************************************
- * EnumLanguageGroupLocalesA (KERNEL32.@)
- *
- * Call a users function for every locale in a language group available on the system.
- *
- * PARAMS
- * pLangGrpLcEnumProc [I] Callback function to call for each locale
- * lgrpid [I] Language group (LGRPID_ values from "winnls.h")
- * dwFlags [I] Reserved, set to 0
- * lParam [I] User parameter to pass to pLangGrpLcEnumProc
- *
- * RETURNS
- * Success: TRUE.
- * Failure: FALSE. Use GetLastError() to determine the cause.
- */
-BOOL WINAPI EnumLanguageGroupLocalesA(LANGGROUPLOCALE_ENUMPROCA pLangGrpLcEnumProc,
- LGRPID lgrpid, DWORD dwFlags, LONG_PTR lParam)
-{
- ENUMLANGUAGEGROUPLOCALE_CALLBACKS callbacks;
-
- TRACE("(%p,0x%08X,0x%08X,0x%08lX)\n", pLangGrpLcEnumProc, lgrpid, dwFlags,
lParam);
-
- callbacks.procA = pLangGrpLcEnumProc;
- callbacks.procW = NULL;
- callbacks.dwFlags = dwFlags;
- callbacks.lgrpid = lgrpid;
- callbacks.lParam = lParam;
-
- return NLS_EnumLanguageGroupLocales( pLangGrpLcEnumProc ? &callbacks : NULL );
-}
-
-/******************************************************************************
- * EnumLanguageGroupLocalesW (KERNEL32.@)
- *
- * See EnumLanguageGroupLocalesA.
- */
-BOOL WINAPI EnumLanguageGroupLocalesW(LANGGROUPLOCALE_ENUMPROCW pLangGrpLcEnumProc,
- LGRPID lgrpid, DWORD dwFlags, LONG_PTR lParam)
-{
- ENUMLANGUAGEGROUPLOCALE_CALLBACKS callbacks;
-
- TRACE("(%p,0x%08X,0x%08X,0x%08lX)\n", pLangGrpLcEnumProc, lgrpid, dwFlags,
lParam);
-
- callbacks.procA = NULL;
- callbacks.procW = pLangGrpLcEnumProc;
- callbacks.dwFlags = dwFlags;
- callbacks.lgrpid = lgrpid;
- callbacks.lParam = lParam;
-
- return NLS_EnumLanguageGroupLocales( pLangGrpLcEnumProc ? &callbacks : NULL );
-}
-
-/* Callback function ptrs for EnumSystemCodePagesA/W */
-typedef struct
-{
- CODEPAGE_ENUMPROCA procA;
- CODEPAGE_ENUMPROCW procW;
- DWORD dwFlags;
-} ENUMSYSTEMCODEPAGES_CALLBACKS;
-
-/* Internal implementation of EnumSystemCodePagesA/W */
-static BOOL NLS_EnumSystemCodePages(ENUMSYSTEMCODEPAGES_CALLBACKS *lpProcs)
-{
- WCHAR szNumber[5 + 1], szValue[MAX_PATH];
- HANDLE hKey;
- BOOL bContinue = TRUE;
- ULONG ulIndex = 0;
-
- if (!lpProcs)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- switch (lpProcs->dwFlags)
- {
- case CP_INSTALLED:
- case CP_SUPPORTED:
- break;
- default:
- SetLastError(ERROR_INVALID_FLAGS);
- return FALSE;
- }
-
- hKey = NLS_RegOpenKey(0,
L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage");
- if (!hKey)
- {
- WARN("NLS_RegOpenKey() failed\n");
- return FALSE;
- }
-
- while (bContinue)
- {
- if (NLS_RegEnumValue(hKey, ulIndex, szNumber, sizeof(szNumber),
- szValue, sizeof(szValue)))
- {
- if ((lpProcs->dwFlags == CP_SUPPORTED)||
- ((lpProcs->dwFlags == CP_INSTALLED)&&(wcslen(szValue) >
2)))
- {
- 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
-WINAPI
-EnumSystemCodePagesW (
- CODEPAGE_ENUMPROCW lpCodePageEnumProc,
- DWORD dwFlags
- )
-{
- ENUMSYSTEMCODEPAGES_CALLBACKS procs;
-
- TRACE("(%p,0x%08X,0x%08lX)\n", lpCodePageEnumProc, dwFlags);
-
- procs.procA = NULL;
- procs.procW = lpCodePageEnumProc;
- procs.dwFlags = dwFlags;
-
- return NLS_EnumSystemCodePages(lpCodePageEnumProc ? &procs : NULL);
-}
-
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-EnumSystemCodePagesA (
- CODEPAGE_ENUMPROCA lpCodePageEnumProc,
- DWORD dwFlags
- )
-{
- ENUMSYSTEMCODEPAGES_CALLBACKS procs;
-
- TRACE("(%p,0x%08X,0x%08lX)\n", lpCodePageEnumProc, dwFlags);
-
- procs.procA = lpCodePageEnumProc;
- procs.procW = NULL;
- procs.dwFlags = dwFlags;
-
- return NLS_EnumSystemCodePages(lpCodePageEnumProc ? &procs : NULL);
-}
-/******************************************************************************
- * EnumSystemGeoID (KERNEL32.@)
- *
- * Call a users function for every location available on the system.
- *
- * PARAMS
- * geoclass [I] Type of information desired (SYSGEOTYPE enum from
"winnls.h")
- * reserved [I] Reserved, set to 0
- * pGeoEnumProc [I] Callback function to call for each location
- *
- * RETURNS
- * Success: TRUE.
- * Failure: FALSE. Use GetLastError() to determine the cause.
- */
-BOOL WINAPI EnumSystemGeoID(GEOCLASS geoclass, GEOID reserved, GEO_ENUMPROC
pGeoEnumProc)
-{
- static const WCHAR szCountryCodeValueName[] = {
-
'C','o','u','n','t','r','y','C','o','d','e','\0'
- };
- WCHAR szNumber[10];
- HANDLE hKey;
- ULONG ulIndex = 0;
-
- TRACE("(0x%08X,0x%08X,%p)\n", geoclass, reserved, pGeoEnumProc);
-
- if (geoclass != GEOCLASS_NATION || reserved || !pGeoEnumProc)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- hKey = NLS_RegOpenKey( 0, szCountryListName );
-
- while (NLS_RegEnumSubKey( hKey, ulIndex, szNumber, sizeof(szNumber) ))
- {
- BOOL bContinue = TRUE;
- DWORD dwGeoId;
- HANDLE hSubKey = NLS_RegOpenKey( hKey, szNumber );
-
- if (hSubKey)
- {
- if (NLS_RegGetDword( hSubKey, szCountryCodeValueName, &dwGeoId ))
- {
- TRACE("Got geoid %d\n", dwGeoId);
-
- if (!pGeoEnumProc( dwGeoId ))
- bContinue = FALSE;
- }
-
- NtClose( hSubKey );
- }
-
- if (!bContinue)
- break;
-
- ulIndex++;
- }
-
- if (hKey)
- NtClose( hKey );
-
- return TRUE;
-}
-
-/******************************************************************************
- * InvalidateNLSCache (KERNEL32.@)
- *
- * Invalidate the cache of NLS values.
- *
- * PARAMS
- * None.
- *
- * RETURNS
- * Success: TRUE.
- * Failure: FALSE.
- */
-BOOL WINAPI InvalidateNLSCache(void)
-{
- FIXME("() stub\n");
- return FALSE;
-}
-
-/******************************************************************************
- * GetUserGeoID (KERNEL32.@)
- */
-GEOID WINAPI GetUserGeoID( GEOCLASS GeoClass )
-{
- GEOID ret = GEOID_NOT_AVAILABLE;
- static const WCHAR geoW[] = {'G','e','o',0};
- static const WCHAR nationW[] =
{'N','a','t','i','o','n',0};
- WCHAR bufferW[40], *end;
- DWORD count;
- HANDLE hkey, hSubkey = 0;
- UNICODE_STRING keyW;
- const KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION
*)bufferW;
- RtlInitUnicodeString( &keyW, nationW );
- count = sizeof(bufferW);
-
- if(!(hkey = create_registry_key())) return ret;
-
- switch( GeoClass ){
- case GEOCLASS_NATION:
- if ((hSubkey = NLS_RegOpenKey(hkey, geoW)))
- {
- if((NtQueryValueKey(hSubkey, &keyW, KeyValuePartialInformation,
- bufferW, count, &count) == STATUS_SUCCESS )
&& info->DataLength)
- ret = strtolW((LPCWSTR)info->Data, &end, 10);
- }
- break;
- case GEOCLASS_REGION:
- FIXME("GEOCLASS_REGION not handled yet\n");
- break;
- }
-
- NtClose(hkey);
- if (hSubkey) NtClose(hSubkey);
- return ret;
-}
-
-/******************************************************************************
- * SetUserGeoID (KERNEL32.@)
- */
-BOOL WINAPI SetUserGeoID( GEOID GeoID )
-{
- static const WCHAR geoW[] = {'G','e','o',0};
- static const WCHAR nationW[] =
{'N','a','t','i','o','n',0};
- static const WCHAR formatW[] = {'%','i',0};
- UNICODE_STRING nameW,keyW;
- WCHAR bufferW[10];
- OBJECT_ATTRIBUTES attr;
- HANDLE hkey;
-
- if(!(hkey = create_registry_key())) return FALSE;
-
- attr.Length = sizeof(attr);
- attr.RootDirectory = hkey;
- attr.ObjectName = &nameW;
- attr.Attributes = 0;
- attr.SecurityDescriptor = NULL;
- attr.SecurityQualityOfService = NULL;
- RtlInitUnicodeString( &nameW, geoW );
- RtlInitUnicodeString( &keyW, nationW );
-
- if (NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) !=
STATUS_SUCCESS)
-
- {
- NtClose(attr.RootDirectory);
- return FALSE;
- }
-
- sprintfW(bufferW, formatW, GeoID);
- NtSetValueKey(hkey, &keyW, 0, REG_SZ, bufferW, (strlenW(bufferW) + 1) *
sizeof(WCHAR));
- NtClose(attr.RootDirectory);
- NtClose(hkey);
- return TRUE;
-}
-
-typedef struct
-{
- union
- {
- UILANGUAGE_ENUMPROCA procA;
- UILANGUAGE_ENUMPROCW procW;
- } u;
- DWORD flags;
- LONG_PTR param;
-} ENUM_UILANG_CALLBACK;
-
-static BOOL CALLBACK enum_uilang_proc_a( HMODULE hModule, LPCSTR type,
- LPCSTR name, WORD LangID, LONG_PTR lParam )
-{
- ENUM_UILANG_CALLBACK *enum_uilang = (ENUM_UILANG_CALLBACK *)lParam;
- char buf[20];
-
- sprintf(buf, "%08x", (UINT)LangID);
- return enum_uilang->u.procA( buf, enum_uilang->param );
-}
-
-static BOOL CALLBACK enum_uilang_proc_w( HMODULE hModule, LPCWSTR type,
- LPCWSTR name, WORD LangID, LONG_PTR lParam )
-{
- static const WCHAR formatW[] = {'%','0','8','x',0};
- ENUM_UILANG_CALLBACK *enum_uilang = (ENUM_UILANG_CALLBACK *)lParam;
- WCHAR buf[20];
-
- sprintfW( buf, formatW, (UINT)LangID );
- return enum_uilang->u.procW( buf, enum_uilang->param );
-}
-
-/******************************************************************************
- * EnumUILanguagesA (KERNEL32.@)
- */
-BOOL WINAPI EnumUILanguagesA(UILANGUAGE_ENUMPROCA pUILangEnumProc, DWORD dwFlags,
LONG_PTR lParam)
-{
- ENUM_UILANG_CALLBACK enum_uilang;
-
- TRACE("%p, %x, %lx\n", pUILangEnumProc, dwFlags, lParam);
-
- if(!pUILangEnumProc) {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- if(dwFlags) {
- SetLastError(ERROR_INVALID_FLAGS);
- return FALSE;
- }
-
- enum_uilang.u.procA = pUILangEnumProc;
- enum_uilang.flags = dwFlags;
- enum_uilang.param = lParam;
-
- EnumResourceLanguagesA( kernel32_handle, (LPCSTR)RT_STRING,
- (LPCSTR)LOCALE_ILANGUAGE, enum_uilang_proc_a,
- (LONG_PTR)&enum_uilang);
- return TRUE;
-}
-
-/******************************************************************************
- * EnumUILanguagesW (KERNEL32.@)
- */
-BOOL WINAPI EnumUILanguagesW(UILANGUAGE_ENUMPROCW pUILangEnumProc, DWORD dwFlags,
LONG_PTR lParam)
-{
- ENUM_UILANG_CALLBACK enum_uilang;
-
- TRACE("%p, %x, %lx\n", pUILangEnumProc, dwFlags, lParam);
-
-
- if(!pUILangEnumProc) {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- if(dwFlags) {
- SetLastError(ERROR_INVALID_FLAGS);
- return FALSE;
- }
-
- enum_uilang.u.procW = pUILangEnumProc;
- enum_uilang.flags = dwFlags;
- enum_uilang.param = lParam;
-
- EnumResourceLanguagesW( kernel32_handle, (LPCWSTR)RT_STRING,
- (LPCWSTR)LOCALE_ILANGUAGE, enum_uilang_proc_w,
- (LONG_PTR)&enum_uilang);
- return TRUE;
-}
-
enum locationkind {
LOCATION_NATION = 0,
LOCATION_REGION,
@@ -2700,82 +2286,6 @@
INT uncode;
enum locationkind kind;
};
-
-static int
-NLS_GetGeoFriendlyName(GEOID Location, LPWSTR szFriendlyName, int cchData)
-{
- HANDLE hKey;
- WCHAR szPath[MAX_PATH];
- UNICODE_STRING ValueName;
- KEY_VALUE_PARTIAL_INFORMATION *info;
- const int info_size = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
- DWORD dwSize;
- NTSTATUS Status;
- int Ret;
-
- swprintf(szPath,
L"\\REGISTRY\\Machine\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Country
List\\%lu", Location);
-
- hKey = NLS_RegOpenKey(0, szPath);
- if (!hKey)
- {
- WARN("NLS_RegOpenKey() failed\n");
- return 0;
- }
-
- dwSize = info_size + cchData * sizeof(WCHAR);
-
- if (!(info = HeapAlloc(GetProcessHeap(), 0, dwSize)))
- {
- NtClose(hKey);
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return 0;
- }
-
- RtlInitUnicodeString(&ValueName, L"Name");
-
- Status = NtQueryValueKey(hKey, &ValueName, KeyValuePartialInformation,
- (LPBYTE)info, dwSize, &dwSize);
-
- if (!Status)
- {
- Ret = (dwSize - info_size) / sizeof(WCHAR);
-
- if (!Ret || ((WCHAR *)info->Data)[Ret-1])
- {
- if (Ret < cchData || !szFriendlyName) Ret++;
- else
- {
- WARN("ERROR_INSUFFICIENT_BUFFER\n");
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- Ret = 0;
- }
- }
-
- if (Ret && szFriendlyName)
- {
- memcpy(szFriendlyName, info->Data, (Ret-1) * sizeof(WCHAR));
- szFriendlyName[Ret-1] = 0;
- }
- }
- else if (Status == STATUS_BUFFER_OVERFLOW && !szFriendlyName)
- {
- Ret = (dwSize - info_size) / sizeof(WCHAR) + 1;
- }
- else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
- {
- Ret = -1;
- }
- else
- {
- SetLastError(RtlNtStatusToDosError(Status));
- Ret = 0;
- }
-
- NtClose(hKey);
- HeapFree(GetProcessHeap(), 0, info);
-
- return Ret;
-}
static const struct geoinfo_t geoinfodata[] = {
{ 2, {'A','G',0}, {'A','T','G',0}, 10039880,
28 }, /* Antigua and Barbuda */
@@ -3079,6 +2589,482 @@
{ 161832257, {'X','X',0}, {'X','X',0}, 10026358, 0,
LOCATION_REGION }, /* Latin America and the Caribbean */
};
+/******************************************************************************
+ * EnumLanguageGroupLocalesA (KERNEL32.@)
+ *
+ * Call a users function for every locale in a language group available on the system.
+ *
+ * PARAMS
+ * pLangGrpLcEnumProc [I] Callback function to call for each locale
+ * lgrpid [I] Language group (LGRPID_ values from "winnls.h")
+ * dwFlags [I] Reserved, set to 0
+ * lParam [I] User parameter to pass to pLangGrpLcEnumProc
+ *
+ * RETURNS
+ * Success: TRUE.
+ * Failure: FALSE. Use GetLastError() to determine the cause.
+ */
+BOOL WINAPI EnumLanguageGroupLocalesA(LANGGROUPLOCALE_ENUMPROCA pLangGrpLcEnumProc,
+ LGRPID lgrpid, DWORD dwFlags, LONG_PTR lParam)
+{
+ ENUMLANGUAGEGROUPLOCALE_CALLBACKS callbacks;
+
+ TRACE("(%p,0x%08X,0x%08X,0x%08lX)\n", pLangGrpLcEnumProc, lgrpid, dwFlags,
lParam);
+
+ callbacks.procA = pLangGrpLcEnumProc;
+ callbacks.procW = NULL;
+ callbacks.dwFlags = dwFlags;
+ callbacks.lgrpid = lgrpid;
+ callbacks.lParam = lParam;
+
+ return NLS_EnumLanguageGroupLocales( pLangGrpLcEnumProc ? &callbacks : NULL );
+}
+
+/******************************************************************************
+ * EnumLanguageGroupLocalesW (KERNEL32.@)
+ *
+ * See EnumLanguageGroupLocalesA.
+ */
+BOOL WINAPI EnumLanguageGroupLocalesW(LANGGROUPLOCALE_ENUMPROCW pLangGrpLcEnumProc,
+ LGRPID lgrpid, DWORD dwFlags, LONG_PTR lParam)
+{
+ ENUMLANGUAGEGROUPLOCALE_CALLBACKS callbacks;
+
+ TRACE("(%p,0x%08X,0x%08X,0x%08lX)\n", pLangGrpLcEnumProc, lgrpid, dwFlags,
lParam);
+
+ callbacks.procA = NULL;
+ callbacks.procW = pLangGrpLcEnumProc;
+ callbacks.dwFlags = dwFlags;
+ callbacks.lgrpid = lgrpid;
+ callbacks.lParam = lParam;
+
+ return NLS_EnumLanguageGroupLocales( pLangGrpLcEnumProc ? &callbacks : NULL );
+}
+
+/* Callback function ptrs for EnumSystemCodePagesA/W */
+typedef struct
+{
+ CODEPAGE_ENUMPROCA procA;
+ CODEPAGE_ENUMPROCW procW;
+ DWORD dwFlags;
+} ENUMSYSTEMCODEPAGES_CALLBACKS;
+
+/* Internal implementation of EnumSystemCodePagesA/W */
+static BOOL NLS_EnumSystemCodePages(ENUMSYSTEMCODEPAGES_CALLBACKS *lpProcs)
+{
+ WCHAR szNumber[5 + 1], szValue[MAX_PATH];
+ HANDLE hKey;
+ BOOL bContinue = TRUE;
+ ULONG ulIndex = 0;
+
+ if (!lpProcs)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ switch (lpProcs->dwFlags)
+ {
+ case CP_INSTALLED:
+ case CP_SUPPORTED:
+ break;
+ default:
+ SetLastError(ERROR_INVALID_FLAGS);
+ return FALSE;
+ }
+
+ hKey = NLS_RegOpenKey(0,
L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage");
+ if (!hKey)
+ {
+ WARN("NLS_RegOpenKey() failed\n");
+ return FALSE;
+ }
+
+ while (bContinue)
+ {
+ if (NLS_RegEnumValue(hKey, ulIndex, szNumber, sizeof(szNumber),
+ szValue, sizeof(szValue)))
+ {
+ if ((lpProcs->dwFlags == CP_SUPPORTED)||
+ ((lpProcs->dwFlags == CP_INSTALLED)&&(wcslen(szValue) >
2)))
+ {
+ 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
+WINAPI
+EnumSystemCodePagesW (
+ CODEPAGE_ENUMPROCW lpCodePageEnumProc,
+ DWORD dwFlags
+ )
+{
+ ENUMSYSTEMCODEPAGES_CALLBACKS procs;
+
+ TRACE("(%p,0x%08X,0x%08lX)\n", lpCodePageEnumProc, dwFlags);
+
+ procs.procA = NULL;
+ procs.procW = lpCodePageEnumProc;
+ procs.dwFlags = dwFlags;
+
+ return NLS_EnumSystemCodePages(lpCodePageEnumProc ? &procs : NULL);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+EnumSystemCodePagesA (
+ CODEPAGE_ENUMPROCA lpCodePageEnumProc,
+ DWORD dwFlags
+ )
+{
+ ENUMSYSTEMCODEPAGES_CALLBACKS procs;
+
+ TRACE("(%p,0x%08X,0x%08lX)\n", lpCodePageEnumProc, dwFlags);
+
+ procs.procA = lpCodePageEnumProc;
+ procs.procW = NULL;
+ procs.dwFlags = dwFlags;
+
+ return NLS_EnumSystemCodePages(lpCodePageEnumProc ? &procs : NULL);
+}
+
+/******************************************************************************
+ * EnumSystemGeoID (KERNEL32.@)
+ *
+ * Call a users function for every location available on the system.
+ *
+ * PARAMS
+ * geoclass [I] Type of information desired (SYSGEOTYPE enum from
"winnls.h")
+ * parent [I] GEOID for the parent
+ * enumproc [I] Callback function to call for each location
+ *
+ * RETURNS
+ * Success: TRUE.
+ * Failure: FALSE. Use GetLastError() to determine the cause.
+ */
+BOOL WINAPI EnumSystemGeoID(GEOCLASS geoclass, GEOID parent, GEO_ENUMPROC enumproc)
+{
+ INT i;
+
+ TRACE("(%d, %d, %p)\n", geoclass, parent, enumproc);
+
+ if (!enumproc) {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ if (geoclass != GEOCLASS_NATION && geoclass != GEOCLASS_REGION) {
+ SetLastError(ERROR_INVALID_FLAGS);
+ return FALSE;
+ }
+
+ for (i = 0; i < sizeof(geoinfodata)/sizeof(struct geoinfo_t); i++) {
+ const struct geoinfo_t *ptr = &geoinfodata[i];
+
+ if (geoclass == GEOCLASS_NATION && (ptr->kind == LOCATION_REGION))
+ continue;
+
+ if (geoclass == GEOCLASS_REGION && (ptr->kind == LOCATION_NATION))
+ continue;
+
+ if (parent && ptr->parent != parent)
+ continue;
+
+ if (!enumproc(ptr->id))
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
+/******************************************************************************
+ * InvalidateNLSCache (KERNEL32.@)
+ *
+ * Invalidate the cache of NLS values.
+ *
+ * PARAMS
+ * None.
+ *
+ * RETURNS
+ * Success: TRUE.
+ * Failure: FALSE.
+ */
+BOOL WINAPI InvalidateNLSCache(void)
+{
+ FIXME("() stub\n");
+ return FALSE;
+}
+
+/******************************************************************************
+ * GetUserGeoID (KERNEL32.@)
+ */
+GEOID WINAPI GetUserGeoID( GEOCLASS GeoClass )
+{
+ GEOID ret = GEOID_NOT_AVAILABLE;
+ static const WCHAR geoW[] = {'G','e','o',0};
+ static const WCHAR nationW[] =
{'N','a','t','i','o','n',0};
+ WCHAR bufferW[40], *end;
+ DWORD count;
+ HANDLE hkey, hSubkey = 0;
+ UNICODE_STRING keyW;
+ const KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION
*)bufferW;
+ RtlInitUnicodeString( &keyW, nationW );
+ count = sizeof(bufferW);
+
+ if(!(hkey = create_registry_key())) return ret;
+
+ switch( GeoClass ){
+ case GEOCLASS_NATION:
+ if ((hSubkey = NLS_RegOpenKey(hkey, geoW)))
+ {
+ if((NtQueryValueKey(hSubkey, &keyW, KeyValuePartialInformation,
+ bufferW, count, &count) == STATUS_SUCCESS )
&& info->DataLength)
+ ret = strtolW((LPCWSTR)info->Data, &end, 10);
+ }
+ break;
+ case GEOCLASS_REGION:
+ FIXME("GEOCLASS_REGION not handled yet\n");
+ break;
+ }
+
+ NtClose(hkey);
+ if (hSubkey) NtClose(hSubkey);
+ return ret;
+}
+
+/******************************************************************************
+ * SetUserGeoID (KERNEL32.@)
+ */
+BOOL WINAPI SetUserGeoID( GEOID GeoID )
+{
+ static const WCHAR geoW[] = {'G','e','o',0};
+ static const WCHAR nationW[] =
{'N','a','t','i','o','n',0};
+ static const WCHAR formatW[] = {'%','i',0};
+ UNICODE_STRING nameW,keyW;
+ WCHAR bufferW[10];
+ OBJECT_ATTRIBUTES attr;
+ HANDLE hkey;
+
+ if(!(hkey = create_registry_key())) return FALSE;
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = hkey;
+ attr.ObjectName = &nameW;
+ attr.Attributes = 0;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+ RtlInitUnicodeString( &nameW, geoW );
+ RtlInitUnicodeString( &keyW, nationW );
+
+ if (NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) !=
STATUS_SUCCESS)
+
+ {
+ NtClose(attr.RootDirectory);
+ return FALSE;
+ }
+
+ sprintfW(bufferW, formatW, GeoID);
+ NtSetValueKey(hkey, &keyW, 0, REG_SZ, bufferW, (strlenW(bufferW) + 1) *
sizeof(WCHAR));
+ NtClose(attr.RootDirectory);
+ NtClose(hkey);
+ return TRUE;
+}
+
+typedef struct
+{
+ union
+ {
+ UILANGUAGE_ENUMPROCA procA;
+ UILANGUAGE_ENUMPROCW procW;
+ } u;
+ DWORD flags;
+ LONG_PTR param;
+} ENUM_UILANG_CALLBACK;
+
+static BOOL CALLBACK enum_uilang_proc_a( HMODULE hModule, LPCSTR type,
+ LPCSTR name, WORD LangID, LONG_PTR lParam )
+{
+ ENUM_UILANG_CALLBACK *enum_uilang = (ENUM_UILANG_CALLBACK *)lParam;
+ char buf[20];
+
+ sprintf(buf, "%08x", (UINT)LangID);
+ return enum_uilang->u.procA( buf, enum_uilang->param );
+}
+
+static BOOL CALLBACK enum_uilang_proc_w( HMODULE hModule, LPCWSTR type,
+ LPCWSTR name, WORD LangID, LONG_PTR lParam )
+{
+ static const WCHAR formatW[] = {'%','0','8','x',0};
+ ENUM_UILANG_CALLBACK *enum_uilang = (ENUM_UILANG_CALLBACK *)lParam;
+ WCHAR buf[20];
+
+ sprintfW( buf, formatW, (UINT)LangID );
+ return enum_uilang->u.procW( buf, enum_uilang->param );
+}
+
+/******************************************************************************
+ * EnumUILanguagesA (KERNEL32.@)
+ */
+BOOL WINAPI EnumUILanguagesA(UILANGUAGE_ENUMPROCA pUILangEnumProc, DWORD dwFlags,
LONG_PTR lParam)
+{
+ ENUM_UILANG_CALLBACK enum_uilang;
+
+ TRACE("%p, %x, %lx\n", pUILangEnumProc, dwFlags, lParam);
+
+ if(!pUILangEnumProc) {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if(dwFlags) {
+ SetLastError(ERROR_INVALID_FLAGS);
+ return FALSE;
+ }
+
+ enum_uilang.u.procA = pUILangEnumProc;
+ enum_uilang.flags = dwFlags;
+ enum_uilang.param = lParam;
+
+ EnumResourceLanguagesA( kernel32_handle, (LPCSTR)RT_STRING,
+ (LPCSTR)LOCALE_ILANGUAGE, enum_uilang_proc_a,
+ (LONG_PTR)&enum_uilang);
+ return TRUE;
+}
+
+/******************************************************************************
+ * EnumUILanguagesW (KERNEL32.@)
+ */
+BOOL WINAPI EnumUILanguagesW(UILANGUAGE_ENUMPROCW pUILangEnumProc, DWORD dwFlags,
LONG_PTR lParam)
+{
+ ENUM_UILANG_CALLBACK enum_uilang;
+
+ TRACE("%p, %x, %lx\n", pUILangEnumProc, dwFlags, lParam);
+
+
+ if(!pUILangEnumProc) {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if(dwFlags) {
+ SetLastError(ERROR_INVALID_FLAGS);
+ return FALSE;
+ }
+
+ enum_uilang.u.procW = pUILangEnumProc;
+ enum_uilang.flags = dwFlags;
+ enum_uilang.param = lParam;
+
+ EnumResourceLanguagesW( kernel32_handle, (LPCWSTR)RT_STRING,
+ (LPCWSTR)LOCALE_ILANGUAGE, enum_uilang_proc_w,
+ (LONG_PTR)&enum_uilang);
+ return TRUE;
+}
+
+static int
+NLS_GetGeoFriendlyName(GEOID Location, LPWSTR szFriendlyName, int cchData)
+{
+ HANDLE hKey;
+ WCHAR szPath[MAX_PATH];
+ UNICODE_STRING ValueName;
+ KEY_VALUE_PARTIAL_INFORMATION *info;
+ const int info_size = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
+ DWORD dwSize;
+ NTSTATUS Status;
+ int Ret;
+
+ swprintf(szPath,
L"\\REGISTRY\\Machine\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Country
List\\%lu", Location);
+
+ hKey = NLS_RegOpenKey(0, szPath);
+ if (!hKey)
+ {
+ WARN("NLS_RegOpenKey() failed\n");
+ return 0;
+ }
+
+ dwSize = info_size + cchData * sizeof(WCHAR);
+
+ if (!(info = HeapAlloc(GetProcessHeap(), 0, dwSize)))
+ {
+ NtClose(hKey);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
+
+ RtlInitUnicodeString(&ValueName, L"Name");
+
+ Status = NtQueryValueKey(hKey, &ValueName, KeyValuePartialInformation,
+ (LPBYTE)info, dwSize, &dwSize);
+
+ if (!Status)
+ {
+ Ret = (dwSize - info_size) / sizeof(WCHAR);
+
+ if (!Ret || ((WCHAR *)info->Data)[Ret-1])
+ {
+ if (Ret < cchData || !szFriendlyName) Ret++;
+ else
+ {
+ WARN("ERROR_INSUFFICIENT_BUFFER\n");
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ Ret = 0;
+ }
+ }
+
+ if (Ret && szFriendlyName)
+ {
+ memcpy(szFriendlyName, info->Data, (Ret-1) * sizeof(WCHAR));
+ szFriendlyName[Ret-1] = 0;
+ }
+ }
+ else if (Status == STATUS_BUFFER_OVERFLOW && !szFriendlyName)
+ {
+ Ret = (dwSize - info_size) / sizeof(WCHAR) + 1;
+ }
+ else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ Ret = -1;
+ }
+ else
+ {
+ SetLastError(RtlNtStatusToDosError(Status));
+ Ret = 0;
+ }
+
+ NtClose(hKey);
+ HeapFree(GetProcessHeap(), 0, info);
+
+ return Ret;
+}
+
static const struct geoinfo_t *get_geoinfo_dataptr(GEOID geoid)
{
int min, max;