---- There is a very important difference between Windows NT and Windows 9x, that is, Windows NT provides many powerful functions and services ). These services can be started automatically with the startup of NT, and can be started by the user through the control panel, and can be used by Win32 applications Program Start and Stop. These services can be executed even if no user logs on to the system. Many FTP, WWW servers, and databases exist in the form of services on the NT, thus achieving unattended. Even the latest "hacker" program Back Orifice 2000 is used as a service to hide on NT. Due to the complexity of Service programming, many developers tend to be discouraged from developing their own services. In view of this, we will construct a brand new service from start to end. Readers only need to add their own Code You can easily own your own service. Before writing a service, we will introduce several important functions:
---- 1. SC _handle openscmanager (maid, lpdatabasename, DWORD dwdesiredaccess)
---- The openscmanager function opens the Service Control Manager Database on the specified computer. The parameter lpmachinename specifies the computer name. If it is null, it is specified as the local machine. Lpdatabasename is the name of the Service Control Manager database to be opened. It is null by default. Dwdesiredaccess specifies the operation permission, which can be one of the following values:
---- SC _manager_all_access // All Permissions ---- SC _manager_connect // you can connect to the Service Control Manager database. ---- SC _manager_create_service // you can create a service object and add it to the database. ---- SC _manager_enumerate_service // You can enumerate the services in the database. ---- SC _manager_lock // you can lock the database. ---- SC _manager_query_lock_status // You can query the database blocking information. ---- If the function is successfully executed, a handle pointing to the Service Control Manager database is returned. If the function fails, null is returned. Note: winnt manages all services through a database named Service Control Manager database. Therefore, you should open this database for any operations on the service.
---- 2. SC _handle createservice (SC _handle hscmanager,
Lptstr lpservicename, Lpctstr lpdisplayname, DWORD dwdesiredaccess, DWORD dwservicetype, DWORD dwstarttype, DWORD dwerrorcontrol, Lpctstr lpbinarypathname, Lpctstr lploadordergroup, Lpdword lpdwtagid, Lptstr lpdependencies, Lpctstr lpservicestartname, Lpctstr lppassword)
---- The creatservice function generates a new service. The hscmanager parameter is the handle pointing to the Service Control Manager Database, which is returned by openscmanager. Lpservicename is the service name, lpdisplayname is the service display name, dwdesiredaccess is the access permission, and service_all_access is used in this program. Wservicetype, indicating the service type. service_win32_own_process | service_interactive_process is used in this program. Dwstarttype is the service startup mode. This program is self-started, that is, dwstarttype is equal to service_auto_start. Dwerrorcontrol indicates the action taken when an error occurs during service startup. In this program, service_error_ignore is used, that is, an error occurs suddenly. You can change it to another one. Lpbinarypathname indicates the path name of the service ontology program. The remaining five parameters can be set to null. If the function call is successful, the new Service handle is returned. If the function fails, null is returned. This function corresponds to deleteservice (hservice), which deletes the specified service. ---- 3. SC _handle openservice (SC _handle hscmanager, lpctstr lpservicename, DWORD dwdesiredaccess)
---- Openservice function to open the specified service. The hscmanager parameter is the handle pointing to the Service Control Manager Database, which is returned by openscmanager. Lpservicename is the name of the service, and dwdesiredaccess is the access permission, which has many optional values. Readers can refer to the SDK help. If the function is successfully called, return the opened Service handle, and if the function fails, return null.
---- 4. bool startservice (SC _handle hservice, DWORD dwnumserviceargs, lpctstr * lpserviceargvectors)
---- Startservice function starts the specified service. The hservice parameter is the handle pointing to the service, which is returned by openservice. Dwnumservicear indicates the number of parameters required to start the service. Lpszserviceargs is the parameter required for starting the service. If the function is successfully executed, true is returned. If the function fails, false is returned.
---- 5. bool controlservice (SC _handle hservice DWORD dwcontrol, lpservice_status lpservicestatus)
---- The service program does not have a special stop function, but uses the controlservice function to control the pause, continue, stop, and other operations of the Service. The dwcontrol parameter specifies the following control commands:
Service_control_stop // stop the service Service_control_pause // pause the service Service_control_continue // continue service Service_control_interrogate // query the service status Service_control_shutdown // invalidate the controlservice call
---- The lpservicestatus parameter is a pointer to service_status. Service_status is an important structure. It contains various service information, such as the current status and the control commands that can be accepted. ---- 6. bool queryservicestatus (SC _handle hservice, lpservice_status lpservicestatus)
---- The queryservicestatus function is relatively simple. It queries and returns the status of the current service.
---- Compiling a service usually requires two programs. One is the service ontology and the other is the control program used to control the service. Generally, the service ontology is a console program, while the control program is a common Win32 application (of course, you can start and stop the service through the control panel without using the control program, but cannot be added or deleted .)
---- First, let's compile the service ontology. For the service ontology, it generally consists of the following three parts: Main (), servicemain (), and handler (). below is the main () Source code (Note: Due to the length, most programs do not handle errors, so you can add them as needed)
Int main (INT argc, char ** argv) { Service_table_entry ste [2]; // A service process can have multiple threads. This is the entry table of each thread. Ste [0]. lpservicename = "W. Z. Service"; // thread name Ste [0]. lpserviceproc = servicemain; // Thread entry address Ste [1]. lpservicename = NULL; // The Last One must be null. Ste [1]. lpserviceproc = NULL; Startservicectrldispatcher (STE ); Return 0; }
---- Main () is the main thread of the service. When servie Control Manager starts a service process, it always waits for the service to call the startservicectrldispatcher () function. The main () as the main thread of this process should call startservicectrldispatcher () as soon as possible after the program starts (). Startservicectrldispatcher () does not return immediately after it is called. It connects the main thread of this service to Service Control Manager, in this way, the Service Control Manager sends control commands such as start and stop to the main thread. The main thread then plays the role of a command forwarder. It can also call handle () to handle control requirements such as stop and continue, or generate a new thread to execute servicemain. Startservicectrldispatcher () is returned only when the entire service ends. ---- Servicemain () is the real entry point of the service and must be correctly defined in main. The two parameters of servicemain () are passed by startservice. The following is the source code of servicemain:
Void winapi servicemain (DWORD dwargc, lptstr * lpszargv) { SSH = registerservicectrlhandler ("W. Z. Service", Handler ); SS. dwservicetype = service_win32_own_process | service_interactive_process; SS. dwcurrentstate = service_start_pending; // If the user program has more code (the execution time exceeds 1 second), set it to service_start_pending. After the user program is completed, set it to service_running. SS. dwcontrolsaccepted = service_accept _ Stop; // indicates that the command currently accepted by the service is stop. SS. dwwin32exitcode = no_error; SS. dwcheckpoint = 0; SS. dwwaithint = 0; Setservicestatus (SSH, & SS ); // The service status in the database must be updated at any time.
Mycode (); // put your own code here
SS. dwservicetype = service_win32_own _ Process | service_interactive_process; SS. dwcurrentstate = service_running; SS. dwcontrolsaccepted = service_accept_stop; SS. dwwin32exitcode = no_error; SS. dwcheckpoint = 0; SS. dwwaithint = 0; Setservicestatus (SSH, & SS );
Mycode (); // you can add your own code here. }
It should be called immediately in servicemain () Registerservicectrlhandler () registers a handler Process the service control requirements of the control program or control panel.
Handler () is called by the forwarder to handle the request, The following is the source code of handler: Void winapi handler (DWORD opcode) { Switch (opcode) { Case service_control_stop: // stop the service Mycode (); // put your own code here SS. dwwin32exitcode = 0; SS. dwcurrentstate = service_stopped; // Set the current status of the Service to stop SS. dwcheckpoint = 0; SS. dwwaithint = 0; Setservicestatus (SSH, & SS ); /The service status in the database must be updated at any time Break; Case service_control_interrogate: Setservicestatus (SSH, & SS ); // The service status in the database must be updated at any time Break; } }
---- Well, the service ontology program has been basically completed. Let's take a look at the service control program: ---- The control program is a standard window program, which has four buttons: Create service, delete service, start, and stop, which are used to generate, delete, start, and stop services respectively. Below are some of their source code:
1. Generate Service Void _ fastcall tform1: createbtnclick (tobject * sender) { SCM = openscmanager (null, null, SC _manager_create_service ); If (SCM! = NULL) { SVC = createservice (SCM, "W. Z. Service", "W. Z. Service", // service name Service_all_access, Service_win32_own_process | service_interactive_process, Service_auto_start, // start automatically Service_error_ignore, "C: \ ntservice.exe", // service ontology program path, must match the specific location Null, null, null ); If (SVC! = NULL) Closeservicehandle (SVC ); Closeservicehandle (SCM ); } }
2. delete a service Void _ fastcall tform1: deletebtnclick (tobject * sender) { SCM = openscmanager (null, null, SC _manager_connect ); If (SCM! = NULL) { SVC = openservice (SCM, "W. Z. Service", service_all_access ); If (SVC! = NULL) { Queryservicestatus (SVC, & servicestatus ); If (servicestatus. dwcurrentstate = service_running) // stop the service before deletion. Controlservice (SVC, service_control_stop, & servicestatus ); Deleteservice (SVC ); Closeservicehandle (SVC); // after the service is deleted, it is best to call closeservicehandle again } // To immediately remove this entry from the database. Closeservicehandle (SCM ); } }
3. Start Service Void _ fastcall tform1: startbtnclick (tobject * sender) { SCM = openscmanager (null, null, SC _manager_connect ); If (SCM! = NULL) { SVC = openservice (SCM, "W. Z. Service", service_start ); If (SVC! = NULL) { Startservice (SVC, 0, null); // start service Closeservicehandle (SVC ); } Closeservicehandle (SCM ); } }
4. Stop the service Void _ fastcall tform1: stopbtnclick (tobject * sender) { SCM = openscmanager (null, null, SC _manager_all_access ); If (SCM! = NULL) { SVC = openservice (SCM, "W. Z. Service", service_stop | service_query_status ); If (SVC! = NULL) { Queryservicestatus (SVC, & servicestatus ); If (servicestatus. dwcurrentstate = service_running) Controlservice (SVC, service_control_stop, & servicestatus ); Closeservicehandle (SVC ); } Closeservicehandle (SCM ); } } |
|