Processing (Windows): prefers NT APIs

This commit is contained in:
李通洲
2026-03-09 20:24:19 +08:00
parent 60d343ca14
commit 6370485dcb
2 changed files with 58 additions and 18 deletions
+38 -18
View File
@@ -140,40 +140,60 @@ const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer)
int32_t timeout = instance.config.general.processingTimeout;
FF_AUTO_CLOSE_FD HANDLE hProcess = handle->pid;
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = handle->pipeRead;
FF_AUTO_CLOSE_FD HANDLE hReadEvent = NULL;
handle->pid = INVALID_HANDLE_VALUE;
handle->pipeRead = INVALID_HANDLE_VALUE;
if (timeout >= 0 && !NT_SUCCESS(NtCreateEvent(&hReadEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE)))
return "NtCreateEvent() failed";
char str[FF_PIPE_BUFSIZ];
DWORD nRead = 0;
OVERLAPPED overlapped = {};
// ReadFile always completes synchronously if the pipe is not created with FILE_FLAG_OVERLAPPED
uint32_t nRead = 0;
IO_STATUS_BLOCK iosb = {};
do
{
if (!ReadFile(hChildPipeRead, str, sizeof(str), &nRead, &overlapped))
NTSTATUS status = NtReadFile(
hChildPipeRead,
hReadEvent,
NULL,
NULL,
&iosb,
str,
(ULONG) sizeof(str),
NULL,
NULL
);
if (status == STATUS_PENDING)
{
switch (GetLastError())
switch (NtWaitForSingleObject(hReadEvent, TRUE, &(LARGE_INTEGER) { .QuadPart = (int64_t) timeout * -10000 }))
{
case ERROR_IO_PENDING:
if (!GetOverlappedResultEx(hChildPipeRead, &overlapped, &nRead, timeout < 0 ? INFINITE : (DWORD) timeout, FALSE))
{
if (GetLastError() == ERROR_BROKEN_PIPE)
return NULL;
CancelIo(hChildPipeRead);
TerminateProcess(hProcess, 1);
return "GetOverlappedResultEx(hChildPipeRead) failed";
}
case STATUS_WAIT_0:
status = iosb.Status;
break;
case ERROR_BROKEN_PIPE:
goto exit;
case STATUS_TIMEOUT:
CancelIo(hChildPipeRead);
TerminateProcess(hProcess, 1);
return "NtReadFile(hChildPipeRead) timed out";
default:
CancelIo(hChildPipeRead);
TerminateProcess(hProcess, 1);
return "ReadFile(hChildPipeRead) failed";
return "WaitForSingleObject(hReadEvent) failed";
}
}
if (status == STATUS_PIPE_BROKEN || status == STATUS_END_OF_FILE)
goto exit;
if (!NT_SUCCESS(status))
{
CancelIo(hChildPipeRead);
TerminateProcess(hProcess, 1);
return "NtReadFile(hChildPipeRead) failed";
}
nRead = (uint32_t) iosb.Information;
ffStrbufAppendNS(buffer, nRead, str);
} while (nRead > 0);
+20
View File
@@ -893,3 +893,23 @@ NTSYSAPI NTSTATUS NTAPI NtQueryInformationToken(
_Out_ PULONG ReturnLength
);
#define NtCurrentProcessToken() ((HANDLE)(LONG_PTR)-4) // for NtQueryInformationToken only; Windows 8+
NTSYSAPI NTSTATUS NTAPI NtReadFile(
_In_ HANDLE FileHandle,
_In_opt_ HANDLE Event,
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_Out_writes_bytes_(Length) PVOID Buffer,
_In_ ULONG Length,
_In_opt_ PLARGE_INTEGER ByteOffset,
_In_opt_ PULONG Key
);
NTSYSAPI NTSTATUS NTAPI NtCreateEvent(
_Out_ PHANDLE EventHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ EVENT_TYPE EventType,
_In_ BOOLEAN InitialState
);