1 /*
2  * PROJECT:     ReactOS RPC Subsystem Service
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     DCOMLAUNCH service
5  * COPYRIGHT:   Copyright 2019 Pierre Schweitzer
6  */
7 
8 /* INCLUDES *****************************************************************/
9 
10 #define WIN32_NO_STATUS
11 #define _INC_WINDOWS
12 #define COM_NO_WINDOWS_H
13 #include <stdarg.h>
14 #include <windef.h>
15 #include <winbase.h>
16 #include <winreg.h>
17 #include <winsvc.h>
18 
19 #define NDEBUG
20 #include <debug.h>
21 
22 /* GLOBALS ******************************************************************/
23 
24 static WCHAR ServiceName[] = L"dcomlaunch";
25 
26 static SERVICE_STATUS_HANDLE ServiceStatusHandle;
27 static SERVICE_STATUS ServiceStatus;
28 static HANDLE ShutdownEvent;
29 
30 /* FUNCTIONS *****************************************************************/
31 
32 static VOID
33 UpdateServiceStatus(DWORD dwState)
34 {
35     ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
36     ServiceStatus.dwCurrentState = dwState;
37     ServiceStatus.dwControlsAccepted = 0;
38     ServiceStatus.dwWin32ExitCode = 0;
39     ServiceStatus.dwServiceSpecificExitCode = 0;
40     ServiceStatus.dwCheckPoint = 0;
41 
42     if (dwState == SERVICE_START_PENDING ||
43         dwState == SERVICE_STOP_PENDING ||
44         dwState == SERVICE_PAUSE_PENDING ||
45         dwState == SERVICE_CONTINUE_PENDING)
46         ServiceStatus.dwWaitHint = 10000;
47     else
48         ServiceStatus.dwWaitHint = 0;
49 
50     SetServiceStatus(ServiceStatusHandle,
51                      &ServiceStatus);
52 }
53 
54 static DWORD WINAPI
55 ServiceControlHandler(DWORD dwControl,
56                       DWORD dwEventType,
57                       LPVOID lpEventData,
58                       LPVOID lpContext)
59 {
60     DPRINT1("ServiceControlHandler() called\n");
61 
62     switch (dwControl)
63     {
64         case SERVICE_CONTROL_STOP:
65             DPRINT1("  SERVICE_CONTROL_STOP received\n");
66             SetEvent(ShutdownEvent);
67             UpdateServiceStatus(SERVICE_STOP_PENDING);
68             return ERROR_SUCCESS;
69 
70         case SERVICE_CONTROL_PAUSE:
71             DPRINT1("  SERVICE_CONTROL_PAUSE received\n");
72             UpdateServiceStatus(SERVICE_PAUSED);
73             return ERROR_SUCCESS;
74 
75         case SERVICE_CONTROL_CONTINUE:
76             DPRINT1("  SERVICE_CONTROL_CONTINUE received\n");
77             UpdateServiceStatus(SERVICE_RUNNING);
78             return ERROR_SUCCESS;
79 
80         case SERVICE_CONTROL_INTERROGATE:
81             DPRINT1("  SERVICE_CONTROL_INTERROGATE received\n");
82             SetServiceStatus(ServiceStatusHandle,
83                              &ServiceStatus);
84             return ERROR_SUCCESS;
85 
86         case SERVICE_CONTROL_SHUTDOWN:
87             DPRINT1("  SERVICE_CONTROL_SHUTDOWN received\n");
88             SetEvent(ShutdownEvent);
89             UpdateServiceStatus(SERVICE_STOP_PENDING);
90             return ERROR_SUCCESS;
91 
92         default :
93             DPRINT1("  Control %lu received\n");
94             return ERROR_CALL_NOT_IMPLEMENTED;
95     }
96 }
97 
98 VOID DealWithDeviceEvent();
99 
100 VOID WINAPI
101 ServiceMain(DWORD argc, LPTSTR *argv)
102 {
103     UNREFERENCED_PARAMETER(argc);
104     UNREFERENCED_PARAMETER(argv);
105 
106     DPRINT("ServiceMain() called\n");
107 
108     ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
109                                                         ServiceControlHandler,
110                                                         NULL);
111     if (!ServiceStatusHandle)
112     {
113         DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
114         return;
115     }
116 
117     ShutdownEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
118 
119     DealWithDeviceEvent();
120 
121     UpdateServiceStatus(SERVICE_RUNNING);
122 
123     WaitForSingleObject(ShutdownEvent, INFINITE);
124     CloseHandle(ShutdownEvent);
125 
126     UpdateServiceStatus(SERVICE_STOPPED);
127 }
128 
129 BOOL WINAPI
130 DllMain(HINSTANCE hinstDLL,
131         DWORD fdwReason,
132         LPVOID lpvReserved)
133 {
134     switch (fdwReason)
135     {
136         case DLL_PROCESS_ATTACH:
137             DisableThreadLibraryCalls(hinstDLL);
138             break;
139 
140         case DLL_PROCESS_DETACH:
141             break;
142     }
143 
144     return TRUE;
145 }
146