Skip to content
⌘ NSIS Forum Archive

System::Call kernel32::GetPrivateProfileSectionNamesA

8 posts

Guest#

System::Call kernel32::GetPrivateProfileSectionNamesA

Hi,

I try to call 'kernel32::GetPrivateProfileSectionNamesA' with
'System::Call' to get all section names from an Inifile.

The API function returns a buffer with null-terminated strings.

I use the following code:

StrCpy $2 ${NSIS_MAX_STRLEN}
StrCpy $3 "Test.ini"
System::Call "kernel32::GetPrivateProfileSectionNamesA(t, i, t) i(.r1, r2, r3) .r4"

MessageBox MB_ICONEXCLAMATION|MB_OK "$1 $4"

$1 contains only the first section name. Is it possible to use something like shift on $1 to get the other parameters or does System::Call cut off itself the string at first nullchar.

Is there a way to use GetPrivateProfileSectionNamesA in NSIS or should I better use FileOpen, FileRead?

thx
nethai
Joel#
You'll have to parse the return buffer so you can extract eache section name... remember, the delimiter is the null string (\0)
Guest#
Originally posted by Joel
You'll have to parse the return buffer so you can extract eache section name... remember, the delimiter is the null string (\0)
That was my problem: how to parse the buffer. I have found a pattern in GetDrives in NSIS Wiki and adapted it for GetPrivateProfileSectionNamesA.

I am not sure what I should free with System::Free.
The buffer pointer $2 in the original GetDrives is increased by each length of null-terminated string and finally freed with 'System::Free $2' ($2 pointed to the last /0 in buffer), but this itn't the alloced memory at the beginning 'System::Alloc 1024'. Is it a bug in GetDrives or do I misinterpret the use of System::Alloc / System::Free.

Function GetSectionNames
; Based on the method to loop over an array of
; null-terminated strings in function "GetDrives"
;
; Syntax:
; ${GetSectionNames} "File" "Function"
;
; "File" ; name of the initialization file
; "Function" ; Callback function then found
;
; Function "Function"
; ; $9 "section name"
;
; ; $R0-$R9 are not used (save data in them).
; ; ...
;
; Push $var ; If $var="GetSectionNames" Then exit from function
; FunctionEnd

!define GetSectionNames `!insertmacro GetSectionNamesCall`

!macro GetSectionNamesCall _FILE _FUNC
Push $0
Push `${_FILE}`
GetFunctionAddress $0 `${_FUNC}`
Push `$0`
Call GetSectionNames
Pop $0
!macroend

Exch $1
Exch
Exch $0
Exch
Push $2
Push $3
Push $4
Push $5
Push $8
Push $9

System::Alloc 1024
Pop $2
StrCpy $3 $2

System::Call "kernel32::GetPrivateProfileSectionNamesA(i, i, t) i(r3, 1024, r0) .r4"

enumok:
System::Call 'kernel32::lstrlenA(t) i(i r3) .r5'
StrCmp $5 '0' enumex

System::Call '*$3(&t1024 .r9)'

Push $0
Push $1
Push $2
Push $3
Push $4
Push $5
Push $8
Call $1
Pop $9
Pop $8
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
StrCmp $9 'GetSectionNames' enumex

enumnext:
IntOp $3 $3 + $5
IntOp $3 $3 + 1
goto enumok

enumex:
System::Free $2

Pop $9
Pop $8
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
FunctionEnd
nechai#
Originally posted by nechai
Function GetSectionNames
; Based on the method to loop over an array of
; null-terminated strings in function "GetDrives"
;
; Syntax:
; ${GetSectionNames} "File" "Function"
FunctionEnd [/B]
I have created two entries in the wiki.

Get all entries in section of INI file
Get all section names of INI file
Instructor#
Is it a bug in GetDrives or do I misinterpret the use of System::Alloc / System::Free.
You are right.
Fixed: "GetDrives" Alloc/Free. Thanks!
brainsucker#
Hey guys, haven't you got tired of all this endless pops pushes and exchanges? If you are using System::Alloc/Free/Call, then why don't use System::Store?
Strange for me 🙂 You scripts will become much more beautiful and smaller.
Instructor#
I think it's not very good idea to use /NOUNLOAD flag in function. For example:

System::Store /NOUNLOAD "s"
quit

System::Store "l"
Not delete temp folder with system.dll

Will be interesting 🙂 if it will be able to use something like:
System::Push "s"
Pop $0 #Pointer to stack

System::Pop "$0"
deguix#
Hey guys, haven't you got tired of all this endless pops pushes and exchanges? If you are using System::Alloc/Free/Call, then why don't use System::Store?
It can pop and push, but it can't exch. This complicates a little bit the clarity of functions.