3

I need Inno Setup to load a wide string from a function in a custom DLL. I have no problem loading Ansi strings – this, for example, works fine:

int __stdcall GetStringA(char *lpText)
{
    StringCchCopyA(lpText, 30, "New Ansi value");
    return strlen(lpText);
}

Pascal Script

function GetStringA(lpText: AnsiString): Integer;
  external 'GetStringA@files:MyDll.dll';

function LoadStringA(): AnsiString;
var
  Str: AnsiString;
  Length: Integer;
begin
  Str := 'Initial Ansi value';
  SetLength(Str, 30);
  Length := GetStringA(Str);
  SetLength(Str, Length);
  Result := Str; // Str == 'New Ansi value'
end;

Doing the same thing with wide strings fails, however:

int __stdcall GetStringW(wchar_t *lpText)
{
    StringCchCopyW(lpText, 30, L"New Wide value");
    return wcslen(lpText);
}

Pascal Script

function GetStringW(lpText: WideString): Integer;
  external 'GetStringW@files:MyDll.dll';

function LoadStringW(): WideString;
var
  Str: WideString;
  Length: Integer;
begin
  Str := 'Initial Wide value';
  SetLength(Str, 30);
  Length := GetStringW(Str); // ** DOES NOT ALTER 'Str' **
  SetLength(Str, Length);
  Result := Str; // Str == 'Initial Wide v' (old string, new length)
end;

Sending a WideString to the DLL works fine. Changing the buffer contents in the DLL also works fine…but somehow that does not percolate back to my Pascal Script variable.

I suspect that some sort of marshaling goes on under the hood, so that the DLL actually manipulates a copy of my variable. Any insights or workarounds appreciated!

I'm using Inno Setup 6.2.0.

Petter Hesselberg
  • 5,062
  • 2
  • 24
  • 42

1 Answers1

3

I made it work by replacing WideString with String:

function GetStringW(lpText: String): Integer;
  external 'GetStringW@files:MyDll.dll';

function LoadStringW(): WideString;
var
  Str: String;
  Length: Integer;
begin
  Str := 'Initial Wide value';
  SetLength(Str, 30);
  Length := GetStringW(Str); // ** ALTERS 'Str' **
  SetLength(Str, Length);
  Result := Str; // Str == 'New Wide value'
end;

I'd have thought WideString and String were equivalent, but apparently not quite. It is necessary to change both the function prototype and the Str declaration. It is not necessary to change the LoadStringW return type, though you may – and the returned value can in either case be assigned to a variable of type WideString or String without problem.

So: Problem solved. I'm still curious about the underlying behavior, though.

Petter Hesselberg
  • 5,062
  • 2
  • 24
  • 42