diff --git a/Include/Aurora/Processes/IProcess.hpp b/Include/Aurora/Processes/IProcess.hpp index 8562354a..cd9e3ddd 100644 --- a/Include/Aurora/Processes/IProcess.hpp +++ b/Include/Aurora/Processes/IProcess.hpp @@ -84,13 +84,13 @@ namespace Aurora::Processes virtual bool Write(const Memory::MemoryViewStreamRead &source) = 0; /** - * @brief Returns a asynchronous file stream transaction of pipe pair: stdout, stdin + * @brief Returns an asynchronous file stream transaction of pipe pair: stdout, stdin * @return */ virtual AuSPtr NewAsyncTransaction() = 0; /** - * @brief Returns a asynchronous file stream transaction of pipe pair: stderr, INVALID + * @brief Returns an asynchronous file stream transaction of pipe pair: stderr, INVALID * @return */ virtual AuSPtr NewErrorStreamAsyncTransaction() = 0; diff --git a/Source/Processes/CreatePipeEx.NT.cpp b/Source/Processes/CreatePipeEx.NT.cpp new file mode 100644 index 00000000..6dc4cf34 --- /dev/null +++ b/Source/Processes/CreatePipeEx.NT.cpp @@ -0,0 +1,122 @@ +/******************************************************************************\ +* This is a part of the Microsoft Source Code Samples. +* Copyright 1995 - 1997 Microsoft Corporation. +* All rights reserved. +* This source code is only intended as a supplement to +* Microsoft Development Tools and/or WinHelp documentation. +* See these sources for detailed information regarding the +* Microsoft samples programs. +\******************************************************************************/ +#include + +/*++ +Copyright (c) 1997 Microsoft Corporation +Module Name: + CreatePipeEx.NT.cpp +Abstract: + CreatePipe-like function that lets one or both handles be overlapped +Author: + Dave Hart Summer 1997 +Revision History: + J Reece Wilson 2022: Updated default size to match Linux's 16 page assumption + Renamed MyCreatePipeEx to CreatePipeEx + Now using Au atomics + Added second parameter check +--*/ + + +static AuUInt32 gPipeSerialNumber; + +BOOL +APIENTRY +CreatePipeEx( + OUT LPHANDLE lpReadPipe, + OUT LPHANDLE lpWritePipe, + IN LPSECURITY_ATTRIBUTES lpPipeAttributes, + IN DWORD nSize, + DWORD dwReadMode, + DWORD dwWriteMode +) +{ + HANDLE ReadPipeHandle, WritePipeHandle; + DWORD dwError; + char PipeNameBuffer[MAX_PATH]; + + // + // Only one valid OpenMode flag - FILE_FLAG_OVERLAPPED + // + + if ((dwReadMode | dwWriteMode) & (~FILE_FLAG_OVERLAPPED)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // + // Check output arguments are non-null + // + + if (!lpReadPipe || !lpWritePipe) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // + // Set the default timeout to 120 seconds + // + + + // + // Set the default pipe size + // + + if (nSize == 0) + { + nSize = 16 * AuHwInfo::GetPageSize(); + } + + sprintf(PipeNameBuffer, + "\\\\.\\Pipe\\AuroraProcessCStandardStream.%08x.%08x", + GetCurrentProcessId(), + AuAtomicAdd(&gPipeSerialNumber, 1u) + ); + + ReadPipeHandle = CreateNamedPipeA( + PipeNameBuffer, + PIPE_ACCESS_INBOUND | dwReadMode, + PIPE_TYPE_BYTE | PIPE_WAIT, + 1, // Number of pipes + nSize, // Out buffer size + nSize, // In buffer size + 120 * 1000, // Timeout in ms + lpPipeAttributes + ); + + if (!ReadPipeHandle) + { + return FALSE; + } + + WritePipeHandle = CreateFileA( + PipeNameBuffer, + GENERIC_WRITE, + 0, // No sharing + lpPipeAttributes, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | dwWriteMode, + NULL // Template file + ); + + if (INVALID_HANDLE_VALUE == WritePipeHandle) + { + dwError = GetLastError(); + CloseHandle(ReadPipeHandle); + SetLastError(dwError); + return FALSE; + } + + *lpReadPipe = ReadPipeHandle; + *lpWritePipe = WritePipeHandle; + return TRUE; +} \ No newline at end of file diff --git a/Source/Processes/CreatePipeEx.NT.hpp b/Source/Processes/CreatePipeEx.NT.hpp new file mode 100644 index 00000000..9dfff268 --- /dev/null +++ b/Source/Processes/CreatePipeEx.NT.hpp @@ -0,0 +1,45 @@ +#pragma once + +/*++ +Routine Description: + The CreatePipeEx API is used to create an anonymous pipe I/O device. + Unlike CreatePipe FILE_FLAG_OVERLAPPED may be specified for one or + both handles. + Two handles to the device are created. One handle is opened for + reading and the other is opened for writing. These handles may be + used in subsequent calls to ReadFile and WriteFile to transmit data + through the pipe. +Arguments: + lpReadPipe - Returns a handle to the read side of the pipe. Data + may be read from the pipe by specifying this handle value in a + subsequent call to ReadFile. + lpWritePipe - Returns a handle to the write side of the pipe. Data + may be written to the pipe by specifying this handle value in a + subsequent call to WriteFile. + lpPipeAttributes - An optional parameter that may be used to specify + the attributes of the new pipe. If the parameter is not + specified, then the pipe is created without a security + descriptor, and the resulting handles are not inherited on + process creation. Otherwise, the optional security attributes + are used on the pipe, and the inherit handles flag effects both + pipe handles. + nSize - Supplies the requested buffer size for the pipe. This is + only a suggestion and is used by the operating system to + calculate an appropriate buffering mechanism. A value of zero + indicates that the system is to choose the default buffering + scheme. +Return Value: + TRUE - The operation was successful. + FALSE/NULL - The operation failed. Extended error status is available + using GetLastError. +--*/ +BOOL +APIENTRY +CreatePipeEx( + OUT LPHANDLE lpReadPipe, + OUT LPHANDLE lpWritePipe, + IN LPSECURITY_ATTRIBUTES lpPipeAttributes, + IN DWORD nSize, + DWORD dwReadMode, + DWORD dwWriteMode +); \ No newline at end of file diff --git a/Source/Processes/Process.NT.cpp b/Source/Processes/Process.NT.cpp index 863948eb..b38a8d44 100644 --- a/Source/Processes/Process.NT.cpp +++ b/Source/Processes/Process.NT.cpp @@ -18,9 +18,27 @@ #include #include +#include + +#include "CreatePipeEx.NT.hpp" namespace Aurora::Processes { + struct ProcessAliveLoopSource : Loop::LSHandle + { + ProcessAliveLoopSource(HANDLE h); + virtual AuLoop::ELoopSource GetType() override; + }; + + ProcessAliveLoopSource::ProcessAliveLoopSource(HANDLE h) : LSHandle(AuReinterpretCast(h)) + { + } + + AuLoop::ELoopSource ProcessAliveLoopSource::GetType() + { + return AuLoop::ELoopSource::eProcessDead; + } + ProcessImpl::ProcessImpl(const StartupParmaters ¶ms) : startup_(params) { AuIOFS::NormalizePath(this->startup_.process, this->startup_.process); @@ -116,6 +134,11 @@ namespace Aurora::Processes return this->thread_->AsWaitable(); } + AuSPtr ProcessImpl::AsLoopSource() + { + return this->loopSource_; + } + AuSInt ProcessImpl::GetExitCode() { return this->exitCode_; @@ -217,7 +240,7 @@ namespace Aurora::Processes this->exitCode_ = 0x10110100; if (this->startup_.fwdOut) { - if (!CreatePipe(&pipeStdOutRead_, &pipeStdOutWrite_, &saAttr, 0)) + if (!CreatePipeEx(&pipeStdOutRead_, &pipeStdOutWrite_, &saAttr, 0, FILE_FLAG_OVERLAPPED, 0)) { return false; } @@ -230,7 +253,7 @@ namespace Aurora::Processes if (this->startup_.fwdErr) { - if (!CreatePipe(&pipeStdErrRead_, &pipeStdErrWrite_, &saAttr, 0)) + if (!CreatePipeEx(&pipeStdErrRead_, &pipeStdErrWrite_, &saAttr, 0, FILE_FLAG_OVERLAPPED, 0)) { return false; } @@ -243,7 +266,7 @@ namespace Aurora::Processes if (this->startup_.fwdIn) { - if (!CreatePipe(&pipeStdInRead_, &pipeStdInWrite_, &saAttr, 0)) + if (!CreatePipeEx(&pipeStdInRead_, &pipeStdInWrite_, &saAttr, 0, 0, FILE_FLAG_OVERLAPPED)) { return false; } @@ -406,6 +429,12 @@ namespace Aurora::Processes return false; } + this->loopSource_ = AuMakeShared(this->process_); + if (!this->loopSource_) + { + return {}; + } + this->thread_->Run(); return true; } diff --git a/Source/Processes/Process.NT.hpp b/Source/Processes/Process.NT.hpp index aa3241af..549cbd26 100644 --- a/Source/Processes/Process.NT.hpp +++ b/Source/Processes/Process.NT.hpp @@ -26,6 +26,7 @@ namespace Aurora::Processes bool Terminate() override; AuSPtr AsWaitable() override; + AuSPtr AsLoopSource() override; AuSInt GetExitCode() override; void ShutdownPipes(); @@ -49,6 +50,8 @@ namespace Aurora::Processes HANDLE pipeStdInRead_ {INVALID_HANDLE_VALUE}; HANDLE pipeStdInWrite_ {INVALID_HANDLE_VALUE}; + AuSPtr loopSource_; + AuSPtr fsHandle_; AuSPtr fsStream_;