Esempio n. 1
0
        private static int _GuestModeMainWrapper(ExceptionGuard entryPointStateDisposer,
                                                 string[] args)
        {
            // We should have two things:
            //    args[ 0 ]: either "consoleOwner" or "shareConsole" (windbg versus ntsd, for instance)
            //    args[ 1 ]: command args should all should get passed in one big string.
            Util.Assert(2 == args.Length);

            bool shareConsole = false;

            if (0 == StringComparer.Ordinal.Compare(args[0], c_guestModeShareConsole))
            {
                shareConsole = true;
            }
            else
            {
                if (0 != StringComparer.Ordinal.Compare(args[0], c_guestModeConsoleOwner))
                {
                    var msg = "Unexpected arg: I expected to see \"consoleOwner\".";
                    Util.Fail(msg);
                    throw new Exception(msg);
                }
            }

            bool firstTime      = null == sm_altMainThread;
            bool alreadyRunning = DbgProvider.EntryDepth > 1;

            try
            {
                bool   noProfile;
                bool   inBreakpointCommand;
                string command = _ParseGuestModeArgs(args[1],
                                                     firstTime,
                                                     out noProfile,
                                                     out inBreakpointCommand);

                if (inBreakpointCommand && !DbgProvider.IsInBreakpointCommand)
                {
                    DbgProvider.IsInBreakpointCommand = true;
                    entryPointStateDisposer.Protect((Disposable)(() => DbgProvider.IsInBreakpointCommand = false));
                }

                if (firstTime)
                {
                    Util.Assert(!alreadyRunning);
                    ColorConsoleHost.GuestModeInjectCommand(command);

                    LogManager.Trace("_GuestModeMainWrapper: initial entry.");
                    // This is the first time we've been run, so we need to start everything
                    // up, pretty much the same as when running as a normal EXE.
                    sm_altMainThread = new Thread(_AltMainThread);

                    DbgProvider.SetGuestMode(shareConsole);

                    string[] mainArgs = null;
                    if (noProfile)
                    {
                        mainArgs = new string[] { "-NoProfile" }
                    }
                    ;

                    sm_altMainThread.Start(mainArgs);

                    // This will get signaled when things have been initialized enough to
                    // where we can start the guest mode thread activity.
                    DbgProvider.GuestModeEvent.WaitOne();
                    DbgProvider.GuestModeEvent.Reset();
                }
                else
                {
                    if (alreadyRunning)
                    {
                        // Re-entrant case: DbgShell is already running, but something called
                        // the debugger "!dbgshell" extension command (for instance, a
                        // breakpoint command).
                        LogManager.Trace("_GuestModeMainWrapper: re-entering (entryDepth: {0}).", DbgProvider.EntryDepth);
                        if (null == DbgProvider.CurrentActionQueue)
                        {
                            Util.Fail("DbgShell is already running, but I don't have a CurrentActionQueue to inject commands.");
                            throw new Exception("DbgShell is already running, but I don't have a CurrentActionQueue to inject commands.");
                        }
                        var transferTicket = entryPointStateDisposer.Transfer();
                        DbgProvider.CurrentActionQueue.PostCommand((cii) =>
                        {
                            using (transferTicket.Redeem())
                            {
                                LogManager.Trace("Executing injected (reentrant) commands:");
                                LogManager.Trace(command.Replace("\n", "\n > "));
                                cii.InvokeScript(command,
                                                 false,
                                                 PipelineResultTypes.Error |
                                                 PipelineResultTypes.Output,
                                                 sm_noInput);
                            }     // end using( new disposer )
                        });
                        transferTicket.CommitTransfer();
                    }
                    else
                    {
                        LogManager.Trace("_GuestModeMainWrapper: resuming.");
                        ColorConsoleHost.GuestModeInjectCommand(command);

                        // We already have an alternate main thread, which is "paused" (blocked),
                        // waiting to resume.

                        DbgProvider.GuestModeResume();
                    }
                }

                if (!alreadyRunning)
                {
                    LogManager.Trace("_GuestModeMainWrapper: entering GuestModeGuestThreadActivity.");
                    // The guest mode thread activity is to pump the DbgEngThread (this thread is
                    // the thread that the debugger extension was called on, and we need to use
                    // this thread to interact with dbgeng).
                    //
                    // (if alreadyRunning, then we are already running the
                    // GuestModeGuestThreadActivity (it's below us on the stack))
                    DbgProvider.GuestModeGuestThreadActivity();
                }

                LogManager.Trace("_GuestModeMainWrapper: returning {0}.",
                                 Util.FormatErrorCode(sm_exitCode));
                return(sm_exitCode);
            }
            finally
            {
                LogManager.Trace("_GuestModeMainWrapper: leaving.");
            }
        } // end _GuestModeMainWrapper()