Created
July 15, 2010 18:08
-
-
Save alexdresko/477296 to your computer and use it in GitHub Desktop.
SharePointSiteAndWebHelper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| namespace CSI.ESS.ServiceModel.Contracts | |
| { | |
| using System; | |
| using System.ComponentModel; | |
| using System.Runtime.InteropServices; | |
| using System.Security.Principal; | |
| /// <summary> | |
| /// This class manages the creation of an impersonation to the Application | |
| /// Pool's context for a defined scope. | |
| /// | |
| /// It just wraps the .Net class for impersonation, thus allowing easier | |
| /// use. | |
| /// | |
| /// This class is made for use with the C# 'using' keyword, as in the | |
| /// example below: | |
| /// <code> | |
| /// using(CSI.Shared.SharePoint.Identity impersonate = CSI.Shared.SharePoint.Identity.ImpersonateAdmin()) | |
| /// { | |
| /// // ... Do whatever job you want as the AppPool | |
| /// } | |
| /// // Back to the original, you don't have to worry about reverting, | |
| /// // this is automatically done with the IDisposable interface | |
| /// </code> | |
| /// </summary> | |
| public sealed class Identity : IDisposable | |
| { | |
| #region Constants and Fields | |
| /// <summary> | |
| /// Windows identity used for the Application Pool | |
| /// </summary> | |
| private static WindowsIdentity _appPoolIdentity; | |
| /// <summary> | |
| /// Stores the currently available Windows Impersonation context. | |
| /// </summary> | |
| private WindowsImpersonationContext _context; | |
| /// <summary> | |
| /// Stores the app pool's identity context. | |
| /// </summary> | |
| private WindowsImpersonationContext _selfContext; | |
| #endregion | |
| #region Constructors and Destructors | |
| /// <summary> | |
| /// Private constructor, static function accessed class. | |
| /// </summary> | |
| private Identity() | |
| { | |
| // Try catch structure to ensure we don't change context in case | |
| // we had an error duplicating the token. | |
| try | |
| { | |
| this._selfContext = WindowsIdentity.Impersonate(IntPtr.Zero); // REVERT to AppPool identity! | |
| this._context = AppPoolIdentity.Impersonate(); | |
| } | |
| catch | |
| { | |
| // Close the context | |
| this.UndoImpersonation(); | |
| // Rethrow the exception | |
| throw; | |
| } | |
| } | |
| #endregion | |
| #region Properties | |
| /// <summary> | |
| /// This function returns the current user's login name. | |
| /// </summary> | |
| public static string CurrentUserName | |
| { | |
| get | |
| { | |
| // ReSharper disable PossibleNullReferenceException | |
| return WindowsIdentity.GetCurrent().Name; | |
| // ReSharper restore PossibleNullReferenceException | |
| } | |
| } | |
| /// <summary> | |
| /// Gets the windows identity used for the Application Pool | |
| /// </summary> | |
| private static WindowsIdentity AppPoolIdentity | |
| { | |
| get | |
| { | |
| // Lock current type to ensure thread safety on | |
| // identity creation. | |
| lock (typeof(Identity)) | |
| { | |
| if (_appPoolIdentity == null) | |
| { | |
| // Create a new handle from this one | |
| // ReSharper disable PossibleNullReferenceException | |
| var token = WindowsIdentity.GetCurrent().Token; | |
| // ReSharper restore PossibleNullReferenceException | |
| // Throw an exception if we have an empty token | |
| if (token == IntPtr.Zero) | |
| { | |
| throw new ApplicationException("Unable to fetch AppPool's identity token !"); | |
| } | |
| // Create a duplicate of the user's token in order to use it for impersonation | |
| if (!DuplicateToken(token, 2, ref token)) | |
| { | |
| throw new Win32Exception(Marshal.GetLastWin32Error(), "Unable to duplicate AppPool's identity token !"); | |
| } | |
| // Throw an exception if we were unable to duplicate the token | |
| if (token == IntPtr.Zero) | |
| { | |
| throw new ApplicationException("Unable to duplicate AppPool's identity token !"); | |
| } | |
| // Store app pool's identity | |
| _appPoolIdentity = new WindowsIdentity(token); | |
| // Free the windows unmanaged resource | |
| CloseHandle(token); | |
| } | |
| return _appPoolIdentity; | |
| } | |
| } | |
| } | |
| #endregion | |
| #region Public Methods | |
| /// <summary> | |
| /// This method creates a new impersonation context. | |
| /// </summary> | |
| public static Identity ImpersonateAdmin() | |
| { | |
| return new Identity(); | |
| } | |
| /// <summary> | |
| /// This method closes the current impersonation context in order revert the user | |
| /// to his real principal. | |
| /// </summary> | |
| public void UndoImpersonation() | |
| { | |
| if (this._context != null) | |
| { | |
| this._context.Undo(); | |
| this._context = null; | |
| } | |
| if (this._selfContext != null) | |
| { | |
| this._selfContext.Undo(); | |
| this._selfContext = null; | |
| } | |
| } | |
| #endregion | |
| #region Implemented Interfaces | |
| #region IDisposable | |
| /// <summary> | |
| /// This method disposes the current object, it frees all resources used by this class. | |
| /// </summary> | |
| public void Dispose() | |
| { | |
| this.Dispose(true); | |
| // Ensure I'm garbage collected. | |
| GC.SuppressFinalize(this); | |
| } | |
| #endregion | |
| #endregion | |
| #region Methods | |
| /// <summary> | |
| /// Closes an unmanaged handle in order to free allocated resources. | |
| /// </summary> | |
| /// <returns>True if the call succeeded, false otherwise.</returns> | |
| [DllImport("kernel32.dll", CharSet = CharSet.Auto)] | |
| private static extern bool CloseHandle(IntPtr handle); | |
| /// <summary> | |
| /// Duplicates a token in order to have it working for impersonation. | |
| /// </summary> | |
| /// <param name = "tokenHandle">Initial token to be duplicated</param> | |
| /// <param name = "impersonationLevel_">Level of impersonation needed</param> | |
| /// <param name = "newTokenHandle">Reference to the new token created</param> | |
| /// <returns>True if the call succeeded, false otherwise.</returns> | |
| [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] | |
| private static extern bool DuplicateToken(IntPtr tokenHandle, int impersonationLevel_, ref IntPtr newTokenHandle); | |
| /// <summary> | |
| /// This method disposes the current object, it frees all resources used by this class. | |
| /// </summary> | |
| /// <param name = "disposing_">Do actual disposing or not.</param> | |
| private void Dispose(bool disposing_) | |
| { | |
| if (disposing_) | |
| { | |
| this.UndoImpersonation(); | |
| } | |
| } | |
| #endregion | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment