Archive: system plugin + GetPrivateProfileSectionNames crash


system plugin + GetPrivateProfileSectionNames crash
Hi Everyone,

I'm using a sample script to read ini files, especially to read section names, to determine if a section exist before try to delete it.

The problem is that the installer crashes randomically, I could check that the size of section is always right, but when the error shows, it is at below call:

System::Call `kernel32::lstrlen(i $pNextSection)i.r5`
$NOMESECTION is defined on another macro that calls this func, removing the callback gives the same error, so I choose put complete code here.

I dont know much about pointers, but I think it is all ok with the calls.

My function:

!define GSN_BufferSize 1024

VAR /GLOBAL lpszReturnBuffer
VAR /GLOBAL fncAddr
VAR /GLOBAL nSize
VAR /GLOBAL pNextSection
VAR /GLOBAL IniPath
VAR /GLOBAL iniSecSize
VAR /GLOBAL PTR_FNC

!define GetSectionNames `!insertmacro GetSectionNamesCall`

!macro GetSectionNamesCall _FILE _FUNC
StrCpy `$IniPath` `${_FILE}`
GetFunctionAddress $fncAddr `${_FUNC}`
Call GetSectionNames
!macroend


Function GetSectionNames

System::Call `*(&t${GSN_BufferSize})i.r2`
StrCpy $PTR_FNC $2
StrCpy $lpszReturnBuffer $2

System::Call `kernel32::GetPrivateProfileSectionNames(i,i,t) ($lpszReturnBuffer, ${GSN_BufferSize}, '$IniPath')`
StrCpy $pNextSection $lpszReturnBuffer

${Do}
System::Call `kernel32::lstrlen(i $pNextSection)i.r5`
StrCpy $iniSecSize $5

System::Call `*$pNextSection(&m${GSN_BufferSize} .r9)`
Call $fncAddr

${If} $9 == 'StopGetSectionName'
${ExitDo}
${Endif}

IntOp $pNextSection $pNextSection + $iniSecSize
IntOp $pNextSection $pNextSection + 1

System::Call `kernel32::lstrlen(i $pNextSection)i.r5`
StrCpy $iniSecSize $5

${LoopWhile} $iniSecSize != 0

System::Free $PTR_FNC

FunctionEnd


Function LISTASECTIONCALLBACK

${If} $9 == $NOMESECTION
StrCpy $9 'StopGetSectionName'
${Endif}

FunctionEnd

If this is a unicode installer:

System::Call `*$pNextSection(&m${GSN_BufferSize} .r9)` should use t type.
IntOp $pNextSection $pNextSection + 1 needs to be + 2


Hi Anders,

I´m not using Unicode here, its not clear on MSDN if I'll need to call the function with A or W when not specific for one system or another, focus here is only pt-br, and using default chars (32-127).

Is there any problem with these conditions?

Anyway, I'll do some tests based on your post... I'll come back with the results.


Test Results...
Changing + 1 to + 2 on "IntOp $pNextSection $pNextSection + 1" cuts the first letter from the second section name and so on...

Calling GetPrivateProfileSectionNames or GetPrivateProfileSectionNamesA I have same result.

Calling GetPrivateProfileSectionNamesW gives a empty result on lstrlen call, but Unicode is not the focus , I'll just ignore this.

Changing "*$pNextSection(&m" to "*$pNextSection(&t" gives the same result, and the crashes (randomically) continues.

I Forgot to tell, at the point the function is called, the stack is empty.

The only thing I can tell is that the crash happens upon calling the line
"System::Call `*$pNextSection(&t${GSN_BufferSize} .r9)`"
the last error I´d get has on 3rd section of ini file (total sections is 14 for test file).

Hope this helps, many thanks in advance.

Edit:
Forgot to ask... is there any newer version os system plugin? cant find references on wiki... mine is from 5/12/2009 that come with nsis last nsis version.


"System::Call `*$pNextSection(&t${GSN_BufferSize} .r9)`" is probably not OK if GSN_BufferSize is above 1024.

Try my version


Everything ok
Anders,

So far so good, everything ok.

Can you explain what´s wrong with the other implementation?

Í'll keep testing, but assume it is ok, tested a lot of times without crash.

I dont understand some points on new code like the lines below.

!ifdef IniGetSectionNames_StopEnum
${If} $3 == "$\n"
System::Call '*$0(&i${NSIS_CHAR_SIZE} 0)'
${EndIf}
!endif
Goto loop
This line is just to not test strlen = 1 for the 'newline' char?
I dont get how this pointer Works...

Thanks again, you have saved me a lot of time, and I think this function is useful to others on fórum... how we can update the wiki with this?

The \n is not a valid section name so it is a good magic value, the system call just "ends" the string (In C this would be mystrptr[0] = '\0';) so lstrlen will return 0 and end the loop...


Many thanks
Anders,

I have imagined that 'magic value', but dunno how to put it in code.

Many thanks for the big Help and enlightment about your solution approach.

Moderator can mark this as solved if needed.