[NETLOGON] Add the netlogon service.
[reactos.git] / base / services / netlogon / netlogon.c
1 /*
2 * PROJECT: ReactOS NetLogon Service
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: NetLogon service RPC server
5 * COPYRIGHT: Eric Kohl 2019 <eric.kohl@reactos.org>
6 */
7
8 /* INCLUDES *****************************************************************/
9
10 #include "precomp.h"
11
12 WINE_DEFAULT_DEBUG_CHANNEL(netlogon);
13
14
15 /* GLOBALS ******************************************************************/
16
17 HINSTANCE hDllInstance;
18
19 static WCHAR ServiceName[] = L"netlogon";
20
21 static SERVICE_STATUS_HANDLE ServiceStatusHandle;
22 static SERVICE_STATUS ServiceStatus;
23
24
25 /* FUNCTIONS *****************************************************************/
26
27 static
28 VOID
29 UpdateServiceStatus(
30 DWORD dwState)
31 {
32 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
33 ServiceStatus.dwCurrentState = dwState;
34 ServiceStatus.dwControlsAccepted = 0;
35 ServiceStatus.dwWin32ExitCode = 0;
36 ServiceStatus.dwServiceSpecificExitCode = 0;
37 ServiceStatus.dwCheckPoint = 0;
38
39 if (dwState == SERVICE_START_PENDING ||
40 dwState == SERVICE_STOP_PENDING ||
41 dwState == SERVICE_PAUSE_PENDING ||
42 dwState == SERVICE_CONTINUE_PENDING)
43 ServiceStatus.dwWaitHint = 10000;
44 else
45 ServiceStatus.dwWaitHint = 0;
46
47 SetServiceStatus(ServiceStatusHandle,
48 &ServiceStatus);
49 }
50
51
52 static
53 DWORD
54 WINAPI
55 ServiceControlHandler(
56 DWORD dwControl,
57 DWORD dwEventType,
58 LPVOID lpEventData,
59 LPVOID lpContext)
60 {
61 TRACE("ServiceControlHandler()\n");
62
63 switch (dwControl)
64 {
65 case SERVICE_CONTROL_STOP:
66 TRACE(" SERVICE_CONTROL_STOP received\n");
67 /* Stop listening to incoming RPC messages */
68 RpcMgmtStopServerListening(NULL);
69 UpdateServiceStatus(SERVICE_STOPPED);
70 return ERROR_SUCCESS;
71
72 case SERVICE_CONTROL_PAUSE:
73 TRACE(" SERVICE_CONTROL_PAUSE received\n");
74 UpdateServiceStatus(SERVICE_PAUSED);
75 return ERROR_SUCCESS;
76
77 case SERVICE_CONTROL_CONTINUE:
78 TRACE(" SERVICE_CONTROL_CONTINUE received\n");
79 UpdateServiceStatus(SERVICE_RUNNING);
80 return ERROR_SUCCESS;
81
82 case SERVICE_CONTROL_INTERROGATE:
83 TRACE(" SERVICE_CONTROL_INTERROGATE received\n");
84 SetServiceStatus(ServiceStatusHandle,
85 &ServiceStatus);
86 return ERROR_SUCCESS;
87
88 case SERVICE_CONTROL_SHUTDOWN:
89 TRACE(" SERVICE_CONTROL_SHUTDOWN received\n");
90 UpdateServiceStatus(SERVICE_STOPPED);
91 return ERROR_SUCCESS;
92
93 default :
94 TRACE(" Control %lu received\n", dwControl);
95 return ERROR_CALL_NOT_IMPLEMENTED;
96 }
97 }
98
99
100 static
101 DWORD
102 ServiceInit(VOID)
103 {
104 HANDLE hThread;
105
106 hThread = CreateThread(NULL,
107 0,
108 (LPTHREAD_START_ROUTINE)RpcThreadRoutine,
109 NULL,
110 0,
111 NULL);
112
113 if (!hThread)
114 {
115 ERR("Can't create PortThread\n");
116 return GetLastError();
117 }
118 else
119 CloseHandle(hThread);
120
121 return ERROR_SUCCESS;
122 }
123
124
125 VOID WINAPI
126 NlNetlogonMain(
127 _In_ INT ArgCount,
128 _In_ PWSTR *ArgVector)
129 {
130 DWORD dwError;
131
132 UNREFERENCED_PARAMETER(ArgCount);
133 UNREFERENCED_PARAMETER(ArgVector);
134
135 TRACE("NlNetlogonMain(%d %p)\n", ArgCount, ArgVector);
136
137 ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
138 ServiceControlHandler,
139 NULL);
140 if (!ServiceStatusHandle)
141 {
142 ERR("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
143 return;
144 }
145
146 UpdateServiceStatus(SERVICE_START_PENDING);
147
148 dwError = ServiceInit();
149 if (dwError != ERROR_SUCCESS)
150 {
151 ERR("Service stopped (dwError: %lu\n", dwError);
152 UpdateServiceStatus(SERVICE_STOPPED);
153 return;
154 }
155
156 UpdateServiceStatus(SERVICE_RUNNING);
157 }
158
159
160 BOOL
161 WINAPI
162 DllMain(
163 _In_ HINSTANCE hinstDLL,
164 _In_ DWORD fdwReason,
165 _In_ PVOID pvReserved)
166 {
167 UNREFERENCED_PARAMETER(pvReserved);
168
169 switch (fdwReason)
170 {
171 case DLL_PROCESS_ATTACH:
172 DisableThreadLibraryCalls(hinstDLL);
173 hDllInstance = hinstDLL;
174 break;
175
176 case DLL_PROCESS_DETACH:
177 break;
178 }
179
180 return TRUE;
181 }
182
183 /* EOF */