Example #1
0
 public static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, out SafeTokenHandle TokenHandle);
Example #2
0
 public static extern bool AdjustTokenPrivileges(SafeTokenHandle TokenHandle,
                                                 [MarshalAs(UnmanagedType.Bool)] bool DisableAllPrivileges,
                                                 ref TOKEN_PRIVILEGES NewState,
                                                 UInt32 BufferLength,
                                                 IntPtr PreviousState,
                                                 IntPtr ReturnLength);
Example #3
0
 public static extern SafeTokenHandle OpenService(SafeTokenHandle hSCManager, string lpServiceName, uint dwDesiredAccess);
Example #4
0
 public static extern bool ChangeServiceConfig2(SafeTokenHandle serviceHandle, uint infoLevel,
                                                IntPtr lpInfo);
Example #5
0
 public static extern bool AdjustTokenPrivileges(SafeTokenHandle TokenHandle,
     [MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
     ref TOKEN_PRIVILEGES NewState,
     UInt32 BufferLength,
     IntPtr PreviousState,
     IntPtr ReturnLength);
Example #6
0
 public static extern bool CloseServiceHandle(SafeTokenHandle hSCObject);
Example #7
0
 public static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, out SafeTokenHandle TokenHandle);
Example #8
0
 public static extern bool ChangeServiceConfig2(SafeTokenHandle serviceHandle, uint infoLevel,
     IntPtr lpInfo);
Example #9
0
 public static extern SafeTokenHandle OpenService(SafeTokenHandle hSCManager, string lpServiceName, uint dwDesiredAccess);
Example #10
0
 public static extern bool CloseServiceHandle(SafeTokenHandle hSCObject);
        public void SetServiceRecoveryOptions(HostSettings settings, ServiceRecoveryOptions options)
        {
            SafeTokenHandle scmHandle     = null;
            SafeTokenHandle serviceHandle = null;
            IntPtr          lpsaActions   = IntPtr.Zero;
            IntPtr          lpInfo        = IntPtr.Zero;
            IntPtr          lpFlagInfo    = IntPtr.Zero;

            try
            {
                List <NativeMethods.SC_ACTION> actions = options.Actions.Select(x => x.GetAction()).ToList();
                if (actions.Count == 0)
                {
                    throw new TopshelfException("Must be at least one failure action configured");
                }

                scmHandle = NativeMethods.OpenSCManager(null, null, (int)NativeMethods.SCM_ACCESS.SC_MANAGER_ALL_ACCESS);
                if (scmHandle == null)
                {
                    throw new TopshelfException("Failed to open service control manager");
                }

                serviceHandle = NativeMethods.OpenService(scmHandle, settings.ServiceName,
                                                          (int)NativeMethods.SCM_ACCESS.SC_MANAGER_ALL_ACCESS);
                if (serviceHandle == null)
                {
                    throw new TopshelfException("Failed to open service: " + settings.ServiceName);
                }

                int actionSize = Marshal.SizeOf(typeof(NativeMethods.SC_ACTION));
                lpsaActions = Marshal.AllocHGlobal(actionSize * actions.Count + 1);
                if (lpsaActions == IntPtr.Zero)
                {
                    throw new TopshelfException("Unable to allocate memory for service recovery actions");
                }

                IntPtr nextAction = lpsaActions;
                for (int i = 0; i < actions.Count; i++)
                {
                    Marshal.StructureToPtr(actions[i], nextAction, false);
                    nextAction = (IntPtr)(nextAction.ToInt64() + actionSize);
                }

                var finalAction = new NativeMethods.SC_ACTION();
                finalAction.Type  = (int)NativeMethods.SC_ACTION_TYPE.None;
                finalAction.Delay = (int)TimeSpan.FromMinutes(1).TotalMilliseconds;

                Marshal.StructureToPtr(finalAction, nextAction, false);

                string rebootMessage = options.Actions.Where(x => x.GetType() == typeof(RestartSystemRecoveryAction))
                                       .OfType <RestartSystemRecoveryAction>().Select(x => x.RestartMessage).
                                       FirstOrDefault() ?? "";

                string runProgramCommand = options.Actions.Where(x => x.GetType() == typeof(RunProgramRecoveryAction))
                                           .OfType <RunProgramRecoveryAction>().Select(x => x.Command).
                                           FirstOrDefault() ?? "";


                var failureActions = new NativeMethods.SERVICE_FAILURE_ACTIONS();
                failureActions.dwResetPeriod =
                    (int)TimeSpan.FromDays(options.ResetPeriod).TotalSeconds;
                failureActions.lpRebootMsg = rebootMessage;
                failureActions.lpCommand   = runProgramCommand;
                failureActions.cActions    = actions.Count + 1;
                failureActions.actions     = lpsaActions;

                lpInfo = Marshal.AllocHGlobal(Marshal.SizeOf(failureActions));
                if (lpInfo == IntPtr.Zero)
                {
                    throw new TopshelfException("Failed to allocate memory for failure actions");
                }

                Marshal.StructureToPtr(failureActions, lpInfo, false);

                // If user specified a Restart option, get shutdown privileges
                if (options.Actions.Any(x => x.GetType() == typeof(RestartSystemRecoveryAction)))
                {
                    RequestShutdownPrivileges();
                }

                if (!NativeMethods.ChangeServiceConfig2(serviceHandle,
                                                        NativeMethods.SERVICE_CONFIG_FAILURE_ACTIONS, lpInfo))
                {
                    throw new TopshelfException(string.Format("Failed to change service recovery options. Windows Error: {0}", new Win32Exception().Message));
                }

                if (false == options.RecoverOnCrashOnly)
                {
                    var flag = new NativeMethods.SERVICE_FAILURE_ACTIONS_FLAG();
                    flag.fFailureActionsOnNonCrashFailures = true;

                    lpFlagInfo = Marshal.AllocHGlobal(Marshal.SizeOf(flag));
                    if (lpFlagInfo == IntPtr.Zero)
                    {
                        throw new TopshelfException("Failed to allocate memory for failure flag");
                    }

                    Marshal.StructureToPtr(flag, lpFlagInfo, false);

                    try
                    {
                        NativeMethods.ChangeServiceConfig2(serviceHandle,
                                                           NativeMethods.SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, lpFlagInfo);
                    }
                    catch
                    {
                        // this fails on XP, but we don't care really as it's optional
                    }
                }
            }
            finally
            {
                if (lpFlagInfo != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(lpFlagInfo);
                }
                if (lpInfo != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(lpInfo);
                }
                if (lpsaActions != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(lpsaActions);
                }
                if (serviceHandle != null)
                {
                    NativeMethods.CloseServiceHandle(serviceHandle);
                }
                if (scmHandle != null)
                {
                    NativeMethods.CloseServiceHandle(scmHandle);
                }
            }
        }