Fill Process on Windows

This commit is contained in:
2025-06-26 11:44:27 -05:00
parent 81f0d3be2e
commit dbfb7c1133
11 changed files with 659 additions and 62 deletions

View File

@@ -5,6 +5,9 @@
#endif
#if defined(_WIN32)
#include <windows.h>
#include "TessesFramework/Filesystem/VFSFix.hpp"
#include "TessesFramework/Text/StringConverter.hpp"
using namespace Tesses::Framework::Text::StringConverter;
#endif
#if !defined(_WIN32)
extern char** environ;
@@ -128,12 +131,13 @@ namespace Tesses::Framework::Platform::Environment
auto pathParts = HttpUtils::SplitString(path,";");
for(auto item : pathParts)
{
auto newPath = LocalFS.SystemToVFSPath(item) / realPath;
for(auto item2 : pext)
{
auto newPathExt = newPath + item2;
if(LocalFS.FileExists(newPathExt)) return newPathExt;
}
auto newPath = LocalFS.SystemToVFSPath(item) / realPath;
if(LocalFS.FileExists(newPath)) return newPath;
}
return realPath;
@@ -158,20 +162,32 @@ namespace Tesses::Framework::Platform::Environment
}
void SetVariable(std::string name, std::optional<std::string> var)
{
if(var)
#if defined(_WIN32)
SetEnvironmentVariable(name.c_str(),var->c_str());
#else
if (var)
#if defined(_WIN32)
{
std::u16string nameu16 = {};
std::u16string varu16 = {};
UTF16::FromUTF8(nameu16, name);
UTF16::FromUTF8(varu16, var.value());
SetEnvironmentVariableW((LPCWSTR)nameu16.c_str(),(LPCWSTR)varu16.c_str());
}
#else
setenv(name.c_str(), var->c_str(),1);
#endif
else
#if defined(_WIN32)
{
SetEnvironmentVariable(name.c_str(),NULL);
}
#else
unsetenv(name.c_str());
#endif
#endif
else
#if defined(_WIN32)
{
std::u16string nameu16 = {};
UTF16::FromUTF8(nameu16, name);
SetEnvironmentVariableW((LPCWSTR)nameu16.c_str(),NULL);
}
#else
unsetenv(name.c_str());
#endif
}
@@ -179,11 +195,14 @@ namespace Tesses::Framework::Platform::Environment
void GetEnvironmentVariables(std::vector<std::pair<std::string,std::string>>& env)
{
#if defined(_WIN32)
char *environ0 = GetEnvironmentStrings();
char* envthing = environ0;
auto environ0 = GetEnvironmentStringsW();
auto envthing = environ0;
while(*envthing)
{
auto items = Http::HttpUtils::SplitString(envthing,"=",2);
std::u16string str = (const char16_t*)envthing;
std::string stru8;
UTF8::FromUTF16(stru8, str);
auto items = Http::HttpUtils::SplitString(stru8, "=", 2);
if(items.size() == 2)
{
@@ -193,9 +212,9 @@ namespace Tesses::Framework::Platform::Environment
{
env.push_back(std::pair<std::string,std::string>(items[0],""));
}
envthing += strlen(envthing)+1;
envthing += str.size() + 1;
}
FreeEnvironmentStrings(environ0);
FreeEnvironmentStringsW(environ0);
#else
for(char** envthing = environ; envthing != NULL; envthing++)
{

View File

@@ -3,16 +3,63 @@
#include "TessesFramework/Platform/Environment.hpp"
#if defined(_WIN32)
extern "C" {
#include <windows.h>
}
#include "TessesFramework/Filesystem/VFSFix.hpp"
#include 'TessesFramework/Text/StringConverter.hpp'
using namespace Tesses::Framework::Text::StringConverter;
static void escape_windows_args(std::string& str, std::vector<std::string> args)
{
bool first = true;
for (auto item : args)
{
if (first)
{
str.push_back('\"');
first = false;
}
else {
str.append(" \"");
}
for (auto c : item)
{
if (c == '"') str.append("\\\"");
else str.push_back(c);
}
str.push_back('\"');
}
}
#else
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#endif
namespace Tesses::Framework::Platform {
class ProcessData {
public:
//TODO: Implement for WIN32
#if defined(_WIN32)
STARTUPINFO si;
PROCESS_INFORMATION pi;
HANDLE stdin_strm;
HANDLE stdout_strm;
HANDLE stderr_strm;
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
#else
int stdin_strm;
@@ -23,7 +70,12 @@ namespace Tesses::Framework::Platform {
ProcessData() {
//TODO: Implement for WIN32
#if defined(_WIN32)
stdin_strm = NULL;
stdout_strm = NULL;
stderr_strm = NULL;
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
#else
@@ -35,23 +87,30 @@ namespace Tesses::Framework::Platform {
};
class ProcessStream : public Tesses::Framework::Streams::Stream {
#if defined(_WIN32)
HANDLE strm;
bool writing;
bool eos;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
#else
int strm;
bool writing;
bool shouldClose;
bool eos;
#endif
public:
#if defined(_WIN32)
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
#else
ProcessStream(int strm, bool writing, bool shouldClose)
ProcessStream(HANDLE strm, bool writing)
{
this->strm = strm;
this->writing = writing;
this->eos = false;
}
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
#else
ProcessStream(int strm, bool writing)
{
this->strm = strm;
this->writing = writing;
this->shouldClose=shouldClose;
this->eos=false;
}
#endif
@@ -59,7 +118,7 @@ namespace Tesses::Framework::Platform {
{
//TODO: Implement for WIN32
#if defined(_WIN32)
return true;
return this->strm == NULL || eos;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return true;
#else
@@ -70,7 +129,7 @@ namespace Tesses::Framework::Platform {
{
//TODO: Implement for WIN32
#if defined(_WIN32)
return false;
return !writing && this->strm != NULL;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return false;
#else
@@ -81,7 +140,8 @@ namespace Tesses::Framework::Platform {
{
//TODO: Implement for WIN32
#if defined(_WIN32)
return false;
return writing && this->strm != NULL;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return false;
#else
@@ -93,7 +153,15 @@ namespace Tesses::Framework::Platform {
{
//TODO: Implement for WIN32
#if defined(_WIN32)
return 0;
if (this->strm == NULL || this->eos && writing) return 0;
DWORD dataR = (DWORD)sz;
if (!ReadFile(this->strm, buff, dataR, &dataR, NULL))
return 0;
if (dataR == 0) {
this->eos = true;
}
return (size_t)dataW;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return 0;
#else
@@ -110,30 +178,22 @@ namespace Tesses::Framework::Platform {
{
//TODO: Implement for WIN32
#if defined(_WIN32)
return 0;
if (this->strm == NULL || !writing) return 0;
DWORD dataW=(DWORD)sz;
if (!WriteFile(this->strm, buff, dataW, &dataW, NULL))
return 0;
return (size_t)dataW;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return 0;
#else
if(this->strm < 0 && !writing) return 0;
if(this->strm < 0 || !writing) return 0;
auto r = write(this->strm,buff,sz);
if(r == -1) return 0;
return (size_t)r;
#endif
}
~ProcessStream()
{
//TODO: Implement for WIN32
#if defined(_WIN32)
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
//do nothing
#else
if(this->strm > -1 && this->shouldClose)
close(this->strm);
#endif
}
};
@@ -174,14 +234,28 @@ namespace Tesses::Framework::Platform {
}
Process::~Process()
{
ProcessData* p = this->hidden.GetField<ProcessData*>();
#if defined(_WIN32)
if (p->stdin_strm != NULL)
CloseHandle(p->stdin_strm);
if (p->stdout_strm != NULL)
CloseHandle(p->stdout_strm);
if (p->stderr_strm != NULL)
CloseHandle(p->stderr_strm);
CloseHandle(p->pi.hProcess);
CloseHandle(p->pi.hThread);
#endif
}
bool Process::Start()
{
auto p =
ProcessData* p =
this->hidden.GetField<ProcessData*>();
std::vector<std::pair<std::string,std::string>> envs;
@@ -204,6 +278,114 @@ namespace Tesses::Framework::Platform {
}
#if defined(_WIN32)
std::u16string u16_name;
std::u16string u16_args;
std::string args;
escape_windows_args(args,this->args);
UTF16::FromUTF8(u16_name,this->name);
UTF16::FromUTF8(u16_args, args);
std::u16string env = {};
for (auto envItem : this->env)
{
auto partOld = envItem.first + "=" + envItem.second;
std::u16string part = {};
UTF16::FromUTF8(part,partOld);
env.append(part);
env.push_back(0);
}
env.push_back(0);
std::u16string workDir = {};
if (!this->workingDirectory.empty())
UTF16::FromUTF8(workDir, this->workingDirectory);
SECURITY_ATTRIBUTES attr;
attr.nLength = sizeof(attr);
attr.lpSecurityDescriptor = NULL;
attr.bInheritHandle = true;
p->si->hStdInput = NULL;
p->si->hStdOutput = NULL;
p->si->hStdError = NULL;
p->stdin_strm = NULL;
p->stdout_strm = NULL;
p->stderr_strm = NULL;
if (this->redirectStdIn)
{
if (!CreatePipe(&p->si->hStdInput, &p->stdin_strm, &attr,0)) return false;
}
if (this->redirectStdOut)
{
if (!CreatePipe(&p->stdout_strm, &p->si->hStdOutput, &attr, 0))
{
if (this->redirectStdIn)
{
CloseHandle(p->stdin_strm);
CloseHandle(p->si->hStdInput);
}
return false;
}
}
if (this->redirectStdErr)
{
if (!CreatePipe(&p->stderr_strm, &p->si->hStdError, &attr, 0))
{
if (this->redirectStdIn)
{
CloseHandle(p->stdin_strm);
CloseHandle(p->si->hStdInput);
}
if (this->redirectStdOut)
{
CloseHandle(p->stdout_strm);
CloseHandle(p->si->hStdOutput);
}
return false;
}
}
if (!CreateProcessW(u16_name.c_str(), u16_args.data(), NULL, NULL, (this->redirectStdIn || this->redirectStdOut || this->redirectStdErr), CREATE_UNICODE_ENVIRONMENT, (LPCWSTR)env.c_str(), workDir.empty() ? (LPCWSTR)NULL : (LPCWSTR)workDir.c_str(), &(p->si), &(p->pi)))
{
if (this->redirectStdIn)
{
CloseHandle(p->stdin_strm);
CloseHandle(p->si->hStdInput);
}
if (this->redirectStdOut)
{
CloseHandle(p->stdout_strm);
CloseHandle(p->si->hStdOutput);
}
if (this->redirectStdErr)
{
CloseHandle(p->stderr_strm);
CloseHandle(p->si->hStdError);
}
return false;
}
/*
BOOL
WINAPI
CreateProcessW(
_In_opt_ LPCWSTR lpApplicationName,
_Inout_opt_ LPWSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCWSTR lpCurrentDirectory,
_In_ LPSTARTUPINFOW lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation
);
*/
return false;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return false;
@@ -352,34 +534,34 @@ namespace Tesses::Framework::Platform {
#endif
}
Tesses::Framework::Streams::Stream* Process::GetStdinStream(bool closeUnderlying)
Tesses::Framework::Streams::Stream* Process::GetStdinStream()
{
#if defined(_WIN32)
return nullptr;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return nullptr;
#else
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdin_strm,true,closeUnderlying);
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdin_strm,true);
#endif
}
Tesses::Framework::Streams::Stream* Process::GetStdoutStream(bool closeUnderlying)
Tesses::Framework::Streams::Stream* Process::GetStdoutStream()
{
#if defined(_WIN32)
return nullptr;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return nullptr;
#else
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdout_strm,false,closeUnderlying);
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdout_strm,false);
#endif
}
Tesses::Framework::Streams::Stream* Process::GetStderrStream(bool closeUnderlying)
Tesses::Framework::Streams::Stream* Process::GetStderrStream()
{
#if defined(_WIN32)
return nullptr;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return nullptr;
#else
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stderr_strm,false,closeUnderlying);
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stderr_strm,false);
#endif
}

View File

@@ -6,6 +6,7 @@ using HttpUtils = Tesses::Framework::Http::HttpUtils;
#if defined(TESSESFRAMEWORK_ENABLE_NETWORKING)
#if defined(GEKKO)
#define ss_family sin_family
@@ -24,9 +25,11 @@ using HttpUtils = Tesses::Framework::Http::HttpUtils;
#include <winsock2.h>
#include <iphlpapi.h>
#include <windows.h>
#include <afunix.h>
#undef min
#pragma comment(lib, "ws2_32.lib")
#else
extern "C" {
#include <netinet/in.h>
#include <netinet/tcp.h>

View File

@@ -114,7 +114,7 @@ namespace Tesses::Framework::Streams {
strm.Flush();
#if defined(_WIN32)
delete buffer;
delete[] buffer;
#endif
}
Stream::~Stream()

View File

@@ -0,0 +1,270 @@
#include "TessesFramework/Text/StringConverter.hpp"
namespace Tesses::Framework::Text::StringConverter {
void UTF8::FromUTF16(std::basic_string<char>& utf8, const std::basic_string<char16_t>& utf16)
{
for (size_t i=0; i < utf16.size();i++)
{
char32_t c = utf16[i];
if ((c & 0xFC00) == 0xD800)
{
c = (c & 0x03FF) << 10;
i++;
if (i >= utf16.size()) return;
char32_t c2 = utf16[i];
if ((c2 & 0xFC00) != 0xDC00) continue;
c |= (c2 & 0x03FF);
c += 0x10000;
}
if (c <= 0x7F)
{
utf8.push_back((char)c);
}
else if (c >= 0x80 && c <= 0x7FF)
{
uint8_t high = 0b11000000 | ((c >> 6) & 0b00011111);
uint8_t low = 0b10000000 | (c & 0b00111111);
utf8.push_back((char)high);
utf8.push_back((char)low);
}
else if (c >= 0x800 && c <= 0xFFFF)
{
uint8_t highest = 0b11100000 | ((c >> 12) & 0b00001111);
uint8_t high = 0b10000000 | ((c >> 6) & 0b00111111);
uint8_t low = 0b10000000 | (c & 0b00111111);
utf8.push_back((char)highest);
utf8.push_back((char)high);
utf8.push_back((char)low);
}
else if (c >= 0x010000 && c <= 0x10FFFF)
{
uint8_t highest = 0b11110000 | ((c >> 18) & 0b00000111);
uint8_t high = 0b10000000 | ((c >> 12) & 0b00111111);
uint8_t low = 0b10000000 | ((c >> 6) & 0b00111111);
uint8_t lowest = 0b10000000 | (c & 0b00111111);
utf8.push_back((char)highest);
utf8.push_back((char)high);
utf8.push_back((char)low);
utf8.push_back((char)lowest);
}
}
}
void UTF8::FromUTF32(std::basic_string<char>& utf8, const std::basic_string<char32_t>& utf32)
{
for (auto c : utf32)
{
if (c <= 0x7F)
{
utf8.push_back((char)c);
}
else if (c >= 0x80 && c <= 0x7FF)
{
uint8_t high = 0b11000000 | ((c >> 6) & 0b00011111);
uint8_t low = 0b10000000 | (c & 0b00111111);
utf8.push_back((char)high);
utf8.push_back((char)low);
}
else if (c >= 0x800 && c <= 0xFFFF)
{
uint8_t highest = 0b11100000 | ((c >> 12) & 0b00001111);
uint8_t high = 0b10000000 | ((c >> 6) & 0b00111111);
uint8_t low = 0b10000000 | (c & 0b00111111);
utf8.push_back((char)highest);
utf8.push_back((char)high);
utf8.push_back((char)low);
}
else if (c >= 0x010000 && c <= 0x10FFFF)
{
uint8_t highest = 0b11110000 | ((c >> 18) & 0b00000111);
uint8_t high = 0b10000000 | ((c >> 12) & 0b00111111);
uint8_t low = 0b10000000 | ((c >> 6) & 0b00111111);
uint8_t lowest = 0b10000000 | (c & 0b00111111);
utf8.push_back((char)highest);
utf8.push_back((char)high);
utf8.push_back((char)low);
utf8.push_back((char)lowest);
}
}
}
void UTF16::FromUTF8(std::basic_string<char16_t>& utf16, const std::basic_string<char>& utf8)
{
for (size_t i = 0; i < utf8.size();i++)
{
uint8_t c = (uint8_t)utf8[i];
char32_t cres = 0;
if (c <= 127)
{
cres = (char32_t)c;
}
else if ((c & 0b11100000) == 0b11000000)
{
if (i + 1 < utf8.size())
{
uint8_t c2 = (uint8_t)utf8[++i];
cres |= c2 & 0b00111111;
cres |= (c & 0b00011111) << 6;
}
else {
i++;
continue;
};
}
else if ((c & 0b11110000) == 0b11100000)
{
if (i + 2 < utf8.size())
{
uint8_t c2 = (uint8_t)utf8[++i];
uint8_t c3 = (uint8_t)utf8[++i];
cres |= c3 & 0b00111111;
cres |= (c2 & 0b00111111) << 6;
cres |= (c & 0b00001111) << 12;
}
else { i += 2; continue; }
}
else if ((c & 0b11111000) == 0b11110000)
{
if (i + 3 < utf8.size())
{
uint8_t c2 = (uint8_t)utf8[++i];
uint8_t c3 = (uint8_t)utf8[++i];
uint8_t c4 = (uint8_t)utf8[++i];
cres |= c4 & 0b00111111;
cres |= (c3 & 0b00111111) << 6;
cres |= (c2 & 0b00111111) << 12;
cres |= (c & 0b00000111) << 18;
}
else { i += 3; continue; }
}
if (cres >= 0x10000 && cres <= 0x10FFFF)
{
auto subtracted = cres - 0x10000;
auto high = (0x3FF & (subtracted >> 10)) | 0xD800;
auto low = (0x3FF & subtracted) | 0xDC00;
utf16.push_back(high);
utf16.push_back(low);
}
else {
utf16.push_back((char16_t)cres);
}
}
}
void UTF16::FromUTF32(std::basic_string<char16_t>& utf16, const std::basic_string<char32_t>& utf32)
{
for (auto cres : utf32)
{
if (cres >= 0x10000 && cres <= 0x10FFFF)
{
auto subtracted = cres - 0x10000;
auto high = (0x3FF & (subtracted >> 10)) | 0xD800;
auto low = (0x3FF & subtracted) | 0xDC00;
utf16.push_back(high);
utf16.push_back(low);
}
else {
utf16.push_back((char16_t)cres);
}
}
}
void UTF32::FromUTF8(std::basic_string<char32_t>& utf32, const std::basic_string<char>& utf8)
{
for (size_t i = 0; i < utf8.size();i++)
{
uint8_t c = (uint8_t)utf8[i];
char32_t cres = 0;
if (c <= 127)
{
cres=(char32_t)c;
}
else if ((c & 0b11100000) == 0b11000000)
{
if (i + 1 < utf8.size())
{
uint8_t c2 = (uint8_t)utf8[++i];
cres |= c2 & 0b00111111;
cres |= (c & 0b00011111) << 6;
}
else {
i++;
continue;
};
}
else if ((c & 0b11110000) == 0b11100000)
{
if (i + 2 < utf8.size())
{
uint8_t c2 = (uint8_t)utf8[++i];
uint8_t c3 = (uint8_t)utf8[++i];
cres |= c3 & 0b00111111;
cres |= (c2 & 0b00111111) << 6;
cres |= (c & 0b00001111) << 12;
}
else { i += 2; continue; }
}
else if ((c & 0b11111000) == 0b11110000)
{
if (i + 3 < utf8.size())
{
uint8_t c2 = (uint8_t)utf8[++i];
uint8_t c3 = (uint8_t)utf8[++i];
uint8_t c4 = (uint8_t)utf8[++i];
cres |= c4 & 0b00111111;
cres |= (c3 & 0b00111111) << 6;
cres |= (c2 & 0b00111111) << 12;
cres |= (c & 0b00000111) << 18;
}
else { i += 3; continue; }
}
utf32.push_back(cres);
}
}
void UTF32::FromUTF16(std::basic_string<char32_t>& utf32, const std::basic_string<char16_t>& utf16)
{
for (size_t i = 0; i < utf16.size();i++)
{
char32_t c = utf16[i];
if ((c & 0xFC00) == 0xD800)
{
c = (c & 0x03FF) << 10;
i++;
if (i >= utf16.size()) return;
char32_t c2 = utf16[i];
if ((c2 & 0xFC00) != 0xDC00) continue;
c |= (c2 & 0x03FF);
c += 0x10000;
}
utf32.push_back(c);
}
}
}