From b8ac39297bd0657784742b8c9c376c6d16f3779c Mon Sep 17 00:00:00 2001 From: Liryna Date: Sun, 6 Mar 2022 08:22:06 -0500 Subject: [PATCH] Library - Get the latest UserContext during Close Close is called when all events are done and we get a kernel close request. The kernel can issue an event (GetFileInfo) but actually do not wait for its completion and directly send a close. We will have a race condition in ReleaseDokanOpenInfo where the DokanFileInfo might have the GetFileInfo UserContext and not the Cleanup UserContext that is expected to happen before Close. This change enforce to get the latest UserContext we can get from DokanOpenInfo. Yes, it does not prevent the GetFileInfo to be the latest to set UserContext in EventCompletion but that's the best we can do. --- dokan/dokan.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/dokan/dokan.c b/dokan/dokan.c index 7feabe3b..a16fc70e 100644 --- a/dokan/dokan.c +++ b/dokan/dokan.c @@ -963,26 +963,26 @@ VOID CreateDispatchCommon(PDOKAN_IO_EVENT IoEvent, ULONG SizeOfEventInfo, BOOL U } VOID ReleaseDokanOpenInfo(PDOKAN_IO_EVENT IoEvent) { - LPWSTR fileNameForClose = NULL; - EnterCriticalSection(&IoEvent->DokanOpenInfo->CriticalSection); IoEvent->DokanOpenInfo->OpenCount--; - if (IoEvent->DokanOpenInfo->OpenCount < 1) { - if (IoEvent->DokanOpenInfo->FileName) { - fileNameForClose = IoEvent->DokanOpenInfo->FileName; - IoEvent->DokanOpenInfo->FileName = NULL; - } - LeaveCriticalSection(&IoEvent->DokanOpenInfo->CriticalSection); - PushFileOpenInfo(IoEvent->DokanOpenInfo); - IoEvent->DokanOpenInfo = NULL; - if (IoEvent->EventResult) { - // Reset the Kernel UserContext if we can. Close events do not have one. - IoEvent->EventResult->Context = 0; - } - } else { + if (IoEvent->DokanOpenInfo->OpenCount > 0) { LeaveCriticalSection(&IoEvent->DokanOpenInfo->CriticalSection); + return; } + LPWSTR fileNameForClose = NULL; + if (IoEvent->DokanOpenInfo->FileName) { + fileNameForClose = IoEvent->DokanOpenInfo->FileName; + IoEvent->DokanOpenInfo->FileName = NULL; + } + IoEvent->DokanFileInfo.Context =IoEvent->DokanOpenInfo->UserContext; + LeaveCriticalSection(&IoEvent->DokanOpenInfo->CriticalSection); + PushFileOpenInfo(IoEvent->DokanOpenInfo); + IoEvent->DokanOpenInfo = NULL; + if (IoEvent->EventResult) { + // Reset the Kernel UserContext if we can. Close events do not have one. + IoEvent->EventResult->Context = 0; + } if (fileNameForClose) { if (IoEvent->DokanInstance->DokanOperations->CloseFile) { IoEvent->DokanInstance->DokanOperations->CloseFile(