Archive: ServiceLib appears to have a bug...


ServiceLib appears to have a bug...
Not sure whether this is the right forum, sorry if it is not.

I have been trying to register a service to run as a particular user, and noticed that the ServiceLib code is not passing a "t" for the last three arguments to CreateServiceA.

I changed the code (see below for an example... I can provide the complete file if needed), and now it works fine. Who would be in charge of updating the code on the web site (if it is deemed correct)? I tried to find a way to contact the original author of that code, but couldn't...

Also... the example page at http://nsis.sourceforge.net/archive/...php?pageid=345 should probably mention that the arguments passed to the call need to end with a ";" (I ran into that issue as well).

Finally, as far as I can tell, the "machine" argument should be called more something like "dependencies" (at least according to the MS docs).

Well this is reall the last question... I noticed a stalled thread on finding a way to programatically change the "log on as a service" setting for an account... is there any conclusion/solution for that?

The new code (just replace the relevant old code):
; create service
lbl_create:
Push $R1 ;depend
Push $R2 ;user
Push $R3 ;password
Push $R4 ;interact
Push $R5 ;autostart
Push $R6 ;path

!insertmacro CALL_GETPARAM $R1 "depend" "n" "lbl_depend"
lbl_depend:
StrCmp $R1 "n" lbl_depend_null lbl_depend_not_null
lbl_depend_null:
StrCpy $R7 ""
Goto lbl_depend_done
lbl_depend_not_null:
StrCpy $R7 "t"
lbl_depend_done:

!insertmacro CALL_GETPARAM $R2 "user" "n" "lbl_user"
lbl_user:
StrCmp $R2 "n" lbl_user_null lbl_user_not_null
lbl_user_null:
StrCpy $R8 ""
Goto lbl_user_done
lbl_user_not_null:
StrCpy $R8 "t"
lbl_user_done:

!insertmacro CALL_GETPARAM $R3 "password" "n" "lbl_password"
lbl_password:
StrCmp $R3 "n" lbl_password_null lbl_password_not_null
lbl_password_null:
StrCpy $R9 ""
Goto lbl_password_done
lbl_password_not_null:
StrCpy $R9 "t"
lbl_password_done:

!insertmacro CALL_GETPARAM $R4 "interact" "0x10" "lbl_interact"
StrCpy $6 0x10
IntCmp $R4 0 +2
IntOp $R4 $6 | 0x100
StrCpy $R4 $6
lbl_interact:

!insertmacro CALL_GETPARAM $R5 "autostart" "0x3" "lbl_autostart"
StrCpy $6 0x3
IntCmp $R5 0 +2
StrCpy $6 0x2
StrCpy $R5 $6
lbl_autostart:

!insertmacro CALL_GETPARAM $R6 "path" "n" "lbl_path"
lbl_path:
StrCmp $R6 "n" lbl_path_null lbl_path_not_null
lbl_path_null:
StrCpy $R0 ""
Goto lbl_path_done
lbl_path_not_null:
StrCpy $R0 "t"
lbl_path_done:

System::Call 'advapi32::CreateServiceA(i r4, t r2, t r2, i ${SERVICE_ALL_ACCESS}, i R4, i R5, i 0, $R0 R6, n, n, $R7 R1, $R8 R2, $R9 R3) i.r6'


Thanks,
Sven


dselkirk has a user with the same name on the forums too. You can send him a private message. Let me know if he doesn't respond and I'll see what I can do with the code.


Hi,
for anyone out there still with the problem of registering a service under a particular account... I hope this will save you some time as I spent 2 hours on this. Unfortuntaley the code posted above did not work for me.

There are 2 gotchas to be aware of:
1. The servicelib.nsh library has a problem in formatting $R1 $R2 $R3 parameters when calling:

System::Call 'advapi32::CreateServiceA(...)

$R1 coresponds to what you define as 'machine' in the macro invocation. it will be 'n' if the machine parameter is omitted.

$R2 corresponds to what you define as 'user' in the macro invocation. it will be 'n' if the user parameter is omitted.

$R3 corresponds to what you define as 'password' in the macro invocation. it will be 'n' if the password parameter is omitted.

all works fine if you omitted those 3. If you specify them, you need to change the macro invocation and prepend to them a 't' to tell to the System::Call method that they are text strings.

So if you want to specify user and password, change the call to:
System::Call 'advapi32::CreateServiceA(i r4, t r2, t r2, i ${SERVICE_ALL_ACCESS}, i R4, i R5, i 0, t R6, n, n, R1, t R2, t R3) i.r6'

I know there should be a more generic method to allow user and password to be specified or not, and 'n' or 't' be used. This is just the line I use if I know that I will specify user and password.

2. you cannot set user and password if you have the parameter interact=1 . It must be set to 0. This is a windows requirement. interact=1 works if you do not specify user and password (local system account will be used).

As for username, use DOMAIN\username , or simply .\username for a local account.

Hope this helps, and thanks to everyone for contributing to NSIS!


The CreateService call indeed contains a few problems. It doesn't define the type of the last five parameters. It also tries to pass "n" inside the variable instead of at the variables's place. The later can probably be fixed with a replacement for CALL_GETPARAM that sets a define containing either "n" or "R6" according the input.