Пример #1
0
        /// <summary>
        /// Attempts to get descriptors of the outpoints of the specified class and subclass.
        /// </summary>
        /// <param name="CallerProcess">The process which owns the memory containing the <paramref cref="request"/>.</param>
        /// <param name="Class">The class of outpoint to search for.</param>
        /// <param name="Subclass">The subclass of outpoint to search for.</param>
        /// <param name="request">A pointer to the request structure (Also used to store the result(s)).</param>
        /// <returns>True if the request was successful. Otherwise, false.</returns>
        public static bool GetPipeOutpoints(Process CallerProcess, PipeClasses Class, PipeSubclasses Subclass, PipeOutpointsRequest *request)
        {
            // Validate inputs & get caller process
            if (CallerProcess == null)
            {
                return(false);
            }

            // Merge memory layouts
            //  so we can access the request structure
            MemoryLayout OriginalMemoryLayout = SystemCallsHelpers.EnableAccessToMemoryOfProcess(CallerProcess);
            bool         OK = true;

            // More validate inputs
            //  - Check request exists (should've been pre-allocated by caller)
            //  - Check request->Outpoints exists (should've been pre-allocated by caller)
            //  - Check request->MaxDescriptors was set correctly
            if (request == null)
            {
                // Should have been pre-allocated by the calling thread (/process)
                OK = false;
            }
            else if (request->Outpoints == null)
            {
                // Should have been pre-allocated by the calling thread (/process)
                OK = false;
            }
            else if (request->MaxDescriptors == 0)
            {
                // Not technically an error but let's not waste time processing 0 descriptors
                OK = true;
            }

            if (OK)
            {
                // Search for all outpoints of correct class and subclass
                int maxDescriptors = request->MaxDescriptors;
                for (int i = 0, j = 0; i < PipeOutpoints.Count && j < maxDescriptors; i++)
                {
                    PipeOutpoint anOutpoint = (PipeOutpoint)PipeOutpoints[i];

                    if (anOutpoint.Class == Class &&
                        anOutpoint.Subclass == Subclass &&
                        (anOutpoint.MaxConnections == PipeConstants.UnlimitedConnections ||
                         anOutpoint.NumConnections < anOutpoint.MaxConnections))
                    {
                        // Set the resultant values
                        request->Outpoints[j++].ProcessId = anOutpoint.ProcessId;
                    }
                }
            }

            SystemCallsHelpers.DisableAccessToMemoryOfProcess(OriginalMemoryLayout);

            return(OK);
        }
Пример #2
0
        public static unsafe SystemCallResults HandleDeferredSystemCall(
            Process CallerProcess, Thread CallerThread,
            SystemCallNumbers syscallNumber, uint Param1, uint Param2, uint Param3,
            ref uint Return2, ref uint Return3, ref uint Return4)
        {
            SystemCallResults result = SystemCallResults.Unhandled;

            switch (syscallNumber)
            {
            case SystemCallNumbers.StartThread:
                //BasicConsole.WriteLine("DSC: Start Thread");
                Return2 = CallerProcess.CreateThread((ThreadStartMethod)Utilities.ObjectUtilities.GetObject((void *)Param1), "[From sys call]").Id;
                //BasicConsole.WriteLine("DSC: Start Thread - done.");
                result = SystemCallResults.OK;
                break;

            case SystemCallNumbers.RegisterPipeOutpoint:
            {
                //BasicConsole.WriteLine("DSC: Register Pipe Outpoint");
                Pipes.PipeOutpoint outpoint;
                bool registered = Pipes.PipeManager.RegisterPipeOutpoint(CallerProcess.Id, (Pipes.PipeClasses)Param1, (Pipes.PipeSubclasses)Param2, (int)Param3, out outpoint);
                if (registered)
                {
                    result = SystemCallResults.OK;
                }
                else
                {
                    result = SystemCallResults.Fail;
                }
                //BasicConsole.WriteLine("DSC: Register Pipe Outpoint - done.");
            }
            break;

            case SystemCallNumbers.GetNumPipeOutpoints:
            {
                //BasicConsole.WriteLine("DSC: Get Num Pipe Outpoints");
                int  numOutpoints;
                bool obtained = Pipes.PipeManager.GetNumPipeOutpoints((Pipes.PipeClasses)Param1, (Pipes.PipeSubclasses)Param2, out numOutpoints);
                if (obtained)
                {
                    result  = SystemCallResults.OK;
                    Return2 = (uint)numOutpoints;
                }
                else
                {
                    result = SystemCallResults.Fail;
                }
                //BasicConsole.WriteLine("DSC: Get Num Pipe Outpoints - done");
            }
            break;

            case SystemCallNumbers.GetPipeOutpoints:
            {
                //BasicConsole.WriteLine("DSC: Get Pipe Outpoints");

                bool obtained = Pipes.PipeManager.GetPipeOutpoints(CallerProcess, (Pipes.PipeClasses)Param1, (Pipes.PipeSubclasses)Param2, (Pipes.PipeOutpointsRequest *)Param3);
                if (obtained)
                {
                    result = SystemCallResults.OK;
                }
                else
                {
                    result = SystemCallResults.Fail;
                }

                //BasicConsole.WriteLine("DSC: Get Pipe Outpoints - done");
            }
            break;

            case SystemCallNumbers.CreatePipe:
            {
                //BasicConsole.WriteLine("DSC: Create Pipe");

                bool created = Pipes.PipeManager.CreatePipe(CallerProcess.Id, Param1, (Pipes.CreatePipeRequest *)Param2);
                if (created)
                {
                    result = SystemCallResults.OK;
                }
                else
                {
                    result = SystemCallResults.Fail;
                }

                //BasicConsole.WriteLine("DSC: Create Pipe - done");
            }
            break;

            case SystemCallNumbers.WaitOnPipeCreate:
            {
                //BasicConsole.WriteLine("DSC: Wait On Pipe Create");

                bool waiting = Pipes.PipeManager.WaitOnPipeCreate(CallerProcess.Id, CallerThread.Id, (Pipes.PipeClasses)Param1, (Pipes.PipeSubclasses)Param2);
                if (waiting)
                {
                    result = SystemCallResults.Deferred;
                }
                else
                {
                    result = SystemCallResults.Fail;
                }

                //BasicConsole.WriteLine("DSC: Wait On Pipe Create - done");
            }
            break;

            case SystemCallNumbers.ReadPipe:
            {
                //BasicConsole.WriteLine("DSC: Read Pipe");

                // Need access to calling process' memory to be able to set values in request structure(s)
                MemoryLayout OriginalMemoryLayout = SystemCallsHelpers.EnableAccessToMemoryOfProcess(CallerProcess);

                Pipes.ReadPipeRequest *     RequestPtr = (Pipes.ReadPipeRequest *)Param1;
                Pipes.PipeManager.RWResults RWResult   = Pipes.PipeManager.ReadPipe(RequestPtr->PipeId, RequestPtr->Blocking, CallerProcess, CallerThread);

                if (RWResult == Pipes.PipeManager.RWResults.Error)
                {
                    result = SystemCallResults.Fail;
                }
                else
                {
                    // Returning Deferred state from here will leave the caller thread
                    //  in whatever state ReadPipe decided it should be in.
                    result = SystemCallResults.Deferred;
                }

                SystemCallsHelpers.DisableAccessToMemoryOfProcess(OriginalMemoryLayout);

                //BasicConsole.WriteLine("DSC: Read Pipe - done");
            }
            break;

            case SystemCallNumbers.WritePipe:
            {
                //BasicConsole.WriteLine("DSC: Write Pipe");

                // Need access to calling process' memory to be able to set values in request structure(s)
                MemoryLayout OriginalMemoryLayout = SystemCallsHelpers.EnableAccessToMemoryOfProcess(CallerProcess);

                Pipes.WritePipeRequest *    RequestPtr = (Pipes.WritePipeRequest *)Param1;
                Pipes.PipeManager.RWResults RWResult   = Pipes.PipeManager.WritePipe(RequestPtr->PipeId, RequestPtr->Blocking, CallerProcess, CallerThread);

                if (RWResult == Pipes.PipeManager.RWResults.Error)
                {
                    result = SystemCallResults.Fail;
                }
                else
                {
                    // Returning Deferred state from here will leave the caller thread
                    //  in whatever state WritePipe decided it should be in.
                    result = SystemCallResults.Deferred;
                }

                SystemCallsHelpers.DisableAccessToMemoryOfProcess(OriginalMemoryLayout);

                //BasicConsole.WriteLine("DSC: Write Pipe - done");
            }
            break;

            default:
                BasicConsole.WriteLine("DSC: Unrecognised call number.");
                BasicConsole.WriteLine((uint)syscallNumber);
                break;
            }

            return(result);
        }
Пример #3
0
        /// <summary>
        /// Attempts to write to the specified pipe.
        /// </summary>
        /// <remarks>
        /// Note that this function is non-blocking. It will, however, block a system caller thread by simply not returning it from
        /// the deferred system call.
        /// </remarks>
        /// <param name="PipeId">The Id of the pipe to write.</param>
        /// <param name="Blocking">Whether the write should be blocking or non-blocking.</param>
        /// <param name="CallerProcess">The process which made the call.</param>
        /// <param name="CallerThread">The thread which made the call.</param>
        /// <returns>See descriptions on <see cref="PipeManager.RWResults"/> values.</returns>
        public static RWResults WritePipe(int PipeId, bool Blocking, Process CallerProcess, Thread CallerThread)
        {
#if PIPES_TRACE
            BasicConsole.WriteLine("WritePipe: Validating inputs");
#endif
            // Validate inputs
            //  - Check pipe exists
            Pipe pipe = GetPipe(PipeId);
            if (pipe == null)
            {
                return(RWResults.Error);
            }

#if PIPES_TRACE
            BasicConsole.WriteLine("WritePipe: Checking caller allowed to write");
#endif
            // Check the caller is allowed to access the pipe
            if (!AllowedToWritePipe(pipe, CallerProcess.Id))
            {
                return(RWResults.Error);
            }

#if PIPES_TRACE
            BasicConsole.WriteLine("WritePipe: Getting out process");
#endif
            // Get outpoint process
            Process OutProcess = ProcessManager.GetProcessById(pipe.Outpoint.ProcessId);
            if (OutProcess == null)
            {
                return(RWResults.Error);
            }

#if PIPES_TRACE
            BasicConsole.WriteLine("WritePipe: Getting in process");
#endif
            // Get inpoint process
            Process InProcess = ProcessManager.GetProcessById(pipe.Inpoint.ProcessId);
            if (InProcess == null)
            {
                return(RWResults.Error);
            }

#if PIPES_TRACE
            BasicConsole.WriteLine("WritePipe: Merging memory layouts");
#endif
            // Merge memory layouts of in process (out process should already have been done by caller)
            //  so we can access the request structure(s) and buffers
            MemoryLayout OriginalMemoryLayout = SystemCallsHelpers.EnableAccessToMemoryOfProcess(InProcess);

#if PIPES_TRACE
            BasicConsole.WriteLine("WritePipe: Adding caller to write queue");
#endif
            // Add caller thread to the write queue
            WritePipeRequest *Request = (WritePipeRequest *)CallerThread.Param1;
            pipe.QueueToWrite(CallerThread.Id, Request->Length);

            // Set up initial failure return value
            CallerThread.Return1 = (uint)SystemCallResults.Fail;

#if PIPES_TRACE
            BasicConsole.WriteLine("WritePipe: Processing pipe queue");
#endif
            // Process the pipe queue
            ProcessPipeQueue(pipe, OutProcess, InProcess);

#if PIPES_TRACE
            BasicConsole.WriteLine("WritePipe: Unmerging memory layouts");
#endif
            // Unmerge memory layouts
            SystemCallsHelpers.DisableAccessToMemoryOfProcess(OriginalMemoryLayout);

            bool Completed = !pipe.AreThreadsWaitingToWrite();
            if (!Blocking)
            {
                if (!Completed)
                {
                    uint temp;
                    bool removed = pipe.RemoveLastToWrite(out temp);

                    if (!removed || temp != CallerThread.Id)
                    {
                        BasicConsole.WriteLine("PipeManager: Error! Async write failed and then removing last from queue resulted in thread Id mismatch!");
                    }

                    CallerThread.Return1 = (uint)SystemCallResults.Fail;
                    CallerThread._Wake();
                }
            }
            return(Completed ? RWResults.Complete : RWResults.Queued);
        }
Пример #4
0
        /// <summary>
        /// Attempts to create a new pipe.
        /// </summary>
        /// <param name="InProcessId">The Id of the target process which owns the inpoint.</param>
        /// <param name="OutProcessId">The Id of the target process which owns the outpoint.</param>
        /// <param name="request">A pointer to the request structure (Also used to store the result).</param>
        /// <returns>True if the request was successful. Otherwise, false.</returns>
        public static bool CreatePipe(uint InProcessId, uint OutProcessId, CreatePipeRequest *request)
        {
            // Validate inputs
            //  - Check out process exists
            //  - Check in process exists
            //  - Check request isn't null (should've been pre-allocated)
            Process InProcess = ProcessManager.GetProcessById(InProcessId);

            if (InProcess == null)
            {
                return(false);
            }
            else if (ProcessManager.GetProcessById(OutProcessId) == null)
            {
                return(false);
            }
            else if (request == null)
            {
                return(false);
            }

            // Merge memory layouts
            //  so we can access the request structure
            MemoryLayout OriginalMemoryLayout = SystemCallsHelpers.EnableAccessToMemoryOfProcess(InProcess);
            bool         OK = true;

            // Find the outpoint
            PipeOutpoint outpoint = GetOutpoint(OutProcessId, request->Class, request->Subclass);

            // Check that we actually found the outpoint
            if (outpoint == null)
            {
                OK = false;
            }

            if (OK)
            {
                // Check there are sufficient connections available
                if (outpoint.NumConnections >= outpoint.MaxConnections &&
                    outpoint.MaxConnections != PipeConstants.UnlimitedConnections)
                {
                    OK = false;
                }

                if (OK)
                {
                    // Create new inpoint
                    PipeInpoint inpoint = new PipeInpoint(InProcessId, request->Class, request->Subclass);

                    // Create new pipe
                    Pipe pipe = new Pipe(PipeIdGenerator++, outpoint, inpoint, request->BufferSize);
                    // Add new pipe to list of pipes
                    Pipes.Add(pipe);
                    // Increment number of connections to the outpoint
                    outpoint.NumConnections++;

                    // Set result information
                    request->Result.Id = pipe.Id;

                    // Wake any threads (/processes) which were waiting on a pipe to be created
                    WakeWaitingThreads(outpoint, pipe.Id);
                }
            }

            SystemCallsHelpers.DisableAccessToMemoryOfProcess(OriginalMemoryLayout);

            return(OK);
        }
Пример #5
0
        public static void Main()
        {
            // The serial ports should have already been initialised
            MsgPort   = Serial.COM2;
            NotifPort = Serial.COM3;

            // This looks silly, but the host debugger is actually waiting for this
            //  to determine the OS has connected and is ready
            MsgPort.Write("Debug thread :D\n");

            //MsgPort.Write("Enabling...\n");
            // Everything is initialised and connected, so enable the debugger
            Enabled = true;
            //MsgPort.Write("Enabled.\n");

            // Note: It doesn't actually matter if the host hasn't connected
            //  because the debugger has near-zero effective cost to the rest of the system
            //  unless it is sent a command (unlike the old debugger, which slowed everything
            //  down to the point of being unusable).

            while (!Terminating)
            {
                // Read in a line from the host
                FOS_System.String line = "";
                char c = (char)MsgPort.Read();
                while (c != '\n' && c != '\r')
                {
                    line += c;
                    c     = (char)MsgPort.Read();
                }

                // Echo the command back to the host for verification
                MsgPort.Write("START OF COMMAND\n");
                MsgPort.Write(line);
                MsgPort.Write("\n");

                // Filter the line
                line = line.Trim().ToLower();

                // Split it up into relevant parts
                List lineParts = line.Split(' ');
                if (lineParts.Count > 0)
                {
                    FOS_System.String cmd = (FOS_System.String)lineParts[0];

                    if (cmd == "ping")
                    {
                        MsgPort.Write("pong\n");
                    }
                    else if (cmd == "help")
                    {
                        #region Help

                        MsgPort.Write("Available commands:\n");
                        MsgPort.Write(" - ping\n");
                        MsgPort.Write(" - threads\n");
                        MsgPort.Write(" - suspend (processId) (threadId | -1 for all threads)\n");
                        MsgPort.Write(" - resume (processId) (threadId | -1 for all threads)\n");
                        MsgPort.Write(" - step (processId) (threadId | -1 for all threads)\n");
                        MsgPort.Write(" - ss (processId) (threadId | -1 for all threads)\n");
                        MsgPort.Write(" - sta (processId) (threadId | -1 for all threads) (address)\n");
                        MsgPort.Write(" - bps (address:hex)\n");
                        MsgPort.Write(" - bpc (address:hex)\n");
                        MsgPort.Write(" - regs (processId) (threadId)\n");
                        MsgPort.Write(" - memory (processId) (address:hex) (length) (units:1,2,4)\n");

                        #endregion
                    }
                    else if (cmd == "threads")
                    {
                        #region Threads

                        for (int i = 0; i < ProcessManager.Processes.Count; i++)
                        {
                            Process AProcess = (Process)ProcessManager.Processes[i];
                            MsgPort.Write(" - Process : ");
                            MsgPort.Write((FOS_System.String)AProcess.Id);
                            MsgPort.Write(" : ");
                            MsgPort.Write(AProcess.Name);
                            MsgPort.Write("\n");
                            for (int j = 0; j < AProcess.Threads.Count; j++)
                            {
                                Thread AThread = (Thread)AProcess.Threads[j];

                                MsgPort.Write("      - Thread : ");
                                MsgPort.Write((FOS_System.String)AThread.Id);
                                MsgPort.Write(" : ");
                                if (AThread.Debug_Suspend)
                                {
                                    MsgPort.Write("Suspended");
                                }
                                else if (AThread.TimeToSleep == -1)
                                {
                                    MsgPort.Write("Waiting  ");
                                }
                                else if (AThread.TimeToSleep > 0)
                                {
                                    MsgPort.Write("Sleeping ");
                                }
                                else
                                {
                                    MsgPort.Write("Running  ");
                                }
                                MsgPort.Write(" : ");
                                MsgPort.Write(AThread.Name);
                                MsgPort.Write("\n");
                            }
                        }

                        #endregion
                    }
                    else if (cmd == "suspend")
                    {
                        #region Suspend

                        if (lineParts.Count == 3)
                        {
                            uint ProcessId = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[1], 0);
                            int  ThreadId  = FOS_System.Int32.Parse_DecimalSigned((FOS_System.String)lineParts[2]);

                            Process TheProcess = ProcessManager.GetProcessById(ProcessId);

                            if (TheProcess != null)
                            {
                                if (ThreadId == -1)
                                {
                                    for (int i = 0; i < TheProcess.Threads.Count; i++)
                                    {
                                        Thread AThread = ((Thread)TheProcess.Threads[i]);

                                        if (AThread != MainThread)
                                        {
                                            UInt64 ProcessThreadId = (((UInt64)ProcessId) << 32) | AThread.Id;
                                            if (ThreadsToSuspend.IndexOf(ProcessThreadId) == -1)
                                            {
                                                ThreadsToSuspend.Add(ProcessThreadId);
                                            }

                                            AThread.Debug_Suspend = true;

                                            MsgPort.Write(" > Suspended ");
                                            MsgPort.Write(AThread.Name);
                                            MsgPort.Write(" thread\n");
                                        }
                                    }
                                }
                                else
                                {
                                    UInt64 ProcessThreadId = (((UInt64)ProcessId) << 32) | (uint)ThreadId;
                                    if (ThreadsToSuspend.IndexOf(ProcessThreadId) == -1)
                                    {
                                        ThreadsToSuspend.Add(ProcessThreadId);
                                    }

                                    Thread TheThread = ProcessManager.GetThreadById((uint)ThreadId, TheProcess);

                                    if (TheThread != null)
                                    {
                                        if (TheThread != MainThread)
                                        {
                                            TheThread.Debug_Suspend = true;

                                            MsgPort.Write(" > Suspended ");
                                            MsgPort.Write(TheThread.Name);
                                            MsgPort.Write(" thread\n");
                                        }
                                    }
                                    else
                                    {
                                        MsgPort.Write("Thread not found.\n");
                                    }
                                }
                            }
                            else
                            {
                                MsgPort.Write("Process not found.\n");
                            }
                        }
                        else
                        {
                            MsgPort.Write("Incorrect arguments, see help.\n");
                        }

                        #endregion
                    }
                    else if (cmd == "resume")
                    {
                        #region Resume

                        if (lineParts.Count == 3)
                        {
                            uint ProcessId = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[1], 0);
                            int  ThreadId  = FOS_System.Int32.Parse_DecimalSigned((FOS_System.String)lineParts[2]);

                            Process TheProcess = ProcessManager.GetProcessById(ProcessId);

                            if (TheProcess != null)
                            {
                                if (ThreadId == -1)
                                {
                                    for (int i = 0; i < TheProcess.Threads.Count; i++)
                                    {
                                        Thread AThread = ((Thread)TheProcess.Threads[i]);

                                        UInt64 ProcessThreadId = (((UInt64)ProcessId) << 32) | AThread.Id;
                                        ThreadsToSuspend.Remove(ProcessThreadId);

                                        AThread.Debug_Suspend = false;

                                        MsgPort.Write(" > Resumed ");
                                        MsgPort.Write(AThread.Name);
                                        MsgPort.Write(" thread\n");
                                    }
                                }
                                else
                                {
                                    UInt64 ProcessThreadId = (((UInt64)ProcessId) << 32) | (uint)ThreadId;
                                    ThreadsToSuspend.Remove(ProcessThreadId);

                                    Thread TheThread = ProcessManager.GetThreadById((uint)ThreadId, TheProcess);

                                    if (TheThread != null)
                                    {
                                        TheThread.Debug_Suspend = false;

                                        MsgPort.Write(" > Resumed ");
                                        MsgPort.Write(TheThread.Name);
                                        MsgPort.Write(" thread\n");
                                    }
                                    else
                                    {
                                        MsgPort.Write("Thread not found.\n");
                                    }
                                }
                            }
                            else
                            {
                                MsgPort.Write("Process not found.\n");
                            }
                        }
                        else
                        {
                            MsgPort.Write("Incorrect arguments, see help.\n");
                        }

                        #endregion
                    }
                    else if (cmd == "step")
                    {
                        #region Step

                        if (lineParts.Count == 3)
                        {
                            uint ProcessId = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[1], 0);
                            int  ThreadId  = FOS_System.Int32.Parse_DecimalSigned((FOS_System.String)lineParts[2]);

                            Process TheProcess = ProcessManager.GetProcessById(ProcessId);

                            if (TheProcess != null)
                            {
                                if (ThreadId == -1)
                                {
                                    for (int i = 0; i < TheProcess.Threads.Count; i++)
                                    {
                                        Thread AThread = ((Thread)TheProcess.Threads[i]);

                                        if (AThread.Debug_Suspend)
                                        {
                                            AThread.Debug_Suspend = false;

                                            MsgPort.Write(" > Stepping ");
                                            MsgPort.Write(AThread.Name);
                                            MsgPort.Write(" thread\n");
                                        }
                                        else
                                        {
                                            MsgPort.Write("Thread must be suspended first.\n");
                                        }
                                    }
                                }
                                else
                                {
                                    Thread TheThread = ProcessManager.GetThreadById((uint)ThreadId, TheProcess);

                                    if (TheThread != null)
                                    {
                                        if (TheThread.Debug_Suspend)
                                        {
                                            TheThread.Debug_Suspend = false;

                                            MsgPort.Write(" > Stepping ");
                                            MsgPort.Write(TheThread.Name);
                                            MsgPort.Write(" thread\n");
                                        }
                                        else
                                        {
                                            MsgPort.Write("Thread must be suspended first.\n");
                                        }
                                    }
                                    else
                                    {
                                        MsgPort.Write("Thread not found.\n");
                                    }
                                }
                            }
                            else
                            {
                                MsgPort.Write("Process not found.\n");
                            }
                        }
                        else
                        {
                            MsgPort.Write("Incorrect arguments, see help.\n");
                        }

                        #endregion
                    }
                    else if (cmd == "ss")
                    {
                        #region Single Step

                        if (lineParts.Count == 3)
                        {
                            uint ProcessId = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[1], 0);
                            int  ThreadId  = FOS_System.Int32.Parse_DecimalSigned((FOS_System.String)lineParts[2]);

                            Process TheProcess = ProcessManager.GetProcessById(ProcessId);

                            if (TheProcess != null)
                            {
                                if (ThreadId == -1)
                                {
                                    for (int i = 0; i < TheProcess.Threads.Count; i++)
                                    {
                                        Thread AThread = ((Thread)TheProcess.Threads[i]);

                                        if (AThread.Debug_Suspend)
                                        {
                                            // Set trap flag (int1)
                                            AThread.EFLAGSFromInterruptStack |= 0x0100;
                                            AThread.Debug_Suspend             = false;

                                            MsgPort.Write(" > Single stepping ");
                                            MsgPort.Write(AThread.Name);
                                            MsgPort.Write(" thread\n");
                                        }
                                        else
                                        {
                                            MsgPort.Write("Thread must be suspended first.\n");
                                        }
                                    }
                                }
                                else
                                {
                                    Thread TheThread = ProcessManager.GetThreadById((uint)ThreadId, TheProcess);

                                    if (TheThread != null)
                                    {
                                        if (TheThread.Debug_Suspend)
                                        {
                                            // Set trap flag (int1)
                                            TheThread.EFLAGSFromInterruptStack |= 0x0100;
                                            TheThread.Debug_Suspend             = false;

                                            MsgPort.Write(" > Single stepping ");
                                            MsgPort.Write(TheThread.Name);
                                            MsgPort.Write(" thread\n");
                                        }
                                        else
                                        {
                                            MsgPort.Write("Thread must be suspended first.\n");
                                        }
                                    }
                                    else
                                    {
                                        MsgPort.Write("Thread not found.\n");
                                    }
                                }
                            }
                            else
                            {
                                MsgPort.Write("Process not found.\n");
                            }
                        }
                        else
                        {
                            MsgPort.Write("Incorrect arguments, see help.\n");
                        }

                        #endregion
                    }
                    else if (cmd == "sta")
                    {
                        #region Step To Address

                        if (lineParts.Count == 4)
                        {
                            uint ProcessId = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[1], 0);
                            int  ThreadId  = FOS_System.Int32.Parse_DecimalSigned((FOS_System.String)lineParts[2]);
                            uint Address   = FOS_System.Int32.Parse_HexadecimalUnsigned((FOS_System.String)lineParts[3], 0);

                            Process TheProcess = ProcessManager.GetProcessById(ProcessId);

                            if (TheProcess != null)
                            {
                                if (ThreadId == -1)
                                {
                                    for (int i = 0; i < TheProcess.Threads.Count; i++)
                                    {
                                        Thread AThread = ((Thread)TheProcess.Threads[i]);

                                        if (AThread.Debug_Suspend)
                                        {
                                            // Set trap flag (int1)
                                            UInt64 ProcessThreadId = (((UInt64)ProcessId) << 32) | (uint)ThreadId;
                                            ThreadsToSuspendAtAddresses.Add(ProcessThreadId, Address);
                                            AThread.EFLAGSFromInterruptStack |= 0x0100;
                                            AThread.Debug_Suspend             = false;

                                            MsgPort.Write(" > Single stepping ");
                                            MsgPort.Write(AThread.Name);
                                            MsgPort.Write(" thread to address ");
                                            MsgPort.Write(Address);
                                            MsgPort.Write("\n");
                                        }
                                        else
                                        {
                                            MsgPort.Write("Thread must be suspended first.\n");
                                        }
                                    }
                                }
                                else
                                {
                                    Thread TheThread = ProcessManager.GetThreadById((uint)ThreadId, TheProcess);

                                    if (TheThread != null)
                                    {
                                        if (TheThread.Debug_Suspend)
                                        {
                                            // Set trap flag (int1)
                                            UInt64 ProcessThreadId = (((UInt64)ProcessId) << 32) | (uint)ThreadId;
                                            ThreadsToSuspendAtAddresses.Add(ProcessThreadId, Address);
                                            TheThread.EFLAGSFromInterruptStack |= 0x0100;
                                            TheThread.Debug_Suspend             = false;

                                            MsgPort.Write(" > Single stepping ");
                                            MsgPort.Write(TheThread.Name);
                                            MsgPort.Write(" thread to address ");
                                            MsgPort.Write(Address);
                                            MsgPort.Write("\n");
                                        }
                                        else
                                        {
                                            MsgPort.Write("Thread must be suspended first.\n");
                                        }
                                    }
                                    else
                                    {
                                        MsgPort.Write("Thread not found.\n");
                                    }
                                }
                            }
                            else
                            {
                                MsgPort.Write("Process not found.\n");
                            }
                        }
                        else
                        {
                            MsgPort.Write("Incorrect arguments, see help.\n");
                        }

                        #endregion
                    }
                    else if (cmd == "bps")
                    {
                        #region Set Breakpoint

                        if (lineParts.Count == 2)
                        {
                            uint Address = FOS_System.Int32.Parse_HexadecimalUnsigned((FOS_System.String)lineParts[1], 0);

                            MsgPort.Write(" > Breakpoint to be set at ");
                            MsgPort.Write(Address);
                            MsgPort.Write("\n");

                            *((byte *)Address) = 0xCC;
                        }
                        else
                        {
                            MsgPort.Write("Incorrect arguments, see help.\n");
                        }

                        #endregion
                    }
                    else if (cmd == "bpc")
                    {
                        #region Clear Breakpoint

                        if (lineParts.Count == 2)
                        {
                            uint Address = FOS_System.Int32.Parse_HexadecimalUnsigned((FOS_System.String)lineParts[1], 0);

                            MsgPort.Write(" > Breakpoint to be cleared at ");
                            MsgPort.Write(Address);
                            MsgPort.Write("\n");

                            *((byte *)Address) = 0x90;
                        }
                        else
                        {
                            MsgPort.Write("Incorrect arguments, see help.\n");
                        }

                        #endregion
                    }
                    else if (cmd == "regs")
                    {
                        #region Registers

                        if (lineParts.Count == 3)
                        {
                            uint ProcessId = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[1], 0);
                            uint ThreadId  = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[2], 0);

                            Process TheProcess = ProcessManager.GetProcessById(ProcessId);

                            if (TheProcess != null)
                            {
                                Thread TheThread = ProcessManager.GetThreadById((uint)ThreadId, TheProcess);

                                if (TheThread != null)
                                {
                                    if (TheThread.Debug_Suspend)
                                    {
                                        MsgPort.Write("Registers of ");
                                        MsgPort.Write(TheThread.Name);
                                        MsgPort.Write(" : \n");

                                        MsgPort.Write(" > EAX : ");
                                        MsgPort.Write((FOS_System.String)TheThread.EAXFromInterruptStack);
                                        MsgPort.Write("\n > EBX : ");
                                        MsgPort.Write((FOS_System.String)TheThread.EBXFromInterruptStack);
                                        MsgPort.Write("\n > ECX : ");
                                        MsgPort.Write((FOS_System.String)TheThread.ECXFromInterruptStack);
                                        MsgPort.Write("\n > EDX : ");
                                        MsgPort.Write((FOS_System.String)TheThread.EDXFromInterruptStack);
                                        MsgPort.Write("\n");

                                        MsgPort.Write("\n > ESP : ");
                                        MsgPort.Write((FOS_System.String)TheThread.ESPFromInterruptStack);
                                        MsgPort.Write("\n > EBP : ");
                                        MsgPort.Write((FOS_System.String)TheThread.EBPFromInterruptStack);
                                        MsgPort.Write("\n > EIP : ");
                                        MsgPort.Write((FOS_System.String)TheThread.EIPFromInterruptStack);
                                        MsgPort.Write("\n");
                                    }
                                    else
                                    {
                                        MsgPort.Write("Thread must be suspended first.\n");
                                    }
                                }
                                else
                                {
                                    MsgPort.Write("Thread not found.\n");
                                }
                            }
                            else
                            {
                                MsgPort.Write("Process not found.\n");
                            }
                        }
                        else
                        {
                            MsgPort.Write("Incorrect arguments, see help.\n");
                        }

                        #endregion
                    }
                    else if (cmd == "mem")
                    {
                        #region Memory

                        if (lineParts.Count == 5)
                        {
                            uint ProcessId = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[1], 0);

                            Process TheProcess = ProcessManager.GetProcessById(ProcessId);

                            if (TheProcess != null)
                            {
                                // Need access to specified process' memory
                                MemoryLayout OriginalMemoryLayout = SystemCallsHelpers.EnableAccessToMemoryOfProcess(TheProcess);

                                uint Address = FOS_System.Int32.Parse_HexadecimalUnsigned((FOS_System.String)lineParts[2], 0);
                                int  length  = FOS_System.Int32.Parse_DecimalSigned((FOS_System.String)lineParts[3]);
                                int  units   = FOS_System.Int32.Parse_DecimalSigned((FOS_System.String)lineParts[4]);

                                MsgPort.Write(" Memory from ");
                                MsgPort.Write(Address);
                                MsgPort.Write(" for ");
                                MsgPort.Write(length);
                                MsgPort.Write(" units with ");
                                MsgPort.Write(units);
                                MsgPort.Write(" bytes/unit:\n");

                                if (units == 1)
                                {
                                    byte *AddrPtr = (byte *)Address;
                                    for (int i = 0; i < length; i++)
                                    {
                                        MsgPort.Write((FOS_System.String)AddrPtr[i]);
                                        MsgPort.Write(" ");
                                    }
                                }
                                else if (units == 2)
                                {
                                    ushort *AddrPtr = (ushort *)Address;
                                    for (int i = 0; i < length; i++)
                                    {
                                        MsgPort.Write((FOS_System.String)AddrPtr[i]);
                                        MsgPort.Write(" ");
                                    }
                                }
                                else if (units == 4)
                                {
                                    uint *AddrPtr = (uint *)Address;
                                    for (int i = 0; i < length; i++)
                                    {
                                        MsgPort.Write((FOS_System.String)AddrPtr[i]);
                                        MsgPort.Write(" ");
                                    }
                                }

                                MsgPort.Write("\n");

                                SystemCallsHelpers.DisableAccessToMemoryOfProcess(OriginalMemoryLayout);
                            }
                            else
                            {
                                MsgPort.Write("Process not found.\n");
                            }
                        }
                        else
                        {
                            MsgPort.Write("Incorrect arguments, see help.\n");
                        }

                        #endregion
                    }
                    else
                    {
                        MsgPort.Write("Unrecognised command. (Note: Backspace not supported!)\n");
                    }
                }

                // Always issue end of command signal, even if something else went wrong
                //  - Keeps the host in sync.
                MsgPort.Write("END OF COMMAND\n");
            }
        }