diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c index 4d4b99660ae..5b196be2d56 100644 --- a/dlls/kernel32/locale.c +++ b/dlls/kernel32/locale.c @@ -2908,6 +2908,34 @@ BOOL WINAPI SetUserGeoID(GEOID geoid) /****************************************************************************** * GetGeoInfoW (KERNEL32.@) + * + * Retrieves information about a geographic location by its GeoID. + * + * PARAMS + * geoid [I] The GeoID of the location of interest. + * geotype [I] The type of information to be retrieved (SYSGEOTYPE enum from "winnls.h"). + * data [O] The output buffer to store the information. + * data_len [I] The length of the buffer, measured in WCHARs and including the null terminator. + * lang [I] Language identifier. Must be 0 unless geotype is GEO_RFC1766 or GEO_LCID. + * + * RETURNS + * Success: The number of WCHARs (including null) written to the buffer -or- + * if no buffer was provided, the minimum length required to hold the full data. + * Failure: Zero. Call GetLastError() to determine the cause. + * + * NOTES + * On failure, GetLastError() will return one of the following values: + * - ERROR_INVALID_PARAMETER: the GeoID provided was invalid. + * - ERROR_INVALID_FLAGS: the specified geotype was invalid. + * - ERROR_INSUFFICIENT_BUFFER: the provided buffer was too small to hold the full data. + * - ERROR_CALL_NOT_IMPLEMENTED: (Wine implementation) we don't handle that geotype yet. + * + * The list of available GeoIDs can be retrieved with EnumSystemGeoID(), + * or call GetUserGeoID() to retrieve the user's current location. + * + * TODO + * Currently, we only handle the following geotypes: GEO_ID, GEO_ISO2, GEO_ISO3, + * GEO_ISO_UN_NUMBER, GEO_PARENT and GEO_NATION. */ INT WINAPI GetGeoInfoW(GEOID geoid, GEOTYPE geotype, LPWSTR data, int data_len, LANGID lang) { @@ -2926,6 +2954,9 @@ INT WINAPI GetGeoInfoW(GEOID geoid, GEOTYPE geotype, LPWSTR data, int data_len, switch (geotype) { case GEO_NATION: + if (ptr->kind != LOCATION_NATION) return 0; + /* fall through */ + case GEO_ID: sprintfW(buffW, fmtW, ptr->id); break; case GEO_ISO_UN_NUMBER: diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index ee38dc36acd..de1d4fca223 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -4984,11 +4984,43 @@ static void test_GetGeoInfo(void) ok(!strcmp(buffA, "RU"), "got %s\n", buffA); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d\n", GetLastError()); - /* GEO_NATION returns GEOID in a string form */ + /* GEO_NATION returns GEOID in a string form, but only for GEOCLASS_NATION-type IDs */ + ret = pGetGeoInfoA(203, GEO_NATION, buffA, 20, 0); /* GEOCLASS_NATION */ + ok(ret == 4, "GEO_NATION of nation: expected 4, got %d\n", ret); + ok(!strcmp(buffA, "203"), "GEO_NATION of nation: expected 203, got %s\n", buffA); + buffA[0] = 0; - ret = pGetGeoInfoA(203, GEO_NATION, buffA, 20, 0); - ok(ret == 4, "got %d\n", ret); - ok(!strcmp(buffA, "203"), "got %s\n", buffA); + ret = pGetGeoInfoA(39070, GEO_NATION, buffA, 20, 0); /* GEOCLASS_REGION */ + ok(ret == 0, "GEO_NATION of region: expected 0, got %d\n", ret); + ok(*buffA == 0, "GEO_NATION of region: expected empty string, got %s\n", buffA); + + buffA[0] = 0; + ret = pGetGeoInfoA(333, GEO_NATION, buffA, 20, 0); /* LOCATION_BOTH internal Wine type */ + ok(ret == 0 || + broken(ret == 4) /* Win7 and older */, + "GEO_NATION of LOCATION_BOTH: expected 0, got %d\n", ret); + ok(*buffA == 0 || + broken(!strcmp(buffA, "333")) /* Win7 and older */, + "GEO_NATION of LOCATION_BOTH: expected empty string, got %s\n", buffA); + + /* GEO_ID is like GEO_NATION but works for any ID */ + buffA[0] = 0; + ret = pGetGeoInfoA(203, GEO_ID, buffA, 20, 0); /* GEOCLASS_NATION */ + if (ret == 0) + win_skip("GEO_ID not supported.\n"); + else + { + ok(ret == 4, "GEO_ID: expected 4, got %d\n", ret); + ok(!strcmp(buffA, "203"), "GEO_ID: expected 203, got %s\n", buffA); + + ret = pGetGeoInfoA(47610, GEO_ID, buffA, 20, 0); /* GEOCLASS_REGION */ + ok(ret == 6, "got %d\n", ret); + ok(!strcmp(buffA, "47610"), "got %s\n", buffA); + + ret = pGetGeoInfoA(333, GEO_ID, buffA, 20, 0); /* LOCATION_BOTH internal Wine type */ + ok(ret == 4, "got %d\n", ret); + ok(!strcmp(buffA, "333"), "got %s\n", buffA); + } /* GEO_PARENT */ buffA[0] = 0;