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
- DynamicPropertyHolder.cs
- GPRECTF.cs
- SerialPinChanges.cs
- ColumnMapProcessor.cs
- Multiply.cs
- PersianCalendar.cs
- HttpWebRequestElement.cs
- ISCIIEncoding.cs
- EmbeddedMailObjectsCollection.cs
- HtmlSelect.cs
- NotifyIcon.cs
- EditingCommands.cs
- AccessedThroughPropertyAttribute.cs
- CompletedAsyncResult.cs
- DispatchWrapper.cs
- AspNetHostingPermission.cs
- SmtpCommands.cs
- EventDescriptor.cs
- PersonalizationStateInfoCollection.cs
- SvcMapFile.cs
- HwndSource.cs
- StringSource.cs
- HttpCapabilitiesEvaluator.cs
- ServicesExceptionNotHandledEventArgs.cs
- HttpListenerRequest.cs
- IItemProperties.cs
- FormatterServices.cs
- CryptographicAttribute.cs
- TextShapeableCharacters.cs
- TypedReference.cs
- ImpersonationContext.cs
- Slider.cs
- ObjectListCommand.cs
- UdpTransportSettings.cs
- FunctionDescription.cs
- TemplateManager.cs
- AutomationInteropProvider.cs
- BaseParser.cs
- Int32CAMarshaler.cs
- TableStyle.cs
- SqlCaseSimplifier.cs
- XhtmlBasicPanelAdapter.cs
- DataMemberAttribute.cs
- ServiceInfo.cs
- ApplicationGesture.cs
- MD5CryptoServiceProvider.cs
- XmlTypeAttribute.cs
- Walker.cs
- RowCache.cs
- followingquery.cs
- AssociatedControlConverter.cs
- TargetControlTypeCache.cs
- ReadOnlyCollection.cs
- HttpBrowserCapabilitiesBase.cs
- IProvider.cs
- WindowsHyperlink.cs
- DesignTimeTemplateParser.cs
- EmissiveMaterial.cs
- DataObjectPastingEventArgs.cs
- HttpDebugHandler.cs
- SiteMapNodeItem.cs
- Renderer.cs
- MenuItemBindingCollection.cs
- TableLayoutStyle.cs
- SecurityTokenRequirement.cs
- SoapBinding.cs
- HttpModuleAction.cs
- PoisonMessageException.cs
- PromptStyle.cs
- EntityKeyElement.cs
- IResourceProvider.cs
- BitmapSource.cs
- HtmlTextArea.cs
- CreateUserWizardStep.cs
- RelatedPropertyManager.cs
- BufferBuilder.cs
- _CookieModule.cs
- TreeNodeCollection.cs
- OrderByQueryOptionExpression.cs
- ControlBuilderAttribute.cs
- TrackingProfile.cs
- CompoundFileDeflateTransform.cs
- PositiveTimeSpanValidatorAttribute.cs
- _ListenerResponseStream.cs
- MultilineStringConverter.cs
- RequestSecurityTokenForRemoteTokenFactory.cs
- TrustLevel.cs
- CounterCreationData.cs
- IntSecurity.cs
- ConnectionPoint.cs
- DbParameterHelper.cs
- EventWaitHandle.cs
- MatrixConverter.cs
- JapaneseLunisolarCalendar.cs
- SqlMethodCallConverter.cs
- XomlCompilerResults.cs
- EncodingDataItem.cs
- Bookmark.cs
- LogLogRecord.cs
- SequenceDesignerAccessibleObject.cs