Recent

Author Topic: How to make a Lazarus built dll portable  (Read 3390 times)

nygyurka

  • Newbie
  • Posts: 6
How to make a Lazarus built dll portable
« on: January 07, 2022, 05:05:14 pm »
I have made a dll that interfaces with an application (for which i don't have source access). It works perfectly on my computer but fails to work when used on other machines. The other machines processor manufacturer and Operating system matches mine. I think it's important to note that when observed with Api Monitor i can see that the host program correctly calls the exported functions from the dll but the dll gives incorrect return values. The problem also persists if i install FreePascal, Lazarus and internettools on the other machine. I even tried building the dll on the other machine with the same results. I would be happy to receive some kind of advice on how to proceed. Thank you! :)

The code is:
Code: Pascal  [Select][+][-]
  1. library PascalLookup;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. {$R *.res}
  6.  
  7. uses
  8.   Classes,
  9.   fileutil,
  10.   Windows,
  11.   sysutils,
  12.   xquery, PUCU, internetaccess, w32internetaccess;
  13.  
  14.  
  15. //Ez keresi meg az Application Data mappát
  16. function GetAppdataFolder: string;
  17. begin
  18.      Result := GetEnvironmentVariable('APPDATA');
  19. end;
  20. //Ennek nincs szerepe a jelenlegi Implementációban
  21. function Initialize(): Longint; cdecl;
  22. begin
  23.      Initialize := 0;
  24. end;
  25. //Ennek nincs szerepe a jelenlegi Implementációban
  26. function DeInitialize(): Longint; cdecl;
  27. begin
  28.      DeInitialize := 0;
  29. end;
  30.  //Ennek nincs szerepe a jelenlegi JAWS Implementációban
  31. function GetInterfaceSchema(var dwSchema: LongWord): Longint; cdecl;
  32. begin
  33.      dwSchema := 12;
  34.      GetInterfaceSchema := 12;
  35. end;
  36.  
  37. var
  38.   namelist, filename, rulefolder: WideString;
  39.   filestring: string;
  40.   firstloop: Boolean;
  41.   filenamelist: TStringList;
  42.   rulefile: TextFile;
  43.   namepos, i: Integer;
  44. //Ez írja ki a modulok nevét
  45. function GetFriendlyName(lpszOut: LPWSTR; var dwSize: LongWord): LongWord; cdecl;
  46. begin
  47.      rulefolder := 'C:\Freedom Scientific\JAWS\2022\Settings\hun\RuleSets\'; //GetAppdataFolder()+'\Freedom Scientific\JAWS\2022\Settings\hun\RuleSets\';
  48.      filenamelist := TStringList.Create();
  49.      FindAllFiles(filenamelist, rulefolder, '*.rul', true);
  50.  
  51.      firstloop := true;
  52.      i:=0;
  53.      while i < filenamelist.Count do
  54.      begin
  55.  
  56.        filename := filenamelist[i];
  57.        if(firstloop = false) then
  58.           namelist := namelist+'|'
  59.        else
  60.           firstloop := false;
  61.        namelist := namelist+copy(filename, Length(rulefolder)+1, Length(filename)-Length(rulefolder)-4);
  62.        //Delete(namelist,Length(namelist)-2,3); //to remove the extension from the name
  63.        namelist := namelist+':';
  64.  
  65.        filestring:= ReadFileToString(filename); //I SHOULD PROBABLY GO BACK TO USING READLN
  66.  
  67.        //readln(rulefile, ruleline); //USE POS LIKE THIS: s:='note-book';
  68.                                      //x:=pos('book',s); {x will be 6}
  69.        namepos :=pos('FriendlyName=',filestring);
  70.        if namepos<>0 then //the line exists
  71.        begin
  72.             filestring:=copy(filestring,namepos+13,Length(filestring)-namepos-13); //get everything from the start of the Friendlyname value
  73.             SetCodePage(RawByteString(filestring), 1252, false);//So utf8 characters work
  74.             namelist := namelist + copy(filestring,1,pos(sLineBreak, filestring)-1); //add everything from the value to the next linebreak
  75.  
  76.        end;
  77.        i:= i+1;
  78.      end;
  79.  
  80.  
  81.  
  82.      filenamelist.Free();
  83.      namelist := 'hello:Hello|plswork:illwork|thxdud:noprob|thisistheplace:a'+filenamelist[1];
  84.      if dwSize >Length(namelist) then
  85.         strCopy(lpszOut,PWideChar(namelist))
  86.      else
  87.          begin
  88.               dwSize := Length(namelist)+1;
  89.               result := $802A0001
  90.          end;
  91.      result := 0;
  92. end;
  93.  
  94. var description, descfilestring: string;
  95.   plsmukodj: PWideChar;
  96.   descpos: Integer;
  97.   //Ez írja ki a modul leírását
  98. function Describe(const lpszRuleSet: LPCWSTR; lpszOut: LPWSTR; var dwSize: DWord): LongWord; cdecl;
  99. begin
  100.      rulefolder := GetAppdataFolder()+'\Freedom Scientific\JAWS\2022\Settings\hun\RuleSets\';
  101.      descfilestring:= ReadFileToString(rulefolder+lpszRuleSet+'.rul'); //I SHOULD PROBABLY GO BACK TO USING READLN
  102.  
  103.      //USE POS LIKE THIS: s:='note-book';
  104.       //x:=pos('book',s); {x will be 6}
  105.      descpos :=pos('Description=',descfilestring);
  106.      if descpos<>0 then //the line exists
  107.      begin
  108.           descfilestring:=copy(descfilestring,descpos+12,Length(descfilestring)-descpos-12); //get everything from the start of the Description value
  109.           SetCodePage(RawByteString(descfilestring), 65001, false);//So utf8 characters work
  110.           description := copy(descfilestring,1,pos(sLineBreak, descfilestring)-1); //add everything from the value to the next linebreak
  111.      end;
  112.  
  113.      SetCodePage(RawByteString(description), 1252, false);
  114.      if dwSize >Length(description) then
  115.         begin
  116.              strCopy(lpszOut,PWideChar(WideString(description)));
  117.              result := 0
  118.         end
  119.      else
  120.          begin
  121.               dwSize := Length(description)+1;
  122.               result := $802A0001
  123.          end;
  124. end;
  125.  
  126. var
  127.   queryresult, querysource, fsi, infoalap: string;
  128.   engine: TXQueryEngine;
  129.  
  130.   //Ez fut le amikor ténylegesen be kell töltenie a szöveget a modulnak
  131. function Invoke(const lpszRuleSet: LPCWSTR; const lpszIn: LPCWSTR; const lpszContext: LPCWSTR; dwOffset: LongWord; lcidAppLocale: LongWord; lpszOut: LPWSTR; var dwSize: LongWord; lpExtra: Pointer): LongWord; cdecl;
  132. begin
  133.      defaultInternetAccessClass := TW32InternetAccess;
  134.  
  135.      querysource := ReadFileToString(GetAppdataFolder()+'\Freedom Scientific\JAWS\2022\Settings\hun\RuleSets\'+lpszRuleSet+'.qry');
  136.      SetCodePage(RawByteString(querysource), 1252, false);
  137.      fsi := ReadFileToString('c:\Program Files\Freedom Scientific\JAWS\2022\LookupModules\ResearchItLibrary.jri');
  138.      SetCodePage(RawByteString(fsi), 1252, false);
  139.      infoalap := ReadFileToString('c:\Program Files\Freedom Scientific\JAWS\2022\LookupModules\InfoalapResearchIt.jri');
  140.      SetCodePage(RawByteString(fsi), 1252, false);
  141.  
  142.      engine := defaultQueryEngine();
  143.      //engine.StaticContext.baseURI := 'c:\"Program Files"\"Freedom Scientific"\JAWS\2022\LookupModules\';
  144.      engine.registerModule(engine.parseQuery(fsi)); //Regisztráljuk a modulokat
  145.      engine.registerModule(engine.parseQuery(infoalap));
  146.      engine.VariableChangelog.add('inputvar',lpszIn);//A keresési szót is regisztráljuk    inputvar néven
  147.      queryresult := engine.evaluateXQuery(WideString(querysource)).toXQuery(); //https://www.benibela.de/documentation/internettools/xquery.html#defaultQueryEngine
  148.      SetCodePage(RawByteString(queryresult), 65001, false);
  149.  
  150.      if dwSize >Length(queryresult)+1 then
  151.         begin
  152.              strCopy(lpszOut,PWideChar(WideString(queryresult)));
  153.              result := 0
  154.         end
  155.      else
  156.          begin
  157.               dwSize := Length(queryresult)+2;
  158.               result := $802A0001
  159.          end;
  160. end;
  161.  
  162. exports
  163.   Initialize,
  164.   DeInitialize,
  165.   GetInterfaceSchema,
  166.   GetFriendlyName,
  167.   Describe,
  168.   Invoke;
  169. end.

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4468
  • I like bugs.
Re: How to make a Lazarus built dll portable
« Reply #1 on: January 07, 2022, 09:52:01 pm »
You have GetEnvironmentVariable('APPDATA') and some hard-coded paths. Maybe they differ between the computers.
Write debug info into a log file to debug it.

Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: How to make a Lazarus built dll portable
« Reply #2 on: January 08, 2022, 01:36:16 am »
Are the files on both systems using codepage 1252?

The path ends with "hun", shouldn't you use 1250 for Hungarian?

When it fails, what exactly fails?

You can try to debug the dll from within Lazarus by adding the application as a host in:
  Run - Run Parameters - Host application

It depends on the host application, but worth a try.
« Last Edit: January 08, 2022, 01:47:03 am by engkin »

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: How to make a Lazarus built dll portable
« Reply #3 on: January 08, 2022, 09:39:34 pm »
my windows 10 points to the ROAMING folder of the APPDATA when using that method to obtain the APPDATA path.

I don't have anything in my Roaming path, its all in the local..

But there is a Key for LOCALAPPDATA which does point to the local one, maybe you should try that instead.
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018