ClientSession.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Base / MS / Internal / Security / RightsManagement / ClientSession.cs / 1 / 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: [....]:  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
 
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.


                        

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