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 Status = LsaRegisterLogonProcess(&ProcessName, 89 &LsaHandle, 90 &Mode); 91 if (!NT_SUCCESS(Status)) 92 { 93 ERR("LsaRegisterLogonProcess() failed! (Status 0x%08lx)\n", Status); 94 return 1; 95 } 96 97 Status = LsaLookupAuthenticationPackage(LsaHandle, 98 &PackageName, 99 &LsaAuthenticationPackage); 100 if (!NT_SUCCESS(Status)) 101 { 102 ERR("LsaLookupAuthenticationPackage() failed! (Status 0x%08lx)\n", Status); 103 return 1; 104 } 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 /* Report a running workstation service */ 122 SetServiceBits(ServiceStatusHandle, 123 SV_TYPE_WORKSTATION, 124 TRUE, 125 TRUE); 126 127 return ERROR_SUCCESS; 128 } 129 130 131 static 132 VOID 133 ServiceShutdown(VOID) 134 { 135 NTSTATUS Status; 136 137 ERR("ServiceShutdown()\n"); 138 139 Status = LsaDeregisterLogonProcess(LsaHandle); 140 if (!NT_SUCCESS(Status)) 141 { 142 ERR("LsaDeRegisterLogonProcess() failed! (Status 0x%08lx)\n", Status); 143 return; 144 } 145 } 146 147 148 static DWORD WINAPI 149 ServiceControlHandler(DWORD dwControl, 150 DWORD dwEventType, 151 LPVOID lpEventData, 152 LPVOID lpContext) 153 { 154 TRACE("ServiceControlHandler() called\n"); 155 156 switch (dwControl) 157 { 158 case SERVICE_CONTROL_STOP: 159 TRACE(" SERVICE_CONTROL_STOP received\n"); 160 UpdateServiceStatus(SERVICE_STOP_PENDING); 161 /* Stop listening to incoming RPC messages */ 162 RpcMgmtStopServerListening(NULL); 163 ServiceShutdown(); 164 UpdateServiceStatus(SERVICE_STOPPED); 165 return ERROR_SUCCESS; 166 167 case SERVICE_CONTROL_PAUSE: 168 TRACE(" SERVICE_CONTROL_PAUSE received\n"); 169 UpdateServiceStatus(SERVICE_PAUSED); 170 return ERROR_SUCCESS; 171 172 case SERVICE_CONTROL_CONTINUE: 173 TRACE(" SERVICE_CONTROL_CONTINUE received\n"); 174 UpdateServiceStatus(SERVICE_RUNNING); 175 return ERROR_SUCCESS; 176 177 case SERVICE_CONTROL_INTERROGATE: 178 TRACE(" SERVICE_CONTROL_INTERROGATE received\n"); 179 SetServiceStatus(ServiceStatusHandle, 180 &ServiceStatus); 181 return ERROR_SUCCESS; 182 183 case SERVICE_CONTROL_SHUTDOWN: 184 TRACE(" SERVICE_CONTROL_SHUTDOWN received\n"); 185 UpdateServiceStatus(SERVICE_STOP_PENDING); 186 /* Stop listening to incoming RPC messages */ 187 RpcMgmtStopServerListening(NULL); 188 ServiceShutdown(); 189 UpdateServiceStatus(SERVICE_STOPPED); 190 return ERROR_SUCCESS; 191 192 default : 193 TRACE(" Control %lu received\n", dwControl); 194 return ERROR_CALL_NOT_IMPLEMENTED; 195 } 196 } 197 198 199 VOID WINAPI 200 ServiceMain(DWORD argc, LPTSTR *argv) 201 { 202 DWORD dwError; 203 204 UNREFERENCED_PARAMETER(argc); 205 UNREFERENCED_PARAMETER(argv); 206 207 TRACE("ServiceMain() called\n"); 208 209 ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName, 210 ServiceControlHandler, 211 NULL); 212 if (!ServiceStatusHandle) 213 { 214 ERR("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError()); 215 return; 216 } 217 218 UpdateServiceStatus(SERVICE_START_PENDING); 219 220 dwError = ServiceInit(); 221 if (dwError != ERROR_SUCCESS) 222 { 223 ERR("Service stopped (dwError: %lu\n", dwError); 224 UpdateServiceStatus(SERVICE_STOPPED); 225 return; 226 } 227 228 UpdateServiceStatus(SERVICE_RUNNING); 229 } 230 231 232 BOOL WINAPI 233 DllMain(HINSTANCE hinstDLL, 234 DWORD fdwReason, 235 LPVOID lpvReserved) 236 { 237 switch (fdwReason) 238 { 239 case DLL_PROCESS_ATTACH: 240 DisableThreadLibraryCalls(hinstDLL); 241 break; 242 243 case DLL_PROCESS_DETACH: 244 break; 245 } 246 247 return TRUE; 248 } 249