You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

423 lines
27 KiB

  1. // <copyright file="ProcessExtensions.cs" company="Nick Lowe">
  2. // Copyright © Nick Lowe 2009
  3. // </copyright>
  4. // <author>Nick Lowe</author>
  5. // <email>nick@int-r.net</email>
  6. // <url>http://processprivileges.codeplex.com/</url>
  7. namespace ProcessPrivileges
  8. {
  9. using System.Diagnostics;
  10. using System.Runtime.CompilerServices;
  11. using System.Security.Permissions;
  12. /// <summary>Provides extension methods to the <see cref="Process" /> class, implementing the functionality necessary to query, enable, disable or remove privileges on a process.</summary>
  13. /// <example>
  14. /// <code>
  15. /// using System;
  16. /// using System.Diagnostics;
  17. /// using System.Linq;
  18. /// using ProcessPrivileges;
  19. ///
  20. /// internal static class ProcessPrivilegesExample
  21. /// {
  22. /// public static void Main()
  23. /// {
  24. /// // Get the current process.
  25. /// Process process = Process.GetCurrentProcess();
  26. ///
  27. /// // Get the privileges and associated attributes.
  28. /// PrivilegeAndAttributesCollection privileges = process.GetPrivileges();
  29. ///
  30. /// int maxPrivilegeLength = privileges.Max(privilege =&gt; privilege.Privilege.ToString().Length);
  31. ///
  32. /// foreach (PrivilegeAndAttributes privilegeAndAttributes in privileges)
  33. /// {
  34. /// // The privilege.
  35. /// Privilege privilege = privilegeAndAttributes.Privilege;
  36. ///
  37. /// // The privilege state.
  38. /// PrivilegeState privilegeState = privilegeAndAttributes.PrivilegeState;
  39. ///
  40. /// // Write out the privilege and its state.
  41. /// Console.WriteLine(
  42. /// "{0}{1} =&gt; {2}",
  43. /// privilege,
  44. /// GetPadding(privilege.ToString().Length, maxPrivilegeLength),
  45. /// privilegeState);
  46. /// }
  47. ///
  48. /// Console.WriteLine();
  49. ///
  50. /// // Privileges can only be enabled on a process if they are disabled.
  51. /// if (process.GetPrivilegeState(Privilege.TakeOwnership) == PrivilegeState.Disabled)
  52. /// {
  53. /// // Enable the TakeOwnership privilege on it.
  54. /// AdjustPrivilegeResult result = process.EnablePrivilege(Privilege.TakeOwnership);
  55. ///
  56. /// // Get the state of the TakeOwnership privilege.
  57. /// PrivilegeState takeOwnershipState = process.GetPrivilegeState(Privilege.TakeOwnership);
  58. ///
  59. /// // Write out the TakeOwnership privilege, its state and the result.
  60. /// Console.WriteLine(
  61. /// "{0}{1} =&gt; {2} ({3})",
  62. /// Privilege.TakeOwnership,
  63. /// GetPadding(Privilege.TakeOwnership.ToString().Length, maxPrivilegeLength),
  64. /// takeOwnershipState,
  65. /// result);
  66. /// }
  67. /// }
  68. ///
  69. /// private static string GetPadding(int length, int maxLength)
  70. /// {
  71. /// int paddingLength = maxLength - length;
  72. /// char[] padding = new char[paddingLength];
  73. /// for (int i = 0; i &lt; paddingLength; i++)
  74. /// {
  75. /// padding[i] = ' ';
  76. /// }
  77. ///
  78. /// return new string(padding);
  79. /// }
  80. /// }
  81. /// </code>
  82. /// <code>
  83. /// using System;
  84. /// using System.Diagnostics;
  85. /// using ProcessPrivileges;
  86. ///
  87. /// internal static class ReusingAccessTokenHandleExample
  88. /// {
  89. /// public static void Main()
  90. /// {
  91. /// // Access token handle reused within the using block.
  92. /// using (AccessTokenHandle accessTokenHandle =
  93. /// Process.GetCurrentProcess().GetAccessTokenHandle(
  94. /// TokenAccessRights.AdjustPrivileges | TokenAccessRights.Query))
  95. /// {
  96. /// // Enable privileges using the same access token handle.
  97. /// AdjustPrivilegeResult backupResult = accessTokenHandle.EnablePrivilege(Privilege.Backup);
  98. /// AdjustPrivilegeResult restoreResult = accessTokenHandle.EnablePrivilege(Privilege.Restore);
  99. ///
  100. /// Console.WriteLine(
  101. /// "{0} => {1} ({2})",
  102. /// Privilege.Backup,
  103. /// accessTokenHandle.GetPrivilegeState(Privilege.Backup),
  104. /// backupResult);
  105. ///
  106. /// Console.WriteLine(
  107. /// "{0} => {1} ({2})",
  108. /// Privilege.Restore,
  109. /// accessTokenHandle.GetPrivilegeState(Privilege.Restore),
  110. /// restoreResult);
  111. /// }
  112. /// }
  113. /// }
  114. /// </code>
  115. /// </example>
  116. /// <remarks>
  117. /// <para>For more information on privileges, see:</para>
  118. /// <para><a href="http://msdn.microsoft.com/en-us/library/aa379306.aspx">Privileges</a></para>
  119. /// <para><a href="http://msdn.microsoft.com/en-us/library/bb530716.aspx">Privilege Constants</a></para>
  120. /// </remarks>
  121. public static class ProcessExtensions
  122. {
  123. /// <summary>Disables the specified <see cref="Privilege"/> on a <see cref="Process"/>.</summary>
  124. /// <param name="accessTokenHandle">The <see cref="AccessTokenHandle"/> for a <see cref="Process"/> on which the operation should be performed.</param>
  125. /// <param name="privilege">The <see cref="Privilege"/> to be disabled.</param>
  126. /// <returns>
  127. /// <para>Result from the privilege adjustment.</para>
  128. /// <para>If the <see cref="Privilege"/> is already disabled, <see cref="AdjustPrivilegeResult.None"/> is returned.</para>
  129. /// </returns>
  130. /// <exception cref="Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
  131. /// <permission cref="SecurityAction.LinkDemand">Requires the immediate caller to have FullTrust.</permission>
  132. /// <remarks>The caller must have permission to query and adjust token privileges on the target process.</remarks>
  133. [MethodImpl(MethodImplOptions.Synchronized),
  134. PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  135. public static AdjustPrivilegeResult DisablePrivilege(this AccessTokenHandle accessTokenHandle, Privilege privilege)
  136. {
  137. return Privileges.DisablePrivilege(accessTokenHandle, privilege);
  138. }
  139. /// <summary>Disables the specified <see cref="Privilege"/> on a <see cref="Process"/>.</summary>
  140. /// <param name="process">The <see cref="Process"/> on which the operation should be performed.</param>
  141. /// <param name="privilege">The <see cref="Privilege"/> to be disabled.</param>
  142. /// <returns>
  143. /// <para>Result from the privilege adjustment.</para>
  144. /// <para>If the <see cref="Privilege"/> is already disabled, <see cref="AdjustPrivilegeResult.None"/> is returned.</para>
  145. /// </returns>
  146. /// <exception cref="Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
  147. /// <permission cref="SecurityAction.LinkDemand">Requires the immediate caller to have FullTrust.</permission>
  148. /// <remarks>
  149. /// <para>If you are adjusting multiple privileges on a process, consider using <see cref="DisablePrivilege(AccessTokenHandle, Privilege)"/> with an access token handle for the process.</para>
  150. /// <para>The caller must have permission to query and adjust token privileges on the target process.</para>
  151. /// </remarks>
  152. [MethodImpl(MethodImplOptions.Synchronized),
  153. PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  154. public static AdjustPrivilegeResult DisablePrivilege(this Process process, Privilege privilege)
  155. {
  156. using (AccessTokenHandle accessTokenHandle = new AccessTokenHandle(
  157. new ProcessHandle(process.Handle, false),
  158. TokenAccessRights.AdjustPrivileges | TokenAccessRights.Query))
  159. {
  160. return DisablePrivilege(accessTokenHandle, privilege);
  161. }
  162. }
  163. /// <summary>Enables the specified <see cref="Privilege"/> on a <see cref="Process"/>.</summary>
  164. /// <param name="accessTokenHandle">The <see cref="AccessTokenHandle"/> for a <see cref="Process"/> on which the operation should be performed.</param>
  165. /// <param name="privilege">The <see cref="Privilege"/> to be enabled.</param>
  166. /// <returns>
  167. /// <para>Result from the privilege adjustment.</para>
  168. /// <para>If the <see cref="Privilege"/> is already enabled, <see cref="AdjustPrivilegeResult.None"/> is returned.</para>
  169. /// </returns>
  170. /// <exception cref="Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
  171. /// <permission cref="SecurityAction.LinkDemand">Requires the immediate caller to have FullTrust.</permission>
  172. /// <remarks>
  173. /// <para>Enabling a privilege allows a process to perform system-level actions that it could not previously.</para>
  174. /// <para>Before enabling a privilege, many potentially dangerous, thoroughly verify that functions or operations in your code actually require them.</para>
  175. /// <para>It is not normally appropriate to hold privileges for the lifetime of a process. Use sparingly; enable when needed, disable when not.</para>
  176. /// <para>Consider using <see cref="PrivilegeEnabler"/> that enables privileges on a process in a safe way, ensuring that they are returned to their original state when an operation that requires a privilege completes.</para>
  177. /// <para>The caller must have permission to query and adjust token privileges on the target process.</para>
  178. /// </remarks>
  179. [MethodImpl(MethodImplOptions.Synchronized),
  180. PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  181. public static AdjustPrivilegeResult EnablePrivilege(this AccessTokenHandle accessTokenHandle, Privilege privilege)
  182. {
  183. return Privileges.EnablePrivilege(accessTokenHandle, privilege);
  184. }
  185. /// <summary>Enables the specified <see cref="Privilege"/> on a <see cref="Process"/>.</summary>
  186. /// <param name="process">The <see cref="Process"/> on which the operation should be performed.</param>
  187. /// <param name="privilege">The <see cref="Privilege"/> to be enabled.</param>
  188. /// <returns>
  189. /// <para>Result from the privilege adjustment.</para>
  190. /// <para>If the <see cref="Privilege"/> is already enabled, <see cref="AdjustPrivilegeResult.None"/> is returned.</para>
  191. /// <para>If a <see cref="Privilege"/> is removed from a process, it cannot be enabled.</para>
  192. /// </returns>
  193. /// <exception cref="Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
  194. /// <permission cref="SecurityAction.LinkDemand">Requires the immediate caller to have FullTrust.</permission>
  195. /// <remarks>
  196. /// <para>Enabling a privilege allows a process to perform system-level actions that it could not previously.</para>
  197. /// <para>Before enabling a privilege, many potentially dangerous, thoroughly verify that functions or operations in your code actually require them.</para>
  198. /// <para>It is not normally appropriate to hold privileges for the lifetime of a process. Use sparingly; enable when needed, disable when not.</para>
  199. /// <para>Consider using <see cref="PrivilegeEnabler"/> that enables privileges on a process in a safe way, ensuring that they are returned to their original state when an operation that requires a privilege completes.</para>
  200. /// <para>If you are adjusting multiple privileges on a process, consider using <see cref="EnablePrivilege(AccessTokenHandle, Privilege)"/> with an access token handle for the process.</para>
  201. /// <para>The caller must have permission to query and adjust token privileges on the target process.</para>
  202. /// </remarks>
  203. [MethodImpl(MethodImplOptions.Synchronized),
  204. PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  205. public static AdjustPrivilegeResult EnablePrivilege(this Process process, Privilege privilege)
  206. {
  207. using (AccessTokenHandle accessTokenHandle = new AccessTokenHandle(
  208. new ProcessHandle(process.Handle, false),
  209. TokenAccessRights.AdjustPrivileges | TokenAccessRights.Query))
  210. {
  211. return EnablePrivilege(accessTokenHandle, privilege);
  212. }
  213. }
  214. /// <summary>Gets an access token handle for a <see cref="Process"/>.</summary>
  215. /// <param name="process">The <see cref="Process"/> on which an access token handle should be retrieved.</param>
  216. /// <returns>An access token handle for a <see cref="Process"/> with <see cref="TokenAccessRights.AllAccess"/> access rights.</returns>
  217. /// <exception cref="Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
  218. /// <permission cref="SecurityAction.LinkDemand">Requires the immediate caller to have FullTrust.</permission>
  219. /// <remarks>
  220. /// <para>The caller must have permission to acquire an access token handle with all access rights.</para>
  221. /// </remarks>
  222. [MethodImpl(MethodImplOptions.Synchronized),
  223. PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  224. public static AccessTokenHandle GetAccessTokenHandle(this Process process)
  225. {
  226. return GetAccessTokenHandle(process, TokenAccessRights.AllAccess);
  227. }
  228. /// <summary>Gets an access token handle for a <see cref="Process"/>.</summary>
  229. /// <param name="process">The <see cref="Process"/> on which an access token handle should be retrieved.</param>
  230. /// <param name="tokenAccessRights">The desired access rights for the access token handle.</param>
  231. /// <returns>An access token handle for a <see cref="Process"/>.</returns>
  232. /// <exception cref="Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
  233. /// <permission cref="SecurityAction.LinkDemand">Requires the immediate caller to have FullTrust.</permission>
  234. /// <remarks>
  235. /// <para>The caller must have permission to acquire an access token handle with the desired access rights.</para>
  236. /// <para>To query permissions, the access token handle must have permission to query and adjust token privileges:</para>
  237. /// <c>TokenAccessRights.Query</c>
  238. /// <para>To enable, disable or remove a permission, the access token handle must have permission to query and adjust token privileges:</para>
  239. /// <c>TokenAccessRights.AdjustPrivileges | TokenAccessRights.Query</c>
  240. /// </remarks>
  241. [MethodImpl(MethodImplOptions.Synchronized),
  242. PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  243. public static AccessTokenHandle GetAccessTokenHandle(this Process process, TokenAccessRights tokenAccessRights)
  244. {
  245. return new AccessTokenHandle(new ProcessHandle(process.Handle, false), tokenAccessRights);
  246. }
  247. /// <summary>Gets the attributes for a <see cref="Privilege"/> on a <see cref="Process"/>.</summary>
  248. /// <param name="accessTokenHandle">The <see cref="AccessTokenHandle"/> for a <see cref="Process"/> on which the operation should be performed.</param>
  249. /// <param name="privilege">The <see cref="Privilege"/> on which the attributes should be retrieved.</param>
  250. /// <returns>The <see cref="PrivilegeAttributes"/> for a <see cref="Privilege"/> on a <see cref="Process"/>.</returns>
  251. /// <exception cref="Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
  252. /// <permission cref="SecurityAction.LinkDemand">Requires the immediate caller to have FullTrust.</permission>
  253. /// <remarks>
  254. /// <para>Consider using <see cref="GetPrivilegeState(AccessTokenHandle, Privilege)"/> as it avoids the need to work with a flags based enumerated type.</para>
  255. /// <para>The caller must have permission to query token privileges on the target process.</para>
  256. /// </remarks>
  257. [MethodImpl(MethodImplOptions.Synchronized),
  258. PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  259. public static PrivilegeAttributes GetPrivilegeAttributes(this AccessTokenHandle accessTokenHandle, Privilege privilege)
  260. {
  261. return Privileges.GetPrivilegeAttributes(privilege, GetPrivileges(accessTokenHandle));
  262. }
  263. /// <summary>Gets the attributes for a <see cref="Privilege"/> on a <see cref="Process"/>.</summary>
  264. /// <param name="process">The <see cref="Process"/> on which the operation should be performed.</param>
  265. /// <param name="privilege">The <see cref="Privilege"/> on which the attributes should be retrieved.</param>
  266. /// <returns>The <see cref="PrivilegeAttributes"/> for a <see cref="Privilege"/> on a <see cref="Process"/>.</returns>
  267. /// <exception cref="Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
  268. /// <permission cref="SecurityAction.LinkDemand">Requires the immediate caller to have FullTrust.</permission>
  269. /// <remarks>
  270. /// <para>Consider using <see cref="GetPrivilegeState(Process, Privilege)"/> as it avoids the need to work with a flags based enumerated type.</para>
  271. /// <para>The caller must have permission to query token privileges on the target process.</para>
  272. /// </remarks>
  273. [MethodImpl(MethodImplOptions.Synchronized),
  274. PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  275. public static PrivilegeAttributes GetPrivilegeAttributes(this Process process, Privilege privilege)
  276. {
  277. return Privileges.GetPrivilegeAttributes(privilege, GetPrivileges(process));
  278. }
  279. /// <summary>Gets the privileges and associated attributes from a <see cref="Process"/>.</summary>
  280. /// <param name="accessTokenHandle">The <see cref="AccessTokenHandle"/> for a <see cref="Process"/> on which the operation should be performed.</param>
  281. /// <returns>The privileges associated with a process.</returns>
  282. /// <exception cref="Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
  283. /// <permission cref="SecurityAction.LinkDemand">Requires the immediate caller to have FullTrust.</permission>
  284. /// <remarks>
  285. /// <para>Consider using <see cref="GetPrivilegeState(PrivilegeAttributes)"/> on attributes within the collection as it avoids the need to work with a flags based enumerated type.</para>
  286. /// <para>The caller must have permission to query token privileges on the target process.</para>
  287. /// </remarks>
  288. [MethodImpl(MethodImplOptions.Synchronized),
  289. PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  290. public static PrivilegeAndAttributesCollection GetPrivileges(this AccessTokenHandle accessTokenHandle)
  291. {
  292. return Privileges.GetPrivileges(accessTokenHandle);
  293. }
  294. /// <summary>Gets the privileges and associated attributes from a <see cref="Process"/>.</summary>
  295. /// <param name="process">The <see cref="Process"/> on which the operation should be performed.</param>
  296. /// <returns>The privileges associated with a process.</returns>
  297. /// <exception cref="Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
  298. /// <permission cref="SecurityAction.LinkDemand">Requires the immediate caller to have FullTrust.</permission>
  299. /// <remarks>
  300. /// <para>Consider using <see cref="GetPrivilegeState(PrivilegeAttributes)"/> method on attributes within the collection as it avoids the need to work with a flags based enumerated type.</para>
  301. /// <para>The caller must have permission to query token privileges on the target process.</para>
  302. /// </remarks>
  303. [MethodImpl(MethodImplOptions.Synchronized),
  304. PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  305. public static PrivilegeAndAttributesCollection GetPrivileges(this Process process)
  306. {
  307. using (AccessTokenHandle accessTokenHandle = new AccessTokenHandle(
  308. new ProcessHandle(process.Handle, false),
  309. TokenAccessRights.Query))
  310. {
  311. return Privileges.GetPrivileges(accessTokenHandle);
  312. }
  313. }
  314. /// <summary>Gets the state of a <see cref="Privilege"/>.</summary>
  315. /// <param name="accessTokenHandle">The <see cref="AccessTokenHandle"/> for a <see cref="Process"/> on which the operation should be performed.</param>
  316. /// <param name="privilege">The <see cref="Privilege"/> that should be checked.</param>
  317. /// <returns>The <see cref="PrivilegeState"/> of the <see cref="Privilege"/>.</returns>
  318. /// <exception cref="Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
  319. /// <permission cref="SecurityAction.LinkDemand">Requires the immediate caller to have FullTrust.</permission>
  320. /// <remarks>
  321. /// <para>Derives <see cref="GetPrivilegeAttributes(AccessTokenHandle, Privilege)"/> to establish the <see cref="PrivilegeState"/> of a <see cref="Privilege"/>.</para>
  322. /// <para>The caller must have permission to query token privileges on the target process.</para>
  323. /// </remarks>
  324. [MethodImpl(MethodImplOptions.Synchronized),
  325. PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  326. public static PrivilegeState GetPrivilegeState(this AccessTokenHandle accessTokenHandle, Privilege privilege)
  327. {
  328. return GetPrivilegeState(GetPrivilegeAttributes(accessTokenHandle, privilege));
  329. }
  330. /// <summary>Gets the state of a <see cref="Privilege"/>.</summary>
  331. /// <param name="process">The <see cref="Process"/> on which the operation should be performed.</param>
  332. /// <param name="privilege">The <see cref="Privilege"/> that should be checked.</param>
  333. /// <returns>The <see cref="PrivilegeState"/> of the <see cref="Privilege"/>.</returns>
  334. /// <exception cref="Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
  335. /// <permission cref="SecurityAction.LinkDemand">Requires the immediate caller to have FullTrust.</permission>
  336. /// <remarks>
  337. /// <para>Derives <see cref="GetPrivilegeAttributes(AccessTokenHandle, Privilege)"/> to establish the <see cref="PrivilegeState"/> of a <see cref="Privilege"/>.</para>
  338. /// <para>The caller must have permission to query token privileges on the target process.</para>
  339. /// </remarks>
  340. [MethodImpl(MethodImplOptions.Synchronized),
  341. PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  342. public static PrivilegeState GetPrivilegeState(this Process process, Privilege privilege)
  343. {
  344. return GetPrivilegeState(GetPrivilegeAttributes(process, privilege));
  345. }
  346. /// <summary>Gets the state of a <see cref="Privilege"/>.</summary>
  347. /// <param name="privilegeAttributes">The privilege attributes.</param>
  348. /// <returns>The <see cref="PrivilegeState"/> of the <see cref="Privilege"/>.</returns>
  349. /// <exception cref="Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
  350. /// <remarks>Derives <see cref="PrivilegeAttributes"/> to establish the <see cref="PrivilegeState"/> of a <see cref="Privilege"/>.</remarks>
  351. [MethodImpl(MethodImplOptions.Synchronized)]
  352. public static PrivilegeState GetPrivilegeState(PrivilegeAttributes privilegeAttributes)
  353. {
  354. if ((privilegeAttributes & PrivilegeAttributes.Enabled) == PrivilegeAttributes.Enabled)
  355. {
  356. return PrivilegeState.Enabled;
  357. }
  358. if ((privilegeAttributes & PrivilegeAttributes.Removed) == PrivilegeAttributes.Removed)
  359. {
  360. return PrivilegeState.Removed;
  361. }
  362. return PrivilegeState.Disabled;
  363. }
  364. /// <summary>Removes the specified <see cref="Privilege"/> from a <see cref="Process"/>.</summary>
  365. /// <param name="accessTokenHandle">The <see cref="AccessTokenHandle"/> for a <see cref="Process"/> on which the operation should be performed.</param>
  366. /// <param name="privilege">The <see cref="Privilege"/> to be removed.</param>
  367. /// <returns>
  368. /// <para>Result from the privilege adjustment.</para>
  369. /// <para>Once a privilege has been removed from a process, it cannot be restored afterwards.</para>
  370. /// </returns>
  371. /// <exception cref="Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
  372. /// <permission cref="SecurityAction.LinkDemand">Requires the immediate caller to have FullTrust.</permission>
  373. /// <remarks>The caller must have permission to query and adjust token privileges on the target process.</remarks>
  374. [MethodImpl(MethodImplOptions.Synchronized),
  375. PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  376. public static AdjustPrivilegeResult RemovePrivilege(this AccessTokenHandle accessTokenHandle, Privilege privilege)
  377. {
  378. return Privileges.RemovePrivilege(accessTokenHandle, privilege);
  379. }
  380. /// <summary>Removes the specified <see cref="Privilege"/> from a <see cref="Process"/>.</summary>
  381. /// <param name="process">The <see cref="Process"/> on which the operation should be performed.</param>
  382. /// <param name="privilege">The <see cref="Privilege"/> to be removed.</param>
  383. /// <returns>
  384. /// <para>Result from the privilege adjustment.</para>
  385. /// <para>Once a privilege has been removed from a process, it cannot be restored afterwards.</para>
  386. /// </returns>
  387. /// <exception cref="Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
  388. /// <permission cref="SecurityAction.LinkDemand">Requires the immediate caller to have FullTrust.</permission>
  389. /// <remarks>
  390. /// <para>If you are adjusting multiple privileges on a process, consider using <see cref="RemovePrivilege(AccessTokenHandle, Privilege)"/> with an access token handle for the process.</para>
  391. /// <para>The caller must have permission to query and adjust token privileges on the target process.</para>
  392. /// </remarks>
  393. [MethodImpl(MethodImplOptions.Synchronized),
  394. PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  395. public static AdjustPrivilegeResult RemovePrivilege(this Process process, Privilege privilege)
  396. {
  397. using (AccessTokenHandle accessTokenHandle = new AccessTokenHandle(
  398. new ProcessHandle(process.Handle, false),
  399. TokenAccessRights.AdjustPrivileges | TokenAccessRights.Query))
  400. {
  401. return RemovePrivilege(accessTokenHandle, privilege);
  402. }
  403. }
  404. }
  405. }