/// <summary> /// Main Routine for Connect on a Shell. /// Calls in server remotesessions ExecuteConnect to run the Connect algorithm /// This call is synchronous. i.e WSManOperationComplete will be called before the routine completes. /// </summary> /// <param name="requestDetails"></param> /// <param name="flags"></param> /// <param name="inboundConnectInformation"></param> internal override void ExecuteConnect( WSManNativeApi.WSManPluginRequest requestDetails, // in int flags, // in WSManNativeApi.WSManData_UnToMan inboundConnectInformation) // in optional { if (inboundConnectInformation == null) { WSManPluginInstance.ReportOperationComplete( requestDetails, WSManPluginErrorCodes.NullInvalidInput, StringUtil.Format( RemotingErrorIdStrings.WSManPluginNullInvalidInput, "inboundConnectInformation", "WSManPluginShellConnect")); return; } // not registering shutdown event as this is a synchronous operation. IntPtr responseXml = IntPtr.Zero; try { byte[] inputData; byte[] outputData; // Retrieve the string (Base64 encoded) inputData = ServerOperationHelpers.ExtractEncodedXmlElement( inboundConnectInformation.Text, WSManNativeApi.PS_CONNECT_XML_TAG); // this will raise exceptions on failure try { _remoteSession.ExecuteConnect(inputData, out outputData); // construct Xml to send back string responseData = string.Format(System.Globalization.CultureInfo.InvariantCulture, "<{0} xmlns=\"{1}\">{2}</{0}>", WSManNativeApi.PS_CONNECTRESPONSE_XML_TAG, WSManNativeApi.PS_XML_NAMESPACE, Convert.ToBase64String(outputData)); // TODO: currently using OperationComplete to report back the responseXml. This will need to change to use WSManReportObject // that is currently internal. WSManPluginInstance.ReportOperationComplete(requestDetails, WSManPluginErrorCodes.NoError, responseData); } catch (PSRemotingDataStructureException ex) { WSManPluginInstance.ReportOperationComplete(requestDetails, WSManPluginErrorCodes.PluginConnectOperationFailed, ex.Message); } } catch (OutOfMemoryException) { WSManPluginInstance.ReportOperationComplete(requestDetails, WSManPluginErrorCodes.OutOfMemory); } finally { if (responseXml != IntPtr.Zero) { Marshal.FreeHGlobal(responseXml); } } return; }
internal bool EnableTransportManagerSendDataToClient( WSManNativeApi.WSManPluginRequest requestDetails, WSManPluginOperationShutdownContext ctxtToReport) { _shutDownContext = ctxtToReport; bool isRegisterWaitForSingleObjectSucceeded = true; lock (_syncObject) { if (_isRequestPending) { // if a request is already pending..ignore this. WSManPluginInstance.ReportWSManOperationComplete( requestDetails, WSManPluginErrorCodes.NoError); return(false); } if (_isClosed) { WSManPluginInstance.ReportWSManOperationComplete(requestDetails, _lastErrorReported); return(false); } _isRequestPending = true; _requestDetails = requestDetails; if (Platform.IsWindows) { // Wrap the provided handle so it can be passed to the registration function SafeWaitHandle safeWaitHandle = new SafeWaitHandle(requestDetails.shutdownNotificationHandle, false); // Owned by WinRM EventWaitHandle eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset); eventWaitHandle.SafeWaitHandle = safeWaitHandle; _registeredShutDownWaitHandle = ThreadPool.RegisterWaitForSingleObject( eventWaitHandle, new WaitOrTimerCallback(WSManPluginManagedEntryWrapper.PSPluginOperationShutdownCallback), _shutDownContext, -1, // INFINITE true); // TODO: Do I need to worry not being able to set missing WT_TRANSFER_IMPERSONATION? if (_registeredShutDownWaitHandle == null) { isRegisterWaitForSingleObjectSucceeded = false; } } // release thread waiting to send data to the client. _waitHandle.Set(); } if (!isRegisterWaitForSingleObjectSucceeded) { WSManPluginInstance.PerformCloseOperation(ctxtToReport); WSManPluginInstance.ReportOperationComplete( requestDetails, WSManPluginErrorCodes.ShutdownRegistrationFailed, StringUtil.Format( RemotingErrorIdStrings.WSManPluginShutdownRegistrationFailed)); return(false); } return(true); }