Calling DLL functions from HEScript

Hi,

I need to call windows DLL functions.
I’ve tried the example (MsgBox) and it’s working fine but…
I struggle to find how to call other methods that have different prototypes.

For example how can I call :
BOOL WINAPI GetUserName(
Out LPTSTR lpBuffer,
Inout LPDWORD lpnSize
);

I also miss information on what exactly is supported in HEScript.
PChar( ), array definitions, GetMemory() and others Delphi things for example produce syntax errors so I can’t find a way to allocate the char buffer…

This is the only thing actually that prevents me from buying the product for a client’s project.
Please help,

Julien

PChar is not used, the script engine treats them as “string”.

Here is a possible translation:
function GetUserName(lpBuffer: string; nSize: LongWORD): BOOL; stdcall; external "Advapi32.dll" name 'GetUserNameW';
(not tested)

Another example we use in our demos:
function GetEnvironmentVariable(lpName: string; lpBuffer: string; nSize: LongWORD): LongWORD; stdcall; external "kernel32.dll" name 'GetEnvironmentVariableA';

For Pascal syntax supported, please see a PM we sent you with a PDF file that explains how the script engine works.

Thanks for your answer.

Where can I find the demo making a call to GetEnvironmentVariable() you’re talking about ?
That would surely help !

In the « Main Demonstration » that comes with HTML Executable. You can download the source code with the Web Update utility.
Here is one of the scripts used:

// MiscFunctions
// Some functions used for our demonstration.

// Win32 API used to determine the %USERPROFILE% variable if required.
function GetEnvironmentVariable(lpName: string; lpBuffer: string; nSize: LongWORD): LongWORD; stdcall; external "kernel32.dll" name 'GetEnvironmentVariableA';
// Check if a file exists!                                             
                         
function SayHello: Boolean;
begin
 MessageDlg("HTML Executable lets you add your own menu commands!", "HELLO!!", mtInformation, [mbOK]);
end;                 
                       
procedure SayHello2(what: string);
begin                                
 MessageDlg(ReplaceString(what, "%20", " "), "HELLO!!", mtInformation, [mbOK]);
end;
                                                
function GetDesktopImageHTMLPath: String;
var                                                                                        
 a, i: integer;
 S: String;
 Path, Path2: String;
 FilePath: String;
begin              
 Result := "Not supported.";
 try
 // a) Read the path to the desktop image file.                   
 Path := ReadRegStr(hkCurrentUser, "Software\Microsoft\Internet Explorer\Desktop\General", "Wallpaper", "");
 // If blank, then Active Desktop may not be set up.
 if Path = "" then Path := ReadRegStr(hkCurrentUser, "Software\Microsoft\Internet Explorer\Desktop\General", "WallpaperSource", "");
 if Path = "" then exit;
 Path2 := "";
 if Pos("%USERPROFILE%", UpperCase(Path)) > 0 then
 begin
  S := "";
  a := GetEnvironmentVariable("USERPROFILE", S, 255);
  Path2 := ReplaceString(Path, "%USERPROFILE%", "");
  Path := Copy(S, 1, a);
 end;
 if Pos("%SYSTEMROOT%", UpperCase(Path)) > 0 then
 begin
  S := "";
  a := GetEnvironmentVariable("SYSTEMROOT", S, 255);
  Path2 := ReplaceString(Path, "%SYSTEMROOT%", "");
  Path := Copy(S, 1, a);
 end;
 FilePath := Path + Path2;
 if not fileexists(FilePath) then
 begin          
  Result := "The desktop wallpaper file was not found!"
  exit;
 end;
 Result := "<IMG SRC=""" + FilePath + """>";
 except
  Result := "An error occurred";
 end;
end;

I think that it’s wrong because the second parameter of GetUserName is a in/out LPDWORD.
So Maybe
function GetUserName(lpBuffer: string; pSize: Pointer): BOOL; stdcall; external “Advapi32.dll” name ‘GetUserNameW’;
?

But how to get the pointer to size. ^ deferencing operator produces syntax error.

Buffer := “”;
Size := 255;
GetUserName(Buffer, ^Size); // Syntax error.

Thanks again for your help.

It should rather be:

function GetUserName(lpBuffer: String; var nSize: DWORD): BOOL; stdcall; external "Advapi32.dll" name 'GetUserNameW';

We’ll make some deeper tests.

With

function GetUsrName(lpBuffer: string; pSize: LongWORD): BOOL; stdcall;
external “Advapi32.dll” name ‘GetUserNameW’;

and

S := “”;
GetUsrName(S, 255);

I get

Which seems pretty logical to me as 255 should in fact be a pointer to a DWORD and not a DWORD according to MS Doc

Julien

OK I missed the var statement in your post above (I thought it was a typo).

So

function GetUserName(lpBuffer: string; var pSize: LongWORD): BOOL; stdcall; 
external "Advapi32.dll" name 'GetUserNameW';

    S := " ";
    Size := 255;
    ret:= GetUserName(S, Size); 

Seems to work. Note that if I don’t put a space into S (S := “”, like in your sample), I get a crash.
Mmm I don’t really understand how the string is allocated and what is its size…

Well I spoke too fast :sweat:
The program struggle to close after calling the function so I guess there is a memory problem of some kind.

I still need to know the proper way to allocate the string… Thanks

Hi,

I’m sorry to insist but I still need some info about the correct way to allocate and pass the string buffer to the DLL function.
If I do

S := ""

I get a crash (access violation).

If I do

S := " "

I can close the application anymore, probably because of a memory override because the string is too small to contain the value.

What’s the correct way to do that ?
Please help.

Julien

I received a negative answer from the script engine developer, the GetUserName API can’t be used because DWORD pointers won’t work properly.
Anyway, you can get the user name from the registry: look at HKEY_CURRENT_USER\Volatile Environment - USERNAME.
Environment variables also contain useful data, and the API can be successfully imported.

Thank you for the answer and the workaround.

It’s bad news though because lots of those “Get” functions use the DWORD pointer mecanism (for example I was also using GetComputerName and GetComputerNameEx).

Julien

Sure, but you can also find computer name in the registry.