Search code examples
windowssmb

Delay between CloseHandle function call and SMB Close request


The bit of code below opens a file on an SMB share and closes it immediately. For some reason I'm seeing a delay between the CloseHandle call and the SMB Close request being sent over the wire.

#include <Windows.h>
#include <stdio.h>

typedef NTSTATUS (__stdcall *NtQuerySecurityObjectPtr)(
    _In_  HANDLE               Handle,
    _In_  SECURITY_INFORMATION SecurityInformation,
    _Out_ PSECURITY_DESCRIPTOR SecurityDescriptor,
    _In_  ULONG                Length,
    _Out_ PULONG               LengthNeeded
    );

void printTime() {
    SYSTEMTIME time;
    GetSystemTime(&time);
    int required = GetTimeFormat(LOCALE_INVARIANT, 0, &time, nullptr, nullptr, 0);
    LPTSTR buffer = (LPTSTR)GlobalAlloc(GPTR, required * sizeof(TCHAR));
    GetTimeFormat(LOCALE_INVARIANT, 0, &time, nullptr, buffer, required);
    wprintf(L"%s\n", buffer);
}

int main()
{
    LPCTSTR file = L"\\\\192.168.13.163\\share\\file1";
    HANDLE f = INVALID_HANDLE_VALUE;


    f = CreateFile(
        file,
        GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        nullptr,
        CREATE_ALWAYS,
        FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN,
        INVALID_HANDLE_VALUE
        );
    CloseHandle(f);
    printTime();

    return 0;
}

I ran this code with a debugger and put a breakpoint right after the printTime call. In one test run of this printTime outputs 12:18:11. In Wireshark I see the corresponding Close request being sent out at 12:18:20. So there's about 10s delay between the function call and the message being sent out.

I thought this might be due to a handle being leaked somewhere or some other process keeping a handle to the file open, but I don't think that's the case. If I halt the program right before the CloseHandle call, the sysinternals handle tool, executed in a system user shell, shows me that my process has a handle to the file

C:\Users\pepijn\Desktop>Handle.exe file1

Handle v4.0
Copyright (C) 1997-2014 Mark Russinovich
Sysinternals - www.sysinternals.com

SmbClose.exe       pid: 7020   type: File            C8: \Device\Mup\192.168.13.163\DMTest_share\file1

Running the same command right after the CloseHandle call results in no handles being found

C:\Users\pepijn\Desktop>Handle.exe file1

Handle v4.0
Copyright (C) 1997-2014 Mark Russinovich
Sysinternals - www.sysinternals.com

No matching handles found.

Does anyone know what could be the cause of this delay?

The closest related question on this topic I could find is FileStream.Close() is not closing the file handle instantly. The accepted answer there is that some other process might be holding on to the file. As stated above, I don't think that's the case here. I don't have any virus scanners running and I would expect any open handles to show up in the output of Handle since it's running with elevated privileges.


Solution

  • This is apparently due to Batch Oplock (or relative Lease) granted by the server on file open. You can prove this by inspecting Create response with Wireshark.

    One of recommended tricks to avoid batch oplocks being granted si opening the same file for reading in another application right before your original CreateFile call.