title: Inno Setup Unicode version and string parameter in Delphi DLL
body: <p>I wrote a DLL in Delphi 10.1 that uses Devart IBDac components to allow backup and restore of a Firebird DB within the installation (upgrade of an application from Firebird 1.5 to 3). With Ansi Inno Setup 5.5.9 everything worked fine. As I wanted to avoid <code>AnsiString</code> and <code>PAnsiChar</code> as parameters (for more convenient use from Delphi) I installed Inno Setup Unicode version 5.5.9(u) and changed the parameters from <code>AnsiString</code>/<code>PAnsiChar</code> to <code>String</code> in the DLL and also in the Inno Setup Script. I also tried <code>WideString</code> in the Inno Setup script but this didn't work at all. <code>PChar</code> is not recognized by Inno Setup.</p>
  
  <p>The strange thing is that the script partly works, the parameters are correctly transferred to the DLL but I experience GPFs in situations that have nothing to do with the parameters:</p>
  
  <ul>
  <li>Using trim on a string within the DLL (no parameter!) creates a GPF.</li>
  <li>Creating a DBConnection-Object creates a GPF too.</li>
  </ul>
  
  <p>I think the parameter-types are root of this evil. That is the only thing I changed in DLL and script. The versions with <code>AnsiString</code> still work well.</p>
  
  <p>Thanks for sharing any ideas about, what I am doing wrong here.</p>
  
  <p>Update: Example Code as requested:</p>
  
  <p>Delphi procedure that runs a script from a resource, fails in the very first statement. With <code>MessageBox</code> in the first line I verified that all parameters arrive correctly. </p>
  
  <pre><code>procedure runScript(aServer, aDatabase, aUser, aPW, aPort, DLL, script: String); stdcall;
  var
    ResStream: TResourceStream;
    DB: TIBCConnection;
    SC: TIBCScript;
    { Muss Ansistring sein wegen Resourcestream }
    s: ansistring;
  begin
    try
      DB := TIBCConnection.create(nil);
      SC := TIBCScript.create(nil);
      SC.Connection := DB;
      try
        DB.clientlibrary := DLL;
        DB.Database := aDatabase;
        DB.Server := aServer;
        DB.Username := aUser;
        DB.Password := aPW;
        DB.Port := aPort;
        DB.connected := true;
        ResStream := TResourceStream.create(hInstance, script, RT_RCDATA);
        setlength(s, ResStream.size);
        ResStream.ReadBuffer(s[1], ResStream.size);
        SC.SQL.Text := String(s);
        SC.Execute;
        DB.close;
      finally
        SC.free;
        DB.free;
      end;
    except
      on e: Exception do
      begin
        MessageBox(0, PChar(e.message), PChar('Setup - Fehler in "' + script + '"'), mb_ok);
        raise;
      end;
    end;
  end;
  </code></pre>
  
  <p>Definition of the procedure in Inno Setup (Unicode). Other required DLLs are declared in the first function definition so they are all present. It works with <code>AnsiString</code>/<code>PAnsiChar</code>!</p>
  
  <pre><code>procedure runScript(aServer, aDatabase, aUser, aPW, aPort, DLL, script: String); 
      external 'runScript@files:itcsetupfb.dll stdcall setuponly';
  </code></pre>
  
  <p>This restore function works but only if I do not use TRIM() within the function:</p>
  
  <pre><code>procedure restoreDB(destServer, destDatabase, destSysdbaPW, aBackupfile, aPort, DLL: String; PBRange: integer;
    PbHandle, LblHandle, WizHandle: THandle); stdcall;
  var
    IBCRestoreService1: TIBCRestoreService;
    cnt: integer;
    s: String;
    Msg: TMsg;
  begin
    IBCRestoreService1 := TIBCRestoreService.create(nil);
    SendMessage(PbHandle, PBM_SETRANGE, 0, PBRange shl 16);
    cnt := 0;
    try
      try
        with IBCRestoreService1 do
        begin
          clientlibrary := DLL;
          Database.Text := destDatabase;
          Server := destServer;
          Username := 'sysdba';
          Password := destSysdbaPW;
          Port := aPort;
          Options := [roFixFssMetadata, roNoValidityCheck, roFixFssData, roOneRelationAtATime, roDeactivateIndexes];
          FixFssCharset := 'ISO8859_1';
          BackupFile.Text := aBackupfile;
          PageSize := 16384;
          verbose := true;
          Attach;
          try
            ServiceStart;
            while IsServiceRunning do
            begin
              inc(cnt);
              if cnt &gt; PBRange then
                cnt := 0;
              s := GetNextLine + ' ';
              { this was formerly s:=trim(strinGreplace(s,'gbak:','', }
              { [rfReplaceall,rfIgnoreCase])). I Identified the trim to be the  }
              { cause of the GPF. Very strange. }
              delete(s, 1, 5);
              while (length(s) &gt; 0) and (s[1] = #32) do
                delete(s, 1, 1);
              { if we have no message file (local fb15) }
              if pos('format message', s) &gt; 0 then
                s := 'Arbeite ...';
              SendMessage(LblHandle, $0C, 0, longint(s));
              SendMessage(PbHandle, PBM_SETPOS, cnt, 0);
              while PeekMessage(Msg, WizHandle, 0, 0, PM_REMOVE) do
              begin
                TranslateMessage(Msg);
                DispatchMessage(Msg);
              end;
              UpdateWindow(PbHandle);
            end;
          finally
            detach;
          end;
        end;
      finally
        IBCRestoreService1.free;
      end;
    except
      on e: Exception do
      begin
        MessageBox(0,
          PChar('Die Wiederherstellung der EMILpro Datenbank ist leider fehlgeschlagen. Folgender Fehler trat auf: ' +
          #13#10#10 + e.message), 'Setup - Fehler bei Wiederherstellung', mb_ok);
        raise;
      end;
    end;
  end;
  </code></pre>
  
  <p>This function is declared in Inno Setup like this:</p>
  
  <pre><code>procedure restoreDB(destServer, destDatabase, destSysdbaPW, aBackupfile, aPort, DLL: String; 
           PBRange: integer; PbHandle,LblHandle,WizHandle: THandle); 
           external 'restoreDB@files:itcsetupfb.dll,fbclient.dll,gds32.dll,icudt52.dll,icudt52l.dat,icuin52.dll,icuuc52.dll,fbintl.dll,firebird.conf,firebird.msg,ib_util.dll,engine12.dll,msvcp100.dll,msvcr100.dll,fbintl.conf stdcall setuponly';
  </code></pre>