Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / InfoCardUIAgent.cs / 1 / InfoCardUIAgent.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- // // Presharp uses the c# pragma mechanism to supress its warnings. // These are not recognised by the base compiler so we need to explictly // disable the following warnings. See http://winweb/cse/Tools/PREsharp/userguide/default.asp // for details. // #pragma warning disable 1634, 1691 // unknown message, unknown pragma namespace Microsoft.InfoCards { using System; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.Configuration; using System.Diagnostics; using System.Globalization; using System.Runtime.InteropServices; using System.Security; using System.Security.Principal; using System.Threading; using System.Runtime.CompilerServices; using System.IO; using Microsoft.Win32; using Microsoft.Win32.SafeHandles; using Microsoft.InfoCards.Diagnostics; using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace; // // Summary: // This classes manages a UIAgent process launched to interact with the user in order manage infocards // or create a token. // internal class InfoCardUIAgent { // // UInt32IndexedHybridDictionary provides a typesafe call into the // indexer by uint. HybridDictionary's indexer is an object, so // any value type passed in must be boxed. That means (uint)0 and // (int)0 don't lookup to the same value. This lead to confusing // bugs where things that you *know* are in the collection appear // not to be. This wrapper will catch this kind of bug at compile time. // private class UInt32IndexedHybridDictionary { private HybridDictionary m_realDictionary = new HybridDictionary(); public UInt32IndexedHybridDictionary() {} public int Count { get { return m_realDictionary.Count; } } public ICollection Values { get { return m_realDictionary.Values; } } public object this[uint index] { get { return m_realDictionary[index]; } set { m_realDictionary[index] = value; } } public void Remove(uint index) { m_realDictionary.Remove(index); } } // // The name of the exe to launch. // private const string UiAgentName = "icardagt.exe"; // // As per threat model mitigation, need to give exact path to agent. // public static readonly string UiAgentFullPath = Path.Combine( Environment.GetFolderPath( Environment.SpecialFolder.System ), UiAgentName ); static bool s_initialized; static bool s_isShuttingDown; static ManualResetEvent s_doneShuttingDownEvent = new ManualResetEvent( false ); // // A collection of uiagents based on TS session. // static UInt32IndexedHybridDictionary s_sessionIdCollection = new UInt32IndexedHybridDictionary(); // // A collection of uiagents based on pid. // static UInt32IndexedHybridDictionary s_pidCollection = new UInt32IndexedHybridDictionary(); // // The key under which we check for the agent sleep time ( under hklm ) // const string IdleTimeoutKey = @"software\microsoft\infocard"; const int IdleTimeoutDefault = 60 * 5; // in seconds const string IdleTimeoutValue = "sleep1"; // // The time we wait for the ui agent to respond to state changes. // readonly TimeSpan AgentStateChangeTimeOut = new TimeSpan( 0, 0, 300 ); // // How long a uiagent should be kept waiting for more work after completing work on the last request. // static TimeSpan s_idleTimeout = new TimeSpan( 0, 0, IdleTimeoutDefault ); static object s_syncRoot = new object(); ManualResetEvent m_uiStatusRecieved; //used by the ShowUI method to know when the ui agent has completed. AutoResetEvent m_agentGetWorkStart; AutoResetEvent m_agentGetWorkComplete; // When set the uiagent process should call the GetWork Method ClientUIRequest m_request; // The request the uiagent is associated with if any. int m_tsSessionId; // The TS session of this uiagent. Process m_process; // The uiagent process. EventHandler m_processExitHandler; System.Threading.Timer m_timer; string m_trustedUserSid; // Logon Sid the agent is running under SafeNativeHandle m_trustedUserToken; // User token the agent and accessibility apps will run under string m_desktopName; // Infocard secure desktop name. string m_user; // string sid of user for which this uiagent was created. CallMode m_mode; RpcUIAgentGetWorkCallback m_getWorkCallback; //Hold reference to prevent cleanup. ClientUIRequest.RequestResult m_currentStatus; //Holds the current status fo the UI. object m_memberSync; public enum CallMode { Sleep = 0, // indicating request to let the UIAgent sleep Initialize = 1, // Show initial splash screen and OOB GetToken = 2, // When a client requests for a security token Manage = 3, // Infocard Management mode Import = 4, // Started via Import API Shutdown = 5, // Indicating request to shutdown the UIAgent Crash = 6, // Indicates a crash on the service side. Error = 7, // Indicates that the agent should show the last processing exception. Release = 8, // last call before state is torn down. }; // // Summary: // Constructs a new UIAgent instance and starts the UI Agent process. // // Parameters: // callerPid - The request that this UI Agent will be replaced with. // userIdentity - The identity of the user that the agent should run as // tsSessionId - The tsSession that the process should be created for. // private InfoCardUIAgent( int callerPid, WindowsIdentity userIdentity, int tsSessionId ) { m_agentGetWorkStart = new AutoResetEvent( false ); m_agentGetWorkComplete = new AutoResetEvent( false ); m_uiStatusRecieved = new ManualResetEvent( false ); m_tsSessionId = tsSessionId; m_timer = null; IntPtr processHandle = IntPtr.Zero; IntPtr trustedUserToken = IntPtr.Zero; int processId = 0; m_mode = CallMode.Sleep; // We start our process state in sleep mode, so the initial initalize will get sent. m_currentStatus = ClientUIRequest.RequestResult.Pending; m_user = userIdentity.User.ToString(); m_memberSync = new object(); // // Verify the signature on the agent executable // int error = NativeMcppMethods.VerifyTrust( UiAgentFullPath ); if( 0 != error ) { // // Log and failfast. Most likely icardagt signing verification failed. // Microsoft.InfoCards.Diagnostics.InfoCardTrace.FailFast( SR.GetString( SR.FailedToVerifySignature, error ) ); } IntPtr jobHandle = IntPtr.Zero; // // We call this method with a null handle as we do not want this // process to be put in a job. // bool fUseElevatedToken = false; error = ( int ) NativeMcppMethods.CreateProcessAsTrustedUserWrapper( UiAgentFullPath, "", (uint)callerPid, @"WinSta0\Default", userIdentity.Name, (uint)m_tsSessionId, ref trustedUserToken, ref processHandle, ref processId, jobHandle, // null handle ref m_trustedUserSid, fUseElevatedToken ); if( 0 != error ) { // // For other errors we'll not crash the service // throw IDT.ThrowHelperError( new FailedToStartupUIException( SR.GetString( SR.CreateProcessFailed, error ), new Win32Exception( error ) ) ); } m_trustedUserToken = new SafeNativeHandle( trustedUserToken, true ); IDT.TraceDebug( "UIAGENT: Trusted User Sid:" + m_trustedUserSid ); using( SafeWaitHandle quickhandle = new SafeWaitHandle( processHandle, true ) ) { // // Get a managed process instance to hold on to and hook // in to the Exited event. // m_process = ProcessMonitor.GetProcessById( ( int ) processId ); m_processExitHandler = new EventHandler( OnProcessExit ); m_process.Exited += m_processExitHandler; // // Make sure the process didn't exit while we were setting // up the managed handler. // Utility.ThrowIfProcessExited( quickhandle ); } } public uint ProcessId { get { return (uint) m_process.Id; } } public string DesktopName { get { return m_desktopName; } } private ClientUIRequest Request { get { return m_request; } } public int TsSessionId { get { return m_tsSessionId; } } public bool IsActive { get { switch( m_mode ) { case CallMode.GetToken: case CallMode.Manage: case CallMode.Import: case CallMode.Error: return true; default: return false; } } } public bool IsShuttingDown { get { return m_mode == CallMode.Shutdown; } } public SafeNativeHandle TrustedUserToken { get { return m_trustedUserToken; } } public string TrustedUserSid { get { return m_trustedUserSid; } } public string User { get { return m_user; } } // // Summary: // See if the default idleTimeout has been overridden and set it if necessary // static private void InitializeIfNecessary() { if( s_initialized ) { return; } lock( s_syncRoot ) { if( !s_initialized ) { using( RegistryKey rk = Registry.LocalMachine.OpenSubKey( IdleTimeoutKey, false ) ) { if( null != rk ) { object sleepTime = rk.GetValue( IdleTimeoutValue, IdleTimeoutDefault ); if( sleepTime is int && (int)sleepTime > 0 ) { s_idleTimeout = new TimeSpan( 0,0,(int)sleepTime ); } } } s_initialized = true; } } } // // Summary: // Called by InfoCardRequest when it needs a UIAgent. This method checks to see whether there // are any already existing UIAgents that are just waiting to serve another request or whether it // needs to create a new one altogether, and does the appropriate thing. // // Parameters: // callerPid - The request that this UI Agent will be replaced with. // userIdentity - The identity of the user that the agent should run as // tsSessionId - The tsSession that the process should be created for. // static public InfoCardUIAgent Create( int callerPid, WindowsIdentity callerIdentity, int tsSessionId ) { InitializeIfNecessary(); InfoCardUIAgent uiagent = null; lock( s_syncRoot ) { ThrowIfShuttingDown(); uiagent = ( InfoCardUIAgent ) s_sessionIdCollection[ (uint)tsSessionId ]; if( null != uiagent ) { if( uiagent.IsShuttingDown ) { // // This one is already going away, we'll need a new one. // uiagent = null; } else if( null != uiagent.Request ) { throw IDT.ThrowHelperError( new ServiceBusyException() ); } else if( uiagent.User != callerIdentity.User.ToString() ) { // // We can't use the existing agent since it's for a different user. Shutdown the existing // agent. // uiagent.Shutdown(); uiagent = null; } else { // // Fall through. // } } if( null == uiagent ) { // // Start a new UI Agent. // uiagent = new InfoCardUIAgent( callerPid, callerIdentity, tsSessionId ); // // Add it to the static lists. // s_pidCollection[ uiagent.ProcessId ] = uiagent; s_sessionIdCollection[ (uint)tsSessionId ] = uiagent; } } return uiagent; } public RpcUIAgentGetWorkCallback Bind( string desktopName, out SecurityIdentifier userSid, out SafeWaitHandle hStartEvent, out SafeWaitHandle hCompleteEvent ) { lock( m_memberSync ) { userSid = new SecurityIdentifier( m_trustedUserSid ); hStartEvent = Utility.GetRemoteHandleFromLocalHandle( m_agentGetWorkStart.SafeWaitHandle, m_process ); hCompleteEvent = Utility.GetRemoteHandleFromLocalHandle( m_agentGetWorkComplete.SafeWaitHandle, m_process ); m_desktopName = desktopName; return ( m_getWorkCallback = new RpcUIAgentGetWorkCallback( GetWork ) ); } } // // Summary: // Resets the current status to pending, and resets the sync handle. // public void ResetUIResult() { m_currentStatus = ClientUIRequest.RequestResult.Pending; m_uiStatusRecieved.Reset(); } // // Summary: // Show the UI // public ClientUIRequest.RequestResult ShowUI( CallMode mode ) { // // if we have not yet recieved a status // In some cases we may have recieved a cancel/error durring the // the splash screen/oobe, which would set the m_currentStatus to cancel/error // if( ClientUIRequest.RequestResult.Pending == m_currentStatus ) { bool waitForChange = false; lock( m_memberSync ) { if( ClientUIRequest.RequestResult.Pending == m_currentStatus ) { // // Signal the agent to pick up the new mode. // switch( mode ) { case CallMode.GetToken: case CallMode.Manage: case CallMode.Import: case CallMode.Error: if( SetMode( mode ) ) { waitForChange = true; } break; default: IDT.ThrowInvalidArgumentConditional( true, "mode" ); break; } } } // // Always wait for change outside the lock. // if( waitForChange ) { WaitForModeChange(); } // // Wait for the agent to signal to us that the ui has send a result // m_uiStatusRecieved.WaitOne(); } return m_currentStatus; } // // Summary: // updates the UI Status info // public void SetUIStatus( ClientUIRequest.RequestResult status ) { lock( m_memberSync ) { // // update the status // m_currentStatus = status; // // Before we signal the primary thread that the results are ready, // we will tell the parent request that a cancel occured to allow it // to clean up an local long lived operations. // if( null != m_request && ( ClientUIRequest.RequestResult.Cancel == m_currentStatus || ClientUIRequest.RequestResult.Untrusted == m_currentStatus || ClientUIRequest.RequestResult.Error == m_currentStatus ) ) { m_request.UserCancel( ClientUIRequest.RequestResult.Untrusted == m_currentStatus ); } // // signal to any waiting threads that the results are ready // m_uiStatusRecieved.Set(); } } public void SetRequest( ClientUIRequest request ) { IDT.Assert( null != request, "Request should not be null" ); bool waitForChange = false; // // Take the global lock. // This method interacts with globally checked resources (m_request), // so it must use the static lock // lock( s_syncRoot ) { // // We have taken the s_syncRoot lock already. // if( null != m_timer ) { m_timer.Dispose(); m_timer = null; } m_request = request; if( SetMode( CallMode.Initialize ) ) { waitForChange = true; } // // reset the ui status event and the last status. // m_currentStatus = ClientUIRequest.RequestResult.Pending; m_uiStatusRecieved.Reset(); } // // Always wait for change outside the lock. // if( waitForChange ) { WaitForModeChange(); } } bool SetMode( CallMode mode ) { bool bChangedMode = false; lock( m_memberSync ) { if( CallMode.Shutdown != m_mode && m_mode != mode ) { switch( mode ) { case CallMode.Sleep: IDT.ThrowInvalidArgumentConditional( m_mode != CallMode.Release, "mode" ); break; case CallMode.Release: switch( m_mode ) { case CallMode.Initialize: case CallMode.GetToken: case CallMode.Manage: case CallMode.Import: case CallMode.Error: break; default: IDT.ThrowInvalidArgumentConditional( true, "mode" ); break; } break; case CallMode.Shutdown: break; case CallMode.GetToken: case CallMode.Manage: case CallMode.Import: case CallMode.Error: // // Throw if current mode isn't initialize mode. // IDT.ThrowInvalidArgumentConditional( m_mode != CallMode.Initialize, "mode" ); break; case CallMode.Initialize: // // Throw if current mode isn't sleep mode. // IDT.ThrowInvalidArgumentConditional( m_mode != CallMode.Sleep, "mode" ); break; default: IDT.ThrowInvalidArgumentConditional( true, "mode" ); break; } m_mode = mode; bChangedMode = true; } } return bChangedMode; } public void ReleaseUI() { if( IsActive || CallMode.Initialize == m_mode ) { if( SetMode( CallMode.Release ) ) { WaitForModeChange(); } } } void WaitForModeChange() { m_agentGetWorkStart.Set(); // // This is added to prevent unbounded waits. Some scenarios like intensive disk IO can cause long delays // and thus the time out has been set to 5 minutes. // Some services like Human Interface devices and utilman can hold // on to a desktop handle for the secure desktop. In such instances there is no way to switch // back from the infocard UI. // if( false == m_agentGetWorkComplete.WaitOne( AgentStateChangeTimeOut , false ) ) { Utility.KillHelper( m_process ); throw IDT.ThrowHelperError( new CommunicationException( SR.GetString( SR.UIAgentCrash ) ) ); } } // // Summary: // Called by the UI Agent process whenever the event passed in to GetByPid is signalled and right after calling // GetByPid in order to get work and connect the UI Agent directly to the relevant request object. // // Parameters: // mode - returns the mode in which the UI Agent should start in. // requestHandle - handle to client request // void GetWork( out InfoCardUIAgent.CallMode mode, out int requestHandle ) { // // Take the global lock. // This method interacts with globally checked resources (IsShuttingDown), // so it must use the static lock // lock ( m_memberSync ) { mode = CallMode.Shutdown; requestHandle = 0; try { mode = m_mode; if( null != m_request ) { requestHandle = m_request.RequestHandle; } if( mode == CallMode.Sleep ) { // // Returning a new sleep mode, start the kill timer. // m_timer = new System.Threading.Timer(IDT.ThunkCallback(new TimerCallback(OnTimeout)), null, // no state s_idleTimeout, new TimeSpan( 0, 0, 0, 0, -1 ) ); // not a periodic timer. } } #pragma warning disable 56500 // do not catch non-recoverable exceptions catch ( Exception e ) { if ( IDT.IsFatal( e ) ) { InfoCardService.Crash( e ); } IDT.TraceDebug( "An exception was generated: \n{0}", e.ToString() ); ClientUIRequest request = this.Request; if ( null != request ) { request.ProcessingException = e; } } #pragma warning restore 56500 } } // // Summary: // Disassociates this UI Agent with the request passed in. // // Parameters: // request - the request to disassociate this uiagent from // public void ClearRequest( ClientUIRequest request ) { // // Take the global lock. // This method interacts with globally checked resources (m_request), // so it must use the static lock // bool bWaitForChange = false; lock( s_syncRoot ) { if( m_request == request ) { // // Once the request is cleared, // tell the UI to go to sleep. // if( SetMode( CallMode.Sleep ) ) { bWaitForChange = true; } m_request = null; } } // // Always wait for change outside the lock. // if( bWaitForChange ) { WaitForModeChange(); // // After we set the UI Agent to sleep, if it indicated // to us (by returning and Error result) that it needs // to terminate gracefully, we send the shutdown command // to terminate the process. // if( ClientUIRequest.RequestResult.Error == m_currentStatus ) { Shutdown(); } } } // // Summary: // Fires when m_timer fires. Used to control how long a UI Agent process sleeps waiting for another // request. // // Parameters: // state - ignored // private void OnTimeout( object state ) { lock( s_syncRoot ) { if( null == m_request && !IsShuttingDown ) { Shutdown(); } } } // // Summary: // Handler for UI Agent process exit cleanup // private void OnProcessExit( int exitCode ) { lock( s_syncRoot ) { // // Set shutdown mode. // m_mode = CallMode.Shutdown; s_pidCollection.Remove( (uint)this.ProcessId ); s_sessionIdCollection.Remove( (uint)this.TsSessionId ); if( null != m_request ) { // // The only states where pending IO can still be going, or the actual // error has not already been received, we use the exit code to determine // the exit result, and modify the result accordingly. // Pending state means we have not received the result yet. // Ok state means that we were given the go-ahead to continue processing // so there may be outstanding IO we need to cancel. // if( ClientUIRequest.RequestResult.Pending == m_currentStatus || ClientUIRequest.RequestResult.Ok == m_currentStatus ) { EventCode exitEventCode = ( EventCode ) exitCode; // // NOTE: We manually set the result to error and single // the handle in this case. This prevents us from taking // the member lock that could be held by the ShowUI method during // the change mode call and dead locking. // switch( exitEventCode ) { // // Results when UI exits from cancel on the final progress page. // Example: It could be a milicious resource STS (an STS that returns HTTP100 continue messages // for ever, and never lets the soap call return)in the browser case, // and that happens after send the UIEnd result of Ok. // So the only way for us to tell the service that the user wants to cancel, is to kill the process // because thats the only thread left listening to the agent process // case EventCode.E_ICARD_USERCANCELLED: m_request.UserCancel( false ); m_currentStatus = ClientUIRequest.RequestResult.Cancel; break; // // Results when UI exits from user choosing "Exit to safe site" on last page // case EventCode.E_ICARD_UNTRUSTED: m_request.UserCancel( true ); m_currentStatus = ClientUIRequest.RequestResult.Untrusted; break; // // Results if the UI exits due to an unhandled InfoCardException // being thrown. Example: Out of memory error during // creation of the private desktop. // case EventCode.E_ICARD_UI_INITIALIZATION: m_request.UserCancel( false ); m_currentStatus = ClientUIRequest.RequestResult.UIFailedInitialization; break; // // Results if the UI exits due to an unexpected error condition // default: m_request.UserCancel( false ); m_currentStatus = ClientUIRequest.RequestResult.UICrashed; break; } m_uiStatusRecieved.Set(); } } // // Ensure that this is set, to allow any pending threads // that are currently waiting for the mode change signal // from the agent to continue. // m_agentGetWorkComplete.Set(); if( s_isShuttingDown ) { if( 0 == s_pidCollection.Count ) { // // The system is shutting down and this was the last uiagent to quite. Signal // the DoShutdown method that we are done shutting down. // s_doneShuttingDownEvent.Set(); } } if( null != m_timer ) { m_timer.Dispose(); m_timer = null; } if( null != m_trustedUserToken ) { m_trustedUserToken.Dispose(); m_trustedUserToken = null; } } } // // Summary: // Handle event that fires when the UI Agent process exits // // Args: // sender - ignored // e - ignored // private void OnProcessExit( object sender, EventArgs e ) { m_process.Exited -= m_processExitHandler; Process agentExited = sender as Process; IDT.Assert( null != agentExited, "Should be of type process." ); IDT.Assert( agentExited.ExitCode == m_process.ExitCode, "Should be the same!" ); OnProcessExit( agentExited.ExitCode ); } private static void ThrowIfShuttingDown() { if( s_isShuttingDown ) { throw IDT.ThrowHelperError( new SystemShuttingDownException() ); } } // // Summary: // Alerts the UI Agent process that it should shut down. // private void Shutdown() { if( SetMode( CallMode.Shutdown ) ) { WaitForModeChange(); } } private void Kill() { Utility.KillHelper( m_process ); } // // Summary: // Whenever a logout occurs on the system we need to see if we have an agent up, and if so // kill it. // public static void OnLogout( uint sessionId ) { if( !s_initialized ) { return; } InfoCardUIAgent agent = null; lock( s_syncRoot ) { agent = (InfoCardUIAgent)s_sessionIdCollection[ sessionId ]; if( null != agent ) { agent.Shutdown(); } } return; } public static void DoShutdown() { bool needToWait = false; if( !s_initialized ) { return; } lock( s_syncRoot ) { s_isShuttingDown = true; foreach( InfoCardUIAgent agent in s_sessionIdCollection.Values ) { needToWait = true; agent.Shutdown(); } } if( needToWait ) { bool signaled = s_doneShuttingDownEvent.WaitOne( new TimeSpan( 0, 0, 15 ), false ); if( !signaled ) { lock( s_syncRoot ) { foreach( InfoCardUIAgent agent in s_sessionIdCollection.Values ) { IDT.TraceDebug( "Have to kill the agent for some reason."); agent.Kill(); } } } } } // // Summary: // Return the InfoCardUIAgent based on pid passed in // // Args: // pid - the pid of the UI Agent object that is requested // public static InfoCardUIAgent FindByPid( uint pid ) { lock ( s_syncRoot ) { return ( InfoCardUIAgent ) s_pidCollection[ pid ]; } } } } // 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
- EmbeddedMailObjectCollectionEditor.cs
- AsyncPostBackTrigger.cs
- TextBoxBase.cs
- DbTransaction.cs
- Odbc32.cs
- MultitargetUtil.cs
- SQLBoolean.cs
- EpmSourcePathSegment.cs
- InputBuffer.cs
- RC2.cs
- cache.cs
- XsltException.cs
- ArrayExtension.cs
- COM2TypeInfoProcessor.cs
- WindowPatternIdentifiers.cs
- EventKeyword.cs
- relpropertyhelper.cs
- WebPartAuthorizationEventArgs.cs
- MsmqIntegrationAppDomainProtocolHandler.cs
- GeometryCollection.cs
- BamlVersionHeader.cs
- KoreanLunisolarCalendar.cs
- EditableTreeList.cs
- ObjectResult.cs
- ExceptionAggregator.cs
- DataAdapter.cs
- SwitchElementsCollection.cs
- TextBlockAutomationPeer.cs
- AlgoModule.cs
- ContractMapping.cs
- BooleanConverter.cs
- FileInfo.cs
- AccessViolationException.cs
- DefaultSettingsSection.cs
- Interop.cs
- InputScopeManager.cs
- AnonymousIdentificationSection.cs
- CryptoApi.cs
- TextureBrush.cs
- SignedXml.cs
- PEFileEvidenceFactory.cs
- GradientSpreadMethodValidation.cs
- RolePrincipal.cs
- Token.cs
- Parser.cs
- HtmlElementErrorEventArgs.cs
- PropertyDescriptorCollection.cs
- LambdaCompiler.Generated.cs
- IncomingWebRequestContext.cs
- FormsIdentity.cs
- SecurityStateEncoder.cs
- WebPartConnectionCollection.cs
- WebPartTransformerCollection.cs
- WebBrowserEvent.cs
- ContainerSelectorGlyph.cs
- VisualTreeHelper.cs
- VectorAnimationUsingKeyFrames.cs
- TextWriter.cs
- CmsInterop.cs
- TextDocumentView.cs
- DataTableCollection.cs
- UpDownBase.cs
- Object.cs
- DataSourceXmlClassAttribute.cs
- XmlSerializerSection.cs
- Schedule.cs
- InitializerFacet.cs
- Image.cs
- PageBreakRecord.cs
- DynamicScriptObject.cs
- CFGGrammar.cs
- Decimal.cs
- SuppressMergeCheckAttribute.cs
- Menu.cs
- DataGridViewTextBoxCell.cs
- ExtensibleClassFactory.cs
- SchemaImporterExtensionsSection.cs
- FormatterServices.cs
- AdapterDictionary.cs
- BitmapPalette.cs
- CustomError.cs
- AudioFormatConverter.cs
- UIElementParagraph.cs
- ExecutedRoutedEventArgs.cs
- Brush.cs
- TableAdapterManagerNameHandler.cs
- SamlConstants.cs
- TemplatePropertyEntry.cs
- EntityTypeEmitter.cs
- SerTrace.cs
- GridItemPattern.cs
- ApplicationProxyInternal.cs
- ProcessThreadCollection.cs
- FlowDecisionDesigner.xaml.cs
- VirtualPathProvider.cs
- ZipIOCentralDirectoryFileHeader.cs
- CommandEventArgs.cs
- WebGetAttribute.cs
- QilXmlReader.cs
- FieldBuilder.cs