Archive: function for writing REG_MULTI_SZ strings


function for writing REG_MULTI_SZ strings
i need to write a reg_multi_sz string fomr my installer and i found this nsis code writen by KiCHiK that reads such strings http://www.cusec.ca/doc/DocSrc/SectionC.7.html

KiCHiK can you make that code into a function that instead of reading such a string creates it ?

or at least help me modify that code into a function that does this

i really need this and it is nesesarry that it be a function so i dont have to write all the code every time i have a multy_sz string to make


Sorry, no time. You'd have to try it on your own.


well here is my best shot
however i dont understand where i should put the data


OutFile "REG_MULTI_SZ_writer.exe"
Name "REG_MULTI_SZ"
ShowInstDetails show

!define HKEY_CLASSES_ROOT 0x80000000
!define HKEY_CURRENT_USER 0x80000001
!define HKEY_LOCAL_MACHINE 0x80000002
!define HKEY_USERS 0x80000003
!define HKEY_PERFORMANCE_DATA 0x80000004
!define HKEY_PERFORMANCE_TEXT 0x80000050
!define HKEY_PERFORMANCE_NLSTEXT 0x80000060
!define HKEY_CURRENT_CONFIG 0x80000005
!define HKEY_DYN_DATA 0x80000006

!define KEY_SET_VALUE 0x0002
!define KEY_CREATE_SUB_KEY 0x0004

!define REG_NONE 0
!define REG_SZ 1
!define REG_EXPAND_SZ 2
!define REG_BINARY 3
!define REG_DWORD 4
!define REG_DWORD_LITTLE_ENDIAN 4
!define REG_DWORD_BIG_ENDIAN 5
!define REG_LINK 6
!define REG_MULTI_SZ 7

!define RegCreateKeyEx "Advapi32::RegCreateKeyA(i, t, i, i, i) i"
!define RegSetValueEx "Advapi32::RegSetValueExA(i, t, i, i, i, i, i) i"
!define RegCloseKey "Advapi32::RegCloseKeyA(i) i"

####### Edit this!
!define ROOT_KEY "${HKEY_LOCAL_MACHINE}"
!define SUB_KEY "SYSTEM\CurrentControlSet\Services\Apache2(SSL)\Parameters"
!define VALUE "ConfigArgs"
!define DATA "-f c:\apache2\conf\httpd.conf"
####### Stop editing

Section "Write"
StrCpy $0 ""
StrCpy $1 ""
StrCpy $2 ""
StrCpy $3 ""
SetPluginUnload alwaysoff
System::Call "*(i) i (0) .r0"
System::Call "*(i) i (0) .r1"
System::Call "*(i) i (0) .r2"
System::Call "${RegCreateKeyEx}(${ROOT_KEY}, '${SUB_KEY}', \
0, ${KEY_SET_VALUE}|${KEY_CREATE_SUB_KEY}, r0) .r3"

StrCmp $3 0 write
MessageBox MB_OK|MB_ICONSTOP "Can't write registry key! ($3)"
Goto done
write:

System::Call "*$0(&i4 .r4)"
System::Call "${RegSetValueEx}(r4, '${VALUE}', 0, r1, 0, r2) .r3"

StrCmp $3 0 done
MessageBox MB_OK|MB_ICONSTOP "Can't set key value! ($3)"
Goto done
done:

System::Free $2
System::Free $1

StrCmp $0 0 noClose
System::Call "${RegCloseKey}(r0)"

noClose:

SetPluginUnload manual
System::Free $0
SectionEnd

ok figured where to put the data but i dont know how to calculate its size


OutFile "REG_MULTI_SZ_writer.exe"
Name "REG_MULTI_SZ"
ShowInstDetails show

!define HKEY_CLASSES_ROOT 0x80000000
!define HKEY_CURRENT_USER 0x80000001
!define HKEY_LOCAL_MACHINE 0x80000002
!define HKEY_USERS 0x80000003
!define HKEY_PERFORMANCE_DATA 0x80000004
!define HKEY_PERFORMANCE_TEXT 0x80000050
!define HKEY_PERFORMANCE_NLSTEXT 0x80000060
!define HKEY_CURRENT_CONFIG 0x80000005
!define HKEY_DYN_DATA 0x80000006

!define KEY_QUERY_VALUE 0x0001
!define KEY_SET_VALUE 0x0002
!define KEY_CREATE_SUB_KEY 0x0004
!define KEY_ENUMERATE_SUB_KEYS 0x0008
!define KEY_NOTIFY 0x0010
!define KEY_CREATE_LINK 0x0020

!define REG_NONE 0
!define REG_SZ 1
!define REG_EXPAND_SZ 2
!define REG_BINARY 3
!define REG_DWORD 4
!define REG_DWORD_LITTLE_ENDIAN 4
!define REG_DWORD_BIG_ENDIAN 5
!define REG_LINK 6
!define REG_MULTI_SZ 7

!define RegCreateKeyEx "Advapi32::RegCreateKeyA(i, t, i) i"
!define RegSetValueEx "Advapi32::RegSetValueExA(i, t, i, i, t, i) i"
!define RegCloseKey "Advapi32::RegCloseKeyA(i) i"

####### Edit this!
!define SUB_KEY "SYSTEM\CurrentControlSet\Services\Apache2(SSL)\Parameters"
!define VALUE "ConfigArgs"
!define DATA "-f c:\apache2\conf\httpd.conf"
####### Stop editing

Section "Write"
StrCpy $0 ""
StrCpy $1 ""
StrCpy $2 ""
StrCpy $3 ""
SetPluginUnload alwaysoff
System::Call "*(i) i (0) .r0"
System::Call "*(i) i (0) .r1"
System::Call "*(i) i (0) .r2"
System::Call "${RegCreateKeyEx}(${HKEY_LOCAL_MACHINE},'${SUB_KEY}',r0) .r3"
;${RegCreateKeyEx}(root key,sub key,subkey handle)

StrCmp $3 0 write
MessageBox MB_OK|MB_ICONSTOP "Can't write registry key! ($3)"
Goto done
write:

; System::Call "*$0(&i4 .r4)"
System::Call "${RegSetValueEx}(r0,'${VALUE}',0,${REG_MULTI_SZ},'${DATA}',29) .r3"
;${RegSetValueEx}(subkey handle,value name,must be zero,value type,value data,lenght of data)

StrCmp $3 0 done
MessageBox MB_OK|MB_ICONSTOP "Can't set key value! ($3)"
Goto done
done:

System::Free $2
System::Free $1

StrCmp $0 0 noClose
System::Call "${RegCloseKey}(r0)"

noClose:

SetPluginUnload manual
System::Free $0
SectionEnd


can you at least tell me what System::Call "*$0(&i4 .r4)" is for and does ?

I have problems with the value insertion, is required from strings with REG_MULTI_SZ the ending of 2 null chars, and a common string has just 1.

The error given was:

ERROR_INVALID_PARAMETER (87)


well i figured out how to get the string lenght (silly me)
but i still dont know what is the symbol for null char in nsis or if there is one


OutFile "REG_MULTI_SZ_writer.exe"
Name "REG_MULTI_SZ"
ShowInstDetails show

!define HKEY_CLASSES_ROOT 0x80000000
!define HKEY_CURRENT_USER 0x80000001
!define HKEY_LOCAL_MACHINE 0x80000002
!define HKEY_USERS 0x80000003
!define HKEY_PERFORMANCE_DATA 0x80000004
!define HKEY_PERFORMANCE_TEXT 0x80000050
!define HKEY_PERFORMANCE_NLSTEXT 0x80000060
!define HKEY_CURRENT_CONFIG 0x80000005
!define HKEY_DYN_DATA 0x80000006

!define KEY_QUERY_VALUE 0x0001
!define KEY_SET_VALUE 0x0002
!define KEY_CREATE_SUB_KEY 0x0004
!define KEY_ENUMERATE_SUB_KEYS 0x0008
!define KEY_NOTIFY 0x0010
!define KEY_CREATE_LINK 0x0020

!define REG_NONE 0
!define REG_SZ 1
!define REG_EXPAND_SZ 2
!define REG_BINARY 3
!define REG_DWORD 4
!define REG_DWORD_LITTLE_ENDIAN 4
!define REG_DWORD_BIG_ENDIAN 5
!define REG_LINK 6
!define REG_MULTI_SZ 7

!define RegCreateKeyEx "Advapi32::RegCreateKeyA(i, t, i) i"
!define RegSetValueEx "Advapi32::RegSetValueExA(i, t, i, i, t, i) i"
!define RegCloseKey "Advapi32::RegCloseKeyA(i) i"

####### Edit this!
!define SUB_KEY "SYSTEM\CurrentControlSet\Services\Apache2(SSL)\Parameters"
!define VALUE "ConfigArgs"
!define DATA "-f\0c:\apache2\conf\httpd.conf\0\0"
####### Stop editing

Section "Write"
StrCpy $0 ""
StrCpy $1 ""
StrCpy $2 ""
StrCpy $3 ""
SetPluginUnload alwaysoff
System::Call "*(i) i (0) .r0"
System::Call "*(i) i (0) .r1"
System::Call "*(i) i (0) .r2"
System::Call "${RegCreateKeyEx}(${HKEY_LOCAL_MACHINE},'${SUB_KEY}',r0) .r3"
;${RegCreateKeyEx}(root key,sub key,subkey handle)

StrCmp $3 0 write
MessageBox MB_OK|MB_ICONSTOP "Can't write registry key! ($3)"
Goto done
write:

; System::Call "*$0(&i4 .r4)"
StrLen $9 '${DATA}'
IntOp $9 $9 + 1
System::Call "${RegSetValueEx}(r0,'${VALUE}',0,${REG_MULTI_SZ},'${DATA}',$9) .r3"
;${RegSetValueEx}(subkey handle,value name,must be zero,value type,value data,lenght of data)

StrCmp $3 0 done
MessageBox MB_OK|MB_ICONSTOP "Can't set key value! ($3)"
Goto done
done:

System::Free $2
System::Free $1

StrCmp $0 0 noClose
System::Call "${RegCloseKey}(r0)"

noClose:

SetPluginUnload manual
System::Free $0
SectionEnd

NSIS strings are automatically cut off when there is a null char.


ok .. well then there is no solution to this ?


Did you get working the first part of your code? (I'm working to fix the code)


everything works for me besides the RegSetValue call


Yep, as everybody is using more the System plugin, new requirements exist, one of them is to add support to include null strings in variables, in NSIS or System plugin.

For me your first part code doesn't work for me, what OS are you using? Win 98? (I have Win XP)


Enjoy :)


Oh man! That is awsome! Where did you find that? It HAS to be in the documentation of System plugin.


Ah, now I know, the old brainsucker lessons. Now I've a lot to do...


Where did you find that?
It's basically the same as kichik's original example but with the innards reversed. The key to both routines is the &t stuff. At no time is the whole multi_sz value in a NSIS string, so we don't need to worry about the NSIS null-in-string restriction.

I also used the * syntax to simplify the code that deals with the registry handle.

thanks eccles

and here is that code turned into a function that can be called multiple times with diferent values from inside a section

however there is a problem .. it only works on versions newer than 20beta3.. because the var comand was implemented in 20beta4


OutFile "REG_MULTI_SZ_writer.exe"
Name "REG_MULTI_SZ"
ShowInstDetails show

var SUB_KEY
var VALUE
var DATA_1
var DATA_2

Section Test
strcpy $SUB_KEY "SYSTEM\CurrentControlSet\Services\Apache2\Parameters"
strcpy $VALUE "ConfigArgs"
strcpy $DATA_1 "-f"
strcpy $DATA_2 "c:\apache2\conf\httpd.conf"
Call RegWrite

strcpy $SUB_KEY "SYSTEM\CurrentControlSet\Services\Apache2(SSL)\Parameters"
strcpy $VALUE "ConfigArgs"
strcpy $DATA_1 "-f"
strcpy $DATA_2 "c:\apache2\conf\httpd.conf"
Call RegWrite
SectionEnd

Function RegWrite
!define HKEY_CLASSES_ROOT 0x80000000
!define HKEY_CURRENT_USER 0x80000001
!define HKEY_LOCAL_MACHINE 0x80000002
!define HKEY_USERS 0x80000003
!define HKEY_PERFORMANCE_DATA 0x80000004
!define HKEY_PERFORMANCE_TEXT 0x80000050
!define HKEY_PERFORMANCE_NLSTEXT 0x80000060
!define HKEY_CURRENT_CONFIG 0x80000005
!define HKEY_DYN_DATA 0x80000006

!define KEY_QUERY_VALUE 0x0001
!define KEY_SET_VALUE 0x0002
!define KEY_CREATE_SUB_KEY 0x0004
!define KEY_ENUMERATE_SUB_KEYS 0x0008
!define KEY_NOTIFY 0x0010
!define KEY_CREATE_LINK 0x0020

!define REG_NONE 0
!define REG_SZ 1
!define REG_EXPAND_SZ 2
!define REG_BINARY 3
!define REG_DWORD 4
!define REG_DWORD_LITTLE_ENDIAN 4
!define REG_DWORD_BIG_ENDIAN 5
!define REG_LINK 6
!define REG_MULTI_SZ 7

!define RegCreateKey "Advapi32::RegCreateKeyA(i, t, *i) i"
!define RegSetValueEx "Advapi32::RegSetValueExA(i, t, i, i, i, i) i"
!define RegCloseKey "Advapi32::RegCloseKeyA(i) i"

SetPluginUnload alwaysoff
; Create a buffer for the multi_sz value
System::Call "*(&t${NSIS_MAX_STRLEN}) i.r1"
; Open/create the registry key
System::Call "${RegCreateKey}(${HKEY_LOCAL_MACHINE}, '$SUB_KEY', .r0) .r9"
; Failed?
IntCmp $9 0 write
MessageBox MB_OK|MB_ICONSTOP "Can't create registry key! ($9)"
Goto noClose

write:
; Fill in the buffer with our strings
StrCpy $2 $1 ; Initial position

StrLen $9 '$DATA_1' ; Length of first string
IntOp $9 $9 + 1 ; Plus null
System::Call "*$2(&t$9 '$DATA_1')" ; Place the string
IntOp $2 $2 + $9 ; Advance to the next position

StrLen $9 '$DATA_2' ; Length of second string
IntOp $9 $9 + 1 ; Plus null
System::Call "*$2(&t$9 '$DATA_2')" ; Place the string
IntOp $2 $2 + $9 ; Advance to the next position

System::Call "*$2(&t1 '')" ; Place the terminating null
IntOp $2 $2 + 1 ; Advance to the next position

; Create/write the value
IntOp $2 $2 - $1 ; Total length
System::Call "${RegSetValueEx}(r0, '$VALUE', 0, ${REG_MULTI_SZ}, r1, r2) .r9"
; Failed?
IntCmp $9 0 done
MessageBox MB_OK|MB_ICONSTOP "Can't set key value! ($9)"
Goto done

done:
; Close the registry key
System::Call "${RegCloseKey}(r0)"

noClose:
; Clear the buffer
SetPluginUnload manual
System::Free $1
FunctionEnd

Continue to request System codes, I'm collecting them all, including all the old ones...