Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a DLL function (GetPrivateProfileSection) using a buffer from Inno Setup

I would like to use GetPrivateProfileSection (from Windows Kernel32.dll) from an Inno Setup script, which is kind of a Delphi (Pascal) program.

But I don't know how to create the buffer which is an Out parameter in the function and where it puts the useful information that I want to retrieve.

like image 205
Carlos E. Ferro Avatar asked Dec 19 '25 20:12

Carlos E. Ferro


1 Answers

The input buffer is a pointer to string, which you can declare simply as string in your function import prototype as long as you'll import proper variant of the function, ANSI or Unicode with respect to which variant of Inno Setup you use.

About the returned buffer, it's a string composed from the key value pairs separated by null characters, which you'll need to process in your code. The following function can read an INI section into the string list e.g.:

[Code]
#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif

function GetPrivateProfileSection(lpAppName: string;
  lpReturnedString: string; nSize: DWORD; lpFileName: string): DWORD;
  external 'GetPrivateProfileSection{#AW}@kernel32.dll stdcall';

function GetIniSection(
  const FileName, Section: string; Strings: TStrings): Integer;
var
  BufLen: DWORD;
  Buffer: string;
begin
  // initialize the result
  Result := 0;
  // first attempt with 1024 chars; use here at least 3 chars so the function can
  // return 1 as a signal of insufficient buffer failure
  SetLength(Buffer, 1024);
  // first attempt to call the function
  BufLen := GetPrivateProfileSection(Section, Buffer, Length(Buffer), FileName);
  // check the first call function result
  case BufLen of
    // the function failed for some reason, that the WinAPI does not provide
    0: Exit;
    // the function returned value of the passed buffer length - 2
    // to indicate that it has insufficient buffer
    Length(Buffer) - 2: 
    begin
      // second attempt with the maximum possible buffer length
      SetLength(Buffer, 32767);
      // this time it should succeed
      BufLen :=
        GetPrivateProfileSection(Section, Buffer, Length(Buffer), FileName);
      // if the returned value is 0, or equals to the passed buffer length - 2,
      // then even this call failed, so let's give it up
      if (BufLen = 0) or (BufLen = Length(Buffer) - 2) then
        Exit;
    end;
  end;
  // the function call succeeded, so let's trim the result
  // (note, that it will trim also the two terminating null characters
  // from the end of the string buffer)
  Buffer := Trim(Buffer);
  // now replace all the null characters with line breaks
  // so we can easily fill the output string list
  StringChangeEx(Buffer, #0, #13#10, True);
  // fill the output string list
  Strings.Text := Buffer;
  // and return the number of items in the output string list
  Result := Strings.Count;
end;

A possible usage:

var
  Strings: TStringList;
begin
  Strings := TStringList.Create;
  try
    { if the function returns value greater than 0, it found a non-empty }
    { section called SectionName in the C:\MyFile.ini file }
    if GetIniSection('C:\MyFile.ini', 'SectionName', Strings) > 0 then
      { process the Strings somehow }
  finally
    Strings.Free;
  end;
end;
like image 174
TLama Avatar answered Dec 22 '25 14:12

TLama



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!