kernel32: Properly implement EnumSystemGeoID().

This commit is contained in:
Nikolay Sivov 2014-07-15 06:41:02 +04:00 committed by Alexandre Julliard
parent 17777c8497
commit ed9e030456
2 changed files with 109 additions and 94 deletions

View File

@ -3367,29 +3367,6 @@ static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
return hkey;
}
static BOOL NLS_RegEnumSubKey(HANDLE hKey, UINT ulIndex, LPWSTR szKeyName,
ULONG keyNameSize)
{
BYTE buffer[80];
KEY_BASIC_INFORMATION *info = (KEY_BASIC_INFORMATION *)buffer;
DWORD dwLen;
if (NtEnumerateKey( hKey, ulIndex, KeyBasicInformation, buffer,
sizeof(buffer), &dwLen) != STATUS_SUCCESS ||
info->NameLength > keyNameSize)
{
return FALSE;
}
TRACE("info->Name %s info->NameLength %d\n", debugstr_w(info->Name), info->NameLength);
memcpy( szKeyName, info->Name, info->NameLength);
szKeyName[info->NameLength / sizeof(WCHAR)] = '\0';
TRACE("returning %s\n", debugstr_w(szKeyName));
return TRUE;
}
static BOOL NLS_RegEnumValue(HANDLE hKey, UINT ulIndex,
LPWSTR szValueName, ULONG valueNameSize,
LPWSTR szValueData, ULONG valueDataSize)
@ -3835,70 +3812,6 @@ BOOL WINAPI EnumLanguageGroupLocalesW(LANGGROUPLOCALE_ENUMPROCW pLangGrpLcEnumPr
return NLS_EnumLanguageGroupLocales( pLangGrpLcEnumProc ? &callbacks : 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.@)
*
@ -4081,15 +3994,22 @@ BOOL WINAPI EnumUILanguagesW(UILANGUAGE_ENUMPROCW pUILangEnumProc, DWORD dwFlags
return TRUE;
}
enum locationkind {
LOCATION_NATION = 0,
LOCATION_REGION,
LOCATION_BOTH
};
struct geoinfo_t {
GEOID id;
WCHAR iso2W[3];
WCHAR iso3W[4];
GEOID parent;
INT uncode;
enum locationkind kind;
};
static const struct geoinfo_t nations_geoinfodata[] = {
static const struct geoinfo_t geoinfodata[] = {
{ 2, {'A','G',0}, {'A','T','G',0}, 10039880, 28 }, /* Antigua and Barbuda */
{ 3, {'A','F',0}, {'A','F','G',0}, 47614, 4 }, /* Afghanistan */
{ 4, {'D','Z',0}, {'D','Z','A',0}, 42487, 12 }, /* Algeria */
@ -4311,7 +4231,7 @@ static const struct geoinfo_t nations_geoinfodata[] = {
{ 305, {'X','X',0}, {'X','X',0}, 161832256 }, /* Baker Island */
{ 306, {'B','V',0}, {'B','V','T',0}, 39070, 74 }, /* Bouvet Island */
{ 307, {'K','Y',0}, {'C','Y','M',0}, 10039880, 136 }, /* Cayman Islands */
{ 308, {'X','X',0}, {'X','X',0}, 10210824 }, /* Channel Islands */
{ 308, {'X','X',0}, {'X','X',0}, 10210824, 0, LOCATION_BOTH }, /* Channel Islands */
{ 309, {'C','X',0}, {'C','X','R',0}, 12, 162 }, /* Christmas Island */
{ 310, {'X','X',0}, {'X','X',0}, 27114 }, /* Clipperton Island */
{ 311, {'C','C',0}, {'C','C','K',0}, 10210825, 166 }, /* Cocos (Keeling) Islands */
@ -4334,7 +4254,7 @@ static const struct geoinfo_t nations_geoinfodata[] = {
{ 330, {'M','Q',0}, {'M','T','Q',0}, 10039880, 474 }, /* Martinique */
{ 331, {'Y','T',0}, {'M','Y','T',0}, 47603, 175 }, /* Mayotte */
{ 332, {'M','S',0}, {'M','S','R',0}, 10039880, 500 }, /* Montserrat */
{ 333, {'A','N',0}, {'A','N','T',0}, 10039880, 530 }, /* Netherlands Antilles (Former) */
{ 333, {'A','N',0}, {'A','N','T',0}, 10039880, 530, LOCATION_BOTH }, /* Netherlands Antilles (Former) */
{ 334, {'N','C',0}, {'N','C','L',0}, 20900, 540 }, /* New Caledonia */
{ 335, {'N','U',0}, {'N','I','U',0}, 26286, 570 }, /* Niue */
{ 336, {'N','F',0}, {'N','F','K',0}, 10210825, 574 }, /* Norfolk Island */
@ -4351,15 +4271,44 @@ static const struct geoinfo_t nations_geoinfodata[] = {
{ 349, {'T','C',0}, {'T','C','A',0}, 10039880, 796 }, /* Turks and Caicos Islands */
{ 351, {'V','G',0}, {'V','G','B',0}, 10039880, 92 }, /* Virgin Islands, British */
{ 352, {'W','F',0}, {'W','L','F',0}, 26286, 876 }, /* Wallis and Futuna */
{ 742, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Africa */
{ 2129, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Asia */
{ 10541, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Europe */
{ 15126, {'I','M',0}, {'I','M','N',0}, 10039882, 833 }, /* Man, Isle of */
{ 19618, {'M','K',0}, {'M','K','D',0}, 47610, 807 }, /* Macedonia, Former Yugoslav Republic of */
{ 20900, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Melanesia */
{ 21206, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Micronesia */
{ 21242, {'X','X',0}, {'X','X',0}, 161832256 }, /* Midway Islands */
{ 23581, {'X','X',0}, {'X','X',0}, 10026358, 0, LOCATION_REGION }, /* Northern America */
{ 26286, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Polynesia */
{ 27082, {'X','X',0}, {'X','X',0}, 161832257, 0, LOCATION_REGION }, /* Central America */
{ 27114, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Oceania */
{ 30967, {'S','X',0}, {'S','X','M',0}, 10039880, 534 }, /* Sint Maarten (Dutch part) */
{ 31396, {'X','X',0}, {'X','X',0}, 161832257, 0, LOCATION_REGION }, /* South America */
{ 31706, {'M','F',0}, {'M','A','F',0}, 10039880, 663 }, /* Saint Martin (French part) */
{ 39070, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* World */
{ 42483, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Western Africa */
{ 42484, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Middle Africa */
{ 42487, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Northern Africa */
{ 47590, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Central Asia */
{ 47599, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* South-Eastern Asia */
{ 47600, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Eastern Asia */
{ 47603, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Eastern Africa */
{ 47609, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Eastern Europe */
{ 47610, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Southern Europe */
{ 47611, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Middle East */
{ 47614, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Southern Asia */
{ 7299303, {'T','L',0}, {'T','L','S',0}, 47599, 626 }, /* Democratic Republic of Timor-Leste */
{ 10026358, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Americas */
{ 10028789, {'A','X',0}, {'A','L','A',0}, 10039882, 248 }, /* Åland Islands */
{ 10039880, {'X','X',0}, {'X','X',0}, 161832257, 0, LOCATION_REGION }, /* Caribbean */
{ 10039882, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Northern Europe */
{ 10039883, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Southern Africa */
{ 10210824, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Western Europe */
{ 10210825, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Australia and New Zealand */
{ 161832015, {'B','L',0}, {'B','L','M',0}, 10039880, 652 }, /* Saint Barthélemy */
{ 161832256, {'U','M',0}, {'U','M','I',0}, 27114, 581 }, /* U.S. Minor Outlying Islands */
{ 161832257, {'X','X',0}, {'X','X',0}, 10026358, 0, LOCATION_REGION }, /* Latin America and the Caribbean */
};
static const struct geoinfo_t *get_geoinfo_dataptr(GEOID geoid)
@ -4367,13 +4316,13 @@ static const struct geoinfo_t *get_geoinfo_dataptr(GEOID geoid)
int min, max;
min = 0;
max = sizeof(nations_geoinfodata)/sizeof(struct geoinfo_t)-1;
max = sizeof(geoinfodata)/sizeof(struct geoinfo_t)-1;
while (min <= max) {
const struct geoinfo_t *ptr;
int n = (min+max)/2;
ptr = &nations_geoinfodata[n];
ptr = &geoinfodata[n];
if (geoid == ptr->id)
/* we don't need empty entry */
return *ptr->iso2W ? ptr : NULL;
@ -4487,6 +4436,55 @@ INT WINAPI GetGeoInfoA(GEOID geoid, GEOTYPE geotype, LPSTR data, int data_len, L
return data_len < len ? 0 : len;
}
/******************************************************************************
* 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;
}
INT WINAPI GetUserDefaultLocaleName(LPWSTR localename, int buffersize)
{
LCID userlcid;

View File

@ -3930,11 +3930,10 @@ static int geoidenum_count;
static BOOL CALLBACK test_geoid_enumproc(GEOID geoid)
{
INT ret = pGetGeoInfoA(geoid, GEO_ISO2, NULL, 0, 0);
todo_wine {
ok(ret == 3, "got %d for %d\n", ret, geoid);
/* valid geoid starts at 2 */
ok(geoid >= 2, "got geoid %d\n", geoid);
}
return geoidenum_count++ < 5;
}
@ -3959,9 +3958,27 @@ static void test_EnumSystemGeoID(void)
ok(!ret, "got %d\n", ret);
ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %d\n", GetLastError());
SetLastError(0xdeadbeef);
ret = pEnumSystemGeoID(GEOCLASS_NATION+1, 0, test_geoid_enumproc);
ok(!ret, "got %d\n", ret);
ok(GetLastError() == ERROR_INVALID_FLAGS, "got %d\n", GetLastError());
SetLastError(0xdeadbeef);
ret = pEnumSystemGeoID(GEOCLASS_NATION+1, 0, NULL);
ok(!ret, "got %d\n", ret);
ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %d\n", GetLastError());
ret = pEnumSystemGeoID(GEOCLASS_NATION, 0, test_geoid_enumproc);
ok(ret, "got %d\n", ret);
/* only first level is enumerated, not the whole hierarchy */
geoidenum_count = 0;
ret = pEnumSystemGeoID(GEOCLASS_NATION, 39070, test_geoid_enumproc2);
if (ret == 0)
win_skip("Parent GEOID is not supported in EnumSystemGeoID.\n");
else
ok(ret && geoidenum_count > 0, "got %d, count %d\n", ret, geoidenum_count);
geoidenum_count = 0;
ret = pEnumSystemGeoID(GEOCLASS_REGION, 39070, test_geoid_enumproc2);
if (ret == 0)