Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / TrustUi / MS / Internal / documents / DocumentSignatureManager.cs / 1 / DocumentSignatureManager.cs
//----------------------------------------------------------------------------
//
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//
//
// Description:
// DocumentSignatureManager is an internal API for Mongoose to deal with Digital Signatures.
//
// History:
// 05/03/05 - [....] created
// 07/26/05 - [....] added shared trace switch and method
//---------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO.Packaging;
using System.Reflection;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Permissions; // For Friend Access and elevations
using System.Threading;
using System.Windows.TrustUI;
using System.Windows.Forms;
using System.Windows.Interop;
using System.Windows.Threading;
using MS.Internal.Documents.Application;
using MS.Internal.PresentationUI;
namespace MS.Internal.Documents
{
///
/// DocumentSignatureManager is a internal Avalon class used to expose the DigSig Document API
///
[FriendAccessAllowed]
internal sealed class DocumentSignatureManager
{
#region Constructors
//-----------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
///
/// The constructor
///
///
/// Critical
/// 1) Sets critical for set property DigitalSignatureProvider, which
/// is the basis for trust decisions.
/// 2) Sets _changeLog to an empty list.
///
[SecurityCritical]
private DocumentSignatureManager(IDigitalSignatureProvider digSigProvider)
{
if (digSigProvider != null)
{
DigitalSignatureProvider = digSigProvider;
}
else
{
throw new ArgumentNullException("digSigProvider");
}
_changeLog = new List();
_digSigSigResources = new Dictionary();
DocumentRightsManagementManager rightsManagementManager =
DocumentRightsManagementManager.Current;
if(rightsManagementManager != null)
{
rightsManagementManager.RMPolicyChange +=
new DocumentRightsManagementManager.RMPolicyChangeHandler(OnRMPolicyChanged);
rightsManagementManager.Evaluate();
}
// notify the documentmanager when the signatures change
SignaturesChanged += DocumentManager.OnModify;
}
#endregion Constructors
#region Public Event
//------------------------------------------------------
//
// Public Event
//
//-----------------------------------------------------
public event EventHandler SignaturesChanged;
public event SignatureStatusChangeHandler SignatureStatusChange;
#endregion Public Event
#region Internal Methods
//------------------------------------------------------
//
// Internal Methods
//
//------------------------------------------------------
///
/// Forces an Evaluate which will result in SignatureStatus and
/// SignaturePolicy event being fired.
///
///
/// Critical
/// 1) Sets a SecurityCritical property (DigitalSignature.SignatureState)
/// TreatAsSafe
/// 1) We are setting the SignatureStatus to "Unverifiable" only in
/// the case where the document does not comply to signing standards.
///
[SecurityCritical, SecurityTreatAsSafe]
internal void Evaluate()
{
Trace.SafeWrite(
Trace.Signatures,
"Evaluate called.");
SignatureStatus calcSigStatus = SignatureStatus.Unknown;
SignaturePolicy calcSigPolicy = SignaturePolicy.AllowSigning |
SignaturePolicy.ModifyDocumentProperties;
// If the document is not signed, we already know the signature
// status of the document
if (!IsSigned)
{
//There are no signatures applied to this document.
calcSigStatus = SignatureStatus.NotSigned;
}
// Check to see if the certificates have been validated
else if (!AreAllSignaturesVerified)
{
calcSigStatus = SignatureStatus.Undetermined;
calcSigPolicy = SignaturePolicy.AllowNothing;
}
// Otherwise we should look at all the signatures in the document
else
{
bool areAllSignaturesValid = true;
// Verify that the document is signable before we continue.
if (!VerifySignability())
{
// If the document does not meet the signing criteria, the signatures are
// not considered valid.
areAllSignaturesValid = false;
// Walk the list of signatures applied to the package and set their state
// to "Unverifiable."
foreach (DigitalSignature digitalSignature in DigitalSignatureProvider.Signatures)
{
digitalSignature.SignatureState = SignatureStatus.Unverifiable;
}
}
else
{
// Check all the signatures applied to the package to see
// if they are all valid. At this point the signatures should
// all have been verified, and the certificates associated with
// them should all have been validated.
foreach (DigitalSignature digitalSignature in DigitalSignatureProvider.Signatures)
{
bool valid =
(digitalSignature.SignatureState == SignatureStatus.Valid) &&
(GetCertificateStatusFromTable(digitalSignature) == CertificatePriorityStatus.Ok);
if (valid)
{
// Add the restrictions on the policy imposed by the
// new signature only if it is valid.
calcSigPolicy =
AddRestrictionsFromSignature(calcSigPolicy, digitalSignature);
}
areAllSignaturesValid &=
(valid ||
(digitalSignature.SignatureState == SignatureStatus.NotSigned));
}
// If the policy does not allow modifying document properties and the properties have been
// changed, then the signatures have been invalidated.
if (!IsAllowedByPolicy(calcSigPolicy, SignaturePolicy.ModifyDocumentProperties) &&
!DocumentProperties.Current.VerifyPropertiesUnchanged())
{
areAllSignaturesValid = false;
// Walk the list of signatures applied to the package and set their state
// to "Invalid" if necessary.
foreach (DigitalSignature digitalSignature in DigitalSignatureProvider.Signatures)
{
if (digitalSignature.IsDocumentPropertiesRestricted)
{
digitalSignature.SignatureState = SignatureStatus.Invalid;
}
}
}
}
if (areAllSignaturesValid)
{
calcSigStatus = SignatureStatus.Valid;
}
else
{
calcSigStatus = SignatureStatus.Invalid;
}
}
Invariant.Assert(
calcSigStatus != SignatureStatus.Unknown,
"We should have determined a signature status by now.");
//Fire the events.
OnSignatureStatusChange(calcSigStatus);
_signaturePolicy.Value = calcSigPolicy;
}
///
/// If the document is signed, this function verifies the signatures and
/// validates all the associated certificates.
///
///
/// This function performs all the signature verification that must
/// happen on the main thread. This includes loading the signatures and
/// verifying the hashes. Certificate validation can and does happen on
/// a background thread.
///
///
/// Critical
/// 1) Calls StartCertificateStatusCheck
/// TreatAsSafe
/// 1) The list of certificates passed to the status check comes from
/// the critical for set provider.
///
[SecurityCritical, SecurityTreatAsSafe]
internal void VerifySignatures()
{
if (AreAllSignaturesVerified)
{
// If the certificates have already been verified, exit
return;
}
else if (!IsSigned)
{
// If the document isn't signed there is no certificate
// validation to do, and we can initialize the (empty)
// certificate status table for later use
_certificateStatusTable =
new Dictionary();
}
else
{
Trace.SafeWrite(
Trace.Signatures,
"Document loading complete; verifying signatures.");
// Once the document has finished loading, we can safely verify all
// the signatures in the package (i.e. compare hashes)
DigitalSignatureProvider.VerifySignatures();
// Retrieve and save all the certificates used
IList certificateList =
DigitalSignatureProvider.GetAllCertificates();
StartCertificateStatusCheck(certificateList);
}
}
///
/// ShowSignatureSummary: Displays the DigSig Summary dialog.
///
///
/// Critical
/// 1) Elevation to show a top level window.
/// 2) This method references the critical RootBrowserWindow property.
/// TreatAsSafe
/// 1) The window is a blessed internal window that uses purely Windows
/// Forms rather than Avalon.
/// 2) The RootBrowserWindow is not leaked beyond this method, and is
/// passed only to a WinForms dialog.
///
[SecurityCritical, SecurityTreatAsSafe]
internal void ShowSignatureSummaryDialog()
{
IList sigResList = GetSignatureResourceList(false /*requestsOnly*/);
SignatureSummaryDialog dialog = null;
System.Windows.Forms.IWin32Window parentWindow =
DocumentApplicationDocumentViewer.Instance.RootBrowserWindow;
(new UIPermission(UIPermissionWindow.AllWindows)).Assert(); //BlessedAssert
try
{
dialog = new SignatureSummaryDialog(
sigResList,
this,
false /*Sig Request Dialog*/);
dialog.ShowDialog(parentWindow);
}
finally
{
UIPermission.RevertAssert();
if (dialog != null)
{
dialog.Dispose();
}
}
}
///
/// RequestSigners: Displays the DigSig Request Signature dialog.
///
///
/// Critical - 1) Elevation to show a top level window.
/// 2) Elevates for unmanaged code access for showing messageboxes on error
/// 3) This method references the critical RootBrowserWindow property.
/// TreatAsSafe - 1) The window is a blessed internal window that uses purely Windows Forms rather than Avalon.
/// 2) Unmanaged code elevation is only for MessageBox.Show call (which internally calls
/// the Win32 MessageBox API. This should be pretty safe.
///
[SecurityCritical, SecurityTreatAsSafe]
internal void ShowSignatureRequestSummaryDialog()
{
//Check to see if package is Read Only or signed (we can't added request to a signed
//document.
//If the document does not meet the signing criteria, we alert the user and return.
if (!VerifySignability())
{
System.Windows.MessageBox.Show(
SR.Get(SRID.DigitalSignatureMessageDocumentNotSignable),
SR.Get(SRID.DigitalSignatureMessageDocumentNotSignableTitle),
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Exclamation);
}
else if (IsSigningAllowed && !IsSigned)
{
IList sigResList = GetSignatureResourceList(true /*requestsOnly*/);
SignatureSummaryDialog dialog = null;
System.Windows.Forms.IWin32Window parentWindow =
DocumentApplicationDocumentViewer.Instance.RootBrowserWindow;
(new UIPermission(UIPermissionWindow.AllWindows)).Assert(); //BlessedAssert
try
{
//Create and show the Summary Dialog in the Request signature mode.
dialog = new SignatureSummaryDialog(
sigResList,
this,
true /*Sig Request Dialog*/);
dialog.ShowDialog(parentWindow);
}
finally
{
UIPermission.RevertAssert();
if (dialog != null)
{
dialog.Dispose();
}
}
}
else
{
if (!IsSigningAllowed)
{
System.Windows.MessageBox.Show(
SR.Get(SRID.DigitalSignatureWarnErrorRMSigningMessage),
SR.Get(SRID.DigitalSignatureWarnErrorSigningErrorTitle),
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Exclamation
);
}
else
{
System.Windows.MessageBox.Show(
SR.Get(SRID.DigitalSignatureWarnErrorReadOnlyNoMoreRequest),
SR.Get(SRID.DigitalSignatureWarnErrorSigningErrorTitle),
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Exclamation
);
}
}
}
///
/// Display the signing dialog parented from the root browser window
/// without an accompanying signature request.
///
///
/// Critical
/// 1) Calls SecurityCritical property RootBrowserWindow on
/// DocumentApplicationDocumentViewer to get a handle to the root
/// browser window
/// 2) Calls critical method ShowSigningDialog(IntPtr)
/// TreatAsSafe
/// 1) The handle is passed only to a critical method.
/// 2) The IntPtr passed to ShowSigningDialog comes from a critical
/// property that is a known source.
///
[SecurityCritical, SecurityTreatAsSafe]
internal void ShowSigningDialog()
{
ShowSigningDialog(
DocumentApplicationDocumentViewer.Instance.RootBrowserWindow.Handle);
}
///
/// Display the signing dialog without an accompanying signature request.
///
/// A handle to the parent window for the
/// signing dialog
///
/// Critical
/// 1) Calls critical method ShowSigningDialog(IntPtr,
/// DigitalSignature) with an IntPtr that comes from an argument
/// to this method.
///
[SecurityCritical]
internal void ShowSigningDialog(IntPtr parentWindow)
{
ShowSigningDialog(
parentWindow,
null /*DigitalSignature digitalSignatureRequest*/);
}
///
/// Display the signing dialog. This method optionally takes a SignatureRequest.
/// The actual signing operation will take place in a callback from the dialog.
///
/// The request to be associated
/// with the signature (can be null)
/// A handle to the window that will be the
/// parent of the signing dialog
///
/// Critical
/// 1) Calls SecurityCritical method ShowCertificatePickerDialog
/// 2) Elevates for UIPermissions to display a signing dialog
/// 3) Creates DigitalSignature instances and sets properties on them
/// 4) Creates a SigningDialog which has a critical constructor
/// 5) Parents a dialog off an IntPtr passed in as an argument and
/// uses the IntPtr under an assert.
/// 6) Elevates for KeyContainerPermission to access PrivateKey
/// TreatAsSafe
/// 0) The parameter that was passed is a trusted DigitalSignature.
/// This is because a security critical code path was required to
/// create it since the constructor is critical. Also the properties
/// were set in a critical code path since the set accessor on all
/// the properties is also critical.
/// 1) The selection dialog is Win32 based and provided by the system.
/// The certificate returned will always be user selected and
/// accessible by the user.
/// 2) The dialog that is invoked is a blessed dialog implemented in
/// WinForms to prevent spoofing from the Avalon content/application.
/// 3) The DigitalSignature instance is created and properties set
/// based on internal resources.
/// 4) We are supplying the SigningDialog a trusted certificate that
/// was selected by the user so this is safe.
/// 5) The PrivateKey value is only placed in a local variable and not
/// leaked anywhere else.
/// NotSafe
/// 1) The IntPtr should only come from trusted code.
///
[SecurityCritical]
internal void ShowSigningDialog(
IntPtr parentWindow,
DigitalSignature digitalSignatureRequest)
{
// First check if signing is allowed by RM. If not, show an error
// dialog and exit.
if (!IsSigningAllowed)
{
System.Windows.MessageBox.Show(
SR.Get(SRID.DigitalSignatureWarnErrorRMSigningMessage),
SR.Get(SRID.DigitalSignatureWarnErrorSigningErrorTitle),
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Exclamation);
return;
}
// If the document does not meet the signing criteria, we alert the user and return.
if (!VerifySignability())
{
System.Windows.MessageBox.Show(
SR.Get(SRID.DigitalSignatureMessageDocumentNotSignable),
SR.Get(SRID.DigitalSignatureMessageDocumentNotSignableTitle),
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Exclamation);
return;
}
// Check the signature policy to see if a new signature will invalidate an
// existing signature.
if (IsSigned && !IsSigningAllowedByPolicy)
{
System.Windows.MessageBoxResult dialogResult = System.Windows.MessageBox.Show(
SR.Get(SRID.DigitalSignatureMessageActionInvalidatesSignature),
SR.Get(SRID.DigitalSignatureMessageSignNowTitle),
System.Windows.MessageBoxButton.YesNo,
System.Windows.MessageBoxImage.Exclamation);
if (dialogResult == System.Windows.MessageBoxResult.No)
{
return;
}
}
// Check to see if user is trying to add another signature when no
// request spot are available. If there are no request spots warn user.
if (IsSigned && !HasRequests)
{
System.Windows.MessageBoxResult dialogResult = System.Windows.MessageBox.Show(
SR.Get(SRID.DigitalSignatureMessageSignNoPending),
SR.Get(SRID.DigitalSignatureMessageSignNowTitle),
System.Windows.MessageBoxButton.YesNo,
System.Windows.MessageBoxImage.Exclamation);
if (dialogResult == System.Windows.MessageBoxResult.No)
{
return;
}
}
// Check to see if user is trying to add another signature when
// request spot are available but they aren't using it. If there are
// no request spots warn user.
else if (IsSigned && HasRequests && digitalSignatureRequest == null)
{
System.Windows.MessageBoxResult dialogResult = System.Windows.MessageBox.Show(
SR.Get(SRID.DigitalSignatureMessageSignPending),
SR.Get(SRID.DigitalSignatureMessageSignNowTitle),
System.Windows.MessageBoxButton.YesNo,
System.Windows.MessageBoxImage.Exclamation);
if (dialogResult == System.Windows.MessageBoxResult.No)
{
return;
}
}
// Check to see if we are signing a request.
if (digitalSignatureRequest == null)
{
//This is not a signing request. Now Check
//to see if document has already been signed. If it has been signed
//then we don't want to allow user to define intent/location (definition)
//on the signing dialog. To prevent this we will create an empty
//DigitalSignatureRequest.
if (IsSigned)
{
digitalSignatureRequest = new DigitalSignature();
}
else
{
// The document hasn't yet been signed -- warn the user that he/she
// should add signature requests before signing and give the user the option
// to cancel
System.Windows.MessageBoxResult dialogResult = System.Windows.MessageBox.Show(
SR.Get(SRID.DigitalSignatureMessageAddRequestsBeforeSigning),
SR.Get(SRID.DigitalSignatureMessageAddRequestsBeforeSigningTitle),
System.Windows.MessageBoxButton.YesNo,
System.Windows.MessageBoxImage.Exclamation);
// If the user canceled, stop the signing process.
if (dialogResult == System.Windows.MessageBoxResult.No)
{
return;
}
}
}
// Get certificate selection from the user. The requestAgain flag is set to
// true if we need to prompt the user for another selection. This happens only
// if the user selects a smart card certificate but doesn't insert the card.
bool requestAgain;
X509Certificate2 x509Certificate2;
do
{
requestAgain = false;
// Show certificate picker dialog
x509Certificate2 = ShowCertificatePickerDialog(parentWindow);
// If the certificate is null, the user cancelled the selection, so exit.
if (x509Certificate2 == null)
{
return;
}
// Check if we can retrieve the private key. This will alert us of the case
// in which the user has selected a smart card certificate but selected
// cancel when asked to insert the card by throwing a CryptoGraphicException.
// If the user selects a non-smart card certificate, or selects a smart card
// certificate and inserts the smart card, no exception will be thrown.
(new KeyContainerPermission(KeyContainerPermissionFlags.AllFlags)).Assert(); //BlessedAssert
try
{
// We access the PrivateKey only to test if it can be retrieved -- the
// actual contents are never used.
AsymmetricAlgorithm testKey = x509Certificate2.PrivateKey;
}
catch (CryptographicException)
{
// In this case the user selected a smart card key but did not insert
// the smart card. We should redisplay the certificate picker to allow
// the user to select a different key.
requestAgain = true;
}
finally
{
KeyContainerPermission.RevertAssert();
}
} while (requestAgain);
SigningDialog dialog = null;
(new UIPermission(UIPermissionWindow.AllWindows)).Assert(); //BlessedAssert
try
{
dialog = new SigningDialog(
x509Certificate2,
digitalSignatureRequest,
this);
dialog.ShowDialog(NativeWindow.FromHandle(parentWindow));
}
finally
{
UIPermission.RevertAssert();
if (dialog != null)
{
dialog.Dispose();
}
}
}
///
/// Gets a List of SignatureResources.
///
internal IList GetSignatureResourceList(bool requestsOnly)
{
//Clear the map.
_digSigSigResources.Clear();
IList signResourcesList = new List();
//Loop through all DigSigs
foreach (DigitalSignature digSig in DigitalSignatureProvider.Signatures)
{
SignatureResources sigResources;
//Is this signature a request signature?
bool notSigned = digSig.SignatureState == SignatureStatus.NotSigned;
//Filter out signed DigitalSignature if requester wants request signatures only
if (!requestsOnly || notSigned)
{
//Use the SignatureResourceHelper to get the strings to display
//in the ListBox
sigResources = SignatureResourceHelper.GetResources(
digSig,
GetCertificateStatusFromTable(digSig));
//Add to map and to list.
_digSigSigResources.Add(sigResources, digSig);
signResourcesList.Add(sigResources);
}
}
return signResourcesList;
}
///
/// Signs the document with the given digital signature. This function
/// blocks the UI until the signing operation is complete.
///
///
/// Critical
/// 1) This method uses the securitycritical field _certificateStatusTable
/// to set CertificatePriorityStatus.
/// 2) Calls critical method UndoChanges.
/// 3) Accesses critical field _changeLog.
/// TreatAsSafe
/// 1) The certificate whose status is added to the table is critical
/// for set in DigitalSignature.
/// 2) UndoChanges is called only if the save fails.
/// 3) The change log is only modified to clear it after the save
/// operation has successfully completed.
///
[SecurityCritical, SecurityTreatAsSafe]
internal bool SignDocument(DigitalSignature digSig, Form parentDialog, bool isSaveAs)
{
bool rtn = false;
//First place this new DigSig's Cert in the CertStatus Table as CertificatePriorityStatus.Ok
//since user has selected this cert to use for signing. We will not be checking the status of
//this cert since the user selected it for signing.
if (_certificateStatusTable != null && !_certificateStatusTable.ContainsKey(digSig.Certificate))
{
_certificateStatusTable.Add(digSig.Certificate, CertificatePriorityStatus.Ok);
}
//Show the progress dialog
ProgressDialog dialog =
ProgressDialog.CreateThreaded(
SR.Get(SRID.SigningProgressTitle),
SR.Get(SRID.SigningProgressLabel)).Form;
try
{
//Need to check if this is the first Signature applied to this document. If so then
//we need to create a SignatureDefinition before we can sign.
if (!IsSigned && digSig.GuidID == null)
{
digSig.GuidID = DigitalSignatureProvider.AddRequestSignature(digSig);
_changeLog.Add(new ChangeLogEntity((Guid)digSig.GuidID, true));
}
//Sign XPS document
try
{
DigitalSignatureProvider.SignDocument(digSig);
}
catch (CryptographicException e)
{
// Close the progress dialog
ProgressDialog.CloseThreaded(dialog);
// If the exception thrown was a result of the user cancelling
// the operation (i.e. cancelling a smartcard PIN prompt)
// then we will return silently; otherwise we'll display the exception
// message to the user since it typically indicates a smartcard failure
// of some sort that the user can take action on, rather than something
// that is catastrophic.
if (GetErrorCode(e) != SCARD_W_CANCELLED_BY_USER)
{
System.Windows.MessageBoxResult dialogResult = System.Windows.MessageBox.Show(
String.Format(
CultureInfo.CurrentCulture,
SR.Get(SRID.DigitalSignatureWarnErrorGeneric),
e.Message),
SR.Get(SRID.DigitalSignatureWarnErrorSigningErrorTitle),
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Exclamation);
}
UndoChanges();
return false;
}
}
finally
{
// Close the progress dialog
ProgressDialog.CloseThreaded(dialog);
}
_changeLog.Add(new ChangeLogEntity((Guid)digSig.GuidID, false));
//Since we're signing the document, signatures have changed; raise the
//SignaturesChanged event before saving takes place.
RaiseSignaturesChanged();
//The signing is complete, now lets save the package.
//Save XPS document to file
DocumentManager docManager = DocumentManager.CreateDefault();
if (docManager != null)
{
if (isSaveAs)
{
rtn = docManager.SaveAs(null);
}
else
{
rtn = docManager.Save(null);
}
if (!rtn)
{
UndoChanges();
}
else
{
// if we succeeded in signing and saving
// the changes are 'committed' now, so
// clear the changelog.
_changeLog.Clear();
}
}
// If the operation succeeded, re-evaluate signature status
if (rtn)
{
// If there are any signatures that will be invalidated by a
// new signature, mark those signatures as invalid
if (!IsSigningAllowedByPolicy)
{
foreach (DigitalSignature signature in DigitalSignatureProvider.Signatures)
{
if (!signature.Equals(digSig) &&
signature.IsAddingSignaturesRestricted)
{
signature.SignatureState = SignatureStatus.Invalid;
}
}
}
Evaluate();
}
return rtn;
}
///
/// Displays a signing dialog off the given parent window, optionally
/// using the fields from the signature request corresponding to the
/// SignatureResources argument. This is called by the Signature Summary
/// dialog.
///
/// An optional SignatureResources
/// object that corresponds to a signature request.
/// The parent window for the signing dialog
///
///
/// Critical
/// 1) Takes an IntPtr argument and passes it to critical code.
///
[SecurityCritical]
internal void OnSign(SignatureResources? signatureResources, IntPtr parentWindow)
{
//Nothing was highlighted in the dialog. So this isn't a request signature.
if (signatureResources == null)
{
ShowSigningDialog(parentWindow);
}
else
{
//Something was highlighted. Need to see if it was a request or regular Sig.
DigitalSignature digSig = _digSigSigResources[signatureResources.Value];
if (digSig.SignatureState == SignatureStatus.NotSigned)
{
//We are signing a request.
ShowSigningDialog(parentWindow, digSig);
}
else
{
//A regular signature was highlighted so just sign document.
ShowSigningDialog(parentWindow);
}
}
}
///
/// Uses the CLR's X509CertificateUI class to display the Windows
/// certificate view dialog for the certificate associated with a given
/// signature.
///
/// The digital signature associated
/// with the certificate
/// The window off which to parent the dialog
///
///
/// Critical
/// 1) Asserts for UnmanagedCode permissions to display the certificate
/// dialog modally using the IntPtr handle passed in as an argument.
/// The overload of DisplayCertificate we use requires this assert.
///
[SecurityCritical]
internal void OnCertificateView(
SignatureResources signatureResources,
IntPtr parentWindow)
{
DigitalSignature digSig = _digSigSigResources[signatureResources];
X509Certificate2 certificate = null;
if (digSig != null)
{
certificate = digSig.Certificate;
}
if (certificate != null)
{
(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Assert(); //BlessedAssert
try
{
X509Certificate2UI.DisplayCertificate(certificate, parentWindow);
}
finally
{
SecurityPermission.RevertAssert();
}
}
}
///
/// OnSummaryAdd.
///
/// Critical - Makes use of critical RootBrowserWindow property.
/// TreatAsSafe - Uses it to parent a safe WinForms dialog.
///
///
[SecurityCritical, SecurityTreatAsSafe]
internal void OnSummaryAdd()
{
RequestedSignatureDialog requestSignatureDialog = new RequestedSignatureDialog(this);
requestSignatureDialog.ShowDialog(DocumentApplicationDocumentViewer.Instance.RootBrowserWindow);
requestSignatureDialog.Dispose();
}
///
/// OnSummaryDelete. This function is called from the signature summary
/// dialog when the Delete button is clicked to remove a signature
/// request.
///
/// The resources of the request to
/// delete
///
/// Critical
/// 1) Removes a signature definition by calling critical function
/// RemoveRequestSignature.
///
[SecurityCritical]
internal void OnSummaryDelete(SignatureResources signatureResources)
{
//Get the corresponding DigSig
DigitalSignature digSig = _digSigSigResources[signatureResources];
//Now lets delete the DigSig (SigDefinition).
DigitalSignatureProvider.RemoveRequestSignature((Guid)digSig.GuidID);
//Fire SignatureChanged event to reflect the removed request.
RaiseSignaturesChanged();
}
///
/// OnAddRequestSignature. Called from Request dialog.
///
///
/// Critical
/// 1) Sets properties on a DocumentSignature instance using input
/// parameters.
///
[SecurityCritical]
internal void OnAddRequestSignature(SignatureResources sigResources, DateTime dateTime)
{
//Use the SignatureResource to create Request Digitalsignature.
DigitalSignature digSigRequest = new DigitalSignature();
//Assign fields.
digSigRequest.SignatureState = SignatureStatus.NotSigned;
digSigRequest.SubjectName = sigResources._subjectName;
digSigRequest.Reason = sigResources._reason;
digSigRequest.Location = sigResources._location;
digSigRequest.SignedOn = dateTime;
Guid spotId = DigitalSignatureProvider.AddRequestSignature(digSigRequest);
digSigRequest.GuidID = spotId;
// A request has been added, so the signatures have changed.
RaiseSignaturesChanged();
}
///
/// HasCertificate. Check to see if this signatureResources has a corresponding cert.
///
internal bool HasCertificate(SignatureResources signatureResources)
{
bool rtn = false;
//Find corresponding digSig
DigitalSignature digSig = _digSigSigResources[signatureResources];
//If this is a request signature it won't have a cert. This can also
//happen if the signature is invalid because it is missing a cert.
if (digSig.Certificate != null)
{
rtn = true;
}
return rtn;
}
///
/// Initialize the singleton DocumentSignatureManager.
///
/// The provider with which to initialize the
/// signature manager
///
/// Critical
/// 1) Calls the critical constructor for DocumentSignatureManager with
/// a parameter passed in as an argument to this function
///
[SecurityCritical]
internal static void Initialize(IDigitalSignatureProvider provider)
{
System.Diagnostics.Debug.Assert(
_singleton == null,
"DocumentSignatureManager initialized twice.");
if (_singleton == null)
{
_singleton = new DocumentSignatureManager(provider);
}
}
#endregion Internal Methods
#region Internal Properties
//-----------------------------------------------------
//
// Internal Properties
//
//------------------------------------------------------
internal static DocumentSignatureManager Current
{
get { return _singleton; }
}
///
/// Whether or not the document contains any signatures.
///
internal bool IsSigned
{
get { return DigitalSignatureProvider.IsSigned; }
}
///
/// Whether or not the document meets the signing criteria.
/// The first call to this may take a significant amount of time;
/// Subsequent calls will return a cached value.
///
internal bool IsSignable
{
get
{
return DigitalSignatureProvider.IsSignable;
}
}
///
/// Whether or not the document contains any signature requests.
///
internal bool HasRequests
{
get { return DigitalSignatureProvider.HasRequests; }
}
#endregion Internal Properties
#region Internal Delegate
//-----------------------------------------------------
//
// Internal Delegate
//
//-----------------------------------------------------
internal delegate void SignatureStatusChangeHandler(object sender,
SignatureStatusEventArgs args
);
#endregion Internal Delegate
#region Private Methods
//-----------------------------------------------------
//
// Private Methods
//
//------------------------------------------------------
///
/// Displays the cert picker dialog.
///
///
/// Critical
/// 1) Method elevates for OpenStore and EnumerateCerticates on
/// StorePermissions which is used to get the user certificates for
/// selection by the user. The certificate that is selected within
/// the certificate picker dialog is returned to the caller of this
/// method.
///
[SecurityCritical]
private static X509Certificate2 ShowCertificatePickerDialog(IntPtr parentWindow)
{
X509Certificate2 x509cert = null;
// look for appropriate certificates
X509Store store = new X509Store(StoreLocation.CurrentUser);
X509Certificate2Collection collection = null;
(new StorePermission(StorePermissionFlags.OpenStore | StorePermissionFlags.EnumerateCertificates)).Assert(); //BlessedAssert
try
{
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
collection = (X509Certificate2Collection)store.Certificates;
}
finally
{
StorePermission.RevertAssert();
}
// narrow down the choices
// timevalid
collection = collection.Find(X509FindType.FindByTimeValid, DateTime.Now, true /*validOnly*/);
// intended for signing (or no intent specified)
collection = collection.Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, false /*validOnly*/);
// remove certs that don't have private key
// work backward so we don't disturb the enumeration
for (int i = collection.Count - 1; i >= 0; i--)
{
if (!collection[i].HasPrivateKey)
{
collection.RemoveAt(i);
}
}
// any suitable certificates available?
if (collection.Count > 0)
{
collection = X509Certificate2UI.SelectFromCollection(
collection,
SR.Get(SRID.CertSelectionDialogTitle),
SR.Get(SRID.CertSelectionDialogMessage),
X509SelectionFlag.SingleSelection,
parentWindow);
if (collection.Count > 0)
{
x509cert = collection[0]; // return the first one
}
}
else
{
System.Windows.MessageBox.Show(
SR.Get(SRID.DigitalSignatureWarnErrorRMSigningMessageNoCerts),
SR.Get(SRID.DigitalSignatureWarnErrorSigningErrorTitle),
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Exclamation);
}
return x509cert;
}
///
/// Add restrictions to a signature policy based on the additional
/// restrictions imposed by a given signature
///
/// The original signature policy
/// The signature from which to add restrictions
/// The new signature policy
private static SignaturePolicy AddRestrictionsFromSignature(SignaturePolicy calcSigPolicy, DigitalSignature digSig)
{
if (digSig.IsDocumentPropertiesRestricted &&
IsAllowedByPolicy(calcSigPolicy, SignaturePolicy.ModifyDocumentProperties))
{
calcSigPolicy ^= SignaturePolicy.ModifyDocumentProperties;
}
if (digSig.IsAddingSignaturesRestricted &&
IsAllowedByPolicy(calcSigPolicy, SignaturePolicy.AllowSigning))
{
calcSigPolicy ^= SignaturePolicy.AllowSigning;
}
return calcSigPolicy;
}
///
/// Checks if an action (represented by a SignaturePolicy) is allowed
/// by the given signature policy.
///
/// The signature policy
/// The action to check
/// True if the action is allowed by the policy
private static bool IsAllowedByPolicy(SignaturePolicy policy, SignaturePolicy action)
{
return ((policy & action) == action);
}
///
/// StartCertificateStatusCheck starts thread to get Certificate status.
/// Only call once at loadtime.
///
/// The list of certificates to validate
///
/// Critical
/// 1) Sets the CertificateList passed to the certificate validation
/// thread, which is critical since it is the basis for the status
/// table.
///
[SecurityCritical]
private void StartCertificateStatusCheck(IList certificateList)
{
// First get a callback setup to call the Evaluate method using
// this thread. After the worker thread gets the certificate
// status and sets the private field it will set the dispatcher
// operation's priority to Background so the Evaluate method gets
// called when the time comes.
DispatcherOperation dispatcherOperation = Dispatcher.CurrentDispatcher.BeginInvoke(
DispatcherPriority.Inactive,
new DispatcherOperationCallback(delegate(object notused)
{
Trace.SafeWrite(
Trace.Signatures,
"Dispatcher callback. Setting document loaded flag to true.");
// Now that the certs have been verified evaluate the DigSig
// state of the document.
Evaluate();
return null;
}),
null);
CertificateValidationThreadInfo threadInfo =
new CertificateValidationThreadInfo();
threadInfo.CertificateList = certificateList;
threadInfo.Operation = dispatcherOperation;
Trace.SafeWrite(
Trace.Signatures,
"Kicking off certificate validation thread");
// Pass certificate validation work off so UI doesn't block.
// There are no concurrency issues here because the only work being
// done by the work item is the validation of a list of
// certificates. Accessing the signatures on the document could
// cause a concurrency problem. This is why we read the signatures
// and certificates in this thread before passing only the
// certificates to the worker thread.
System.Threading.ThreadPool.QueueUserWorkItem(new WaitCallback(CertificateStatusCheckWorkItem), threadInfo);
}
///
/// CertificateStatusCheckThreadProc. This is a worker thread used to call into the DigitalSignatureProvider
/// to verify the all certificates used to sign the document. This method takes an unknown amount of time
/// (default of 15 second timeout per cert). Once the work has been done then we set the waiting
/// dispatcherOperation to status background so it will call the Evaluate method.
///
///
/// Critical
/// 1) Sets SecurityCritical field _certificateStatusTable.
/// TreatAsSafe
/// 1) The status table is set from a function specifically for this
/// purpose defined on the critical for set provider. The list that
/// we pass to the function is critical, so it comes from a trusted
/// source.
///
[SecurityCritical, SecurityTreatAsSafe]
private void CertificateStatusCheckWorkItem(object stateInfo)
{
CertificateValidationThreadInfo threadInfo = (CertificateValidationThreadInfo)stateInfo;
Trace.SafeWrite(
Trace.Signatures,
"Starting certificate validation in thread.");
// XPSDocumentCertificateStatus can take an undetermined amount of
// time. If timeouts occur then each Cert could take 15 secs each
// by default and more if admin has changed defaults.
_certificateStatusTable =
DigitalSignatureProvider.GetCertificateStatus(threadInfo.CertificateList);
Trace.SafeWrite(
Trace.Signatures,
"Done with certificate validation. Starting dispatcher operation.");
// The DispatcherOperation was passed to this thread so the
// DispatcherPriority could be set to Background, and the operation
// that will run can call the Evaluate method.
threadInfo.Operation.Priority = DispatcherPriority.Background;
}
///
/// Gets the CertificateStatus for a specific x509Certificate from the
/// cached dictionary of certificates and their status.
///
///
/// Critical
/// 1) This method uses the securitycritical field _certificateStatusTable
/// to get CertificatePriorityStatus
/// TreatAsSafe
/// 1) This method only returns the status of certificates contained
/// within the Xps Document.
///
[SecurityCritical, SecurityTreatAsSafe]
private CertificatePriorityStatus GetCertificateStatusFromTable(DigitalSignature digitalSignature)
{
CertificatePriorityStatus certificatePriorityStatus = CertificatePriorityStatus.Corrupted;
if (digitalSignature == null)
{
throw new ArgumentNullException("digitalSignature");
}
// Signature requests and invalid signatures with missing certificates
// both get the certificate status NoCertificate
if (digitalSignature.SignatureState == SignatureStatus.NotSigned ||
digitalSignature.Certificate == null)
{
certificatePriorityStatus = CertificatePriorityStatus.NoCertificate;
}
// If the certificate status table is null, the certificates are
// still being verified
else if (_certificateStatusTable == null)
{
certificatePriorityStatus = CertificatePriorityStatus.Verifying;
}
else
{
Invariant.Assert(
_certificateStatusTable.ContainsKey(digitalSignature.Certificate),
"The certificate was not found in the certificate status table.");
certificatePriorityStatus = _certificateStatusTable[digitalSignature.Certificate];
}
return certificatePriorityStatus;
}
///
/// OnSignatureStatusChange.
///
///
/// This sends an event to update the UI which displays whether or not
/// a document is signed, which may be used for a trust decision by the
/// user. However, since the UI is currently displayed in an Avalon
/// control, making the events themselves critical does not add any
/// protection.
///
private void OnSignatureStatusChange(SignatureStatus newStatus)
{
SignatureStatusEventArgs args = new SignatureStatusEventArgs(
newStatus,
SignatureResourceHelper.GetDocumentLevelResources(newStatus));
RaiseSignatureStatusChange(args);
}
///
/// RaiseSignatureStatusChange.
///
private void RaiseSignatureStatusChange(SignatureStatusEventArgs args)
{
if (SignatureStatusChange != null)
{
SignatureStatusChange(this, args);
}
}
///
/// Raises the SignaturesChanged event
///
private void RaiseSignaturesChanged()
{
if (SignaturesChanged != null)
{
SignaturesChanged(this, EventArgs.Empty);
}
}
///
/// Handles the RMPolicyChanged event fired by the RMManager.
///
///
///
///
/// Critical - Updates _allowSign, which is marked SecurityCriticalDataForSet, with
/// data obtained in the event arguments.
/// TreatAsSafe - The args have to be created and passed from critical code. In
/// addition the actual RMPolicy value is protected within the args from
/// write.
///
[SecurityCritical, SecurityTreatAsSafe]
private void OnRMPolicyChanged(object sender, DocumentRightsManagementManager.RightsManagementPolicyEventArgs args)
{
if (args != null)
{
if ((args.RMPolicy & RightsManagementPolicy.AllowSign) == RightsManagementPolicy.AllowSign)
{
_allowSign.Value = true;
}
else
{
_allowSign.Value = false;
}
}
else
{
throw new ArgumentNullException("args");
}
}
///
/// VerifySignability checks the XpsDocument.IsSignable property, which
/// may take a significant amount of time to complete. Because of this
/// it will display a progress dialog to alert the user while the operation
/// is pending.
///
///
private bool VerifySignability()
{
bool result;
//Show the Progress dialog
ProgressDialog dialog =
ProgressDialog.CreateThreaded(
SR.Get(SRID.ValidationProgressTitle),
SR.Get(SRID.ValidationProgressLabel)).Form;
try
{
//Check the IsSignable property, which can take a significant portion of time...
result = IsSignable;
}
// Close the progress dialog in the event of any exception. This prevents the
// dialog from remaining open when the error page appears. We cannot use a finally
// block here because in the case of an uncaught exception the unhandled exception
// handler will get the exception (and show the error page) before the block runs.
catch
{
ProgressDialog.CloseThreaded(dialog);
throw;
}
// Close the progress dialog
ProgressDialog.CloseThreaded(dialog);
return result;
}
///
/// Uses reflection to get the protected HResult out of a CryptographicException,
/// since it's not polite enough to make it publicly accessible to begin with.
///
/// Critical:
/// 1) Asserts for Reflection permissions to access the HResult field of the
/// incoming CryptographicException which is protected instead of public.
/// TreatAsSafe:
/// 1) Only accesses and returns the HResult field, which is not critical data.
///
///
///
[SecurityCritical, SecurityTreatAsSafe]
private int GetErrorCode(CryptographicException ce)
{
int error = 0;
(new ReflectionPermission(ReflectionPermissionFlag.MemberAccess)).Assert(); //BlessedAssert
try
{
// Get the protected "HResult" field from the CryptographicException
Type t = typeof(CryptographicException);
PropertyInfo p = t.GetProperty("HResult", BindingFlags.NonPublic | BindingFlags.Instance);
error = (int)p.GetValue(ce, null);
}
finally
{
ReflectionPermission.RevertAssert();
}
return error;
}
///
/// Un-does the changes in the current changelog and clears the changelog.
/// Called when a signing or saving operation fails. This method is critical
/// because clearing the changelog at inopportune times could put us in an
/// inconsistent state.
///
/// Critical:
/// 1) Accesses and modifies critical _changeLog field
/// 2) Calls critical RemoveRequestSignature and UnsignDocument methods
/// on DigitalSignatureProvider.
///
///
[SecurityCritical]
private void UndoChanges()
{
foreach (ChangeLogEntity entry in _changeLog)
{
if (entry.IsSignatureRequest)
{
DigitalSignatureProvider.RemoveRequestSignature(entry.Id);
}
else
{
DigitalSignatureProvider.UnsignDocument(entry.Id);
}
}
_changeLog.Clear();
}
#endregion Private Methods
#region Private Properties
//-----------------------------------------------------
//
// Private Properties
//
//------------------------------------------------------
///
/// Gets whether or not all signatures on the document have had their
/// certificates validated.
///
///
/// This simply goes through all the signatures on the document and
/// ensures that they are all represented in the status table. This is
/// a safe way to check whether all signatures are verified because the
/// status table is critical.
///
///
/// Critical
/// 1) Accesses critical member variable _certificateStatusTable.
/// 2) Can be used to make security decisions.
/// TreatAsSafe
/// 1) The table is not modified.
/// 2) The decisions are made based on the critical certificate status
/// table.
///
private bool AreAllSignaturesVerified
{
[SecurityCritical, SecurityTreatAsSafe]
get
{
if (_certificateStatusTable == null)
{
return false;
}
foreach (DigitalSignature signature in DigitalSignatureProvider.Signatures)
{
if (signature.Certificate != null &&
!_certificateStatusTable.ContainsKey(signature.Certificate))
{
return false;
}
}
return true;
}
}
///
/// The IDigitalSignatureProvider associated with this instance of the
/// signature manager.
///
///
/// Critical for set
/// 1) This is a wrapper around a critical for set variable.
///
private IDigitalSignatureProvider DigitalSignatureProvider
{
get
{
return _digitalSignatureProvider.Value;
}
[SecurityCritical]
set
{
_digitalSignatureProvider.Value = value;
}
}
///
/// Whether or not the current Rights Management policy allows signing.
/// This is a convenience wrapper around critical for set data
/// _allowSign.
///
private bool IsSigningAllowed
{
get
{
return _allowSign.Value;
}
}
///
/// Returns true if (as indicated by the current signature policy) any
/// additional signatures will not invalidate existing ones.
///
private bool IsSigningAllowedByPolicy
{
get
{
return IsAllowedByPolicy(_signaturePolicy.Value, SignaturePolicy.AllowSigning);
}
}
#endregion Private Properties
#region Private Fields
//------------------------------------------------------
//
// Private Fields
//
//-----------------------------------------------------
private static DocumentSignatureManager _singleton;
///
/// The IDigitalSignatureProvider associated with this instance of the
/// digital signature manager.
///
///
/// This data is critical for set because trust decisions are made on
/// data returned from this object. For example, whether or not a
/// document is signed is determined through this.
///
private SecurityCriticalDataForSet _digitalSignatureProvider;
private IDictionary _digSigSigResources;
private SecurityCriticalDataForSet _allowSign;
private SecurityCriticalDataForSet _signaturePolicy;
///
/// The change log that is used to roll back signatures on failure.
///
///
/// We do not want to allow the list to be modified because we use the
/// log to determine which signatures and requests to remove, and
/// removing signatures or definitions is a critical operation.
///
[SecurityCritical]
private List _changeLog;
/// Dictionary that stores the status of each certificate used
/// in signatures in the document
///
/// Critical
/// 1) We are marking this critical so that we are guaranteed that all
/// callers that modify this instance are in a trusted code path.
///
[SecurityCritical]
private IDictionary _certificateStatusTable;
///
/// Constant for CryptographicException HResult corresponding to user-cancellation
/// of smart-card signing.
///
private const int SCARD_W_CANCELLED_BY_USER = -2146434962;
#endregion Private Fields
#region Nested Class
//------------------------------------------------------
//
// Nested Class
//
//-----------------------------------------------------
///
/// A struct representing data passed to the thread that validates a
/// list of certificates
///
private struct CertificateValidationThreadInfo
{
///
/// The list of certificates to validate
///
///
/// Critical
/// 1) The certificate status table is expected to be set from the
/// elements of this list.
///
[SecurityCritical]
internal IList CertificateList;
///
/// A handle to a dispatcher operation that will evaluate the
/// document's signature status after the certificates have all been
/// validated
///
internal DispatcherOperation Operation;
}
///
/// SignatureStatusEventArgs, object used when firing SigStatus change.
///
///
/// This is used to determine what the UI shows and may be the basis for
/// a trust decision by the user. However, it is not useful to make
/// this class critical because the actual UI controls are in Avalon and
/// can be modified directly.
///
public class SignatureStatusEventArgs : EventArgs
{
#region Constructors
//-----------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
///
/// The constructor
///
/// signature status
/// Resources containing other information
/// relevant to the document signature status
public SignatureStatusEventArgs(
SignatureStatus signatureStatus,
DocumentStatusResources statusResources)
{
_signatureStatus = signatureStatus;
_statusResources = statusResources;
}
#endregion Constructors
#region Public Properties
//------------------------------------------------------
//
// Public Properties
//
//-----------------------------------------------------
///
/// Property to get the SigStatus
///
public SignatureStatus SignatureStatus
{
get { return _signatureStatus; }
}
///
/// Property to get the StatusResources
///
public DocumentStatusResources StatusResources
{
get { return _statusResources; }
}
#endregion Public Properties
#region Private Fields
//------------------------------------------------------
//
// Private Fields
//
//------------------------------------------------------
private SignatureStatus _signatureStatus;
private DocumentStatusResources _statusResources;
#endregion Private Fields
}
///
/// Each instance represents the addition of either a request or a
/// signature (determined by IsSignatureRequest) along with the unique
/// id for the item (Id).
///
private struct ChangeLogEntity
{
#region Constructors
//-----------------------------------------------------------------
// Constructors
//------------------------------------------------------------------
internal ChangeLogEntity(Guid id, bool isSignatureRequest)
{
_id = id;
_isSignatureRequest = isSignatureRequest;
}
#endregion Constructors
#region Internal Properties
//-----------------------------------------------------------------
// Internal Properties
//-----------------------------------------------------------------
public Guid Id
{
get { return _id; }
}
public bool IsSignatureRequest
{
get { return _isSignatureRequest; }
}
#endregion Internal Properties
#region Private Fields
//-----------------------------------------------------------------
// Private Fields
//------------------------------------------------------------------
private Guid _id;
private bool _isSignatureRequest;
#endregion Private Fields
}
#endregion Nested Class
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Constraint.cs
- OdbcConnectionStringbuilder.cs
- CookielessHelper.cs
- PlaceHolder.cs
- MetadataElement.cs
- TreeView.cs
- SingleObjectCollection.cs
- SplashScreenNativeMethods.cs
- NotFiniteNumberException.cs
- QuadraticBezierSegment.cs
- basenumberconverter.cs
- CacheDependency.cs
- AdapterUtil.cs
- EventSourceCreationData.cs
- XPathAncestorIterator.cs
- ScriptHandlerFactory.cs
- InfoCardRSAPKCS1KeyExchangeDeformatter.cs
- COM2ComponentEditor.cs
- ToolStripDropTargetManager.cs
- Empty.cs
- FindCriteriaElement.cs
- GeometryGroup.cs
- Stream.cs
- RecordsAffectedEventArgs.cs
- RequestBringIntoViewEventArgs.cs
- TypeResolver.cs
- PeerNeighborManager.cs
- TextTreeObjectNode.cs
- ManipulationBoundaryFeedbackEventArgs.cs
- PLINQETWProvider.cs
- DefaultTextStore.cs
- TextBoxBase.cs
- RelationshipFixer.cs
- BitVector32.cs
- SqlMetaData.cs
- MulticastOption.cs
- WeakHashtable.cs
- TextStore.cs
- HtmlHistory.cs
- MTConfigUtil.cs
- sqlstateclientmanager.cs
- KeyValueConfigurationCollection.cs
- CanExecuteRoutedEventArgs.cs
- WindowsScroll.cs
- ReliabilityContractAttribute.cs
- LogEntryHeaderDeserializer.cs
- GACMembershipCondition.cs
- RoleService.cs
- TextTreeExtractElementUndoUnit.cs
- CannotUnloadAppDomainException.cs
- XmlSchemaSet.cs
- PropertyMetadata.cs
- TextBreakpoint.cs
- InternalResources.cs
- Peer.cs
- ByValueEqualityComparer.cs
- FaultDescription.cs
- HtmlTable.cs
- EmissiveMaterial.cs
- FormViewRow.cs
- DrawingContextWalker.cs
- XmlQueryType.cs
- SkewTransform.cs
- OSFeature.cs
- hwndwrapper.cs
- UnsafeNativeMethods.cs
- SerialReceived.cs
- Main.cs
- ExtensionElementCollection.cs
- GridViewItemAutomationPeer.cs
- ResXResourceSet.cs
- HyperLinkColumn.cs
- GridViewRowPresenter.cs
- PaperSize.cs
- GridViewAutomationPeer.cs
- ObjectStorage.cs
- RemoteX509Token.cs
- ExternalDataExchangeService.cs
- EntryPointNotFoundException.cs
- ProgressiveCrcCalculatingStream.cs
- QueryCacheEntry.cs
- OnOperation.cs
- GeometryDrawing.cs
- Stackframe.cs
- HttpHostedTransportConfiguration.cs
- StorageEntitySetMapping.cs
- TextRangeProviderWrapper.cs
- ToolStripAdornerWindowService.cs
- MetadataCacheItem.cs
- DelegateSerializationHolder.cs
- CodePageEncoding.cs
- ToolboxItemAttribute.cs
- ChangeDirector.cs
- JournalEntryListConverter.cs
- TreeNodeCollectionEditor.cs
- PersonalizationAdministration.cs
- DesignerToolboxInfo.cs
- CustomError.cs
- EventProviderTraceListener.cs
- ObjectPersistData.cs