Skip to content

Commit 92aa8a7

Browse files
+ DeviceIoControl hang patch (winfsp/winspd#10 (comment))
1 parent aab46b4 commit 92aa8a7

File tree

5 files changed

+169
-44
lines changed

5 files changed

+169
-44
lines changed

vanilla/inc/winspd/ioctl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,8 @@ DWORD SpdIoctlTransact(HANDLE DeviceHandle,
215215
UINT32 Btl,
216216
SPD_IOCTL_TRANSACT_RSP *Rsp,
217217
SPD_IOCTL_TRANSACT_REQ *Req,
218-
PVOID DataBuffer);
218+
PVOID DataBuffer,
219+
OVERLAPPED *Overlapped);
219220
DWORD SpdIoctlSetTransactProcessId(HANDLE DeviceHandle,
220221
UINT32 Btl,
221222
ULONG ProcessId);

vanilla/src/shared/ioctl.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,8 @@ DWORD SpdIoctlTransact(HANDLE DeviceHandle,
412412
UINT32 Btl,
413413
SPD_IOCTL_TRANSACT_RSP *Rsp,
414414
SPD_IOCTL_TRANSACT_REQ *Req,
415-
PVOID DataBuffer)
415+
PVOID DataBuffer,
416+
OVERLAPPED *Overlapped)
416417
{
417418
SPD_IOCTL_TRANSACT_PARAMS Params;
418419
DWORD BytesTransferred;
@@ -452,13 +453,26 @@ DWORD SpdIoctlTransact(HANDLE DeviceHandle,
452453
* FILE_FLAG_OVERLAPPED flag we ensure that the unproductive serialization
453454
* does not happen.
454455
*/
456+
// DeviceIoControl() can hang if lpOverlapped is NULL
455457
if (!DeviceIoControl(DeviceHandle, IOCTL_MINIPORT_PROCESS_SERVICE_IRP,
456458
&Params, sizeof Params,
457459
&Params, sizeof Params,
458-
&BytesTransferred, 0))
460+
&BytesTransferred, Overlapped))
459461
{
460462
Error = GetLastError();
461-
goto exit;
463+
if (ERROR_IO_PENDING == Error)
464+
{
465+
if (!GetOverlappedResult(DeviceHandle, Overlapped,
466+
&BytesTransferred, TRUE))
467+
{
468+
Error = GetLastError();
469+
goto exit;
470+
}
471+
}
472+
else
473+
{
474+
goto exit;
475+
}
462476
}
463477

464478
if (0 != Req)

vanilla/src/shared/stghandle.c

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -278,24 +278,20 @@ static DWORD SpdStorageUnitHandleTransactPipe(HANDLE Handle,
278278
UINT32 Btl,
279279
SPD_IOCTL_TRANSACT_RSP *Rsp,
280280
SPD_IOCTL_TRANSACT_REQ *Req,
281-
PVOID DataBuffer)
281+
PVOID DataBuffer,
282+
OVERLAPPED *Overlapped)
282283
{
283284
STORAGE_UNIT *StorageUnit = Handle;
284285
LONG Connected;
285286
ULONG DataLength;
286287
TRANSACT_MSG *Msg = 0;
287-
OVERLAPPED Overlapped;
288288
DWORD BytesTransferred;
289289
DWORD Error;
290290

291291
if ((0 == Req && 0 == Rsp) ||
292292
(0 != Req && 0 == DataBuffer))
293293
return ERROR_INVALID_PARAMETER;
294294

295-
Error = SpdOverlappedInit(&Overlapped);
296-
if (ERROR_SUCCESS != Error)
297-
goto exit;
298-
299295
AcquireSRWLockShared(&StorageUnitLock);
300296
Error = StorageUnit == StorageUnits[SPD_INDEX_FROM_BTL(Btl)] ?
301297
ERROR_SUCCESS : ERROR_FILE_NOT_FOUND;
@@ -316,16 +312,16 @@ static DWORD SpdStorageUnitHandleTransactPipe(HANDLE Handle,
316312
{
317313
Error = WaitOverlappedResult(
318314
StorageUnit->Event,
319-
ConnectNamedPipe(StorageUnit->Pipe, &Overlapped),
320-
StorageUnit->Pipe, &Overlapped, &BytesTransferred);
315+
ConnectNamedPipe(StorageUnit->Pipe, Overlapped),
316+
StorageUnit->Pipe, Overlapped, &BytesTransferred);
321317
if (ERROR_SUCCESS == Error || ERROR_PIPE_CONNECTED == Error)
322318
{
323319
Error = WaitOverlappedResult(
324320
StorageUnit->Event,
325321
WriteFile(StorageUnit->Pipe,
326322
&StorageUnit->StorageUnitParams, sizeof StorageUnit->StorageUnitParams,
327-
0, &Overlapped),
328-
StorageUnit->Pipe, &Overlapped, &BytesTransferred);
323+
0, Overlapped),
324+
StorageUnit->Pipe, Overlapped, &BytesTransferred);
329325
if (ERROR_SUCCESS == Error)
330326
{
331327
StorageUnit->Connected = -StorageUnit->Connected;
@@ -354,8 +350,8 @@ static DWORD SpdStorageUnitHandleTransactPipe(HANDLE Handle,
354350
memcpy(Msg + 1, DataBuffer, DataLength);
355351
Error = WaitOverlappedResult(
356352
StorageUnit->Event,
357-
WriteFile(StorageUnit->Pipe, Msg, sizeof(TRANSACT_MSG) + DataLength, 0, &Overlapped),
358-
StorageUnit->Pipe, &Overlapped, &BytesTransferred);
353+
WriteFile(StorageUnit->Pipe, Msg, sizeof(TRANSACT_MSG) + DataLength, 0, Overlapped),
354+
StorageUnit->Pipe, Overlapped, &BytesTransferred);
359355
if (ERROR_SUCCESS != Error)
360356
goto disconnect;
361357
}
@@ -365,8 +361,8 @@ static DWORD SpdStorageUnitHandleTransactPipe(HANDLE Handle,
365361
Error = WaitOverlappedResult(
366362
StorageUnit->Event,
367363
ReadFile(StorageUnit->Pipe,
368-
Msg, sizeof(TRANSACT_MSG) + StorageUnit->StorageUnitParams.MaxTransferLength, 0, &Overlapped),
369-
StorageUnit->Pipe, &Overlapped, &BytesTransferred);
364+
Msg, sizeof(TRANSACT_MSG) + StorageUnit->StorageUnitParams.MaxTransferLength, 0, Overlapped),
365+
StorageUnit->Pipe, Overlapped, &BytesTransferred);
370366
if (ERROR_SUCCESS != Error)
371367
goto disconnect;
372368

@@ -418,8 +414,6 @@ static DWORD SpdStorageUnitHandleTransactPipe(HANDLE Handle,
418414
exit:
419415
MemFree(Msg);
420416

421-
SpdOverlappedFini(&Overlapped);
422-
423417
return Error;
424418

425419
disconnect:
@@ -544,12 +538,29 @@ DWORD SpdStorageUnitHandleTransact(HANDLE Handle,
544538
UINT32 Btl,
545539
SPD_IOCTL_TRANSACT_RSP *Rsp,
546540
SPD_IOCTL_TRANSACT_REQ *Req,
547-
PVOID DataBuffer)
541+
PVOID DataBuffer,
542+
OVERLAPPED *Overlapped)
548543
{
544+
OVERLAPPED TempOverlapped = { 0 };
545+
DWORD Error;
546+
547+
if (Overlapped == NULL)
548+
{
549+
Error = SpdOverlappedInit(&TempOverlapped);
550+
if (ERROR_SUCCESS != Error)
551+
return Error;
552+
553+
Overlapped = &TempOverlapped;
554+
}
555+
549556
if (IsPipeHandle(Handle))
550-
return SpdStorageUnitHandleTransactPipe(GetPipeHandle(Handle), Btl, Rsp, Req, DataBuffer);
557+
Error = SpdStorageUnitHandleTransactPipe(GetPipeHandle(Handle), Btl, Rsp, Req, DataBuffer, Overlapped);
551558
else
552-
return SpdIoctlTransact(GetDeviceHandle(Handle), Btl, Rsp, Req, DataBuffer);
559+
Error = SpdIoctlTransact(GetDeviceHandle(Handle), Btl, Rsp, Req, DataBuffer, Overlapped);
560+
561+
SpdOverlappedFini(&TempOverlapped);
562+
563+
return Error;
553564
}
554565

555566
DWORD SpdStorageUnitHandleShutdown(HANDLE Handle,

vanilla/src/shared/stgunit.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ DWORD SpdStorageUnitHandleTransact(HANDLE Handle,
2828
UINT32 Btl,
2929
SPD_IOCTL_TRANSACT_RSP *Rsp,
3030
SPD_IOCTL_TRANSACT_REQ *Req,
31-
PVOID DataBuffer);
31+
PVOID DataBuffer,
32+
OVERLAPPED *Overlapped);
3233
DWORD SpdStorageUnitHandleShutdown(HANDLE Handle,
3334
const GUID *Guid);
3435
DWORD SpdStorageUnitHandleClose(HANDLE Handle);
@@ -135,6 +136,7 @@ static DWORD WINAPI SpdStorageUnitDispatcherThread(PVOID StorageUnit0)
135136
SPD_IOCTL_TRANSACT_RSP ResponseBuf, *Response;
136137
SPD_STORAGE_UNIT_OPERATION_CONTEXT OperationContext;
137138
PVOID DataBuffer = 0;
139+
OVERLAPPED Overlapped;
138140
HANDLE DispatcherThread = 0;
139141
BOOLEAN Complete;
140142
DWORD Error;
@@ -146,6 +148,10 @@ static DWORD WINAPI SpdStorageUnitDispatcherThread(PVOID StorageUnit0)
146148
goto exit;
147149
}
148150

151+
Error = SpdOverlappedInit(&Overlapped);
152+
if (ERROR_SUCCESS != Error)
153+
goto exit;
154+
149155
OperationContext.Request = &RequestBuf;
150156
OperationContext.Response = &ResponseBuf;
151157
OperationContext.DataBuffer = DataBuffer;
@@ -165,9 +171,15 @@ static DWORD WINAPI SpdStorageUnitDispatcherThread(PVOID StorageUnit0)
165171
Response = 0;
166172
for (;;)
167173
{
174+
if (!ResetEvent(Overlapped.hEvent))
175+
{
176+
Error = GetLastError();
177+
goto exit;
178+
}
179+
168180
memset(Request, 0, sizeof *Request);
169181
Error = SpdStorageUnitHandleTransact(StorageUnit->Handle,
170-
StorageUnit->Btl, Response, Request, DataBuffer);
182+
StorageUnit->Btl, Response, Request, DataBuffer, &Overlapped);
171183
if (ERROR_SUCCESS != Error)
172184
goto exit;
173185

@@ -277,6 +289,8 @@ static DWORD WINAPI SpdStorageUnitDispatcherThread(PVOID StorageUnit0)
277289

278290
TlsSetValue(SpdStorageUnitTlsKey, 0);
279291

292+
SpdOverlappedFini(&Overlapped);
293+
280294
StorageUnit->BufferFree(DataBuffer);
281295

282296
return Error;
@@ -336,7 +350,7 @@ VOID SpdStorageUnitSendResponse(SPD_STORAGE_UNIT *StorageUnit,
336350
}
337351

338352
Error = SpdStorageUnitHandleTransact(StorageUnit->Handle,
339-
StorageUnit->Btl, Response, 0, DataBuffer);
353+
StorageUnit->Btl, Response, 0, DataBuffer, NULL);
340354
if (ERROR_SUCCESS != Error)
341355
{
342356
SpdStorageUnitSetDispatcherError(StorageUnit, Error);

0 commit comments

Comments
 (0)