- NSIS Discussion
- Binary read
Archive: Binary read
superruzafa
13th January 2005 20:35 UTC
Binary read
Hi,
I must modify some parts of a 153 Mb binary file. The only function I've found that performs this is FileReadByte and FileWriteByte but are toooooooooo slow.
Is there any way to read/write strings of non-character bytes using FileRead/FileWrite? Or I must making an external program who performs that?
Thanks
kichik
13th January 2005 20:44 UTC
If you want to patch a binary file, why not use VPatch?
superruzafa
13th January 2005 20:58 UTC
Could you write the link?
kichik
13th January 2005 21:00 UTC
It's in your Contrib folder.
superruzafa
13th January 2005 21:13 UTC
Sorry, I'm a total newbie and I don't know where that folder is. I'll search other posts ;)
kichik
13th January 2005 21:15 UTC
Where you installed NSIS, there's a folder named Contrib. Inside that folder, there's a folder named VPatch. Normally, that should be:
C:\Program Files\NSIS\Contrib\VPatch
Afrow UK
13th January 2005 21:40 UTC
Have a good look around your NSIS directory. It's always a good idea to know what's available to you :)
-Stu
Takhir
14th January 2005 11:31 UTC
I had to write my own binary read script for license page. It was empty installer with all files located in CVS folders including installer itself and license file, and like Joost wrote long ago we can use WM_SETTEXT for txt files. The only problem I found - System plug-in can not allocate variable size memory (&t$1), but calloc() can ;) Sample script attached.
Might be good to allow users to skip License file name for such situations in MUI page definition, 0 parameters may create warning only, in this script I had to use additional short "dummy.txt" file (not committed to our CVS, this may create problems with later installer rebuilds :( ).
kichik
14th January 2005 11:49 UTC
The System.dll plug-in should have no problem allocating variable size memory blocks. The problem you've encountered is probably NSIS's string size limit (1024 by default). If you read using FileRead and then append using a call to lstrcat, it should be OK.
BTW, it's not a good idea to allocate using calloc and free using System::Free. They use two different allocation methods. In the worst case, it can cause a crash. Usually, it should just create a memory leak.
Takhir
14th January 2005 12:27 UTC
Thanks, KichiK!
Might be something was wrong in my syntax, this not worked with System::Call allocation, but looks OK now with Alloc and Free.
BTW I used
System::Alloc '$1 .r0'
syntax in the updated file, and this works fine, but System.htm uses
System::Alloc 64
Pop $0
Is my variant correct?
kichik
14th January 2005 12:32 UTC
Your variant is incorrect. Take a look at Contrib\System\Source\Buffers.c. Alloc is right on the top.
Takhir
14th January 2005 12:52 UTC
OK, I'll better use my favourite msvcrt calls ;)
superruzafa
14th January 2005 14:47 UTC
I've found very interesting all you have talk.
Where can I find more info about system calls and the parameters for that functions?
BTW, I made an patch.exe file which does the patching logic and I call externally.
kichik
14th January 2005 14:49 UTC
You can find information about the System plug-in in its readme. You can find the readme, the source code and some examples in <nsis folder>\Contrib\System.
superruzafa
14th January 2005 16:07 UTC
Take a look of that code. I have a binary file "prueba.bin" who is 1024 bytes and I try to copy into another file, but nothing happens.
Need more code? (includes, defines) or simplily the params are wrong?
System::Call 'msvcrt.dll::calloc(i 1024, i 1) i .r0' ; creates a 1024 size buffer
System::Call 'msvcrt.dll::_open(t "$INSTDIR\prueba.bin, i 0x8000) i .r1' ; open first file
System::Call 'msvcrt.dll::_open(t "$INSTDIR\prueba2.bin, i 0x8101) i .r2' ; open second file
System::Call 'msvcrt.dll::_read(i r1, i r0, 1024) i .r3' ;read the first file
System::Call 'msvcrt.dll::_write(i r2, i r0, 1024) i .r3' ;and writes to the second
System::Call 'msvcrt.dll::_close(i r1)' ; close file 1
System::Call 'msvcrt.dll::_close(i r2)' ; close file 2
kichik
14th January 2005 16:09 UTC
You're missing closing quotes for the file names in both _open calls.
superruzafa
14th January 2005 16:20 UTC
Originally posted by kichik
You're missing closing quotes for the file names in both _open calls.
:eek: Ups. Now file is created but nothing is readed nor writed. I'll continue investigating about that :cool:
kichik
14th January 2005 16:22 UTC
It might be because you're missing an `i` before 1024 in the _read and _write lines.
superruzafa
14th January 2005 16:24 UTC
I got it! :D
It failed type for 1024. Well, hope this will serve for others.
System::Call 'msvcrt.dll::_read(i r1, i r0, /* this -> */ i 1024) i .r3'
System::Call 'msvcrt.dll::_write(i r2, i r0, /* and this -> */ i 1024) i .r3'
superruzafa
14th January 2005 16:26 UTC
It seems we are writing at time, ;)
Thanks for all, guys
Takhir
15th January 2005 10:56 UTC
And
System::Call 'msvcrt.dll::free(i ro)'
at the end of code :)
superruzafa
15th January 2005 11:02 UTC
I've used System::Alloc and System::Free for that.
Is a good idea to allocate memory with those functions and then use the memory allocated with msvcrt.dll call functions?
Takhir
15th January 2005 11:08 UTC
This is not a problem I guess, both allocs should work with this code 100%. But System::Alloc + Pop take 2 lines of script :( - this is the only reason why I used direct msvcrt calls.
superruzafa
17th January 2005 13:37 UTC
What if msvcrt.dll isn't installed? Must I include in the installer? And then, extract and installing?
Takhir
17th January 2005 13:46 UTC
Don't worry about msvcrt.dll ;)
Only msvcrtd.dll (debug version) may not present.