Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / ClientRequest.cs / 1 / ClientRequest.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.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.IO; //Stream using System.Security.Principal; //WindowsIdentity using System.ComponentModel; //Win32Exception using System.Security; //SecurityException using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Runtime.InteropServices; // Marshal using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace; // // Summary: Base class to represent requests from the InfoCard client // internal abstract class ClientRequest : Request { internal delegate void AsyncEntryCallback(); // // Timeout for existing user requests to finish. // const int OutstandingCallWaitTime = 30000; // // Collection of outstanding async ops associated with this request. // IDictionary m_asyncOps; // // Collection of cached certs. // IDictionary m_cachedCerts; // // Represents the caller process that initated the client request // Process m_callerProcess; WindowsIdentity m_callerIdentity; Dictionarym_contextBag; // // Cancel callback for current service async operations. // object m_serviceAsyncSyncRoot; ServiceAsyncOperation m_serviceAsyncOperation; bool m_cancelled; bool m_untrusted; // // Summary: // Given an RpcHandle pointer returns a Process object corresponding to the calling process. // // Parameters: // RpcHandle - The RpcHandle for which a process object is desired. // // Returns: // The process object that corresponds to the calling process of the RpcHandle. // public static Process GetCallingProcessFromRpcHandle( IntPtr RpcHandle ) { uint callerPid; // Pinvoke the RPC function that gets that pid from the idl handle int err = (int) NativeMethods.I_RpcBindingInqLocalClientPID( RpcHandle, out callerPid ); if ( 0 != err ) { throw IDT.ThrowHelperError( new CommunicationException( SR.GetString( SR.ServiceErrorGettingClientPid ) ) ); } Process clientProcess = null; bool done=false; bool secondTry = false; while( !done ) { // // Assume only one pass will be necessary. // done = true; try { if( secondTry ) { // // This is the second try so we need to update the ACL on the process. // NativeMcppMethods.AddSystemAccessToProcess( RpcHandle, callerPid ); } clientProcess = ProcessMonitor.GetProcessById( (int) callerPid ); } catch( ArgumentException ) { // // The client process has gone away since the call. // throw IDT.ThrowHelperError( new UserCancelledException() ); } catch( Win32Exception e ) { bool tryAgain = false; if( NativeMethods.ERROR_ACCESS_DENIED == e.NativeErrorCode ) { if( !secondTry ) { // // The first try failed. Set up for a second try in which the Security Descriptor // on the process of interest will be modified. // done = false; secondTry = true; tryAgain = true; } } if( !tryAgain ) { throw IDT.ThrowHelperError( new SecurityException( SR.GetString( SR.ClientAPIInfocardError ), e ) ); } } } return clientProcess; } // // Summary: // Base CTOR for client requests // // Arguments: // callingProcess - The process in which the caller originated. // callingIdentity - The WindowsIdentity of the caller // rpcHandle - The handle of the native RPC request // inArgs - The stream to read input data from // outArgs - The stream to write output data to // public ClientRequest( Process callingProcess, WindowsIdentity userIdentity, IntPtr rpcHandle, Stream inArgs, Stream outArgs ) : this( callingProcess, userIdentity, rpcHandle, inArgs, outArgs, ExceptionList.AllNonFatal ) { } // // Summary: // Base CTOR for client requests // // Arguments: // callingProcess - The process in which the caller originated. // callingIdentity - The WindowsIdentity of the caller // rpcHandle - The handle of the native RPC request // inArgs - The stream to read input data from // outArgs - The stream to write output data to // recoverableExceptions - Table of exception types that should not be concidered fatal // public ClientRequest( Process callingProcess, WindowsIdentity callingIdentity, IntPtr rpcHandle, Stream inArgs, Stream outArgs, ExceptionList recoverableExceptions ) : base( rpcHandle, inArgs, outArgs, recoverableExceptions ) { IDT.ThrowInvalidArgumentConditional( null == callingProcess, "callingProcess" ); IDT.ThrowInvalidArgumentConditional( null == callingIdentity, "userIdentity" ); IDT.ThrowInvalidArgumentConditional( IntPtr.Zero == rpcHandle, "rpcHandle" ); IDT.ThrowInvalidArgumentConditional( null == inArgs, "inArgs" ); IDT.ThrowInvalidArgumentConditional( null == outArgs , "outArgs" ); m_callerProcess = callingProcess; m_callerIdentity = callingIdentity; m_contextBag = new Dictionary ( ); m_serviceAsyncSyncRoot = new object(); // // Signal the lifetime monitor that the client is incoming. This // can throw a service shutting down exception if we hit the situation where // a shutdown has just become active. // InfoCardService.LifeTimeMonitor.AddClient(); } public override WindowsIdentity RequestorIdentity { get{ return m_callerIdentity; } } public Process CallerProcess { get { return m_callerProcess; } } public uint CallerPid { get { return (uint)CallerProcess.Id; } } protected override void OnInitializeAsSystem() { if( CallerProcess.HasExited ) { throw IDT.ThrowHelperError( new UserCancelledException() ); } } /* * Unused code, but available if needed. * protected bool Cancelled { get{ return m_cancelled; } } */ public T GetContext ( ) { object value = null; if( m_contextBag.TryGetValue( typeof(T), out value ) ) { return (T)value; } return default(T); } public void SetContext ( T value ) { m_contextBag[ typeof(T) ] = value; } public void ClearContext () { m_contextBag.Remove( typeof( T ) ); } // // Summary: // This method adds an RpcAsyncResult to the list of RpcAsyncResults associated with this // InfoCard request. // // Parameters: // async - The RpcAsyncResult to be added. // public void AddAsyncOp( RpcAsyncResult async ) { lock( SyncRoot ) { if( null == m_asyncOps ) { m_asyncOps = new HybridDictionary(); } m_asyncOps[ async.Handle ] = async; } } // // Summary: // This method cancels the specifed aysnc operation by handle // // Parameters: // handle - The internal handle created for the operation // public void CancelAsyncOp( int handle ) { RpcAsyncResult rpcAsyncResult; lock ( SyncRoot ) { if ( null != m_asyncOps && m_asyncOps.Contains( handle ) ) { rpcAsyncResult = ( RpcAsyncResult ) m_asyncOps[ handle ]; rpcAsyncResult.Cancel(); } } } // // Summary: // Removes an RpcAsyncResult from the list of the RpcAsyncResults associated with this // InfoCardRequest. // // Paramters: // handle - The id of the RpcAsyncResult to remove. // public void RemoveAsyncOp( int handle ) { lock( SyncRoot ) { m_asyncOps.Remove( handle ); } } // // Summary: // Finds an RpcAsyncResult in the list of the RpcAsyncResults // associated with this Request. // // Paramters: // handle - The id of the RpcAsyncResult to remove. // private RpcAsyncResult FindAsyncOp( int handle ) { RpcAsyncResult rpcAsyncResult; lock ( SyncRoot ) { rpcAsyncResult = ( RpcAsyncResult ) m_asyncOps[ handle ]; } return rpcAsyncResult; } // // Summary: // Function for UIEndRequest to call to ascertain that // all async ops have been completed/cancelled. // protected void CheckIfAllAsyncOpsCompleted() { lock( SyncRoot ) { if( null != m_asyncOps ) { foreach( RpcAsyncResult theResult in m_asyncOps.Values ) { IDT.DebugAssert( theResult.IsCanceled || theResult.IsCompleted, "AsyncOp's endrequest must have occurred before UI End" ); } } } } // // Summary: // Given the handle to an RpcAsyncResult this method will look it up and wait until the associated // async operation has completed. // // Paramters: // handle - The handle of an RpcAsyncResult associated with this request. // // Remarks: // Running on UIAgent RPC Thread. // public RpcAsyncResult WaitForAsyncCompletion( int handle ) { RpcAsyncResult result = FindAsyncOp( handle ); if( null == result ) { throw IDT.ThrowHelperError( new CommunicationException( SR.GetString( SR.ServiceInvalidAsyncHandle ) ) ); } IAsyncResult async = ( IAsyncResult )result; // // This is where End***Request thread waits until the begin completes. // async.AsyncWaitHandle.WaitOne(); Exception e = result.Exception; if( null != e ) { throw new InfoCardRequestException( SR.GetString( SR.ServiceAsyncOpGeneratedException ), e ); } return result; } // // Even though the recipientIdentifier can be calculated from the cert directly, // we pass it in to avoid the additonal computation // public void CertCacheAdd( string recipientIdentifier, X509Certificate2 cert ) { // // lock ( SyncRoot ) { if ( null == m_cachedCerts ) { m_cachedCerts = new HybridDictionary(); } m_cachedCerts[ recipientIdentifier ] = cert; } } public X509Certificate2 CertCacheFind( string recipientId ) { lock ( SyncRoot ) { return ( X509Certificate2 ) m_cachedCerts[ recipientId ]; } } // // Summary: // Called be native RPC code to see if client is authorized to call // the client API interface. // // Remarks: // Checks to make sure that incoming clients are authenticated as // windows principals. // // Parameters: // rpcIfHandle - An rpc interface handle for the client api interface. // context - An RPC binding handle. // static public uint Authorize( IntPtr rpcIfHandle, IntPtr context ) { uint err = NativeMethods.ERROR_ACCESS_DENIED; IDT.ThrowInvalidArgumentConditional( IntPtr.Zero == rpcIfHandle, "rpcIfHandle" ); IDT.ThrowInvalidArgumentConditional( IntPtr.Zero == context, "context" ); try { using( WindowsIdentity id = Utility.GetWindowsIdentity( context ) ) { if( !id.IsAuthenticated ) { throw IDT.ThrowHelperError( new SecurityException() ); } if( !ValidateToken( context, id ) ) { throw IDT.ThrowHelperError( new CommunicationException( SR.GetString( SR.ServiceInvalidCallerToken ) ) ); } // // The client has passed all checks, let them in. // err = 0; } } catch( System.Runtime.CompilerServices.RuntimeWrappedException rwe ) { IDT.TraceAndLogException( rwe ); IDT.TraceDebug( "an exception was generated: \n{0}", rwe.ToString() ); InfoCardService.Crash(); } catch( SecurityException ) { IDT.Assert( NativeMethods.ERROR_ACCESS_DENIED == err, "Unexpected value for err!" ); } catch( InfoCardBaseException ) { throw; } // // Review: We are ok to catch all here as we are effectively transferring the error between threads. // #pragma warning suppress 56500 // do not catch null reference or seh exceptions. catch( Exception e ) { if ( IDT.IsFatal( e ) ) { InfoCardService.Crash( e ); } throw IDT.ThrowHelperError( new CommunicationException( SR.GetString( SR.ServiceUnableToValidateCallerToken, e.Message ) ) ); } // // Review: We are ok to catch all here as we are effectively transferring the error between threads. // #pragma warning suppress 56500 return err; } // // Summary: // Validates that the caller's token is in the form we require // Parameters: // rpcItfHandle - the rpc interface handle for the incoming call // rpcIdentity - the incoming rpc identity // private static bool ValidateToken( IntPtr rpcItfHandle, WindowsIdentity rpcIdentity ) { // // Retrieve the calling process identity // Process p = GetCallingProcessFromRpcHandle(rpcItfHandle); WindowsIdentity caller = NativeMcppMethods.CreateServiceExecutionIdentity( p ); // // We must have the same identity as the calling process token // bool ok = ( caller.User.Value == rpcIdentity.User.Value ); // // Calling process token must not be running under changed credentials // if( ok ) { ok = NativeMcppMethods.IsTokenValid( p ); } return ok; } // // Summary: Free any resources held by this class. // Be sure to call base.OnDisposeAsSystem before returning // so that the base class has an opportunity to do its cleanup // protected override void OnDisposeAsSystem() { m_callerProcess = null; // // Clean up any async requests that are still outstanding. // object[] asyncOps = null; lock( SyncRoot ) { if( null != m_asyncOps ) { asyncOps = new object[ m_asyncOps.Values.Count ]; m_asyncOps.Values.CopyTo( asyncOps, 0 ); } } // // Dispose of each async result outside of the lock since Disposal will cause the async result to // take the lock and remove itself from the dictionary. // if( null != asyncOps ) { foreach( RpcAsyncResult result in asyncOps ) { result.Dispose(); } } InfoCardService.LifeTimeMonitor.RemoveClient(); // // Always call base.OnDisposeAsSystem before returning // base.OnDisposeAsSystem(); } // // Summary: // Executes the specified delegate on a thread pool thread, and waits for it to complete. // If canceled, the cancel delegate is called. // protected void ExecuteCancelable( AsyncEntryCallback entry, AsyncEntryCallback cancel ) { lock( m_serviceAsyncSyncRoot ) { // // If we received a cancel message before we were able to create or between two // the async operations, we will just throw the appropriate exception. // if( m_cancelled ) { // // Throw untrusted if the user clicked "return to safe page". // if( m_untrusted ) { throw IDT.ThrowHelperError( new UntrustedRecipientException() ); } else { throw IDT.ThrowHelperError( new UserCancelledException() ); } } IDT.Assert( null == m_serviceAsyncOperation, "Only a single cancelable service operation can be running at a time" ); m_serviceAsyncOperation = new ServiceAsyncOperation( entry, cancel ); try { if( !ThreadPool.QueueUserWorkItem( IDT.ThunkCallback( new WaitCallback( ServiceAsyncEntry ) ), m_serviceAsyncOperation ) ) { throw IDT.ThrowHelperError( new CommunicationException( SR.GetString( SR.UnableToQueueThreadpool ) ) ); } m_serviceAsyncOperation.WaitForCompletion(); if( m_serviceAsyncOperation.WasCancelled ) { if( m_untrusted ) { throw IDT.ThrowHelperError( new UntrustedRecipientException() ); } else { throw IDT.ThrowHelperError( new UserCancelledException() ); } } if( null != m_serviceAsyncOperation.ExecutionException ) { throw IDT.ThrowHelperError( new CommunicationException( m_serviceAsyncOperation.ExecutionException.Message, m_serviceAsyncOperation.ExecutionException ) ); } } finally { m_serviceAsyncOperation = null; } } } // // Summary: // Cancel the current outstanding aysnc operation and any new ones. // Params // untrusted - whether we are cancelling due to a trust decision by the user. // protected void CancelServiceAsyncOperation( bool untrusted ) { if( null != m_serviceAsyncOperation ) { m_serviceAsyncOperation.Cancel(); } m_untrusted = untrusted; m_cancelled = true; } // // Summary: // ThreadPool entry point for service async operations. // static void ServiceAsyncEntry( object state ) { ServiceAsyncOperation callback = (ServiceAsyncOperation)state; try { callback.Execute(); } finally { callback.Complete(); } } // // Summary: // State info for the current service async operation // class ServiceAsyncOperation { AsyncEntryCallback m_cancelCallback; AsyncEntryCallback m_entryCallback; ManualResetEvent m_syncEvent; Exception m_exception; bool m_complete; bool m_cancelled; object m_sync; public ServiceAsyncOperation( AsyncEntryCallback entry, AsyncEntryCallback cancel ) { m_entryCallback = entry; m_cancelCallback = cancel; m_sync = new object(); m_syncEvent = new ManualResetEvent( false ); } public bool WasCancelled { get{ return m_cancelled; } } public Exception ExecutionException { get{ return m_exception; } } // // Summary: // Completes the operation // public void Complete() { if( !m_complete ) { lock( m_sync ) { if( !m_complete ) { m_complete = true; m_syncEvent.Set(); } } } } // // Summary // Waits for completion.of the operation // public void WaitForCompletion() { m_syncEvent.WaitOne(); } // // Summary: // Starts the operations, and handles the exceptions. // public void Execute() { lock( m_sync ) { // // if this object has ever been cancelled, we will immediatley // return. This can happen if a cancel is recieved between // service async calls. // if( m_cancelled ) { return; } m_complete = false; m_syncEvent.Reset(); } try { m_entryCallback(); } #pragma warning suppress 56500 // do not catch null reference or seh exceptions. catch( Exception e ) { if ( IDT.IsFatal( e ) ) { InfoCardService.Crash( e ); } else { m_exception = e; } } } // // Summary: // Cancel the async operation. // public void Cancel() { lock( m_sync ) { if( m_complete ) { return; } m_cancelled = true; try { if( null != m_cancelCallback ) { m_cancelCallback(); } } finally { Complete(); } } } } } } // 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
- IgnoreSectionHandler.cs
- DocumentPageViewAutomationPeer.cs
- LineServicesRun.cs
- compensatingcollection.cs
- XmlSchemaComplexContentRestriction.cs
- NodeLabelEditEvent.cs
- EmptyReadOnlyDictionaryInternal.cs
- AsymmetricCryptoHandle.cs
- SqlDataSourceFilteringEventArgs.cs
- SplineQuaternionKeyFrame.cs
- ADMembershipProvider.cs
- PolicyException.cs
- CodeCompiler.cs
- HttpStreamXmlDictionaryReader.cs
- Query.cs
- CommonDialog.cs
- XmlSchemaIdentityConstraint.cs
- SqlRemoveConstantOrderBy.cs
- KeyedHashAlgorithm.cs
- FontNameConverter.cs
- EncoderNLS.cs
- StoryFragments.cs
- SmiConnection.cs
- IndentTextWriter.cs
- DBAsyncResult.cs
- FrameworkContentElementAutomationPeer.cs
- ReadOnlyTernaryTree.cs
- ToolStripSystemRenderer.cs
- OleCmdHelper.cs
- RectangleConverter.cs
- SqlStream.cs
- TraceSwitch.cs
- KeyEvent.cs
- WhereQueryOperator.cs
- validationstate.cs
- SystemFonts.cs
- OracleDataAdapter.cs
- TypeUtil.cs
- HwndMouseInputProvider.cs
- ToolStripManager.cs
- PackageRelationshipSelector.cs
- PreviewKeyDownEventArgs.cs
- SerializableAttribute.cs
- HttpPostedFile.cs
- UpdatableWrapper.cs
- EditorZone.cs
- DetailsViewInsertedEventArgs.cs
- BroadcastEventHelper.cs
- XmlHierarchicalDataSourceView.cs
- ExceptionUtil.cs
- sqlnorm.cs
- CellTreeNodeVisitors.cs
- ConfigurationFileMap.cs
- Visitor.cs
- JournalEntryListConverter.cs
- AspNetRouteServiceHttpHandler.cs
- ContextCorrelationInitializer.cs
- ListViewCommandEventArgs.cs
- NeutralResourcesLanguageAttribute.cs
- EncoderFallback.cs
- ConfigXmlCDataSection.cs
- DateTimeOffset.cs
- PartialList.cs
- XPathEmptyIterator.cs
- DictionaryContent.cs
- ClearTypeHintValidation.cs
- ObservableCollection.cs
- WindowsUpDown.cs
- TextEditorContextMenu.cs
- PlainXmlSerializer.cs
- WorkflowOwnerAsyncResult.cs
- EndpointInfo.cs
- ClientTargetCollection.cs
- LightweightCodeGenerator.cs
- EndpointDiscoveryMetadata.cs
- HashRepartitionStream.cs
- AmbientLight.cs
- TypeConverterMarkupExtension.cs
- DiffuseMaterial.cs
- MailAddress.cs
- bindurihelper.cs
- Serializer.cs
- activationcontext.cs
- ResourcesGenerator.cs
- SessionStateModule.cs
- UnorderedHashRepartitionStream.cs
- ThreadStaticAttribute.cs
- ExtentKey.cs
- FormView.cs
- HMAC.cs
- OrderByBuilder.cs
- Utils.cs
- BrowserDefinitionCollection.cs
- ProfileServiceManager.cs
- XmlObjectSerializerReadContextComplex.cs
- NumberAction.cs
- SpeechEvent.cs
- BaseValidatorDesigner.cs
- FormsIdentity.cs
- MatrixAnimationUsingPath.cs