2022-10-08 16:04:55 +08:00
|
|
|
#include "fastfetch.h"
|
|
|
|
|
#include "common/processing.h"
|
2023-07-10 21:02:13 +08:00
|
|
|
#include "common/io/io.h"
|
2022-10-08 16:04:55 +08:00
|
|
|
|
|
|
|
|
#include <Windows.h>
|
|
|
|
|
|
2023-12-04 15:10:58 +08:00
|
|
|
enum { FF_PIPE_BUFSIZ = 8192 };
|
2023-07-11 16:00:58 +08:00
|
|
|
|
2023-07-10 21:02:13 +08:00
|
|
|
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
|
2022-10-08 16:04:55 +08:00
|
|
|
{
|
2023-10-25 13:39:13 +08:00
|
|
|
int timeout = instance.config.general.processingTimeout;
|
2022-10-08 16:04:55 +08:00
|
|
|
|
2023-07-11 16:00:58 +08:00
|
|
|
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = CreateNamedPipeW(
|
|
|
|
|
L"\\\\.\\pipe\\LOCAL\\",
|
|
|
|
|
PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE | (timeout < 0 ? 0 : FILE_FLAG_OVERLAPPED),
|
|
|
|
|
0,
|
|
|
|
|
1,
|
|
|
|
|
FF_PIPE_BUFSIZ,
|
|
|
|
|
FF_PIPE_BUFSIZ,
|
|
|
|
|
0,
|
|
|
|
|
NULL
|
|
|
|
|
);
|
|
|
|
|
if (hChildPipeRead == INVALID_HANDLE_VALUE)
|
|
|
|
|
return "CreateNamedPipeW(L\"\\\\.\\pipe\\LOCAL\\\") failed";
|
2022-10-08 16:04:55 +08:00
|
|
|
|
2023-07-11 16:00:58 +08:00
|
|
|
HANDLE hChildPipeWrite = CreateFileW(
|
|
|
|
|
L"\\\\.\\pipe\\LOCAL\\",
|
|
|
|
|
GENERIC_WRITE,
|
|
|
|
|
0,
|
|
|
|
|
&(SECURITY_ATTRIBUTES){
|
|
|
|
|
.nLength = sizeof(SECURITY_ATTRIBUTES),
|
|
|
|
|
.lpSecurityDescriptor = NULL,
|
|
|
|
|
.bInheritHandle = TRUE,
|
|
|
|
|
},
|
|
|
|
|
OPEN_EXISTING,
|
|
|
|
|
0,
|
|
|
|
|
NULL
|
|
|
|
|
);
|
|
|
|
|
if (hChildPipeWrite == INVALID_HANDLE_VALUE)
|
|
|
|
|
return "CreateFileW(L\"\\\\.\\pipe\\LOCAL\\\") failed";
|
2022-10-08 16:04:55 +08:00
|
|
|
|
|
|
|
|
PROCESS_INFORMATION piProcInfo = {0};
|
|
|
|
|
|
2022-11-13 00:04:34 +08:00
|
|
|
BOOL success;
|
2022-10-08 16:04:55 +08:00
|
|
|
|
2022-11-13 00:04:34 +08:00
|
|
|
{
|
2023-07-11 16:00:58 +08:00
|
|
|
STARTUPINFOA siStartInfo = {
|
|
|
|
|
.cb = sizeof(siStartInfo),
|
|
|
|
|
.dwFlags = STARTF_USESTDHANDLES,
|
|
|
|
|
};
|
|
|
|
|
if (useStdErr)
|
|
|
|
|
siStartInfo.hStdError = hChildPipeWrite;
|
|
|
|
|
else
|
|
|
|
|
siStartInfo.hStdOutput = hChildPipeWrite;
|
|
|
|
|
|
2023-04-15 15:29:54 +08:00
|
|
|
FF_STRBUF_AUTO_DESTROY cmdline = ffStrbufCreateF("\"%s\"", argv[0]);
|
2022-11-13 00:04:34 +08:00
|
|
|
for(char* const* parg = &argv[1]; *parg; ++parg)
|
|
|
|
|
{
|
|
|
|
|
ffStrbufAppendC(&cmdline, ' ');
|
|
|
|
|
ffStrbufAppendS(&cmdline, *parg);
|
|
|
|
|
}
|
2022-10-08 16:04:55 +08:00
|
|
|
|
2022-11-13 00:04:34 +08:00
|
|
|
success = CreateProcessA(
|
|
|
|
|
NULL, // application name
|
|
|
|
|
cmdline.chars, // command line
|
|
|
|
|
NULL, // process security attributes
|
|
|
|
|
NULL, // primary thread security attributes
|
|
|
|
|
TRUE, // handles are inherited
|
|
|
|
|
0, // creation flags
|
|
|
|
|
NULL, // use parent's environment
|
|
|
|
|
NULL, // use parent's current directory
|
|
|
|
|
&siStartInfo, // STARTUPINFO pointer
|
|
|
|
|
&piProcInfo // receives PROCESS_INFORMATION
|
|
|
|
|
);
|
|
|
|
|
}
|
2022-10-13 20:06:54 +08:00
|
|
|
|
2023-07-10 09:36:33 +08:00
|
|
|
CloseHandle(hChildPipeWrite);
|
2022-10-08 16:04:55 +08:00
|
|
|
if(!success)
|
|
|
|
|
return "CreateProcessA() failed";
|
2023-07-10 09:36:33 +08:00
|
|
|
|
2023-07-16 18:57:33 +08:00
|
|
|
FF_AUTO_CLOSE_FD HANDLE hProcess = piProcInfo.hProcess;
|
|
|
|
|
FF_MAYBE_UNUSED FF_AUTO_CLOSE_FD HANDLE hThread = piProcInfo.hThread;
|
|
|
|
|
|
2023-07-11 16:00:58 +08:00
|
|
|
char str[FF_PIPE_BUFSIZ];
|
|
|
|
|
DWORD nRead = 0;
|
2024-01-13 13:38:53 +08:00
|
|
|
OVERLAPPED overlapped = { };
|
2023-07-11 16:00:58 +08:00
|
|
|
// ReadFile always completes synchronously if the pipe is not created with FILE_FLAG_OVERLAPPED
|
2023-07-11 19:45:16 +08:00
|
|
|
do
|
2023-07-10 09:36:33 +08:00
|
|
|
{
|
2023-07-11 16:00:58 +08:00
|
|
|
if (!ReadFile(hChildPipeRead, str, sizeof(str), &nRead, &overlapped))
|
|
|
|
|
{
|
2023-07-11 19:45:16 +08:00
|
|
|
switch (GetLastError())
|
2023-07-11 16:00:58 +08:00
|
|
|
{
|
2023-07-11 19:45:16 +08:00
|
|
|
case ERROR_IO_PENDING:
|
2024-01-13 13:38:53 +08:00
|
|
|
if (!timeout || WaitForSingleObject(hChildPipeRead, (DWORD) timeout) != WAIT_OBJECT_0)
|
2023-07-16 18:57:33 +08:00
|
|
|
{
|
|
|
|
|
CancelIo(hChildPipeRead);
|
|
|
|
|
TerminateProcess(hProcess, 1);
|
2024-04-30 10:33:21 +08:00
|
|
|
return "WaitForSingleObject(hChildPipeRead) failed or timeout (try increasing --processing-timeout)";
|
2023-07-16 18:57:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!GetOverlappedResult(hChildPipeRead, &overlapped, &nRead, FALSE))
|
2023-07-11 19:45:16 +08:00
|
|
|
{
|
|
|
|
|
if (GetLastError() == ERROR_BROKEN_PIPE)
|
|
|
|
|
return NULL;
|
2023-07-16 18:57:33 +08:00
|
|
|
|
2023-07-11 19:45:16 +08:00
|
|
|
CancelIo(hChildPipeRead);
|
2023-07-16 18:57:33 +08:00
|
|
|
TerminateProcess(hProcess, 1);
|
|
|
|
|
return "GetOverlappedResult(hChildPipeRead) failed";
|
2023-07-11 19:45:16 +08:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ERROR_BROKEN_PIPE:
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
default:
|
2023-07-11 16:00:58 +08:00
|
|
|
CancelIo(hChildPipeRead);
|
2023-07-16 18:57:33 +08:00
|
|
|
TerminateProcess(hProcess, 1);
|
2023-07-11 19:45:16 +08:00
|
|
|
return "ReadFile(hChildPipeRead) failed";
|
2023-07-11 16:00:58 +08:00
|
|
|
}
|
|
|
|
|
}
|
2023-07-11 19:45:16 +08:00
|
|
|
ffStrbufAppendNS(buffer, nRead, str);
|
|
|
|
|
} while (nRead > 0);
|
2023-07-10 09:36:33 +08:00
|
|
|
|
2022-10-08 16:04:55 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|