Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / ClientUIRequest.cs / 1 / ClientUIRequest.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.ComponentModel; //Win32Exception
using System.Diagnostics;
using System.IO; //Stream
using System.Runtime.InteropServices;
using System.Security.Principal; //WindowsIdentity
using System.Threading; //ManualResetEvent
using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace;
abstract class ClientUIRequest :ClientRequest
{
class ProcessHandleDictionary :HandleDictionary { }
static object s_syncRoot = new object();
static ProcessHandleDictionary s_connectedProcesses = new ProcessHandleDictionary();
public enum RequestResult
{
Pending = 0, // Indicating that the results are still pending.
Ok = 1, // Indicating that the request was completed sucessfully
Cancel = 2, // Indicating that the request was cancelled by the user
Untrusted = 3, // Indicating that the request was cancelled by the user as the recipient was not trusted
Error = 4, // Indicating that an error occured during the request processing.
UIFailedInitialization = 5, // Indicating that an error occured during initialization of the Ui agent.
// for example during creation of the secure desktop.
UICrashed = 6, // Indicating that an unexpected error occurred in the agent causing it to crash
};
//
// Set when the uiagent is done.
//
ManualResetEvent m_uiAgentDone;
//
// This connection is made on the root incoming UI request.
// This should no be directly used, but is maintained to ensure
// that the store is not de-referenced by another call and remains loaded
// throughout the entire request.
//
StoreConnection m_rootStoreReference;
volatile InfoCardUIAgent m_uiAgent;
InfoCardUIAgent.CallMode m_uiAgentMode;
AccessibilityApplicationManager m_atManager = new AccessibilityApplicationManager();
//
// Summary:
// Base CTOR for client UI requests
//
// Arguments:
// callingProcess - The process in which the caller originated.
// callingIdentity - The WindowsIdentity of the caller
// uiAgent - The instance of the InfoCardUIAgent class that we should bind to.
// 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 ClientUIRequest( Process callingProcess, WindowsIdentity callingIdentity, InfoCardUIAgent uiAgent, IntPtr rpcHandle, Stream inArgs, Stream outArgs, InfoCardUIAgent.CallMode callMode, ExceptionList recoverableExceptions )
: base( callingProcess, callingIdentity, rpcHandle, inArgs, outArgs, recoverableExceptions )
{
m_uiAgentMode = callMode;
m_uiAgentDone = new ManualResetEvent( false );
//
// Set the request, and bind to it.
//
m_uiAgent = uiAgent;
m_uiAgent.SetRequest( this );
}
//
// Summary:
// Creates a client rpc context handle that the client can use in a later call to the RPCDispatchClientUIRequest
// RPC function.
//
// Parameters:
// rpcHandle - an incoming rpc handle.
// context - on return contains the newly created context handle.
//
// Returns:
// An HRESULT.
//
static public int BindToService( IntPtr rpcHandle, out IntPtr context )
{
int status = 0;
context = IntPtr.Zero;
try
{
Process callingProcess = GetCallingProcessFromRpcHandle( rpcHandle );
WindowsIdentity identity = NativeMcppMethods.CreateServiceExecutionIdentity( callingProcess );
WindowsImpersonationContext impersonationContext = identity.Impersonate();
try
{
int id = 0;
lock( s_syncRoot )
{
try
{
//
// Try to get a new handle under which to store the Process.
//
try
{
id = s_connectedProcesses.GetNewHandle();
}
catch( IndexOutOfRangeException e )
{
throw IDT.ThrowHelperError( new ServiceBusyException( SR.GetString( SR.TooManyClientUIConnections ), e ) );
}
//
// Store the process and set up the context to return to the client.
//
s_connectedProcesses[ id ] = callingProcess;
context = new IntPtr( id );
//
// We are now certain of success so clear these out so that they don't get cleaned up on the way
// out.
//
id = 0;
callingProcess = null;
}
finally
{
if( null != callingProcess )
{
callingProcess.Dispose();
}
if( 0 != id )
{
s_connectedProcesses.Remove( id );
}
}
}
}
finally
{
impersonationContext.Undo();
}
}
catch( InfoCardBaseException e )
{
status = e.NativeHResult;
}
return status;
}
//
// Summary:
// Retrieves a Process instance that this the process of the client that is bound to the context handle
// passed in to this method.
//
// Parameters:
// context - an Rpc context handle.
// clear - if set to true then this method will remove the entry from the HandleDictionary before returning.
//
// Returns:
// A process instance that was saved in a previous call to BindToService.
//
public static Process GetContextMapping( IntPtr context, bool clear )
{
int id = context.ToInt32();
Process callingProcess = null;
lock( s_syncRoot )
{
if( s_connectedProcesses.ContainsHandle( id ) )
{
callingProcess = s_connectedProcesses[ id ];
if( clear )
{
s_connectedProcesses.Remove( id );
}
}
}
return callingProcess;
}
//
// Summary:
// Given an rpc context handle finds the corresponding process isntance that was created in BindToService and
// Disposes it.
//
// Parameters:
// context - an rpc context handle created in a previous call to BindToService.
//
public static void RemoveAndDisposeContextMapping( IntPtr context )
{
Process p = GetContextMapping( context, true );
if( null != p )
{
p.Dispose();
}
}
//
// Summary:
// The ultimate mode we will require in order
// to complete this request.
//
public InfoCardUIAgent.CallMode UIAgentMode
{
get { return m_uiAgentMode; }
}
internal InfoCardUIAgent UIAgent
{
get
{
return m_uiAgent;
}
}
public int UIAgentPid
{
get
{
return (int)UIAgent.ProcessId;
}
}
public string UIAgentLogonSid
{
get
{
return UIAgent.TrustedUserSid;
}
}
public bool UIAgentActive
{
get { return null != UIAgent && UIAgent.IsActive; }
}
protected override void OnInitializeAsUser()
{
base.OnInitializeAsUser();
m_rootStoreReference = StoreConnection.CreateConnection();
}
//
// Summary:
// PreProcess the request.
// Handle the exceptions
//
protected override void PreProcessRequest()
{
try
{
base.PreProcessRequest();
}
catch( UIAgentInitializationException )
{
throw;
}
catch( UserCancelledException )
{
throw;
}
catch( UntrustedRecipientException )
{
throw;
}
catch( UIAgentCrashedException )
{
throw new CommunicationException( SR.GetString( SR.UIAgentCrash ) );
}
catch( InfoCardBaseException e )
{
//
// At this point we have set the UI to initialize mode,
// so it is showing the progress screen, but we have
// encountered an error during the processing of
// input arguments. We will signal to the UI that
// it should show this error, and wait for the ui to close.
// once closed, we will re-throw the same exception to allow it
// to return to the client.
//
throw ShowError( e );
}
}
//
// Summary:
// Process the request.
// Handle the exceptions
//
protected override void ProcessRequest()
{
try
{
base.ProcessRequest();
}
catch( UntrustedRecipientException )
{
throw;
}
catch( UIAgentInitializationException )
{
throw;
}
catch( UserCancelledException )
{
throw;
}
catch( UIAgentCrashedException )
{
throw new CommunicationException( SR.GetString( SR.UIAgentCrash ) );
}
catch( InfoCardBaseException e )
{
//
// At this point, we have caught an error that was not
// a direct result of a ui operation. We will display
// this error in the error dialog, then rethrow the exception
//
throw ShowError( e );
}
}
//
// Summary:
// PostProcess the request.
// Handle the exceptions
//
protected override void PostProcessRequest()
{
try
{
base.PostProcessRequest();
}
catch( InfoCardBaseException e )
{
//
// At this point, we have already selected a token or doen our
// our Ui work, and we are now attempting to marshal the return
// arguments back to the client, but an error occurred. If this happens,
// we will show the error over the shutting down progress page, and
// then rethrow the error.
//
throw ShowError( e );
}
}
//
// Summary:
// Tells the UI agent to show the information of the specified exception to the user.
//
// Returns:
// The exception that should be thrown to the client.
//
protected Exception ShowError( Exception ex )
{
//
// If the agent is in the process of shutting down, there is no UI around to
// show the error on.
//
if( m_uiAgent.IsShuttingDown )
{
return ex;
}
//
// Capture the error for the agent.
//
base.ProcessingException = ex;
//
// Reset any results we may have already recieved from the agent, as we will
// need to wait for them again.
//
m_uiAgent.ResetUIResult();
//
// Show the ui.
//
RequestResult result = m_uiAgent.ShowUI( InfoCardUIAgent.CallMode.Error );
//
// If the user deciced in some way that the recipient is untrusted
// we will discard the current processing exception, and throw
// a new exception to indicate this.
//
if( RequestResult.Untrusted == result )
{
ex = IDT.ThrowHelperError( new UntrustedRecipientException() );
}
base.ProcessingException = null;
return ex;
}
//
// Summary:
// Start a UI Agent if necessary and assign it this reqeust object.
// Wait till the UI Agent is done (i.e. Wait till user has finished interacting with the
// UI that is shown to satisfy the client UI request)
//
protected void StartAndWaitForUIAgent()
{
//
// Take a local lock so that when child requests start asking for UIAgent information we have it
// ready for them before they get a null reference exception.
//
RequestResult result = m_uiAgent.ShowUI( UIAgentMode );
switch( result )
{
case RequestResult.Ok:
{
;//Nothing to do here.
}
break;
case RequestResult.Cancel:
case RequestResult.Error:
{
//
// If the UI ever returns the ERROR state, that means that
// the UI had to terminate due to a screensaver, desktop switch,
// or some other reason in which it needs to exit the process to
// release the desktop. In this case, we return a cancel exception
// to the client. When we tear down, we will then tell the agent
// to exit gracefully.
//
throw IDT.ThrowHelperError( new UserCancelledException() );
}
case RequestResult.UICrashed:
{
//
// NB: UIAgentCrashedException does NOT derive from InfoCardBaseException.
// We'll catch this and throw CommunicationException instead in *ProcessRequest().
//
throw IDT.ThrowHelperError( new UIAgentCrashedException() );
}
case RequestResult.Untrusted:
{
throw IDT.ThrowHelperError( new UntrustedRecipientException() );
}
case RequestResult.UIFailedInitialization:
{
throw IDT.ThrowHelperError( new UIAgentInitializationException() );
}
case RequestResult.Pending:
default:
{
IDT.Assert( false, "We should never get Pending or invalid state here" );
}
break;
}
}
//
// Summary:
// Start the accessibility applications on the InfoCard desktop.
// The ATApplicationFlags parameter is used to indicate if AT Application
// support has really been enabled or if we are in this call because
// InfoCard is running on TabletPC.
//
// userATApplicationFlags - If set, AT applications are enabled.
//
public void StartAccessibilityApplications( uint userATApplicationFlags )
{
if( null != m_uiAgent )
{
IDT.DebugAssert(
false == String.IsNullOrEmpty( m_uiAgent.DesktopName ),
"Desktop name should be non-null" );
IDT.DebugAssert( 0 != CallerPid, "CallerPid should not be zero" );
string trustedUserSid = m_uiAgent.TrustedUserSid;
m_atManager.RestartOnInfoCardDesktop(
userATApplicationFlags,
m_uiAgent.TrustedUserToken,
ref trustedUserSid,
"WinSta0\\" + m_uiAgent.DesktopName,
m_uiAgent.TsSessionId,
CallerPid,
this.RequestorIdentity );
}
}
//
// Summary:
// Stop the AT apps on default desktop and start them on user desktop.
// Returns a bool value, if true agent needs to start AT apps.
//
public bool RestartAccessibilityApplications()
{
m_atManager.Stop();
return m_atManager.RestartOnUsersDesktop( CallerPid, @"WinSta0\Default", RequestorIdentity );
}
//
// Summary:
// Start the accessibility applications on the InfoCard desktop
//
public void StopAccessibilityApplications()
{
m_atManager.Stop();
}
//
// Summary:
// Signals that the user has canceled the operation before the UI results are returned.
// This allows for local async operations to be canceled.
//
public void UserCancel( bool untrusted )
{
lock( SyncRoot )
{
base.CancelServiceAsyncOperation( untrusted );
OnUserCancel();
}
}
//
// Summary:
// virtual Handler for UserCancel operatiions.
//
protected virtual void OnUserCancel()
{
}
//
// Summary:
// Releases the current UI agent.
//
void ReleaseUIAgent()
{
lock( SyncRoot )
{
//
// Any pending async requests (e.g. GetRecipientLogosAsyncRequest)
// must have been already cancelled by now.
//
CheckIfAllAsyncOpsCompleted();
StopAccessibilityApplications();
if( null != m_uiAgent )
{
m_uiAgent.ReleaseUI();
m_uiAgent.ClearRequest( this );
m_uiAgent = null;
}
}
}
protected override void OnDisposeAsUser()
{
base.OnDisposeAsUser();
if( null != m_rootStoreReference )
{
m_rootStoreReference.Close();
m_rootStoreReference = null;
}
}
//
// 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()
{
if( null != m_uiAgentDone )
{
m_uiAgentDone.Close();
m_uiAgentDone = null;
}
//
// Capture the use info for after we revert.
//
RemoveAndDisposeContextMapping( RpcHandle );
//
// The agent must be released before calling the base class as the base class disposes of the caller
// process which is needed during the SendAgentStatusRequest which may be sent while releasing the
// agent.
//
ReleaseUIAgent();
//
// Always call base.OnDispose before returning
//
base.OnDisposeAsSystem();
}
}
}
// 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
- ImplicitInputBrush.cs
- NamedPipeChannelFactory.cs
- Win32.cs
- MeasureItemEvent.cs
- EventLogPermissionEntryCollection.cs
- GridViewCommandEventArgs.cs
- SqlConnectionPoolProviderInfo.cs
- NativeMethods.cs
- Underline.cs
- XmlSiteMapProvider.cs
- MachineKeyConverter.cs
- Matrix3D.cs
- DbgUtil.cs
- UpdatePanel.cs
- URL.cs
- ClientBuildManager.cs
- HealthMonitoringSectionHelper.cs
- AccessibleObject.cs
- Matrix.cs
- SessionState.cs
- RotateTransform3D.cs
- RequestCachePolicyConverter.cs
- ControlPropertyNameConverter.cs
- ObjectListFieldCollection.cs
- DispatchWrapper.cs
- Transform3DGroup.cs
- SerializationInfo.cs
- __Error.cs
- Types.cs
- PasswordRecoveryAutoFormat.cs
- LogExtentCollection.cs
- basecomparevalidator.cs
- PassportAuthentication.cs
- FactoryMaker.cs
- TemplatedWizardStep.cs
- FormatConvertedBitmap.cs
- AttachmentCollection.cs
- RSACryptoServiceProvider.cs
- TransformGroup.cs
- LoginView.cs
- LockCookie.cs
- Helpers.cs
- OSEnvironmentHelper.cs
- AnimationLayer.cs
- ClientRoleProvider.cs
- DBCommandBuilder.cs
- EncoderReplacementFallback.cs
- SBCSCodePageEncoding.cs
- PackageDigitalSignatureManager.cs
- DbCommandTree.cs
- DrawingImage.cs
- SmiMetaDataProperty.cs
- SafeBitVector32.cs
- MD5Cng.cs
- Converter.cs
- RowToFieldTransformer.cs
- ImmutableClientRuntime.cs
- SqlParameter.cs
- LayoutDump.cs
- DocumentAutomationPeer.cs
- Native.cs
- CacheVirtualItemsEvent.cs
- SkinIDTypeConverter.cs
- CompressionTransform.cs
- HtmlTable.cs
- HtmlImage.cs
- EncoderNLS.cs
- XmlSchemas.cs
- EntityDataSourceChangedEventArgs.cs
- ContractAdapter.cs
- MachineKeySection.cs
- Underline.cs
- ScrollItemPatternIdentifiers.cs
- RefreshInfo.cs
- RegisteredDisposeScript.cs
- PropertyRecord.cs
- RelationshipEndCollection.cs
- BulletedListEventArgs.cs
- DataGridToolTip.cs
- MultiPropertyDescriptorGridEntry.cs
- ArgIterator.cs
- _WebProxyDataBuilder.cs
- HashCryptoHandle.cs
- ThumbButtonInfoCollection.cs
- CellQuery.cs
- MyContact.cs
- Stroke.cs
- DecoderExceptionFallback.cs
- PageAsyncTaskManager.cs
- SocketCache.cs
- CompareValidator.cs
- SmiSettersStream.cs
- HttpHandlerActionCollection.cs
- PixelFormat.cs
- Evidence.cs
- SafeEventLogWriteHandle.cs
- DataGrid.cs
- RoleService.cs
- InstanceOwnerQueryResult.cs
- InvalidateEvent.cs