---- Windows NT has a very important difference with Windows 9x, that is, Windows NT provides a lot of powerful service. These services can start from the start of NT, or allow users to start by the control panel, and can be stopped by the Win32 application. Even without the user login system, these services can also be executed. Many ftps, WWW servers and databases are in NT in the form of service, thereby achieving unattended. Even the latest version of the "hacker" program Back OrificE 2000 is also hidden on the service in the form of a service. Because Service is more complicated, many developers want to develop their own service but often. In view of this, then we will construct a new service from the head to the end, readers as long as they add their own code in the program, then you can easily have a self-service. Before writing service, first introduce several important functions: ---- 1. SC_Handle OpenScManager (LPCTSTSTR LPMABASENAME, DWORD DWDESIREDACCESS) --- OpenScManager function Opens the Service Control Manager Database on the specified computer. The parameter lpMachinename specifies the computer name, and if specified as the unit for the air. LPDATABASENAME is empty for the Service Control Manager Database name to be opened. Dwdesired Accept specified permissions, one of the values below: ---- SC_Manager_all_Access file: // All permissions ---- SC_Manager_Connect File: // Allow to connect to Service Control Manager Database ---- SC_Manager_create_service file: // Allow the service object and add it to Database ---- SC_Manager_Enumerate_Service File: // Allow enumeration of services in Database ---- SC_Manager_lock file: // Allow lock Database ---- SC_Manager_Query_lock_status file: // Allow Query Database Blocking information ---- Function is successfully returned to a handle pointing to Service Control Manager Database, returns NULL. Note: Winnt manages all services through a database called Service Control Manager Database, so this database should be opened for any operation of Service.
---- 2. SC_HANDLE CreateService (SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPCTSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCTSTR lpBinaryPathName, LPCTSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCTSTR lpDependencies, LPCTSTR lpServiceStartName, LPCTSTR lpPassword)
---- CreatService function generates a new service. The parameter hscmanager is the handle of the Service Control Manager Database, returned by OpenScManager. LPServiceName is the name of Service, LPDisplayName is a service display name, DwdesiredAccess is access, this program with service_all_access. WSERVICEPE, specify the service type, in this program with service_win32_oen_process | service_interactive_process. DWStartType is the service launch method, this program uses self-start, ie DWStartType is equal to service_auto_start. DWERRORCONTROL Note What actions take when the Service is in the launch, this program uses service_error_ignore, and readers can be changed to other. LPBINARYPATHNAME indicates the path name of the Service ontology program. The remaining five parameters can be typically set to NULL. If the function call is successful, return this new service handle, and the null is returned. Corresponding to this function is DELETSERVICE (HService), which deletes the specified service. ---- 3. SC_Handle OpenService (sc_handle hscmanager, lpctstr lpserviceename, dword dwdesiredAccess) ---- OpenService function Opens the specified service. The parameter hscmanager is the handle of the Service Control Manager Database, returned by OpenScManager. LPServiceName is the name of Service, dwdesiredAccess is access to access, and its optional value is more, readers can see the SDK Help. The function call successfully returns the open service handle, and returns NULL. ---- 4. Bool StartService (sc_handle hservice, dword dword dword dword dwnumservicegs) ---- StartService function launches the specified service. The parameter hservice is a handle pointing to the service, returned by OpenService. DwnumServiceA is the number of parameters required to start the service. LPSZServiceArgs is the parameters required to start the service. The function is successful, returns true, and false is returned. ---- 5. Bool ControlService (SC_Handle HService DWORD DWCONTROL, LPSERVICE_STATUS LPSERVICESTATUS) ---- Service program does not have a dedicated stop function, but with the controlService function to control the service's pause, continue, stop and other operations.
DwControl parameter specifies the control command is issued, it is possible for the following values: SERVICE_CONTROL_STOP file: // Stop ServiceSERVICE_CONTROL_PAUSE file: // pause ServiceSERVICE_CONTROL_CONTINUE file: // continue ServiceSERVICE_CONTROL_INTERROGATE file: // Query Service status SERVICE_CONTROL_SHUTDOWN file: // Let ControlService call Failure ---- Parameter LPServiceStatus is a pointer to Service_Status. Service_status is a more important structure that contains various information of the service, such as the current state, which control commands, and more. ---- 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. ---- Preparing a service usually requires two programs, one is a service body, one is a control program for controlling Service. Usually the service body is a console program, and the control program is a normal WIN32 application (of course, the user can be enabled by the control panel without the control program, stopping, but can not add, delete operation.) - First, let's write a service body. For the service body, it is generally composed of three parts: main (), servicemain (), handler (), the source code of Main (): (Note: Due to the relationship of the space, most of the program is not Error handling, readers can add themselves) int Main (int Argc, char ** argv) {service_table_entry ste [2]; file: // A Service process can have multiple threads, this is the entrance to each file: // thread Table STE [0] .LPServiceName = "WZService"; file: // thread name Ste [0] .lpserviceProc = serviceMain; file: // thread portfolio address STE [1] .lpServiceName = null; file: // 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 is always waiting for this service to call the StartServiceCtrldispatcher () function. Main () as the main thread of this process should call StartServiceCtrlDispatcher as soon as possible after the program. StartServiceCtrlDispatcher () is not immediately returned after being called, connects the host's main thread to Service Control Manager, so that Service Control Manager will start, stop control commands to the main thread through this connection. The main thread played the role of a command transponder, it or calls handle () to process the stop, continue the control requirements, or generate a new thread to execute ServiceMain. StartServiceCtrlDispatcher () returned at the end of the service. ---- ServiceMain () is a true entry point for Service, must be properly defined in main (). The two parameters of ServiceMain () are passed by StartService (). The following is the ServiceMain () of source code: void WINAPI ServiceMain (DWORD dwArgc, LPTSTR * lpszArgv) {ssh = RegisterServiceCtrlHandler ( "WZSERVICE", Handler); ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS; ss.dwCurrentState = SERVICE_START_PENDING; file: / / If the code of the user program is more (execution time is more than 1 second), it is set to service_start_pending. After the user program is completed, set to service_running. Ss.dwcontrolsaccepted = service_accept_stop; // indicates that the command currently can accept is a stop command. Ss.dwwin32exitcode = no_error; s.dwcheckpoint = 0; ss.dwwaithint = 0; setServiceStatus (ssh, & ss); file: // must update the status of the service in the database at any time. Mycode (); file: // here can be placed in the user's own code 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 (); // This can also be put into the user's own code} should immediately call registerServiceCtrlHandler () Register a Handler to deal with the control program or control panel to Service Control requirements.
Handler () is called to deal with the forwarder, the following is the source code of Handler (): void WinApi Handler (DWRD OPCode) {switch (opcode) {copy service_control_stop: file: // Stop service mycode (); // Put the user's own code ss.dwwin32exitcode = 0; ss.dwcurrentState = service_stopped; file: // Set the current status of the service to stop ss.dwcheckpoint = 0; ss.dwwaithint = 0; setServiceStatus (SSH, & SS); / Must update the status of Service in the database; Case Service_Control_Interrogate: SetServiceStatus (SSH, & SS); / Must update the status of Service in the database at any time;}}
---- Well, the service body program has been basically completed, let's take a look at the service control program: ---- Control program is a standard Window program, which mainly has four heads: Create Service, Delete Service START, STOP, used to generate, delete, start, and stop service. The following is a part of the source thereof: 1. Generate Servicevoid __fastcall TForm1 :: CreateBtnClick (TObject * Sender) {scm = OpenSCManager (NULL, NULL, SC_MANAGER_CREATE_SERVICE); if (scm = NULL!) {Svc = CreateService (scm, "WZ SERVICE "," WZSERVICE ", // Service name SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, SERVICE_AUTO_START, file: // an automated way to start SERVICE_ERROR_IGNORE," C: //ntservice.exe ", file: // Service body program path, you must NULL, NULL, NULL, NULL, NULL); if (SVC! = Null) ClosEServiceHandle (SVC); ClosESERVICEHANDLE (SCM);}} 2. Delete Servicevoid __fastcall tform1 :: deletebtnclick (Tobject * sender) {SCM = OpenSCManager (NULL, NULL, SC_MANAGER_CONNECT); if (scm = NULL!) {svc = OpenService (scm, "WZSERVICE", SERVICE_ALL_ACCESS); if (! svc = NULL) {QueryServiceStatus (svc, & ServiceStatus); if (ServiceStatus .dwcurrentState == service_running) // Before delete, stop this service. ControlService first (SVC, Service_Control_Stop, & ServiceStatus); deleteService (SVC); ClosESERVICEHANDLE (SVC) ); File: // After deleting the service, it is best to call CloseServiceHandle} file: // to immediately remove this entry from the database.
CloseServiceHandle (scm);.}} 3 starts Servicevoid __fastcall TForm1 :: StartBtnClick (TObject * Sender) {scm = OpenSCManager (NULL, NULL, SC_MANAGER_CONNECT); if (scm = NULL!) {Svc = OpenService (scm, "WZSERVICE ", Service_start); if (SVC! = Null) {StartService (SVC, 0, NULL); // Start Service ClosESERVICEHANDE (SVC);} ClosESERVICEHANDE (SCM);}} 4. Stop Service Void __fastcall tform1 :: stopbtnclick TObject * Sender) {scm = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);! if (scm = NULL) {svc = OpenService (scm, "WZSERVICE", 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);}} ---- procedures in the C Builder and Windows NT 4.0 compiles the pass.