A Sample Service

Well, now the most interesting part of the chapter beginsnaturally, these are the examples. For clarity, I have divided the task into four subtasks : writing the service program, registering the service in the system registry, starting the service, and stopping the service and removing it from the registry. The SERV.EXE program presented in Listing 21.1 cannot be started in a normal way. If you try, you'll fail. The structure of this program requires it to be previously registered in the system registry using the SETSERV.EXE program shown in Listing 21.2. After that, the service can be started for execution using the STSERV.EXE program presented in Listing 21.3. The same result can be achieved using the standard Services console in the standard Administrative Tools window. Finally, the service can be deleted using the DELSERV.EXE program (Listing 21.4) whether it is running or not.

Listing 21.1: The simplest service (SERV.EXE)
image from book
 .586P ; Flat' memory model .MODEL FLAT, stdcall ; Constants SERVICE_CONTROL_STOP            equ 1h SERVICE_CONTROL_SHUTDOWN        equ 5h SERVICE_CONTROL_INTERROGATE     equ 4h SERVICE_CONTROL_CONTINUE        equ 3h SERVICE_START_PENDING           equ 2h ERROR_SERVICE_SPECIFIC_ERROR    equ 1066 SERVICE_RUNNING                 equ 4h MB_SERVICE_NOTIFICATION         equ 200000h CRST EQU SERVICE_CONTROL_STOP OR \ SERVICE_CONTROL_SHUTDOWN OR \ SERVICE_CONTROL_CONTINUE SERVICE_WIN32_OWN_PROCESS       equ 00000010h ; Prototypes of external procedures IFDEF MASM         EXTERN  Sleep@4:NEAR         EXTERN  SetServiceStatus@8:NEAR         EXTERN  RegisterServiceCtrlHandlerA@8:NEAR         EXTERN  StartServiceCtrlDispatcherA@4:NEAR         EXTERN  ExitProcess@4:NEAR         EXTERN  MessageBoxA@16:NEAR ELSE         EXTERN  Sleep:NEAR         EXTERN  SetServiceStatus:NEAR         EXTERN  RegisterServiceCtrlHandlerA:NEAR         EXTERN  StartServiceCtrlDispatcherA:NEAR         EXTERN  ExitProcess:NEAR         EXTERN  MessageBoxA:NEAR         Sleep@4 = Sleep         SetServiceStatus@8 = SetServiceStatus         MessageBoxA@16 = MessageBoxA         RegisterServiceCtrlHandlerA@8 = RegisterServiceCtrlHandlerA         StartServiceCtrlDispatcherA@4=StartServiceCtrlDispatcherA         ExitProcess@4 = ExitProcess ENDIF ; INCLUDELIB directives for the linker IFDEF MASM         includelib d:\masm32\lib\user32.lib         includelib d:\masm32\lib\kernel32.lib         includelib d:\masm32\lib\advapi32.lib ELSE         includelib c:\tasm32\lib\import32.lib ENDIF ;------------------------------------------------ SSTATUS STRUC         STYPE    DD ?         SSTATE   DD ?         SACCEPT  DD ?         SEXCODE  DD ?         SEXSCOD  DD ?         SCHEKPO  DD ?         SWAITHI  DD ? SSTATUS ENDS ; Data segment _DATA SEGMENT         SNAME   DB "MyService", 0         DTS     DD OFFSET SNAME, OFFSET WINSERV, 0, 0         SRS     SSTATUS <0>         H1      DD ? _DATA ENDS ; Code segment _TEXT SEGMENT START: ; Service registration         PUSH  OFFSET DTS         CALL  StartServiceCtrlDispatcherA@4 ; Exit after the service has stopped         PUSH  0         CALL  ExitProcess@4 ; The service WINSERV PROC ; Fill the structure         MOV   SRS.STYPE, SERVICE_WIN32_OWN_PROCESS         MOV   SRS.SSTATE, SERVICE_RUNNING ; SERVICE_START_PENDING         MOV   SRS.SACCEPT, CRST         MOV   SRS.SEXCODE, 0 ; ERROR_SERVICE_SPECIFIC_ERROR         MOV   SRS.SEXSCOD, 0         MOV   SRS.SCHEKPO, 0         MOV   SRS.SWAITHI, 1 ; Register the command-handling function         PUSH  OFFSET HANDLER         PUSH  OFFSET SNAME         CALL RegisterServiceCtrlHandlerA@8 ; Set the status         MOV   H1, EAX         PUSH  OFFSET SRS         PUSH  H1         CALL  SetServiceStatus@8 ; Main function of this service starts here         PUSH  200000         CALL  Sleep@4 ; Set the status         MOV   SRS.SSTATE, SERVICE_CONTROL_STOP         PUSH  OFFSET SRS         PUSH  H1         CALL  SetServiceStatus@8         RET   8 WINSERV ENDP ; Interrupt handler ; [EBP+08H] - The only parameter HANDLER PROC         PUSH  EBP         MOV   EBP, ESP         INC   SRS.SCHEKPO         MOV   EAX, DWORD PTR [EBP+08H]         CMP   EAX, SERVICE_CONTROL_STOP         JNZ   NO_STOP         MOV   SRS.SSTATE, SERVICE_CONTROL_STOP         JMP   _SET NO_STOP:         CMP   EAX, SERVICE_CONTROL_SHUTDOWN         JNZ   NO_SHUTDOWN         MOV   SRS.SSTATE, SERVICE_CONTROL_STOP         JMP   _SET NO_SHUTDOWN:         CMP   EAX, SERVICE_CONTROL_CONTINUE         JNZ   NO_CONTINUE         MOV   SRS.SSTATE, SERVICE_CONTROL_CONTINUE         JMP   _SET NO_CONTINUE:         CMP   EAX, SERVICE_CONTROL_INTERROGATE ; Set the service status _SET:         PUSH  OFFSET SRS         PUSH  H1         CALL  SetServiceStatus@8 ; The message included for debugging ; The MB_SERVICE_NOTIFICATION constant is required         PUSH  0 OR MB_SERVICE_NOTIFICATION         PUSH  OFFSET SNAME         PUSH  OFFSET SNAME         PUSH  0         CALL  MessageBoxA@16 ;----------------------------         MOV   ESP, EBP         POP   EBP         RET   4 HANDLER ENDP _TEXT ENDS END START 
image from book
 

The program presented in Listing 21.1 requires some comments.

  • Pay attention to the program structure. As already mentioned, it contains the main function (the START label), the logical service (in this program, there is only one such service WINSERV ), and the command handler called HANDLER .

  • For simplicity, I used the Sleep function with a long delay as the executable process. When the STSERV program starts for execution, this function is started. Principally, this service doesn't need to be stopped forcibly , because after the termination of the sleep function it will stop automatically.

  • The WINSERV function is terminated by RET 8 . This means that two parameters are sent to the function but are never processed (see the description of StartService ).

  • From the Assembly language programmer's point of view, the structure of the HANDLER procedure is simple. Principally, this handler is needed only for processing the SERVICE_CONTROL_STOP command.

  • For debugging purposes, I have placed the MessageBox function into the command handler. This aspect is quite interesting. The message must appear in relation to a specific desktop. Because of this, I used the MB_SERVICE_NOTIFICATION constant intended for displaying the messages from the service. This message will appear even if no user is logged on to the computer.

  • The RET 4 command that terminates the handler means that only one parameterthe command to the serviceis accepted in the course of the call.

To translate this program, issue the following commands for MASM32:

 ML /c /coff /DMASM serv.asm     LINK /SUBSYSTEM.CONSOLE serv.obj 

Issue the following commands for TASM32:

 TASM32 /ml serv.asm     TLINK32 -ap serv.obj 
Listing 21.2: The program that installs the service (SETSERV.EXE)
image from book
 .586P ; Flat memory model .MODEL FLAT, stdcall ; Constants STD_OUTPUT_HANDLE          equ -11 SC_MANAGER_ALL_ACCESS      equ 0F003Fh SERVICE_ALL_ACCESS         equ 0F01FFH SERVICE_WIN32_OWN_PROCESS  equ 00000010h SERVICE_DEMAND_START       equ 00000003h SERVICE_ERROR_NORMAL       equ 00000001h ; Prototypes of external procedures IFDEF MASM         EXTERN  CreateServiceA@52:NEAR         EXTERN  CloseServiceHandle@4:NEAR         EXTERN  OpenSCManagerA@12:NEAR         EXTERN  wsprint fA:NEAR         EXTERN  GetLastError@0:NEAR         EXTERN  StartServiceCtrlDispatcherA@4:NEAR         EXTERN  ExitProcess@4:NEAR         EXTERN  lstrlenA@4:NEAR         EXTERN  WriteConsoleA@20:NEAR         EXTERN  GetStdHandle@4:NEAR ELSE         EXTERN  CreateServiceA:NEAR         EXTERN  CloseServiceHandle:NEAR         EXTERN  OpenSCManagerA:NEAR         EXTERN  _wsprintfA:NEAR         EXTERN  GetLastError:NEAR         EXTERN  StartServiceCtrlDispatcherA:NEAR         EXTERN  ExitProcess:NEAR         EXTERN  MessageBoxA:NEAR         EXTERN  lstrlenA:NEAR         EXTERN  WriteConsoleA:NEAR         EXTERN  GetStdHandle:NEAR         CreateServiceA@52 = CreateServiceA         CloseServiceHandle@4 = CloseServiceHandle         OpenSCManagerA@12 = OpenSCManagerA         GetStdHandle@4 = GetStdHandle         WriteConsoleA@20 = WriteConsoleA         lstrlenA@4 = lstrlenA         wsprintfA = _wsprintfA         GetLastError@0 = GetLastError         StartServiceCtrlDispatcherA@4 = StartServiceCtrlDispatcherA         ExitProcess@4 = ExitProcess ENDIF ; INCLUDELIB directives for the linker IFDEF MASM         includelib d:\masm32\lib\user32.lib         includelib d:\masm32\lib\kernel32.lib         includelib d:\masm32\lib\advapi32.lib ELSE         includelib c:\tasm32\lib\import32.lib ENDIF ;----------------------------------------------- ; Data segment _DATA SEGMENT     H1      DD ?     H2      DD ?     ALIGN   4     SNAME1  DB "MyService", 0     ALIGN  4     NM     DB "D:\masm32\BIN\serv.exe", 0     LENS   DD 0     HANDL  DD 0     BUF1   DB 512 DUP(0)     ERRS   DB "Error %u ", 0 _DATA ENDS ; Code segment _TEXT SEGMENT START: ; Define the output console handle         PUSH  STD_OUTPUT_HANDLE         CALL  GetStdHandle@4         MOV   HANDL, EAX ; Open the services database         PUSH  SC_MANAGER_ALL_ACCESS         PUSH  0         PUSH  0         CALL  OpenSCManagerA@12         CMP   EAX, 0         JNZ   NO_ERR         CALL  ERROB         JMP   EXI NO_ERR:         MOV   H1, EAX ; Identifier received; now, create the service         PUSH  0         PUSH  0         PUSH  0         PUSH  0         PUSH  0         PUSH  OFFSET NM         PUSH  SERVICE_ERROR_NORMAL         PUSH  SERVICE_DEMAND_START         PUSH  SERVICE_WIN32_OWN_PROCESS         PUSH  SERVICE_ALL_ACCESS         PUSH  OFFSET SNAME1         PUSH  OFFSET SNAME1         PUSH  H1         CALL  CreateServiceA@52         CMP   EAX, 0         JNZ   CLOS         MOV   H2, EAX         CALL  ERROB         JMP   CLOS1 ; Error-handling block ERROB:         CALL  GetLastError@0         PUSH  EAX         PUSH  OFFSET ERRS         PUSH  OFFSET BUF1         CALL  wsprintfA         ADD   ESP, 12         LEA   EAX, BUF1         MOV   EDI, 1         CALL  WRITE         RET CLOSE1: ; Close the service         PUSH  H2         CALL  CloseServiceHandle@4 CLOSE: ; Close the services database         PUSH  H1         CALL  CloseServiceHandle@4 EXI: ; Exit after all services terminate         PUSH  0         CALL  ExitProcess@4 ; Output the string (line feed in the end) ; EAX --- To the start of the string ; EDI - With or without the line feed WRITE PROC ; Get the parameter length         PUSH  EAX         PUSH  EAX         CALL  lstrlenA@4         MOV   ESI, EAX         POP   EBX         CMP   EDI, 1         JNE   NO_ENT ; Line feed in the end         MOV   BYTE PTR [EBX+ESI], 13         MOV   BYTE PTR [EBX+ESI+1], 10         MOV   BYTE PTR [EBX+ESI+2], 0         ADD   EAX, 2 NO_ENT: ; String output         PUSH  0         PUSH  OFFSET LENS         PUSH  EAX         PUSH  EBX         PUSH  HANDL         CALL  WriteConsoleA@20         RET WRITE   ENDP _TEXT ENDS END START 
image from book
 

When considering the program presented in Listing 21.2 (SETSERV.EXE), pay attention to the following aspects:

  • This program registers the SERV.EXE service in the system registry using the CreateService API function.

  • Note that here you handle all possible errors when using this function and, if an error has occurred, you output the error code to the console.

To translate this program, issue the following commands for MASM32:

 ML /c /coff /DMASM setserv.asm     LINK /SUBSYSTEM:CONSOLE setserv.obj 

Issue the following commands for TASM32:

 TASM32 /ml setserv.asm     TLINK32 -ap setserv.obj 
Listing 21.3: The program that starts the service (STSERV.EXE)
image from book
 .586P ; Flat memory model .MODEL FLAT, stdcall ; Constants DELETE                     equ 10000h STD_OUTPUT_HANDLE          equ -11 SC_MANAGER_ALL_ACCESS      equ 0F003Fh SERVICE_ALL_ACCESS         equ 0F01FFH SERVICE_WIN32_OWN_PROCESS  equ 00000010h SERVICE_DEMAND_START       equ 00000003h SERVICE_ERROR_NORMAL       equ 00000001h SERVICE_CONTROL_STOP       equ 1h ; Prototypes of external procedures IFDEF MASM         EXTERN  StartServiceA@12:NEAR         EXTERN  OpenServiceA@12:NEAR         EXTERN  CloseServiceHandle@4:NEAR         EXTERN  OpenSCManagerA@12:NEAR         EXTERN  wsprintfA:NEAR         EXTERN  GetLastError@0:NEAR         EXTERN  ExitProcess@4:NEAR         EXTERN  lstrlenA@4:NEAR         EXTERN  WriteConsoleA@20:NEAR         EXTERN  GetStdHandle@4:NEAR ELSE         EXTERN  StartServiceA:NEAR         EXTERN  OpenServiceA:NEAR         EXTERN  CloseServiceHandle:NEAR         EXTERN  OpenSCManagerA:NEAR         EXTERN  _wsprintfA:NEAR         EXTERN  GetLastError:NEAR         EXTERN  ExitProcess:NEAR         EXTERN  lstrlenA:NEAR         EXTERN  WriteConsoleA:NEAR         EXTERN  GetStdHandle:NEAR         StartServiceA@12 = StartServiceA         OpenServiceA@12 = OpenServiceA         CloseServiceHandle@4 = CloseServiceHandle         OpenSCManagerA@12 = OpenSCManagerA         GetStdHandle@4 = GetStdHandle         WriteConsoleA@20 = WriteConsoleA         lstrlenA@4 = lstrlenA         wsprintfA = _wsprintfA         GetLastError@0 = GetLastError         ExitProcess@4 = ExitProcess ENDIF ; INCLUDELIB directives for the linker IFDEF MASM         includelib d:\masm32\lib\user32.lib         includelib d:\masm32\lib\kernel32.lib         includelib d:\masm32\lib\advapi32.lib ELSE         includelib c:\tasm32\lib\import32.lib ENDIF ;----------------------------------------------- SSTATUS STRUC         STYPE    DD ?         SSTATE   DD ?         SACCEPT  DD ?         SEXCODE  DD ?         SEXSCOD  DD ?         SCHEKPO  DD ?         SWAITHI  DD ? SSTATUS ENDS ; Data segment _DATA SEGMENT     SRS     SSTATUS <?>     H1      DD ?     H2      DD ?     ALIGN   4     SNAME1  DB "MyService", 0     ALIGN   4     LENS    DD 0     HANDL   DD 0     BUF1    DB 512 DUP(0)     ERRS    DB "Error %u ", 0 _DATA ENDS ; Code segment _TEXT SEGMENT START:         PUSH  STD OUTPUT_HANDLE         CALL  GetStdHandle@4         MOV   HANDL, EAX ;------------------------------         PUSH  SC_MANAGER_ALL_ACCESS         PUSH  0         PUSH  0         CALL  OpenSCManagerA@12         CMP   EAX, 0         JNZ   NO_ERR1         CALL  ERROB         JMP   EXI NO_ERR1:         MOV   H1, EAX ; Identifier received         PUSH  SC_MANAGER_ALL_ACCESS ; DELETE         PUSH  OFFSET SNAME1         PUSH  H1         CALL  OpenServiceA@12         CMP   EAX, 0         JNZ   NO_ERR2         CALL  ERROB         JMP   CLOSE NO_ERR2.         MOV   H2, EAX ; Service identifier received ; Send the command for starting the service         PUSH  0         PUSH  0         PUSH  H2         CALL  StartServiceA@12         CMP   EAX, 0         JNZ   CLOSE1         CALL  ERROB         JMP   CLOS1 ; Error-handling block ERROB:         CALL  GetLastError@0         PUSH  EAX         PUSH  OFFSET ERRS         PUSH  OFFSET BUF1         CALL  wsprintfA         ADD   ESP, 12         LEA   EAX, BUF1         MOV   EDI, 1         CALL  WRITE         RET CLOSE1: ; Close the service         PUSH  H2         CALL  CloseServiceHandle@4 ; Close the services database CLOSE:         PUSH  H1         CALL  CloseServiceHandle@4 EXI: ; Exit         PUSH  0         CALL  ExitProcess@4 ; Output the string (line feed in the end) ; EAX --- To the start of the string ; EDI --- With or without line feed WRITE PROC ; Get the parameter length         PUSH  EAX         PUSH  EAX         CALL  lstrlenA@4         MOV   ESI, EAX         POP   EBX         CMP   EDI, 1         JNE   NO_ENT ; Line feed in the end         MOV   BYTE PTR [EBX+ESI], 13         MOV   BYTE PTR [EBX+ESI+1], 10         MOV   BYTE PTR [EBX+ESI+2], 0         ADD   EAX, 2 NO_ENT: ; String output         PUSH  0         PUSH  OFFSET LENS         PUSH  EAX         PUSH  EBX         PUSH  HANDL         CALL  WriteConsoleA@20         RET WRITE   ENDP _TEXT ENDS END START 
image from book
 

The STSERV.EXE program presented in Listing 21.3 starts the service with the name MyService for execution. The start is carried out using the StartService API function.

To translate this program, issue the following commands for MASM32:

 ML /c /coff /DMASM stserv.asm     LINK /SUBSYSTEM:CONSOLE stserv.obj 

Issue the following commands for TASM32:

 TASM32 /ml stserv.asm     TLINK32 -ap stserv.obj 
Listing 21.4: The program that deletes the service (DELSERV.EXE)
image from book
 .586P ; Flat memory model .MODEL FLAT, stdcall ; Constants DELETE                     equ 10000h STD_OUTPUT_HANDLE          equ -11 SC_MANAGER_ALL_ACCESS      equ OF003Fh SERVICE_ALL_ACCESS         equ 0F01FFH SERVICE_WIN32_OWN_PROCESS  equ 00000010h SERVICE_DEMAND_START       equ 00000003h SERVICE_ERROR_NORMAL       equ 00000001h SERVICE_CONTROL_STOP       equ 1h ; Prototypes of external procedures IFDEF MASM         EXTERN  ControlService@12:NEAR         EXTERN  DeleteService@4:NEAR         EXTERN  OpenServiceA@12:NEAR         EXTERN  CloseServiceHandle@4:NEAR         EXTERN  OpenSCManagerA@12:NEAR         EXTERN  wsprintfA:NEAR         EXTERN  GetLastError@0:NEAR         EXTERN  ExitProcess@4:NEAR         EXTERN  lstrlenA@ 4:NEAR         EXTERN  WriteConsoleA@20:NEAR         EXTERN  GetStdHandle@4:NEAR ELSE         EXTERN  ControlService:NEAR         EXTERN  DeleteService:NEAR         EXTERN  OpenServiceA:NEAR         EXTERN  CloseServiceHandle:NEAR         EXTERN  OpenSCManagerA:NEAR         EXTERN  _wsprintfA:NEAR         EXTERN  GetLastError:NEAR         EXTERN  ExitProcess:NEAR         EXTERN  lstrlenA:NEAR         EXTERN  WriteConsoleA:NEAR         EXTERN  GetStdHandle:NEAR         ControlService@12 = ControlService         DeleteService@4 = DeleteService         OpenServiceA@12 = OpenServiceA         CloseServiceHandle@4 = CloseServiceHandle         OpenSCManagerA@12 = OpenSCManagerA         GetStdHandle@4 = GetStdHandle         WriteConsoleA@20 = WriteConsoleA         lstrlenA@4 = lstrlenA         wsprintfA = _wsprintfA         GetLastError@0 = GetLastError         StartServiceCtrlDispatcherA@4 = StartServiceCtrlDispatcherA         MessageBoxA@16 = MessageBoxA         ExitProcess@4 = ExitProcess ENDIF ; INCLUDELIB directives for the linker IFDEF MASM         includelib d:\masm32\lib\user32.lib         includelib d:\masm32\lib\kernel32.lib         includelib d:\masm32\lib\advapi32.lib ELSE         includelib c:\tasm32\lib\import32.lib ENDIF ;---------------------------------------------- SSTATUS STRUC         STYPE    DD ?         SSTATE   DD ?         SACCEPT  DD ?         SEXCODE  DD ?         SEXSCOD  DD ?         SCHEKPO  DD ?         SWAITHI  DD ? SSTATUS ENDS ; Data segment _DATA SEGMENT     SRS     SSTATUS <?>     H1      DD ?     H2      DD ?     ALIGN   4     SNAME1  DB "MyService", 0     ALIGN   4     LENS    DD 0     HANDL   DD 0     BUF1    DB 512 DUP(0)     ERRS    DB "Error %u ", 0 _DATA ENDS ; Code segment _TEXT SEGMENT START:         PUSH  STD_OUTPUT_HANDLE         CALL  GetStdHandle@4         MOV   HANDL, EAX ; Open the services database         PUSH  SC_MANAGER_ALL_ACCESS         PUSH  0         PUSH  0         CALL  OpenSCManagerA@12         CMP   EAX, 0         JNZ   Z1         CALL  ERROB         JMP   EXI Z1:         MOV   H1, EAX ; Identifier has been received; open the service         PUSH  SC_MANAGER_ALL_ACCESS ; DELETE         PUSH  OFFSET SNAME1         PUSH  H1         CALL  OpenServiceA@12         CMP   EAX, 0         JNZ   Z2         CALL  ERROB         JMP   CLOSE Z2:         MOV   H2, EAX ; Send the stop command         PUSH  OFFSET SRS         PUSH  SERVICE_CONTROL_STOP         PUSH  H2         CALL  ControlService@12         CMP   EAX, 0         JNZ   Z3         CALL  ERROB Z3: ; Delete the service         PUSH  H2         CALL  DeleteService@4         CMP   EAX, 0         JNZ   CLOSE         CALL  ERROB         JMP   CLOSE1 ; Error-handling block ERROB:         CALL  GetLastError@0         PUSH  EAX '         PUSH  OFFSET ERRS         PUSH  OFFSET BUF1         CALL  wsprintfA         ADD   ESP, 12         LEA   EAX, BUF1         MOV   EDI, 1         CALL  WRITE         RET CLOSE1: ; Close the service         PUSH  H2         CALL  CloseServiceHandle@4 CLOSE: ; Close the services database         PUSH  H1         CALL  CloseServiceHandle@4 EXI: ; Exit when all services stop         PUSH  0         CALL  ExitProcess@4 ; Output the string (line feed in the end) ; EAX --- To the start of the string ; EDI --- With or without the line feed WRITE     PROC ; Get the parameter length         PUSH  EAX         PUSH  EAX         CALL  lstrlenA@4         MOV   ESI, EAX         POP   EBX         CMP   EDI, 1         JNE   NO_ENT ; Line feed in the end         MOV   BYTE PTR [EBX+ESI], 13         MOV   BYTE PTR [EBX+ESI+1], 10         MOV   BYTE PTR [EBX+ESI+2], 0         ADD   EAX, 2 NO_ENT: ; String output         PUSH  0         PUSH  OFFSET LENS         PUSH  EAX         PUSH  EBX         PUSH  HANDL         CALL  WriteConsoleA@20         RET WRITE ENDP _TEXT ENDS END START 
image from book
 

To translate this program, issue the following commands for MASM32:

 ML /c /coff /DMASM delserv.asm     LINK /SUBSYSTEM:CONSOLE delserv.obj 

Issue the following commands for TASM32:

 TASM32 /ml delserv.asm     TLINK32 -ap delserv.obj 

This program requires some comments.

This example shows how it is possible to delete the service even if it is running. This can be achieved if the service makes provision for a reaction to the stop command. Principally, everything is self-evident. However, note that even if an error occurs when executing the ControlService API function, everything will continue to execute in due order. The point is that this command sends the stop command to the service. However, if the service is registered in the services database but is not running, then the function will return error code 1062, which means that the service has been stopped already.



The Assembly Programming Master Book
The Assembly Programming Master Book
ISBN: 8170088178
EAN: 2147483647
Year: 2004
Pages: 140
Authors: Vlad Pirogov

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net