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 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 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 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 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 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 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