1 /*
2 * ReactOS Services
3 * Copyright (C) 2015 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS Services
22 * FILE: base/services/wkssvc/wkssvc.c
23 * PURPOSE: Workstation service
24 * PROGRAMMER: Eric Kohl
25 */
26
27 /* INCLUDES *****************************************************************/
28
29 #include "precomp.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(wkssvc);
32
33 /* GLOBALS ******************************************************************/
34
35 static WCHAR ServiceName[] = L"lanmanworkstation";
36
37 static SERVICE_STATUS_HANDLE ServiceStatusHandle;
38 static SERVICE_STATUS ServiceStatus;
39
40 OSVERSIONINFOW VersionInfo;
41 HANDLE LsaHandle = NULL;
42 ULONG LsaAuthenticationPackage = 0;
43
44 /* FUNCTIONS *****************************************************************/
45
46 static VOID
UpdateServiceStatus(DWORD dwState)47 UpdateServiceStatus(DWORD dwState)
48 {
49 ServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
50 ServiceStatus.dwCurrentState = dwState;
51 ServiceStatus.dwControlsAccepted = 0;
52 ServiceStatus.dwWin32ExitCode = 0;
53 ServiceStatus.dwServiceSpecificExitCode = 0;
54 ServiceStatus.dwCheckPoint = 0;
55
56 if (dwState == SERVICE_START_PENDING ||
57 dwState == SERVICE_STOP_PENDING ||
58 dwState == SERVICE_PAUSE_PENDING ||
59 dwState == SERVICE_CONTINUE_PENDING)
60 ServiceStatus.dwWaitHint = 10000;
61 else
62 ServiceStatus.dwWaitHint = 0;
63
64 if (dwState == SERVICE_RUNNING)
65 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
66
67 SetServiceStatus(ServiceStatusHandle,
68 &ServiceStatus);
69 }
70
71
72 static
73 DWORD
ServiceInit(VOID)74 ServiceInit(VOID)
75 {
76 LSA_STRING ProcessName = RTL_CONSTANT_STRING("Workstation");
77 LSA_STRING PackageName = RTL_CONSTANT_STRING(MSV1_0_PACKAGE_NAME);
78 LSA_OPERATIONAL_MODE Mode;
79 HANDLE hThread;
80 NTSTATUS Status;
81
82 ERR("ServiceInit()\n");
83
84 /* Get the OS version */
85 VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
86 GetVersionExW(&VersionInfo);
87
88 InitWorkstationInfo();
89
90 Status = LsaRegisterLogonProcess(&ProcessName,
91 &LsaHandle,
92 &Mode);
93 if (!NT_SUCCESS(Status))
94 {
95 ERR("LsaRegisterLogonProcess() failed! (Status 0x%08lx)\n", Status);
96 return 1;
97 }
98
99 Status = LsaLookupAuthenticationPackage(LsaHandle,
100 &PackageName,
101 &LsaAuthenticationPackage);
102 if (!NT_SUCCESS(Status))
103 {
104 ERR("LsaLookupAuthenticationPackage() failed! (Status 0x%08lx)\n", Status);
105 return 1;
106 }
107
108 hThread = CreateThread(NULL,
109 0,
110 (LPTHREAD_START_ROUTINE)RpcThreadRoutine,
111 NULL,
112 0,
113 NULL);
114
115 if (!hThread)
116 {
117 ERR("Can't create PortThread\n");
118 return GetLastError();
119 }
120 else
121 CloseHandle(hThread);
122
123 /* Report a running workstation service */
124 SetServiceBits(ServiceStatusHandle,
125 SV_TYPE_WORKSTATION,
126 TRUE,
127 TRUE);
128
129 return ERROR_SUCCESS;
130 }
131
132
133 static
134 VOID
ServiceShutdown(VOID)135 ServiceShutdown(VOID)
136 {
137 NTSTATUS Status;
138
139 ERR("ServiceShutdown()\n");
140
141 Status = LsaDeregisterLogonProcess(LsaHandle);
142 if (!NT_SUCCESS(Status))
143 {
144 ERR("LsaDeRegisterLogonProcess() failed! (Status 0x%08lx)\n", Status);
145 return;
146 }
147 }
148
149
150 static DWORD WINAPI
ServiceControlHandler(DWORD dwControl,DWORD dwEventType,LPVOID lpEventData,LPVOID lpContext)151 ServiceControlHandler(DWORD dwControl,
152 DWORD dwEventType,
153 LPVOID lpEventData,
154 LPVOID lpContext)
155 {
156 TRACE("ServiceControlHandler() called\n");
157
158 switch (dwControl)
159 {
160 case SERVICE_CONTROL_STOP:
161 TRACE(" SERVICE_CONTROL_STOP received\n");
162 UpdateServiceStatus(SERVICE_STOP_PENDING);
163 /* Stop listening to incoming RPC messages */
164 RpcMgmtStopServerListening(NULL);
165 ServiceShutdown();
166 UpdateServiceStatus(SERVICE_STOPPED);
167 return ERROR_SUCCESS;
168
169 case SERVICE_CONTROL_PAUSE:
170 TRACE(" SERVICE_CONTROL_PAUSE received\n");
171 UpdateServiceStatus(SERVICE_PAUSED);
172 return ERROR_SUCCESS;
173
174 case SERVICE_CONTROL_CONTINUE:
175 TRACE(" SERVICE_CONTROL_CONTINUE received\n");
176 UpdateServiceStatus(SERVICE_RUNNING);
177 return ERROR_SUCCESS;
178
179 case SERVICE_CONTROL_INTERROGATE:
180 TRACE(" SERVICE_CONTROL_INTERROGATE received\n");
181 SetServiceStatus(ServiceStatusHandle,
182 &ServiceStatus);
183 return ERROR_SUCCESS;
184
185 case SERVICE_CONTROL_SHUTDOWN:
186 TRACE(" SERVICE_CONTROL_SHUTDOWN received\n");
187 UpdateServiceStatus(SERVICE_STOP_PENDING);
188 /* Stop listening to incoming RPC messages */
189 RpcMgmtStopServerListening(NULL);
190 ServiceShutdown();
191 UpdateServiceStatus(SERVICE_STOPPED);
192 return ERROR_SUCCESS;
193
194 default :
195 TRACE(" Control %lu received\n", dwControl);
196 return ERROR_CALL_NOT_IMPLEMENTED;
197 }
198 }
199
200
201 VOID WINAPI
ServiceMain(DWORD argc,LPTSTR * argv)202 ServiceMain(DWORD argc, LPTSTR *argv)
203 {
204 DWORD dwError;
205
206 UNREFERENCED_PARAMETER(argc);
207 UNREFERENCED_PARAMETER(argv);
208
209 TRACE("ServiceMain() called\n");
210
211 ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
212 ServiceControlHandler,
213 NULL);
214 if (!ServiceStatusHandle)
215 {
216 ERR("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
217 return;
218 }
219
220 UpdateServiceStatus(SERVICE_START_PENDING);
221
222 dwError = ServiceInit();
223 if (dwError != ERROR_SUCCESS)
224 {
225 ERR("Service stopped (dwError: %lu\n", dwError);
226 UpdateServiceStatus(SERVICE_STOPPED);
227 return;
228 }
229
230 UpdateServiceStatus(SERVICE_RUNNING);
231 }
232
233
234 BOOL WINAPI
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)235 DllMain(HINSTANCE hinstDLL,
236 DWORD fdwReason,
237 LPVOID lpvReserved)
238 {
239 switch (fdwReason)
240 {
241 case DLL_PROCESS_ATTACH:
242 DisableThreadLibraryCalls(hinstDLL);
243 break;
244
245 case DLL_PROCESS_DETACH:
246 break;
247 }
248
249 return TRUE;
250 }
251