Ejemplo n.º 1
0
        protected WSManPluginServerSession(
            WSManNativeApi.WSManPluginRequest creationRequestDetails,
            WSManPluginServerTransportManager transportMgr)
        {
            _syncObject = new Object();
            this.creationRequestDetails = creationRequestDetails;
            this.transportMgr = transportMgr;

            transportMgr.PrepareCalled +=
                new EventHandler<EventArgs>(this.HandlePrepareFromTransportManager);
            transportMgr.WSManTransportErrorOccured +=
                new EventHandler<TransportErrorOccuredEventArgs>(this.HandleTransportError);
        }
        internal bool EnableSessionToSendDataToClient(
            WSManNativeApi.WSManPluginRequest requestDetails,
            int flags,
            WSManNativeApi.WSManStreamIDSet_UnToMan streamSet,
            WSManPluginOperationShutdownContext ctxtToReport)
        {
            if (isClosed)
            {
                WSManPluginInstance.ReportWSManOperationComplete(requestDetails, lastErrorReported);
                return(false);
            }

            if ((streamSet == null) ||
                (1 != streamSet.streamIDsCount))
            {
                // only "stdout" is the supported output stream.
                WSManPluginInstance.ReportOperationComplete(
                    requestDetails,
                    WSManPluginErrorCodes.InvalidOutputStream,
                    StringUtil.Format(
                        RemotingErrorIdStrings.WSManPluginInvalidOutputStream,
                        WSManPluginConstants.SupportedOutputStream));
                return(false);
            }

            if (!string.Equals(streamSet.streamIDs[0], WSManPluginConstants.SupportedOutputStream, StringComparison.Ordinal))
            {
                // only "stdout" is the supported output stream.
                WSManPluginInstance.ReportOperationComplete(
                    requestDetails,
                    WSManPluginErrorCodes.InvalidOutputStream,
                    StringUtil.Format(
                        RemotingErrorIdStrings.WSManPluginInvalidOutputStream,
                        WSManPluginConstants.SupportedOutputStream));
                return(false);
            }

            return(transportMgr.EnableTransportManagerSendDataToClient(requestDetails, ctxtToReport));
        }
        /// <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 (null == inboundConnectInformation)
            {
                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
            {
                System.Byte[] inputData;
                System.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 abstract void ExecuteConnect(
     WSManNativeApi.WSManPluginRequest requestDetails,            // in
     int flags,                                                   // in
     WSManNativeApi.WSManData_UnToMan inboundConnectInformation); // in optional
Ejemplo n.º 5
0
        internal void DoClose(
            bool isShuttingDown,
            Exception reasonForClose)
        {
            if (_isClosed)
            {
                return;
            }

            lock (_syncObject)
            {
                if (_isClosed)
                {
                    return;
                }

                _isClosed          = true;
                _lastErrorReported = reasonForClose;

                if (!_isRequestPending)
                {
                    // release threads blocked on the sending data to client if any
                    _waitHandle.Set();
                }
            }

            // only one thread will reach here

            // let everyone know that we are about to close
            try
            {
                RaiseClosingEvent();

                foreach (var cmdTransportKvp in _activeCmdTransportManagers)
                {
                    cmdTransportKvp.Value.Close(reasonForClose);
                }

                _activeCmdTransportManagers.Clear();

                if (_registeredShutDownWaitHandle != null)
                {
                    // This will not wait for the callback to complete.
                    _registeredShutDownWaitHandle.Unregister(null);
                    _registeredShutDownWaitHandle = null;
                }

                // Delete the context only if isShuttingDown != true. isShuttingDown will
                // be true only when the method is called from RegisterWaitForSingleObject
                // handler..in which case the context will be freed from the callback.
                if (_shutDownContext != null)
                {
                    _shutDownContext = null;
                }

                // This might happen when client did not send a receive request
                // but the server is closing
                if (_requestDetails != null)
                {
                    // Notify that no more data is being sent on this transport.
                    WSManNativeApi.WSManPluginReceiveResult(
                        _requestDetails.unmanagedHandle,
                        (int)WSManNativeApi.WSManFlagReceive.WSMAN_FLAG_RECEIVE_RESULT_NO_MORE_DATA,
                        WSManPluginConstants.SupportedOutputStream,
                        IntPtr.Zero,
                        WSManNativeApi.WSMAN_COMMAND_STATE_DONE,
                        0);

                    WSManPluginInstance.ReportWSManOperationComplete(_requestDetails, reasonForClose);
                    // We should not use request details again after reporting operation complete
                    // so releasing the resource. Remember not to free this memory as this memory
                    // is allocated and owned by WSMan.
                    _requestDetails = null;
                }
            }
            finally
            {
                // dispose resources
                _waitHandle.Dispose();
            }
        }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 7
0
 // Report Operation Complete using the send request details.
 internal void ReportSendOperationComplete()
 {
     lock (_syncObject)
     {
         if (null != sendRequestDetails)
         {
             // report and clear the send request details
             WSManPluginInstance.ReportWSManOperationComplete(sendRequestDetails, lastErrorReported);
             sendRequestDetails = null;
         }
     }
 }
Ejemplo n.º 8
0
        internal void Close(bool isShuttingDown)
        {
            if (Interlocked.Exchange(ref registeredShutdownNotification, 0) == 1)
            {
                // release the shutdown notification handle.
                if (null != registeredShutDownWaitHandle)
                {
                    registeredShutDownWaitHandle.Unregister(null);
                    registeredShutDownWaitHandle = null;
                }
            }

            // Delete the context only if isShuttingDown != true. isShuttingDown will
            // be true only when the method is called from RegisterWaitForSingleObject
            // handler..in which case the context will be freed from the callback.
            if (null != shutDownContext)
            {
                shutDownContext = null;
            }

            transportMgr.WSManTransportErrorOccured -=
                new EventHandler<TransportErrorOccuredEventArgs>(this.HandleTransportError);

            // We should not use request details again after so releasing the resource. 
            // Remember not to free this memory as this memory is allocated and owned by WSMan.
            creationRequestDetails = null;
            // if already disposing..no need to let finalizer thread
            // put resources to clean this object.
            //System.GC.SuppressFinalize(this); // TODO: This is already called in Dispose().
        }
Ejemplo n.º 9
0
        internal void SendOneItemToSession(
            WSManNativeApi.WSManPluginRequest requestDetails,
            int flags,
            string stream,
            WSManNativeApi.WSManData_UnToMan inboundData)
        {
            if ((!String.Equals(stream, WSManPluginConstants.SupportedInputStream, StringComparison.Ordinal)) &&
                (!String.Equals(stream, WSManPluginConstants.SupportedPromptResponseStream, StringComparison.Ordinal)))
            {
                WSManPluginInstance.ReportOperationComplete(
                    requestDetails,
                    WSManPluginErrorCodes.InvalidInputStream,
                    StringUtil.Format(
                        RemotingErrorIdStrings.WSManPluginInvalidInputStream,
                        WSManPluginConstants.SupportedInputStream));
                return;
            }

            if (null == inboundData)
            {
                // no data is supplied..just ignore.
                WSManPluginInstance.ReportOperationComplete(
                    requestDetails,
                    WSManPluginErrorCodes.NoError);
                return;
            }

            if ((uint)WSManNativeApi.WSManDataType.WSMAN_DATA_TYPE_BINARY != inboundData.Type)
            {
                // only binary data is supported
                WSManPluginInstance.ReportOperationComplete(
                    requestDetails,
                    WSManPluginErrorCodes.InvalidInputDatatype,
                    StringUtil.Format(
                        RemotingErrorIdStrings.WSManPluginInvalidInputStream,
                        "WSMAN_DATA_TYPE_BINARY"));
                return;
            }

            lock (_syncObject)
            {
                if (true == isClosed)
                {
                    WSManPluginInstance.ReportWSManOperationComplete(requestDetails, lastErrorReported);
                    return;
                }
                // store the send request details..because the operation complete
                // may happen from a different thread.
                sendRequestDetails = requestDetails;
            }

            SendOneItemToSessionHelper(inboundData.Data, stream);

            // report operation complete.
            ReportSendOperationComplete();
        }
Ejemplo n.º 10
0
        internal void DoClose(
            bool isShuttingDown,
            Exception reasonForClose)
        {
            if (_isClosed)
            {
                return;
            }

            lock (_syncObject)
            {
                if (_isClosed)
                {
                    return;
                }

                _isClosed = true;
                _lastErrorReported = reasonForClose;

                if (!_isRequestPending)
                {
                    // release threads blocked on the sending data to client if any
                    _waitHandle.Set();
                }
            }

            // only one thread will reach here

            // let everyone know that we are about to close
            try
            {
                RaiseClosingEvent();

                foreach (var cmdTransportKvp in _activeCmdTransportManagers)
                {
                    cmdTransportKvp.Value.Close(reasonForClose);
                }
                _activeCmdTransportManagers.Clear();

                if (null != _registeredShutDownWaitHandle)
                {
                    // This will not wait for the callback to complete.
                    _registeredShutDownWaitHandle.Unregister(null);
                    _registeredShutDownWaitHandle = null;
                }

                // Delete the context only if isShuttingDown != true. isShuttingDown will
                // be true only when the method is called from RegisterWaitForSingleObject
                // handler..in which case the context will be freed from the callback.
                if (null != _shutDownContext)
                {
                    _shutDownContext = null;
                }

                // This might happen when client did not send a receive request
                // but the server is closing
                if (null != _requestDetails)
                {
                    // Notify that no more data is being sent on this transport.
                    WSManNativeApi.WSManPluginReceiveResult(
                        _requestDetails.unmanagedHandle,
                        (int)WSManNativeApi.WSManFlagReceive.WSMAN_FLAG_RECEIVE_RESULT_NO_MORE_DATA,
                        WSManPluginConstants.SupportedOutputStream,
                        IntPtr.Zero,
                        WSManNativeApi.WSMAN_COMMAND_STATE_DONE,
                        0);

                    WSManPluginInstance.ReportWSManOperationComplete(_requestDetails, reasonForClose);
                    // We should not use request details again after reporting operation complete
                    // so releasing the resource. Remember not to free this memory as this memory
                    // is allocated and owned by WSMan.
                    _requestDetails = null;
                }
            }
            finally
            {
                // dispose resources
                _waitHandle.Dispose();
            }
        }
Ejemplo n.º 11
0
        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);
                    ClrFacade.SetSafeWaitHandle(eventWaitHandle, 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 (null == _registeredShutDownWaitHandle)
                    {
                        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;
        }