/// <summary> /// Process the read/write queues of the specified pipe. /// </summary> /// <param name="pipe">The pipe to process.</param> /// <param name="OutProcess">The process which owns the pipe's outpoint.</param> /// <param name="InProcess">The process which owns the pipe's inpoint.</param> private static void ProcessPipeQueue(Pipe pipe, Process OutProcess, Process InProcess) { #if PIPES_TRACE BasicConsole.WriteLine("ProcessPipeQueue: Checking first loop condition"); #endif while ((pipe.AreThreadsWaitingToWrite() && pipe.CanWrite()) || (pipe.AreThreadsWaitingToRead() && pipe.CanRead())) { #if PIPES_TRACE BasicConsole.WriteLine("ProcessPipeQueue: Loop start"); #endif if (pipe.AreThreadsWaitingToWrite() && pipe.CanWrite()) { #if PIPES_TRACE BasicConsole.WriteLine("ProcessPipeQueue: Pipe can write"); #endif /* - Dequeue thread to write * - Find thread to write * - Load pointer to request structure from thread's stack * - Write pipe * - Setup return values for thread * - Wake thread * - Loop back */ #if PIPES_TRACE BasicConsole.WriteLine("ProcessPipeQueue: Dequeuing out thread id"); #endif UInt32 ThreadId; if (!pipe.DequeueToWrite(out ThreadId)) { break; } #if PIPES_TRACE BasicConsole.WriteLine("ProcessPipeQueue: Getting out thread"); #endif Thread WriteThread = ProcessManager.GetThreadById(ThreadId, OutProcess); if (WriteThread == null) { break; } #if PIPES_TRACE BasicConsole.WriteLine("ProcessPipeQueue: Writing pipe"); #endif WritePipeRequest* Request = (WritePipeRequest*)WriteThread.Param1; bool Successful = pipe.Write(Request->InBuffer, Request->Offset, Request->Length); if (Successful) { #if PIPES_TRACE BasicConsole.WriteLine("ProcessPipeQueue: Write successful"); #endif WriteThread.Return1 = (uint)SystemCallResults.OK; WriteThread._Wake(); } else { #if PIPES_TRACE BasicConsole.WriteLine("ProcessPipeQueue: Write failed"); #endif WriteThread.Return1 = (uint)SystemCallResults.Fail; WriteThread._Wake(); } } else if (pipe.AreThreadsWaitingToRead() && pipe.CanRead()) { #if PIPES_TRACE BasicConsole.WriteLine("ProcessPipeQueue: Pipe can read"); #endif /* - Dequeue thread to read * - Find thread to read * - Load pointer to request structure from thread's stack * - Read pipe * - Setup return values for thread * - Wake thread * - Loop back */ #if PIPES_TRACE BasicConsole.WriteLine("ProcessPipeQueue: Dequeuing in thread id"); #endif UInt32 ThreadId; if (!pipe.DequeueToRead(out ThreadId)) { break; } #if PIPES_TRACE BasicConsole.WriteLine("ProcessPipeQueue: Getting in thread"); #endif Thread ReadThread = ProcessManager.GetThreadById(ThreadId, InProcess); if (ReadThread == null) { break; } #if PIPES_TRACE BasicConsole.WriteLine("ProcessPipeQueue: Reading pipe"); #endif ReadPipeRequest* Request = (ReadPipeRequest*)ReadThread.Param1; int BytesRead; bool Successful = pipe.Read(Request->OutBuffer, Request->Offset, Request->Length, out BytesRead); if (Successful) { #if PIPES_TRACE BasicConsole.WriteLine("ProcessPipeQueue: Read successful"); #endif ReadThread.Return1 = (uint)SystemCallResults.OK; ReadThread.Return2 = (uint)BytesRead; ReadThread._Wake(); } else { #if PIPES_TRACE BasicConsole.WriteLine("ProcessPipeQueue: Read failed"); #endif ReadThread.Return1 = (uint)SystemCallResults.Fail; ReadThread._Wake(); } } #if PIPES_TRACE BasicConsole.WriteLine("ProcessPipeQueue: Looping..."); #endif } }
/// <summary> /// Determines whether the specified process is allowed to read from the specified pipe. /// </summary> /// <param name="ThePipe">The pipe to check.</param> /// <param name="ProcessId">The Id of the process to check.</param> /// <returns>True if the process is allowed. Otherwise, false.</returns> private static bool AllowedToReadPipe(Pipe ThePipe, uint ProcessId) { return ThePipe.Inpoint.ProcessId == ProcessId; }
/// <summary> /// Determines whether the specified process is allowed to write to the specified pipe. /// </summary> /// <param name="ThePipe">The pipe to check.</param> /// <param name="ProcessId">The Id of the process to check.</param> /// <returns>True if the process is allowed. Otherwise, false.</returns> private static bool AllowedToWritePipe(Pipe ThePipe, uint ProcessId) { return ThePipe.Outpoint.ProcessId == ProcessId; }
/// <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; }