/// <summary> /// Attempts to add the specified thread to the list of threads waiting on a pipe to be created for the specified outpoint. /// </summary> /// <param name="OutProcessId">The Id of the process which owns the outpoint and the thread to block.</param> /// <param name="OutThreadId">The Id of the thread to block.</param> /// <param name="Class">The class of the outpoint.</param> /// <param name="Subclass">The subclass of the outpoint.</param> /// <returns>True if the request was successful. Otherwise, false.</returns> public static bool WaitOnPipeCreate(uint OutProcessId, uint OutThreadId, PipeClasses Class, PipeSubclasses Subclass) { // Validate inputs // - Check the process exists // - Check the thread exists Process OutProcess = ProcessManager.GetProcessById(OutProcessId); if (OutProcess == null) { return(false); } Thread OutThread = ProcessManager.GetThreadById(OutThreadId, OutProcess); if (OutThread == null) { return(false); } // Find the outpoint PipeOutpoint outpoint = GetOutpoint(OutProcessId, Class, Subclass); // Check that we actually found the outpoint if (outpoint == null) { return(false); } // Mark the outpoint as being waited on by the specified process/thread outpoint.WaitingThreads.Add(((UInt64)OutProcessId << 32) | OutThreadId); return(true); }
/// <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); } // Need access to the request structure ProcessManager.EnableKernelAccessToProcessMemory(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; } } } ProcessManager.DisableKernelAccessToProcessMemory(CallerProcess); return(OK); }
/// <summary> /// Creates a new pipe. /// </summary> /// <param name="AnId">The pipe's Id.</param> /// <param name="outpoint">The outpoint of the pipe.</param> /// <param name="inpoint">The inpoint of the pipe.</param> /// <param name="BufferSize">The size of buffer to use within the pipe.</param> public Pipe(int AnId, PipeOutpoint outpoint, PipeInpoint inpoint, int BufferSize) { Id = AnId; Outpoint = outpoint; Inpoint = inpoint; Buffer = new byte[BufferSize]; DataAvailable = 0; ThreadsWaitingToRead = new UInt32Queue(5, true); ThreadsWaitingToWrite = new UInt32Queue(5, true); SizesWaitingToWrite = new UInt32Queue(5, true); }
/// <summary> /// Gets the outpoint from the specified process of the desired class and subclass. /// </summary> /// <param name="OutProcessId">The Id of the process which owns the outpoint.</param> /// <param name="Class">The class of the outpoint.</param> /// <param name="Subclass">The subclass of the outpoint.</param> /// <returns>The outpoint or null if not found.</returns> private static PipeOutpoint GetOutpoint(uint OutProcessId, PipeClasses Class, PipeSubclasses Subclass) { PipeOutpoint outpoint = null; for (int i = 0; i < PipeOutpoints.Count; i++) { PipeOutpoint anOutpoint = (PipeOutpoint)PipeOutpoints[i]; if (anOutpoint.ProcessId == OutProcessId && anOutpoint.Class == Class && anOutpoint.Subclass == Subclass) { outpoint = anOutpoint; break; } } return(outpoint); }
/// <summary> /// Wakes all threads waiting on a pipe to be created for the specified outpoint. /// </summary> /// <param name="outpoint">The outpoint to wake waiting threads of.</param> /// <param name="newPipeId">The Id of the newly created pipe.</param> private static void WakeWaitingThreads(PipeOutpoint outpoint, int newPipeId) { while (outpoint.WaitingThreads.Count > 0) { UInt64 identifier = outpoint.WaitingThreads[0]; outpoint.WaitingThreads.RemoveAt(0); UInt32 processId = (UInt32)(identifier >> 32); UInt32 threadId = (UInt32)(identifier); Process process = ProcessManager.GetProcessById(processId); Thread thread = ProcessManager.GetThreadById(threadId, process); thread.Return1 = (uint)SystemCallResults.OK; thread.Return2 = (uint)newPipeId; thread.Return3 = 0; thread.Return4 = 0; thread._Wake(); } }
/// <summary> /// Attempts to register a pipe outpoint. /// </summary> /// <param name="OutProcessId">The Id of the process which should own the outpoint.</param> /// <param name="Class">The class of pipe the outpoint will create.</param> /// <param name="Subclass">The subclass of pipe the outpoint will create.</param> /// <param name="MaxConnections">The maximum number of connections allowed to the outpoint. Also see <see cref="PipeConstants.UnlimitedConnections"/>.</param> /// <param name="outpoint">Out : The newly created outpoint (or null if the request fails).</param> /// <returns>True if the request was successful. Otherwise, false.</returns> /// <seealso cref="PipeConstants.UnlimitedConnections"/> public static bool RegisterPipeOutpoint(uint OutProcessId, PipeClasses Class, PipeSubclasses Subclass, int MaxConnections, out PipeOutpoint outpoint) { // Validate inputs // - Check process exists (if it doesn't then hmm...) // - Check MaxConnections > 0 (0 or negative number of connections would be insane) if (ProcessManager.GetProcessById(OutProcessId) == null) { outpoint = null; return(false); } else if (MaxConnections <= 0 && MaxConnections != PipeConstants.UnlimitedConnections) { outpoint = null; return(false); } // Check no existing outpoints of the same type exist for the specified process for (int i = 0; i < PipeOutpoints.Count; i++) { PipeOutpoint anOutpoint = (PipeOutpoint)PipeOutpoints[i]; if (anOutpoint.ProcessId == OutProcessId && anOutpoint.Class == Class && anOutpoint.Subclass == Subclass) { // Set the resultant outpoint to the existing outpoint outpoint = anOutpoint; // Return true because the outpoint exists (even though we didn't create a new one) return(true); } } // None exists? Create a new one outpoint = new PipeOutpoint(OutProcessId, Class, Subclass, MaxConnections); // Add it to our complete list outpoints PipeOutpoints.Add(outpoint); // Return true because the outpoint exists (a new one was created) return(true); }
/// <summary> /// Attempts to get the number of outpoints of the specified class and subclass. /// </summary> /// <param name="Class">The class of outpoint to search for.</param> /// <param name="Subclass">The subclass of outpoint to search for.</param> /// <param name="numOutpoints">Out : The number of outpoints of the specified class and subclass.</param> /// <returns>True if the request was successful. Otherwise, false.</returns> public static bool GetNumPipeOutpoints(PipeClasses Class, PipeSubclasses Subclass, out int numOutpoints) { // Initialise count to zero numOutpoints = 0; // Search for outpoints of correct class and subclass, incrementing count as we go for (int i = 0; i < PipeOutpoints.Count; i++) { PipeOutpoint anOutpoint = (PipeOutpoint)PipeOutpoints[i]; if (anOutpoint.Class == Class && anOutpoint.Subclass == Subclass && (anOutpoint.MaxConnections == PipeConstants.UnlimitedConnections || anOutpoint.NumConnections < anOutpoint.MaxConnections)) { numOutpoints++; } } // This method will always succeed unless it throws an exception // - A count result of zero is valid / success return(true); }
/// <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); } // Need access to the request structure bool ShouldDisableKernelAccessToProcessMemory = true; ProcessManager.EnableKernelAccessToProcessMemory(InProcessId); 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; ShouldDisableKernelAccessToProcessMemory = false; ProcessManager.DisableKernelAccessToProcessMemory(InProcessId); // Wake any threads (/processes) which were waiting on a pipe to be created WakeWaitingThreads(outpoint, pipe.Id); } } if (ShouldDisableKernelAccessToProcessMemory) { ProcessManager.DisableKernelAccessToProcessMemory(InProcessId); } return(OK); }
/// <summary> /// Attempts to register a pipe outpoint. /// </summary> /// <param name="OutProcessId">The Id of the process which should own the outpoint.</param> /// <param name="Class">The class of pipe the outpoint will create.</param> /// <param name="Subclass">The subclass of pipe the outpoint will create.</param> /// <param name="MaxConnections">The maximum number of connections allowed to the outpoint. Also see <see cref="PipeConstants.UnlimitedConnections"/>.</param> /// <param name="outpoint">Out : The newly created outpoint (or null if the request fails).</param> /// <returns>True if the request was successful. Otherwise, false.</returns> /// <seealso cref="PipeConstants.UnlimitedConnections"/> public static bool RegisterPipeOutpoint(uint OutProcessId, PipeClasses Class, PipeSubclasses Subclass, int MaxConnections, out PipeOutpoint outpoint) { // Validate inputs // - Check process exists (if it doesn't then hmm...) // - Check MaxConnections > 0 (0 or negative number of connections would be insane) if (ProcessManager.GetProcessById(OutProcessId) == null) { outpoint = null; return false; } else if (MaxConnections <= 0 && MaxConnections != PipeConstants.UnlimitedConnections) { outpoint = null; return false; } // Check no existing outpoints of the same type exist for the specified process for (int i = 0; i < PipeOutpoints.Count; i++) { PipeOutpoint anOutpoint = (PipeOutpoint)PipeOutpoints[i]; if (anOutpoint.ProcessId == OutProcessId && anOutpoint.Class == Class && anOutpoint.Subclass == Subclass) { // Set the resultant outpoint to the existing outpoint outpoint = anOutpoint; // Return true because the outpoint exists (even though we didn't create a new one) return true; } } // None exists? Create a new one outpoint = new PipeOutpoint(OutProcessId, Class, Subclass, MaxConnections); // Add it to our complete list outpoints PipeOutpoints.Add(outpoint); // Return true because the outpoint exists (a new one was created) return true; }