Advapi32.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. // ReSharper disable InconsistentNaming
  7. namespace winsw
  8. {
  9. class ServiceManager : IDisposable
  10. {
  11. private IntPtr _handle;
  12. public ServiceManager()
  13. {
  14. _handle = Advapi32.OpenSCManager(null, null, (uint)SCM_ACCESS.SC_MANAGER_ALL_ACCESS);
  15. if (_handle == IntPtr.Zero)
  16. {
  17. throw new Exception(String.Format("Error connecting to Service Control Manager. Error provided was: 0x{0:X}", Marshal.GetLastWin32Error()));
  18. }
  19. }
  20. public Service Open(string serviceName)
  21. {
  22. IntPtr svcHandle = Advapi32.OpenService(_handle, serviceName, (int)SERVICE_ACCESS.SERVICE_ALL_ACCESS);
  23. if (svcHandle == IntPtr.Zero)
  24. {
  25. throw new Exception(String.Format("Error opening service for modifying. Error returned was: 0x{0:X}", Marshal.GetLastWin32Error()));
  26. }
  27. return new Service(svcHandle);
  28. }
  29. public void Dispose()
  30. {
  31. if (_handle != IntPtr.Zero)
  32. Advapi32.CloseServiceHandle(_handle);
  33. _handle = IntPtr.Zero;
  34. }
  35. }
  36. class Service : IDisposable
  37. {
  38. internal IntPtr Handle;
  39. internal Service(IntPtr service)
  40. {
  41. Handle = service;
  42. }
  43. public void ChangeConfig(TimeSpan failureResetPeriod, List<SC_ACTION> actions)
  44. {
  45. SERVICE_FAILURE_ACTIONS sfa = new SERVICE_FAILURE_ACTIONS
  46. {
  47. dwResetPeriod = (int) failureResetPeriod.TotalSeconds,
  48. lpRebootMsg = "",
  49. lpCommand = ""
  50. };
  51. // delete message
  52. // delete the command to run
  53. int len = Marshal.SizeOf(typeof(SC_ACTION));
  54. sfa.cActions = actions.Count;
  55. sfa.lpsaActions = Marshal.AllocHGlobal(len * actions.Count);
  56. try
  57. {
  58. for (int i = 0; i < actions.Count; i++)
  59. {
  60. Marshal.StructureToPtr(actions[i], new IntPtr(sfa.lpsaActions.ToInt64() + i * len), false);
  61. }
  62. if (!Advapi32.ChangeServiceConfig2(Handle, SERVICE_CONFIG_INFOLEVEL.SERVICE_CONFIG_FAILURE_ACTIONS, ref sfa))
  63. throw new Exception("Failed to change the failure actions", new Win32Exception());
  64. }
  65. finally
  66. {
  67. Marshal.FreeHGlobal(sfa.lpsaActions);
  68. }
  69. }
  70. public void Dispose()
  71. {
  72. if (Handle!=IntPtr.Zero)
  73. Advapi32.CloseServiceHandle(Handle);
  74. Handle = IntPtr.Zero;
  75. }
  76. }
  77. static class LogonAsAService
  78. {
  79. public static void AddLogonAsAServiceRight(string username)
  80. {
  81. //Needs to be at least XP or 2003 server
  82. //https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832%28v=vs.85%29.aspx
  83. OperatingSystem osInfo = Environment.OSVersion;
  84. if (osInfo.Version.Major >= 5 && osInfo.Version.Minor >= 1)
  85. {
  86. var newuser = GetLocalAccountIfLocalAccount(username);
  87. //Trace.WriteLine("Username for Logon as A Service: " + newuser);
  88. long rightexitcode = SetRight(newuser, PrivlegeRights.SeServiceLogonRight.ToString());
  89. if (rightexitcode != 0)
  90. {
  91. Console.WriteLine("Failed to set logon as a service right");
  92. Environment.Exit(1);
  93. }
  94. }
  95. else
  96. {
  97. Console.WriteLine("Cannot set Logon as a Service right. Unsupported operating system detected");
  98. }
  99. }
  100. private static string GetDomain(string s)
  101. {
  102. int stop = s.IndexOf("\\", StringComparison.Ordinal);
  103. if (stop >= 0)
  104. return s.Substring(0, stop);
  105. else
  106. return null;
  107. }
  108. private static string GetLogin(string s)
  109. {
  110. int stop = s.IndexOf("\\", StringComparison.Ordinal);
  111. return (stop > -1) ? s.Substring(stop + 1, s.Length - stop - 1) : s;
  112. }
  113. private static string GetLocalAccountIfLocalAccount(string username)
  114. {
  115. var machinename = Environment.MachineName;
  116. string domain = GetDomain(username);
  117. if (domain == null || domain.ToLower() == machinename.ToLower() || domain == ".")
  118. {
  119. return GetLogin(username);
  120. }
  121. return username;
  122. }
  123. /// <summary>Adds a privilege to an account</summary>
  124. /// <param name="accountName">Name of an account - "domain\account" or only "account"</param>
  125. /// <param name="privilegeName">Name ofthe privilege</param>
  126. /// <returns>The windows error code returned by LsaAddAccountRights</returns>
  127. private static long SetRight(String accountName, String privilegeName)
  128. {
  129. long winErrorCode = 0; //contains the last error
  130. //pointer an size for the SID
  131. IntPtr sid = IntPtr.Zero;
  132. int sidSize = 0;
  133. //StringBuilder and size for the domain name
  134. StringBuilder domainName = new StringBuilder();
  135. int nameSize = 0;
  136. //account-type variable for lookup
  137. int accountType = 0;
  138. //get required buffer size
  139. Advapi32.LookupAccountName(String.Empty, accountName, sid, ref sidSize, domainName, ref nameSize, ref accountType);
  140. //allocate buffers
  141. domainName = new StringBuilder(nameSize);
  142. sid = Marshal.AllocHGlobal(sidSize);
  143. //lookup the SID for the account
  144. bool result = Advapi32.LookupAccountName(String.Empty, accountName, sid, ref sidSize, domainName, ref nameSize,
  145. ref accountType);
  146. //say what you're doing
  147. //Console.WriteLine("LookupAccountName result = " + result);
  148. //Console.WriteLine("IsValidSid: " + Advapi32.IsValidSid(sid));
  149. //Console.WriteLine("LookupAccountName domainName: " + domainName.ToString());
  150. if (!result)
  151. {
  152. winErrorCode = Kernel32.GetLastError();
  153. Console.WriteLine("LookupAccountName failed: " + winErrorCode);
  154. }
  155. else
  156. {
  157. //initialize an empty unicode-string
  158. LSA_UNICODE_STRING systemName = new LSA_UNICODE_STRING();
  159. //combine all policies
  160. const int access = (int)(
  161. LSA_AccessPolicy.POLICY_AUDIT_LOG_ADMIN |
  162. LSA_AccessPolicy.POLICY_CREATE_ACCOUNT |
  163. LSA_AccessPolicy.POLICY_CREATE_PRIVILEGE |
  164. LSA_AccessPolicy.POLICY_CREATE_SECRET |
  165. LSA_AccessPolicy.POLICY_GET_PRIVATE_INFORMATION |
  166. LSA_AccessPolicy.POLICY_LOOKUP_NAMES |
  167. LSA_AccessPolicy.POLICY_NOTIFICATION |
  168. LSA_AccessPolicy.POLICY_SERVER_ADMIN |
  169. LSA_AccessPolicy.POLICY_SET_AUDIT_REQUIREMENTS |
  170. LSA_AccessPolicy.POLICY_SET_DEFAULT_QUOTA_LIMITS |
  171. LSA_AccessPolicy.POLICY_TRUST_ADMIN |
  172. LSA_AccessPolicy.POLICY_VIEW_AUDIT_INFORMATION |
  173. LSA_AccessPolicy.POLICY_VIEW_LOCAL_INFORMATION
  174. );
  175. //initialize a pointer for the policy handle
  176. IntPtr policyHandle = IntPtr.Zero;
  177. //these attributes are not used, but LsaOpenPolicy wants them to exists
  178. LSA_OBJECT_ATTRIBUTES objectAttributes = new LSA_OBJECT_ATTRIBUTES
  179. {
  180. Length = 0,
  181. RootDirectory = IntPtr.Zero,
  182. Attributes = 0,
  183. SecurityDescriptor = IntPtr.Zero,
  184. SecurityQualityOfService = IntPtr.Zero
  185. };
  186. //get a policy handle
  187. uint resultPolicy = Advapi32.LsaOpenPolicy(ref systemName, ref objectAttributes, access, out policyHandle);
  188. winErrorCode = Advapi32.LsaNtStatusToWinError(resultPolicy);
  189. if (winErrorCode != 0)
  190. {
  191. Console.WriteLine("OpenPolicy failed: " + winErrorCode);
  192. }
  193. else
  194. {
  195. //Now that we have the SID an the policy,
  196. //we can add rights to the account.
  197. //initialize an unicode-string for the privilege name
  198. LSA_UNICODE_STRING[] userRights = new LSA_UNICODE_STRING[1];
  199. userRights[0] = new LSA_UNICODE_STRING();
  200. userRights[0].Buffer = Marshal.StringToHGlobalUni(privilegeName);
  201. userRights[0].Length = (UInt16)(privilegeName.Length * UnicodeEncoding.CharSize);
  202. userRights[0].MaximumLength = (UInt16)((privilegeName.Length + 1) * UnicodeEncoding.CharSize);
  203. //add the right to the account
  204. uint res = Advapi32.LsaAddAccountRights(policyHandle, sid, userRights, 1);
  205. winErrorCode = Advapi32.LsaNtStatusToWinError(res);
  206. if (winErrorCode != 0)
  207. {
  208. Console.WriteLine("LsaAddAccountRights failed: " + winErrorCode);
  209. }
  210. Advapi32.LsaClose(policyHandle);
  211. }
  212. Advapi32.FreeSid(sid);
  213. }
  214. return winErrorCode;
  215. }
  216. }
  217. /// <summary>
  218. /// Advapi32.dll wrapper for performing additional service related operations that are not
  219. /// available in WMI.
  220. /// </summary>
  221. internal class Advapi32
  222. {
  223. [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
  224. [return: MarshalAs(UnmanagedType.Bool)]
  225. internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, IntPtr lpInfo);
  226. [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
  227. [return: MarshalAs(UnmanagedType.Bool)]
  228. internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, ref SERVICE_FAILURE_ACTIONS sfa);
  229. [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
  230. internal static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess);
  231. [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
  232. internal static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
  233. [DllImport("advapi32.dll", SetLastError = true)]
  234. [return: MarshalAs(UnmanagedType.Bool)]
  235. internal static extern bool CloseServiceHandle(IntPtr hSCObject);
  236. [DllImport("advapi32.DLL")]
  237. internal static extern bool SetServiceStatus(IntPtr hServiceStatus, ref SERVICE_STATUS lpServiceStatus);
  238. [DllImport("advapi32.dll", PreserveSig = true)]
  239. internal static extern UInt32 LsaOpenPolicy(ref LSA_UNICODE_STRING SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, Int32 DesiredAccess,
  240. out IntPtr PolicyHandle);
  241. [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
  242. internal static extern uint LsaAddAccountRights(IntPtr PolicyHandle, IntPtr AccountSid, LSA_UNICODE_STRING[] UserRights, uint CountOfRights);
  243. [DllImport("advapi32")]
  244. internal static extern void FreeSid(IntPtr pSid);
  245. [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, PreserveSig = true)]
  246. internal static extern bool LookupAccountName(string lpSystemName, string lpAccountName, IntPtr psid, ref int cbsid, StringBuilder domainName,
  247. ref int cbdomainLength, ref int use);
  248. [DllImport("advapi32.dll")]
  249. internal static extern bool IsValidSid(IntPtr pSid);
  250. [DllImport("advapi32.dll", SetLastError = true)]
  251. internal static extern uint LsaClose(IntPtr ObjectHandle);
  252. [DllImport("advapi32.dll", SetLastError = false)]
  253. internal static extern uint LsaNtStatusToWinError(uint status);
  254. }
  255. //http://msdn.microsoft.com/en-us/library/windows/desktop/bb545671(v=vs.85).aspx
  256. internal enum PrivlegeRights
  257. {
  258. SeServiceLogonRight, //Required for an account to log on using the service logon type.
  259. SeRemoteInteractiveLogonRight, //Required for an account to log on remotely using the interactive logon type.
  260. SeNetworkLogonRight, //Required for an account to log on using the network logon type.
  261. SeInteractiveLogonRight, //Required for an account to log on using the interactive logon type.
  262. SeDenyServiceLogonRight, //Explicitly denies an account the right to log on using the service logon type.
  263. SeDenyRemoteInteractiveLogonRight, //Explicitly denies an account the right to log on remotely using the interactive logon type.
  264. SeDenyNetworkLogonRight, //Explicitly denies an account the right to log on using the network logon type.
  265. SeDenyInteractiveLogonRight, //Explicitly denies an account the right to log on using the interactive logon type.
  266. SeDenyBatchLogonRight, //Explicitly denies an account the right to log on using the batch logon type.
  267. SeBatchLogonRight //Required for an account to log on using the batch logon type.
  268. }
  269. [StructLayout(LayoutKind.Sequential)]
  270. struct LSA_UNICODE_STRING
  271. {
  272. public UInt16 Length;
  273. public UInt16 MaximumLength;
  274. public IntPtr Buffer;
  275. }
  276. [StructLayout(LayoutKind.Sequential)]
  277. struct LSA_OBJECT_ATTRIBUTES
  278. {
  279. public int Length;
  280. public IntPtr RootDirectory;
  281. public LSA_UNICODE_STRING ObjectName;
  282. public UInt32 Attributes;
  283. public IntPtr SecurityDescriptor;
  284. public IntPtr SecurityQualityOfService;
  285. }
  286. // enum all policies
  287. [Flags]
  288. enum LSA_AccessPolicy : long
  289. {
  290. POLICY_VIEW_LOCAL_INFORMATION = 0x00000001L,
  291. POLICY_VIEW_AUDIT_INFORMATION = 0x00000002L,
  292. POLICY_GET_PRIVATE_INFORMATION = 0x00000004L,
  293. POLICY_TRUST_ADMIN = 0x00000008L,
  294. POLICY_CREATE_ACCOUNT = 0x00000010L,
  295. POLICY_CREATE_SECRET = 0x00000020L,
  296. POLICY_CREATE_PRIVILEGE = 0x00000040L,
  297. POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080L,
  298. POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100L,
  299. POLICY_AUDIT_LOG_ADMIN = 0x00000200L,
  300. POLICY_SERVER_ADMIN = 0x00000400L,
  301. POLICY_LOOKUP_NAMES = 0x00000800L,
  302. POLICY_NOTIFICATION = 0x00001000L
  303. }
  304. internal enum SCM_ACCESS : uint
  305. {
  306. /// <summary>
  307. /// Required to connect to the service control manager.
  308. /// </summary>
  309. SC_MANAGER_CONNECT = 0x00001,
  310. /// <summary>
  311. /// Required to call the CreateService function to create a service
  312. /// object and add it to the database.
  313. /// </summary>
  314. SC_MANAGER_CREATE_SERVICE = 0x00002,
  315. /// <summary>
  316. /// Required to call the EnumServicesStatusEx function to list the
  317. /// services that are in the database.
  318. /// </summary>
  319. SC_MANAGER_ENUMERATE_SERVICE = 0x00004,
  320. /// <summary>
  321. /// Required to call the LockServiceDatabase function to acquire a
  322. /// lock on the database.
  323. /// </summary>
  324. SC_MANAGER_LOCK = 0x00008,
  325. /// <summary>
  326. /// Required to call the QueryServiceLockStatus function to retrieve
  327. /// the lock status information for the database.
  328. /// </summary>
  329. SC_MANAGER_QUERY_LOCK_STATUS = 0x00010,
  330. /// <summary>
  331. /// Required to call the NotifyBootConfigStatus function.
  332. /// </summary>
  333. SC_MANAGER_MODIFY_BOOT_CONFIG = 0x00020,
  334. /// <summary>
  335. /// Includes STANDARD_RIGHTS_REQUIRED, in addition to all access
  336. /// rights in this table.
  337. /// </summary>
  338. SC_MANAGER_ALL_ACCESS = ACCESS_MASK.STANDARD_RIGHTS_REQUIRED |
  339. SC_MANAGER_CONNECT |
  340. SC_MANAGER_CREATE_SERVICE |
  341. SC_MANAGER_ENUMERATE_SERVICE |
  342. SC_MANAGER_LOCK |
  343. SC_MANAGER_QUERY_LOCK_STATUS |
  344. SC_MANAGER_MODIFY_BOOT_CONFIG,
  345. GENERIC_READ = ACCESS_MASK.STANDARD_RIGHTS_READ |
  346. SC_MANAGER_ENUMERATE_SERVICE |
  347. SC_MANAGER_QUERY_LOCK_STATUS,
  348. GENERIC_WRITE = ACCESS_MASK.STANDARD_RIGHTS_WRITE |
  349. SC_MANAGER_CREATE_SERVICE |
  350. SC_MANAGER_MODIFY_BOOT_CONFIG,
  351. GENERIC_EXECUTE = ACCESS_MASK.STANDARD_RIGHTS_EXECUTE |
  352. SC_MANAGER_CONNECT | SC_MANAGER_LOCK,
  353. GENERIC_ALL = SC_MANAGER_ALL_ACCESS,
  354. }
  355. [Flags]
  356. internal enum SERVICE_ACCESS : uint
  357. {
  358. STANDARD_RIGHTS_REQUIRED = 0xF0000,
  359. SERVICE_QUERY_CONFIG = 0x00001,
  360. SERVICE_CHANGE_CONFIG = 0x00002,
  361. SERVICE_QUERY_STATUS = 0x00004,
  362. SERVICE_ENUMERATE_DEPENDENTS = 0x00008,
  363. SERVICE_START = 0x00010,
  364. SERVICE_STOP = 0x00020,
  365. SERVICE_PAUSE_CONTINUE = 0x00040,
  366. SERVICE_INTERROGATE = 0x00080,
  367. SERVICE_USER_DEFINED_CONTROL = 0x00100,
  368. SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
  369. SERVICE_QUERY_CONFIG |
  370. SERVICE_CHANGE_CONFIG |
  371. SERVICE_QUERY_STATUS |
  372. SERVICE_ENUMERATE_DEPENDENTS |
  373. SERVICE_START |
  374. SERVICE_STOP |
  375. SERVICE_PAUSE_CONTINUE |
  376. SERVICE_INTERROGATE |
  377. SERVICE_USER_DEFINED_CONTROL)
  378. }
  379. [Flags]
  380. internal enum ACCESS_MASK : uint
  381. {
  382. DELETE = 0x00010000,
  383. READ_CONTROL = 0x00020000,
  384. WRITE_DAC = 0x00040000,
  385. WRITE_OWNER = 0x00080000,
  386. SYNCHRONIZE = 0x00100000,
  387. STANDARD_RIGHTS_REQUIRED = 0x000f0000,
  388. STANDARD_RIGHTS_READ = 0x00020000,
  389. STANDARD_RIGHTS_WRITE = 0x00020000,
  390. STANDARD_RIGHTS_EXECUTE = 0x00020000,
  391. STANDARD_RIGHTS_ALL = 0x001f0000,
  392. SPECIFIC_RIGHTS_ALL = 0x0000ffff,
  393. ACCESS_SYSTEM_SECURITY = 0x01000000,
  394. MAXIMUM_ALLOWED = 0x02000000,
  395. GENERIC_READ = 0x80000000,
  396. GENERIC_WRITE = 0x40000000,
  397. GENERIC_EXECUTE = 0x20000000,
  398. GENERIC_ALL = 0x10000000,
  399. DESKTOP_READOBJECTS = 0x00000001,
  400. DESKTOP_CREATEWINDOW = 0x00000002,
  401. DESKTOP_CREATEMENU = 0x00000004,
  402. DESKTOP_HOOKCONTROL = 0x00000008,
  403. DESKTOP_JOURNALRECORD = 0x00000010,
  404. DESKTOP_JOURNALPLAYBACK = 0x00000020,
  405. DESKTOP_ENUMERATE = 0x00000040,
  406. DESKTOP_WRITEOBJECTS = 0x00000080,
  407. DESKTOP_SWITCHDESKTOP = 0x00000100,
  408. WINSTA_ENUMDESKTOPS = 0x00000001,
  409. WINSTA_READATTRIBUTES = 0x00000002,
  410. WINSTA_ACCESSCLIPBOARD = 0x00000004,
  411. WINSTA_CREATEDESKTOP = 0x00000008,
  412. WINSTA_WRITEATTRIBUTES = 0x00000010,
  413. WINSTA_ACCESSGLOBALATOMS = 0x00000020,
  414. WINSTA_EXITWINDOWS = 0x00000040,
  415. WINSTA_ENUMERATE = 0x00000100,
  416. WINSTA_READSCREEN = 0x00000200,
  417. WINSTA_ALL_ACCESS = 0x0000037f
  418. }
  419. public struct SERVICE_STATUS
  420. {
  421. public int serviceType;
  422. public int currentState;
  423. public int controlsAccepted;
  424. public int win32ExitCode;
  425. public int serviceSpecificExitCode;
  426. public int checkPoint;
  427. public int waitHint;
  428. }
  429. public enum State
  430. {
  431. SERVICE_STOPPED = 0x00000001,
  432. SERVICE_START_PENDING = 0x00000002,
  433. SERVICE_STOP_PENDING = 0x00000003,
  434. SERVICE_RUNNING = 0x00000004,
  435. SERVICE_CONTINUE_PENDING = 0x00000005,
  436. SERVICE_PAUSE_PENDING = 0x00000006,
  437. SERVICE_PAUSED = 0x00000007,
  438. }
  439. // http://msdn.microsoft.com/en-us/library/windows/desktop/ms685126(v=vs.85).aspx
  440. [StructLayout(LayoutKind.Sequential)]
  441. public struct SC_ACTION
  442. {
  443. public SC_ACTION_TYPE Type;
  444. /// <summary>
  445. /// The time to wait before performing the specified action, in milliseconds.
  446. /// </summary>
  447. public uint Delay;
  448. public SC_ACTION(SC_ACTION_TYPE type, TimeSpan delay)
  449. {
  450. Type = type;
  451. Delay = (uint)delay.TotalMilliseconds;
  452. }
  453. }
  454. internal enum SERVICE_CONFIG_INFOLEVEL
  455. {
  456. SERVICE_CONFIG_DESCRIPTION = 1,
  457. SERVICE_CONFIG_FAILURE_ACTIONS = 2,
  458. SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3,
  459. SERVICE_CONFIG_FAILURE_ACTIONS_FLAG = 4,
  460. SERVICE_CONFIG_SERVICE_SID_INFO = 5,
  461. SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO = 6,
  462. SERVICE_CONFIG_PRESHUTDOWN_INFO = 7,
  463. SERVICE_CONFIG_TRIGGER_INFO = 8,
  464. SERVICE_CONFIG_PREFERRED_NODE = 9
  465. }
  466. public enum SC_ACTION_TYPE
  467. {
  468. SC_ACTION_NONE = 0,
  469. SC_ACTION_RESTART = 1,
  470. SC_ACTION_REBOOT = 2,
  471. SC_ACTION_RUN_COMMAND = 3
  472. }
  473. // http://msdn.microsoft.com/en-us/library/windows/desktop/ms685939(v=vs.85).aspx
  474. [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]
  475. public struct SERVICE_FAILURE_ACTIONS
  476. {
  477. /// <summary>
  478. /// The time after which to reset the failure count to zero if there are no failures, in seconds.
  479. /// Specify INFINITE to indicate that this value should never be reset.
  480. /// </summary>
  481. public int dwResetPeriod;
  482. [MarshalAs(UnmanagedType.LPWStr)]
  483. public string lpRebootMsg;
  484. [MarshalAs(UnmanagedType.LPWStr)]
  485. public string lpCommand;
  486. public int cActions;
  487. public IntPtr/*SC_ACTION[]*/ lpsaActions;
  488. }
  489. }