1c2c66affSColin Finck /*
2c2c66affSColin Finck * ReactOS Services
3c2c66affSColin Finck * Copyright (C) 2015 ReactOS Team
4c2c66affSColin Finck *
5c2c66affSColin Finck * This program is free software; you can redistribute it and/or modify
6c2c66affSColin Finck * it under the terms of the GNU General Public License as published by
7c2c66affSColin Finck * the Free Software Foundation; either version 2 of the License, or
8c2c66affSColin Finck * (at your option) any later version.
9c2c66affSColin Finck *
10c2c66affSColin Finck * This program is distributed in the hope that it will be useful,
11c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
12c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c2c66affSColin Finck * GNU General Public License for more details.
14c2c66affSColin Finck *
15c2c66affSColin Finck * You should have received a copy of the GNU General Public License along
16c2c66affSColin Finck * with this program; if not, write to the Free Software Foundation, Inc.,
17c2c66affSColin Finck * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18c2c66affSColin Finck */
19c2c66affSColin Finck /*
20c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
21c2c66affSColin Finck * PROJECT: ReactOS Services
22c2c66affSColin Finck * FILE: base/services/wkssvc/wkssvc.c
23c2c66affSColin Finck * PURPOSE: Workstation service
24c2c66affSColin Finck * PROGRAMMER: Eric Kohl
25c2c66affSColin Finck */
26c2c66affSColin Finck
27c2c66affSColin Finck /* INCLUDES *****************************************************************/
28c2c66affSColin Finck
29c2c66affSColin Finck #include "precomp.h"
30c2c66affSColin Finck
31c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(wkssvc);
32c2c66affSColin Finck
33c2c66affSColin Finck /* GLOBALS ******************************************************************/
34c2c66affSColin Finck
35c2c66affSColin Finck static WCHAR ServiceName[] = L"lanmanworkstation";
36c2c66affSColin Finck
37c2c66affSColin Finck static SERVICE_STATUS_HANDLE ServiceStatusHandle;
38c2c66affSColin Finck static SERVICE_STATUS ServiceStatus;
39c2c66affSColin Finck
4095188553SEric Kohl OSVERSIONINFOW VersionInfo;
4195188553SEric Kohl HANDLE LsaHandle = NULL;
4295188553SEric Kohl ULONG LsaAuthenticationPackage = 0;
4395188553SEric Kohl
44c2c66affSColin Finck /* FUNCTIONS *****************************************************************/
45c2c66affSColin Finck
46c2c66affSColin Finck static VOID
UpdateServiceStatus(DWORD dwState)47c2c66affSColin Finck UpdateServiceStatus(DWORD dwState)
48c2c66affSColin Finck {
4969bd857eSEric Kohl ServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
50c2c66affSColin Finck ServiceStatus.dwCurrentState = dwState;
51c2c66affSColin Finck ServiceStatus.dwControlsAccepted = 0;
52c2c66affSColin Finck ServiceStatus.dwWin32ExitCode = 0;
53c2c66affSColin Finck ServiceStatus.dwServiceSpecificExitCode = 0;
54c2c66affSColin Finck ServiceStatus.dwCheckPoint = 0;
55c2c66affSColin Finck
56c2c66affSColin Finck if (dwState == SERVICE_START_PENDING ||
57c2c66affSColin Finck dwState == SERVICE_STOP_PENDING ||
58c2c66affSColin Finck dwState == SERVICE_PAUSE_PENDING ||
59c2c66affSColin Finck dwState == SERVICE_CONTINUE_PENDING)
60c2c66affSColin Finck ServiceStatus.dwWaitHint = 10000;
61c2c66affSColin Finck else
62c2c66affSColin Finck ServiceStatus.dwWaitHint = 0;
63c2c66affSColin Finck
644073a8c5SEric Kohl if (dwState == SERVICE_RUNNING)
654073a8c5SEric Kohl ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
664073a8c5SEric Kohl
67c2c66affSColin Finck SetServiceStatus(ServiceStatusHandle,
68c2c66affSColin Finck &ServiceStatus);
69c2c66affSColin Finck }
70c2c66affSColin Finck
7195188553SEric Kohl
7295188553SEric Kohl static
7395188553SEric Kohl DWORD
ServiceInit(VOID)7495188553SEric Kohl ServiceInit(VOID)
7595188553SEric Kohl {
765d8e8348STimo Kreuzer LSA_STRING ProcessName = RTL_CONSTANT_STRING("Workstation");
775d8e8348STimo Kreuzer LSA_STRING PackageName = RTL_CONSTANT_STRING(MSV1_0_PACKAGE_NAME);
7895188553SEric Kohl LSA_OPERATIONAL_MODE Mode;
7995188553SEric Kohl HANDLE hThread;
8095188553SEric Kohl NTSTATUS Status;
8195188553SEric Kohl
8295188553SEric Kohl ERR("ServiceInit()\n");
8395188553SEric Kohl
8495188553SEric Kohl /* Get the OS version */
8595188553SEric Kohl VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
8695188553SEric Kohl GetVersionExW(&VersionInfo);
8795188553SEric Kohl
88*51b55982SEric Kohl InitWorkstationInfo();
89*51b55982SEric Kohl
9095188553SEric Kohl Status = LsaRegisterLogonProcess(&ProcessName,
9195188553SEric Kohl &LsaHandle,
9295188553SEric Kohl &Mode);
9395188553SEric Kohl if (!NT_SUCCESS(Status))
9495188553SEric Kohl {
9595188553SEric Kohl ERR("LsaRegisterLogonProcess() failed! (Status 0x%08lx)\n", Status);
9695188553SEric Kohl return 1;
9795188553SEric Kohl }
9895188553SEric Kohl
9995188553SEric Kohl Status = LsaLookupAuthenticationPackage(LsaHandle,
10095188553SEric Kohl &PackageName,
10195188553SEric Kohl &LsaAuthenticationPackage);
10295188553SEric Kohl if (!NT_SUCCESS(Status))
10395188553SEric Kohl {
10495188553SEric Kohl ERR("LsaLookupAuthenticationPackage() failed! (Status 0x%08lx)\n", Status);
10595188553SEric Kohl return 1;
10695188553SEric Kohl }
10795188553SEric Kohl
10895188553SEric Kohl hThread = CreateThread(NULL,
10995188553SEric Kohl 0,
11095188553SEric Kohl (LPTHREAD_START_ROUTINE)RpcThreadRoutine,
11195188553SEric Kohl NULL,
11295188553SEric Kohl 0,
11395188553SEric Kohl NULL);
11495188553SEric Kohl
11595188553SEric Kohl if (!hThread)
11695188553SEric Kohl {
11795188553SEric Kohl ERR("Can't create PortThread\n");
11895188553SEric Kohl return GetLastError();
11995188553SEric Kohl }
12095188553SEric Kohl else
12195188553SEric Kohl CloseHandle(hThread);
12295188553SEric Kohl
12395188553SEric Kohl /* Report a running workstation service */
12495188553SEric Kohl SetServiceBits(ServiceStatusHandle,
12595188553SEric Kohl SV_TYPE_WORKSTATION,
12695188553SEric Kohl TRUE,
12795188553SEric Kohl TRUE);
12895188553SEric Kohl
12995188553SEric Kohl return ERROR_SUCCESS;
13095188553SEric Kohl }
13195188553SEric Kohl
13295188553SEric Kohl
13395188553SEric Kohl static
13495188553SEric Kohl VOID
ServiceShutdown(VOID)13595188553SEric Kohl ServiceShutdown(VOID)
13695188553SEric Kohl {
13795188553SEric Kohl NTSTATUS Status;
13895188553SEric Kohl
13995188553SEric Kohl ERR("ServiceShutdown()\n");
14095188553SEric Kohl
14195188553SEric Kohl Status = LsaDeregisterLogonProcess(LsaHandle);
14295188553SEric Kohl if (!NT_SUCCESS(Status))
14395188553SEric Kohl {
14495188553SEric Kohl ERR("LsaDeRegisterLogonProcess() failed! (Status 0x%08lx)\n", Status);
14595188553SEric Kohl return;
14695188553SEric Kohl }
14795188553SEric Kohl }
14895188553SEric Kohl
14995188553SEric Kohl
150c2c66affSColin Finck static DWORD WINAPI
ServiceControlHandler(DWORD dwControl,DWORD dwEventType,LPVOID lpEventData,LPVOID lpContext)151c2c66affSColin Finck ServiceControlHandler(DWORD dwControl,
152c2c66affSColin Finck DWORD dwEventType,
153c2c66affSColin Finck LPVOID lpEventData,
154c2c66affSColin Finck LPVOID lpContext)
155c2c66affSColin Finck {
156c2c66affSColin Finck TRACE("ServiceControlHandler() called\n");
157c2c66affSColin Finck
158c2c66affSColin Finck switch (dwControl)
159c2c66affSColin Finck {
160c2c66affSColin Finck case SERVICE_CONTROL_STOP:
161c2c66affSColin Finck TRACE(" SERVICE_CONTROL_STOP received\n");
162e0c97c9eSEric Kohl UpdateServiceStatus(SERVICE_STOP_PENDING);
163c2c66affSColin Finck /* Stop listening to incoming RPC messages */
164c2c66affSColin Finck RpcMgmtStopServerListening(NULL);
16595188553SEric Kohl ServiceShutdown();
166c2c66affSColin Finck UpdateServiceStatus(SERVICE_STOPPED);
167c2c66affSColin Finck return ERROR_SUCCESS;
168c2c66affSColin Finck
169c2c66affSColin Finck case SERVICE_CONTROL_PAUSE:
170c2c66affSColin Finck TRACE(" SERVICE_CONTROL_PAUSE received\n");
171c2c66affSColin Finck UpdateServiceStatus(SERVICE_PAUSED);
172c2c66affSColin Finck return ERROR_SUCCESS;
173c2c66affSColin Finck
174c2c66affSColin Finck case SERVICE_CONTROL_CONTINUE:
175c2c66affSColin Finck TRACE(" SERVICE_CONTROL_CONTINUE received\n");
176c2c66affSColin Finck UpdateServiceStatus(SERVICE_RUNNING);
177c2c66affSColin Finck return ERROR_SUCCESS;
178c2c66affSColin Finck
179c2c66affSColin Finck case SERVICE_CONTROL_INTERROGATE:
180c2c66affSColin Finck TRACE(" SERVICE_CONTROL_INTERROGATE received\n");
181c2c66affSColin Finck SetServiceStatus(ServiceStatusHandle,
182c2c66affSColin Finck &ServiceStatus);
183c2c66affSColin Finck return ERROR_SUCCESS;
184c2c66affSColin Finck
185c2c66affSColin Finck case SERVICE_CONTROL_SHUTDOWN:
186c2c66affSColin Finck TRACE(" SERVICE_CONTROL_SHUTDOWN received\n");
187e0c97c9eSEric Kohl UpdateServiceStatus(SERVICE_STOP_PENDING);
188e0c97c9eSEric Kohl /* Stop listening to incoming RPC messages */
189e0c97c9eSEric Kohl RpcMgmtStopServerListening(NULL);
19095188553SEric Kohl ServiceShutdown();
191c2c66affSColin Finck UpdateServiceStatus(SERVICE_STOPPED);
192c2c66affSColin Finck return ERROR_SUCCESS;
193c2c66affSColin Finck
194c2c66affSColin Finck default :
195c2c66affSColin Finck TRACE(" Control %lu received\n", dwControl);
196c2c66affSColin Finck return ERROR_CALL_NOT_IMPLEMENTED;
197c2c66affSColin Finck }
198c2c66affSColin Finck }
199c2c66affSColin Finck
200c2c66affSColin Finck
201c2c66affSColin Finck VOID WINAPI
ServiceMain(DWORD argc,LPTSTR * argv)202c2c66affSColin Finck ServiceMain(DWORD argc, LPTSTR *argv)
203c2c66affSColin Finck {
204c2c66affSColin Finck DWORD dwError;
205c2c66affSColin Finck
206c2c66affSColin Finck UNREFERENCED_PARAMETER(argc);
207c2c66affSColin Finck UNREFERENCED_PARAMETER(argv);
208c2c66affSColin Finck
209c2c66affSColin Finck TRACE("ServiceMain() called\n");
210c2c66affSColin Finck
211c2c66affSColin Finck ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
212c2c66affSColin Finck ServiceControlHandler,
213c2c66affSColin Finck NULL);
214c2c66affSColin Finck if (!ServiceStatusHandle)
215c2c66affSColin Finck {
216c2c66affSColin Finck ERR("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
217c2c66affSColin Finck return;
218c2c66affSColin Finck }
219c2c66affSColin Finck
220c2c66affSColin Finck UpdateServiceStatus(SERVICE_START_PENDING);
221c2c66affSColin Finck
222c2c66affSColin Finck dwError = ServiceInit();
223c2c66affSColin Finck if (dwError != ERROR_SUCCESS)
224c2c66affSColin Finck {
225c2c66affSColin Finck ERR("Service stopped (dwError: %lu\n", dwError);
226c2c66affSColin Finck UpdateServiceStatus(SERVICE_STOPPED);
227c2c66affSColin Finck return;
228c2c66affSColin Finck }
229c2c66affSColin Finck
230c2c66affSColin Finck UpdateServiceStatus(SERVICE_RUNNING);
231c2c66affSColin Finck }
232c2c66affSColin Finck
233c2c66affSColin Finck
234c2c66affSColin Finck BOOL WINAPI
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)235c2c66affSColin Finck DllMain(HINSTANCE hinstDLL,
236c2c66affSColin Finck DWORD fdwReason,
237c2c66affSColin Finck LPVOID lpvReserved)
238c2c66affSColin Finck {
239c2c66affSColin Finck switch (fdwReason)
240c2c66affSColin Finck {
241c2c66affSColin Finck case DLL_PROCESS_ATTACH:
242c2c66affSColin Finck DisableThreadLibraryCalls(hinstDLL);
243c2c66affSColin Finck break;
244c2c66affSColin Finck
245c2c66affSColin Finck case DLL_PROCESS_DETACH:
246c2c66affSColin Finck break;
247c2c66affSColin Finck }
248c2c66affSColin Finck
249c2c66affSColin Finck return TRUE;
250c2c66affSColin Finck }
251