As @Uwe mentioned in his comment, you can use the EnumSystemGeoID and GetGeoInfo functions. The principle is that using the EnumSystemGeoID function EnumSystemGeoID you list the geographic location identifiers and GetGeoInfo if the requested ISO country / region code of the 2-letter ISO identifier ( GEO_ISO2 information GEO_ISO2 ) corresponds to one of your interests. If so, you can request for this identifier with the same function either a friendly name (information type GEO_FRIENDLYNAME ) or an official name (information type GEO_OFFICIALNAME ), return the result and stop the listing.
Here is an example of code that can do this (unfortunately, the enumeration function does not support the transfer of user data, so I used a global write variable to pass values):
type TEnumData = record GeoCode: string; GeoName: string; Success: Boolean; end; GEOID = type LONG; GEOTYPE = type DWORD; GEOCLASS = type DWORD; SYSGEOTYPE = ( GEO_NATION = $0001, GEO_LATITUDE = $0002, GEO_LONGITUDE = $0003, GEO_ISO2 = $0004, GEO_ISO3 = $0005, GEO_RFC1766 = $0006, GEO_LCID = $0007, GEO_FRIENDLYNAME= $0008, GEO_OFFICIALNAME= $0009, GEO_TIMEZONES = $000A, GEO_OFFICIALLANGUAGES = $000B, GEO_ISO_UN_NUMBER = $000C, GEO_PARENT = $000D ); SYSGEOCLASS = ( GEOCLASS_NATION = 16, GEOCLASS_REGION = 14, GEOCLASS_ALL = 0 ); GEO_ENUMPROC = function(GeoId: GEOID): BOOL; stdcall; function EnumSystemGeoID(GeoClass: GEOCLASS; ParentGeoId: GEOID; lpGeoEnumProc: GEO_ENUMPROC): BOOL; stdcall; external kernel32 name 'EnumSystemGeoID'; function GetGeoInfo(Location: GEOID; GeoType: GEOTYPE; lpGeoData: LPTSTR; cchData: Integer; LangId: LANGID): Integer; stdcall; external kernel32 name {$IFDEF UNICODE}'GetGeoInfoW'{$ELSE}'GetGeoInfoA'{$ENDIF}; implementation var // I have used this global variable due to a lack of user data parameter for the callback function EnumData: TEnumData; function TryGetGeoInfo(GeoId: GEOID; GeoType: GEOTYPE; out Value: string): Boolean; var Buffer: string; BufferLen: Integer; begin Result := False; BufferLen := GetGeoInfo(GeoId, GeoType, LPTSTR(Buffer), 0, 0); if BufferLen <> 0 then begin SetLength(Buffer, BufferLen); Result := GetGeoInfo(GeoId, GeoType, LPTSTR(Buffer), BufferLen, 0) <> 0; if Result then Value := Trim(Buffer); end; end; function EnumGeoInfoProc(GeoId: GEOID): BOOL; stdcall; var S: string; begin Result := TryGetGeoInfo(GeoId, GEOTYPE(GEO_ISO2), S); if Result and (S = EnumData.GeoCode) then begin // stop the enumeration since we've found the country by its ISO code Result := False; // return the success flag and try to return the friendly name of the country to the // EnumData.GeoName record field; you can optionally query the GEO_OFFICIALNAME EnumData.Success := TryGetGeoInfo(GeoId, GEOTYPE(GEO_FRIENDLYNAME), EnumData.GeoName); end; end; function TryGetCountryNameByISO2(const Code: string; out Name: string): Boolean; begin // here is the brainless part using global record variable (because the function used // here with its callback does not support passing user data); no, you cannot tune it // up by making the callback function nested EnumData.GeoCode := Code; EnumData.Success := False; if not EnumSystemGeoID(GEOCLASS(GEOCLASS_NATION), 0, EnumGeoInfoProc) then RaiseLastOSError; Result := EnumData.Success; if Result then Name := EnumData.GeoName; end;
And possible use:
var S: string; begin if TryGetCountryNameByISO2('DE', S) then ShowMessage(S); end;