Skip to content

Commit 6370485

Browse files
committed
Processing (Windows): prefers NT APIs
1 parent 60d343c commit 6370485

2 files changed

Lines changed: 58 additions & 18 deletions

File tree

src/common/impl/processing_windows.c

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -140,40 +140,60 @@ const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer)
140140
int32_t timeout = instance.config.general.processingTimeout;
141141
FF_AUTO_CLOSE_FD HANDLE hProcess = handle->pid;
142142
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = handle->pipeRead;
143+
FF_AUTO_CLOSE_FD HANDLE hReadEvent = NULL;
143144
handle->pid = INVALID_HANDLE_VALUE;
144145
handle->pipeRead = INVALID_HANDLE_VALUE;
145146

147+
if (timeout >= 0 && !NT_SUCCESS(NtCreateEvent(&hReadEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE)))
148+
return "NtCreateEvent() failed";
149+
146150
char str[FF_PIPE_BUFSIZ];
147-
DWORD nRead = 0;
148-
OVERLAPPED overlapped = {};
149-
// ReadFile always completes synchronously if the pipe is not created with FILE_FLAG_OVERLAPPED
151+
uint32_t nRead = 0;
152+
IO_STATUS_BLOCK iosb = {};
150153
do
151154
{
152-
if (!ReadFile(hChildPipeRead, str, sizeof(str), &nRead, &overlapped))
155+
NTSTATUS status = NtReadFile(
156+
hChildPipeRead,
157+
hReadEvent,
158+
NULL,
159+
NULL,
160+
&iosb,
161+
str,
162+
(ULONG) sizeof(str),
163+
NULL,
164+
NULL
165+
);
166+
if (status == STATUS_PENDING)
153167
{
154-
switch (GetLastError())
168+
switch (NtWaitForSingleObject(hReadEvent, TRUE, &(LARGE_INTEGER) { .QuadPart = (int64_t) timeout * -10000 }))
155169
{
156-
case ERROR_IO_PENDING:
157-
if (!GetOverlappedResultEx(hChildPipeRead, &overlapped, &nRead, timeout < 0 ? INFINITE : (DWORD) timeout, FALSE))
158-
{
159-
if (GetLastError() == ERROR_BROKEN_PIPE)
160-
return NULL;
161-
162-
CancelIo(hChildPipeRead);
163-
TerminateProcess(hProcess, 1);
164-
return "GetOverlappedResultEx(hChildPipeRead) failed";
165-
}
170+
case STATUS_WAIT_0:
171+
status = iosb.Status;
166172
break;
167173

168-
case ERROR_BROKEN_PIPE:
169-
goto exit;
174+
case STATUS_TIMEOUT:
175+
CancelIo(hChildPipeRead);
176+
TerminateProcess(hProcess, 1);
177+
return "NtReadFile(hChildPipeRead) timed out";
170178

171179
default:
172180
CancelIo(hChildPipeRead);
173181
TerminateProcess(hProcess, 1);
174-
return "ReadFile(hChildPipeRead) failed";
182+
return "WaitForSingleObject(hReadEvent) failed";
175183
}
176184
}
185+
186+
if (status == STATUS_PIPE_BROKEN || status == STATUS_END_OF_FILE)
187+
goto exit;
188+
189+
if (!NT_SUCCESS(status))
190+
{
191+
CancelIo(hChildPipeRead);
192+
TerminateProcess(hProcess, 1);
193+
return "NtReadFile(hChildPipeRead) failed";
194+
}
195+
196+
nRead = (uint32_t) iosb.Information;
177197
ffStrbufAppendNS(buffer, nRead, str);
178198
} while (nRead > 0);
179199

src/common/windows/nt.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,3 +893,23 @@ NTSYSAPI NTSTATUS NTAPI NtQueryInformationToken(
893893
_Out_ PULONG ReturnLength
894894
);
895895
#define NtCurrentProcessToken() ((HANDLE)(LONG_PTR)-4) // for NtQueryInformationToken only; Windows 8+
896+
897+
NTSYSAPI NTSTATUS NTAPI NtReadFile(
898+
_In_ HANDLE FileHandle,
899+
_In_opt_ HANDLE Event,
900+
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
901+
_In_opt_ PVOID ApcContext,
902+
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
903+
_Out_writes_bytes_(Length) PVOID Buffer,
904+
_In_ ULONG Length,
905+
_In_opt_ PLARGE_INTEGER ByteOffset,
906+
_In_opt_ PULONG Key
907+
);
908+
909+
NTSYSAPI NTSTATUS NTAPI NtCreateEvent(
910+
_Out_ PHANDLE EventHandle,
911+
_In_ ACCESS_MASK DesiredAccess,
912+
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
913+
_In_ EVENT_TYPE EventType,
914+
_In_ BOOLEAN InitialState
915+
);

0 commit comments

Comments
 (0)