New Platform types for Windows

FreePascal 2.4.0+ supports a UnicodeString type that is similar to the UnicodeString type in Delphi 2009+. However, unlike Delphi, FreePascal does not map its String type to UnicodeString by default. You have to use the {$MODE DelphiUnicode} or {$MODESWITCH UnicodeStrings} directive to enable that mapping.

Indy assumed that String/(P)Char maps to UnicodeString/(P)WideChar when UNICODE is defined, and to AnsiString/(P)AnsiChar otherwise. This is true in Delphi, but not in FreePascal. This mismatch presented a problem for Indy on Windows platforms. When UNICODE is defined, Win32 API functions expect Unicode data, but Indy was using Ansi data instead in some places. Either the compiler would fail in places, or APIs would fail at runtime due to bad input.

To address this, three new types have been added to the IdGlobal unit for Windows platforms:
TIdPlatformString, TIdPlatformChar, and PIdPlatformChar

These types map to appropriate Ansi/Unicode types based on whether UNICODE is defined or not. Indy has been updated to use these new types internally when making Win32 API function calls.

Indy already had a UNICODE_BUT_STRING_IS_ANSI define for detecting when UNICODE is defined and String/(P)Char maps to AnsiString/(P)AnsiChar, so it could do appropriate type-casts where needed. But Indy did not have a corresponding define for detecting when UNICODE is not defined and String/(P)Char maps to UnicodeString/(P)WideChar. Rather than adding a new ANSI_BUT_STRING_IS_UNICODE define, the existing UNICODE_BUT_STRING_IS_ANSI define has been replaced with a new STRING_UNICODE_MISMATCH define that covers both scenarios.

For example:

Before:

procedure DebugOutput(const AText: string);
{$IFDEF WINDOWS}
  {$IFDEF UNICODE_BUT_STRING_IS_ANSI}
var
  LTemp: WideString;
  ...
{$ENDIF}
begin
  ...
  {$IFDEF WINDOWS}
    {$IFDEF UNICODE_BUT_STRING_IS_ANSI}
  LTemp := WideString(AText); 
  OutputDebugString(PWideChar(LTemp));
    {$ELSE}
  OutputDebugString(PChar(AText));
    {$ENDIF}
  {$ENDIF}
  ...
end;

After:

procedure DebugOutput(const AText: string);
{$IFDEF WINDOWS}
  {$IFDEF STRING_UNICODE_MISMATCH}
var
  LTemp: TIdPlatformString;
  ...
{$ENDIF}
begin
  ...
  {$IFDEF WINDOWS}
    {$IFDEF STRING_UNICODE_MISMATCH}
  LTemp := TIdPlatformString(AText); 
  OutputDebugString(PIdPlatformChar(LTemp));
    {$ELSE}
  OutputDebugString(PChar(AText));
    {$ENDIF}
  {$ENDIF}
  ...
end;

The IdWship6 unit in particular was badly affected by this String/UNICODE mismatch for its getaddrinfo() and getnameinfo() support code. Windows CE has Ansi versions of getaddrinfo() and getnameinfo(), but does not have Unicode versions. Indy needed to know when (and how) to convert strings correctly when calling these Ansi functions on Windows CE. But also, on older Windows platforms where getaddrinfo() and getnameinfo() are not available at all, IdWShip6 simulates the functions for IPv4, so proper string conversions were important for that code as well.