From 2f7df12fc863f28bea429c73ad222cd364b43e0f Mon Sep 17 00:00:00 2001 From: Decaf Code Date: Tue, 20 Nov 2018 19:49:38 -0500 Subject: [PATCH] hook/iohook.c: Fix DeviceIoControl error path --- hook/iohook.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/hook/iohook.c b/hook/iohook.c index 5e54255..0adcc41 100644 --- a/hook/iohook.c +++ b/hook/iohook.c @@ -525,12 +525,15 @@ static HRESULT iohook_invoke_real_ioctl(struct irp *irp) &nread, irp->ovl); + /* Must be propagated even if there is an error, see + iohook_DeviceIoControl. */ + + irp->read.pos = nread; + if (!ok) { return HRESULT_FROM_WIN32(GetLastError()); } - irp->read.pos = nread; - return S_OK; } @@ -905,13 +908,23 @@ static BOOL WINAPI iohook_DeviceIoControl( hr = iohook_invoke_next(&irp); - if (FAILED(hr)) { - return hr_propagate_win32(hr, FALSE); - } - assert(irp.write.pos <= irp.write.nbytes); assert(irp.read.pos <= irp.read.nbytes); + if (FAILED(hr)) { + /* Special case: ERROR_MORE_DATA requires this out parameter to be + propagated, per MSDN. All ioctls in the entire process that go via + the win32 API (as opposed to the NTDLL API) get redirected through + iohook, and the Windows XP version of DirectSound is known to rely + on this behavior. */ + + if (lpBytesReturned != NULL) { + *lpBytesReturned = (DWORD) irp.read.pos; + } + + return hr_propagate_win32(hr, FALSE); + } + return iohook_overlapped_result( lpBytesReturned, lpOverlapped,