mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 16:33:02 -05:00
192 lines
6.0 KiB
C#
192 lines
6.0 KiB
C#
/*
|
|
* dotnet/Service.cs
|
|
*
|
|
* Copyright 2015-2022 Bill Zissimopoulos
|
|
*/
|
|
/*
|
|
* This file is part of WinFsp.
|
|
*
|
|
* You can redistribute it and/or modify it under the terms of the GNU
|
|
* General Public License version 3 as published by the Free Software
|
|
* Foundation.
|
|
*
|
|
* Licensees holding a valid commercial license may use this software
|
|
* in accordance with the commercial license agreement provided in
|
|
* conjunction with the software. The terms and conditions of any such
|
|
* commercial license agreement shall govern, supersede, and render
|
|
* ineffective any application of the GPLv3 license to this software,
|
|
* notwithstanding of any reference thereto in the software or
|
|
* associated repository.
|
|
*/
|
|
|
|
using System;
|
|
|
|
using Fsp.Interop;
|
|
|
|
namespace Fsp
|
|
{
|
|
|
|
/// <summary>
|
|
/// Provides the base class for a process that can be run as a service,
|
|
/// command line application or under the control of the WinFsp launcher.
|
|
/// </summary>
|
|
public class Service
|
|
{
|
|
/* const */
|
|
public const UInt32 EVENTLOG_ERROR_TYPE = 0x0001;
|
|
public const UInt32 EVENTLOG_WARNING_TYPE = 0x0002;
|
|
public const UInt32 EVENTLOG_INFORMATION_TYPE = 0x0004;
|
|
|
|
/* ctor/dtor */
|
|
/// <summary>
|
|
/// Creates an instance of the Service class.
|
|
/// </summary>
|
|
/// <param name="ServiceName">The name of the service.</param>
|
|
public Service(String ServiceName)
|
|
{
|
|
Api.FspServiceCreate(ServiceName, _OnStart, _OnStop, null, out _ServicePtr);
|
|
if (IntPtr.Zero != _ServicePtr)
|
|
Api.SetUserContext(_ServicePtr, this);
|
|
}
|
|
~Service()
|
|
{
|
|
if (IntPtr.Zero != _ServicePtr)
|
|
{
|
|
Api.DisposeUserContext(_ServicePtr);
|
|
Api.FspServiceDelete(_ServicePtr);
|
|
}
|
|
}
|
|
|
|
/* control */
|
|
/// <summary>
|
|
/// Runs a service.
|
|
/// </summary>
|
|
/// <returns>Service process exit code.</returns>
|
|
public int Run()
|
|
{
|
|
if (IntPtr.Zero == _ServicePtr)
|
|
{
|
|
const Int32 STATUS_INSUFFICIENT_RESOURCES = unchecked((Int32)0xc000009a);
|
|
Log(EVENTLOG_ERROR_TYPE,
|
|
String.Format("The service {0} cannot be created (Status={1:X}).",
|
|
GetType().FullName, STATUS_INSUFFICIENT_RESOURCES));
|
|
return (int)Api.FspWin32FromNtStatus(STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
Api.FspServiceAllowConsoleMode(_ServicePtr);
|
|
Int32 Result = Api.FspServiceLoop(_ServicePtr);
|
|
int ExitCode = (int)Api.FspServiceGetExitCode(_ServicePtr);
|
|
if (0 > Result)
|
|
{
|
|
Log(EVENTLOG_ERROR_TYPE,
|
|
String.Format("The service {0} has failed to run (Status={1:X}).",
|
|
GetType().FullName, Result));
|
|
return (int)Api.FspWin32FromNtStatus(Result);
|
|
}
|
|
return ExitCode;
|
|
}
|
|
/// <summary>
|
|
/// Stops a running service.
|
|
/// </summary>
|
|
public void Stop()
|
|
{
|
|
if (IntPtr.Zero == _ServicePtr)
|
|
throw new InvalidOperationException();
|
|
Api.FspServiceStop(_ServicePtr);
|
|
}
|
|
public void RequestTime(UInt32 Time)
|
|
{
|
|
if (IntPtr.Zero == _ServicePtr)
|
|
throw new InvalidOperationException();
|
|
Api.FspServiceRequestTime(_ServicePtr, Time);
|
|
}
|
|
/// <summary>
|
|
/// Gets or sets the service process exit code.
|
|
/// </summary>
|
|
public int ExitCode
|
|
{
|
|
get
|
|
{
|
|
if (IntPtr.Zero == _ServicePtr)
|
|
throw new InvalidOperationException();
|
|
return (int)Api.FspServiceGetExitCode(_ServicePtr);
|
|
}
|
|
set
|
|
{
|
|
if (IntPtr.Zero == _ServicePtr)
|
|
throw new InvalidOperationException();
|
|
Api.FspServiceSetExitCode(_ServicePtr, (UInt32)value);
|
|
}
|
|
}
|
|
public IntPtr ServiceHandle
|
|
{
|
|
get { return _ServicePtr; }
|
|
}
|
|
public static void Log(UInt32 Type, String Message)
|
|
{
|
|
Api.FspServiceLog(Type, "%s", Message);
|
|
}
|
|
|
|
/* start/stop */
|
|
/// <summary>
|
|
/// Provides a means to customize the returned status code when an exception happens.
|
|
/// </summary>
|
|
/// <param name="ex"></param>
|
|
/// <returns>STATUS_SUCCESS or error code.</returns>
|
|
protected virtual Int32 ExceptionHandler(Exception ex)
|
|
{
|
|
return unchecked((Int32)0xE0434f4D)/*STATUS_CLR_EXCEPTION*/;
|
|
}
|
|
/// <summary>
|
|
/// Occurs when the service starts.
|
|
/// </summary>
|
|
/// <param name="Args">Command line arguments passed to the service.</param>
|
|
protected virtual void OnStart(String[] Args)
|
|
{
|
|
}
|
|
/// <summary>
|
|
/// Occurs when the service stops.
|
|
/// </summary>
|
|
protected virtual void OnStop()
|
|
{
|
|
}
|
|
|
|
/* callbacks */
|
|
private static Int32 OnStart(
|
|
IntPtr Service,
|
|
UInt32 Argc,
|
|
String[] Argv)
|
|
{
|
|
Service self = (Service)Api.GetUserContext(Service);
|
|
try
|
|
{
|
|
self.OnStart(
|
|
Argv);
|
|
return 0/*STATUS_SUCCESS*/;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return self.ExceptionHandler(ex);
|
|
}
|
|
}
|
|
private static Int32 OnStop(
|
|
IntPtr Service)
|
|
{
|
|
Service self = (Service)Api.GetUserContext(Service);
|
|
try
|
|
{
|
|
self.OnStop();
|
|
return 0/*STATUS_SUCCESS*/;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return self.ExceptionHandler(ex);
|
|
}
|
|
}
|
|
|
|
private static Api.Proto.ServiceStart _OnStart = OnStart;
|
|
private static Api.Proto.ServiceStop _OnStop = OnStop;
|
|
private IntPtr _ServicePtr;
|
|
}
|
|
|
|
}
|