ClientSession.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / Security / RightsManagement / ClientSession.cs / 1305600 / ClientSession.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (c) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//  These are the internal helpers required to call into unmanaged 
//  Promethium Rights Management SDK APIs
// 
// History:
//  06/13/2005: IgorBel:  Initial implementation.
//
//----------------------------------------------------------------------------- 

using System; 
using System.Collections; 
using System.Collections.ObjectModel;
using System.Collections.Generic; 
using System.Diagnostics;
using System.Security;
using System.Security.Permissions;
using System.Security.RightsManagement; 
using SecurityHelper = MS.Internal.WindowsBase.SecurityHelper;
using System.Text; 
using System.Globalization;                 // For CultureInfo 
// for Invariant
using System.Windows;                       // for SR and SRID 

using MS.Internal;
using System.Runtime.InteropServices;
 
using Microsoft.Win32; // for Registry and RegistryKey classes
 
using MS.Internal.WindowsBase; 

namespace MS.Internal.Security.RightsManagement 
{
    /// 
    ///     Critical:    This class expose access to methods that eventually do one or more of the the following
    ///             1. call into unmanaged code 
    ///             2. affects state/data that will eventually cross over unmanaged code boundary
    ///             3. Return some RM related information which is considered private 
    ///  
    [SecurityCritical(SecurityCriticalScope.Everything)]
    internal class ClientSession : IDisposable 
    {
        internal ClientSession(ContentUser user)
            :
                    this(user, UserActivationMode.Permanent) 
        {
        } 
 
        internal ClientSession(
            ContentUser user, 
            UserActivationMode userActivationMode)
        {
            Invariant.Assert(user != null);
            Invariant.Assert((userActivationMode == UserActivationMode.Permanent) || 
                                    (userActivationMode == UserActivationMode.Temporary));
 
            _user = user; 
            _userActivationMode = userActivationMode;
 
            // prepare callback handler
            _callbackHandler = new CallbackHandler();

            int hr = SafeNativeMethods.DRMCreateClientSession( 
                _callbackHandler.CallbackDelegate,
                NativeConstants.DrmCallbackVersion, 
                _user.AuthenticationProviderType, 
                _user.Name,
                out _hSession); 

            Errors.ThrowOnErrorCode(hr);
            Invariant.Assert((_hSession != null) && (!_hSession.IsInvalid));
        } 

        ~ClientSession() 
        { 
            Dispose(false);
        } 

        public void Dispose()
        {
            Dispose(true); 
            GC.SuppressFinalize(this);
        } 
 
        protected virtual void Dispose(bool disposing)
        { 
            if (disposing)
            {
                // close all the CryptoProviders that are bound to the Session
                // This way if user attempt to close SecureEnvironment while using the CryptoProvider 
                // the meaningful object Disposed exception will be thrown instead of misleading
                // Interop exception indicating that an invalid handle was used. 
                try 
                {
                    if (_cryptoProviderList != null) 
                    {
                        foreach (CryptoProvider cryptoProvider in _cryptoProviderList)
                        {
                            cryptoProvider.Dispose(); 
                        }
                    } 
                } 
                finally
                { 
                    _cryptoProviderList = null;

                    // close session handle which is a DRMHSESSION
                    try 
                    {
                        if ((_hSession != null) && 
                            (!_hSession.IsInvalid)) 
                        {
                            // if we deal with temporatry activation we should clean up 
                            // Group Identity Cerytificates and the Client Licensor Certificates
                            if (_userActivationMode == UserActivationMode.Temporary)
                            {
                                RemoveUsersCertificates(EnumerateLicenseFlags.SpecifiedClientLicensor); 
                                RemoveUsersCertificates(EnumerateLicenseFlags.SpecifiedGroupIdentity);
                            } 
 
                            _hSession.Dispose();
                        } 
                    }
                    finally
                    {
                        _hSession = null; 

                        // close default library handle which is a DRMHANDLE 
                        try 
                        {
                            if ((_defaultLibraryHandle != null) && 
                                (!_defaultLibraryHandle.IsInvalid))
                            {
                                _defaultLibraryHandle.Dispose();
                            } 
                        }
                        finally 
                        { 
                            _defaultLibraryHandle = null;
 
                            // close secure environment handle which is a DRMENVHANDLE
                            try
                            {
                                if ((_envHandle != null) && 
                                     (!_envHandle.IsInvalid))
                                { 
                                    _envHandle.Dispose(); 
                                }
                            } 
                            finally
                            {
                                _envHandle = null;
 
                                // Dispose call back handler
                                try 
                                { 
                                    if (_callbackHandler != null)
                                    { 
                                        _callbackHandler.Dispose();
                                    }
                                }
                                finally 
                                {
                                    _callbackHandler = null; 
                                } 
                            }
                        } 
                    }
                }
            }
        } 

        internal static ClientSession DefaultUserClientSession(AuthenticationType authentication) 
        { 
            return new ClientSession(new ContentUser(_defaultUserName, authentication));
        } 

        internal bool IsMachineActivated()
        {
            CheckDisposed(); 

            return IsActivated(ActivationFlags.Machine) && (GetMachineCert() != null); 
        } 

        internal void ActivateMachine(AuthenticationType authentication) 
        {
            CheckDisposed();

            // machine activation is always silent 
            ActivationFlags actFlags = ActivationFlags.Machine | ActivationFlags.Silent;
 
            Activate(actFlags, null); // GetActivationUrl(authentication));  // for local activation we do not need URL 
            // as we have Hard dependency on SP1 lock box - which is the only one that
            // is managed code friendly, we should never try to activate machine 
            // using URL - always local SP1 activation
        }

        internal bool IsUserActivated() 
        {
            CheckDisposed(); 
 
            // check that group identity is activated
            if (!IsActivated(ActivationFlags.GroupIdentity)) 
            {
                return false;
            }
 
            // enumerate user certificates andg get the current one
            string userCertificateChain = GetGroupIdentityCert(); 
 
            if (userCertificateChain == null)
            { 
                return false;
            }

            // extract identity from the certitficate and match it with the user 
            ContentUser userFromCert = ExtractUserFromCertificateChain(userCertificateChain);
 
            if (userFromCert == null) 
            {
                return false; 
            }

            // make sure the user matches completely (including authentication type).
            // All the checks above will pass if the requested user identity and 
            // activated user identity only differ by authentication type.
            return _user.GenericEquals(userFromCert); 
        } 

        internal ContentUser ActivateUser( 
            AuthenticationType authentication, UserActivationMode userActivationMode)
        {
            CheckDisposed();
 
            ActivationFlags actFlags = ActivationFlags.GroupIdentity;
 
            // for windows Silen Flag must be set For Passport it must not be set 
            if (_user.AuthenticationType == AuthenticationType.Windows)
            { 
                actFlags |= ActivationFlags.Silent;
            }

            if (userActivationMode == UserActivationMode.Temporary) 
            {
                actFlags |= ActivationFlags.Temporary; 
            } 

            string userCertificate = 
                Activate(actFlags, GetCertificationUrl(authentication));

            return ExtractUserFromCertificate(userCertificate);
        } 

        internal bool IsClientLicensorCertificatePresent() 
        { 
            CheckDisposed();
 
            return (GetClientLicensorCert() != null);
        }

        ///  
        /// This function is used to acquire a license either an End Use license
        /// or a Client Licensor Certificate 
        ///  
        internal void AcquireClientLicensorCertificate()
        { 
            CheckDisposed();

            // get the URL for Client Licensor Cert Acquisition
            Uri url = GetClientLicensorUrl(_user.AuthenticationType); 

            string license = GetGroupIdentityCert(); 
 
            int hr = SafeNativeMethods.DRMAcquireLicense(
                _hSession, 
                0,  // flags default to 0  for CLC acquisition
                license,
                null,  // requested data is reserved and not used
                null, // custom data 
                url.AbsoluteUri,  // We are using Uri class as a basic validation mechanism. These URIs come from unmanaged
                // code libraries and go back as parameters into the unmanaged code libraries. 
                // We use AbsoluteUri property as means of verifying that it is actually an absolute and 
                // well formed Uri. If by any chance it happened to be a relative URI, an exception will
                // be thrown here. This will perform the necessary escaping. 

                IntPtr.Zero);    // context

            Errors.ThrowOnErrorCode(hr); 

            _callbackHandler.WaitForCompletion();     // it will throw a proper exception in a failure case 
        } 

        internal void BuildSecureEnvironment(string applicationManifest) 
        {
            CheckDisposed();

            Invariant.Assert(_envHandle == null); 

            string providerPath = GetSecurityProviderPath(); 
            string machineCertificate = GetMachineCert(); 

            _defaultLibraryHandle = null; 
            _envHandle = null;

            int hr = SafeNativeMethods.DRMInitEnvironment(
                (uint)SecurityProviderType.SoftwareSecRep, 
                (uint)SpecType.FileName,
                providerPath, 
                applicationManifest, 
                machineCertificate,
                out _envHandle, 
                out _defaultLibraryHandle);

            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((_envHandle != null) && (!_envHandle.IsInvalid)); 
        }
 
        private bool IsActivated(ActivationFlags activateFlags) 
        {
            CheckDisposed(); 

            return (0 == SafeNativeMethods.DRMIsActivated(_hSession, (uint)activateFlags, null));
        }
 
        internal string GetMachineCert()
        { 
            CheckDisposed(); 

            // We always assume that the first machine certificate is the correct one 
            return EnumerateLicense(EnumerateLicenseFlags.Machine, 0);
        }

        ///  
        ///  This function is used to build a List of certificates of a given type (Licensor or Identity)
        ///  From all of the certificates based on the matching of the User Id 
        ///  
        internal List EnumerateUsersCertificateIds(
                                                                                ContentUser user, 
                                                                                EnumerateLicenseFlags certificateType)
        {
            CheckDisposed();
 
            if ((certificateType != EnumerateLicenseFlags.Machine) &&
                                    (certificateType != EnumerateLicenseFlags.GroupIdentity) && 
                                    (certificateType != EnumerateLicenseFlags.GroupIdentityName) && 
                                    (certificateType != EnumerateLicenseFlags.GroupIdentityLid) &&
                                    (certificateType != EnumerateLicenseFlags.SpecifiedGroupIdentity) && 
                                    (certificateType != EnumerateLicenseFlags.Eul) &&
                                    (certificateType != EnumerateLicenseFlags.EulLid) &&
                                    (certificateType != EnumerateLicenseFlags.ClientLicensor) &&
                                    (certificateType != EnumerateLicenseFlags.ClientLicensorLid) && 
                                    (certificateType != EnumerateLicenseFlags.SpecifiedClientLicensor) &&
                                    (certificateType != EnumerateLicenseFlags.RevocationList) && 
                                    (certificateType != EnumerateLicenseFlags.RevocationListLid) && 
                                    (certificateType != EnumerateLicenseFlags.Expired))
            { 
                throw new ArgumentOutOfRangeException("certificateType");
            }

            List certificateIdList = new List(); 

            int index = 0; 
            // first enumerate certificates and find the ones that match given user 
            while (true)
            { 
                // we get a string which can be parsed to get the ID and type
                string currentUserCertificate = EnumerateLicense(certificateType, index);

                if (currentUserCertificate == null) 
                    break;
 
                // we need to parse the information out of the string 
                ContentUser currentUser = ExtractUserFromCertificateChain(currentUserCertificate);
 
                // let's see if we have a match on the User Id, if we do we need to add it to the list
                if (user.GenericEquals(currentUser))
                {
                    // we got a match let's preserve the certificate in the list 
                    certificateIdList.Add(ClientSession.ExtractCertificateIdFromCertificateChain(currentUserCertificate));
                } 
 
                index++;
            } 

            return certificateIdList;
        }
 
        internal void DeleteLicense(string licenseId)
        { 
            CheckDisposed(); 

            int hr = SafeNativeMethods.DRMDeleteLicense(_hSession, licenseId); 
            Errors.ThrowOnErrorCode(hr);
        }

        internal void RemoveUsersCertificates(EnumerateLicenseFlags certificateType) 
        {
            CheckDisposed(); 
 
            // We only expect to be called for removal of the specific Group Identity Certs
            // and the specific Client Licensor Certs 
            Invariant.Assert((certificateType == EnumerateLicenseFlags.SpecifiedClientLicensor) ||
                                  (certificateType == EnumerateLicenseFlags.SpecifiedGroupIdentity));

            // We actually need to enumerate all the specified identity certs and then parse 
            // them to get the license Id , and only then remove them
            ArrayList certList = EnumerateAllValuesOnSession(_hSession, certificateType); 
 
            foreach (string cert in certList)
            { 
                DeleteLicense(ExtractCertificateIdFromCertificateChain(cert));
            }
        }
 
        private string GetClientLicensorCert()
        { 
            return GetLatestCertificate(EnumerateLicenseFlags.SpecifiedClientLicensor); 
        }
 
        private string GetGroupIdentityCert()
        {
            return GetLatestCertificate(EnumerateLicenseFlags.SpecifiedGroupIdentity);
        } 

        private string GetLatestCertificate(EnumerateLicenseFlags enumerateLicenseFlags) 
        { 
            int index = 0;
 
            string currentCert = EnumerateLicense(enumerateLicenseFlags, index);
            if (currentCert == null)
            {
                return null; 
            }
 
            DateTime currentTimeStamp = ExtractIssuedTimeFromCertificateChain(currentCert, DateTime.MinValue); 

            while (currentCert != null) 
            {
                index++;

                string newCert = EnumerateLicense(enumerateLicenseFlags, index); 

                // if we have completed the enumeration we can stop right here 
                if (newCert == null) 
                {
                    break; 
                }

                DateTime newTimeStamp = ExtractIssuedTimeFromCertificateChain(newCert, DateTime.MinValue);
 
                if (DateTime.Compare(currentTimeStamp, newTimeStamp) < 0)
                { 
                    currentCert = newCert; 
                    currentTimeStamp = newTimeStamp;
                } 
            }

            return currentCert;
        } 

        private static ArrayList EnumerateAllValuesOnSession(SafeRightsManagementSessionHandle sessionHandle, EnumerateLicenseFlags enumerateLicenseFlags) 
        { 
            ArrayList result = new ArrayList(5);
            int index = 0; 

            while (true)
            {
                string currentRes = GetLicenseOnSession(sessionHandle, enumerateLicenseFlags, index); 

                if (currentRes == null) 
                { 
                    break;
                } 
                result.Add(currentRes);
                index++;
            }
            return result; 
        }
 
        internal static string GetLicenseOnSession(SafeRightsManagementSessionHandle sessionHandle, EnumerateLicenseFlags enumerateLicenseFlags, int index) 
        {
            Invariant.Assert(index >= 0); 

            if ((enumerateLicenseFlags != EnumerateLicenseFlags.Machine) &&
                (enumerateLicenseFlags != EnumerateLicenseFlags.GroupIdentity) &&
                (enumerateLicenseFlags != EnumerateLicenseFlags.GroupIdentityName) && 
                (enumerateLicenseFlags != EnumerateLicenseFlags.GroupIdentityLid) &&
                (enumerateLicenseFlags != EnumerateLicenseFlags.SpecifiedGroupIdentity) && 
                (enumerateLicenseFlags != EnumerateLicenseFlags.Eul) && 
                (enumerateLicenseFlags != EnumerateLicenseFlags.EulLid) &&
                (enumerateLicenseFlags != EnumerateLicenseFlags.ClientLicensor) && 
                (enumerateLicenseFlags != EnumerateLicenseFlags.ClientLicensorLid) &&
                (enumerateLicenseFlags != EnumerateLicenseFlags.SpecifiedClientLicensor) &&
                (enumerateLicenseFlags != EnumerateLicenseFlags.RevocationList) &&
                (enumerateLicenseFlags != EnumerateLicenseFlags.RevocationListLid) && 
                (enumerateLicenseFlags != EnumerateLicenseFlags.Expired))
            { 
                throw new ArgumentOutOfRangeException("enumerateLicenseFlags"); 
            }
 
            int hr = 0;
            bool sharedFlag = false;
            uint dataLen = 0;
            StringBuilder license = null; 

            hr = SafeNativeMethods.DRMEnumerateLicense( 
                sessionHandle, (uint)enumerateLicenseFlags, (uint)index, ref sharedFlag, ref dataLen, null); 

            if (hr == (int)RightsManagementFailureCode.NoMoreData) 
                return null;

            Errors.ThrowOnErrorCode(hr);
 
            if (dataLen > System.Int32.MaxValue)
                return null; 
 
            //returned size accounts for null termination; we do not need to add 1
            checked 
            {
                license = new StringBuilder((int)dataLen);
            }
 
            hr = SafeNativeMethods.DRMEnumerateLicense(
                sessionHandle, (uint)enumerateLicenseFlags, (uint)index, ref sharedFlag, ref dataLen, license); 
 
            Errors.ThrowOnErrorCode(hr);
 
            return license.ToString();
        }

        internal string EnumerateLicense(EnumerateLicenseFlags enumerateLicenseFlags, int index) 
        {
            CheckDisposed(); 
 
            return GetLicenseOnSession(_hSession, enumerateLicenseFlags, index);
        } 

        internal PublishLicense SignIssuanceLicense(IssuanceLicense issuanceLicense, out UseLicense authorUseLicense)
        {
            CheckDisposed(); 

            Invariant.Assert(issuanceLicense != null); 
            Invariant.Assert(!_envHandle.IsInvalid); 

            using (CallbackHandler signIssuanceLicenseCallbackHandler = new CallbackHandler()) 
            {
                string clientLicensorCertificate = GetClientLicensorCert();

                if (clientLicensorCertificate == null) 
                    throw new RightsManagementException(SR.Get(SRID.UserHasNoClientLicensorCert));
 
                // Trim all the leading and trailing white space characters 
                // of the clientLicensorCertificate.
                clientLicensorCertificate = clientLicensorCertificate.Trim(); 

                // Make sure the clientLicensorCertificate is valid. By trimming white spaces
                // above, if the certificate string is empty or contains only white spaces, it
                // is empty now. 
                if (clientLicensorCertificate.Length == 0)
                    throw new RightsManagementException(SR.Get(SRID.UserHasNoClientLicensorCert)); 
 
                // Offline publishing supported no Online publishing support
                int hr = SafeNativeMethods.DRMGetSignedIssuanceLicense( 
                    _envHandle,
                    issuanceLicense.Handle,
                    (uint)(SignIssuanceLicenseFlags.Offline |
                                SignIssuanceLicenseFlags.AutoGenerateKey | 
                                SignIssuanceLicenseFlags.OwnerLicenseNoPersist),
                    null, 
                    0, 
                    NativeConstants.ALGORITHMID_AES,     // currently AES is the only supported key type
                    clientLicensorCertificate, 
                    signIssuanceLicenseCallbackHandler.CallbackDelegate,
                    null, // we are only supporting offline publishing no url needed
                    0); // no context required
 
                Errors.ThrowOnErrorCode(hr);
 
                signIssuanceLicenseCallbackHandler.WaitForCompletion();     // it will throw a proper exception in a failure case 

                // build publish License from th result 
                PublishLicense publishLicense = new PublishLicense(
                    signIssuanceLicenseCallbackHandler.CallbackData);

                // After Issuance license is signed we should build the Author's Use License 
                authorUseLicense = new UseLicense(GetOwnerLicense(issuanceLicense.Handle));
 
                return publishLicense; 
            }
        } 

        internal UseLicense AcquireUseLicense(string publishLicense, bool noUI)
        {
            CheckDisposed(); 

            Invariant.Assert(!_envHandle.IsInvalid); 
 
            SafeRightsManagementSessionHandle licenseStorageSessionHandle = null;
 
            //first let's build the license storage session
            int hr = SafeNativeMethods.DRMCreateLicenseStorageSession(
                _envHandle,
                _defaultLibraryHandle, 
                _hSession,
                0, 
                publishLicense, 
                out licenseStorageSessionHandle);
 
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((licenseStorageSessionHandle != null) && (!licenseStorageSessionHandle.IsInvalid));

            using (licenseStorageSessionHandle) 
            {
                uint flags = 0; 
                if (noUI) 
                {
                    flags |= (uint)AcquireLicenseFlags.NoUI; 
                }

                string license = GetGroupIdentityCert();
 
                // the newly acquired use license will be added to the License Storage Session.
                // We need to enumerate all the entries before and after in order to properly find the new one 
                ArrayList oldLicenseIds = EnumerateAllValuesOnSession 
                                        (licenseStorageSessionHandle, EnumerateLicenseFlags.EulLid);
 
                hr = SafeNativeMethods.DRMAcquireLicense(
                    licenseStorageSessionHandle,
                    flags,
                    license, 
                    null,  // requested data is reserved and not used
                    null, // custom data 
                    null, //no url required it will be taken from publish license 
                    IntPtr.Zero);    // context
 
                Errors.ThrowOnErrorCode(hr);

                _callbackHandler.WaitForCompletion();         // it will throw a proper exception in a failure case
 
                // now we can enumerate the EUL Ids  again and try to find the new one
                ArrayList newLicenseIds = EnumerateAllValuesOnSession 
                                        (licenseStorageSessionHandle, EnumerateLicenseFlags.EulLid); 

                int indexOfTheAcquiredLicense = FindNewEntryIndex(oldLicenseIds, newLicenseIds); 

                if (indexOfTheAcquiredLicense < 0)
                {
                    // we have failed to find the new license 
                    throw new RightsManagementException(RightsManagementFailureCode.LicenseAcquisitionFailed);
                } 
 
                return new UseLicense(GetLicenseOnSession(
                                                            licenseStorageSessionHandle, 
                                                            EnumerateLicenseFlags.Eul,
                                                            indexOfTheAcquiredLicense));
            }
        } 

        private static int FindNewEntryIndex(ArrayList oldList, ArrayList newList) 
        { 
            Invariant.Assert((oldList != null) && (newList != null));
 
            for (int i = 0; i < newList.Count; i++)
            {
                string newElement = (string)newList[i];
                bool matchFound = false; 

                foreach (string oldElement in oldList) 
                { 
                    if (String.CompareOrdinal(newElement, oldElement) == 0)
                    { 
                        matchFound = true;
                        break;
                    }
                } 

                // we have found an entry in the newList without a match in the old list 
                // we can return the index 
                if (!matchFound)
                { 
                    return i;
                }
            }
 
            // No new entry were found
            return -1; 
        } 

        // This function attempts to bind License to a given Identity 
        // It will try to bind all rights One-by-one in order to eliminate
        // grants that may have been expired, so it will only bind The ones that are still valid
        private CryptoProvider BindUseLicense(string serializedUseLicense,
                                                                List unboundRightsList, 
                                                                BoundLicenseParams boundLicenseParams,
                                                                out int theFirstHrFailureCode) 
        { 
            Debug.Assert(serializedUseLicense != null);
            Debug.Assert(unboundRightsList != null); 
            Debug.Assert(boundLicenseParams != null);


            List successfullyBoundLicenseHandleList = 
                        new List(unboundRightsList.Count);
 
            List successfullyBoundRightsList = 
                        new List(unboundRightsList.Count);
            try 
            {
                uint errorLogHandle;

                // we neeed to return the first failure code, that is the one that will communicate to the user 
                int hr;
                theFirstHrFailureCode = 0; 
 
                SafeRightsManagementHandle boundLicenseHandle;
 
                // first we are enumerating all rights one-by-one and preserving the ones that can be bound
                // we are going through the list of "recognised rights"
                foreach (RightNameExpirationInfoPair rightInfo in unboundRightsList)
                { 

                    boundLicenseParams.wszRightsRequested = rightInfo.RightName; 
                    boundLicenseHandle = null; 
                    errorLogHandle = 0;
 
                    hr = SafeNativeMethods.DRMCreateBoundLicense(
                                                _envHandle,
                                                boundLicenseParams,
                                                serializedUseLicense, 
                                                out boundLicenseHandle,
                                                out errorLogHandle); 
 
                    if (boundLicenseHandle != null && (hr == 0))
                    { 
                        // we got a successful bound let's copy the whole grant
                        // the only thing that we need to substitute in the grant is the User identity
                        // along with the original right name (prior to binding), as unmanaged SDK
                        // messes up right names and their expiration 
                        // in case of multiple expiration dates and additional rights granted to an owner
                        successfullyBoundLicenseHandleList.Add(boundLicenseHandle); 
                        successfullyBoundRightsList.Add(rightInfo); 
                    }
 
                    // preserve the first encountered error code
                    if ((theFirstHrFailureCode == 0) && (hr != 0))
                    {
                        theFirstHrFailureCode = hr; 
                    }
                } 
 
                // At this point we have a list of potential "Right" -candidates
                // if it is empty we can get out 
                if (successfullyBoundLicenseHandleList.Count > 0)
                {
                    ContentUser user = ExtractUserFromCertificateChain(boundLicenseParams.wszDefaultEnablingPrincipalCredentials);
 
                    CryptoProvider cryptoProvider = new CryptoProvider(successfullyBoundLicenseHandleList,
                                                                    successfullyBoundRightsList, 
                                                                    user); 
                    CryptoProviderList.Add(cryptoProvider);
                    return cryptoProvider; 
                }
                else
                {
                    return null; 
                }
            } 
            catch 
            {
                // In case of a failure we should clean up handle that have been accumulated 
                // otherwise the list of handles is either empty or given to the CryptoProvider
                // to be taken care of
                foreach (SafeRightsManagementHandle handle in successfullyBoundLicenseHandleList)
                { 
                    handle.Dispose();
                } 
                throw; 
            }
        } 


        internal CryptoProvider TryBindUseLicenseToAllIdentites(string serializedUseLicense)
        { 
            CheckDisposed();
 
            Invariant.Assert(serializedUseLicense != null); 

            int hr = 0; 
            int theFirstHrFailureCode = 0;

            ///////////////////////////
            // prepare bound license param structure 
            ///////////////////////////
            //prepare for binding (enumerate unbound rights) 
            string rightsGroupName; 

            List unboundRightsList = 
                        GetRightsInfoFromUseLicense(serializedUseLicense, out rightsGroupName);

            BoundLicenseParams boundLicenseParams = new BoundLicenseParams();
 
            boundLicenseParams.uVersion = 0;
            boundLicenseParams.hEnablingPrincipal = 0; 
            boundLicenseParams.hSecureStore = 0; 
            boundLicenseParams.wszRightsGroup = rightsGroupName;
 
            string contentId;
            string contentIdType;
            GetContentIdFromLicense(serializedUseLicense, out contentId, out contentIdType);
 
            boundLicenseParams.DRMIDuVersion = 0;
            boundLicenseParams.DRMIDIdType = contentIdType; 
            boundLicenseParams.DRMIDId = contentId; 

            boundLicenseParams.cAuthenticatorCount = 0;//reserved.should be 0. 
            boundLicenseParams.rghAuthenticators = IntPtr.Zero;

            string userCertificate = GetGroupIdentityCert();
 
            boundLicenseParams.wszDefaultEnablingPrincipalCredentials = userCertificate;
 
            boundLicenseParams.dwFlags = 0; 

            // let's try to bind this using currently provided user first 
            CryptoProvider cryptoProvider = BindUseLicense(serializedUseLicense,
                                                                unboundRightsList,
                                                                boundLicenseParams,
                                                                out hr); 

            if (cryptoProvider != null) 
            { 
                return cryptoProvider;
            } 

            // preserve the first encountered error code
            if ((theFirstHrFailureCode == 0) && (hr != 0))
            { 
                theFirstHrFailureCode = hr;
            } 
 
            // now if the current user failed we can try to enumerate all the userr certificates
            // and go through them one-by-one 
            int userCertIndex = 0;
            while (true)
            {
                userCertificate = EnumerateLicense(EnumerateLicenseFlags.GroupIdentity, userCertIndex); 
                if (userCertificate == null)
                { 
                    // we have to enumerate all of the user certs . . . 
                    break;
                } 
                userCertIndex++;
                boundLicenseParams.wszDefaultEnablingPrincipalCredentials = userCertificate;

                cryptoProvider = BindUseLicense(serializedUseLicense, 
                                                                unboundRightsList,
                                                                boundLicenseParams, 
                                                                out hr); 

                if (cryptoProvider != null) 
                {
                    return cryptoProvider;
                }
 
                // preserve the first encountered error code
                if ((theFirstHrFailureCode == 0) && (hr != 0)) 
                { 
                    theFirstHrFailureCode = hr;
                } 
            }

            // at this point we can only translate failure into some meaningfull exception
            Invariant.Assert(theFirstHrFailureCode != 0); // it must contain an error as a succesfull return above should take of non-failure cases 
            Errors.ThrowOnErrorCode(theFirstHrFailureCode);
            return null; 
        } 

        // The newer SDK automatically does machine activation. This function would be necessary if we had 
        // to support the older SDK.
#if needToActivateExplicitly
        private Uri GetActivationUrl(AuthenticationType authentication)
        { 
            if (authentication == AuthenticationType.Windows)
            { 
                return GetServiceLocation(ServiceType.Activation, ServiceLocation.Enterprise, null); 
            }
            else if (authentication == AuthenticationType.Passport) 
            {
                return GetServiceLocation(ServiceType.Activation, ServiceLocation.Internet, null);
            }
            else 
            {
                Debug.Assert(false,"Invalid Authentication type"); 
                return null;            // retail build might be ale to recover from SDK defaults 
            }
        } 
#endif

        private Uri GetCertificationUrl(AuthenticationType authentication)
        { 
            Debug.Assert((authentication == AuthenticationType.Windows) ||
                               (authentication == AuthenticationType.Passport)); 
 
            // for Passport scenario we just use default null value everywhere and expect promethium
            // SDK do proper server discovery 
            Uri server = null;

            if (authentication == AuthenticationType.Windows)
            { 
                // first try to get Corporate Domain server, if it fails try the internet
                // regardless of the user type 
                server = GetServiceLocation(ServiceType.Certification, ServiceLocation.Enterprise, null); 

                if (server == null) 
                {
                    server = GetServiceLocation(ServiceType.Certification, ServiceLocation.Internet, null);
                }
            } 
            else // it must be passport
            { 
                // 1st we need to check regiostry for override, and then if it missing we can use Discovery Service 
                server = GetRegistryPassportCertificationUrl();
                if (server == null) 
                {  // let's use server discovery
                    server = GetServiceLocation(ServiceType.Certification, ServiceLocation.Internet, null);
                }
            } 

            return server; 
        } 

 

        private static Uri GetRegistryPassportCertificationUrl()
        {
            // This Function Will return null, if the registry entry is missing 

            // Acquire permissions to read the one key we care about from the registry 
            RegistryPermission permission = new RegistryPermission( 
                    RegistryPermissionAccess.Read,
                    System.Security.AccessControl.AccessControlActions.View, 
                    _passportActivationRegistryFullKeyName);

            permission.Assert();
 
            try
            { 
                RegistryKey key = Registry.LocalMachine.OpenSubKey(_passportActivationRegistryKeyName); 
                if (key == null)
                { 
                    return null;
                }
                else
                { 
                    object keyValue = key.GetValue(null); // this should get the default value
                    string stringValue = keyValue as string; 
                    if (stringValue != null) 
                    {
                        return new Uri(stringValue); 
                    }
                    else
                    {
                        return null; 
                    }
                } 
            } 
            finally
            { 
                RegistryPermission.RevertAssert();
            }
        }
 
        private Uri GetClientLicensorUrl(AuthenticationType authentication)
        { 
            Debug.Assert((authentication == AuthenticationType.Windows) || 
                               (authentication == AuthenticationType.Passport));
 
            // Both, for Passport and Windows authenticvation types scenarios we do the same server discovery:
            // first try to get Corporate Domain server
            Uri server = GetServiceLocation(ServiceType.ClientLicensor, ServiceLocation.Enterprise, null);
 
            if (server == null)
            { 
                // if it fails try the internet discovery services 
                server = GetServiceLocation(ServiceType.ClientLicensor, ServiceLocation.Internet, null);
            } 

            return server;
        }
 
#if false           // re-enable when needed, This is only needed for on-line publishing, which currently isn't supported
        private Uri GetClientPublishingUrl() 
        { 
            // first try to get Corporate Domain server, if it fails try the internet
            // regardless of the user type 
            Uri server = GetServiceLocation(ServiceType.Publishing, ServiceLocation.Enterprise, null);

            if (server != null)
            { 
                return server;
            } 
 
            return GetServiceLocation(ServiceType.Publishing, ServiceLocation.Internet, null);
        } 
#endif

        /// 
        /// The Activate function obtains a lockbox and machine certificate for a machine or a rights 
        /// account certificate for a user (depend on activationFlags).
        ///  
        private string Activate( 
            ActivationFlags activationFlags, Uri url)
        { 
            // Optional server information. To query UDDI for an activation URL, pass in NULL
            ActivationServerInfo activationServer = null;

            if (url != null) 
            {
                activationServer = new ActivationServerInfo(); 
                activationServer.PubKey = null; 
                activationServer.Url = url.AbsoluteUri;  // We are using Uri class as a basic validation mechanism. These URIs come from unmanaged
                // code libraries and go back as parameters into the unmanaged code libraries. 
                // We use AbsoluteUri property as means of verifying that it is actually an absolute and
                // well formed Uri. If by any chance it happened to be a relative URI, an exception will
                // be thrown here. This will perform the necessary escaping.
 
                activationServer.Version = NativeConstants.DrmCallbackVersion;
            } 
 
            int hr = SafeNativeMethods.DRMActivate(
                _hSession, 
                (uint)activationFlags,
                0,                          //language Id
                activationServer,
                IntPtr.Zero,    // context 
                IntPtr.Zero);  // parent Window handle
 
            Errors.ThrowOnErrorCode(hr); 

            _callbackHandler.WaitForCompletion();        // it will throw a proper exception in a failure case 

            return _callbackHandler.CallbackData;
        }
 
        private Uri GetServiceLocation(
                ServiceType serviceType, ServiceLocation serviceLocation, string issuanceLicense) 
        { 
            uint serviceUrlLength = 0;
            StringBuilder serviceUrl = null; 

            int hr = SafeNativeMethods.DRMGetServiceLocation(
                _hSession, (uint)serviceType, (uint)serviceLocation, issuanceLicense, ref serviceUrlLength, null);
 
            if (hr == (int)RightsManagementFailureCode.UseDefault)
            { 
                // there is a special case in which this error code means that application supposed to use the default nul URL 
                return null;
            } 

            Errors.ThrowOnErrorCode(hr);

            checked 
            {
                serviceUrl = new StringBuilder((int)serviceUrlLength); 
            } 

            hr = SafeNativeMethods.DRMGetServiceLocation( 
                _hSession, (uint)serviceType, (uint)serviceLocation, issuanceLicense, ref serviceUrlLength, serviceUrl);

            Errors.ThrowOnErrorCode(hr);
 
            return new Uri(serviceUrl.ToString());
        } 
 
        internal static string GetOwnerLicense(SafeRightsManagementPubHandle issuanceLicenseHandle)
        { 
            Invariant.Assert(!issuanceLicenseHandle.IsInvalid);

            uint ownerLicenseLength = 0;
            StringBuilder ownerLicense = null; 

            int hr = SafeNativeMethods.DRMGetOwnerLicense( 
                issuanceLicenseHandle, ref ownerLicenseLength, null); 
            Errors.ThrowOnErrorCode(hr);
 
            checked
            {
                ownerLicense = new StringBuilder((int)ownerLicenseLength);
            } 

            hr = SafeNativeMethods.DRMGetOwnerLicense( 
                issuanceLicenseHandle, ref ownerLicenseLength, ownerLicense); 
            Errors.ThrowOnErrorCode(hr);
 
            return ownerLicense.ToString();
        }

        static private string GetElementFromCertificateChain( 
            string certificateChain, int index)
        { 
            Invariant.Assert(index >= 0); 
            Invariant.Assert(certificateChain != null);
            uint chainElementSize = 0; 
            StringBuilder chainElement = null;

            int hr = SafeNativeMethods.DRMDeconstructCertificateChain(
                certificateChain, 
                (uint)index,
                ref chainElementSize, 
                null); 

            Errors.ThrowOnErrorCode(hr); 

            checked
            {
                chainElement = new StringBuilder((int)chainElementSize); 
            }
 
            hr = SafeNativeMethods.DRMDeconstructCertificateChain( 
                certificateChain,
                (uint)index, 
                ref chainElementSize,
                chainElement);

            Errors.ThrowOnErrorCode(hr); 

            return chainElement.ToString(); 
        } 

        private static string GetUnboundLicenseStringAttribute( 
            SafeRightsManagementQueryHandle queryHandle, string attributeType, uint attributeIndex)
        {
            uint attributeSize = 0;
            byte[] dataBuffer = null; 

            uint encodingType; 
 
            // get the attribute information (memory size to be allocated)
            int hr = SafeNativeMethods.DRMGetUnboundLicenseAttribute( 
                queryHandle, attributeType, attributeIndex, out encodingType, ref attributeSize, null);

            if (hr == (int)RightsManagementFailureCode.QueryReportsNoResults)
            { 
                return null;
            } 
            Errors.ThrowOnErrorCode(hr); 

            // this is the size of the null terminator so essentially this is an empty string 
            if (attributeSize < 2)
                return null;

            checked 
            {
                dataBuffer = new byte[(int)attributeSize]; 
            } 

            hr = SafeNativeMethods.DRMGetUnboundLicenseAttribute( 
                queryHandle, attributeType, attributeIndex, out encodingType, ref attributeSize, dataBuffer);
            Errors.ThrowOnErrorCode(hr);

            // we need to truncate the last 2 bytes that have unicode 0 termination 
            return Encoding.Unicode.GetString(dataBuffer, 0, dataBuffer.Length - 2);
        } 
 
        // This method has only one caller GetGrantsFromBoundUseLicense(), which is
        // in the 

#if DEBUG
        static private string GetBoundLicenseStringAttribute(
            SafeRightsManagementHandle queryHandle, 
            string attributeType,
            uint attributeIndex) 
        { 
            uint attributeSize = 0;
            byte[] dataBuffer = null; 

            uint encodingType;

            int hr = SafeNativeMethods.DRMGetBoundLicenseAttribute( 
                queryHandle, attributeType, attributeIndex, out encodingType, ref attributeSize, null);
            Errors.ThrowOnErrorCode(hr); 
 
            if (encodingType != (uint)LicenseAttributeEncoding.String)
            { 
                throw new RightsManagementException(RightsManagementFailureCode.InvalidLicense);
            }

            // this is the size of the null terminator so essentially this is an empty string 
            if (attributeSize < 2)
                return null; 
 
            checked
            { 
                dataBuffer = new byte[(int)attributeSize];
            }

            hr = SafeNativeMethods.DRMGetBoundLicenseAttribute( 
                queryHandle, attributeType, attributeIndex, out encodingType, ref attributeSize, dataBuffer);
            Errors.ThrowOnErrorCode(hr); 
 
            // we need to truncate the last 2 bytes that have unicode 0 termination
            return Encoding.Unicode.GetString(dataBuffer, 0, dataBuffer.Length - 2); 
        }
#endif

        static private DateTime GetUnboundLicenseDateTimeAttribute( 
            SafeRightsManagementQueryHandle queryHandle,
            string attributeType, 
            uint attributeIndex, 
            DateTime defaultValue)
        { 
            uint attributeSize = SystemTime.Size;
            byte[] dataBuffer = new byte[attributeSize];
            uint encodingType;
 
            int hr = SafeNativeMethods.DRMGetUnboundLicenseAttribute(
                queryHandle, attributeType, attributeIndex, out encodingType, 
                ref attributeSize, dataBuffer); 

            if (encodingType != (uint)LicenseAttributeEncoding.Time) 
            {
                throw new RightsManagementException(RightsManagementFailureCode.InvalidLicense);
            }
 
            if ((hr == (int)RightsManagementFailureCode.NoMoreData) ||
                 (hr == (int)RightsManagementFailureCode.QueryReportsNoResults)) 
            { 
                return defaultValue;
            } 
            Errors.ThrowOnErrorCode(hr);

            Debug.Assert(attributeSize == SystemTime.Size); // if isn't true it is an indication of a problem in the underlying libraries
 
            SystemTime sysTime = new SystemTime(dataBuffer);
 
            return sysTime.GetDateTime(defaultValue); 
        }
 
        // This method has only one caller GetGrantsFromBoundUseLicense(), which is
        // in the

#if DEBUG 
        static private DateTime GetBoundLicenseDateTimeAttribute(
            SafeRightsManagementHandle queryHandle, 
            string attributeType, 
            uint attributeIndex,
            DateTime defaultValue) 
        {
            uint attributeSize = SystemTime.Size;
            byte[] dataBuffer = new byte[attributeSize];
            uint encodingType; 

            int hr = SafeNativeMethods.DRMGetBoundLicenseAttribute( 
                queryHandle, attributeType, attributeIndex, out encodingType, 
                ref attributeSize, dataBuffer);
 
            if (encodingType != (uint)LicenseAttributeEncoding.Time)
            {
                throw new RightsManagementException(RightsManagementFailureCode.InvalidLicense);
            } 

            if ((hr == (int)RightsManagementFailureCode.NoMoreData) || 
                 (hr == (int)RightsManagementFailureCode.QueryReportsNoResults)) 
            {
                return defaultValue; 
            }
            Errors.ThrowOnErrorCode(hr);

            Debug.Assert(attributeSize == SystemTime.Size); // if isn't true it is an indication of a problem in the underlying libraries 

            SystemTime sysTime = new SystemTime(dataBuffer); 
 
            return sysTime.GetDateTime(defaultValue);
        } 
#endif

        internal static ContentUser ExtractUserFromCertificateChain(string certificateChain)
        { 
            Invariant.Assert(certificateChain != null);
 
            return ExtractUserFromCertificate(GetElementFromCertificateChain(certificateChain, 0)); 
        }
 

        private static DateTime ExtractIssuedTimeFromCertificateChain(
                        string certificateChain,
                        DateTime defaultValue) 
        {
            Invariant.Assert(certificateChain != null); 
 
            return ExtractIssuedTimeFromCertificate(GetElementFromCertificateChain(certificateChain, 0), defaultValue);
        } 

        private static DateTime ExtractIssuedTimeFromCertificate(
                        string certificate,
                        DateTime defaultValue) 
        {
            SafeRightsManagementQueryHandle queryRootHandle = null; 
            int hr; 

            hr = SafeNativeMethods.DRMParseUnboundLicense( 
                certificate,
                out queryRootHandle);
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid)); 

            using (queryRootHandle) 
            { 
                return GetUnboundLicenseDateTimeAttribute(
                            queryRootHandle, 
                            NativeConstants.QUERY_ISSUEDTIME,
                            0,
                            defaultValue);
            } 
        }
 
        internal static ContentUser 
            ExtractUserFromCertificate(string certificate)
        { 
            SafeRightsManagementQueryHandle queryRootHandle = null;

            int hr;
 
            hr = SafeNativeMethods.DRMParseUnboundLicense(
                certificate, 
                out queryRootHandle); 
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid)); 

            using (queryRootHandle)
            {
                SafeRightsManagementQueryHandle querySubHandle = null; 

                hr = SafeNativeMethods.DRMGetUnboundLicenseObject( 
                    queryRootHandle, 
                    NativeConstants.QUERY_ISSUEDPRINCIPAL,
                    0, 
                    out querySubHandle);
                Errors.ThrowOnErrorCode(hr);
                Debug.Assert((querySubHandle != null) && (!querySubHandle.IsInvalid));
 
                using (querySubHandle)
                { 
                    string name = GetUnboundLicenseStringAttribute( 
                        querySubHandle,
                        NativeConstants.QUERY_NAME, 
                        0);

                    string authenticationType = GetUnboundLicenseStringAttribute(
                        querySubHandle, 
                        NativeConstants.QUERY_IDTYPE,
                        0); 
 
                    // We recognise authentication type Windows everything else is assumed to be Passport
                    if (String.CompareOrdinal( 
                        AuthenticationType.Windows.ToString().ToUpper(CultureInfo.InvariantCulture),
                        authenticationType.ToUpper(CultureInfo.InvariantCulture)) == 0)
                    {
                        return new ContentUser(name, AuthenticationType.Windows); 
                    }
                    else 
                    { 
                        return new ContentUser(name, AuthenticationType.Passport);
                    } 
                }
            }
        }
 
        internal static string ExtractCertificateIdFromCertificateChain(string certificateChain)
        { 
            Invariant.Assert(certificateChain != null); 

            return ExtractCertificateIdFromCertificate(GetElementFromCertificateChain(certificateChain, 0)); 
        }

        internal static string
            ExtractCertificateIdFromCertificate(string certificate) 
        {
            SafeRightsManagementQueryHandle queryRootHandle = null; 
 
            int hr = SafeNativeMethods.DRMParseUnboundLicense(
                certificate, 
                out queryRootHandle);
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid));
 
            using (queryRootHandle)
            { 
                string certificateId = GetUnboundLicenseStringAttribute( 
                    queryRootHandle,
                    NativeConstants.QUERY_IDVALUE, 
                    0);

                return certificateId;
            } 
        }
 
        internal static Dictionary ExtractApplicationSpecificDataFromLicense(string useLicenseChain) 
        {
            Invariant.Assert(useLicenseChain != null); 
            Dictionary _applicationSpecificDataDictionary =
                        new Dictionary(3, StringComparer.Ordinal);

            string useLicense = 
                GetElementFromCertificateChain(useLicenseChain, 0);
            Invariant.Assert(useLicense != null); 
 
            SafeRightsManagementQueryHandle queryRootHandle = null;
 
            int hr = SafeNativeMethods.DRMParseUnboundLicense(useLicense, out queryRootHandle);
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid));
 
            using (queryRootHandle)
            { 
                uint index = 0; 
                while (true)
                { 
                    // extract Application Data Name
                    string attributeName = GetUnboundLicenseStringAttribute(queryRootHandle,
                                                            NativeConstants.QUERY_APPDATANAME,
                                                            index); 
                    if (attributeName == null) // null is used to indicate a missing value or an end of sequence
                    { 
                        break; 
                    }
                    Errors.ThrowOnErrorCode(hr); 

                    // extract Application Data Value
                    string attributeValue = GetUnboundLicenseStringAttribute(queryRootHandle,
                                                            NativeConstants.QUERY_APPDATAVALUE, 
                                                            index);
                    Errors.ThrowOnErrorCode(hr); 
 
                    // we expect that dictionary will validate all necessary key/value data requirements
                    _applicationSpecificDataDictionary.Add(attributeName, attributeValue); 

                    index++;
                }
            } 

            return _applicationSpecificDataDictionary; 
        } 

        internal static void GetContentIdFromLicense( 
            string useLicenseChain,
            out string contentId,
            out string contentIdType)
        { 
            Invariant.Assert(useLicenseChain != null);
 
            string useLicense = 
                GetElementFromCertificateChain(useLicenseChain, 0);
            Invariant.Assert(useLicense != null); 

            SafeRightsManagementQueryHandle queryRootHandle = null;

            // Parse the license and get the query handle 
            int hr = SafeNativeMethods.DRMParseUnboundLicense(
                useLicense, 
                out queryRootHandle); 
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid)); 

            using (queryRootHandle)
            {
                SafeRightsManagementQueryHandle workItemQueryHandle = null; 

                // extract object information from each Work Item 
                hr = SafeNativeMethods.DRMGetUnboundLicenseObject( 
                                        queryRootHandle,
                                        NativeConstants.QUERY_WORK, 
                                        0,
                                        out workItemQueryHandle);
                Errors.ThrowOnErrorCode(hr);
                Debug.Assert((workItemQueryHandle != null) && (!workItemQueryHandle.IsInvalid)); 

                using (workItemQueryHandle) 
                { 
                    // get the attributes we are after
                    contentIdType = GetUnboundLicenseStringAttribute( 
                        workItemQueryHandle,
                        NativeConstants.QUERY_IDTYPE,
                        0);
 
                    contentId = GetUnboundLicenseStringAttribute(
                        workItemQueryHandle, 
                        NativeConstants.QUERY_IDVALUE, 
                        0);
                } 
            }
        }

        #region Debug 
        // We currently don’t use these two methods, but they may be useful in the future.
        // So we keep them in the debug build only, and changed them from internal methods 
        // to private methods to remove them from asmmeta files. 
#if DEBUG
        private static List GetGrantsFromBoundUseLicense( 
                                    SafeRightsManagementHandle boundUseLicenseHandle, ContentUser user)
        {
            Invariant.Assert(!boundUseLicenseHandle.IsInvalid);
 
            List resultList = new List(10);
 
            // Go through each ContentRight within group  item 
            for (uint rightIndex = 0; ; rightIndex++)
            { 
                // extract object information from each Work Item
                SafeRightsManagementHandle rightQueryHandle = null;

                int hr = SafeNativeMethods.DRMGetBoundLicenseObject( 
                    boundUseLicenseHandle,
                    NativeConstants.QUERY_RIGHT, 
                    rightIndex, 
                    out rightQueryHandle);
 
                if ((hr == (int)RightsManagementFailureCode.NoMoreData) ||
                     (hr == (int)RightsManagementFailureCode.QueryReportsNoResults))
                {
                    // we got to the end of the RIGHT's list 
                    break;
                } 
 
                Errors.ThrowOnErrorCode(hr);
                Debug.Assert((rightQueryHandle != null) && (!rightQueryHandle.IsInvalid)); 

                using (rightQueryHandle)
                {
                    // We got to the "right" object, now we can ask for the name 
                    string rightName = GetBoundLicenseStringAttribute(rightQueryHandle, NativeConstants.QUERY_NAME, 0);
 
                    // if it is one of the erights that we "understand" we can proceed to query the time interval 
                    Nullable right = GetRightFromString(rightName);
 
                    if (right != null)
                    {
                        DateTime timeFrom = DateTime.MinValue;
                        DateTime timeUntil = DateTime.MaxValue; 

                        SafeRightsManagementHandle rangeTimeQueryHandle = null; 
 
                        hr = SafeNativeMethods.DRMGetBoundLicenseObject(
                            rightQueryHandle, 
                            NativeConstants.QUERY_RANGETIMECONDITION,
                            0,
                            out rangeTimeQueryHandle);
 

                        if ((hr != (int)RightsManagementFailureCode.NoMoreData) && 
                             (hr != (int)RightsManagementFailureCode.QueryReportsNoResults)) 
                        {
                            Errors.ThrowOnErrorCode(hr); 
                            Debug.Assert((rangeTimeQueryHandle != null) && (!rangeTimeQueryHandle.IsInvalid));

                            using (rangeTimeQueryHandle)
                            { 
                                timeFrom = GetBoundLicenseDateTimeAttribute(
                                                rangeTimeQueryHandle, 
                                                NativeConstants.QUERY_FROMTIME, 
                                                0,
                                                DateTime.MinValue); 

                                timeUntil = GetBoundLicenseDateTimeAttribute(
                                                rangeTimeQueryHandle,
                                                NativeConstants.QUERY_UNTILTIME, 
                                                0,
                                                DateTime.MaxValue); 
                            } 
                        }
 
                        resultList.Add(new ContentGrant(user, right.Value, timeFrom, timeUntil));
                    }
                }
            } 
            return resultList;
        } 
 
        private static List GetGrantsFromBoundUseLicenseList(
                                    List boundUseLicenseHandleList, ContentUser user) 
        {
            Invariant.Assert(boundUseLicenseHandleList != null);

            List resultList = new List(boundUseLicenseHandleList.Count); 

            // Go through each ContentRight within group  item 
            foreach (SafeRightsManagementHandle boundUseLicenseHandle in boundUseLicenseHandleList) 
            {
                Debug.Assert(!boundUseLicenseHandle.IsInvalid); 

                List newList = GetGrantsFromBoundUseLicense(boundUseLicenseHandle, user);
                foreach (ContentGrant newGrant in newList)
                { 
                    resultList.Add(newGrant);
                } 
            } 
            return resultList;
        } 
#endif
        #endregion Debug

        private static List GetRightsInfoFromUseLicense( 
            string useLicenseChain,
            out string rightGroupName) 
        { 
            Invariant.Assert(useLicenseChain != null);
 
            string useLicense = GetElementFromCertificateChain(useLicenseChain, 0);
            Invariant.Assert(useLicense != null);

            List resultRightsInfoList = new List(10); 

            SafeRightsManagementQueryHandle queryRootHandle = null; 
 
            // Parse the license and get the query handle
            int hr = SafeNativeMethods.DRMParseUnboundLicense( 
                    useLicense,
                    out queryRootHandle);
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid)); 

            using (queryRootHandle) 
            { 
                SafeRightsManagementQueryHandle workItemQueryHandle = null;
 
                // extract object information from the Work Item
                hr = SafeNativeMethods.DRMGetUnboundLicenseObject(
                    queryRootHandle,
                    NativeConstants.QUERY_WORK, 
                    0,
                    out workItemQueryHandle); 
                Errors.ThrowOnErrorCode(hr); 
                Debug.Assert((workItemQueryHandle != null) && (!workItemQueryHandle.IsInvalid));
 
                using (workItemQueryHandle)
                {
                    SafeRightsManagementQueryHandle rightGroupQueryHandle = null;
 
                    // extract object information from right group Item
                    hr = SafeNativeMethods.DRMGetUnboundLicenseObject( 
                        workItemQueryHandle, 
                        NativeConstants.QUERY_RIGHTSGROUP,
                        0, 
                        out rightGroupQueryHandle);
                    Errors.ThrowOnErrorCode(hr);
                    Debug.Assert((rightGroupQueryHandle != null) && (!rightGroupQueryHandle.IsInvalid));
 
                    using (rightGroupQueryHandle)
                    { 
                        rightGroupName = GetUnboundLicenseStringAttribute( 
                            rightGroupQueryHandle,
                            NativeConstants.QUERY_NAME, 
                            0);

                        // Go through each Right within group  item
                        for (uint rightIndex = 0; ; rightIndex++) 
                        {
                            RightNameExpirationInfoPair rightInfo = 
                                        GetRightInfoFromRightGroupQueryHandle(rightGroupQueryHandle, rightIndex); 

                            if (rightInfo == null) 
                            {
                                break;
                            }
 
                            resultRightsInfoList.Add(rightInfo);
                        } 
                    } 
                }
            } 

            return resultRightsInfoList;
        }
 
        private static RightNameExpirationInfoPair GetRightInfoFromRightGroupQueryHandle
                            (SafeRightsManagementQueryHandle rightGroupQueryHandle, uint rightIndex) 
        { 
            SafeRightsManagementQueryHandle rightQueryHandle = null;
 
            int hr = SafeNativeMethods.DRMGetUnboundLicenseObject(
                    rightGroupQueryHandle,
                    NativeConstants.QUERY_RIGHT,
                    rightIndex, 
                    out rightQueryHandle);
 
            if ((hr == (int)RightsManagementFailureCode.NoMoreData) || 
                     (hr == (int)RightsManagementFailureCode.QueryReportsNoResults))
            { 
                // we got to the end of the RIGHT's list
                return null;
            }
            Errors.ThrowOnErrorCode(hr); 
            Debug.Assert((rightQueryHandle != null) && (!rightQueryHandle.IsInvalid));
 
            using (rightQueryHandle) 
            {
                // We got to the "right" object, now we can ask for the name 
                string rightName = GetUnboundLicenseStringAttribute(
                                                                        rightQueryHandle,
                                                                        NativeConstants.QUERY_NAME,
                                                                        0); 

                DateTime timeFrom = DateTime.MinValue; 
                DateTime timeUntil = DateTime.MaxValue; 

                SafeRightsManagementQueryHandle conditionListHandle = null; 

                // we should also get the expiration infornmation out
                hr = SafeNativeMethods.DRMGetUnboundLicenseObject(
                    rightQueryHandle, 
                    NativeConstants.QUERY_CONDITIONLIST,
                    0, 
                    out conditionListHandle); 

                if (hr >= 0) 
                {
                    Debug.Assert((conditionListHandle != null) && (!conditionListHandle.IsInvalid));

                    using (conditionListHandle) 
                    {
                        SafeRightsManagementQueryHandle rangeTimeQueryHandle = null; 
 
                        hr = SafeNativeMethods.DRMGetUnboundLicenseObject(
                            conditionListHandle, 
                            NativeConstants.QUERY_RANGETIMECONDITION,
                            0,
                            out rangeTimeQueryHandle);
 
                        if ((hr != (int)RightsManagementFailureCode.NoMoreData) &&
                             (hr != (int)RightsManagementFailureCode.QueryReportsNoResults)) 
                        { 
                            Errors.ThrowOnErrorCode(hr);
                            Debug.Assert((rangeTimeQueryHandle != null) && (!rangeTimeQueryHandle.IsInvalid)); 

                            using (rangeTimeQueryHandle)
                            {
                                timeFrom = GetUnboundLicenseDateTimeAttribute( 
                                                rangeTimeQueryHandle,
                                                NativeConstants.QUERY_FROMTIME, 
                                                0, 
                                                DateTime.MinValue);
 
                                timeUntil = GetUnboundLicenseDateTimeAttribute(
                                                rangeTimeQueryHandle,
                                                NativeConstants.QUERY_UNTILTIME,
                                                0, 
                                                DateTime.MaxValue);
                            } 
                        } 
                    }
                } 

                return new RightNameExpirationInfoPair(rightName, timeFrom, timeUntil);
            }
        } 

        internal static string GetContentIdFromPublishLicense(string publishLicense) 
        { 
            Invariant.Assert(publishLicense != null);
 
            SafeRightsManagementQueryHandle queryRootHandle = null;

            // Parse the license and get the query handle
            int hr = SafeNativeMethods.DRMParseUnboundLicense(publishLicense, out queryRootHandle); 
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid)); 
 
            using (queryRootHandle)
            { 

                SafeRightsManagementQueryHandle workQueryHandle = null;

 
                // extract object information from the Work Item
                hr = SafeNativeMethods.DRMGetUnboundLicenseObject( 
                                        queryRootHandle, 
                                        NativeConstants.QUERY_WORK,
                                        0, 
                                        out workQueryHandle);
                Errors.ThrowOnErrorCode(hr);
                Debug.Assert((workQueryHandle != null) && (!workQueryHandle.IsInvalid));
 
                // contentIdValue information from the root query object
                using (workQueryHandle) 
                { 
                    return GetUnboundLicenseStringAttribute(
                                            workQueryHandle, 
                                            NativeConstants.QUERY_IDVALUE,
                                            0);
                }
            } 
        }
 
        internal static Uri GetUseLicenseAcquisitionUriFromPublishLicense(string publishLicense) 
        {
            string nameAttributeValue; 
            string addressAttributeValue;

            GetDistributionPointInfoFromPublishLicense
                        (publishLicense, 
                        _distributionPointLicenseAcquisitionType,
                        out nameAttributeValue, 
                        out addressAttributeValue); 

            return new Uri(addressAttributeValue); 
        }

        internal static void GetReferralInfoFromPublishLicense(
                            string publishLicense, 
                            out string referralInfoName,
                            out Uri referralInfoUri) 
        { 
            string nameAttributeValue;
            string addressAttributeValue; 

            GetDistributionPointInfoFromPublishLicense
                        (publishLicense,
                        _distributionPointReferralInfoType, 
                        out nameAttributeValue,
                        out addressAttributeValue); 
 
            referralInfoName = nameAttributeValue;
 
            if (addressAttributeValue != null)
            {
                referralInfoUri = new Uri(addressAttributeValue);
            } 
            else
            { 
                referralInfoUri = null; 
            }
        } 

        private static void GetDistributionPointInfoFromPublishLicense(
                                                                            string publishLicense,
                                                                            string distributionPointType, 
                                                                            out string nameAttributeValue,
                                                                            out string addressAttributeValue) 
        { 
            Invariant.Assert(publishLicense != null);
 
            // we are not making a distinction between truly missing values and NULL values
            nameAttributeValue = null;
            addressAttributeValue = null;
 
            // Parse the license and get the query handle
            SafeRightsManagementQueryHandle queryRootHandle = null; 
            int hr = SafeNativeMethods.DRMParseUnboundLicense(publishLicense, out queryRootHandle); 
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid)); 

            using (queryRootHandle)
            {
                uint index = 0; 

                while (true) 
                { 
                    SafeRightsManagementQueryHandle distributionPointQueryHandle = null;
                    // extract object information from the Root Item 
                    hr = SafeNativeMethods.DRMGetUnboundLicenseObject(
                                            queryRootHandle,
                                            NativeConstants.QUERY_DISTRIBUTIONPOINT,
                                            index, 
                                            out distributionPointQueryHandle);
                    if (hr == (int)RightsManagementFailureCode.QueryReportsNoResults) 
                    { 
                        break;
                    } 
                    Errors.ThrowOnErrorCode(hr);
                    Debug.Assert((distributionPointQueryHandle != null) && (!distributionPointQueryHandle.IsInvalid));

                    using (distributionPointQueryHandle) 
                    {
                        string addressType = GetUnboundLicenseStringAttribute( 
                                                distributionPointQueryHandle, 
                                                NativeConstants.QUERY_OBJECTTYPE,
                                                0); 
                        if (String.CompareOrdinal(addressType, distributionPointType) == 0)
                        {
                            nameAttributeValue = GetUnboundLicenseStringAttribute(
                                                distributionPointQueryHandle, 
                                                NativeConstants.QUERY_NAME,
                                                0); 
 
                            addressAttributeValue = GetUnboundLicenseStringAttribute(
                                                distributionPointQueryHandle, 
                                                NativeConstants.QUERY_ADDRESSVALUE,
                                                0);
                            return;
                        } 
                    }
 
                    index++; 
                }
            } 
        }


#if FALSE 
        // not using this for now, as we are not binding successfully bound rights as a single list
        internal static string BuildCommaSeparatedList(List stringList) 
        { 
            StringBuilder concatenatedStringList  = new StringBuilder(stringList.Count * 10);//guess the average right name size
 
            bool firstElementFlag = true;

            foreach (string right in stringList)
            { 
                if (firstElementFlag)
                { 
                    firstElementFlag = false; 
                }
                else 
                {
                    concatenatedStringList .Append(',');
                }
 
                concatenatedStringList.Append(right);
            } 
 
            return concatenatedStringList.ToString();
        } 
#endif

        internal static string GetSecurityProviderPath()
        { 
            uint typeLength = 0;
            StringBuilder type = null; 
            uint pathLength = 0; 
            StringBuilder path = null;
 
            int hr = SafeNativeMethods.DRMGetSecurityProvider(0,
                                                        ref typeLength,
                                                        null,
                                                        ref pathLength, 
                                                        null);
            Errors.ThrowOnErrorCode(hr); 
 
            checked
            { 
                type = new StringBuilder((int)typeLength);
                path = new StringBuilder((int)pathLength);
            }
 
            hr = SafeNativeMethods.DRMGetSecurityProvider(0,
                                                        ref typeLength, 
                                                        type, 
                                                        ref pathLength,
                                                        path); 
            Errors.ThrowOnErrorCode(hr);

            return path.ToString();
        } 

        internal static Nullable GetRightFromString(string rightName) 
        { 
            rightName = rightName.ToString().ToUpper(CultureInfo.InvariantCulture);
 
            for (int i = 0; i < _rightEnums.Length; i++)
            {
                if (String.CompareOrdinal(_rightNames[i], rightName) == 0)
                { 
                    return _rightEnums[i];
                } 
            } 

            return null; 
        }


        internal static string GetStringFromRight(ContentRight right) 
        {
            for (int i = 0; i < _rightEnums.Length; i++) 
            { 
                if (_rightEnums[i] == right)
                { 
                    return _rightNames[i];
                }
            }
 
            throw new ArgumentOutOfRangeException("right");
        } 
 
        private List CryptoProviderList
        { 
            get
            {
                if (_cryptoProviderList == null)
                { 
                    _cryptoProviderList = new List(5);
                } 
                return _cryptoProviderList; 
            }
        } 

        /// 
        /// Call this before accepting any API call
        ///  
        private void CheckDisposed()
        { 
            if ((_hSession == null) || 
                (_hSession.IsInvalid))
                throw new ObjectDisposedException("SecureEnvironment"); 
        }

        private const string _defaultUserName = @"DefaultUser@DefaultDomain.DefaultCom";     // RM default user name
 
        private const string _distributionPointLicenseAcquisitionType = @"License-Acquisition-URL";
        private const string _distributionPointReferralInfoType = @"Referral-Info"; 
 
        private const string _passportActivationRegistryFullKeyName = @"HKEY_LOCAL_MACHINE\Software\Microsoft\MSDRM\ServiceLocation\PassportActivation";
        private const string _passportActivationRegistryKeyName = @"Software\Microsoft\MSDRM\ServiceLocation\PassportActivation"; 

        private ContentUser _user = null;
        private CallbackHandler _callbackHandler;
 
        private SafeRightsManagementSessionHandle _hSession = null; // if this is zero, we are disposed
 
        // we preserve this so ve can remove certificates in case of temp activation 
        UserActivationMode _userActivationMode = UserActivationMode.Permanent;
 
        private SafeRightsManagementEnvironmentHandle _envHandle = null;  // if this is null, we are disposed

        private SafeRightsManagementHandle _defaultLibraryHandle = null;
 
        private List _cryptoProviderList;
 
        // the following 2 arrays are used for parsing and converting between String and Enum; 
        // therefore, the entries in the _rightEnums and the _rightNames must be in the same order.
        static private ContentRight[] _rightEnums = { 
                                        ContentRight.View,
                                        ContentRight.Edit,
                                        ContentRight.Print,
                                        ContentRight.Extract, 
                                        ContentRight.ObjectModel,
                                        ContentRight.Owner, 
                                        ContentRight.ViewRightsData, 
                                        ContentRight.Forward,
                                        ContentRight.Reply, 
                                        ContentRight.ReplyAll,
                                        ContentRight.Sign,
                                        ContentRight.DocumentEdit,
                                        ContentRight.Export}; 

        // entries in this array must be in UPPERCASE, as we make such assumption during parsing 
        static private string[] _rightNames = { 
                                        "VIEW",
                                        "EDIT", 
                                        "PRINT",
                                        "EXTRACT",
                                        "OBJMODEL",
                                        "OWNER", 
                                        "VIEWRIGHTSDATA",
                                        "FORWARD", 
                                        "REPLY", 
                                        "REPLYALL",
                                        "SIGN", 
                                        "DOCEDIT",
                                        "EXPORT"};
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
//
// 
//    Copyright (c) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//  These are the internal helpers required to call into unmanaged 
//  Promethium Rights Management SDK APIs
// 
// History:
//  06/13/2005: IgorBel:  Initial implementation.
//
//----------------------------------------------------------------------------- 

using System; 
using System.Collections; 
using System.Collections.ObjectModel;
using System.Collections.Generic; 
using System.Diagnostics;
using System.Security;
using System.Security.Permissions;
using System.Security.RightsManagement; 
using SecurityHelper = MS.Internal.WindowsBase.SecurityHelper;
using System.Text; 
using System.Globalization;                 // For CultureInfo 
// for Invariant
using System.Windows;                       // for SR and SRID 

using MS.Internal;
using System.Runtime.InteropServices;
 
using Microsoft.Win32; // for Registry and RegistryKey classes
 
using MS.Internal.WindowsBase; 

namespace MS.Internal.Security.RightsManagement 
{
    /// 
    ///     Critical:    This class expose access to methods that eventually do one or more of the the following
    ///             1. call into unmanaged code 
    ///             2. affects state/data that will eventually cross over unmanaged code boundary
    ///             3. Return some RM related information which is considered private 
    ///  
    [SecurityCritical(SecurityCriticalScope.Everything)]
    internal class ClientSession : IDisposable 
    {
        internal ClientSession(ContentUser user)
            :
                    this(user, UserActivationMode.Permanent) 
        {
        } 
 
        internal ClientSession(
            ContentUser user, 
            UserActivationMode userActivationMode)
        {
            Invariant.Assert(user != null);
            Invariant.Assert((userActivationMode == UserActivationMode.Permanent) || 
                                    (userActivationMode == UserActivationMode.Temporary));
 
            _user = user; 
            _userActivationMode = userActivationMode;
 
            // prepare callback handler
            _callbackHandler = new CallbackHandler();

            int hr = SafeNativeMethods.DRMCreateClientSession( 
                _callbackHandler.CallbackDelegate,
                NativeConstants.DrmCallbackVersion, 
                _user.AuthenticationProviderType, 
                _user.Name,
                out _hSession); 

            Errors.ThrowOnErrorCode(hr);
            Invariant.Assert((_hSession != null) && (!_hSession.IsInvalid));
        } 

        ~ClientSession() 
        { 
            Dispose(false);
        } 

        public void Dispose()
        {
            Dispose(true); 
            GC.SuppressFinalize(this);
        } 
 
        protected virtual void Dispose(bool disposing)
        { 
            if (disposing)
            {
                // close all the CryptoProviders that are bound to the Session
                // This way if user attempt to close SecureEnvironment while using the CryptoProvider 
                // the meaningful object Disposed exception will be thrown instead of misleading
                // Interop exception indicating that an invalid handle was used. 
                try 
                {
                    if (_cryptoProviderList != null) 
                    {
                        foreach (CryptoProvider cryptoProvider in _cryptoProviderList)
                        {
                            cryptoProvider.Dispose(); 
                        }
                    } 
                } 
                finally
                { 
                    _cryptoProviderList = null;

                    // close session handle which is a DRMHSESSION
                    try 
                    {
                        if ((_hSession != null) && 
                            (!_hSession.IsInvalid)) 
                        {
                            // if we deal with temporatry activation we should clean up 
                            // Group Identity Cerytificates and the Client Licensor Certificates
                            if (_userActivationMode == UserActivationMode.Temporary)
                            {
                                RemoveUsersCertificates(EnumerateLicenseFlags.SpecifiedClientLicensor); 
                                RemoveUsersCertificates(EnumerateLicenseFlags.SpecifiedGroupIdentity);
                            } 
 
                            _hSession.Dispose();
                        } 
                    }
                    finally
                    {
                        _hSession = null; 

                        // close default library handle which is a DRMHANDLE 
                        try 
                        {
                            if ((_defaultLibraryHandle != null) && 
                                (!_defaultLibraryHandle.IsInvalid))
                            {
                                _defaultLibraryHandle.Dispose();
                            } 
                        }
                        finally 
                        { 
                            _defaultLibraryHandle = null;
 
                            // close secure environment handle which is a DRMENVHANDLE
                            try
                            {
                                if ((_envHandle != null) && 
                                     (!_envHandle.IsInvalid))
                                { 
                                    _envHandle.Dispose(); 
                                }
                            } 
                            finally
                            {
                                _envHandle = null;
 
                                // Dispose call back handler
                                try 
                                { 
                                    if (_callbackHandler != null)
                                    { 
                                        _callbackHandler.Dispose();
                                    }
                                }
                                finally 
                                {
                                    _callbackHandler = null; 
                                } 
                            }
                        } 
                    }
                }
            }
        } 

        internal static ClientSession DefaultUserClientSession(AuthenticationType authentication) 
        { 
            return new ClientSession(new ContentUser(_defaultUserName, authentication));
        } 

        internal bool IsMachineActivated()
        {
            CheckDisposed(); 

            return IsActivated(ActivationFlags.Machine) && (GetMachineCert() != null); 
        } 

        internal void ActivateMachine(AuthenticationType authentication) 
        {
            CheckDisposed();

            // machine activation is always silent 
            ActivationFlags actFlags = ActivationFlags.Machine | ActivationFlags.Silent;
 
            Activate(actFlags, null); // GetActivationUrl(authentication));  // for local activation we do not need URL 
            // as we have Hard dependency on SP1 lock box - which is the only one that
            // is managed code friendly, we should never try to activate machine 
            // using URL - always local SP1 activation
        }

        internal bool IsUserActivated() 
        {
            CheckDisposed(); 
 
            // check that group identity is activated
            if (!IsActivated(ActivationFlags.GroupIdentity)) 
            {
                return false;
            }
 
            // enumerate user certificates andg get the current one
            string userCertificateChain = GetGroupIdentityCert(); 
 
            if (userCertificateChain == null)
            { 
                return false;
            }

            // extract identity from the certitficate and match it with the user 
            ContentUser userFromCert = ExtractUserFromCertificateChain(userCertificateChain);
 
            if (userFromCert == null) 
            {
                return false; 
            }

            // make sure the user matches completely (including authentication type).
            // All the checks above will pass if the requested user identity and 
            // activated user identity only differ by authentication type.
            return _user.GenericEquals(userFromCert); 
        } 

        internal ContentUser ActivateUser( 
            AuthenticationType authentication, UserActivationMode userActivationMode)
        {
            CheckDisposed();
 
            ActivationFlags actFlags = ActivationFlags.GroupIdentity;
 
            // for windows Silen Flag must be set For Passport it must not be set 
            if (_user.AuthenticationType == AuthenticationType.Windows)
            { 
                actFlags |= ActivationFlags.Silent;
            }

            if (userActivationMode == UserActivationMode.Temporary) 
            {
                actFlags |= ActivationFlags.Temporary; 
            } 

            string userCertificate = 
                Activate(actFlags, GetCertificationUrl(authentication));

            return ExtractUserFromCertificate(userCertificate);
        } 

        internal bool IsClientLicensorCertificatePresent() 
        { 
            CheckDisposed();
 
            return (GetClientLicensorCert() != null);
        }

        ///  
        /// This function is used to acquire a license either an End Use license
        /// or a Client Licensor Certificate 
        ///  
        internal void AcquireClientLicensorCertificate()
        { 
            CheckDisposed();

            // get the URL for Client Licensor Cert Acquisition
            Uri url = GetClientLicensorUrl(_user.AuthenticationType); 

            string license = GetGroupIdentityCert(); 
 
            int hr = SafeNativeMethods.DRMAcquireLicense(
                _hSession, 
                0,  // flags default to 0  for CLC acquisition
                license,
                null,  // requested data is reserved and not used
                null, // custom data 
                url.AbsoluteUri,  // We are using Uri class as a basic validation mechanism. These URIs come from unmanaged
                // code libraries and go back as parameters into the unmanaged code libraries. 
                // We use AbsoluteUri property as means of verifying that it is actually an absolute and 
                // well formed Uri. If by any chance it happened to be a relative URI, an exception will
                // be thrown here. This will perform the necessary escaping. 

                IntPtr.Zero);    // context

            Errors.ThrowOnErrorCode(hr); 

            _callbackHandler.WaitForCompletion();     // it will throw a proper exception in a failure case 
        } 

        internal void BuildSecureEnvironment(string applicationManifest) 
        {
            CheckDisposed();

            Invariant.Assert(_envHandle == null); 

            string providerPath = GetSecurityProviderPath(); 
            string machineCertificate = GetMachineCert(); 

            _defaultLibraryHandle = null; 
            _envHandle = null;

            int hr = SafeNativeMethods.DRMInitEnvironment(
                (uint)SecurityProviderType.SoftwareSecRep, 
                (uint)SpecType.FileName,
                providerPath, 
                applicationManifest, 
                machineCertificate,
                out _envHandle, 
                out _defaultLibraryHandle);

            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((_envHandle != null) && (!_envHandle.IsInvalid)); 
        }
 
        private bool IsActivated(ActivationFlags activateFlags) 
        {
            CheckDisposed(); 

            return (0 == SafeNativeMethods.DRMIsActivated(_hSession, (uint)activateFlags, null));
        }
 
        internal string GetMachineCert()
        { 
            CheckDisposed(); 

            // We always assume that the first machine certificate is the correct one 
            return EnumerateLicense(EnumerateLicenseFlags.Machine, 0);
        }

        ///  
        ///  This function is used to build a List of certificates of a given type (Licensor or Identity)
        ///  From all of the certificates based on the matching of the User Id 
        ///  
        internal List EnumerateUsersCertificateIds(
                                                                                ContentUser user, 
                                                                                EnumerateLicenseFlags certificateType)
        {
            CheckDisposed();
 
            if ((certificateType != EnumerateLicenseFlags.Machine) &&
                                    (certificateType != EnumerateLicenseFlags.GroupIdentity) && 
                                    (certificateType != EnumerateLicenseFlags.GroupIdentityName) && 
                                    (certificateType != EnumerateLicenseFlags.GroupIdentityLid) &&
                                    (certificateType != EnumerateLicenseFlags.SpecifiedGroupIdentity) && 
                                    (certificateType != EnumerateLicenseFlags.Eul) &&
                                    (certificateType != EnumerateLicenseFlags.EulLid) &&
                                    (certificateType != EnumerateLicenseFlags.ClientLicensor) &&
                                    (certificateType != EnumerateLicenseFlags.ClientLicensorLid) && 
                                    (certificateType != EnumerateLicenseFlags.SpecifiedClientLicensor) &&
                                    (certificateType != EnumerateLicenseFlags.RevocationList) && 
                                    (certificateType != EnumerateLicenseFlags.RevocationListLid) && 
                                    (certificateType != EnumerateLicenseFlags.Expired))
            { 
                throw new ArgumentOutOfRangeException("certificateType");
            }

            List certificateIdList = new List(); 

            int index = 0; 
            // first enumerate certificates and find the ones that match given user 
            while (true)
            { 
                // we get a string which can be parsed to get the ID and type
                string currentUserCertificate = EnumerateLicense(certificateType, index);

                if (currentUserCertificate == null) 
                    break;
 
                // we need to parse the information out of the string 
                ContentUser currentUser = ExtractUserFromCertificateChain(currentUserCertificate);
 
                // let's see if we have a match on the User Id, if we do we need to add it to the list
                if (user.GenericEquals(currentUser))
                {
                    // we got a match let's preserve the certificate in the list 
                    certificateIdList.Add(ClientSession.ExtractCertificateIdFromCertificateChain(currentUserCertificate));
                } 
 
                index++;
            } 

            return certificateIdList;
        }
 
        internal void DeleteLicense(string licenseId)
        { 
            CheckDisposed(); 

            int hr = SafeNativeMethods.DRMDeleteLicense(_hSession, licenseId); 
            Errors.ThrowOnErrorCode(hr);
        }

        internal void RemoveUsersCertificates(EnumerateLicenseFlags certificateType) 
        {
            CheckDisposed(); 
 
            // We only expect to be called for removal of the specific Group Identity Certs
            // and the specific Client Licensor Certs 
            Invariant.Assert((certificateType == EnumerateLicenseFlags.SpecifiedClientLicensor) ||
                                  (certificateType == EnumerateLicenseFlags.SpecifiedGroupIdentity));

            // We actually need to enumerate all the specified identity certs and then parse 
            // them to get the license Id , and only then remove them
            ArrayList certList = EnumerateAllValuesOnSession(_hSession, certificateType); 
 
            foreach (string cert in certList)
            { 
                DeleteLicense(ExtractCertificateIdFromCertificateChain(cert));
            }
        }
 
        private string GetClientLicensorCert()
        { 
            return GetLatestCertificate(EnumerateLicenseFlags.SpecifiedClientLicensor); 
        }
 
        private string GetGroupIdentityCert()
        {
            return GetLatestCertificate(EnumerateLicenseFlags.SpecifiedGroupIdentity);
        } 

        private string GetLatestCertificate(EnumerateLicenseFlags enumerateLicenseFlags) 
        { 
            int index = 0;
 
            string currentCert = EnumerateLicense(enumerateLicenseFlags, index);
            if (currentCert == null)
            {
                return null; 
            }
 
            DateTime currentTimeStamp = ExtractIssuedTimeFromCertificateChain(currentCert, DateTime.MinValue); 

            while (currentCert != null) 
            {
                index++;

                string newCert = EnumerateLicense(enumerateLicenseFlags, index); 

                // if we have completed the enumeration we can stop right here 
                if (newCert == null) 
                {
                    break; 
                }

                DateTime newTimeStamp = ExtractIssuedTimeFromCertificateChain(newCert, DateTime.MinValue);
 
                if (DateTime.Compare(currentTimeStamp, newTimeStamp) < 0)
                { 
                    currentCert = newCert; 
                    currentTimeStamp = newTimeStamp;
                } 
            }

            return currentCert;
        } 

        private static ArrayList EnumerateAllValuesOnSession(SafeRightsManagementSessionHandle sessionHandle, EnumerateLicenseFlags enumerateLicenseFlags) 
        { 
            ArrayList result = new ArrayList(5);
            int index = 0; 

            while (true)
            {
                string currentRes = GetLicenseOnSession(sessionHandle, enumerateLicenseFlags, index); 

                if (currentRes == null) 
                { 
                    break;
                } 
                result.Add(currentRes);
                index++;
            }
            return result; 
        }
 
        internal static string GetLicenseOnSession(SafeRightsManagementSessionHandle sessionHandle, EnumerateLicenseFlags enumerateLicenseFlags, int index) 
        {
            Invariant.Assert(index >= 0); 

            if ((enumerateLicenseFlags != EnumerateLicenseFlags.Machine) &&
                (enumerateLicenseFlags != EnumerateLicenseFlags.GroupIdentity) &&
                (enumerateLicenseFlags != EnumerateLicenseFlags.GroupIdentityName) && 
                (enumerateLicenseFlags != EnumerateLicenseFlags.GroupIdentityLid) &&
                (enumerateLicenseFlags != EnumerateLicenseFlags.SpecifiedGroupIdentity) && 
                (enumerateLicenseFlags != EnumerateLicenseFlags.Eul) && 
                (enumerateLicenseFlags != EnumerateLicenseFlags.EulLid) &&
                (enumerateLicenseFlags != EnumerateLicenseFlags.ClientLicensor) && 
                (enumerateLicenseFlags != EnumerateLicenseFlags.ClientLicensorLid) &&
                (enumerateLicenseFlags != EnumerateLicenseFlags.SpecifiedClientLicensor) &&
                (enumerateLicenseFlags != EnumerateLicenseFlags.RevocationList) &&
                (enumerateLicenseFlags != EnumerateLicenseFlags.RevocationListLid) && 
                (enumerateLicenseFlags != EnumerateLicenseFlags.Expired))
            { 
                throw new ArgumentOutOfRangeException("enumerateLicenseFlags"); 
            }
 
            int hr = 0;
            bool sharedFlag = false;
            uint dataLen = 0;
            StringBuilder license = null; 

            hr = SafeNativeMethods.DRMEnumerateLicense( 
                sessionHandle, (uint)enumerateLicenseFlags, (uint)index, ref sharedFlag, ref dataLen, null); 

            if (hr == (int)RightsManagementFailureCode.NoMoreData) 
                return null;

            Errors.ThrowOnErrorCode(hr);
 
            if (dataLen > System.Int32.MaxValue)
                return null; 
 
            //returned size accounts for null termination; we do not need to add 1
            checked 
            {
                license = new StringBuilder((int)dataLen);
            }
 
            hr = SafeNativeMethods.DRMEnumerateLicense(
                sessionHandle, (uint)enumerateLicenseFlags, (uint)index, ref sharedFlag, ref dataLen, license); 
 
            Errors.ThrowOnErrorCode(hr);
 
            return license.ToString();
        }

        internal string EnumerateLicense(EnumerateLicenseFlags enumerateLicenseFlags, int index) 
        {
            CheckDisposed(); 
 
            return GetLicenseOnSession(_hSession, enumerateLicenseFlags, index);
        } 

        internal PublishLicense SignIssuanceLicense(IssuanceLicense issuanceLicense, out UseLicense authorUseLicense)
        {
            CheckDisposed(); 

            Invariant.Assert(issuanceLicense != null); 
            Invariant.Assert(!_envHandle.IsInvalid); 

            using (CallbackHandler signIssuanceLicenseCallbackHandler = new CallbackHandler()) 
            {
                string clientLicensorCertificate = GetClientLicensorCert();

                if (clientLicensorCertificate == null) 
                    throw new RightsManagementException(SR.Get(SRID.UserHasNoClientLicensorCert));
 
                // Trim all the leading and trailing white space characters 
                // of the clientLicensorCertificate.
                clientLicensorCertificate = clientLicensorCertificate.Trim(); 

                // Make sure the clientLicensorCertificate is valid. By trimming white spaces
                // above, if the certificate string is empty or contains only white spaces, it
                // is empty now. 
                if (clientLicensorCertificate.Length == 0)
                    throw new RightsManagementException(SR.Get(SRID.UserHasNoClientLicensorCert)); 
 
                // Offline publishing supported no Online publishing support
                int hr = SafeNativeMethods.DRMGetSignedIssuanceLicense( 
                    _envHandle,
                    issuanceLicense.Handle,
                    (uint)(SignIssuanceLicenseFlags.Offline |
                                SignIssuanceLicenseFlags.AutoGenerateKey | 
                                SignIssuanceLicenseFlags.OwnerLicenseNoPersist),
                    null, 
                    0, 
                    NativeConstants.ALGORITHMID_AES,     // currently AES is the only supported key type
                    clientLicensorCertificate, 
                    signIssuanceLicenseCallbackHandler.CallbackDelegate,
                    null, // we are only supporting offline publishing no url needed
                    0); // no context required
 
                Errors.ThrowOnErrorCode(hr);
 
                signIssuanceLicenseCallbackHandler.WaitForCompletion();     // it will throw a proper exception in a failure case 

                // build publish License from th result 
                PublishLicense publishLicense = new PublishLicense(
                    signIssuanceLicenseCallbackHandler.CallbackData);

                // After Issuance license is signed we should build the Author's Use License 
                authorUseLicense = new UseLicense(GetOwnerLicense(issuanceLicense.Handle));
 
                return publishLicense; 
            }
        } 

        internal UseLicense AcquireUseLicense(string publishLicense, bool noUI)
        {
            CheckDisposed(); 

            Invariant.Assert(!_envHandle.IsInvalid); 
 
            SafeRightsManagementSessionHandle licenseStorageSessionHandle = null;
 
            //first let's build the license storage session
            int hr = SafeNativeMethods.DRMCreateLicenseStorageSession(
                _envHandle,
                _defaultLibraryHandle, 
                _hSession,
                0, 
                publishLicense, 
                out licenseStorageSessionHandle);
 
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((licenseStorageSessionHandle != null) && (!licenseStorageSessionHandle.IsInvalid));

            using (licenseStorageSessionHandle) 
            {
                uint flags = 0; 
                if (noUI) 
                {
                    flags |= (uint)AcquireLicenseFlags.NoUI; 
                }

                string license = GetGroupIdentityCert();
 
                // the newly acquired use license will be added to the License Storage Session.
                // We need to enumerate all the entries before and after in order to properly find the new one 
                ArrayList oldLicenseIds = EnumerateAllValuesOnSession 
                                        (licenseStorageSessionHandle, EnumerateLicenseFlags.EulLid);
 
                hr = SafeNativeMethods.DRMAcquireLicense(
                    licenseStorageSessionHandle,
                    flags,
                    license, 
                    null,  // requested data is reserved and not used
                    null, // custom data 
                    null, //no url required it will be taken from publish license 
                    IntPtr.Zero);    // context
 
                Errors.ThrowOnErrorCode(hr);

                _callbackHandler.WaitForCompletion();         // it will throw a proper exception in a failure case
 
                // now we can enumerate the EUL Ids  again and try to find the new one
                ArrayList newLicenseIds = EnumerateAllValuesOnSession 
                                        (licenseStorageSessionHandle, EnumerateLicenseFlags.EulLid); 

                int indexOfTheAcquiredLicense = FindNewEntryIndex(oldLicenseIds, newLicenseIds); 

                if (indexOfTheAcquiredLicense < 0)
                {
                    // we have failed to find the new license 
                    throw new RightsManagementException(RightsManagementFailureCode.LicenseAcquisitionFailed);
                } 
 
                return new UseLicense(GetLicenseOnSession(
                                                            licenseStorageSessionHandle, 
                                                            EnumerateLicenseFlags.Eul,
                                                            indexOfTheAcquiredLicense));
            }
        } 

        private static int FindNewEntryIndex(ArrayList oldList, ArrayList newList) 
        { 
            Invariant.Assert((oldList != null) && (newList != null));
 
            for (int i = 0; i < newList.Count; i++)
            {
                string newElement = (string)newList[i];
                bool matchFound = false; 

                foreach (string oldElement in oldList) 
                { 
                    if (String.CompareOrdinal(newElement, oldElement) == 0)
                    { 
                        matchFound = true;
                        break;
                    }
                } 

                // we have found an entry in the newList without a match in the old list 
                // we can return the index 
                if (!matchFound)
                { 
                    return i;
                }
            }
 
            // No new entry were found
            return -1; 
        } 

        // This function attempts to bind License to a given Identity 
        // It will try to bind all rights One-by-one in order to eliminate
        // grants that may have been expired, so it will only bind The ones that are still valid
        private CryptoProvider BindUseLicense(string serializedUseLicense,
                                                                List unboundRightsList, 
                                                                BoundLicenseParams boundLicenseParams,
                                                                out int theFirstHrFailureCode) 
        { 
            Debug.Assert(serializedUseLicense != null);
            Debug.Assert(unboundRightsList != null); 
            Debug.Assert(boundLicenseParams != null);


            List successfullyBoundLicenseHandleList = 
                        new List(unboundRightsList.Count);
 
            List successfullyBoundRightsList = 
                        new List(unboundRightsList.Count);
            try 
            {
                uint errorLogHandle;

                // we neeed to return the first failure code, that is the one that will communicate to the user 
                int hr;
                theFirstHrFailureCode = 0; 
 
                SafeRightsManagementHandle boundLicenseHandle;
 
                // first we are enumerating all rights one-by-one and preserving the ones that can be bound
                // we are going through the list of "recognised rights"
                foreach (RightNameExpirationInfoPair rightInfo in unboundRightsList)
                { 

                    boundLicenseParams.wszRightsRequested = rightInfo.RightName; 
                    boundLicenseHandle = null; 
                    errorLogHandle = 0;
 
                    hr = SafeNativeMethods.DRMCreateBoundLicense(
                                                _envHandle,
                                                boundLicenseParams,
                                                serializedUseLicense, 
                                                out boundLicenseHandle,
                                                out errorLogHandle); 
 
                    if (boundLicenseHandle != null && (hr == 0))
                    { 
                        // we got a successful bound let's copy the whole grant
                        // the only thing that we need to substitute in the grant is the User identity
                        // along with the original right name (prior to binding), as unmanaged SDK
                        // messes up right names and their expiration 
                        // in case of multiple expiration dates and additional rights granted to an owner
                        successfullyBoundLicenseHandleList.Add(boundLicenseHandle); 
                        successfullyBoundRightsList.Add(rightInfo); 
                    }
 
                    // preserve the first encountered error code
                    if ((theFirstHrFailureCode == 0) && (hr != 0))
                    {
                        theFirstHrFailureCode = hr; 
                    }
                } 
 
                // At this point we have a list of potential "Right" -candidates
                // if it is empty we can get out 
                if (successfullyBoundLicenseHandleList.Count > 0)
                {
                    ContentUser user = ExtractUserFromCertificateChain(boundLicenseParams.wszDefaultEnablingPrincipalCredentials);
 
                    CryptoProvider cryptoProvider = new CryptoProvider(successfullyBoundLicenseHandleList,
                                                                    successfullyBoundRightsList, 
                                                                    user); 
                    CryptoProviderList.Add(cryptoProvider);
                    return cryptoProvider; 
                }
                else
                {
                    return null; 
                }
            } 
            catch 
            {
                // In case of a failure we should clean up handle that have been accumulated 
                // otherwise the list of handles is either empty or given to the CryptoProvider
                // to be taken care of
                foreach (SafeRightsManagementHandle handle in successfullyBoundLicenseHandleList)
                { 
                    handle.Dispose();
                } 
                throw; 
            }
        } 


        internal CryptoProvider TryBindUseLicenseToAllIdentites(string serializedUseLicense)
        { 
            CheckDisposed();
 
            Invariant.Assert(serializedUseLicense != null); 

            int hr = 0; 
            int theFirstHrFailureCode = 0;

            ///////////////////////////
            // prepare bound license param structure 
            ///////////////////////////
            //prepare for binding (enumerate unbound rights) 
            string rightsGroupName; 

            List unboundRightsList = 
                        GetRightsInfoFromUseLicense(serializedUseLicense, out rightsGroupName);

            BoundLicenseParams boundLicenseParams = new BoundLicenseParams();
 
            boundLicenseParams.uVersion = 0;
            boundLicenseParams.hEnablingPrincipal = 0; 
            boundLicenseParams.hSecureStore = 0; 
            boundLicenseParams.wszRightsGroup = rightsGroupName;
 
            string contentId;
            string contentIdType;
            GetContentIdFromLicense(serializedUseLicense, out contentId, out contentIdType);
 
            boundLicenseParams.DRMIDuVersion = 0;
            boundLicenseParams.DRMIDIdType = contentIdType; 
            boundLicenseParams.DRMIDId = contentId; 

            boundLicenseParams.cAuthenticatorCount = 0;//reserved.should be 0. 
            boundLicenseParams.rghAuthenticators = IntPtr.Zero;

            string userCertificate = GetGroupIdentityCert();
 
            boundLicenseParams.wszDefaultEnablingPrincipalCredentials = userCertificate;
 
            boundLicenseParams.dwFlags = 0; 

            // let's try to bind this using currently provided user first 
            CryptoProvider cryptoProvider = BindUseLicense(serializedUseLicense,
                                                                unboundRightsList,
                                                                boundLicenseParams,
                                                                out hr); 

            if (cryptoProvider != null) 
            { 
                return cryptoProvider;
            } 

            // preserve the first encountered error code
            if ((theFirstHrFailureCode == 0) && (hr != 0))
            { 
                theFirstHrFailureCode = hr;
            } 
 
            // now if the current user failed we can try to enumerate all the userr certificates
            // and go through them one-by-one 
            int userCertIndex = 0;
            while (true)
            {
                userCertificate = EnumerateLicense(EnumerateLicenseFlags.GroupIdentity, userCertIndex); 
                if (userCertificate == null)
                { 
                    // we have to enumerate all of the user certs . . . 
                    break;
                } 
                userCertIndex++;
                boundLicenseParams.wszDefaultEnablingPrincipalCredentials = userCertificate;

                cryptoProvider = BindUseLicense(serializedUseLicense, 
                                                                unboundRightsList,
                                                                boundLicenseParams, 
                                                                out hr); 

                if (cryptoProvider != null) 
                {
                    return cryptoProvider;
                }
 
                // preserve the first encountered error code
                if ((theFirstHrFailureCode == 0) && (hr != 0)) 
                { 
                    theFirstHrFailureCode = hr;
                } 
            }

            // at this point we can only translate failure into some meaningfull exception
            Invariant.Assert(theFirstHrFailureCode != 0); // it must contain an error as a succesfull return above should take of non-failure cases 
            Errors.ThrowOnErrorCode(theFirstHrFailureCode);
            return null; 
        } 

        // The newer SDK automatically does machine activation. This function would be necessary if we had 
        // to support the older SDK.
#if needToActivateExplicitly
        private Uri GetActivationUrl(AuthenticationType authentication)
        { 
            if (authentication == AuthenticationType.Windows)
            { 
                return GetServiceLocation(ServiceType.Activation, ServiceLocation.Enterprise, null); 
            }
            else if (authentication == AuthenticationType.Passport) 
            {
                return GetServiceLocation(ServiceType.Activation, ServiceLocation.Internet, null);
            }
            else 
            {
                Debug.Assert(false,"Invalid Authentication type"); 
                return null;            // retail build might be ale to recover from SDK defaults 
            }
        } 
#endif

        private Uri GetCertificationUrl(AuthenticationType authentication)
        { 
            Debug.Assert((authentication == AuthenticationType.Windows) ||
                               (authentication == AuthenticationType.Passport)); 
 
            // for Passport scenario we just use default null value everywhere and expect promethium
            // SDK do proper server discovery 
            Uri server = null;

            if (authentication == AuthenticationType.Windows)
            { 
                // first try to get Corporate Domain server, if it fails try the internet
                // regardless of the user type 
                server = GetServiceLocation(ServiceType.Certification, ServiceLocation.Enterprise, null); 

                if (server == null) 
                {
                    server = GetServiceLocation(ServiceType.Certification, ServiceLocation.Internet, null);
                }
            } 
            else // it must be passport
            { 
                // 1st we need to check regiostry for override, and then if it missing we can use Discovery Service 
                server = GetRegistryPassportCertificationUrl();
                if (server == null) 
                {  // let's use server discovery
                    server = GetServiceLocation(ServiceType.Certification, ServiceLocation.Internet, null);
                }
            } 

            return server; 
        } 

 

        private static Uri GetRegistryPassportCertificationUrl()
        {
            // This Function Will return null, if the registry entry is missing 

            // Acquire permissions to read the one key we care about from the registry 
            RegistryPermission permission = new RegistryPermission( 
                    RegistryPermissionAccess.Read,
                    System.Security.AccessControl.AccessControlActions.View, 
                    _passportActivationRegistryFullKeyName);

            permission.Assert();
 
            try
            { 
                RegistryKey key = Registry.LocalMachine.OpenSubKey(_passportActivationRegistryKeyName); 
                if (key == null)
                { 
                    return null;
                }
                else
                { 
                    object keyValue = key.GetValue(null); // this should get the default value
                    string stringValue = keyValue as string; 
                    if (stringValue != null) 
                    {
                        return new Uri(stringValue); 
                    }
                    else
                    {
                        return null; 
                    }
                } 
            } 
            finally
            { 
                RegistryPermission.RevertAssert();
            }
        }
 
        private Uri GetClientLicensorUrl(AuthenticationType authentication)
        { 
            Debug.Assert((authentication == AuthenticationType.Windows) || 
                               (authentication == AuthenticationType.Passport));
 
            // Both, for Passport and Windows authenticvation types scenarios we do the same server discovery:
            // first try to get Corporate Domain server
            Uri server = GetServiceLocation(ServiceType.ClientLicensor, ServiceLocation.Enterprise, null);
 
            if (server == null)
            { 
                // if it fails try the internet discovery services 
                server = GetServiceLocation(ServiceType.ClientLicensor, ServiceLocation.Internet, null);
            } 

            return server;
        }
 
#if false           // re-enable when needed, This is only needed for on-line publishing, which currently isn't supported
        private Uri GetClientPublishingUrl() 
        { 
            // first try to get Corporate Domain server, if it fails try the internet
            // regardless of the user type 
            Uri server = GetServiceLocation(ServiceType.Publishing, ServiceLocation.Enterprise, null);

            if (server != null)
            { 
                return server;
            } 
 
            return GetServiceLocation(ServiceType.Publishing, ServiceLocation.Internet, null);
        } 
#endif

        /// 
        /// The Activate function obtains a lockbox and machine certificate for a machine or a rights 
        /// account certificate for a user (depend on activationFlags).
        ///  
        private string Activate( 
            ActivationFlags activationFlags, Uri url)
        { 
            // Optional server information. To query UDDI for an activation URL, pass in NULL
            ActivationServerInfo activationServer = null;

            if (url != null) 
            {
                activationServer = new ActivationServerInfo(); 
                activationServer.PubKey = null; 
                activationServer.Url = url.AbsoluteUri;  // We are using Uri class as a basic validation mechanism. These URIs come from unmanaged
                // code libraries and go back as parameters into the unmanaged code libraries. 
                // We use AbsoluteUri property as means of verifying that it is actually an absolute and
                // well formed Uri. If by any chance it happened to be a relative URI, an exception will
                // be thrown here. This will perform the necessary escaping.
 
                activationServer.Version = NativeConstants.DrmCallbackVersion;
            } 
 
            int hr = SafeNativeMethods.DRMActivate(
                _hSession, 
                (uint)activationFlags,
                0,                          //language Id
                activationServer,
                IntPtr.Zero,    // context 
                IntPtr.Zero);  // parent Window handle
 
            Errors.ThrowOnErrorCode(hr); 

            _callbackHandler.WaitForCompletion();        // it will throw a proper exception in a failure case 

            return _callbackHandler.CallbackData;
        }
 
        private Uri GetServiceLocation(
                ServiceType serviceType, ServiceLocation serviceLocation, string issuanceLicense) 
        { 
            uint serviceUrlLength = 0;
            StringBuilder serviceUrl = null; 

            int hr = SafeNativeMethods.DRMGetServiceLocation(
                _hSession, (uint)serviceType, (uint)serviceLocation, issuanceLicense, ref serviceUrlLength, null);
 
            if (hr == (int)RightsManagementFailureCode.UseDefault)
            { 
                // there is a special case in which this error code means that application supposed to use the default nul URL 
                return null;
            } 

            Errors.ThrowOnErrorCode(hr);

            checked 
            {
                serviceUrl = new StringBuilder((int)serviceUrlLength); 
            } 

            hr = SafeNativeMethods.DRMGetServiceLocation( 
                _hSession, (uint)serviceType, (uint)serviceLocation, issuanceLicense, ref serviceUrlLength, serviceUrl);

            Errors.ThrowOnErrorCode(hr);
 
            return new Uri(serviceUrl.ToString());
        } 
 
        internal static string GetOwnerLicense(SafeRightsManagementPubHandle issuanceLicenseHandle)
        { 
            Invariant.Assert(!issuanceLicenseHandle.IsInvalid);

            uint ownerLicenseLength = 0;
            StringBuilder ownerLicense = null; 

            int hr = SafeNativeMethods.DRMGetOwnerLicense( 
                issuanceLicenseHandle, ref ownerLicenseLength, null); 
            Errors.ThrowOnErrorCode(hr);
 
            checked
            {
                ownerLicense = new StringBuilder((int)ownerLicenseLength);
            } 

            hr = SafeNativeMethods.DRMGetOwnerLicense( 
                issuanceLicenseHandle, ref ownerLicenseLength, ownerLicense); 
            Errors.ThrowOnErrorCode(hr);
 
            return ownerLicense.ToString();
        }

        static private string GetElementFromCertificateChain( 
            string certificateChain, int index)
        { 
            Invariant.Assert(index >= 0); 
            Invariant.Assert(certificateChain != null);
            uint chainElementSize = 0; 
            StringBuilder chainElement = null;

            int hr = SafeNativeMethods.DRMDeconstructCertificateChain(
                certificateChain, 
                (uint)index,
                ref chainElementSize, 
                null); 

            Errors.ThrowOnErrorCode(hr); 

            checked
            {
                chainElement = new StringBuilder((int)chainElementSize); 
            }
 
            hr = SafeNativeMethods.DRMDeconstructCertificateChain( 
                certificateChain,
                (uint)index, 
                ref chainElementSize,
                chainElement);

            Errors.ThrowOnErrorCode(hr); 

            return chainElement.ToString(); 
        } 

        private static string GetUnboundLicenseStringAttribute( 
            SafeRightsManagementQueryHandle queryHandle, string attributeType, uint attributeIndex)
        {
            uint attributeSize = 0;
            byte[] dataBuffer = null; 

            uint encodingType; 
 
            // get the attribute information (memory size to be allocated)
            int hr = SafeNativeMethods.DRMGetUnboundLicenseAttribute( 
                queryHandle, attributeType, attributeIndex, out encodingType, ref attributeSize, null);

            if (hr == (int)RightsManagementFailureCode.QueryReportsNoResults)
            { 
                return null;
            } 
            Errors.ThrowOnErrorCode(hr); 

            // this is the size of the null terminator so essentially this is an empty string 
            if (attributeSize < 2)
                return null;

            checked 
            {
                dataBuffer = new byte[(int)attributeSize]; 
            } 

            hr = SafeNativeMethods.DRMGetUnboundLicenseAttribute( 
                queryHandle, attributeType, attributeIndex, out encodingType, ref attributeSize, dataBuffer);
            Errors.ThrowOnErrorCode(hr);

            // we need to truncate the last 2 bytes that have unicode 0 termination 
            return Encoding.Unicode.GetString(dataBuffer, 0, dataBuffer.Length - 2);
        } 
 
        // This method has only one caller GetGrantsFromBoundUseLicense(), which is
        // in the 

#if DEBUG
        static private string GetBoundLicenseStringAttribute(
            SafeRightsManagementHandle queryHandle, 
            string attributeType,
            uint attributeIndex) 
        { 
            uint attributeSize = 0;
            byte[] dataBuffer = null; 

            uint encodingType;

            int hr = SafeNativeMethods.DRMGetBoundLicenseAttribute( 
                queryHandle, attributeType, attributeIndex, out encodingType, ref attributeSize, null);
            Errors.ThrowOnErrorCode(hr); 
 
            if (encodingType != (uint)LicenseAttributeEncoding.String)
            { 
                throw new RightsManagementException(RightsManagementFailureCode.InvalidLicense);
            }

            // this is the size of the null terminator so essentially this is an empty string 
            if (attributeSize < 2)
                return null; 
 
            checked
            { 
                dataBuffer = new byte[(int)attributeSize];
            }

            hr = SafeNativeMethods.DRMGetBoundLicenseAttribute( 
                queryHandle, attributeType, attributeIndex, out encodingType, ref attributeSize, dataBuffer);
            Errors.ThrowOnErrorCode(hr); 
 
            // we need to truncate the last 2 bytes that have unicode 0 termination
            return Encoding.Unicode.GetString(dataBuffer, 0, dataBuffer.Length - 2); 
        }
#endif

        static private DateTime GetUnboundLicenseDateTimeAttribute( 
            SafeRightsManagementQueryHandle queryHandle,
            string attributeType, 
            uint attributeIndex, 
            DateTime defaultValue)
        { 
            uint attributeSize = SystemTime.Size;
            byte[] dataBuffer = new byte[attributeSize];
            uint encodingType;
 
            int hr = SafeNativeMethods.DRMGetUnboundLicenseAttribute(
                queryHandle, attributeType, attributeIndex, out encodingType, 
                ref attributeSize, dataBuffer); 

            if (encodingType != (uint)LicenseAttributeEncoding.Time) 
            {
                throw new RightsManagementException(RightsManagementFailureCode.InvalidLicense);
            }
 
            if ((hr == (int)RightsManagementFailureCode.NoMoreData) ||
                 (hr == (int)RightsManagementFailureCode.QueryReportsNoResults)) 
            { 
                return defaultValue;
            } 
            Errors.ThrowOnErrorCode(hr);

            Debug.Assert(attributeSize == SystemTime.Size); // if isn't true it is an indication of a problem in the underlying libraries
 
            SystemTime sysTime = new SystemTime(dataBuffer);
 
            return sysTime.GetDateTime(defaultValue); 
        }
 
        // This method has only one caller GetGrantsFromBoundUseLicense(), which is
        // in the

#if DEBUG 
        static private DateTime GetBoundLicenseDateTimeAttribute(
            SafeRightsManagementHandle queryHandle, 
            string attributeType, 
            uint attributeIndex,
            DateTime defaultValue) 
        {
            uint attributeSize = SystemTime.Size;
            byte[] dataBuffer = new byte[attributeSize];
            uint encodingType; 

            int hr = SafeNativeMethods.DRMGetBoundLicenseAttribute( 
                queryHandle, attributeType, attributeIndex, out encodingType, 
                ref attributeSize, dataBuffer);
 
            if (encodingType != (uint)LicenseAttributeEncoding.Time)
            {
                throw new RightsManagementException(RightsManagementFailureCode.InvalidLicense);
            } 

            if ((hr == (int)RightsManagementFailureCode.NoMoreData) || 
                 (hr == (int)RightsManagementFailureCode.QueryReportsNoResults)) 
            {
                return defaultValue; 
            }
            Errors.ThrowOnErrorCode(hr);

            Debug.Assert(attributeSize == SystemTime.Size); // if isn't true it is an indication of a problem in the underlying libraries 

            SystemTime sysTime = new SystemTime(dataBuffer); 
 
            return sysTime.GetDateTime(defaultValue);
        } 
#endif

        internal static ContentUser ExtractUserFromCertificateChain(string certificateChain)
        { 
            Invariant.Assert(certificateChain != null);
 
            return ExtractUserFromCertificate(GetElementFromCertificateChain(certificateChain, 0)); 
        }
 

        private static DateTime ExtractIssuedTimeFromCertificateChain(
                        string certificateChain,
                        DateTime defaultValue) 
        {
            Invariant.Assert(certificateChain != null); 
 
            return ExtractIssuedTimeFromCertificate(GetElementFromCertificateChain(certificateChain, 0), defaultValue);
        } 

        private static DateTime ExtractIssuedTimeFromCertificate(
                        string certificate,
                        DateTime defaultValue) 
        {
            SafeRightsManagementQueryHandle queryRootHandle = null; 
            int hr; 

            hr = SafeNativeMethods.DRMParseUnboundLicense( 
                certificate,
                out queryRootHandle);
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid)); 

            using (queryRootHandle) 
            { 
                return GetUnboundLicenseDateTimeAttribute(
                            queryRootHandle, 
                            NativeConstants.QUERY_ISSUEDTIME,
                            0,
                            defaultValue);
            } 
        }
 
        internal static ContentUser 
            ExtractUserFromCertificate(string certificate)
        { 
            SafeRightsManagementQueryHandle queryRootHandle = null;

            int hr;
 
            hr = SafeNativeMethods.DRMParseUnboundLicense(
                certificate, 
                out queryRootHandle); 
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid)); 

            using (queryRootHandle)
            {
                SafeRightsManagementQueryHandle querySubHandle = null; 

                hr = SafeNativeMethods.DRMGetUnboundLicenseObject( 
                    queryRootHandle, 
                    NativeConstants.QUERY_ISSUEDPRINCIPAL,
                    0, 
                    out querySubHandle);
                Errors.ThrowOnErrorCode(hr);
                Debug.Assert((querySubHandle != null) && (!querySubHandle.IsInvalid));
 
                using (querySubHandle)
                { 
                    string name = GetUnboundLicenseStringAttribute( 
                        querySubHandle,
                        NativeConstants.QUERY_NAME, 
                        0);

                    string authenticationType = GetUnboundLicenseStringAttribute(
                        querySubHandle, 
                        NativeConstants.QUERY_IDTYPE,
                        0); 
 
                    // We recognise authentication type Windows everything else is assumed to be Passport
                    if (String.CompareOrdinal( 
                        AuthenticationType.Windows.ToString().ToUpper(CultureInfo.InvariantCulture),
                        authenticationType.ToUpper(CultureInfo.InvariantCulture)) == 0)
                    {
                        return new ContentUser(name, AuthenticationType.Windows); 
                    }
                    else 
                    { 
                        return new ContentUser(name, AuthenticationType.Passport);
                    } 
                }
            }
        }
 
        internal static string ExtractCertificateIdFromCertificateChain(string certificateChain)
        { 
            Invariant.Assert(certificateChain != null); 

            return ExtractCertificateIdFromCertificate(GetElementFromCertificateChain(certificateChain, 0)); 
        }

        internal static string
            ExtractCertificateIdFromCertificate(string certificate) 
        {
            SafeRightsManagementQueryHandle queryRootHandle = null; 
 
            int hr = SafeNativeMethods.DRMParseUnboundLicense(
                certificate, 
                out queryRootHandle);
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid));
 
            using (queryRootHandle)
            { 
                string certificateId = GetUnboundLicenseStringAttribute( 
                    queryRootHandle,
                    NativeConstants.QUERY_IDVALUE, 
                    0);

                return certificateId;
            } 
        }
 
        internal static Dictionary ExtractApplicationSpecificDataFromLicense(string useLicenseChain) 
        {
            Invariant.Assert(useLicenseChain != null); 
            Dictionary _applicationSpecificDataDictionary =
                        new Dictionary(3, StringComparer.Ordinal);

            string useLicense = 
                GetElementFromCertificateChain(useLicenseChain, 0);
            Invariant.Assert(useLicense != null); 
 
            SafeRightsManagementQueryHandle queryRootHandle = null;
 
            int hr = SafeNativeMethods.DRMParseUnboundLicense(useLicense, out queryRootHandle);
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid));
 
            using (queryRootHandle)
            { 
                uint index = 0; 
                while (true)
                { 
                    // extract Application Data Name
                    string attributeName = GetUnboundLicenseStringAttribute(queryRootHandle,
                                                            NativeConstants.QUERY_APPDATANAME,
                                                            index); 
                    if (attributeName == null) // null is used to indicate a missing value or an end of sequence
                    { 
                        break; 
                    }
                    Errors.ThrowOnErrorCode(hr); 

                    // extract Application Data Value
                    string attributeValue = GetUnboundLicenseStringAttribute(queryRootHandle,
                                                            NativeConstants.QUERY_APPDATAVALUE, 
                                                            index);
                    Errors.ThrowOnErrorCode(hr); 
 
                    // we expect that dictionary will validate all necessary key/value data requirements
                    _applicationSpecificDataDictionary.Add(attributeName, attributeValue); 

                    index++;
                }
            } 

            return _applicationSpecificDataDictionary; 
        } 

        internal static void GetContentIdFromLicense( 
            string useLicenseChain,
            out string contentId,
            out string contentIdType)
        { 
            Invariant.Assert(useLicenseChain != null);
 
            string useLicense = 
                GetElementFromCertificateChain(useLicenseChain, 0);
            Invariant.Assert(useLicense != null); 

            SafeRightsManagementQueryHandle queryRootHandle = null;

            // Parse the license and get the query handle 
            int hr = SafeNativeMethods.DRMParseUnboundLicense(
                useLicense, 
                out queryRootHandle); 
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid)); 

            using (queryRootHandle)
            {
                SafeRightsManagementQueryHandle workItemQueryHandle = null; 

                // extract object information from each Work Item 
                hr = SafeNativeMethods.DRMGetUnboundLicenseObject( 
                                        queryRootHandle,
                                        NativeConstants.QUERY_WORK, 
                                        0,
                                        out workItemQueryHandle);
                Errors.ThrowOnErrorCode(hr);
                Debug.Assert((workItemQueryHandle != null) && (!workItemQueryHandle.IsInvalid)); 

                using (workItemQueryHandle) 
                { 
                    // get the attributes we are after
                    contentIdType = GetUnboundLicenseStringAttribute( 
                        workItemQueryHandle,
                        NativeConstants.QUERY_IDTYPE,
                        0);
 
                    contentId = GetUnboundLicenseStringAttribute(
                        workItemQueryHandle, 
                        NativeConstants.QUERY_IDVALUE, 
                        0);
                } 
            }
        }

        #region Debug 
        // We currently don’t use these two methods, but they may be useful in the future.
        // So we keep them in the debug build only, and changed them from internal methods 
        // to private methods to remove them from asmmeta files. 
#if DEBUG
        private static List GetGrantsFromBoundUseLicense( 
                                    SafeRightsManagementHandle boundUseLicenseHandle, ContentUser user)
        {
            Invariant.Assert(!boundUseLicenseHandle.IsInvalid);
 
            List resultList = new List(10);
 
            // Go through each ContentRight within group  item 
            for (uint rightIndex = 0; ; rightIndex++)
            { 
                // extract object information from each Work Item
                SafeRightsManagementHandle rightQueryHandle = null;

                int hr = SafeNativeMethods.DRMGetBoundLicenseObject( 
                    boundUseLicenseHandle,
                    NativeConstants.QUERY_RIGHT, 
                    rightIndex, 
                    out rightQueryHandle);
 
                if ((hr == (int)RightsManagementFailureCode.NoMoreData) ||
                     (hr == (int)RightsManagementFailureCode.QueryReportsNoResults))
                {
                    // we got to the end of the RIGHT's list 
                    break;
                } 
 
                Errors.ThrowOnErrorCode(hr);
                Debug.Assert((rightQueryHandle != null) && (!rightQueryHandle.IsInvalid)); 

                using (rightQueryHandle)
                {
                    // We got to the "right" object, now we can ask for the name 
                    string rightName = GetBoundLicenseStringAttribute(rightQueryHandle, NativeConstants.QUERY_NAME, 0);
 
                    // if it is one of the erights that we "understand" we can proceed to query the time interval 
                    Nullable right = GetRightFromString(rightName);
 
                    if (right != null)
                    {
                        DateTime timeFrom = DateTime.MinValue;
                        DateTime timeUntil = DateTime.MaxValue; 

                        SafeRightsManagementHandle rangeTimeQueryHandle = null; 
 
                        hr = SafeNativeMethods.DRMGetBoundLicenseObject(
                            rightQueryHandle, 
                            NativeConstants.QUERY_RANGETIMECONDITION,
                            0,
                            out rangeTimeQueryHandle);
 

                        if ((hr != (int)RightsManagementFailureCode.NoMoreData) && 
                             (hr != (int)RightsManagementFailureCode.QueryReportsNoResults)) 
                        {
                            Errors.ThrowOnErrorCode(hr); 
                            Debug.Assert((rangeTimeQueryHandle != null) && (!rangeTimeQueryHandle.IsInvalid));

                            using (rangeTimeQueryHandle)
                            { 
                                timeFrom = GetBoundLicenseDateTimeAttribute(
                                                rangeTimeQueryHandle, 
                                                NativeConstants.QUERY_FROMTIME, 
                                                0,
                                                DateTime.MinValue); 

                                timeUntil = GetBoundLicenseDateTimeAttribute(
                                                rangeTimeQueryHandle,
                                                NativeConstants.QUERY_UNTILTIME, 
                                                0,
                                                DateTime.MaxValue); 
                            } 
                        }
 
                        resultList.Add(new ContentGrant(user, right.Value, timeFrom, timeUntil));
                    }
                }
            } 
            return resultList;
        } 
 
        private static List GetGrantsFromBoundUseLicenseList(
                                    List boundUseLicenseHandleList, ContentUser user) 
        {
            Invariant.Assert(boundUseLicenseHandleList != null);

            List resultList = new List(boundUseLicenseHandleList.Count); 

            // Go through each ContentRight within group  item 
            foreach (SafeRightsManagementHandle boundUseLicenseHandle in boundUseLicenseHandleList) 
            {
                Debug.Assert(!boundUseLicenseHandle.IsInvalid); 

                List newList = GetGrantsFromBoundUseLicense(boundUseLicenseHandle, user);
                foreach (ContentGrant newGrant in newList)
                { 
                    resultList.Add(newGrant);
                } 
            } 
            return resultList;
        } 
#endif
        #endregion Debug

        private static List GetRightsInfoFromUseLicense( 
            string useLicenseChain,
            out string rightGroupName) 
        { 
            Invariant.Assert(useLicenseChain != null);
 
            string useLicense = GetElementFromCertificateChain(useLicenseChain, 0);
            Invariant.Assert(useLicense != null);

            List resultRightsInfoList = new List(10); 

            SafeRightsManagementQueryHandle queryRootHandle = null; 
 
            // Parse the license and get the query handle
            int hr = SafeNativeMethods.DRMParseUnboundLicense( 
                    useLicense,
                    out queryRootHandle);
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid)); 

            using (queryRootHandle) 
            { 
                SafeRightsManagementQueryHandle workItemQueryHandle = null;
 
                // extract object information from the Work Item
                hr = SafeNativeMethods.DRMGetUnboundLicenseObject(
                    queryRootHandle,
                    NativeConstants.QUERY_WORK, 
                    0,
                    out workItemQueryHandle); 
                Errors.ThrowOnErrorCode(hr); 
                Debug.Assert((workItemQueryHandle != null) && (!workItemQueryHandle.IsInvalid));
 
                using (workItemQueryHandle)
                {
                    SafeRightsManagementQueryHandle rightGroupQueryHandle = null;
 
                    // extract object information from right group Item
                    hr = SafeNativeMethods.DRMGetUnboundLicenseObject( 
                        workItemQueryHandle, 
                        NativeConstants.QUERY_RIGHTSGROUP,
                        0, 
                        out rightGroupQueryHandle);
                    Errors.ThrowOnErrorCode(hr);
                    Debug.Assert((rightGroupQueryHandle != null) && (!rightGroupQueryHandle.IsInvalid));
 
                    using (rightGroupQueryHandle)
                    { 
                        rightGroupName = GetUnboundLicenseStringAttribute( 
                            rightGroupQueryHandle,
                            NativeConstants.QUERY_NAME, 
                            0);

                        // Go through each Right within group  item
                        for (uint rightIndex = 0; ; rightIndex++) 
                        {
                            RightNameExpirationInfoPair rightInfo = 
                                        GetRightInfoFromRightGroupQueryHandle(rightGroupQueryHandle, rightIndex); 

                            if (rightInfo == null) 
                            {
                                break;
                            }
 
                            resultRightsInfoList.Add(rightInfo);
                        } 
                    } 
                }
            } 

            return resultRightsInfoList;
        }
 
        private static RightNameExpirationInfoPair GetRightInfoFromRightGroupQueryHandle
                            (SafeRightsManagementQueryHandle rightGroupQueryHandle, uint rightIndex) 
        { 
            SafeRightsManagementQueryHandle rightQueryHandle = null;
 
            int hr = SafeNativeMethods.DRMGetUnboundLicenseObject(
                    rightGroupQueryHandle,
                    NativeConstants.QUERY_RIGHT,
                    rightIndex, 
                    out rightQueryHandle);
 
            if ((hr == (int)RightsManagementFailureCode.NoMoreData) || 
                     (hr == (int)RightsManagementFailureCode.QueryReportsNoResults))
            { 
                // we got to the end of the RIGHT's list
                return null;
            }
            Errors.ThrowOnErrorCode(hr); 
            Debug.Assert((rightQueryHandle != null) && (!rightQueryHandle.IsInvalid));
 
            using (rightQueryHandle) 
            {
                // We got to the "right" object, now we can ask for the name 
                string rightName = GetUnboundLicenseStringAttribute(
                                                                        rightQueryHandle,
                                                                        NativeConstants.QUERY_NAME,
                                                                        0); 

                DateTime timeFrom = DateTime.MinValue; 
                DateTime timeUntil = DateTime.MaxValue; 

                SafeRightsManagementQueryHandle conditionListHandle = null; 

                // we should also get the expiration infornmation out
                hr = SafeNativeMethods.DRMGetUnboundLicenseObject(
                    rightQueryHandle, 
                    NativeConstants.QUERY_CONDITIONLIST,
                    0, 
                    out conditionListHandle); 

                if (hr >= 0) 
                {
                    Debug.Assert((conditionListHandle != null) && (!conditionListHandle.IsInvalid));

                    using (conditionListHandle) 
                    {
                        SafeRightsManagementQueryHandle rangeTimeQueryHandle = null; 
 
                        hr = SafeNativeMethods.DRMGetUnboundLicenseObject(
                            conditionListHandle, 
                            NativeConstants.QUERY_RANGETIMECONDITION,
                            0,
                            out rangeTimeQueryHandle);
 
                        if ((hr != (int)RightsManagementFailureCode.NoMoreData) &&
                             (hr != (int)RightsManagementFailureCode.QueryReportsNoResults)) 
                        { 
                            Errors.ThrowOnErrorCode(hr);
                            Debug.Assert((rangeTimeQueryHandle != null) && (!rangeTimeQueryHandle.IsInvalid)); 

                            using (rangeTimeQueryHandle)
                            {
                                timeFrom = GetUnboundLicenseDateTimeAttribute( 
                                                rangeTimeQueryHandle,
                                                NativeConstants.QUERY_FROMTIME, 
                                                0, 
                                                DateTime.MinValue);
 
                                timeUntil = GetUnboundLicenseDateTimeAttribute(
                                                rangeTimeQueryHandle,
                                                NativeConstants.QUERY_UNTILTIME,
                                                0, 
                                                DateTime.MaxValue);
                            } 
                        } 
                    }
                } 

                return new RightNameExpirationInfoPair(rightName, timeFrom, timeUntil);
            }
        } 

        internal static string GetContentIdFromPublishLicense(string publishLicense) 
        { 
            Invariant.Assert(publishLicense != null);
 
            SafeRightsManagementQueryHandle queryRootHandle = null;

            // Parse the license and get the query handle
            int hr = SafeNativeMethods.DRMParseUnboundLicense(publishLicense, out queryRootHandle); 
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid)); 
 
            using (queryRootHandle)
            { 

                SafeRightsManagementQueryHandle workQueryHandle = null;

 
                // extract object information from the Work Item
                hr = SafeNativeMethods.DRMGetUnboundLicenseObject( 
                                        queryRootHandle, 
                                        NativeConstants.QUERY_WORK,
                                        0, 
                                        out workQueryHandle);
                Errors.ThrowOnErrorCode(hr);
                Debug.Assert((workQueryHandle != null) && (!workQueryHandle.IsInvalid));
 
                // contentIdValue information from the root query object
                using (workQueryHandle) 
                { 
                    return GetUnboundLicenseStringAttribute(
                                            workQueryHandle, 
                                            NativeConstants.QUERY_IDVALUE,
                                            0);
                }
            } 
        }
 
        internal static Uri GetUseLicenseAcquisitionUriFromPublishLicense(string publishLicense) 
        {
            string nameAttributeValue; 
            string addressAttributeValue;

            GetDistributionPointInfoFromPublishLicense
                        (publishLicense, 
                        _distributionPointLicenseAcquisitionType,
                        out nameAttributeValue, 
                        out addressAttributeValue); 

            return new Uri(addressAttributeValue); 
        }

        internal static void GetReferralInfoFromPublishLicense(
                            string publishLicense, 
                            out string referralInfoName,
                            out Uri referralInfoUri) 
        { 
            string nameAttributeValue;
            string addressAttributeValue; 

            GetDistributionPointInfoFromPublishLicense
                        (publishLicense,
                        _distributionPointReferralInfoType, 
                        out nameAttributeValue,
                        out addressAttributeValue); 
 
            referralInfoName = nameAttributeValue;
 
            if (addressAttributeValue != null)
            {
                referralInfoUri = new Uri(addressAttributeValue);
            } 
            else
            { 
                referralInfoUri = null; 
            }
        } 

        private static void GetDistributionPointInfoFromPublishLicense(
                                                                            string publishLicense,
                                                                            string distributionPointType, 
                                                                            out string nameAttributeValue,
                                                                            out string addressAttributeValue) 
        { 
            Invariant.Assert(publishLicense != null);
 
            // we are not making a distinction between truly missing values and NULL values
            nameAttributeValue = null;
            addressAttributeValue = null;
 
            // Parse the license and get the query handle
            SafeRightsManagementQueryHandle queryRootHandle = null; 
            int hr = SafeNativeMethods.DRMParseUnboundLicense(publishLicense, out queryRootHandle); 
            Errors.ThrowOnErrorCode(hr);
            Debug.Assert((queryRootHandle != null) && (!queryRootHandle.IsInvalid)); 

            using (queryRootHandle)
            {
                uint index = 0; 

                while (true) 
                { 
                    SafeRightsManagementQueryHandle distributionPointQueryHandle = null;
                    // extract object information from the Root Item 
                    hr = SafeNativeMethods.DRMGetUnboundLicenseObject(
                                            queryRootHandle,
                                            NativeConstants.QUERY_DISTRIBUTIONPOINT,
                                            index, 
                                            out distributionPointQueryHandle);
                    if (hr == (int)RightsManagementFailureCode.QueryReportsNoResults) 
                    { 
                        break;
                    } 
                    Errors.ThrowOnErrorCode(hr);
                    Debug.Assert((distributionPointQueryHandle != null) && (!distributionPointQueryHandle.IsInvalid));

                    using (distributionPointQueryHandle) 
                    {
                        string addressType = GetUnboundLicenseStringAttribute( 
                                                distributionPointQueryHandle, 
                                                NativeConstants.QUERY_OBJECTTYPE,
                                                0); 
                        if (String.CompareOrdinal(addressType, distributionPointType) == 0)
                        {
                            nameAttributeValue = GetUnboundLicenseStringAttribute(
                                                distributionPointQueryHandle, 
                                                NativeConstants.QUERY_NAME,
                                                0); 
 
                            addressAttributeValue = GetUnboundLicenseStringAttribute(
                                                distributionPointQueryHandle, 
                                                NativeConstants.QUERY_ADDRESSVALUE,
                                                0);
                            return;
                        } 
                    }
 
                    index++; 
                }
            } 
        }


#if FALSE 
        // not using this for now, as we are not binding successfully bound rights as a single list
        internal static string BuildCommaSeparatedList(List stringList) 
        { 
            StringBuilder concatenatedStringList  = new StringBuilder(stringList.Count * 10);//guess the average right name size
 
            bool firstElementFlag = true;

            foreach (string right in stringList)
            { 
                if (firstElementFlag)
                { 
                    firstElementFlag = false; 
                }
                else 
                {
                    concatenatedStringList .Append(',');
                }
 
                concatenatedStringList.Append(right);
            } 
 
            return concatenatedStringList.ToString();
        } 
#endif

        internal static string GetSecurityProviderPath()
        { 
            uint typeLength = 0;
            StringBuilder type = null; 
            uint pathLength = 0; 
            StringBuilder path = null;
 
            int hr = SafeNativeMethods.DRMGetSecurityProvider(0,
                                                        ref typeLength,
                                                        null,
                                                        ref pathLength, 
                                                        null);
            Errors.ThrowOnErrorCode(hr); 
 
            checked
            { 
                type = new StringBuilder((int)typeLength);
                path = new StringBuilder((int)pathLength);
            }
 
            hr = SafeNativeMethods.DRMGetSecurityProvider(0,
                                                        ref typeLength, 
                                                        type, 
                                                        ref pathLength,
                                                        path); 
            Errors.ThrowOnErrorCode(hr);

            return path.ToString();
        } 

        internal static Nullable GetRightFromString(string rightName) 
        { 
            rightName = rightName.ToString().ToUpper(CultureInfo.InvariantCulture);
 
            for (int i = 0; i < _rightEnums.Length; i++)
            {
                if (String.CompareOrdinal(_rightNames[i], rightName) == 0)
                { 
                    return _rightEnums[i];
                } 
            } 

            return null; 
        }


        internal static string GetStringFromRight(ContentRight right) 
        {
            for (int i = 0; i < _rightEnums.Length; i++) 
            { 
                if (_rightEnums[i] == right)
                { 
                    return _rightNames[i];
                }
            }
 
            throw new ArgumentOutOfRangeException("right");
        } 
 
        private List CryptoProviderList
        { 
            get
            {
                if (_cryptoProviderList == null)
                { 
                    _cryptoProviderList = new List(5);
                } 
                return _cryptoProviderList; 
            }
        } 

        /// 
        /// Call this before accepting any API call
        ///  
        private void CheckDisposed()
        { 
            if ((_hSession == null) || 
                (_hSession.IsInvalid))
                throw new ObjectDisposedException("SecureEnvironment"); 
        }

        private const string _defaultUserName = @"DefaultUser@DefaultDomain.DefaultCom";     // RM default user name
 
        private const string _distributionPointLicenseAcquisitionType = @"License-Acquisition-URL";
        private const string _distributionPointReferralInfoType = @"Referral-Info"; 
 
        private const string _passportActivationRegistryFullKeyName = @"HKEY_LOCAL_MACHINE\Software\Microsoft\MSDRM\ServiceLocation\PassportActivation";
        private const string _passportActivationRegistryKeyName = @"Software\Microsoft\MSDRM\ServiceLocation\PassportActivation"; 

        private ContentUser _user = null;
        private CallbackHandler _callbackHandler;
 
        private SafeRightsManagementSessionHandle _hSession = null; // if this is zero, we are disposed
 
        // we preserve this so ve can remove certificates in case of temp activation 
        UserActivationMode _userActivationMode = UserActivationMode.Permanent;
 
        private SafeRightsManagementEnvironmentHandle _envHandle = null;  // if this is null, we are disposed

        private SafeRightsManagementHandle _defaultLibraryHandle = null;
 
        private List _cryptoProviderList;
 
        // the following 2 arrays are used for parsing and converting between String and Enum; 
        // therefore, the entries in the _rightEnums and the _rightNames must be in the same order.
        static private ContentRight[] _rightEnums = { 
                                        ContentRight.View,
                                        ContentRight.Edit,
                                        ContentRight.Print,
                                        ContentRight.Extract, 
                                        ContentRight.ObjectModel,
                                        ContentRight.Owner, 
                                        ContentRight.ViewRightsData, 
                                        ContentRight.Forward,
                                        ContentRight.Reply, 
                                        ContentRight.ReplyAll,
                                        ContentRight.Sign,
                                        ContentRight.DocumentEdit,
                                        ContentRight.Export}; 

        // entries in this array must be in UPPERCASE, as we make such assumption during parsing 
        static private string[] _rightNames = { 
                                        "VIEW",
                                        "EDIT", 
                                        "PRINT",
                                        "EXTRACT",
                                        "OBJMODEL",
                                        "OWNER", 
                                        "VIEWRIGHTSDATA",
                                        "FORWARD", 
                                        "REPLY", 
                                        "REPLYALL",
                                        "SIGN", 
                                        "DOCEDIT",
                                        "EXPORT"};
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK