Writing system service program

xiaoxiao2021-03-06  59

| Home >> Programming >> Win32 Assembly Programming | Win32ASM Forum | Contact webmaster |

Service program written in assembly systems author: Luo Bin Release dates: 2002-8-9

[Download the source code here]

Opening white

I want to write an article about the service, and after searching, I found a "Win32 programming service" "Win32 programming service" said that most of the things to say, so in order not to repeat labor, so Here first refer to this article to explain the principles of the service program, and then make up some content and a source code that implements the service with compilation. ============================================================================================================================================================================================================= ====================

Part 1: Reprinted "Win32 Program Design Service"

Published in: Yesky Compile: QQ New Human Original Location: http://www.chinabyte.com/20010528/181751.shtml======================= =============================================== each operation The system requires a method of performing tasks in the background, both of which is using this machine, which can continue to run, and the background task can handle various important services, including systems or users. For example, a messenger service can monitor the network, and a dialog box can be displayed when information is received another machine. An application that sends and receives faxes needs to be run at startup and constantly monitor the MODEM responsible for faxes, and see if there is any fax. A family or office security procedure for controlling a test device, it needs to query the sensor from time to time and respond to it when appropriate. All of these tasks require CPU time to perform them, but because they need the CPU time, they can be placed in the background without affecting the user. In MS-DOS, the background task is processed by the TSR (Terminate and stay resident program. These programs start via the Autoexec.bat file. In UNIX, the background task is processed by daem. In the process of starting UNIX, you can see that the operating system launches some tasks, such as timing programs (CRON), and Finger's daem, and then let the first user log in. In Windows NT, the task of the background is called a service. The service can run at each time NT started, and no matter who landed, it will run. The Windows NT service is implemented through a general executable program, which is designed to follow an internal specific protocol so that they can configure correctly with the Service Control Manager (SCM, Service Control Manager). In this article, you will learn how to create and install simple Win32 services in Windows NT. Once you know this simple service, you have to build your own service is not difficult, because all services, whether it is complicated, must contain the same basic SCM interface code. As long as it meets the requirements of SCM, it is actually the service-designed executable and general procedures do not differ. Whether it is for the programmer or system administrator, it is important to learn how NT's service is very important. The programmer doesn't have to say, because they have to create their own services, and for system administrators, they are equally important. Because the task of the background can be dangerous. The MS-DOS and Macintosh systems are a hotbed of a virus because they are inherent in terms of security, they can allow anyone or program to create a background task at any time.

The Windows NT and UNIX systems are secure because only system administrators can add the task of the background for the system, but if the system administrator joins a destructive background program, it can do whatever you want. Therefore, the system administrator wants to understand the skills and permission settings of the Windows NT service, you can avoid joining a potentially dangerous background task. Basic concept

There are two different forms of services. The drive service uses a drive protocol, allowing NT to communicate with a particular hardware. The other is the Win32 service, and the background task is implemented through the general Win32 API. The focus of this article is to talk about Win32 services because they are more common and it is easy to create. Any NT programmer can install and install your Win32 service by using a general NT SDK (or Visual C ) and can access one NT machine as an administrator. If you want to create a program that runs when Windows NT starts, and requires it to run in the system, you will use Win32 service. In NT, the service is managed by the control panel. In the control panel, you will find an icon with a service, open it, you will see the list of all Win32 services. There you can start, stop, suspend, and continue a service. After you press the start button, a dialog box will appear, you can modify the startup operation and the default account used by the service. A service can automatically run when the system is started, or it can be completely disabled. Or set to manually execute. When manual, the user can set the start-up parameters. To modify the items in the service, you need to log in as an administrator or superuser. Windows NT comes with some pre-installed tasks to handle operations such as network messenger services or use the "At" command timing execution, and distributed RPC naming. When you create your own service, you have to perform a separate installation step to insert the information of the service into the list of service management tools, including the name of the new service, the name of the execution file, and the type of startup, etc. Both will be written to the registry, so when the machine is started next time, the SCM will receive information about the new service.

Create a new service

The execution service program is also an exe file, but it must meet certain specific specifications so that you can configure correctly with the SCM. Microsoft is well designed in the process of function calls, you must follow these processes, otherwise your service can't work. Specific provisions are listed below. You can find the following functions in the Win32 programmer's reference guide, these information in the SDK Win32 online help or Visual C :. The service code must have a general main or winmain function. This function should immediately call the StartServiceCrtLDispatcher function. By calling this function, you can get the SCM to get a pointer to the servicemain function, you can call it when SCM is to start the service. When the SCM is to start the service, the serviceMain function will be called. For example, if the administrator presses the button in the Service Manager, SCM will execute the servicemain function in a separate thread. ServiceMain should call the RegisterServiceCtrlHandler function so that you can register a Handler function so that SCM controls the service. The name of the Handler function can be arbitrary, but it will be listed in the document under Handler. The RegisterServiceCtrlHandler function returns a handle that can be performed by this handle when the service needs to send statly information to the SCM. The .serviceMain function must also start the thread that actually works actually in this service. The servicemain function should not be returned before the service is stopped. When it returns, the service has stopped. The .Handler function contains a Switch statement to analyze the request from SCM. By default, SCM can send any of the following control constants: SERVICE_CONTROL_STOP - To service stops SERVICE_CONTROL_PAUSE - to serve the suspended SERVICE_CONTROL_CONTINUE - To service continues SERVICE_CONTROL_INTERROGATE - to be served immediately report its status SERVICE_CONTROL_SHUTDOWN - told the service will shut down can also create custom The constant (value between 128 and 255) and sent to the service via SCM. If you created EXE includes the above, servicemain, and handler functions, as well as thread functions that perform service own tasks, then your service program is complete. The following graph summarizes these different functions and SCM interactions:

In the final list of this article, there are several programs list, where the list one shows us that one may be the simplest service. This service only issues a "beep" ring. In the default, it rang every two seconds. You can modify the interval of the vocal by starting parameters. This service is quite complete, it can properly respond to each control signal from the SCM. Therefore, this program can serve as a good template you create yourself. The main function registers the ServiceMain function by calling StartServiceCtrldispatcher. The registered operation uses an array of service_table_entry structures. In this example, the program only contains a service, so there will be only one item in the table. However, for an EXE file, you can create several tasks so that there will be several items in the table to identify different servicemain functions. Before calling StartServiceCtrldispatcher, you can put the initialized code in the main function, but these code must be completed within 30 seconds, otherwise the SCM will think that certain places have error and terminate service. The servicemain function will be called when the service is automatically or manually started. The servicemain function will contain the following steps: 1. It immediately calls the registerServiceCtrlHandler to register the Handler function, which is the Handler function 2 of the service as the SCM. Then it will call the sendstatustoscm function to report the current process to the SCM. The fourth parameter is a "Click Count" value, and its value increases when the program is updated each time. SCMs and other programs can know the process of initialization according to the value of Click Count. The final parameter is "Wait Hint", which is used to tell SCM before the next update of Click Count, it needs to wait for the time (in milliseconds). 3. ServiceMain then creates a thing, the event is used at the bottom of the function, allowing it to run until the SCM issues a STOP request. 4. Next, ServiceMain checks the start-up parameters. The parameters can be transferred through the startup parameters in the service management tool when the user is manually started. These parameters enters the servicemain function in an argument in the form of an Argv. 5. If your service needs to handle other initialization tasks, they should be placed in this step and before invoing INITSERVICE. 6. The servicemain function then calls the INITSERVICE function, which will start the thread and do the truly work of the service. If the call is successful, SverviceMain will notify the SCM service has been successfully started. 7. ServiceMain will call WaitForsingleObject to wait for the TerminateEvent event object to be set. This object is set through the Handler function, once it is set, ServiceMain will call the termination function to do the clear work, then return and stop the service. You can see from above, there is not much flexible place in this function. In addition to step 5, you must press the task mentioned above, otherwise the service will not start correctly. The termination function clears all open handles and sends a state information to the SCM, telling it that the service is now stopped. When SCM is paused, continuing, queries, or stopping the service, it will call the Handler function. To stop the service, Handler sets TerminateEvent, which will cause servicemain to terminate and return in a stand-alone thread.

Once ServiceMain returns, the service stops. The SendStatustoscm function is responsible for sending the current state of the service to the SCM. When you need to start the service thread, ServiceMain calls the INITSERVICE function. This function calls CreateTHRead to create a new thread for the service. The ServiceThread function contains the work that the service really wants. In this example, the thread contains an unlimited loop to emit a sound in a predefined time interval. When you create your own service, you can put any code in this thread, call the Win32 function or your own function. Installation and removal service

In order to use the sound service mentioned above, you must install it. Installation allows SCM to know this service and let SCM add it to the list of service in the control panel. The code for forms two shows how to install a service. Form 2 first opens a connection to SCM through the OpenScManager function. In the invocation of OpenScManager, you must specify what you have to do so that SCM can verify this behavior. If the account you log in does not have enough permissions, the call will return null. CreateService's call is truly used to load new service. It uses OpenScManager to return to the EXE file in the SCM's pointer, name, tag, and command line, and some standard parameter values. Using Service_WIN32_OWN_PROCESS indicates that the service's EXE file contains only one service, and service_demand_start indicates that the service is manual instead of automatic start. A typical format using the command line installer is as follows: install beepservice "beeper" c: /winnt/beep.exe first parameter is the service name used inside the SCM. This name is also used in later removal services. The second parameter is an identifier, namely the name displayed in service management. The third parameter indicates the path to the execution file of the service. After you install the service, you can start it in the service management of the control panel. If it is wrong, you can find the meaning of the error code in the online document of the Win32 API. To remove the service, you have to follow the steps 3. It first opens a connection to the SCM and then use the OpenService function to open a connection with the service. Listing 3 is then queried to see if it is now stopped. If not, it will stop it. DELETSERVICE is used to remove service from the control panel, and the typical format of removal operation is as follows: Remove Beepservice is required, you can also reinstall the service immediately.

in conclusion

Services is a very important part of Windows NT because it allows you to expand your operating system. Using the code of the list 1 as a template, you will find that it is very simple to build a new service. List 1 Implementation may be the code of the simplest NT service // ******************************************************* **********************************

// from the book "Win32 System Services: The Heart Of Windows NT"

// by Marshall Brain

// Published by PRENTICE HALL

File: //

// this Code Implements The SimpleSt Possible Service.

// IT Beeps Every 2 Seconds, or at a user specified interval.

File: // ************************************************************** ******************

// beepserv.cpp

#include

#include

#include

#include

#define default_beep_delay 2000 // Global Variables

// the name of the service

Char * service_name = "beepservice";

// Event Used to Hold ServiceMain from Completion

Handle TerminateEvent = NULL;

// Handle Used to Communicate Status Info with

// The scm. Created by RegisterServiceCtrlHandler

Service_status_handle service .tatushandle;

// The beep interval in ms.

INT beepdelay = default_beep_delay;

// Flags Holding Current State of Service

Bool pauseservice = false;

Bool RunningService = false;

// Thread for the Actual Work

Handle threadhandle = 0;

Void Errorhandler (Char * S, DWORD ERR)

{

Cout << s << endl;

Cout << "Error Number:" << Err << Endl;

EXITPROCESS (ERR);

}

// this function consolidates the Activities of

// Updating the service status with

// setServiceStatus

Bool SendStatustoscm (DWORD DWCURRENTSTATATE,

DWORD dwwin32exitcode,

DWORD DWSERVICESPECICEXITCODE,

DWORD DWCHECKPOINT,

DWORD DWWAITHINT)

{

BOOL SUCCESS;

Service_status serviceArstatus;

// Fill in all of the service_status fields

ServiceStatus.dwserviceTyPE = service_win32_oen_process;

ServiceStatus.dwcurrentState = dwcurrentState;

// if in the process of doing something, the accept

// no Control Events, Else Accept Anything

IF (dwcurrentState == service_start_pending)

ServiceStatus.dwcontrolsAccepted = 0;

Else

ServicesTatus.dwcontrolsAccepted = service_accept_stop |

Service_accept_pause_continue |

Service_accept_shutdown;

// if a specific exit code is defined, set up

// the win32 exit code process

IF (dwserviceSpecifiXitcode == 0)

ServicesTatus.dwwin32exitcode = dwwin32exitcode;

Else

ServicesTatus.dwwin32exitcode = error_service_specific_error; serviceatus.dwservicespecificeXitcode = dwserviceXitcodeXitcode;

ServiceStatus.dwcheckpoint = dwcheckpoint;

ServiceStatus.dwwaithint = dwwaithint;

// Pass the status record to the scm

Success = setServiceStatus (ServiceStatusHandle, & ServiceStatus);

RETURN SUCCESS;

}

DWORD ServiceThread (LPDWORD PARAM)

{

While (1)

{

BEEP (200, 200);

Sleep (beepdelay);

}

Return 0;

}

// Initializes the service by starting its thread

BOOL INITSERVICE ()

{

DWORD ID;

// Start the service's thread

ThreadHandle = CreateThread (0, 0, (lpthread_start_routine) ServicesRead, 0, 0, & ID);

IF (threadhandle == 0)

Return False;

Else

{

RunningService = true;

Return True;

}

}

// Dispatches Events Received from the SCM

Void Handler (DWORD Controlcode)

{

DWORD CURRENTSTATE = 0;

BOOL SUCCESS;

Switch (Controlcode)

{

// there is no start option Because

// Servicemain Gets Called on A Start

// stop the service

Case Service_Control_Stop:

// Tell The SCM What's Happening

Success = sendStatuscm (Service_stop_pending, NO_ERROR, 0, 1, 5000);

RunningService = false;

// set the Event this is all for servicemain

// SO That Servicemain Can Return

SetEvent (TerminateEvent);

Return;

// Pause the service

Case service_control_pause:

IF (RunningService &&! Pauseservice)

{

// Tell The SCM What's Happening

Success = sendstatuscm (service_pause_pending,

NO_ERROR, 0, 1, 1000);

Pauseservice = true;

Suspendthread (threadhandle);

CurrentState = service_paused;

}

Break;

// Resume from a painse

Case Service_Control_Continue:

IF (RunningService && Pauseservice)

{

// Tell the SCM What's HappeningsUccess = sendstatustoscm (Service_Continue_pending,

NO_ERROR, 0, 1, 1000);

Pauseservice = false;

ResumeThread (ThreadHandle);

CurrentState = service_running;

}

Break;

// Update Current Status

Case Service_Control_Interrogate:

// it will fall to bottom and send status

Break;

// do nothing in a shutdown. Could do cleanup

// Here But It Must Be Very Quick.

Case Service_Control_shutdown:

Return;

DEFAULT:

Break;

}

SendStatustoscm (CurrentState, NO_ERROR, 0, 0, 0);

}

// Handle An Error from ServiceMain by Cleaning Up

// and Telling SCM That The Service Didn't Start.

Void Terminate (DWORD ERROR)

{

// if TerminateEvent Has Been CREATED, Close IT.

IF (TerminateEvent) CloseHandle (TERMINATEEVENT);

// send a message to the scm to tell about stopage

IF (ServiceStatushandle)

SendStatustOScm (Service_stopped, Error, 0, 0, 0);

// if The Thread Has Started, Kill IT OFF

IF (threadHandle) CloseHandle (ThreadHandle);

// Do Not Need to Close ServiceStatushandle

}

// Servicemain Is Called when SCM Wants To

// Start The Service .hen It Returns, The Service

// HAS Stopped. it therefore Waits on An Event

// just before the end of the function, and

// That Event Gets set by IT is time to stop.

// it also returns on any error Because the

// service cannot start if there is an eror.

Void ServiceMain (DWORD ARGC, LPTSTSTSTSTSTSTSTSTSTSTSTSTSTSTSTSTSTSTSTSTSTSTS

{

BOOL SUCCESS;

// Immediately Call Registration function

ServiceStatusHandle =

RegisterServiceCtrlHandler

Service_name, (lphandler_function);

IF (! serviceestatushandle) {terminate (getLastError ()); return;}

// Notify SCM of Progress

Success = sendstatustoscm (service_start_pending,

NO_ERROR, 0, 1, 5000);

IF (! success) {terminate (getLastError ()); return;} // create the terminal

TerminateEvent = CreateEvent (0, True, False, 0);

IF (! TerminateEvent) {terminate (getLastError ()); return;}

// Notify SCM of Progress

Success = sendstatustoscm (service_start_pending,

NO_ERROR, 0, 2, 1000);

IF (! "{terminate (getLastError ()); return;

// Check for Startup params

IF (argc == 2)

{

INT TEMP = ATOI (Argv [1]);

IF (Temp <1000)

Beepdelay = default_beep_delay;

Else

Beepdelay = temp;

}

// Notify SCM of Progress

Success = sendstatustoscm (service_start_pending,

NO_ERROR, 0, 3, 5000);

IF (! "{terminate (getLastError ()); return;

// Start the service itself

Success = INITSERVICE ();

IF (! "{terminate (getLastError ()); return;

// The service is now running.

// Notify SCM of Progress

Success = sendstatustoscm (service_running,

NO_ERROR, 0, 0, 0);

IF (! "{terminate (getLastError ()); return;

// Wait for Stop Signal, and Then Terminate

WaitForsingleObject (TerminateEvent, Infinite);

Terminate (0);

}

Void main (void)

{

Service_table_entry serviceable [] =

{

{Service_name,

(Lpservice_main_function) servicemain},

{Null, null}

}

BOOL SUCCESS;

// register with the SCM

Success =

StartServiceCtrldispatcher (ServiceTable);

IF (! SUCCESS)

Errorhandler ("in StartServiceCtrldispatcher",

GetLastError ());

}

Listing 2

Install the NT service code

File: // ************************************************************** ******************

// from the book "Win32 System Services: The Heart Of Windows NT"

// by Marshall Brain

// Published by PRENTICE HALL

File: //

// This Code Installs a service.

File: // ************************************************************** **************** // install.cpp

#include

#include

Void Errorhandler (Char * S, DWORD ERR)

{

Cout << s << endl;

Cout << "Error Number:" << Err << Endl;

EXITPROCESS (ERR);

}

Void main (int Argc, char * argv [])

{

SC_Handle NewService, SCM

IF (argc! = 4)

{

Cout << "USAGE: / N";

COUT << "install service_name /

Service_Label Executable / N ";

Cout << "service_name is the /

Name Used INTERLY BY The SCM / N ";

Cout << "service_label is the /

Name That APPEARS IN The Services Applet / N ";

Cout << "(for multiple /

Words, Put them in double quotes / n ";

COUT << "Executable is the /

Full Path to the EXE / N / N ";

Return;

}

// Open a connection to the SCM

SCM = OpenScManager (0, 0, SC_Manager_create_service);

IF (! SCM) Errorhandler ("in OpenscManager",

GetLastError ());

// install the new service

NewService = CREATSERVICE

SCM, Argv [1], // EG "beep_srv"

Argv [2], // EG "beep service"

Service_all_access, service_win32_oen_process,

Service_demand_start, service_error_normal,

Argv [3], // EG "c: /winnt/xxx.exe"

0, 0, 0, 0, 0);

IF (! newservice) Errorhandler ("In CreateService",

GetLastError ());

Else Cout << "Service Installed / N";

// Clean Up

ClosESERVICEHANDE (NewService);

ClosEServiceHandle (SCM);

}

Listing 3

Remove the code of the NT service

File: // ************************************************************** ******************

// from the book "Win32 System Services: The Heart Of Windows NT"

// by Marshall Brain

// Published by PRENTICE HALL

File: //

// This Code Removes a Service from the service applet in the // control panel.

File: // ************************************************************** ******************

// remove.cpp

#include

#include

Void Errorhandler (Char * S, DWORD ERR)

{

Cout << s << endl;

Cout << "Error Number:" << Err << Endl;

EXITPROCESS (ERR);

}

Void main (int Argc, char * argv [])

{

SC_Handle Service, SCM;

BOOL SUCCESS;

Service_status status;

IF (argc! = 2)

{

Cout << "USAGE: / N Remove Service_name / N";

Return;

}

// Open a connection to the SCM

SCM = OpenScManager (0, 0, SC_Manager_create_service);

IF (! SCM) Errorhandler ("in OpenscManager",

GetLastError ());

// Get the service's handle

Service = OpenService (SCM, Argv [1],

Service_all_access | delete);

IF (! service) Errorhandler ("in OpenService",

GetLastError ());

// stop the service if nesery

Success = queryServiceStatus (Service, & status);

IF (! Success) Errorhandler ("in QueryServiceStatus",

GetLastError ());

IF (status.dwcurrentstate! = service_stopped)

{

COUT << "Stopping Service ... / N";

Success = ControlService (Service,

Service_Control_Stop, & status

IF (! Success) Errorhandler ("in ControlService",

GetLastError ());

}

// Remove the service

Success = deleteService (Service);

IF (Success) cout << "service remoded / n";

Else Errorhandler ("in deleteService",

GetLastError ());

// Clean Up

ClosESERVICEHANDE (Service);

ClosEServiceHandle (SCM);

}

============================================================================================================================================================================================================= ==================== Part 2: System services to implement system services with Win32

By: Luo Yunbin, after the article above, everyone should have a preliminary understanding, but pay attention to the name of the API name and program mentioned in the article, such as CreateService is an API, while ServiceMain It is the name of a subroutine in the program, don't use the subroutine named system API to use :) In this complement, I will return the steps and use of the API function name and use of various functions. And provide an assembly program example to provide you with reference, you can also download the entire source package and modify usage. In general, the entire service program system consists of two separate procedures: the service program and service control program, after the above introduction, everyone must understand which parts should be composed of these two procedures:

Server structure

The service program is part of the service functionality, which consists of relatively independent three parts: 1. Program portal -> Call StartServiceCtrLDispatcher (Register Service Main Program) 2. Service Main Program (Call by SCM) -> Call RegisterServiceCtrlHandler (Register Control Handler) -> Call the At SetServiceStatus Settings Service Correct Status -> The function code of the execution service -> When you need to end the service, return. 3. Control the Handler -> Set the internal flag to control the code towards the code in the main program in Part 2, and call the status of the SetServiceStatus update service. It can be seen that the API that the service program must use only STARTSERVICTRLDISPATCHER, RegisterServiceCtrlHandler, and SetServiceStatus, and most of the other code is the functional module that performs itself. Here is a simple example of a service program, which is implemented for a function of making a speaker once a second. The following source code is the service.asm program: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>

; Windows NT Server Template

: By Luo Yunbin, http://asm.yeah.net

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Suppose program Ver 1.0

;

; 2002.06.20 ----- 1st Edition

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

.386

.Model flat, stdcall

Option CaseMAP: NONE

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

Include file definition

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

INCLUDE Windows.inc

INCLUDE User32.inc

INCLUDELIB USER32.LIB

INCLUDE KERNEL32.INC

IncludeLib kernel32.lib

Include advapi32.inc

IncludedElib Advapi32.lib

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

Data segment

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>

STSS Service_Status <>; service status

HSS DD?; service status handle

DWOPTION DD?

F_stop equ 0001h; stop service

Include

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

Code segment

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

.code

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

Service control program

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

_Prochandler Proc_dwcontrol

Pushhad

Mov Eax, _dwcontrol

.IF EAX == Service_Control_Stop

OR dwoption, f_stop

Mov stss.dwcurrentstate, service_stopped

Invoke SetServiceStatus, HSS, Addr Stss

.ELSEIF EAX == Service_Control_INTERROGATEINVOKE SETSERVICESTATUS, HSS, AddR Stss

.endif

Popad

RET

_PROCHANDLER ENDP

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

Service master program

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

_ServiceMain Proc_dwargc, _lpszargv

Pushhad

Invoke RegisterServiceCtrlhandler, AddR SzServiceName, Offset _Prochandler

MOV HSS, EAX

Mov stss.dwserviceType, service_win32_oen_process or service_interactive_process

Mov stss.dwcurrentstate, service_start_pending

Mov stss.dwcontrolsaccepted, service_accept_stop

Mov stss.dwwin32exitcode, no_error

Invoke SetServiceStatus, HSS, Addr Stss

*********************************************************** *******************

If the initialization code is more, you need to set the status as Pending, etc.

; Set to Running. (Add initialization code here)

*********************************************************** *******************

Mov stss.dwcurrentstate, service_running

Invoke SetServiceStatus, HSS, Addr Stss

*********************************************************** *******************

; Specific implementation code

Here is every 1 second to make a speaker

*********************************************************** *******************

.repeat

Invoke MessageBeep, -1

Invoke Sleep, 1000

.until dwoption & f_stop

Popad

RET

_ServiceMain ENDP

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

_WinMain Proc

Local @stste [2]: Service_Table_ENETRY

Invoke RTLZERMEMORY, AddR @ Stste, SizeOf @stste

Mov @stste [0] .lpServiceName, Offset SzServiceName

Mov @stste [0] .lpserviceproc, offset _ServiceMain

Invoke StartServiceCtrldispatcher, Addr @stste

RET

_WinMain ENDP

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

Start:

Invoke _winmain

Invoke EXITPROCESS, NULL

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

End Start

Here is the definition file definition file definition file define.inc, this file is already in front of the include statement to include:

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Folding text information

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

.const

SZSERVICEEXE DB 'Service.exe', 0; Defining the EXE file name of the running service here

SZServiceName DB 'ServiceTemplate', 0; Defined the name of the service here

SZDisPlayName DB 'Service Template for Test', 0; defined the name of the service display here

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

It should be noted that there is no flexibility of the code of the service program, it must be implemented in this step, otherwise Windows does not think it is a service program, in addition, it is necessary to add: 1. StartServiceCtrldispatcher After the function is called, it is not immediately returned immediately. At this time, the system will call the service master program (above the _servicemain subroutine), only when the service master returns, the function will return, then the main program continues to execute and execute EXITPROCESS Terminate execution. 2. From 1st point, you can find that in the service program, the exit of the service main program means that the service is based on the service, so if the program creates multiple threads, the main program is still after the thread is created. Need to wait here, otherwise the subscriber will return after the service process, how can these threads continue?

Service control program structure

Ok, after a service program, you need to properly install the service to make it run. This job is the service control program. In general, the structure of the service control program does not have a special requirement, it is just a general Win32 executable, you can use the following API in the service control program to perform various controls, please check the Win32 API manual for specific syntax: 1. OpenScManager must be used before performing and service-related operations. To contact the Service Manager, get a handle HSCM of a service manager from this API. 2. Before operating a specific service, you need to use OpenService to open the service, and get the handle of the service, you can use this handle to control the service (of course, this step is required when installing the service. Not there, how do you open?) 3. Installation service: Using the CreateService function, this function registers the executable of the service program in the SCM. Note: "Register" does not mean execution, it is just in the SCM database Registering a data containing information such as executable file name, startup method, service name, after executing this function, you can see this service in the service list in the service list, because this is just "Register", so the system does not check the legality of the executable file, that is, even if you register an unsatisfactory executable, the registration operation will still succeed, but this will fail when you start the service. After registering once, the information in the SCM database will be saved automatically, so "Register" is a one-time process, and it does not need to be registered once every time the service is started. 4. Start service: After the service is installed, you can start the service with the StartService function, and the system is really based on the registered file name. 5. Delete Service: Deleting Service is the reverse process of the installation service, that is, delete the service program in the SCM database, deleting the service using the deleteService function. 6. Control of service: The service is paused, stop and other work can be done by the service control function ControlService, and it is only specified by different parameters. 7. The query of the service status can be done by the QueryServiceStatus function. 8. Close of the handle: The handle (including the SCM handle and service handle) related to the above operation, you need to shut down with the ClosServiceHandle function after no longer use. Several subprograms below illustrate the operation method of installing services, deleting services, launching services, and stop services, and the HSCM used in the subroutine has first called the OpenScManager function otherwhere. For more specific source code, check the Control.asm file in the source package included in the article. ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - INSTALLSERVICE PROC

Local @ hservice, @ dwreturn

Mov @ dwreturn, false

*********************************************************** *******************

Create service

*********************************************************** *******************

Invoke CreateService, HSCM, AddR SzServiceName, AddR SzdisplayName, /

Service_all_access, service_win32_oen_process or service_interactive_process, /

Service_auto_start, service_error_normal, addr szservicefile, /

NULL, NULL, NULL, NULL, NULL

.IF! EAX

Invoke getLastError

.IF eax == error_dup_name || Eax == Error_Service_exists

Mov @ dwreturn, TRUE

.lse

Mov @ dwreturn, false

.endif

JMP @f

.endif

Mov @ hservice, EAX

Mov @ dwreturn, TRUE

*********************************************************** *******************

Invoke ClosESERVICEHANDLE, @ hservice

@@:

Mov Eax, @ dwreturn

RET

_INSTALLSERVICE ENDP

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

Delete service

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

_DELETSERVICE PROC

Local @ hservice, @ dwreturnlocal @ststatus: service_status

Mov @ dwreturn, false

*********************************************************** *******************

Open service

*********************************************************** *******************

Invoke OpenService, HSCM, Addr SzServiceName, Service_all_Access

.IF! EAX

JMP @f

.endif

Mov @ hservice, EAX

*********************************************************** *******************

; Stop service and delete services

*********************************************************** *******************

Call_stopservice

Invoke deleteService, @ hservice

.if EAX

Mov @ dwreturn, TRUE

.endif

Invoke ClosESERVICEHANDLE, @ hservice

@@:

Mov Eax, @ dwreturn

RET

_DeleteService Endp

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

Start service

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

_StartService Proc

Local @HService

Invoke OpenService, HSCM, Addr SzServiceName, Service_Start

.if EAX

Mov @ hservice, EAX

Invoke StartService, @ hservice, 0, NULL

.if EAX

Mov Eax, True

.lse

Mov Eax, False

.endif

Push EAX

Invoke ClosESERVICEHANDLE, @ hservice

POP EAX

.lse

Mov Eax, False

.endif

RET

_StartService Endp

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

_StopService Proc

Local @HService

Local @ststatus: Service_Status

Invoke OpenService, HSCM, Addr SzServiceName, Service_all_Access

.if EAX

Mov @ hservice, EAX

Invoke QueryServiceStatus, @ hservice, addr @ststatus

Invoke ControlService, @ hservice, service_control_stop, addr @ststatus

.if EAX

Mov Eax, True

.lse

Mov Eax, False

.endif

Push EAX

Invoke ClosESERVICEHANDLE, @ hservice

POP EAX

.lse

Mov Eax, False

.endif

RET

_StopService Endp

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>

Merge service procedures and service control procedures

In the above example, separate the service programs and service control programs to better describe the difference from the concept, but in actual applications, there are still many programs to combine two parts in the same executable. During this, the two parts are only physically placed in the same exe file, and the structure is still unstoppable, completely independent. Although the implementation of the two parts is completely different, but as long as the entrance to the program, the code is executed in a different part, and it is still feasible in a file, and the key is that the distingurant is executed. When executed as a service program or is executed as a service control program, the common methods are: 1. Use the command line parameters to distinguish when using the CreateService function to submit a file name string when you submit a file name, you can follow the parameters. This allows the program entry to acquire the command line parameters with the getcommandline function, and detect a specific parameter, follow the service mode, or run according to the service control program. 2. Use the running path to distinguish it when some virus programs are initialized, and the copy is copied into the Windows directory and register this copy as a service, so it is time to detect the current path is the Windows directory. [Close this window]

Copyright © 1998-2002 By Luo Yunbin, All Rights Reserved, all articles copyrights belong to their authors, such as reprint, you must note the author!