xref: /reactos/base/services/wkssvc/wkssvc.c (revision 51b55982)
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