mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 16:33:02 -05:00
dll: add FSP_SERVICE and EventLog functionality
This commit is contained in:
parent
de973fa5ab
commit
d7a6f33d26
@ -25,6 +25,7 @@
|
||||
<ClInclude Include="..\..\src\dll\library.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\dll\eventlog.c" />
|
||||
<ClCompile Include="..\..\src\dll\np.c" />
|
||||
<ClCompile Include="..\..\src\dll\security.c" />
|
||||
<ClCompile Include="..\..\src\dll\debug.c" />
|
||||
@ -34,6 +35,7 @@
|
||||
<ClCompile Include="..\..\src\dll\fs.c" />
|
||||
<ClCompile Include="..\..\src\dll\ntstatus.c" />
|
||||
<ClCompile Include="..\..\src\dll\path.c" />
|
||||
<ClCompile Include="..\..\src\dll\service.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\src\dll\library.def" />
|
||||
|
@ -52,6 +52,12 @@
|
||||
<ClCompile Include="..\..\src\dll\np.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\dll\service.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\dll\eventlog.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\src\dll\ntstatus.i">
|
||||
|
@ -838,10 +838,52 @@ FSP_API VOID FspPathPrefix(PWSTR Path, PWSTR *PPrefix, PWSTR *PRemain, PWSTR Roo
|
||||
FSP_API VOID FspPathSuffix(PWSTR Path, PWSTR *PRemain, PWSTR *PSuffix, PWSTR Root);
|
||||
FSP_API VOID FspPathCombine(PWSTR Prefix, PWSTR Suffix);
|
||||
|
||||
/*
|
||||
* Service Framework
|
||||
*/
|
||||
typedef struct _FSP_SERVICE FSP_SERVICE;
|
||||
typedef NTSTATUS FSP_SERVICE_START(FSP_SERVICE *, ULONG, PWSTR *);
|
||||
typedef NTSTATUS FSP_SERVICE_STOP(FSP_SERVICE *);
|
||||
typedef NTSTATUS FSP_SERVICE_CONTROL(FSP_SERVICE *, ULONG, ULONG, PVOID);
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4200) /* zero-sized array in struct/union */
|
||||
typedef struct _FSP_SERVICE
|
||||
{
|
||||
UINT16 Version;
|
||||
PVOID UserContext;
|
||||
FSP_SERVICE_START *OnStart;
|
||||
FSP_SERVICE_STOP *OnStop;
|
||||
FSP_SERVICE_CONTROL *OnControl;
|
||||
ULONG AcceptControl;
|
||||
ULONG ExitCode;
|
||||
SERVICE_STATUS_HANDLE StatusHandle;
|
||||
CRITICAL_SECTION ServiceStatusGuard;
|
||||
SERVICE_STATUS ServiceStatus;
|
||||
BOOLEAN AllowInteractive;
|
||||
HANDLE InteractiveEvent;
|
||||
WCHAR ServiceName[];
|
||||
} FSP_SERVICE;
|
||||
#pragma warning(pop)
|
||||
FSP_API NTSTATUS FspServiceCreate(PWSTR ServiceName,
|
||||
FSP_SERVICE_START *OnStart,
|
||||
FSP_SERVICE_STOP *OnStop,
|
||||
FSP_SERVICE_CONTROL *OnControl,
|
||||
FSP_SERVICE **PService);
|
||||
FSP_API VOID FspServiceDelete(FSP_SERVICE *Service);
|
||||
FSP_API VOID FspServiceAllowInteractive(FSP_SERVICE *Service);
|
||||
FSP_API VOID FspServiceAcceptControl(FSP_SERVICE *Service, ULONG Control);
|
||||
FSP_API VOID FspServiceRequestTime(FSP_SERVICE *Service, ULONG Time);
|
||||
FSP_API VOID FspServiceSetExitCode(FSP_SERVICE *Service, ULONG ExitCode);
|
||||
FSP_API NTSTATUS FspServiceRun(FSP_SERVICE *Service);
|
||||
FSP_API VOID FspServiceStop(FSP_SERVICE *Service);
|
||||
|
||||
/*
|
||||
* Utility
|
||||
*/
|
||||
FSP_API NTSTATUS FspNtStatusFromWin32(DWORD Error);
|
||||
FSP_API DWORD FspWin32FromNtStatus(NTSTATUS Status);
|
||||
FSP_API VOID FspEventLog(ULONG Type, PWSTR Format, ...);
|
||||
FSP_API VOID FspEventLogV(ULONG Type, PWSTR Format, va_list ap);
|
||||
FSP_API VOID FspDebugLog(const char *format, ...);
|
||||
FSP_API VOID FspDebugLogSD(const char *format, PSECURITY_DESCRIPTOR SecurityDescriptor);
|
||||
FSP_API VOID FspDebugLogFT(const char *format, PFILETIME FileTime);
|
||||
|
56
src/dll/eventlog.c
Normal file
56
src/dll/eventlog.c
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @file dll/eventlog.c
|
||||
*
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the
|
||||
* GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
static HANDLE FspEventLogHandle;
|
||||
static INIT_ONCE FspEventLogInitOnce = INIT_ONCE_STATIC_INIT;
|
||||
static BOOL WINAPI FspEventLogRegisterEventSource(
|
||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context);
|
||||
|
||||
FSP_API VOID FspEventLog(ULONG Type, PWSTR Format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, Format);
|
||||
FspEventLogV(Type, Format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
FSP_API VOID FspEventLogV(ULONG Type, PWSTR Format, va_list ap)
|
||||
{
|
||||
InitOnceExecuteOnce(&FspEventLogInitOnce, FspEventLogRegisterEventSource, 0, 0);
|
||||
if (0 == FspEventLogHandle)
|
||||
return;
|
||||
|
||||
WCHAR Buf[1024], *Strings[1];
|
||||
/* wvsprintfW is only safe with a 1024 WCHAR buffer */
|
||||
|
||||
wvsprintfW(Buf, Format, ap);
|
||||
Buf[(sizeof Buf / sizeof Buf[0]) - 1] = L'\0';
|
||||
|
||||
Strings[0] = Buf;
|
||||
ReportEventW(FspEventLogHandle, (WORD)Type, 0, 1, 0, 1, 0, Strings, 0);
|
||||
}
|
||||
|
||||
static BOOL WINAPI FspEventLogRegisterEventSource(
|
||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||
{
|
||||
FspEventLogHandle = RegisterEventSourceW(0, L"" LIBRARY_NAME);
|
||||
return TRUE;
|
||||
}
|
@ -29,6 +29,7 @@ BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
|
||||
ProcessHeap = GetProcessHeap();
|
||||
if (0 == ProcessHeap)
|
||||
return FALSE;
|
||||
FspNtStatusInitialize();
|
||||
FspFileSystemInitialize();
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
|
@ -103,6 +103,8 @@ BOOLEAN RemoveEntryList(PLIST_ENTRY Entry)
|
||||
return Flink == Blink;
|
||||
}
|
||||
|
||||
VOID FspNtStatusInitialize(VOID);
|
||||
|
||||
VOID FspFileSystemInitialize(VOID);
|
||||
VOID FspFileSystemFinalize(VOID);
|
||||
|
||||
|
@ -17,6 +17,25 @@
|
||||
|
||||
#include <dll/library.h>
|
||||
|
||||
static ULONG (WINAPI *FspRtlNtStatusToDosError)(NTSTATUS Status);
|
||||
|
||||
VOID FspNtStatusInitialize(VOID)
|
||||
{
|
||||
/*
|
||||
* This function is called during DLL_PROCESS_ATTACH. We must therefore keep initialization
|
||||
* tasks to a minimum.
|
||||
*
|
||||
* GetModuleHandle/GetProcAddress is allowed (because they are kernel32 API's)! See:
|
||||
* https://msdn.microsoft.com/en-us/library/windows/desktop/dn633971(v=vs.85).aspx
|
||||
*/
|
||||
|
||||
HANDLE Handle;
|
||||
|
||||
Handle = GetModuleHandleW(L"ntdll.dll");
|
||||
if (0 != Handle)
|
||||
FspRtlNtStatusToDosError = (PVOID)GetProcAddress(Handle, "RtlNtStatusToDosError");
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspNtStatusFromWin32(DWORD Error)
|
||||
{
|
||||
switch (Error)
|
||||
@ -26,3 +45,11 @@ FSP_API NTSTATUS FspNtStatusFromWin32(DWORD Error)
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
|
||||
FSP_API DWORD FspWin32FromNtStatus(NTSTATUS Status)
|
||||
{
|
||||
if (0 == FspRtlNtStatusToDosError)
|
||||
return ERROR_MR_MID_NOT_FOUND;
|
||||
|
||||
return FspRtlNtStatusToDosError(Status);
|
||||
}
|
||||
|
418
src/dll/service.c
Normal file
418
src/dll/service.c
Normal file
@ -0,0 +1,418 @@
|
||||
/**
|
||||
* @file dll/service.c
|
||||
*
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the
|
||||
* GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
|
||||
// !!!: NOTIMPLEMENTED
|
||||
#define FspEventLog(Type, Message, ...)
|
||||
|
||||
enum
|
||||
{
|
||||
SetStatus_ServiceType = 0x0001,
|
||||
SetStatus_CurrentState = 0x0002,
|
||||
SetStatus_ControlsAccepted = 0x0004,
|
||||
SetStatus_Win32ExitCode = 0x0008,
|
||||
SetStatus_ServiceSpecificExitCode = 0x0010,
|
||||
SetStatus_CheckPoint = 0x0020,
|
||||
SetStatus_WaitHint = 0x0040,
|
||||
GetStatus_ServiceType = 0x0100,
|
||||
GetStatus_CurrentState = 0x0200,
|
||||
GetStatus_ControlsAccepted = 0x0400,
|
||||
GetStatus_Win32ExitCode = 0x0800,
|
||||
GetStatus_ServiceSpecificExitCode = 0x1000,
|
||||
GetStatus_CheckPoint = 0x2000,
|
||||
GetStatus_WaitHint = 0x4000,
|
||||
};
|
||||
|
||||
static SERVICE_TABLE_ENTRYW *FspServiceTable;
|
||||
static VOID FspServiceSetStatus(FSP_SERVICE *Service, ULONG Flags, SERVICE_STATUS *ServiceStatus);
|
||||
static VOID WINAPI FspServiceEntry(DWORD Argc, PWSTR *Argv);
|
||||
static VOID FspServiceMain(FSP_SERVICE *Service, DWORD Argc, PWSTR *Argv);
|
||||
static DWORD WINAPI FspServiceCtrlHandler(
|
||||
DWORD Control, DWORD EventType, PVOID EventData, PVOID Context);
|
||||
static DWORD WINAPI FspServiceStopRoutine(PVOID Context);
|
||||
static DWORD WINAPI FspServiceInteractiveThread(PVOID Context);
|
||||
static BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType);
|
||||
|
||||
static inline FSP_SERVICE *FspServiceFromTable(VOID)
|
||||
{
|
||||
FSP_SERVICE *Service = 0;
|
||||
|
||||
if (0 != FspServiceTable)
|
||||
{
|
||||
Service = (PVOID)((PUINT8)FspServiceTable[0].lpServiceName -
|
||||
FIELD_OFFSET(FSP_SERVICE, ServiceName));
|
||||
FspServiceTable = 0;
|
||||
}
|
||||
|
||||
return Service;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspServiceCreate(PWSTR ServiceName,
|
||||
FSP_SERVICE_START *OnStart,
|
||||
FSP_SERVICE_STOP *OnStop,
|
||||
FSP_SERVICE_CONTROL *OnControl,
|
||||
FSP_SERVICE **PService)
|
||||
{
|
||||
FSP_SERVICE *Service;
|
||||
DWORD Size;
|
||||
|
||||
*PService = 0;
|
||||
|
||||
Size = (lstrlenW(ServiceName) + 1) * sizeof(WCHAR);
|
||||
|
||||
Service = MemAlloc(sizeof *Service + Size);
|
||||
if (0 == Service)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
memset(Service, 0, sizeof *Service);
|
||||
memcpy(Service->ServiceName, ServiceName, Size);
|
||||
|
||||
Service->OnStart = OnStart;
|
||||
Service->OnStop = OnStop;
|
||||
Service->OnControl = OnControl;
|
||||
|
||||
Service->AcceptControl = OnStop ? SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN : 0;
|
||||
|
||||
InitializeCriticalSection(&Service->ServiceStatusGuard);
|
||||
Service->ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||
Service->ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
Service->ServiceStatus.dwControlsAccepted = 0;
|
||||
Service->ServiceStatus.dwWin32ExitCode = NO_ERROR;
|
||||
Service->ServiceStatus.dwServiceSpecificExitCode = 0;
|
||||
Service->ServiceStatus.dwCheckPoint = 0;
|
||||
Service->ServiceStatus.dwWaitHint = 0;
|
||||
|
||||
*PService = Service;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
FSP_API VOID FspServiceDelete(FSP_SERVICE *Service)
|
||||
{
|
||||
if (0 != Service->InteractiveEvent)
|
||||
CloseHandle(Service->InteractiveEvent);
|
||||
|
||||
DeleteCriticalSection(&Service->ServiceStatusGuard);
|
||||
MemFree(Service);
|
||||
}
|
||||
|
||||
static VOID FspServiceSetStatus(FSP_SERVICE *Service, ULONG Flags, SERVICE_STATUS *ServiceStatus)
|
||||
{
|
||||
#define XCHG(FIELD)\
|
||||
if (Flags & SetStatus_##FIELD)\
|
||||
{\
|
||||
DWORD Temp = ServiceStatus->dw##FIELD;\
|
||||
if (Flags & GetStatus_##FIELD)\
|
||||
ServiceStatus->dw##FIELD = Service->ServiceStatus.dw##FIELD;\
|
||||
Service->ServiceStatus.dw##FIELD = Temp;\
|
||||
}
|
||||
|
||||
EnterCriticalSection(&Service->ServiceStatusGuard);
|
||||
|
||||
//XCHG(ServiceType);
|
||||
XCHG(CurrentState);
|
||||
XCHG(ControlsAccepted);
|
||||
XCHG(Win32ExitCode);
|
||||
//XCHG(ServiceSpecificExitCode);
|
||||
if (Flags & SetStatus_CheckPoint)
|
||||
{
|
||||
DWORD Temp = ServiceStatus->dwCheckPoint;
|
||||
if (Flags & GetStatus_CheckPoint)
|
||||
ServiceStatus->dwCheckPoint = Service->ServiceStatus.dwCheckPoint;
|
||||
|
||||
/* treat CheckPoint specially! */
|
||||
if (0 == Temp)
|
||||
Service->ServiceStatus.dwCheckPoint = 0;
|
||||
else
|
||||
Service->ServiceStatus.dwCheckPoint += Temp;
|
||||
}
|
||||
XCHG(WaitHint);
|
||||
|
||||
if (0 != Service->StatusHandle)
|
||||
{
|
||||
if (!SetServiceStatus(Service->StatusHandle, &Service->ServiceStatus))
|
||||
FspEventLog(EVENTLOG_ERROR_TYPE,
|
||||
L"" __FUNCTION__ ": error = %ld", GetLastError());
|
||||
}
|
||||
else if (0 != Service->InteractiveEvent &&
|
||||
SERVICE_STOPPED == Service->ServiceStatus.dwCurrentState)
|
||||
{
|
||||
SetEvent(Service->InteractiveEvent);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&Service->ServiceStatusGuard);
|
||||
|
||||
#undef XCHG
|
||||
}
|
||||
|
||||
FSP_API VOID FspServiceAllowInteractive(FSP_SERVICE *Service)
|
||||
{
|
||||
Service->AllowInteractive = TRUE;
|
||||
}
|
||||
|
||||
FSP_API VOID FspServiceAcceptControl(FSP_SERVICE *Service, ULONG Control)
|
||||
{
|
||||
Service->AcceptControl = Control & ~SERVICE_ACCEPT_PAUSE_CONTINUE;
|
||||
}
|
||||
|
||||
FSP_API VOID FspServiceRequestTime(FSP_SERVICE *Service, ULONG Time)
|
||||
{
|
||||
SERVICE_STATUS ServiceStatus;
|
||||
|
||||
ServiceStatus.dwCheckPoint = +1;
|
||||
ServiceStatus.dwWaitHint = Time;
|
||||
FspServiceSetStatus(Service,
|
||||
SetStatus_CheckPoint | SetStatus_WaitHint, &ServiceStatus);
|
||||
}
|
||||
|
||||
FSP_API VOID FspServiceSetExitCode(FSP_SERVICE *Service, ULONG ExitCode)
|
||||
{
|
||||
Service->ExitCode = ExitCode;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspServiceRun(FSP_SERVICE *Service)
|
||||
{
|
||||
SERVICE_TABLE_ENTRYW ServiceTable[2];
|
||||
|
||||
ServiceTable[0].lpServiceName = Service->ServiceName;
|
||||
ServiceTable[0].lpServiceProc = FspServiceEntry;
|
||||
ServiceTable[1].lpServiceName = 0;
|
||||
ServiceTable[1].lpServiceProc = 0;
|
||||
FspServiceTable = ServiceTable;
|
||||
|
||||
if (!StartServiceCtrlDispatcherW(ServiceTable))
|
||||
{
|
||||
HANDLE Thread;
|
||||
DWORD WaitResult;
|
||||
DWORD LastError;
|
||||
|
||||
LastError = GetLastError();
|
||||
if (!Service->AllowInteractive || ERROR_FAILED_SERVICE_CONTROLLER_CONNECT != LastError)
|
||||
return FspNtStatusFromWin32(LastError);
|
||||
|
||||
/* enter INTERACTIVE (DEBUG) mode! */
|
||||
|
||||
Service->InteractiveEvent = CreateEventW(0, TRUE, FALSE, 0);
|
||||
if (0 == Service->InteractiveEvent)
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
|
||||
Thread = CreateThread(0, 0, FspServiceInteractiveThread, Service, 0, 0);
|
||||
if (0 == Thread)
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
WaitResult = WaitForSingleObject(Thread, INFINITE);
|
||||
CloseHandle(Thread);
|
||||
if (WAIT_OBJECT_0 != WaitResult)
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
|
||||
if (!SetConsoleCtrlHandler(FspServiceConsoleCtrlHandler, TRUE))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
|
||||
WaitResult = WaitForSingleObject(Service->InteractiveEvent, INFINITE);
|
||||
if (WAIT_OBJECT_0 != WaitResult)
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
FSP_API VOID FspServiceStop(FSP_SERVICE *Service)
|
||||
{
|
||||
SERVICE_STATUS ServiceStatus;
|
||||
NTSTATUS Result;
|
||||
|
||||
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
||||
ServiceStatus.dwCheckPoint = 0;
|
||||
ServiceStatus.dwWaitHint = 0;
|
||||
FspServiceSetStatus(Service,
|
||||
SetStatus_CurrentState | SetStatus_CheckPoint | SetStatus_WaitHint |
|
||||
GetStatus_CurrentState | GetStatus_CheckPoint | GetStatus_WaitHint,
|
||||
&ServiceStatus);
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
if (0 != Service->OnStop)
|
||||
Result = Service->OnStop(Service);
|
||||
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
ServiceStatus.dwWin32ExitCode = Service->ExitCode;
|
||||
FspServiceSetStatus(Service,
|
||||
SetStatus_CurrentState | SetStatus_Win32ExitCode, &ServiceStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* revert the service status */
|
||||
FspServiceSetStatus(Service,
|
||||
SetStatus_CurrentState | SetStatus_CheckPoint | SetStatus_WaitHint,
|
||||
&ServiceStatus);
|
||||
}
|
||||
}
|
||||
|
||||
static VOID WINAPI FspServiceEntry(DWORD Argc, PWSTR *Argv)
|
||||
{
|
||||
FSP_SERVICE *Service;
|
||||
|
||||
Service = FspServiceFromTable();
|
||||
if (0 == Service)
|
||||
{
|
||||
FspEventLog(EVENTLOG_ERROR_TYPE,
|
||||
L"" __FUNCTION__ ": internal error: FspServiceFromTable = 0");
|
||||
return;
|
||||
}
|
||||
|
||||
Service->StatusHandle = RegisterServiceCtrlHandlerExW(Service->ServiceName,
|
||||
FspServiceCtrlHandler, Service);
|
||||
if (0 == Service->StatusHandle)
|
||||
{
|
||||
FspEventLog(EVENTLOG_ERROR_TYPE,
|
||||
L"" __FUNCTION__ ": RegisterServiceCtrlHandlerW = %ld", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
FspServiceMain(Service, Argc, Argv);
|
||||
}
|
||||
|
||||
static VOID FspServiceMain(FSP_SERVICE *Service, DWORD Argc, PWSTR *Argv)
|
||||
{
|
||||
SERVICE_STATUS ServiceStatus;
|
||||
NTSTATUS Result;
|
||||
|
||||
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
|
||||
ServiceStatus.dwControlsAccepted = 0;
|
||||
ServiceStatus.dwCheckPoint = 0;
|
||||
ServiceStatus.dwWaitHint = 0;
|
||||
FspServiceSetStatus(Service,
|
||||
SetStatus_CurrentState | SetStatus_ControlsAccepted | SetStatus_CheckPoint | SetStatus_WaitHint,
|
||||
&ServiceStatus);
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
if (0 != Service->OnStart)
|
||||
Result = Service->OnStart(Service, Argc, Argv);
|
||||
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
||||
ServiceStatus.dwControlsAccepted = Service->AcceptControl;
|
||||
FspServiceSetStatus(Service,
|
||||
SetStatus_CurrentState | SetStatus_ControlsAccepted, &ServiceStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
ServiceStatus.dwWin32ExitCode = FspWin32FromNtStatus(Result);
|
||||
FspServiceSetStatus(Service,
|
||||
SetStatus_CurrentState | SetStatus_Win32ExitCode, &ServiceStatus);
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD WINAPI FspServiceCtrlHandler(
|
||||
DWORD Control, DWORD EventType, PVOID EventData, PVOID Context)
|
||||
{
|
||||
FSP_SERVICE *Service = Context;
|
||||
NTSTATUS Result;
|
||||
|
||||
switch (Control)
|
||||
{
|
||||
case SERVICE_CONTROL_SHUTDOWN:
|
||||
Result = STATUS_NOT_IMPLEMENTED;
|
||||
if (0 != Service->OnControl)
|
||||
Result = Service->OnControl(Service, Control, EventType, EventData);
|
||||
if (STATUS_NOT_IMPLEMENTED != Result)
|
||||
return FspWin32FromNtStatus(Result);
|
||||
/* fall through */
|
||||
|
||||
case SERVICE_CONTROL_STOP:
|
||||
if (!QueueUserWorkItem(FspServiceStopRoutine, Service, WT_EXECUTEDEFAULT))
|
||||
FspServiceStopRoutine(Service);
|
||||
return NO_ERROR;
|
||||
|
||||
case SERVICE_CONTROL_PAUSE:
|
||||
case SERVICE_CONTROL_CONTINUE:
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
|
||||
case SERVICE_CONTROL_INTERROGATE:
|
||||
return NO_ERROR;
|
||||
|
||||
default:
|
||||
Result = STATUS_SUCCESS;
|
||||
if (0 != Service->OnControl)
|
||||
Result = Service->OnControl(Service, Control, EventType, EventData);
|
||||
return FspWin32FromNtStatus(Result);
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD WINAPI FspServiceStopRoutine(PVOID Context)
|
||||
{
|
||||
FSP_SERVICE *Service = Context;
|
||||
|
||||
FspServiceStop(Service);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD WINAPI FspServiceInteractiveThread(PVOID Context)
|
||||
{
|
||||
FSP_SERVICE *Service;
|
||||
PWSTR Args[2] = { 0, 0 };
|
||||
PWSTR *Argv;
|
||||
DWORD Argc;
|
||||
|
||||
Service = FspServiceFromTable();
|
||||
if (0 == Service)
|
||||
{
|
||||
FspEventLog(EVENTLOG_ERROR_TYPE,
|
||||
L"" __FUNCTION__ ": internal error: FspServiceFromTable = 0");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
|
||||
if (0 == Argv)
|
||||
{
|
||||
Argv = Args;
|
||||
Argc = 1;
|
||||
}
|
||||
Argv[0] = Service->ServiceName;
|
||||
|
||||
FspServiceMain(Service, Argc, Argv);
|
||||
|
||||
if (Args != Argv)
|
||||
LocalFree(Argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType)
|
||||
{
|
||||
FSP_SERVICE *Service;
|
||||
|
||||
Service = FspServiceFromTable();
|
||||
if (0 == Service)
|
||||
{
|
||||
FspEventLog(EVENTLOG_ERROR_TYPE,
|
||||
L"" __FUNCTION__ ": internal error: FspServiceFromTable = 0");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (CtrlType)
|
||||
{
|
||||
case CTRL_SHUTDOWN_EVENT:
|
||||
FspServiceCtrlHandler(SERVICE_CONTROL_SHUTDOWN, 0, 0, Service);
|
||||
return TRUE;
|
||||
default:
|
||||
FspServiceCtrlHandler(SERVICE_CONTROL_STOP, 0, 0, Service);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user