Esempio n. 1
0
        internal WSManPluginShellSession(
            WSManNativeApi.WSManPluginRequest creationRequestDetails,
            WSManPluginServerTransportManager trnsprtMgr,
            ServerRemoteSession remoteSession,
            WSManPluginOperationShutdownContext shutDownContext)
            : base(creationRequestDetails, trnsprtMgr)
        {
            _remoteSession         = remoteSession;
            _remoteSession.Closed +=
                new EventHandler <RemoteSessionStateMachineEventArgs>(this.HandleServerRemoteSessionClosed);

            _activeCommandSessions = new Dictionary <IntPtr, WSManPluginCommandSession>();
            this.shellSyncObject   = new System.Object();
            this.shutDownContext   = shutDownContext;
        }
Esempio n. 2
0
        /// <summary>
        /// Callback used to register with thread pool to notify when a plugin operation shuts down.
        /// Conforms to:
        ///     public delegate void WaitOrTimerCallback( Object state, bool timedOut )
        /// </summary>
        /// <param name="operationContext">PVOID.</param>
        /// <param name="timedOut">BOOLEAN.</param>
        /// <returns></returns>
        public static void PSPluginOperationShutdownCallback(
            object operationContext,
            bool timedOut)
        {
            if (operationContext == null)
            {
                return;
            }

            WSManPluginOperationShutdownContext context = (WSManPluginOperationShutdownContext)operationContext;

            context.isShuttingDown = true;

            WSManPluginInstance.PerformCloseOperation(context);
        }
Esempio n. 3
0
        internal override void CloseOperation(
            WSManPluginOperationShutdownContext context,
            Exception reasonForClose)
        {
            // let command sessions to close.
            lock (cmdSyncObject)
            {
                if (isClosed)
                {
                    return;
                }

                if (!context.isReceiveOperation)
                {
                    isClosed = true;
                }
            }

            WSManPluginInstance.SetThreadProperties(creationRequestDetails);

            bool isRcvOp = context.isReceiveOperation;
            // only one thread will be here.
            bool isRcvOpShuttingDown = (context.isShuttingDown) &&
                                       (context.isReceiveOperation) &&
                                       (context.commandContext == creationRequestDetails.unmanagedHandle);

            bool isCmdShuttingDown = (context.isShuttingDown) &&
                                     (!context.isReceiveOperation) &&
                                     (context.commandContext == creationRequestDetails.unmanagedHandle);

            // close the pending send operation if any
            ReportSendOperationComplete();
            // close the shell's transport manager first..so we wont send data.
            transportMgr.DoClose(isRcvOpShuttingDown, reasonForClose);

            if (!isRcvOp)
            {
                // raise session closed event and let dependent code to release resources.
                // null check is not performed here because Managed C++ will take care of this.
                base.SafeInvokeSessionClosed(creationRequestDetails.unmanagedHandle, EventArgs.Empty);
                // Send Operation Complete to WSMan service
                WSManPluginInstance.ReportWSManOperationComplete(creationRequestDetails, reasonForClose);
                // let base class release its resources
                this.Close(isCmdShuttingDown);
            }
        }
Esempio n. 4
0
        internal override void CloseOperation(
            WSManPluginOperationShutdownContext context,
            Exception reasonForClose)
        {
            // let command sessions to close.
            lock (shellSyncObject)
            {
                if (isClosed)
                {
                    return;
                }

                if (!context.isReceiveOperation)
                {
                    isClosed = true;
                }
            }

            WSManPluginInstance.SetThreadProperties(creationRequestDetails);

            bool isRcvOpShuttingDown = (context.isShuttingDown) && (context.isReceiveOperation);
            bool isRcvOp             = context.isReceiveOperation;
            bool isShuttingDown      = context.isShuttingDown;

            // close the pending send operation if any
            ReportSendOperationComplete();
            // close the shell's transport manager after commands handled the operation
            transportMgr.DoClose(isRcvOpShuttingDown, reasonForClose);

            if (!isRcvOp)
            {
                // Initiate close on the active command sessions and then clear the internal
                // Command Session dictionary
                CloseAndClearCommandSessions(reasonForClose);
                // raise session closed event and let dependent code to release resources.
                // null check is not performed here because the handler will take care of this.
                base.SafeInvokeSessionClosed(creationRequestDetails.unmanagedHandle, EventArgs.Empty);
                // Send Operation Complete to WSMan service
                WSManPluginInstance.ReportWSManOperationComplete(creationRequestDetails, reasonForClose);
                // let base class release its resources
                base.Close(isShuttingDown);
            }
            // TODO: Do this.Dispose(); here?
        }
        // Closes the command and clears associated resources
        internal void CloseCommandOperation(
            WSManPluginOperationShutdownContext context)
        {
            WSManPluginCommandSession mgdCmdSession = GetCommandSession(context.commandContext);

            if (null == mgdCmdSession)
            {
                // this should never be the case. this will protect the service.
                return;
            }

            // update the internal data store only if this is not receive operation.
            if (!context.isReceiveOperation)
            {
                DeleteFromActiveCmdSessions(mgdCmdSession.creationRequestDetails.unmanagedHandle);
            }

            mgdCmdSession.CloseOperation(context, null);
        }
        internal bool EnableSessionToSendDataToClient(
            WSManNativeApi.WSManPluginRequest requestDetails,
            int flags,
            WSManNativeApi.WSManStreamIDSet_UnToMan streamSet,
            WSManPluginOperationShutdownContext ctxtToReport)
        {
            if (true == isClosed)
            {
                WSManPluginInstance.ReportWSManOperationComplete(requestDetails, lastErrorReported);
                return(false);
            }

            if ((null == streamSet) ||
                (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));
        }
 internal abstract void CloseOperation(WSManPluginOperationShutdownContext context, Exception reasonForClose);
Esempio n. 8
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();
            }
        }
Esempio n. 9
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);
        }