I want in nsis to be able to read from file contents into byte array, update the array and then write the contents of the buffer into another file.
My Code
System::Call "kernel32::GetFileSize(i$0,i0)i.s"
Pop $7
System::Alloc $7 ;Reading file contents into a buffer
Pop $buffer
System::Call "kernel32::ReadFile(i$0,i$buffer,i$7,*i.r6,i0)i.s"
loop2:
StrCpy $2 $buffer 1 $1
StrCmp $2 '' end
IntOp $1 $1 + 1
goto loop2
I wanted to be able to iterate over the byte array that i read from the file and to be able to change its contents. (OR bytes for instance) and i wanted to save time from reading byte from a file directly and then writing single byte to a new file. So thats why wanted to use buffer byte array allocated. Is that possible? I saw that nsis does not support arrays natively.
NSIS does not support byte arrays but the System plug-in struct syntax allows you to access raw bytes in a memory buffer:
!include LogicLib.nsh
!include Util.nsh
ShowInstDetails show
!macro DisplayTestFile
FileOpen $0 "$PluginsDir\Test.txt" r
FileRead $0 $1
FileClose $0
DetailPrint Line1=$1
!macroend
Section
InitPluginsDir
FileOpen $0 "$PluginsDir\Test.txt" w
${If} $0 P<> 0
FileWrite $0 "HELLO World$\r$\n"
FileClose $0
${EndIf}
!insertmacro DisplayTestFile
FileOpen $0 "$PluginsDir\Test.txt" a
${If} $0 P<> 0
FileSeek $0 0 Set
System::Call "KERNEL32::GetFileSize(pr0,p0)i.r1"
${IfThen} $1 = -1 ${|} Abort "Could not get file size" ${|}
System::Call '*(&i$1,i0)p.r2' ; Allocate the file size + a zero terminator just in case
${If} $2 P<> 0
System::Call "KERNEL32::ReadFile(pr0,pr2,ir1,*i,p0)i.r3"
${If} $3 <> 0
${For} $3 0 5 ; Change byte 0..5
System::Call '*$2(&i$3,&i1.r4)' ; Read a byte
IntOp $4 $4 | 32
System::Call '*$2(&i$3,&i1 r4)' ; Write a byte
${Next}
FileSeek $0 0 Set
System::Call "KERNEL32::WriteFile(pr0,pr2,ir1,*i,p0)i.r3"
${EndIf}
System::Free $2
${EndIf}
FileClose $0
${EndIf}
!insertmacro DisplayTestFile
SectionEnd