Index: trunk/src/VBox/Additions/WINNT/SharedFolders/driver/Makefile.kmk
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/driver/Makefile.kmk	(revision 78301)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/driver/Makefile.kmk	(revision 78302)
@@ -34,6 +34,6 @@
 VBoxSF_SOURCES     = \
 	file.c \
-	info.c \
-	vbsf.c \
+	info.cpp \
+	vbsf.cpp \
 	net.c \
 	path.c \
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/driver/file.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/driver/file.c	(revision 78301)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/driver/file.c	(revision 78302)
@@ -328,15 +328,27 @@
 }
 
-
 NTSTATUS VBoxMRxRead(IN PRX_CONTEXT RxContext)
 {
-    NTSTATUS Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue,
-                                               vbsfReadWorker,
-                                               RxContext);
-
-    Log(("VBOXSF: MRxRead: RxDispatchToWorkerThread: Status 0x%08X\n", Status));
-
-    if (Status == STATUS_SUCCESS)
-        Status = STATUS_PENDING;
+    NTSTATUS Status;
+
+#if 0
+    if (   IoIsOperationSynchronous(RxContext->CurrentIrp)
+        /*&& IoGetRemainingStackSize() >= 1024 - not necessary, checked by RxFsdCommonDispatch already */)
+    {
+        RxContext->IoStatusBlock.Status = Status = vbsfReadInternal(RxContext);
+        Assert(Status != STATUS_PENDING);
+
+        Log(("VBOXSF: MRxRead: vbsfReadInternal: Status %#08X\n", Status));
+    }
+    else
+#endif
+    {
+        Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue, vbsfReadWorker, RxContext);
+
+        Log(("VBOXSF: MRxRead: RxDispatchToWorkerThread: Status 0x%08X\n", Status));
+
+        if (Status == STATUS_SUCCESS)
+            Status = STATUS_PENDING;
+    }
 
     return Status;
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/driver/info.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/driver/info.c	(revision 78301)
+++ 	(revision )
@@ -1,1576 +1,0 @@
-/* $Id$ */
-/** @file
- *
- * VirtualBox Windows Guest Shared Folders
- *
- * File System Driver query and set information routines
- */
-
-/*
- * Copyright (C) 2012-2019 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#include "vbsf.h"
-#include <iprt/err.h>
-
-
-/** Macro for copying a SHFLSTRING file name into a FILE_DIRECTORY_INFORMATION structure. */
-#define INIT_FILE_NAME(obj, str) \
-    do { \
-        ULONG cbLength = (str).u16Length; \
-        (obj)->FileNameLength = cbLength; \
-        RtlCopyMemory((obj)->FileName, &(str).String.ucs2[0], cbLength + 2); \
-    } while (0)
-
-NTSTATUS VBoxMRxQueryDirectory(IN OUT PRX_CONTEXT RxContext)
-{
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    RxCaptureFobx;
-    RxCaptureFcb;
-
-    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
-    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
-    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
-
-    PUNICODE_STRING DirectoryName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
-    PUNICODE_STRING Template = &capFobx->UnicodeQueryTemplate;
-    FILE_INFORMATION_CLASS FileInformationClass = RxContext->Info.FileInformationClass;
-    PCHAR pInfoBuffer = (PCHAR)RxContext->Info.Buffer;
-    LONG cbMaxSize = RxContext->Info.Length;
-    LONG *pLengthRemaining = (LONG *)&RxContext->Info.LengthRemaining;
-
-    LONG cbToCopy;
-    int vrc;
-    uint8_t *pHGCMBuffer;
-    uint32_t index, fSFFlags, cFiles, u32BufSize;
-    LONG cbHGCMBuffer;
-    PSHFLDIRINFO pDirEntry;
-
-    ULONG *pNextOffset = 0;
-    PSHFLSTRING ParsedPath = NULL;
-
-    Log(("VBOXSF: MrxQueryDirectory: FileInformationClass %d, pVBoxFobx %p, hFile %RX64, pInfoBuffer %p\n",
-         FileInformationClass, pVBoxFobx, pVBoxFobx->hFile, pInfoBuffer));
-
-    if (!pVBoxFobx)
-    {
-        Log(("VBOXSF: MrxQueryDirectory: pVBoxFobx is invalid!\n"));
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    if (!DirectoryName)
-        return STATUS_INVALID_PARAMETER;
-
-    if (DirectoryName->Length == 0)
-        Log(("VBOXSF: MrxQueryDirectory: DirectoryName = \\ (null string)\n"));
-    else
-        Log(("VBOXSF: MrxQueryDirectory: DirectoryName = %.*ls\n",
-             DirectoryName->Length / sizeof(WCHAR), DirectoryName->Buffer));
-
-    if (!Template)
-        return STATUS_INVALID_PARAMETER;
-
-    if (Template->Length == 0)
-        Log(("VBOXSF: MrxQueryDirectory: Template = \\ (null string)\n"));
-    else
-        Log(("VBOXSF: MrxQueryDirectory: Template = %.*ls\n",
-             Template->Length / sizeof(WCHAR), Template->Buffer));
-
-    cbHGCMBuffer = RT_MAX(cbMaxSize, PAGE_SIZE);
-
-    Log(("VBOXSF: MrxQueryDirectory: Allocating cbHGCMBuffer = %d\n",
-         cbHGCMBuffer));
-
-    pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbHGCMBuffer);
-    if (!pHGCMBuffer)
-    {
-        AssertFailed();
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    /* Assume start from the beginning. */
-    index = 0;
-    if (RxContext->QueryDirectory.IndexSpecified == TRUE)
-    {
-        Log(("VBOXSF: MrxQueryDirectory: Index specified %d\n",
-             index));
-        index = RxContext->QueryDirectory.FileIndex;
-    }
-
-    fSFFlags = SHFL_LIST_NONE;
-    if (RxContext->QueryDirectory.ReturnSingleEntry == TRUE)
-    {
-        Log(("VBOXSF: MrxQueryDirectory: Query single entry\n"));
-        fSFFlags |= SHFL_LIST_RETURN_ONE;
-    }
-    if (   RxContext->QueryDirectory.RestartScan == TRUE
-        && RxContext->QueryDirectory.InitialQuery == FALSE)
-    {
-        Log(("VBOXSF: MrxQueryDirectory: Restart scan\n"));
-        fSFFlags |= SHFL_LIST_RESTART;
-    }
-
-    if (Template->Length)
-    {
-        ULONG ParsedPathSize, cch;
-
-        /* Calculate size required for parsed path: dir + \ + template + 0. */
-        ParsedPathSize = SHFLSTRING_HEADER_SIZE + Template->Length + sizeof(WCHAR);
-        if (DirectoryName->Length)
-            ParsedPathSize += DirectoryName->Length + sizeof(WCHAR);
-        Log(("VBOXSF: MrxQueryDirectory: ParsedPathSize = %d\n", ParsedPathSize));
-
-        ParsedPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);
-        if (!ParsedPath)
-        {
-            Status = STATUS_INSUFFICIENT_RESOURCES;
-            goto end;
-        }
-
-        if (!ShflStringInitBuffer(ParsedPath, ParsedPathSize))
-        {
-            Status = STATUS_INSUFFICIENT_RESOURCES;
-            goto end;
-        }
-
-        cch = 0;
-        if (DirectoryName->Length)
-        {
-            /* Copy directory name into ParsedPath. */
-            RtlCopyMemory(ParsedPath->String.ucs2, DirectoryName->Buffer, DirectoryName->Length);
-            cch += DirectoryName->Length / sizeof(WCHAR);
-
-            /* Add terminating backslash. */
-            ParsedPath->String.ucs2[cch] = L'\\';
-            cch++;
-        }
-
-        RtlCopyMemory (&ParsedPath->String.ucs2[cch], Template->Buffer, Template->Length);
-        cch += Template->Length / sizeof(WCHAR);
-
-        /* Add terminating nul. */
-        ParsedPath->String.ucs2[cch] = 0;
-
-        /* cch is the number of chars without trailing nul. */
-        ParsedPath->u16Length = (uint16_t)(cch * sizeof(WCHAR));
-
-        AssertMsg(ParsedPath->u16Length + sizeof(WCHAR) == ParsedPath->u16Size,
-                  ("u16Length %d, u16Size %d\n", ParsedPath->u16Length, ParsedPath->u16Size));
-
-        Log(("VBOXSF: MrxQueryDirectory: ParsedPath = %.*ls\n",
-             ParsedPath->u16Length / sizeof(WCHAR), ParsedPath->String.ucs2));
-    }
-
-    cFiles = 0;
-
-    /* VbglR0SfDirInfo requires a pointer to uint32_t. */
-    u32BufSize = cbHGCMBuffer;
-
-    Log(("VBOXSF: MrxQueryDirectory: CallDirInfo: File = 0x%08x, Flags = 0x%08x, Index = %d, u32BufSize = %d\n",
-         pVBoxFobx->hFile, fSFFlags, index, u32BufSize));
-    vrc = VbglR0SfDirInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
-                          ParsedPath, fSFFlags, index, &u32BufSize, (PSHFLDIRINFO)pHGCMBuffer, &cFiles);
-    Log(("VBOXSF: MrxQueryDirectory: u32BufSize after CallDirInfo = %d, rc = %Rrc\n",
-         u32BufSize, vrc));
-
-    switch (vrc)
-    {
-        case VINF_SUCCESS:
-            /* Nothing to do here. */
-            break;
-
-        case VERR_NO_TRANSLATION:
-            Log(("VBOXSF: MrxQueryDirectory: Host could not translate entry!\n"));
-            break;
-
-        case VERR_NO_MORE_FILES:
-            if (cFiles <= 0) /* VERR_NO_MORE_FILES appears at the first lookup when just returning the current dir ".".
-                              * So we also have to check for the cFiles counter. */
-            {
-                /* Not an error, but we have to handle the return value. */
-                Log(("VBOXSF: MrxQueryDirectory: Host reported no more files!\n"));
-
-                if (RxContext->QueryDirectory.InitialQuery)
-                {
-                    /* First call. MSDN on FindFirstFile: "If the function fails because no matching files
-                     * can be found, the GetLastError function returns ERROR_FILE_NOT_FOUND."
-                     * So map this rc to file not found.
-                     */
-                    Status = STATUS_NO_SUCH_FILE;
-                }
-                else
-                {
-                    /* Search continued. */
-                    Status = STATUS_NO_MORE_FILES;
-                }
-            }
-            break;
-
-        case VERR_FILE_NOT_FOUND:
-            Status = STATUS_NO_SUCH_FILE;
-            Log(("VBOXSF: MrxQueryDirectory: no such file!\n"));
-            break;
-
-        default:
-            Status = VBoxErrorToNTStatus(vrc);
-            Log(("VBOXSF: MrxQueryDirectory: Error %Rrc from CallDirInfo (cFiles=%d)!\n",
-                 vrc, cFiles));
-            break;
-    }
-
-    if (Status != STATUS_SUCCESS)
-        goto end;
-
-    /* Verify that the returned buffer length is not greater than the original one. */
-    if (u32BufSize > (uint32_t)cbHGCMBuffer)
-    {
-        Log(("VBOXSF: MrxQueryDirectory: returned buffer size (%u) is invalid!!!\n",
-             u32BufSize));
-        Status = STATUS_INVALID_NETWORK_RESPONSE;
-        goto end;
-    }
-
-    /* How many bytes remain in the buffer. */
-    cbHGCMBuffer = u32BufSize;
-
-    pDirEntry = (PSHFLDIRINFO)pHGCMBuffer;
-    Status = STATUS_SUCCESS;
-
-    Log(("VBOXSF: MrxQueryDirectory: cFiles=%d, Length=%d\n",
-         cFiles, cbHGCMBuffer));
-
-    while ((*pLengthRemaining) && (cFiles > 0) && (pDirEntry != NULL))
-    {
-        int cbEntry = RT_UOFFSETOF(SHFLDIRINFO, name.String) + pDirEntry->name.u16Size;
-
-        if (cbEntry > cbHGCMBuffer)
-        {
-            Log(("VBOXSF: MrxQueryDirectory: Entry size (%d) exceeds the buffer size (%d)!!!\n",
-                 cbEntry, cbHGCMBuffer));
-            Status = STATUS_INVALID_NETWORK_RESPONSE;
-            goto end;
-        }
-
-        switch (FileInformationClass)
-        {
-            case FileDirectoryInformation:
-            {
-                PFILE_DIRECTORY_INFORMATION pInfo = (PFILE_DIRECTORY_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryDirectory: FileDirectoryInformation\n"));
-
-                cbToCopy = sizeof(FILE_DIRECTORY_INFORMATION);
-                /* Struct already contains one char for null terminator. */
-                cbToCopy += pDirEntry->name.u16Size;
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    RtlZeroMemory(pInfo, cbToCopy);
-
-                    pInfo->CreationTime.QuadPart   = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
-                    pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
-                    pInfo->LastWriteTime.QuadPart  = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
-                    pInfo->ChangeTime.QuadPart     = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
-                    pInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
-                    pInfo->EndOfFile.QuadPart      = pDirEntry->Info.cbObject;
-                    pInfo->FileIndex               = index;
-                    pInfo->FileAttributes          = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
-
-                    INIT_FILE_NAME(pInfo, pDirEntry->name);
-
-                    /* Align to 8 byte boundary */
-                    cbToCopy = RT_ALIGN(cbToCopy, sizeof(LONGLONG));
-                    pInfo->NextEntryOffset = cbToCopy;
-                    pNextOffset = &pInfo->NextEntryOffset;
-                }
-                else
-                {
-                    pInfo->NextEntryOffset = 0; /* last item */
-                    Status = STATUS_BUFFER_OVERFLOW;
-                }
-                break;
-            }
-
-            case FileFullDirectoryInformation:
-            {
-                PFILE_FULL_DIR_INFORMATION pInfo = (PFILE_FULL_DIR_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryDirectory: FileFullDirectoryInformation\n"));
-
-                cbToCopy = sizeof(FILE_FULL_DIR_INFORMATION);
-                /* Struct already contains one char for null terminator. */
-                cbToCopy += pDirEntry->name.u16Size;
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    RtlZeroMemory(pInfo, cbToCopy);
-
-                    pInfo->CreationTime.QuadPart   = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
-                    pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
-                    pInfo->LastWriteTime.QuadPart  = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
-                    pInfo->ChangeTime.QuadPart     = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
-                    pInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
-                    pInfo->EndOfFile.QuadPart      = pDirEntry->Info.cbObject;
-                    pInfo->EaSize                  = 0;
-                    pInfo->FileIndex               = index;
-                    pInfo->FileAttributes          = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
-
-                    INIT_FILE_NAME(pInfo, pDirEntry->name);
-
-                    /* Align to 8 byte boundary */
-                    cbToCopy = RT_ALIGN(cbToCopy, sizeof(LONGLONG));
-                    pInfo->NextEntryOffset = cbToCopy;
-                    pNextOffset = &pInfo->NextEntryOffset;
-                }
-                else
-                {
-                    pInfo->NextEntryOffset = 0; /* last item */
-                    Status = STATUS_BUFFER_OVERFLOW;
-                }
-                break;
-            }
-
-            case FileBothDirectoryInformation:
-            {
-                PFILE_BOTH_DIR_INFORMATION pInfo = (PFILE_BOTH_DIR_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryDirectory: FileBothDirectoryInformation\n"));
-
-                cbToCopy = sizeof(FILE_BOTH_DIR_INFORMATION);
-                /* struct already contains one char for null terminator */
-                cbToCopy += pDirEntry->name.u16Size;
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    RtlZeroMemory(pInfo, cbToCopy);
-
-                    pInfo->CreationTime.QuadPart   = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
-                    pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
-                    pInfo->LastWriteTime.QuadPart  = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
-                    pInfo->ChangeTime.QuadPart     = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
-                    pInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
-                    pInfo->EndOfFile.QuadPart      = pDirEntry->Info.cbObject;
-                    pInfo->EaSize                  = 0;
-                    pInfo->ShortNameLength         = 0; /** @todo ? */
-                    pInfo->FileIndex               = index;
-                    pInfo->FileAttributes          = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
-
-                    INIT_FILE_NAME(pInfo, pDirEntry->name);
-
-                    Log(("VBOXSF: MrxQueryDirectory: FileBothDirectoryInformation cbAlloc = %x cbObject = %x\n",
-                         pDirEntry->Info.cbAllocated, pDirEntry->Info.cbObject));
-                    Log(("VBOXSF: MrxQueryDirectory: FileBothDirectoryInformation cbToCopy = %d, name size=%d name len=%d\n",
-                         cbToCopy, pDirEntry->name.u16Size, pDirEntry->name.u16Length));
-                    Log(("VBOXSF: MrxQueryDirectory: FileBothDirectoryInformation File name %.*ls (DirInfo)\n",
-                         pInfo->FileNameLength / sizeof(WCHAR), pInfo->FileName));
-                    Log(("VBOXSF: MrxQueryDirectory: FileBothDirectoryInformation File name %.*ls (DirEntry)\n",
-                         pDirEntry->name.u16Size / sizeof(WCHAR), pDirEntry->name.String.ucs2));
-
-                    /* Align to 8 byte boundary. */
-                    cbToCopy = RT_ALIGN(cbToCopy, sizeof(LONGLONG));
-                    pInfo->NextEntryOffset = cbToCopy;
-                    pNextOffset = &pInfo->NextEntryOffset;
-                }
-                else
-                {
-                    pInfo->NextEntryOffset = 0; /* Last item. */
-                    Status = STATUS_BUFFER_OVERFLOW;
-                }
-                break;
-            }
-
-            case FileIdBothDirectoryInformation:
-            {
-                PFILE_ID_BOTH_DIR_INFORMATION pInfo = (PFILE_ID_BOTH_DIR_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryDirectory: FileIdBothDirectoryInformation\n"));
-
-                cbToCopy = sizeof(FILE_ID_BOTH_DIR_INFORMATION);
-                /* struct already contains one char for null terminator */
-                cbToCopy += pDirEntry->name.u16Size;
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    RtlZeroMemory(pInfo, cbToCopy);
-
-                    pInfo->CreationTime.QuadPart   = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
-                    pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
-                    pInfo->LastWriteTime.QuadPart  = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
-                    pInfo->ChangeTime.QuadPart     = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
-                    pInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
-                    pInfo->EndOfFile.QuadPart      = pDirEntry->Info.cbObject;
-                    pInfo->EaSize                  = 0;
-                    pInfo->ShortNameLength         = 0; /** @todo ? */
-                    pInfo->EaSize                  = 0;
-                    pInfo->FileId.QuadPart         = 0;
-                    pInfo->FileAttributes          = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
-
-                    INIT_FILE_NAME(pInfo, pDirEntry->name);
-
-                    Log(("VBOXSF: MrxQueryDirectory: FileIdBothDirectoryInformation cbAlloc = 0x%RX64 cbObject = 0x%RX64\n",
-                         pDirEntry->Info.cbAllocated, pDirEntry->Info.cbObject));
-                    Log(("VBOXSF: MrxQueryDirectory: FileIdBothDirectoryInformation cbToCopy = %d, name size=%d name len=%d\n",
-                         cbToCopy, pDirEntry->name.u16Size, pDirEntry->name.u16Length));
-                    Log(("VBOXSF: MrxQueryDirectory: FileIdBothDirectoryInformation File name %.*ls (DirInfo)\n",
-                         pInfo->FileNameLength / sizeof(WCHAR), pInfo->FileName));
-                    Log(("VBOXSF: MrxQueryDirectory: FileIdBothDirectoryInformation File name %.*ls (DirEntry)\n",
-                         pDirEntry->name.u16Size / sizeof(WCHAR), pDirEntry->name.String.ucs2));
-
-                    /* Align to 8 byte boundary. */
-                    cbToCopy = RT_ALIGN(cbToCopy, sizeof(LONGLONG));
-                    pInfo->NextEntryOffset = cbToCopy;
-                    pNextOffset = &pInfo->NextEntryOffset;
-                }
-                else
-                {
-                    pInfo->NextEntryOffset = 0; /* Last item. */
-                    Status = STATUS_BUFFER_OVERFLOW;
-                }
-                break;
-            }
-
-            case FileNamesInformation:
-            {
-                PFILE_NAMES_INFORMATION pInfo = (PFILE_NAMES_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryDirectory: FileNamesInformation\n"));
-
-                cbToCopy = sizeof(FILE_NAMES_INFORMATION);
-                /* Struct already contains one char for null terminator. */
-                cbToCopy += pDirEntry->name.u16Size;
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    RtlZeroMemory(pInfo, cbToCopy);
-
-                    pInfo->FileIndex = index;
-
-                    INIT_FILE_NAME(pInfo, pDirEntry->name);
-
-                    Log(("VBOXSF: MrxQueryDirectory: FileNamesInformation: File name [%.*ls]\n",
-                         pInfo->FileNameLength / sizeof(WCHAR), pInfo->FileName));
-
-                    /* Align to 8 byte boundary. */
-                    cbToCopy = RT_ALIGN(cbToCopy, sizeof(LONGLONG));
-                    pInfo->NextEntryOffset = cbToCopy;
-                    pNextOffset = &pInfo->NextEntryOffset;
-                }
-                else
-                {
-                    pInfo->NextEntryOffset = 0; /* Last item. */
-                    Status = STATUS_BUFFER_OVERFLOW;
-                }
-                break;
-            }
-
-            default:
-                Log(("VBOXSF: MrxQueryDirectory: Not supported FileInformationClass %d!\n",
-                     FileInformationClass));
-                Status = STATUS_INVALID_PARAMETER;
-                goto end;
-        }
-
-        cbHGCMBuffer -= cbEntry;
-        pDirEntry = (PSHFLDIRINFO)((uintptr_t)pDirEntry + cbEntry);
-
-        Log(("VBOXSF: MrxQueryDirectory: %d bytes left in HGCM buffer\n",
-             cbHGCMBuffer));
-
-        if (*pLengthRemaining >= cbToCopy)
-        {
-            pInfoBuffer += cbToCopy;
-            *pLengthRemaining -= cbToCopy;
-        }
-        else
-            break;
-
-        if (RxContext->QueryDirectory.ReturnSingleEntry)
-            break;
-
-        /* More left? */
-        if (cbHGCMBuffer <= 0)
-            break;
-
-        index++; /* File Index. */
-
-        cFiles--;
-    }
-
-    if (pNextOffset)
-        *pNextOffset = 0; /* Last pInfo->NextEntryOffset should be set to zero! */
-
-end:
-    if (pHGCMBuffer)
-        vbsfFreeNonPagedMem(pHGCMBuffer);
-
-    if (ParsedPath)
-        vbsfFreeNonPagedMem(ParsedPath);
-
-    Log(("VBOXSF: MrxQueryDirectory: Returned 0x%08X\n",
-         Status));
-    return Status;
-}
-
-NTSTATUS VBoxMRxQueryVolumeInfo(IN OUT PRX_CONTEXT RxContext)
-{
-    NTSTATUS Status;
-
-    RxCaptureFcb;
-    RxCaptureFobx;
-
-    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
-    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
-    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
-
-    FS_INFORMATION_CLASS FsInformationClass = RxContext->Info.FsInformationClass;
-    PVOID pInfoBuffer = RxContext->Info.Buffer;
-    ULONG cbInfoBuffer = RxContext->Info.LengthRemaining;
-    ULONG cbToCopy = 0;
-    ULONG cbString = 0;
-
-    Log(("VBOXSF: MrxQueryVolumeInfo: pInfoBuffer = %p, cbInfoBuffer = %d\n",
-         RxContext->Info.Buffer, RxContext->Info.LengthRemaining));
-    Log(("VBOXSF: MrxQueryVolumeInfo: vboxFobx = %p, Handle = 0x%RX64\n",
-         pVBoxFobx, pVBoxFobx? pVBoxFobx->hFile: 0));
-
-    Status = STATUS_INVALID_PARAMETER;
-
-    switch (FsInformationClass)
-    {
-        case FileFsVolumeInformation:
-        {
-            PFILE_FS_VOLUME_INFORMATION pInfo = (PFILE_FS_VOLUME_INFORMATION)pInfoBuffer;
-
-            PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
-            PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
-
-            PWCHAR pRootName;
-            ULONG cbRootName;
-
-            PSHFLVOLINFO pShflVolInfo;
-            uint32_t cbHGCMBuffer;
-            uint8_t *pHGCMBuffer;
-            int vrc;
-
-            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsVolumeInformation\n"));
-
-            if (!pVBoxFobx)
-            {
-                Log(("VBOXSF: MrxQueryVolumeInfo: pVBoxFobx is NULL!\n"));
-                Status = STATUS_INVALID_PARAMETER;
-                break;
-            }
-
-            cbRootName = pNetRoot->pNetRootName->Length - pSrvCall->pSrvCallName->Length;
-            cbRootName -= sizeof(WCHAR); /* Remove the leading backslash. */
-            pRootName = pNetRoot->pNetRootName->Buffer + (pSrvCall->pSrvCallName->Length / sizeof(WCHAR));
-            pRootName++; /* Remove the leading backslash. */
-
-            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsVolumeInformation: Root name = %.*ls, %d bytes\n",
-                 cbRootName / sizeof(WCHAR), pRootName, cbRootName));
-
-            cbToCopy = FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel);
-
-            cbString  = VBOX_VOLNAME_PREFIX_SIZE;
-            cbString += cbRootName;
-            cbString += sizeof(WCHAR);
-
-            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsVolumeInformation: cbToCopy %d, cbString %d\n",
-                 cbToCopy, cbString));
-
-            if (cbInfoBuffer < cbToCopy)
-            {
-                Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            RtlZeroMemory(pInfo, cbToCopy);
-
-            /* Query serial number. */
-            cbHGCMBuffer = sizeof(SHFLVOLINFO);
-            pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbHGCMBuffer);
-            if (!pHGCMBuffer)
-            {
-                Status = STATUS_INSUFFICIENT_RESOURCES;
-                break;
-            }
-
-            vrc = VbglR0SfFsInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
-                                 SHFL_INFO_GET | SHFL_INFO_VOLUME, &cbHGCMBuffer, (PSHFLDIRINFO)pHGCMBuffer);
-
-            if (vrc != VINF_SUCCESS)
-            {
-                Status = VBoxErrorToNTStatus(vrc);
-                vbsfFreeNonPagedMem(pHGCMBuffer);
-                break;
-            }
-
-            pShflVolInfo = (PSHFLVOLINFO)pHGCMBuffer;
-            pInfo->VolumeSerialNumber = pShflVolInfo->ulSerial;
-            vbsfFreeNonPagedMem(pHGCMBuffer);
-
-            pInfo->VolumeCreationTime.QuadPart = 0;
-            pInfo->SupportsObjects = FALSE;
-
-            if (cbInfoBuffer >= cbToCopy + cbString)
-            {
-                RtlCopyMemory(&pInfo->VolumeLabel[0],
-                              VBOX_VOLNAME_PREFIX,
-                              VBOX_VOLNAME_PREFIX_SIZE);
-                RtlCopyMemory(&pInfo->VolumeLabel[VBOX_VOLNAME_PREFIX_SIZE / sizeof(WCHAR)],
-                              pRootName,
-                              cbRootName);
-                pInfo->VolumeLabel[cbString / sizeof(WCHAR) -  1] = 0;
-            }
-            else
-            {
-                cbString = cbInfoBuffer - cbToCopy;
-
-                RtlCopyMemory(&pInfo->VolumeLabel[0],
-                              VBOX_VOLNAME_PREFIX,
-                              RT_MIN(cbString, VBOX_VOLNAME_PREFIX_SIZE));
-                if (cbString > VBOX_VOLNAME_PREFIX_SIZE)
-                {
-                    RtlCopyMemory(&pInfo->VolumeLabel[VBOX_VOLNAME_PREFIX_SIZE / sizeof(WCHAR)],
-                                  pRootName,
-                                  cbString - VBOX_VOLNAME_PREFIX_SIZE);
-                }
-            }
-
-            pInfo->VolumeLabelLength = cbString;
-
-            cbToCopy += cbString;
-
-            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsVolumeInformation: VolumeLabelLength %d\n",
-                 pInfo->VolumeLabelLength));
-
-            Status = STATUS_SUCCESS;
-            break;
-        }
-
-        case FileFsLabelInformation:
-        {
-            PFILE_FS_LABEL_INFORMATION pInfo = (PFILE_FS_LABEL_INFORMATION)pInfoBuffer;
-
-            PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
-            PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
-
-            PWCHAR pRootName;
-            ULONG cbRootName;
-
-            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsLabelInformation\n"));
-
-            cbRootName = pNetRoot->pNetRootName->Length - pSrvCall->pSrvCallName->Length;
-            cbRootName -= sizeof(WCHAR); /* Remove the leading backslash. */
-            pRootName = pNetRoot->pNetRootName->Buffer + (pSrvCall->pSrvCallName->Length / sizeof(WCHAR));
-            pRootName++; /* Remove the leading backslash. */
-
-            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsLabelInformation: Root name = %.*ls, %d bytes\n",
-                 cbRootName / sizeof(WCHAR), pRootName, cbRootName));
-
-            cbToCopy = FIELD_OFFSET(FILE_FS_LABEL_INFORMATION, VolumeLabel);
-
-            cbString  = VBOX_VOLNAME_PREFIX_SIZE;
-            cbString += cbRootName;
-            cbString += sizeof(WCHAR);
-
-            if (cbInfoBuffer < cbToCopy)
-            {
-                Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            RtlZeroMemory(pInfo, cbToCopy);
-
-            if (cbInfoBuffer >= cbToCopy + cbString)
-            {
-                RtlCopyMemory(&pInfo->VolumeLabel[0],
-                              VBOX_VOLNAME_PREFIX,
-                              VBOX_VOLNAME_PREFIX_SIZE);
-                RtlCopyMemory(&pInfo->VolumeLabel[VBOX_VOLNAME_PREFIX_SIZE / sizeof(WCHAR)],
-                              pRootName,
-                              cbRootName);
-                pInfo->VolumeLabel[cbString / sizeof(WCHAR) -  1] = 0;
-            }
-            else
-            {
-                cbString = cbInfoBuffer - cbToCopy;
-
-                RtlCopyMemory(&pInfo->VolumeLabel[0],
-                              VBOX_VOLNAME_PREFIX,
-                              RT_MIN(cbString, VBOX_VOLNAME_PREFIX_SIZE));
-                if (cbString > VBOX_VOLNAME_PREFIX_SIZE)
-                {
-                    RtlCopyMemory(&pInfo->VolumeLabel[VBOX_VOLNAME_PREFIX_SIZE / sizeof(WCHAR)],
-                                  pRootName,
-                                  cbString - VBOX_VOLNAME_PREFIX_SIZE);
-                }
-            }
-
-            pInfo->VolumeLabelLength = cbString;
-
-            cbToCopy += cbString;
-
-            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsLabelInformation: VolumeLabelLength %d\n",
-                 pInfo->VolumeLabelLength));
-
-            Status = STATUS_SUCCESS;
-            break;
-        }
-
-        case FileFsFullSizeInformation:
-        case FileFsSizeInformation:
-        {
-            PFILE_FS_FULL_SIZE_INFORMATION pFullSizeInfo = (PFILE_FS_FULL_SIZE_INFORMATION)pInfoBuffer;
-            PFILE_FS_SIZE_INFORMATION pSizeInfo = (PFILE_FS_SIZE_INFORMATION)pInfoBuffer;
-
-            uint32_t cbHGCMBuffer;
-            uint8_t *pHGCMBuffer;
-            int vrc;
-            PSHFLVOLINFO pShflVolInfo;
-
-            LARGE_INTEGER TotalAllocationUnits;
-            LARGE_INTEGER AvailableAllocationUnits;
-            ULONG         SectorsPerAllocationUnit;
-            ULONG         BytesPerSector;
-
-            if (FsInformationClass == FileFsFullSizeInformation)
-            {
-                Log(("VBOXSF: MrxQueryVolumeInfo: FileFsFullSizeInformation\n"));
-                cbToCopy = sizeof(FILE_FS_FULL_SIZE_INFORMATION);
-            }
-            else
-            {
-                Log(("VBOXSF: MrxQueryVolumeInfo: FileFsSizeInformation\n"));
-                cbToCopy = sizeof(FILE_FS_SIZE_INFORMATION);
-            }
-
-            if (!pVBoxFobx)
-            {
-                Log(("VBOXSF: MrxQueryVolumeInfo: pVBoxFobx is NULL!\n"));
-                Status = STATUS_INVALID_PARAMETER;
-                break;
-            }
-
-            if (cbInfoBuffer < cbToCopy)
-            {
-                Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            RtlZeroMemory(pInfoBuffer, cbToCopy);
-
-            cbHGCMBuffer = sizeof(SHFLVOLINFO);
-            pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbHGCMBuffer);
-            if (!pHGCMBuffer)
-            {
-                Status = STATUS_INSUFFICIENT_RESOURCES;
-                break;
-            }
-
-            vrc = VbglR0SfFsInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
-                                 SHFL_INFO_GET | SHFL_INFO_VOLUME, &cbHGCMBuffer, (PSHFLDIRINFO)pHGCMBuffer);
-
-            if (vrc != VINF_SUCCESS)
-            {
-                Status = VBoxErrorToNTStatus(vrc);
-                vbsfFreeNonPagedMem(pHGCMBuffer);
-                break;
-            }
-
-            pShflVolInfo = (PSHFLVOLINFO)pHGCMBuffer;
-
-            TotalAllocationUnits.QuadPart     = pShflVolInfo->ullTotalAllocationBytes / pShflVolInfo->ulBytesPerAllocationUnit;
-            AvailableAllocationUnits.QuadPart = pShflVolInfo->ullAvailableAllocationBytes / pShflVolInfo->ulBytesPerAllocationUnit;
-            SectorsPerAllocationUnit          = pShflVolInfo->ulBytesPerAllocationUnit / pShflVolInfo->ulBytesPerSector;
-            BytesPerSector                    = pShflVolInfo->ulBytesPerSector;
-
-            Log(("VBOXSF: MrxQueryVolumeInfo: TotalAllocationUnits     0x%RX64\n", TotalAllocationUnits.QuadPart));
-            Log(("VBOXSF: MrxQueryVolumeInfo: AvailableAllocationUnits 0x%RX64\n", AvailableAllocationUnits.QuadPart));
-            Log(("VBOXSF: MrxQueryVolumeInfo: SectorsPerAllocationUnit 0x%X\n", SectorsPerAllocationUnit));
-            Log(("VBOXSF: MrxQueryVolumeInfo: BytesPerSector           0x%X\n", BytesPerSector));
-
-            if (FsInformationClass == FileFsFullSizeInformation)
-            {
-                pFullSizeInfo->TotalAllocationUnits           = TotalAllocationUnits;
-                pFullSizeInfo->CallerAvailableAllocationUnits = AvailableAllocationUnits;
-                pFullSizeInfo->ActualAvailableAllocationUnits = AvailableAllocationUnits;
-                pFullSizeInfo->SectorsPerAllocationUnit       = SectorsPerAllocationUnit;
-                pFullSizeInfo->BytesPerSector                 = BytesPerSector;
-            }
-            else
-            {
-                pSizeInfo->TotalAllocationUnits     = TotalAllocationUnits;
-                pSizeInfo->AvailableAllocationUnits = AvailableAllocationUnits;
-                pSizeInfo->SectorsPerAllocationUnit = SectorsPerAllocationUnit;
-                pSizeInfo->BytesPerSector           = BytesPerSector;
-            }
-
-            vbsfFreeNonPagedMem(pHGCMBuffer);
-
-            Status = STATUS_SUCCESS;
-            break;
-        }
-
-        case FileFsDeviceInformation:
-        {
-            PFILE_FS_DEVICE_INFORMATION pInfo = (PFILE_FS_DEVICE_INFORMATION)pInfoBuffer;
-            PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
-
-            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsDeviceInformation: Type = %d\n",
-                 NetRoot->DeviceType));
-
-            cbToCopy = sizeof(FILE_FS_DEVICE_INFORMATION);
-
-            if (cbInfoBuffer < cbToCopy)
-            {
-                Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            pInfo->DeviceType = NetRoot->DeviceType;
-            pInfo->Characteristics = FILE_REMOTE_DEVICE;
-
-            Status = STATUS_SUCCESS;
-            break;
-        }
-
-        case FileFsAttributeInformation:
-        {
-            PFILE_FS_ATTRIBUTE_INFORMATION pInfo = (PFILE_FS_ATTRIBUTE_INFORMATION)pInfoBuffer;
-
-            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsAttributeInformation\n"));
-
-            cbToCopy = FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName);
-
-            cbString = sizeof(MRX_VBOX_FILESYS_NAME_U);
-
-            if (cbInfoBuffer < cbToCopy)
-            {
-                Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            pInfo->FileSystemAttributes = 0; /** @todo set unicode, case sensitive etc? */
-            pInfo->MaximumComponentNameLength = 255; /** @todo should query from the host */
-
-            if (cbInfoBuffer >= cbToCopy + cbString)
-            {
-                RtlCopyMemory(pInfo->FileSystemName,
-                              MRX_VBOX_FILESYS_NAME_U,
-                              sizeof(MRX_VBOX_FILESYS_NAME_U));
-            }
-            else
-            {
-                cbString = cbInfoBuffer - cbToCopy;
-
-                RtlCopyMemory(pInfo->FileSystemName,
-                              MRX_VBOX_FILESYS_NAME_U,
-                              RT_MIN(cbString, sizeof(MRX_VBOX_FILESYS_NAME_U)));
-            }
-
-            pInfo->FileSystemNameLength = cbString;
-
-            cbToCopy += cbString;
-
-            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsAttributeInformation: FileSystemNameLength %d\n",
-                 pInfo->FileSystemNameLength));
-
-            Status = STATUS_SUCCESS;
-            break;
-        }
-
-        case FileFsControlInformation:
-            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsControlInformation: not supported\n"));
-            Status = STATUS_INVALID_PARAMETER;
-            break;
-
-        case FileFsObjectIdInformation:
-            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsObjectIdInformation: not supported\n"));
-            Status = STATUS_INVALID_PARAMETER;
-            break;
-
-        case FileFsMaximumInformation:
-            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsMaximumInformation: not supported\n"));
-            Status = STATUS_INVALID_PARAMETER;
-            break;
-
-        default:
-            Log(("VBOXSF: MrxQueryVolumeInfo: Not supported FsInformationClass %d!\n",
-                 FsInformationClass));
-            Status = STATUS_INVALID_PARAMETER;
-            break;
-    }
-
-    if (Status == STATUS_SUCCESS)
-        RxContext->Info.LengthRemaining = cbInfoBuffer - cbToCopy;
-    else if (Status == STATUS_BUFFER_TOO_SMALL)
-    {
-        Log(("VBOXSF: MrxQueryVolumeInfo: Insufficient buffer size %d, required %d\n",
-             cbInfoBuffer, cbToCopy));
-        RxContext->InformationToReturn = cbToCopy;
-    }
-
-    Log(("VBOXSF: MrxQueryVolumeInfo: cbToCopy = %d, LengthRemaining = %d, Status = 0x%08X\n",
-         cbToCopy, RxContext->Info.LengthRemaining, Status));
-
-    return Status;
-}
-
-NTSTATUS VBoxMRxQueryFileInfo(IN PRX_CONTEXT RxContext)
-{
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    RxCaptureFcb;
-    RxCaptureFobx;
-
-    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
-    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
-    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
-
-    PUNICODE_STRING FileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
-    FILE_INFORMATION_CLASS FunctionalityRequested = RxContext->Info.FileInformationClass;
-    PCHAR pInfoBuffer = (PCHAR)RxContext->Info.Buffer;
-    uint32_t cbInfoBuffer = RxContext->Info.Length;
-    ULONG *pLengthRemaining = (PULONG) & RxContext->Info.LengthRemaining;
-
-    int vrc = 0;
-
-    ULONG cbToCopy = 0;
-    uint8_t *pHGCMBuffer = 0;
-    uint32_t cbHGCMBuffer;
-    PSHFLFSOBJINFO pFileEntry = NULL;
-
-    if (!pLengthRemaining)
-    {
-        Log(("VBOXSF: MrxQueryFileInfo: length pointer is NULL!\n"));
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    Log(("VBOXSF: MrxQueryFileInfo: InfoBuffer = %p, Size = %d bytes, LenRemain = %d bytes\n",
-         pInfoBuffer, cbInfoBuffer, *pLengthRemaining));
-
-    if (!pVBoxFobx)
-    {
-        Log(("VBOXSF: MrxQueryFileInfo: pVBoxFobx is NULL!\n"));
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    if (!pInfoBuffer)
-    {
-        Log(("VBOXSF: MrxQueryFileInfo: pInfoBuffer is NULL!\n"));
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    if (pVBoxFobx->FileStandardInfo.Directory == TRUE)
-    {
-        Log(("VBOXSF: MrxQueryFileInfo: Directory -> Copy info retrieved during the create call\n"));
-        Status = STATUS_SUCCESS;
-
-        switch (FunctionalityRequested)
-        {
-            case FileBasicInformation:
-            {
-                PFILE_BASIC_INFORMATION pInfo = (PFILE_BASIC_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryFileInfo: FileBasicInformation\n"));
-
-                cbToCopy = sizeof(FILE_BASIC_INFORMATION);
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    *pInfo = pVBoxFobx->FileBasicInfo;
-                    Log(("VBOXSF: MrxQueryFileInfo: FileBasicInformation: File attributes: 0x%x\n",
-                         pInfo->FileAttributes));
-                }
-                else
-                {
-                    Status = STATUS_BUFFER_TOO_SMALL;
-                }
-                break;
-            }
-
-            case FileStandardInformation:
-            {
-                PFILE_STANDARD_INFORMATION pInfo = (PFILE_STANDARD_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryFileInfo: FileStandardInformation\n"));
-
-                cbToCopy = sizeof(FILE_STANDARD_INFORMATION);
-
-                if (*pLengthRemaining >= cbToCopy)
-                    *pInfo = pVBoxFobx->FileStandardInfo;
-                else
-                    Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            case FileNamesInformation:
-            {
-                PFILE_NAMES_INFORMATION pInfo = (PFILE_NAMES_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryFileInfo: FileNamesInformation\n"));
-
-                cbToCopy = sizeof(FILE_NAMES_INFORMATION);
-                /* And size in bytes of the WCHAR name. */
-                cbToCopy += FileName->Length;
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    RtlZeroMemory(pInfo, cbToCopy);
-
-                    pInfo->FileNameLength = FileName->Length;
-
-                    RtlCopyMemory(pInfo->FileName, FileName->Buffer, FileName->Length);
-                    pInfo->FileName[FileName->Length] = 0; /* FILE_NAMES_INFORMATION had space for the nul. */
-                }
-                else
-                    Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            case FileInternalInformation:
-            {
-                PFILE_INTERNAL_INFORMATION pInfo = (PFILE_INTERNAL_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryFileInfo: FileInternalInformation\n"));
-
-                cbToCopy = sizeof(FILE_INTERNAL_INFORMATION);
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    /* A 8-byte file reference number for the file. */
-                    pInfo->IndexNumber.QuadPart = (ULONG_PTR)capFcb;
-                }
-                else
-                    Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-            case FileEaInformation:
-            {
-                PFILE_EA_INFORMATION pInfo = (PFILE_EA_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryFileInfo: FileEaInformation\n"));
-
-                cbToCopy = sizeof(FILE_EA_INFORMATION);
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    pInfo->EaSize = 0;
-                }
-                else
-                    Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            case FileNetworkOpenInformation:
-            {
-                PFILE_NETWORK_OPEN_INFORMATION pInfo = (PFILE_NETWORK_OPEN_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryFileInfo: FileNetworkOpenInformation\n"));
-
-                cbToCopy = sizeof(FILE_NETWORK_OPEN_INFORMATION);
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    pInfo->CreationTime   = pVBoxFobx->FileBasicInfo.CreationTime;
-                    pInfo->LastAccessTime = pVBoxFobx->FileBasicInfo.LastAccessTime;
-                    pInfo->LastWriteTime  = pVBoxFobx->FileBasicInfo.LastWriteTime;
-                    pInfo->ChangeTime     = pVBoxFobx->FileBasicInfo.ChangeTime;
-                    pInfo->AllocationSize.QuadPart = 0;
-                    pInfo->EndOfFile.QuadPart      = 0;
-                    pInfo->FileAttributes = pVBoxFobx->FileBasicInfo.FileAttributes;
-                }
-                else
-                    Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            case FileStreamInformation:
-                Log(("VBOXSF: MrxQueryFileInfo: FileStreamInformation: not supported\n"));
-                Status = STATUS_INVALID_PARAMETER;
-                goto end;
-
-            default:
-                Log(("VBOXSF: MrxQueryFileInfo: Not supported FunctionalityRequested %d!\n",
-                     FunctionalityRequested));
-                Status = STATUS_INVALID_PARAMETER;
-                goto end;
-        }
-    }
-    else /* Entry is a file. */
-    {
-        cbHGCMBuffer = RT_MAX(cbInfoBuffer, PAGE_SIZE);
-        pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbHGCMBuffer);
-
-        if (!pHGCMBuffer)
-            return STATUS_INSUFFICIENT_RESOURCES;
-
-        Assert(pVBoxFobx && pNetRootExtension && pDeviceExtension);
-        vrc = VbglR0SfFsInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
-                             SHFL_INFO_GET | SHFL_INFO_FILE, &cbHGCMBuffer, (PSHFLDIRINFO)pHGCMBuffer);
-
-        if (vrc != VINF_SUCCESS)
-        {
-            Status = VBoxErrorToNTStatus(vrc);
-            goto end;
-        }
-
-        pFileEntry = (PSHFLFSOBJINFO)pHGCMBuffer;
-        Status = STATUS_SUCCESS;
-
-        switch (FunctionalityRequested)
-        {
-            case FileBasicInformation:
-            {
-                PFILE_BASIC_INFORMATION pInfo = (PFILE_BASIC_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryFileInfo: FileBasicInformation\n"));
-
-                cbToCopy = sizeof(FILE_BASIC_INFORMATION);
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    pInfo->CreationTime.QuadPart   = RTTimeSpecGetNtTime(&pFileEntry->BirthTime); /* Ridiculous name. */
-                    pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->AccessTime);
-                    pInfo->LastWriteTime.QuadPart  = RTTimeSpecGetNtTime(&pFileEntry->ModificationTime);
-                    pInfo->ChangeTime.QuadPart     = RTTimeSpecGetNtTime(&pFileEntry->ChangeTime);
-                    pInfo->FileAttributes          = VBoxToNTFileAttributes(pFileEntry->Attr.fMode);
-
-                    Log(("VBOXSF: MrxQueryFileInfo: FileBasicInformation: File attributes = 0x%x\n",
-                         pInfo->FileAttributes));
-                }
-                else
-                    Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            case FileStandardInformation:
-            {
-                PFILE_STANDARD_INFORMATION pInfo = (PFILE_STANDARD_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryFileInfo: FileStandardInformation\n"));
-
-                cbToCopy = sizeof(FILE_STANDARD_INFORMATION);
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    pInfo->AllocationSize.QuadPart = pFileEntry->cbAllocated;
-                    pInfo->EndOfFile.QuadPart      = pFileEntry->cbObject;
-                    pInfo->NumberOfLinks           = 1; /** @todo 0? */
-                    pInfo->DeletePending           = FALSE;
-
-                    if (pFileEntry->Attr.fMode & RTFS_DOS_DIRECTORY)
-                        pInfo->Directory = TRUE;
-                    else
-                        pInfo->Directory = FALSE;
-                }
-                else
-                    Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            case FileNamesInformation:
-            {
-                PFILE_NAMES_INFORMATION pInfo = (PFILE_NAMES_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryFileInfo: FileNamesInformation\n"));
-
-                cbToCopy = sizeof(FILE_NAMES_INFORMATION);
-                /* And size in bytes of the WCHAR name. */
-                cbToCopy += FileName->Length;
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    RtlZeroMemory(pInfo, cbToCopy);
-
-                    pInfo->FileNameLength = FileName->Length;
-
-                    RtlCopyMemory(pInfo->FileName, FileName->Buffer, FileName->Length);
-                    pInfo->FileName[FileName->Length] = 0; /* FILE_NAMES_INFORMATION had space for the nul. */
-                }
-                else
-                    Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            case FileInternalInformation:
-            {
-                PFILE_INTERNAL_INFORMATION pInfo = (PFILE_INTERNAL_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryFileInfo: FileInternalInformation\n"));
-
-                cbToCopy = sizeof(FILE_INTERNAL_INFORMATION);
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    /* A 8-byte file reference number for the file. */
-                    pInfo->IndexNumber.QuadPart = (ULONG_PTR)capFcb;
-                }
-                else
-                    Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            case FileEaInformation:
-            {
-                PFILE_EA_INFORMATION pInfo = (PFILE_EA_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryFileInfo: FileEaInformation\n"));
-
-                cbToCopy = sizeof(FILE_EA_INFORMATION);
-
-                if (*pLengthRemaining >= cbToCopy)
-                    pInfo->EaSize = 0;
-                else
-                    Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            case FileAttributeTagInformation:
-            {
-                PFILE_ATTRIBUTE_TAG_INFORMATION pInfo = (PFILE_ATTRIBUTE_TAG_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryFileInfo: FileAttributeTagInformation\n"));
-
-                cbToCopy = sizeof(FILE_ATTRIBUTE_TAG_INFORMATION);
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    pInfo->FileAttributes = VBoxToNTFileAttributes(pFileEntry->Attr.fMode);
-                    pInfo->ReparseTag = 0;
-                }
-                else
-                    Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            case FileEndOfFileInformation:
-            {
-                PFILE_END_OF_FILE_INFORMATION pInfo = (PFILE_END_OF_FILE_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryFileInfo: FileEndOfFileInformation\n"));
-
-                cbToCopy = sizeof(FILE_END_OF_FILE_INFORMATION);
-
-                if (*pLengthRemaining >= cbToCopy)
-                    pInfo->EndOfFile.QuadPart = pFileEntry->cbObject;
-                else
-                    Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            case FileAllocationInformation:
-            {
-                PFILE_ALLOCATION_INFORMATION pInfo = (PFILE_ALLOCATION_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryFileInfo: FileAllocationInformation\n"));
-
-                cbToCopy = sizeof(FILE_ALLOCATION_INFORMATION);
-
-                if (*pLengthRemaining >= cbToCopy)
-                    pInfo->AllocationSize.QuadPart = pFileEntry->cbAllocated;
-                else
-                    Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            case FileNetworkOpenInformation:
-            {
-                PFILE_NETWORK_OPEN_INFORMATION pInfo = (PFILE_NETWORK_OPEN_INFORMATION)pInfoBuffer;
-                Log(("VBOXSF: MrxQueryFileInfo: FileNetworkOpenInformation\n"));
-
-                cbToCopy = sizeof(FILE_NETWORK_OPEN_INFORMATION);
-
-                if (*pLengthRemaining >= cbToCopy)
-                {
-                    pInfo->CreationTime.QuadPart   = RTTimeSpecGetNtTime(&pFileEntry->BirthTime); /* Ridiculous name. */
-                    pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->AccessTime);
-                    pInfo->LastWriteTime.QuadPart  = RTTimeSpecGetNtTime(&pFileEntry->ModificationTime);
-                    pInfo->ChangeTime.QuadPart     = RTTimeSpecGetNtTime(&pFileEntry->ChangeTime);
-                    pInfo->AllocationSize.QuadPart = pFileEntry->cbAllocated;
-                    pInfo->EndOfFile.QuadPart      = pFileEntry->cbObject;
-                    pInfo->FileAttributes          = VBoxToNTFileAttributes(pFileEntry->Attr.fMode);
-                }
-                else
-                    Status = STATUS_BUFFER_TOO_SMALL;
-                break;
-            }
-
-            case FileStreamInformation:
-                Log(("VBOXSF: MrxQueryFileInfo: FileStreamInformation: not supported\n"));
-                Status = STATUS_INVALID_PARAMETER;
-                goto end;
-
-            default:
-                Log(("VBOXSF: MrxQueryFileInfo: Not supported FunctionalityRequested %d!\n",
-                     FunctionalityRequested));
-                Status = STATUS_INVALID_PARAMETER;
-                goto end;
-        }
-    }
-
-    if (Status == STATUS_SUCCESS)
-    {
-        if (*pLengthRemaining < cbToCopy)
-        {
-            /* This situation must be already taken into account by the above code. */
-            AssertMsgFailed(("VBOXSF: MrxQueryFileInfo: Length remaining is below 0! (%d - %d)!\n",
-                             *pLengthRemaining, cbToCopy));
-            Status = STATUS_BUFFER_TOO_SMALL;
-        }
-        else
-        {
-            pInfoBuffer += cbToCopy;
-            *pLengthRemaining -= cbToCopy;
-        }
-    }
-
-end:
-    if (Status == STATUS_BUFFER_TOO_SMALL)
-    {
-        Log(("VBOXSF: MrxQueryFileInfo: Buffer too small %d, required %d!\n",
-             *pLengthRemaining, cbToCopy));
-        RxContext->InformationToReturn = cbToCopy;
-    }
-
-    if (pHGCMBuffer)
-        vbsfFreeNonPagedMem(pHGCMBuffer);
-
-    if (Status == STATUS_SUCCESS)
-    {
-        Log(("VBOXSF: MrxQueryFileInfo: Remaining length = %d\n",
-             *pLengthRemaining));
-    }
-
-    Log(("VBOXSF: MrxQueryFileInfo: Returned 0x%08X\n", Status));
-    return Status;
-}
-
-NTSTATUS VBoxMRxSetFileInfo(IN PRX_CONTEXT RxContext)
-{
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    RxCaptureFcb;
-    RxCaptureFobx;
-
-    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
-    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
-    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
-
-    FILE_INFORMATION_CLASS FunctionalityRequested = RxContext->Info.FileInformationClass;
-    PVOID pInfoBuffer = (PVOID)RxContext->Info.Buffer;
-
-    int vrc;
-
-    uint8_t *pHGCMBuffer = NULL;
-    uint32_t cbBuffer = 0;
-
-    Log(("VBOXSF: MrxSetFileInfo: pInfoBuffer %p\n",
-         pInfoBuffer));
-
-    switch (FunctionalityRequested)
-    {
-        case FileBasicInformation:
-        {
-            PFILE_BASIC_INFORMATION pInfo = (PFILE_BASIC_INFORMATION)pInfoBuffer;
-            PSHFLFSOBJINFO pSHFLFileInfo;
-
-            Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: CreationTime   %RX64\n", pInfo->CreationTime.QuadPart));
-            Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: LastAccessTime %RX64\n", pInfo->LastAccessTime.QuadPart));
-            Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: LastWriteTime  %RX64\n", pInfo->LastWriteTime.QuadPart));
-            Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: ChangeTime     %RX64\n", pInfo->ChangeTime.QuadPart));
-            Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: FileAttributes %RX32\n", pInfo->FileAttributes));
-
-            /* When setting file attributes, a value of -1 indicates to the server that it MUST NOT change this attribute
-             * for all subsequent operations on the same file handle.
-             */
-            if (pInfo->CreationTime.QuadPart == -1)
-            {
-                pVBoxFobx->fKeepCreationTime = TRUE;
-                pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_CREATION_TIME;
-            }
-            if (pInfo->LastAccessTime.QuadPart == -1)
-            {
-                pVBoxFobx->fKeepLastAccessTime = TRUE;
-                pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_LASTACCESS_TIME;
-            }
-            if (pInfo->LastWriteTime.QuadPart == -1)
-            {
-                pVBoxFobx->fKeepLastWriteTime = TRUE;
-                pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_LASTWRITE_TIME;
-            }
-            if (pInfo->ChangeTime.QuadPart == -1)
-            {
-                pVBoxFobx->fKeepChangeTime = TRUE;
-                pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_CHANGE_TIME;
-            }
-
-            cbBuffer = sizeof(SHFLFSOBJINFO);
-            pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbBuffer);
-            if (!pHGCMBuffer)
-            {
-                AssertFailed();
-                return STATUS_INSUFFICIENT_RESOURCES;
-            }
-            RtlZeroMemory(pHGCMBuffer, cbBuffer);
-            pSHFLFileInfo = (PSHFLFSOBJINFO)pHGCMBuffer;
-
-            Log(("VBOXSF: MrxSetFileInfo: FileBasicInformation: keeps %d %d %d %d\n",
-                 pVBoxFobx->fKeepCreationTime, pVBoxFobx->fKeepLastAccessTime, pVBoxFobx->fKeepLastWriteTime, pVBoxFobx->fKeepChangeTime));
-
-            /* The properties, that need to be changed, are set to something other than zero */
-            if (pInfo->CreationTime.QuadPart && !pVBoxFobx->fKeepCreationTime)
-            {
-                RTTimeSpecSetNtTime(&pSHFLFileInfo->BirthTime, pInfo->CreationTime.QuadPart);
-                pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_CREATION_TIME;
-            }
-            if (pInfo->LastAccessTime.QuadPart && !pVBoxFobx->fKeepLastAccessTime)
-            {
-                RTTimeSpecSetNtTime(&pSHFLFileInfo->AccessTime, pInfo->LastAccessTime.QuadPart);
-                pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_LASTACCESS_TIME;
-            }
-            if (pInfo->LastWriteTime.QuadPart && !pVBoxFobx->fKeepLastWriteTime)
-            {
-                RTTimeSpecSetNtTime(&pSHFLFileInfo->ModificationTime, pInfo->LastWriteTime.QuadPart);
-                pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_LASTWRITE_TIME;
-            }
-            if (pInfo->ChangeTime.QuadPart && !pVBoxFobx->fKeepChangeTime)
-            {
-                RTTimeSpecSetNtTime(&pSHFLFileInfo->ChangeTime, pInfo->ChangeTime.QuadPart);
-                pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_CHANGE_TIME;
-            }
-            if (pInfo->FileAttributes)
-            {
-                pSHFLFileInfo->Attr.fMode = NTToVBoxFileAttributes(pInfo->FileAttributes);
-            }
-
-            Assert(pVBoxFobx && pNetRootExtension && pDeviceExtension);
-            vrc = VbglR0SfFsInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
-                                 SHFL_INFO_SET | SHFL_INFO_FILE, &cbBuffer, (PSHFLDIRINFO)pSHFLFileInfo);
-
-            if (vrc != VINF_SUCCESS)
-            {
-                Status = VBoxErrorToNTStatus(vrc);
-                goto end;
-            }
-            else
-            {
-                /* Update our internal copy. Ignore zero fields! */
-                if (pInfo->CreationTime.QuadPart && !pVBoxFobx->fKeepCreationTime)
-                    pVBoxFobx->FileBasicInfo.CreationTime = pInfo->CreationTime;
-                if (pInfo->LastAccessTime.QuadPart && !pVBoxFobx->fKeepLastAccessTime)
-                    pVBoxFobx->FileBasicInfo.LastAccessTime = pInfo->LastAccessTime;
-                if (pInfo->LastWriteTime.QuadPart && !pVBoxFobx->fKeepLastWriteTime)
-                    pVBoxFobx->FileBasicInfo.LastWriteTime = pInfo->LastWriteTime;
-                if (pInfo->ChangeTime.QuadPart && !pVBoxFobx->fKeepChangeTime)
-                    pVBoxFobx->FileBasicInfo.ChangeTime = pInfo->ChangeTime;
-                if (pInfo->FileAttributes)
-                    pVBoxFobx->FileBasicInfo.FileAttributes = pInfo->FileAttributes;
-            }
-
-            break;
-        }
-
-        case FileDispositionInformation:
-        {
-            PFILE_DISPOSITION_INFORMATION pInfo = (PFILE_DISPOSITION_INFORMATION)pInfoBuffer;
-
-            Log(("VBOXSF: MrxSetFileInfo: FileDispositionInformation: Delete = %d\n",
-                 pInfo->DeleteFile));
-
-            if (pInfo->DeleteFile && capFcb->OpenCount == 1)
-                Status = vbsfRemove(RxContext);
-            else
-                Status = STATUS_SUCCESS;
-            break;
-        }
-
-        case FilePositionInformation:
-        {
-#ifdef LOG_ENABLED
-            PFILE_POSITION_INFORMATION pInfo = (PFILE_POSITION_INFORMATION)pInfoBuffer;
-            Log(("VBOXSF: MrxSetFileInfo: FilePositionInformation: CurrentByteOffset = 0x%RX64. Unsupported!\n",
-                 pInfo->CurrentByteOffset.QuadPart));
-#endif
-
-            Status = STATUS_INVALID_PARAMETER;
-            break;
-        }
-
-        case FileAllocationInformation:
-        {
-            PFILE_ALLOCATION_INFORMATION pInfo = (PFILE_ALLOCATION_INFORMATION)pInfoBuffer;
-
-            Log(("VBOXSF: MrxSetFileInfo: FileAllocationInformation: new AllocSize = 0x%RX64, FileSize = 0x%RX64\n",
-                 pInfo->AllocationSize.QuadPart, capFcb->Header.FileSize.QuadPart));
-
-            /* Check if the new allocation size changes the file size. */
-            if (pInfo->AllocationSize.QuadPart > capFcb->Header.FileSize.QuadPart)
-            {
-                /* Ignore this request and return success. Shared folders do not distinguish between
-                 * AllocationSize and FileSize.
-                 */
-                Status = STATUS_SUCCESS;
-            }
-            else
-            {
-                /* Treat the request as a EndOfFile update. */
-                LARGE_INTEGER NewAllocationSize;
-                Status = vbsfSetEndOfFile(RxContext, &pInfo->AllocationSize, &NewAllocationSize);
-            }
-
-            break;
-        }
-
-        case FileEndOfFileInformation:
-        {
-            PFILE_END_OF_FILE_INFORMATION pInfo = (PFILE_END_OF_FILE_INFORMATION)pInfoBuffer;
-            LARGE_INTEGER NewAllocationSize;
-
-            Log(("VBOXSF: MrxSetFileInfo: FileEndOfFileInformation: new EndOfFile 0x%RX64, FileSize = 0x%RX64\n",
-                 pInfo->EndOfFile.QuadPart, capFcb->Header.FileSize.QuadPart));
-
-            Status = vbsfSetEndOfFile(RxContext, &pInfo->EndOfFile, &NewAllocationSize);
-
-            Log(("VBOXSF: MrxSetFileInfo: FileEndOfFileInformation: AllocSize = 0x%RX64, Status 0x%08X\n",
-                 NewAllocationSize.QuadPart, Status));
-
-            break;
-        }
-
-        case FileLinkInformation:
-        {
-#ifdef LOG_ENABLED
-            PFILE_LINK_INFORMATION pInfo = (PFILE_LINK_INFORMATION )pInfoBuffer;
-            Log(("VBOXSF: MrxSetFileInfo: FileLinkInformation: ReplaceIfExists = %d, RootDirectory = 0x%x = [%.*ls]. Not implemented!\n",
-                 pInfo->ReplaceIfExists, pInfo->RootDirectory, pInfo->FileNameLength / sizeof(WCHAR), pInfo->FileName));
-#endif
-
-            Status = STATUS_NOT_IMPLEMENTED;
-            break;
-        }
-
-        case FileRenameInformation:
-        {
-#ifdef LOG_ENABLED
-            PFILE_RENAME_INFORMATION pInfo = (PFILE_RENAME_INFORMATION)pInfoBuffer;
-            Log(("VBOXSF: MrxSetFileInfo: FileRenameInformation: ReplaceIfExists = %d, RootDirectory = 0x%x = [%.*ls]\n",
-                 pInfo->ReplaceIfExists, pInfo->RootDirectory, pInfo->FileNameLength / sizeof(WCHAR), pInfo->FileName));
-#endif
-
-            Status = vbsfRename(RxContext, FileRenameInformation, pInfoBuffer, RxContext->Info.Length);
-            break;
-        }
-
-        default:
-            Log(("VBOXSF: MrxSetFileInfo: Not supported FunctionalityRequested %d!\n",
-                 FunctionalityRequested));
-            Status = STATUS_INVALID_PARAMETER;
-            break;
-    }
-
-end:
-    if (pHGCMBuffer)
-        vbsfFreeNonPagedMem(pHGCMBuffer);
-
-    Log(("VBOXSF: MrxSetFileInfo: Returned 0x%08X\n", Status));
-    return Status;
-}
-
-NTSTATUS VBoxMRxSetFileInfoAtCleanup(IN PRX_CONTEXT RxContext)
-{
-    RT_NOREF(RxContext);
-    Log(("VBOXSF: MRxSetFileInfoAtCleanup\n"));
-    return STATUS_SUCCESS;
-}
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/driver/info.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/driver/info.cpp	(revision 78302)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/driver/info.cpp	(revision 78302)
@@ -0,0 +1,1533 @@
+/* $Id$ */
+/** @file
+ * VirtualBox Windows Guest Shared Folders FSD - Information Querying & Setting Routines.
+ */
+
+/*
+ * Copyright (C) 2012-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "vbsf.h"
+#include <iprt/err.h>
+
+
+/** Macro for copying a SHFLSTRING file name into a FILE_DIRECTORY_INFORMATION structure. */
+#define INIT_FILE_NAME(obj, str) \
+    do { \
+        ULONG cbLength = (str).u16Length; \
+        (obj)->FileNameLength = cbLength; \
+        RtlCopyMemory((obj)->FileName, &(str).String.ucs2[0], cbLength + 2); \
+    } while (0)
+
+NTSTATUS VBoxMRxQueryDirectory(IN OUT PRX_CONTEXT RxContext)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    RxCaptureFobx;
+    RxCaptureFcb;
+
+    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
+    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
+
+    PUNICODE_STRING DirectoryName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
+    PUNICODE_STRING Template = &capFobx->UnicodeQueryTemplate;
+    FILE_INFORMATION_CLASS FileInformationClass = RxContext->Info.FileInformationClass;
+    PCHAR pInfoBuffer = (PCHAR)RxContext->Info.Buffer;
+    LONG cbMaxSize = RxContext->Info.Length;
+    LONG *pLengthRemaining = (LONG *)&RxContext->Info.LengthRemaining;
+
+    LONG cbToCopy;
+    int vrc;
+    uint8_t *pHGCMBuffer;
+    uint32_t index, fSFFlags, cFiles, u32BufSize;
+    LONG cbHGCMBuffer;
+    PSHFLDIRINFO pDirEntry;
+
+    ULONG *pNextOffset = 0;
+    PSHFLSTRING ParsedPath = NULL;
+
+    Log(("VBOXSF: MrxQueryDirectory: FileInformationClass %d, pVBoxFobx %p, hFile %RX64, pInfoBuffer %p\n",
+         FileInformationClass, pVBoxFobx, pVBoxFobx->hFile, pInfoBuffer));
+
+    if (!pVBoxFobx)
+    {
+        Log(("VBOXSF: MrxQueryDirectory: pVBoxFobx is invalid!\n"));
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if (!DirectoryName)
+        return STATUS_INVALID_PARAMETER;
+
+    if (DirectoryName->Length == 0)
+        Log(("VBOXSF: MrxQueryDirectory: DirectoryName = \\ (null string)\n"));
+    else
+        Log(("VBOXSF: MrxQueryDirectory: DirectoryName = %.*ls\n",
+             DirectoryName->Length / sizeof(WCHAR), DirectoryName->Buffer));
+
+    if (!Template)
+        return STATUS_INVALID_PARAMETER;
+
+    if (Template->Length == 0)
+        Log(("VBOXSF: MrxQueryDirectory: Template = \\ (null string)\n"));
+    else
+        Log(("VBOXSF: MrxQueryDirectory: Template = %.*ls\n",
+             Template->Length / sizeof(WCHAR), Template->Buffer));
+
+    cbHGCMBuffer = RT_MAX(cbMaxSize, PAGE_SIZE);
+
+    Log(("VBOXSF: MrxQueryDirectory: Allocating cbHGCMBuffer = %d\n",
+         cbHGCMBuffer));
+
+    pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbHGCMBuffer);
+    if (!pHGCMBuffer)
+    {
+        AssertFailed();
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Assume start from the beginning. */
+    index = 0;
+    if (RxContext->QueryDirectory.IndexSpecified == TRUE)
+    {
+        Log(("VBOXSF: MrxQueryDirectory: Index specified %d\n",
+             index));
+        index = RxContext->QueryDirectory.FileIndex;
+    }
+
+    fSFFlags = SHFL_LIST_NONE;
+    if (RxContext->QueryDirectory.ReturnSingleEntry == TRUE)
+    {
+        Log(("VBOXSF: MrxQueryDirectory: Query single entry\n"));
+        fSFFlags |= SHFL_LIST_RETURN_ONE;
+    }
+    if (   RxContext->QueryDirectory.RestartScan == TRUE
+        && RxContext->QueryDirectory.InitialQuery == FALSE)
+    {
+        Log(("VBOXSF: MrxQueryDirectory: Restart scan\n"));
+        fSFFlags |= SHFL_LIST_RESTART;
+    }
+
+    if (Template->Length)
+    {
+        ULONG ParsedPathSize, cch;
+
+        /* Calculate size required for parsed path: dir + \ + template + 0. */
+        ParsedPathSize = SHFLSTRING_HEADER_SIZE + Template->Length + sizeof(WCHAR);
+        if (DirectoryName->Length)
+            ParsedPathSize += DirectoryName->Length + sizeof(WCHAR);
+        Log(("VBOXSF: MrxQueryDirectory: ParsedPathSize = %d\n", ParsedPathSize));
+
+        ParsedPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);
+        if (!ParsedPath)
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto end;
+        }
+
+        if (!ShflStringInitBuffer(ParsedPath, ParsedPathSize))
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto end;
+        }
+
+        cch = 0;
+        if (DirectoryName->Length)
+        {
+            /* Copy directory name into ParsedPath. */
+            RtlCopyMemory(ParsedPath->String.ucs2, DirectoryName->Buffer, DirectoryName->Length);
+            cch += DirectoryName->Length / sizeof(WCHAR);
+
+            /* Add terminating backslash. */
+            ParsedPath->String.ucs2[cch] = L'\\';
+            cch++;
+        }
+
+        RtlCopyMemory (&ParsedPath->String.ucs2[cch], Template->Buffer, Template->Length);
+        cch += Template->Length / sizeof(WCHAR);
+
+        /* Add terminating nul. */
+        ParsedPath->String.ucs2[cch] = 0;
+
+        /* cch is the number of chars without trailing nul. */
+        ParsedPath->u16Length = (uint16_t)(cch * sizeof(WCHAR));
+
+        AssertMsg(ParsedPath->u16Length + sizeof(WCHAR) == ParsedPath->u16Size,
+                  ("u16Length %d, u16Size %d\n", ParsedPath->u16Length, ParsedPath->u16Size));
+
+        Log(("VBOXSF: MrxQueryDirectory: ParsedPath = %.*ls\n",
+             ParsedPath->u16Length / sizeof(WCHAR), ParsedPath->String.ucs2));
+    }
+
+    cFiles = 0;
+
+    /* VbglR0SfDirInfo requires a pointer to uint32_t. */
+    u32BufSize = cbHGCMBuffer;
+
+    Log(("VBOXSF: MrxQueryDirectory: CallDirInfo: File = 0x%08x, Flags = 0x%08x, Index = %d, u32BufSize = %d\n",
+         pVBoxFobx->hFile, fSFFlags, index, u32BufSize));
+    vrc = VbglR0SfDirInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
+                          ParsedPath, fSFFlags, index, &u32BufSize, (PSHFLDIRINFO)pHGCMBuffer, &cFiles);
+    Log(("VBOXSF: MrxQueryDirectory: u32BufSize after CallDirInfo = %d, rc = %Rrc\n",
+         u32BufSize, vrc));
+
+    switch (vrc)
+    {
+        case VINF_SUCCESS:
+            /* Nothing to do here. */
+            break;
+
+        case VERR_NO_TRANSLATION:
+            Log(("VBOXSF: MrxQueryDirectory: Host could not translate entry!\n"));
+            break;
+
+        case VERR_NO_MORE_FILES:
+            if (cFiles <= 0) /* VERR_NO_MORE_FILES appears at the first lookup when just returning the current dir ".".
+                              * So we also have to check for the cFiles counter. */
+            {
+                /* Not an error, but we have to handle the return value. */
+                Log(("VBOXSF: MrxQueryDirectory: Host reported no more files!\n"));
+
+                if (RxContext->QueryDirectory.InitialQuery)
+                {
+                    /* First call. MSDN on FindFirstFile: "If the function fails because no matching files
+                     * can be found, the GetLastError function returns ERROR_FILE_NOT_FOUND."
+                     * So map this rc to file not found.
+                     */
+                    Status = STATUS_NO_SUCH_FILE;
+                }
+                else
+                {
+                    /* Search continued. */
+                    Status = STATUS_NO_MORE_FILES;
+                }
+            }
+            break;
+
+        case VERR_FILE_NOT_FOUND:
+            Status = STATUS_NO_SUCH_FILE;
+            Log(("VBOXSF: MrxQueryDirectory: no such file!\n"));
+            break;
+
+        default:
+            Status = VBoxErrorToNTStatus(vrc);
+            Log(("VBOXSF: MrxQueryDirectory: Error %Rrc from CallDirInfo (cFiles=%d)!\n",
+                 vrc, cFiles));
+            break;
+    }
+
+    if (Status != STATUS_SUCCESS)
+        goto end;
+
+    /* Verify that the returned buffer length is not greater than the original one. */
+    if (u32BufSize > (uint32_t)cbHGCMBuffer)
+    {
+        Log(("VBOXSF: MrxQueryDirectory: returned buffer size (%u) is invalid!!!\n",
+             u32BufSize));
+        Status = STATUS_INVALID_NETWORK_RESPONSE;
+        goto end;
+    }
+
+    /* How many bytes remain in the buffer. */
+    cbHGCMBuffer = u32BufSize;
+
+    pDirEntry = (PSHFLDIRINFO)pHGCMBuffer;
+    Status = STATUS_SUCCESS;
+
+    Log(("VBOXSF: MrxQueryDirectory: cFiles=%d, Length=%d\n",
+         cFiles, cbHGCMBuffer));
+
+    while ((*pLengthRemaining) && (cFiles > 0) && (pDirEntry != NULL))
+    {
+        int cbEntry = RT_UOFFSETOF(SHFLDIRINFO, name.String) + pDirEntry->name.u16Size;
+
+        if (cbEntry > cbHGCMBuffer)
+        {
+            Log(("VBOXSF: MrxQueryDirectory: Entry size (%d) exceeds the buffer size (%d)!!!\n",
+                 cbEntry, cbHGCMBuffer));
+            Status = STATUS_INVALID_NETWORK_RESPONSE;
+            goto end;
+        }
+
+        switch (FileInformationClass)
+        {
+            case FileDirectoryInformation:
+            {
+                PFILE_DIRECTORY_INFORMATION pInfo = (PFILE_DIRECTORY_INFORMATION)pInfoBuffer;
+                Log(("VBOXSF: MrxQueryDirectory: FileDirectoryInformation\n"));
+
+                cbToCopy = sizeof(FILE_DIRECTORY_INFORMATION);
+                /* Struct already contains one char for null terminator. */
+                cbToCopy += pDirEntry->name.u16Size;
+
+                if (*pLengthRemaining >= cbToCopy)
+                {
+                    RtlZeroMemory(pInfo, cbToCopy);
+
+                    pInfo->CreationTime.QuadPart   = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
+                    pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
+                    pInfo->LastWriteTime.QuadPart  = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
+                    pInfo->ChangeTime.QuadPart     = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
+                    pInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
+                    pInfo->EndOfFile.QuadPart      = pDirEntry->Info.cbObject;
+                    pInfo->FileIndex               = index;
+                    pInfo->FileAttributes          = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
+
+                    INIT_FILE_NAME(pInfo, pDirEntry->name);
+
+                    /* Align to 8 byte boundary */
+                    cbToCopy = RT_ALIGN(cbToCopy, sizeof(LONGLONG));
+                    pInfo->NextEntryOffset = cbToCopy;
+                    pNextOffset = &pInfo->NextEntryOffset;
+                }
+                else
+                {
+                    pInfo->NextEntryOffset = 0; /* last item */
+                    Status = STATUS_BUFFER_OVERFLOW;
+                }
+                break;
+            }
+
+            case FileFullDirectoryInformation:
+            {
+                PFILE_FULL_DIR_INFORMATION pInfo = (PFILE_FULL_DIR_INFORMATION)pInfoBuffer;
+                Log(("VBOXSF: MrxQueryDirectory: FileFullDirectoryInformation\n"));
+
+                cbToCopy = sizeof(FILE_FULL_DIR_INFORMATION);
+                /* Struct already contains one char for null terminator. */
+                cbToCopy += pDirEntry->name.u16Size;
+
+                if (*pLengthRemaining >= cbToCopy)
+                {
+                    RtlZeroMemory(pInfo, cbToCopy);
+
+                    pInfo->CreationTime.QuadPart   = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
+                    pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
+                    pInfo->LastWriteTime.QuadPart  = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
+                    pInfo->ChangeTime.QuadPart     = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
+                    pInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
+                    pInfo->EndOfFile.QuadPart      = pDirEntry->Info.cbObject;
+                    pInfo->EaSize                  = 0;
+                    pInfo->FileIndex               = index;
+                    pInfo->FileAttributes          = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
+
+                    INIT_FILE_NAME(pInfo, pDirEntry->name);
+
+                    /* Align to 8 byte boundary */
+                    cbToCopy = RT_ALIGN(cbToCopy, sizeof(LONGLONG));
+                    pInfo->NextEntryOffset = cbToCopy;
+                    pNextOffset = &pInfo->NextEntryOffset;
+                }
+                else
+                {
+                    pInfo->NextEntryOffset = 0; /* last item */
+                    Status = STATUS_BUFFER_OVERFLOW;
+                }
+                break;
+            }
+
+            case FileBothDirectoryInformation:
+            {
+                PFILE_BOTH_DIR_INFORMATION pInfo = (PFILE_BOTH_DIR_INFORMATION)pInfoBuffer;
+                Log(("VBOXSF: MrxQueryDirectory: FileBothDirectoryInformation\n"));
+
+                cbToCopy = sizeof(FILE_BOTH_DIR_INFORMATION);
+                /* struct already contains one char for null terminator */
+                cbToCopy += pDirEntry->name.u16Size;
+
+                if (*pLengthRemaining >= cbToCopy)
+                {
+                    RtlZeroMemory(pInfo, cbToCopy);
+
+                    pInfo->CreationTime.QuadPart   = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
+                    pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
+                    pInfo->LastWriteTime.QuadPart  = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
+                    pInfo->ChangeTime.QuadPart     = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
+                    pInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
+                    pInfo->EndOfFile.QuadPart      = pDirEntry->Info.cbObject;
+                    pInfo->EaSize                  = 0;
+                    pInfo->ShortNameLength         = 0; /** @todo ? */
+                    pInfo->FileIndex               = index;
+                    pInfo->FileAttributes          = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
+
+                    INIT_FILE_NAME(pInfo, pDirEntry->name);
+
+                    Log(("VBOXSF: MrxQueryDirectory: FileBothDirectoryInformation cbAlloc = %x cbObject = %x\n",
+                         pDirEntry->Info.cbAllocated, pDirEntry->Info.cbObject));
+                    Log(("VBOXSF: MrxQueryDirectory: FileBothDirectoryInformation cbToCopy = %d, name size=%d name len=%d\n",
+                         cbToCopy, pDirEntry->name.u16Size, pDirEntry->name.u16Length));
+                    Log(("VBOXSF: MrxQueryDirectory: FileBothDirectoryInformation File name %.*ls (DirInfo)\n",
+                         pInfo->FileNameLength / sizeof(WCHAR), pInfo->FileName));
+                    Log(("VBOXSF: MrxQueryDirectory: FileBothDirectoryInformation File name %.*ls (DirEntry)\n",
+                         pDirEntry->name.u16Size / sizeof(WCHAR), pDirEntry->name.String.ucs2));
+
+                    /* Align to 8 byte boundary. */
+                    cbToCopy = RT_ALIGN(cbToCopy, sizeof(LONGLONG));
+                    pInfo->NextEntryOffset = cbToCopy;
+                    pNextOffset = &pInfo->NextEntryOffset;
+                }
+                else
+                {
+                    pInfo->NextEntryOffset = 0; /* Last item. */
+                    Status = STATUS_BUFFER_OVERFLOW;
+                }
+                break;
+            }
+
+            case FileIdBothDirectoryInformation:
+            {
+                PFILE_ID_BOTH_DIR_INFORMATION pInfo = (PFILE_ID_BOTH_DIR_INFORMATION)pInfoBuffer;
+                Log(("VBOXSF: MrxQueryDirectory: FileIdBothDirectoryInformation\n"));
+
+                cbToCopy = sizeof(FILE_ID_BOTH_DIR_INFORMATION);
+                /* struct already contains one char for null terminator */
+                cbToCopy += pDirEntry->name.u16Size;
+
+                if (*pLengthRemaining >= cbToCopy)
+                {
+                    RtlZeroMemory(pInfo, cbToCopy);
+
+                    pInfo->CreationTime.QuadPart   = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
+                    pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
+                    pInfo->LastWriteTime.QuadPart  = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
+                    pInfo->ChangeTime.QuadPart     = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
+                    pInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
+                    pInfo->EndOfFile.QuadPart      = pDirEntry->Info.cbObject;
+                    pInfo->EaSize                  = 0;
+                    pInfo->ShortNameLength         = 0; /** @todo ? */
+                    pInfo->EaSize                  = 0;
+                    pInfo->FileId.QuadPart         = 0;
+                    pInfo->FileAttributes          = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
+
+                    INIT_FILE_NAME(pInfo, pDirEntry->name);
+
+                    Log(("VBOXSF: MrxQueryDirectory: FileIdBothDirectoryInformation cbAlloc = 0x%RX64 cbObject = 0x%RX64\n",
+                         pDirEntry->Info.cbAllocated, pDirEntry->Info.cbObject));
+                    Log(("VBOXSF: MrxQueryDirectory: FileIdBothDirectoryInformation cbToCopy = %d, name size=%d name len=%d\n",
+                         cbToCopy, pDirEntry->name.u16Size, pDirEntry->name.u16Length));
+                    Log(("VBOXSF: MrxQueryDirectory: FileIdBothDirectoryInformation File name %.*ls (DirInfo)\n",
+                         pInfo->FileNameLength / sizeof(WCHAR), pInfo->FileName));
+                    Log(("VBOXSF: MrxQueryDirectory: FileIdBothDirectoryInformation File name %.*ls (DirEntry)\n",
+                         pDirEntry->name.u16Size / sizeof(WCHAR), pDirEntry->name.String.ucs2));
+
+                    /* Align to 8 byte boundary. */
+                    cbToCopy = RT_ALIGN(cbToCopy, sizeof(LONGLONG));
+                    pInfo->NextEntryOffset = cbToCopy;
+                    pNextOffset = &pInfo->NextEntryOffset;
+                }
+                else
+                {
+                    pInfo->NextEntryOffset = 0; /* Last item. */
+                    Status = STATUS_BUFFER_OVERFLOW;
+                }
+                break;
+            }
+
+            case FileNamesInformation:
+            {
+                PFILE_NAMES_INFORMATION pInfo = (PFILE_NAMES_INFORMATION)pInfoBuffer;
+                Log(("VBOXSF: MrxQueryDirectory: FileNamesInformation\n"));
+
+                cbToCopy = sizeof(FILE_NAMES_INFORMATION);
+                /* Struct already contains one char for null terminator. */
+                cbToCopy += pDirEntry->name.u16Size;
+
+                if (*pLengthRemaining >= cbToCopy)
+                {
+                    RtlZeroMemory(pInfo, cbToCopy);
+
+                    pInfo->FileIndex = index;
+
+                    INIT_FILE_NAME(pInfo, pDirEntry->name);
+
+                    Log(("VBOXSF: MrxQueryDirectory: FileNamesInformation: File name [%.*ls]\n",
+                         pInfo->FileNameLength / sizeof(WCHAR), pInfo->FileName));
+
+                    /* Align to 8 byte boundary. */
+                    cbToCopy = RT_ALIGN(cbToCopy, sizeof(LONGLONG));
+                    pInfo->NextEntryOffset = cbToCopy;
+                    pNextOffset = &pInfo->NextEntryOffset;
+                }
+                else
+                {
+                    pInfo->NextEntryOffset = 0; /* Last item. */
+                    Status = STATUS_BUFFER_OVERFLOW;
+                }
+                break;
+            }
+
+            default:
+                Log(("VBOXSF: MrxQueryDirectory: Not supported FileInformationClass %d!\n",
+                     FileInformationClass));
+                Status = STATUS_INVALID_PARAMETER;
+                goto end;
+        }
+
+        cbHGCMBuffer -= cbEntry;
+        pDirEntry = (PSHFLDIRINFO)((uintptr_t)pDirEntry + cbEntry);
+
+        Log(("VBOXSF: MrxQueryDirectory: %d bytes left in HGCM buffer\n",
+             cbHGCMBuffer));
+
+        if (*pLengthRemaining >= cbToCopy)
+        {
+            pInfoBuffer += cbToCopy;
+            *pLengthRemaining -= cbToCopy;
+        }
+        else
+            break;
+
+        if (RxContext->QueryDirectory.ReturnSingleEntry)
+            break;
+
+        /* More left? */
+        if (cbHGCMBuffer <= 0)
+            break;
+
+        index++; /* File Index. */
+
+        cFiles--;
+    }
+
+    if (pNextOffset)
+        *pNextOffset = 0; /* Last pInfo->NextEntryOffset should be set to zero! */
+
+end:
+    if (pHGCMBuffer)
+        vbsfFreeNonPagedMem(pHGCMBuffer);
+
+    if (ParsedPath)
+        vbsfFreeNonPagedMem(ParsedPath);
+
+    Log(("VBOXSF: MrxQueryDirectory: Returned 0x%08X\n",
+         Status));
+    return Status;
+}
+
+NTSTATUS VBoxMRxQueryVolumeInfo(IN OUT PRX_CONTEXT RxContext)
+{
+    NTSTATUS Status;
+
+    RxCaptureFcb;
+    RxCaptureFobx;
+
+    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
+    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
+
+    FS_INFORMATION_CLASS FsInformationClass = RxContext->Info.FsInformationClass;
+    PVOID pInfoBuffer = RxContext->Info.Buffer;
+    ULONG cbInfoBuffer = RxContext->Info.LengthRemaining;
+    ULONG cbToCopy = 0;
+    ULONG cbString = 0;
+
+    Log(("VBOXSF: MrxQueryVolumeInfo: pInfoBuffer = %p, cbInfoBuffer = %d\n",
+         RxContext->Info.Buffer, RxContext->Info.LengthRemaining));
+    Log(("VBOXSF: MrxQueryVolumeInfo: vboxFobx = %p, Handle = 0x%RX64\n",
+         pVBoxFobx, pVBoxFobx? pVBoxFobx->hFile: 0));
+
+    Status = STATUS_INVALID_PARAMETER;
+
+    switch (FsInformationClass)
+    {
+        case FileFsVolumeInformation:
+        {
+            PFILE_FS_VOLUME_INFORMATION pInfo = (PFILE_FS_VOLUME_INFORMATION)pInfoBuffer;
+
+            PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
+            PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
+
+            PWCHAR pRootName;
+            ULONG cbRootName;
+
+            PSHFLVOLINFO pShflVolInfo;
+            uint32_t cbHGCMBuffer;
+            uint8_t *pHGCMBuffer;
+            int vrc;
+
+            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsVolumeInformation\n"));
+
+            if (!pVBoxFobx)
+            {
+                Log(("VBOXSF: MrxQueryVolumeInfo: pVBoxFobx is NULL!\n"));
+                Status = STATUS_INVALID_PARAMETER;
+                break;
+            }
+
+            cbRootName = pNetRoot->pNetRootName->Length - pSrvCall->pSrvCallName->Length;
+            cbRootName -= sizeof(WCHAR); /* Remove the leading backslash. */
+            pRootName = pNetRoot->pNetRootName->Buffer + (pSrvCall->pSrvCallName->Length / sizeof(WCHAR));
+            pRootName++; /* Remove the leading backslash. */
+
+            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsVolumeInformation: Root name = %.*ls, %d bytes\n",
+                 cbRootName / sizeof(WCHAR), pRootName, cbRootName));
+
+            cbToCopy = FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel);
+
+            cbString  = VBOX_VOLNAME_PREFIX_SIZE;
+            cbString += cbRootName;
+            cbString += sizeof(WCHAR);
+
+            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsVolumeInformation: cbToCopy %d, cbString %d\n",
+                 cbToCopy, cbString));
+
+            if (cbInfoBuffer < cbToCopy)
+            {
+                Status = STATUS_BUFFER_TOO_SMALL;
+                break;
+            }
+
+            RtlZeroMemory(pInfo, cbToCopy);
+
+            /* Query serial number. */
+            cbHGCMBuffer = sizeof(SHFLVOLINFO);
+            pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbHGCMBuffer);
+            if (!pHGCMBuffer)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                break;
+            }
+
+            vrc = VbglR0SfFsInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
+                                 SHFL_INFO_GET | SHFL_INFO_VOLUME, &cbHGCMBuffer, (PSHFLDIRINFO)pHGCMBuffer);
+
+            if (vrc != VINF_SUCCESS)
+            {
+                Status = VBoxErrorToNTStatus(vrc);
+                vbsfFreeNonPagedMem(pHGCMBuffer);
+                break;
+            }
+
+            pShflVolInfo = (PSHFLVOLINFO)pHGCMBuffer;
+            pInfo->VolumeSerialNumber = pShflVolInfo->ulSerial;
+            vbsfFreeNonPagedMem(pHGCMBuffer);
+
+            pInfo->VolumeCreationTime.QuadPart = 0;
+            pInfo->SupportsObjects = FALSE;
+
+            if (cbInfoBuffer >= cbToCopy + cbString)
+            {
+                RtlCopyMemory(&pInfo->VolumeLabel[0],
+                              VBOX_VOLNAME_PREFIX,
+                              VBOX_VOLNAME_PREFIX_SIZE);
+                RtlCopyMemory(&pInfo->VolumeLabel[VBOX_VOLNAME_PREFIX_SIZE / sizeof(WCHAR)],
+                              pRootName,
+                              cbRootName);
+                pInfo->VolumeLabel[cbString / sizeof(WCHAR) -  1] = 0;
+            }
+            else
+            {
+                cbString = cbInfoBuffer - cbToCopy;
+
+                RtlCopyMemory(&pInfo->VolumeLabel[0],
+                              VBOX_VOLNAME_PREFIX,
+                              RT_MIN(cbString, VBOX_VOLNAME_PREFIX_SIZE));
+                if (cbString > VBOX_VOLNAME_PREFIX_SIZE)
+                {
+                    RtlCopyMemory(&pInfo->VolumeLabel[VBOX_VOLNAME_PREFIX_SIZE / sizeof(WCHAR)],
+                                  pRootName,
+                                  cbString - VBOX_VOLNAME_PREFIX_SIZE);
+                }
+            }
+
+            pInfo->VolumeLabelLength = cbString;
+
+            cbToCopy += cbString;
+
+            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsVolumeInformation: VolumeLabelLength %d\n",
+                 pInfo->VolumeLabelLength));
+
+            Status = STATUS_SUCCESS;
+            break;
+        }
+
+        case FileFsLabelInformation:
+        {
+            PFILE_FS_LABEL_INFORMATION pInfo = (PFILE_FS_LABEL_INFORMATION)pInfoBuffer;
+
+            PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
+            PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
+
+            PWCHAR pRootName;
+            ULONG cbRootName;
+
+            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsLabelInformation\n"));
+
+            cbRootName = pNetRoot->pNetRootName->Length - pSrvCall->pSrvCallName->Length;
+            cbRootName -= sizeof(WCHAR); /* Remove the leading backslash. */
+            pRootName = pNetRoot->pNetRootName->Buffer + (pSrvCall->pSrvCallName->Length / sizeof(WCHAR));
+            pRootName++; /* Remove the leading backslash. */
+
+            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsLabelInformation: Root name = %.*ls, %d bytes\n",
+                 cbRootName / sizeof(WCHAR), pRootName, cbRootName));
+
+            cbToCopy = FIELD_OFFSET(FILE_FS_LABEL_INFORMATION, VolumeLabel);
+
+            cbString  = VBOX_VOLNAME_PREFIX_SIZE;
+            cbString += cbRootName;
+            cbString += sizeof(WCHAR);
+
+            if (cbInfoBuffer < cbToCopy)
+            {
+                Status = STATUS_BUFFER_TOO_SMALL;
+                break;
+            }
+
+            RtlZeroMemory(pInfo, cbToCopy);
+
+            if (cbInfoBuffer >= cbToCopy + cbString)
+            {
+                RtlCopyMemory(&pInfo->VolumeLabel[0],
+                              VBOX_VOLNAME_PREFIX,
+                              VBOX_VOLNAME_PREFIX_SIZE);
+                RtlCopyMemory(&pInfo->VolumeLabel[VBOX_VOLNAME_PREFIX_SIZE / sizeof(WCHAR)],
+                              pRootName,
+                              cbRootName);
+                pInfo->VolumeLabel[cbString / sizeof(WCHAR) -  1] = 0;
+            }
+            else
+            {
+                cbString = cbInfoBuffer - cbToCopy;
+
+                RtlCopyMemory(&pInfo->VolumeLabel[0],
+                              VBOX_VOLNAME_PREFIX,
+                              RT_MIN(cbString, VBOX_VOLNAME_PREFIX_SIZE));
+                if (cbString > VBOX_VOLNAME_PREFIX_SIZE)
+                {
+                    RtlCopyMemory(&pInfo->VolumeLabel[VBOX_VOLNAME_PREFIX_SIZE / sizeof(WCHAR)],
+                                  pRootName,
+                                  cbString - VBOX_VOLNAME_PREFIX_SIZE);
+                }
+            }
+
+            pInfo->VolumeLabelLength = cbString;
+
+            cbToCopy += cbString;
+
+            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsLabelInformation: VolumeLabelLength %d\n",
+                 pInfo->VolumeLabelLength));
+
+            Status = STATUS_SUCCESS;
+            break;
+        }
+
+        case FileFsFullSizeInformation:
+        case FileFsSizeInformation:
+        {
+            PFILE_FS_FULL_SIZE_INFORMATION pFullSizeInfo = (PFILE_FS_FULL_SIZE_INFORMATION)pInfoBuffer;
+            PFILE_FS_SIZE_INFORMATION pSizeInfo = (PFILE_FS_SIZE_INFORMATION)pInfoBuffer;
+
+            uint32_t cbHGCMBuffer;
+            uint8_t *pHGCMBuffer;
+            int vrc;
+            PSHFLVOLINFO pShflVolInfo;
+
+            LARGE_INTEGER TotalAllocationUnits;
+            LARGE_INTEGER AvailableAllocationUnits;
+            ULONG         SectorsPerAllocationUnit;
+            ULONG         BytesPerSector;
+
+            if (FsInformationClass == FileFsFullSizeInformation)
+            {
+                Log(("VBOXSF: MrxQueryVolumeInfo: FileFsFullSizeInformation\n"));
+                cbToCopy = sizeof(FILE_FS_FULL_SIZE_INFORMATION);
+            }
+            else
+            {
+                Log(("VBOXSF: MrxQueryVolumeInfo: FileFsSizeInformation\n"));
+                cbToCopy = sizeof(FILE_FS_SIZE_INFORMATION);
+            }
+
+            if (!pVBoxFobx)
+            {
+                Log(("VBOXSF: MrxQueryVolumeInfo: pVBoxFobx is NULL!\n"));
+                Status = STATUS_INVALID_PARAMETER;
+                break;
+            }
+
+            if (cbInfoBuffer < cbToCopy)
+            {
+                Status = STATUS_BUFFER_TOO_SMALL;
+                break;
+            }
+
+            RtlZeroMemory(pInfoBuffer, cbToCopy);
+
+            cbHGCMBuffer = sizeof(SHFLVOLINFO);
+            pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbHGCMBuffer);
+            if (!pHGCMBuffer)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                break;
+            }
+
+            vrc = VbglR0SfFsInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
+                                 SHFL_INFO_GET | SHFL_INFO_VOLUME, &cbHGCMBuffer, (PSHFLDIRINFO)pHGCMBuffer);
+
+            if (vrc != VINF_SUCCESS)
+            {
+                Status = VBoxErrorToNTStatus(vrc);
+                vbsfFreeNonPagedMem(pHGCMBuffer);
+                break;
+            }
+
+            pShflVolInfo = (PSHFLVOLINFO)pHGCMBuffer;
+
+            TotalAllocationUnits.QuadPart     = pShflVolInfo->ullTotalAllocationBytes / pShflVolInfo->ulBytesPerAllocationUnit;
+            AvailableAllocationUnits.QuadPart = pShflVolInfo->ullAvailableAllocationBytes / pShflVolInfo->ulBytesPerAllocationUnit;
+            SectorsPerAllocationUnit          = pShflVolInfo->ulBytesPerAllocationUnit / pShflVolInfo->ulBytesPerSector;
+            BytesPerSector                    = pShflVolInfo->ulBytesPerSector;
+
+            Log(("VBOXSF: MrxQueryVolumeInfo: TotalAllocationUnits     0x%RX64\n", TotalAllocationUnits.QuadPart));
+            Log(("VBOXSF: MrxQueryVolumeInfo: AvailableAllocationUnits 0x%RX64\n", AvailableAllocationUnits.QuadPart));
+            Log(("VBOXSF: MrxQueryVolumeInfo: SectorsPerAllocationUnit 0x%X\n", SectorsPerAllocationUnit));
+            Log(("VBOXSF: MrxQueryVolumeInfo: BytesPerSector           0x%X\n", BytesPerSector));
+
+            if (FsInformationClass == FileFsFullSizeInformation)
+            {
+                pFullSizeInfo->TotalAllocationUnits           = TotalAllocationUnits;
+                pFullSizeInfo->CallerAvailableAllocationUnits = AvailableAllocationUnits;
+                pFullSizeInfo->ActualAvailableAllocationUnits = AvailableAllocationUnits;
+                pFullSizeInfo->SectorsPerAllocationUnit       = SectorsPerAllocationUnit;
+                pFullSizeInfo->BytesPerSector                 = BytesPerSector;
+            }
+            else
+            {
+                pSizeInfo->TotalAllocationUnits     = TotalAllocationUnits;
+                pSizeInfo->AvailableAllocationUnits = AvailableAllocationUnits;
+                pSizeInfo->SectorsPerAllocationUnit = SectorsPerAllocationUnit;
+                pSizeInfo->BytesPerSector           = BytesPerSector;
+            }
+
+            vbsfFreeNonPagedMem(pHGCMBuffer);
+
+            Status = STATUS_SUCCESS;
+            break;
+        }
+
+        case FileFsDeviceInformation:
+        {
+            PFILE_FS_DEVICE_INFORMATION pInfo = (PFILE_FS_DEVICE_INFORMATION)pInfoBuffer;
+            PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
+
+            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsDeviceInformation: Type = %d\n",
+                 NetRoot->DeviceType));
+
+            cbToCopy = sizeof(FILE_FS_DEVICE_INFORMATION);
+
+            if (cbInfoBuffer < cbToCopy)
+            {
+                Status = STATUS_BUFFER_TOO_SMALL;
+                break;
+            }
+
+            pInfo->DeviceType = NetRoot->DeviceType;
+            pInfo->Characteristics = FILE_REMOTE_DEVICE;
+
+            Status = STATUS_SUCCESS;
+            break;
+        }
+
+        case FileFsAttributeInformation:
+        {
+            PFILE_FS_ATTRIBUTE_INFORMATION pInfo = (PFILE_FS_ATTRIBUTE_INFORMATION)pInfoBuffer;
+
+            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsAttributeInformation\n"));
+
+            cbToCopy = FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName);
+
+            cbString = sizeof(MRX_VBOX_FILESYS_NAME_U);
+
+            if (cbInfoBuffer < cbToCopy)
+            {
+                Status = STATUS_BUFFER_TOO_SMALL;
+                break;
+            }
+
+            pInfo->FileSystemAttributes = 0; /** @todo set unicode, case sensitive etc? */
+            pInfo->MaximumComponentNameLength = 255; /** @todo should query from the host */
+
+            if (cbInfoBuffer >= cbToCopy + cbString)
+            {
+                RtlCopyMemory(pInfo->FileSystemName,
+                              MRX_VBOX_FILESYS_NAME_U,
+                              sizeof(MRX_VBOX_FILESYS_NAME_U));
+            }
+            else
+            {
+                cbString = cbInfoBuffer - cbToCopy;
+
+                RtlCopyMemory(pInfo->FileSystemName,
+                              MRX_VBOX_FILESYS_NAME_U,
+                              RT_MIN(cbString, sizeof(MRX_VBOX_FILESYS_NAME_U)));
+            }
+
+            pInfo->FileSystemNameLength = cbString;
+
+            cbToCopy += cbString;
+
+            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsAttributeInformation: FileSystemNameLength %d\n",
+                 pInfo->FileSystemNameLength));
+
+            Status = STATUS_SUCCESS;
+            break;
+        }
+
+        case FileFsControlInformation:
+            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsControlInformation: not supported\n"));
+            Status = STATUS_INVALID_PARAMETER;
+            break;
+
+        case FileFsObjectIdInformation:
+            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsObjectIdInformation: not supported\n"));
+            Status = STATUS_INVALID_PARAMETER;
+            break;
+
+        case FileFsMaximumInformation:
+            Log(("VBOXSF: MrxQueryVolumeInfo: FileFsMaximumInformation: not supported\n"));
+            Status = STATUS_INVALID_PARAMETER;
+            break;
+
+        default:
+            Log(("VBOXSF: MrxQueryVolumeInfo: Not supported FsInformationClass %d!\n",
+                 FsInformationClass));
+            Status = STATUS_INVALID_PARAMETER;
+            break;
+    }
+
+    if (Status == STATUS_SUCCESS)
+        RxContext->Info.LengthRemaining = cbInfoBuffer - cbToCopy;
+    else if (Status == STATUS_BUFFER_TOO_SMALL)
+    {
+        Log(("VBOXSF: MrxQueryVolumeInfo: Insufficient buffer size %d, required %d\n",
+             cbInfoBuffer, cbToCopy));
+        RxContext->InformationToReturn = cbToCopy;
+    }
+
+    Log(("VBOXSF: MrxQueryVolumeInfo: cbToCopy = %d, LengthRemaining = %d, Status = 0x%08X\n",
+         cbToCopy, RxContext->Info.LengthRemaining, Status));
+
+    return Status;
+}
+
+void vbsfNtCopyInfoToLegacy(PMRX_VBOX_FOBX pVBoxFobx, PCSHFLFSOBJINFO pInfo)
+{
+    pVBoxFobx->FileBasicInfo.CreationTime.QuadPart   = RTTimeSpecGetNtTime(&pInfo->BirthTime);
+    pVBoxFobx->FileBasicInfo.LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pInfo->AccessTime);
+    pVBoxFobx->FileBasicInfo.LastWriteTime.QuadPart  = RTTimeSpecGetNtTime(&pInfo->ModificationTime);
+    pVBoxFobx->FileBasicInfo.ChangeTime.QuadPart     = RTTimeSpecGetNtTime(&pInfo->ChangeTime);
+    pVBoxFobx->FileBasicInfo.FileAttributes          = VBoxToNTFileAttributes(pInfo->Attr.fMode);
+}
+
+static void vbsfNtCopyInfo(PMRX_VBOX_FOBX pVBoxFobx, PSHFLFSOBJINFO pObjInfo, uint32_t fOverrides)
+{
+    if (pObjInfo->cbObject != pVBoxFobx->Info.cbObject)
+    {
+        /** @todo tell RDBSS about this? */
+    }
+
+    /* To simplify stuff, copy user timestamps to the input structure before copying. */
+    if (   pVBoxFobx->fKeepCreationTime
+        || pVBoxFobx->fKeepLastAccessTime
+        || pVBoxFobx->fKeepLastWriteTime
+        || pVBoxFobx->fKeepChangeTime)
+    {
+        if (pVBoxFobx->fKeepCreationTime   && !(fOverrides & VBOX_FOBX_F_INFO_CREATION_TIME))
+            pObjInfo->BirthTime         = pVBoxFobx->Info.BirthTime;
+        if (pVBoxFobx->fKeepLastAccessTime && !(fOverrides & VBOX_FOBX_F_INFO_LASTACCESS_TIME))
+            pObjInfo->AccessTime        = pVBoxFobx->Info.AccessTime;
+        if (pVBoxFobx->fKeepLastWriteTime  && !(fOverrides & VBOX_FOBX_F_INFO_LASTWRITE_TIME))
+            pObjInfo->ModificationTime  = pVBoxFobx->Info.ModificationTime;
+        if (pVBoxFobx->fKeepChangeTime     && !(fOverrides & VBOX_FOBX_F_INFO_CHANGE_TIME))
+            pObjInfo->ChangeTime        = pVBoxFobx->Info.ChangeTime;
+    }
+    pVBoxFobx->Info = *pObjInfo;
+
+    vbsfNtCopyInfoToLegacy(pVBoxFobx, pObjInfo);
+}
+
+
+NTSTATUS VBoxMRxQueryFileInfo(IN PRX_CONTEXT RxContext)
+{
+    RxCaptureFcb;
+    RxCaptureFobx;
+    NTSTATUS                    Status            = STATUS_SUCCESS;
+    //PMRX_VBOX_DEVICE_EXTENSION  pDeviceExtension  = VBoxMRxGetDeviceExtension(RxContext);
+    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
+    PMRX_VBOX_FOBX              pVBoxFobx         = VBoxMRxGetFileObjectExtension(capFobx);
+    ULONG                       cbToCopy          = 0;
+
+    Log(("VBOXSF: MrxQueryFileInfo: InfoBuffer = %p, Size = %d bytes, FileInformationClass = %d\n",
+         RxContext->Info.Buffer, RxContext->Info.Length, RxContext->Info.FileInformationClass));
+
+    AssertReturn(pVBoxFobx, STATUS_INVALID_PARAMETER);
+    AssertReturn(RxContext->Info.Buffer, STATUS_INVALID_PARAMETER);
+
+#define CHECK_SIZE_BREAK(a_RxContext, a_cbNeeded) \
+        /* IO_STACK_LOCATION::Parameters::SetFile::Length is signed, the RxContext bugger is LONG. See end of function for why. */ \
+        if ((ULONG)(a_RxContext)->Info.Length >= (a_cbNeeded)) \
+        { /*likely */ } \
+        else if (1) { Status = STATUS_BUFFER_TOO_SMALL; break; } else do { } while (0)
+
+    switch (RxContext->Info.FileInformationClass)
+    {
+        /*
+         * Queries we can satisfy without calling the host:
+         */
+
+        case FileNamesInformation:
+        {
+            PFILE_NAMES_INFORMATION pInfo    = (PFILE_NAMES_INFORMATION)RxContext->Info.Buffer;
+            PUNICODE_STRING         FileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
+            Log(("VBOXSF: MrxQueryFileInfo: FileNamesInformation\n"));
+
+            cbToCopy = RT_UOFFSETOF_DYN(FILE_NAMES_INFORMATION, FileName[FileName->Length / 2 + 1]);
+            CHECK_SIZE_BREAK(RxContext, cbToCopy);
+
+            pInfo->NextEntryOffset = 0;
+            pInfo->FileIndex       = 0;
+            pInfo->FileNameLength  = FileName->Length;
+
+            RtlCopyMemory(pInfo->FileName, FileName->Buffer, FileName->Length);
+            pInfo->FileName[FileName->Length] = 0;
+            break;
+        }
+
+        case FileInternalInformation:
+        {
+            PFILE_INTERNAL_INFORMATION pInfo = (PFILE_INTERNAL_INFORMATION)RxContext->Info.Buffer;
+            Log(("VBOXSF: MrxQueryFileInfo: FileInternalInformation\n"));
+
+            cbToCopy = sizeof(FILE_INTERNAL_INFORMATION);
+            CHECK_SIZE_BREAK(RxContext, cbToCopy);
+
+            /* A 8-byte file reference number for the file. */
+            pInfo->IndexNumber.QuadPart = (ULONG_PTR)capFcb;
+            break;
+        }
+
+        case FileEaInformation:
+        {
+            PFILE_EA_INFORMATION pInfo = (PFILE_EA_INFORMATION)RxContext->Info.Buffer;
+            Log(("VBOXSF: MrxQueryFileInfo: FileEaInformation\n"));
+
+            cbToCopy = sizeof(FILE_EA_INFORMATION);
+            CHECK_SIZE_BREAK(RxContext, cbToCopy);
+
+            pInfo->EaSize = 0;
+            break;
+        }
+
+        case FileStreamInformation:
+            Log(("VBOXSF: MrxQueryFileInfo: FileStreamInformation: not supported\n"));
+            Status = STATUS_INVALID_PARAMETER;
+            break;
+
+        case FileAlternateNameInformation:
+            Log(("VBOXSF: MrxQueryFileInfo: FileStreamInformation: not implemented\n"));
+            Status = STATUS_OBJECT_NAME_NOT_FOUND;
+            break;
+
+        case FileNumaNodeInformation:
+            Log(("VBOXSF: MrxQueryFileInfo: FileNumaNodeInformation: not supported\n"));
+            Status = STATUS_NO_SUCH_DEVICE; /* what's returned on a samba share */
+            break;
+
+        case FileStandardLinkInformation:
+            Log(("VBOXSF: MrxQueryFileInfo: FileStandardLinkInformation: not supported\n"));
+            Status = STATUS_NOT_SUPPORTED; /* what's returned on a samba share */
+            break;
+
+        /*
+         * Queries where we need info from the host.
+         *
+         * For directories we don't necessarily go to the host but use info from when we
+         * opened the them, why we do this is a little unclear as all the clues that r9630
+         * give is "fixes".
+         *
+         * Note! We verify the buffer size after talking to the host, assuming that there
+         *       won't be a problem and saving an extra switch statement.  IIRC the
+         *       NtQueryInformationFile code verfies the sizes too.
+         */
+        /** @todo r=bird: install a hack so we get FileAllInformation directly up here
+         *        rather than 5 individual queries.  We may end up going 3 times to
+         *        the host (depending on the TTL hack) to fetch the same info over
+         *        and over again. */
+        case FileEndOfFileInformation:
+        case FileAllocationInformation:
+        case FileBasicInformation:
+        case FileStandardInformation:
+        case FileNetworkOpenInformation:
+        case FileAttributeTagInformation:
+        case FileCompressionInformation:
+        {
+            /* Query the information if necessary. */
+            if (   !(pVBoxFobx->Info.Attr.fMode & RTFS_DOS_DIRECTORY) /** @todo figure out why we don't return up-to-date info for directories! */
+                && (   !pVBoxFobx->nsUpToDate
+                    || pVBoxFobx->nsUpToDate - RTTimeSystemNanoTS() < RT_NS_100US /** @todo implement proper TTL */ ) )
+            {
+                int               vrc;
+                VBOXSFOBJINFOREQ *pReq = (VBOXSFOBJINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
+                AssertBreakStmt(pReq, Status = STATUS_NO_MEMORY);
+
+                vrc = VbglR0SfHostReqQueryObjInfo(pNetRootExtension->map.root, pReq, pVBoxFobx->hFile);
+                if (RT_SUCCESS(vrc))
+                    vbsfNtCopyInfo(pVBoxFobx, &pReq->ObjInfo, 0);
+                else
+                {
+                    Status = VBoxErrorToNTStatus(vrc);
+                    VbglR0PhysHeapFree(pReq);
+                    break;
+                }
+                VbglR0PhysHeapFree(pReq);
+            }
+
+            /* Copy it into the return buffer. */
+            switch (RxContext->Info.FileInformationClass)
+            {
+                case FileBasicInformation:
+                {
+                    PFILE_BASIC_INFORMATION pInfo = (PFILE_BASIC_INFORMATION)RxContext->Info.Buffer;
+                    Log(("VBOXSF: MrxQueryFileInfo: FileBasicInformation\n"));
+
+                    cbToCopy = sizeof(FILE_BASIC_INFORMATION);
+                    CHECK_SIZE_BREAK(RxContext, cbToCopy);
+
+                    pInfo->CreationTime.QuadPart   = RTTimeSpecGetNtTime(&pVBoxFobx->Info.BirthTime);
+                    pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pVBoxFobx->Info.AccessTime);
+                    pInfo->LastWriteTime.QuadPart  = RTTimeSpecGetNtTime(&pVBoxFobx->Info.ModificationTime);
+                    pInfo->ChangeTime.QuadPart     = RTTimeSpecGetNtTime(&pVBoxFobx->Info.ChangeTime);
+                    pInfo->FileAttributes          = VBoxToNTFileAttributes(pVBoxFobx->Info.Attr.fMode);
+                    Log(("VBOXSF: MrxQueryFileInfo: FileBasicInformation: File attributes: 0x%x\n",
+                         pInfo->FileAttributes));
+                    break;
+                }
+
+                case FileStandardInformation:
+                {
+                    PFILE_STANDARD_INFORMATION pInfo = (PFILE_STANDARD_INFORMATION)RxContext->Info.Buffer;
+                    Log(("VBOXSF: MrxQueryFileInfo: FileStandardInformation\n"));
+
+                    cbToCopy = sizeof(FILE_STANDARD_INFORMATION);
+                    CHECK_SIZE_BREAK(RxContext, cbToCopy);
+
+                    /* Note! We didn't used to set allocation size and end-of-file for directories.
+                             NTFS reports these, though, so why shouldn't we. */
+                    pInfo->AllocationSize.QuadPart = pVBoxFobx->Info.cbAllocated;
+                    pInfo->EndOfFile.QuadPart      = pVBoxFobx->Info.cbObject;
+                    pInfo->NumberOfLinks           = 1; /** @todo 0? */
+                    pInfo->DeletePending           = FALSE;
+                    pInfo->Directory               = pVBoxFobx->Info.Attr.fMode & RTFS_DOS_DIRECTORY ? TRUE : FALSE;
+                    break;
+                }
+
+                case FileNetworkOpenInformation:
+                {
+                    PFILE_NETWORK_OPEN_INFORMATION pInfo = (PFILE_NETWORK_OPEN_INFORMATION)RxContext->Info.Buffer;
+                    Log(("VBOXSF: MrxQueryFileInfo: FileNetworkOpenInformation\n"));
+
+                    cbToCopy = sizeof(FILE_NETWORK_OPEN_INFORMATION);
+                    CHECK_SIZE_BREAK(RxContext, cbToCopy);
+
+                    pInfo->CreationTime.QuadPart   = RTTimeSpecGetNtTime(&pVBoxFobx->Info.BirthTime);
+                    pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pVBoxFobx->Info.AccessTime);
+                    pInfo->LastWriteTime.QuadPart  = RTTimeSpecGetNtTime(&pVBoxFobx->Info.ModificationTime);
+                    pInfo->ChangeTime.QuadPart     = RTTimeSpecGetNtTime(&pVBoxFobx->Info.ChangeTime);
+                    /* Note! We didn't used to set allocation size and end-of-file for directories.
+                             NTFS reports these, though, so why shouldn't we. */
+                    pInfo->AllocationSize.QuadPart = pVBoxFobx->Info.cbAllocated;
+                    pInfo->EndOfFile.QuadPart      = pVBoxFobx->Info.cbObject;
+                    pInfo->FileAttributes          = VBoxToNTFileAttributes(pVBoxFobx->Info.Attr.fMode);
+                    break;
+                }
+
+                case FileEndOfFileInformation:
+                {
+                    PFILE_END_OF_FILE_INFORMATION pInfo = (PFILE_END_OF_FILE_INFORMATION)RxContext->Info.Buffer;
+                    Log(("VBOXSF: MrxQueryFileInfo: FileEndOfFileInformation\n"));
+
+                    cbToCopy = sizeof(FILE_END_OF_FILE_INFORMATION);
+                    CHECK_SIZE_BREAK(RxContext, cbToCopy);
+
+                    /* Note! We didn't used to set allocation size and end-of-file for directories.
+                             NTFS reports these, though, so why shouldn't we. */
+                    pInfo->EndOfFile.QuadPart      = pVBoxFobx->Info.cbObject;
+                    break;
+                }
+
+                case FileAllocationInformation:
+                {
+                    PFILE_ALLOCATION_INFORMATION pInfo = (PFILE_ALLOCATION_INFORMATION)RxContext->Info.Buffer;
+                    Log(("VBOXSF: MrxQueryFileInfo: FileAllocationInformation\n"));
+
+                    cbToCopy = sizeof(FILE_ALLOCATION_INFORMATION);
+                    CHECK_SIZE_BREAK(RxContext, cbToCopy);
+
+                    /* Note! We didn't used to set allocation size and end-of-file for directories.
+                             NTFS reports these, though, so why shouldn't we. */
+                    pInfo->AllocationSize.QuadPart = pVBoxFobx->Info.cbAllocated;
+                    break;
+                }
+
+                case FileAttributeTagInformation:
+                {
+                    PFILE_ATTRIBUTE_TAG_INFORMATION pInfo = (PFILE_ATTRIBUTE_TAG_INFORMATION)RxContext->Info.Buffer;
+                    Log(("VBOXSF: MrxQueryFileInfo: FileAttributeTagInformation\n"));
+
+                    cbToCopy = sizeof(FILE_ATTRIBUTE_TAG_INFORMATION);
+                    CHECK_SIZE_BREAK(RxContext, cbToCopy);
+
+                    pInfo->FileAttributes = VBoxToNTFileAttributes(pVBoxFobx->Info.Attr.fMode);
+                    pInfo->ReparseTag     = 0;
+                    break;
+                }
+
+                case FileCompressionInformation:
+                {
+                    //PFILE_COMPRESSION_INFO pInfo = (PFILE_COMPRESSION_INFO)RxContext->Info.Buffer;
+                    struct MY_FILE_COMPRESSION_INFO
+                    {
+                        LARGE_INTEGER   CompressedFileSize;
+                        WORD            CompressionFormat;
+                        UCHAR           CompressionUnitShift;
+                        UCHAR           ChunkShift;
+                        UCHAR           ClusterShift;
+                        UCHAR           Reserved[3];
+                    } *pInfo = (struct MY_FILE_COMPRESSION_INFO *)RxContext->Info.Buffer;
+                    Log(("VBOXSF: MrxQueryFileInfo: FileCompressionInformation\n"));
+
+                    cbToCopy = sizeof(*pInfo);
+                    CHECK_SIZE_BREAK(RxContext, cbToCopy);
+
+                    pInfo->CompressedFileSize.QuadPart = pVBoxFobx->Info.cbObject;
+                    pInfo->CompressionFormat           = 0;
+                    pInfo->CompressionUnitShift        = 0;
+                    pInfo->ChunkShift                  = 0;
+                    pInfo->ClusterShift                = 0;
+                    pInfo->Reserved[0]                 = 0;
+                    pInfo->Reserved[1]                 = 0;
+                    pInfo->Reserved[2]                 = 0;
+                    AssertCompile(sizeof(pInfo->Reserved) == 3);
+                    break;
+                }
+
+                default:
+                    AssertLogRelMsgFailed(("FileInformationClass=%d\n",
+                                           RxContext->Info.FileInformationClass));
+                    Status = STATUS_INTERNAL_ERROR;
+                    break;
+            }
+            break;
+        }
+
+
+/** @todo Implement:
+ * FileHardLinkInformation: rcNt=0 (STATUS_SUCCESS) Ios.Status=0 (STATUS_SUCCESS) Ios.Information=0000000000000048
+ * FileProcessIdsUsingFileInformation: rcNt=0 (STATUS_SUCCESS) Ios.Status=0 (STATUS_SUCCESS) Ios.Information=0000000000000010
+ * FileNormalizedNameInformation: rcNt=0 (STATUS_SUCCESS) Ios.Status=0 (STATUS_SUCCESS) Ios.Information=00000000000000AA
+ * FileNetworkPhysicalNameInformation: rcNt=0xc000000d (STATUS_INVALID_PARAMETER) Ios={not modified}
+ * FileShortNameInformation?
+ * FileNetworkPhysicalNameInformation
+ */
+
+        /*
+         * Unsupported ones (STATUS_INVALID_PARAMETER is correct here if you
+         * go by what fat + ntfs return, however samba mounts generally returns
+         * STATUS_INVALID_INFO_CLASS except for pipe info - see queryfileinfo-1).
+         */
+        default:
+            Log(("VBOXSF: MrxQueryFileInfo: Not supported FileInformationClass: %d!\n",
+                 RxContext->Info.FileInformationClass));
+            Status = STATUS_INVALID_PARAMETER;
+            break;
+
+    }
+#undef CHECK_SIZE_BREAK
+
+    /* Note! InformationToReturn doesn't seem to be used, instead Info.LengthRemaining should underflow
+             so it can be used together with RxContext->CurrentIrpSp->Parameters.QueryFile.Length
+             to calc the Ios.Information value.  This explain the weird LONG type choice.  */
+    RxContext->InformationToReturn   = cbToCopy;
+    RxContext->Info.LengthRemaining -= cbToCopy;
+    AssertStmt(RxContext->Info.LengthRemaining >= 0 || Status != STATUS_SUCCESS, Status = STATUS_BUFFER_TOO_SMALL);
+
+    Log(("VBOXSF: MrxQueryFileInfo: Returns %#x, Remaining length = %d, cbToCopy = %u (%#x)\n",
+         Status, RxContext->Info.Length, cbToCopy));
+    return Status;
+}
+
+NTSTATUS VBoxMRxSetFileInfo(IN PRX_CONTEXT RxContext)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    RxCaptureFcb;
+    RxCaptureFobx;
+
+    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
+    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
+    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
+
+    FILE_INFORMATION_CLASS FunctionalityRequested = RxContext->Info.FileInformationClass;
+    PVOID pInfoBuffer = (PVOID)RxContext->Info.Buffer;
+
+    int vrc;
+
+    uint8_t *pHGCMBuffer = NULL;
+    uint32_t cbBuffer = 0;
+
+    Log(("VBOXSF: MrxSetFileInfo: pInfoBuffer %p\n",
+         pInfoBuffer));
+
+    switch (FunctionalityRequested)
+    {
+        case FileBasicInformation:
+        {
+            PFILE_BASIC_INFORMATION pInfo = (PFILE_BASIC_INFORMATION)pInfoBuffer;
+            PSHFLFSOBJINFO pSHFLFileInfo;
+            uint32_t fModified;
+
+            Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: CreationTime   %RX64\n", pInfo->CreationTime.QuadPart));
+            Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: LastAccessTime %RX64\n", pInfo->LastAccessTime.QuadPart));
+            Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: LastWriteTime  %RX64\n", pInfo->LastWriteTime.QuadPart));
+            Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: ChangeTime     %RX64\n", pInfo->ChangeTime.QuadPart));
+            Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: FileAttributes %RX32\n", pInfo->FileAttributes));
+
+            /*
+             * Note! If a timestamp value is non-zero, the client disables implicit updating of
+             *       that timestamp via this handle when reading, writing and changing attributes.
+             *       The special -1 value is used to just disable implicit updating without
+             *       modifying the timestamp.  While the value is allowed for the CreationTime
+             *       field, it will be treated as zero.
+             *
+             *       More clues can be found here:
+             * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/16023025-8a78-492f-8b96-c873b042ac50
+             * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/d4bc551b-7aaf-4b4f-ba0e-3a75e7c528f0#Appendix_A_86
+             */
+
+            /** @todo r=bird: The attempt at implementing the disable-timestamp-update
+             *        behaviour here needs a little adjusting.  I'll get to that later.
+             *
+             * Reminders:
+             *
+             *  1. Drop VBOX_FOBX_F_INFO_CREATION_TIME.
+             *
+             *  2. Drop unused VBOX_FOBX_F_INFO_ATTRIBUTES.
+             *
+             *  3. Only act on VBOX_FOBX_F_INFO_CHANGE_TIME if modified attributes or grown
+             *     the file (?) so we don't cancel out updates by other parties (like the
+             *     host).
+             *
+             *  4. Only act on VBOX_FOBX_F_INFO_LASTWRITE_TIME if we've written to the file.
+             *
+             *  5. Only act on VBOX_FOBX_F_INFO_LASTACCESS_TIME if we've read from the file
+             *     or done whatever else might modify the access time.
+             *
+             *  6. Don't bother calling the host if there are only zeros and -1 values.
+             *
+             *  7. Client application should probably be allowed to modify the timestamps
+             *     explicitly using this API after disabling updating, given the wording of
+             *     the footnote referenced above.
+             *
+             *  8. Extend the host interface to let the host handle this crap instead as it
+             *     can do a better job, like on windows it's done implicitly if we let -1
+             *     pass thru IPRT.
+             *
+             * One worry here is that we hide timestamp updates made by the host or other
+             * guest side processes.  This could account for some of the issues we've been
+             * having with the guest not noticing host side changes.
+             */
+
+            if (pInfo->CreationTime.QuadPart == -1)
+            {
+                pVBoxFobx->fKeepCreationTime = TRUE;
+                pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_CREATION_TIME;
+            }
+            if (pInfo->LastAccessTime.QuadPart == -1)
+            {
+                pVBoxFobx->fKeepLastAccessTime = TRUE;
+                pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_LASTACCESS_TIME;
+            }
+            if (pInfo->LastWriteTime.QuadPart == -1)
+            {
+                pVBoxFobx->fKeepLastWriteTime = TRUE;
+                pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_LASTWRITE_TIME;
+            }
+            if (pInfo->ChangeTime.QuadPart == -1)
+            {
+                pVBoxFobx->fKeepChangeTime = TRUE;
+                pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_CHANGE_TIME;
+            }
+
+            cbBuffer = sizeof(SHFLFSOBJINFO);
+            pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbBuffer);
+            AssertReturn(pHGCMBuffer, STATUS_INSUFFICIENT_RESOURCES);
+            RtlZeroMemory(pHGCMBuffer, cbBuffer);
+            pSHFLFileInfo = (PSHFLFSOBJINFO)pHGCMBuffer;
+
+            Log(("VBOXSF: MrxSetFileInfo: FileBasicInformation: keeps %d %d %d %d\n",
+                 pVBoxFobx->fKeepCreationTime, pVBoxFobx->fKeepLastAccessTime, pVBoxFobx->fKeepLastWriteTime, pVBoxFobx->fKeepChangeTime));
+
+            /* The properties, that need to be changed, are set to something other than zero */
+            fModified = 0;
+            if (pInfo->CreationTime.QuadPart && !pVBoxFobx->fKeepCreationTime)
+            {
+                RTTimeSpecSetNtTime(&pSHFLFileInfo->BirthTime, pInfo->CreationTime.QuadPart);
+                fModified |= VBOX_FOBX_F_INFO_CREATION_TIME;
+            }
+            /** @todo FsPerf need to check what is supposed to happen if modified
+             *        against after -1 is specified.  */
+            if (pInfo->LastAccessTime.QuadPart && !pVBoxFobx->fKeepLastAccessTime)
+            {
+                RTTimeSpecSetNtTime(&pSHFLFileInfo->AccessTime, pInfo->LastAccessTime.QuadPart);
+                fModified |= VBOX_FOBX_F_INFO_LASTACCESS_TIME;
+            }
+            if (pInfo->LastWriteTime.QuadPart && !pVBoxFobx->fKeepLastWriteTime)
+            {
+                RTTimeSpecSetNtTime(&pSHFLFileInfo->ModificationTime, pInfo->LastWriteTime.QuadPart);
+                fModified |= VBOX_FOBX_F_INFO_LASTWRITE_TIME;
+            }
+            if (pInfo->ChangeTime.QuadPart && !pVBoxFobx->fKeepChangeTime)
+            {
+                RTTimeSpecSetNtTime(&pSHFLFileInfo->ChangeTime, pInfo->ChangeTime.QuadPart);
+                fModified |= VBOX_FOBX_F_INFO_CHANGE_TIME;
+            }
+            if (pInfo->FileAttributes)
+                pSHFLFileInfo->Attr.fMode = NTToVBoxFileAttributes(pInfo->FileAttributes);
+
+            Assert(pVBoxFobx && pNetRootExtension && pDeviceExtension);
+            vrc = VbglR0SfFsInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
+                                 SHFL_INFO_SET | SHFL_INFO_FILE, &cbBuffer, (PSHFLDIRINFO)pSHFLFileInfo);
+
+            if (RT_SUCCESS(vrc))
+            {
+                vbsfNtCopyInfo(pVBoxFobx, pSHFLFileInfo, fModified);
+                pVBoxFobx->SetFileInfoOnCloseFlags |= fModified;
+            }
+            else
+            {
+                Status = VBoxErrorToNTStatus(vrc);
+                goto end;
+            }
+            break;
+        }
+
+        case FileDispositionInformation:
+        {
+            PFILE_DISPOSITION_INFORMATION pInfo = (PFILE_DISPOSITION_INFORMATION)pInfoBuffer;
+
+            Log(("VBOXSF: MrxSetFileInfo: FileDispositionInformation: Delete = %d\n",
+                 pInfo->DeleteFile));
+
+            if (pInfo->DeleteFile && capFcb->OpenCount == 1)
+                Status = vbsfRemove(RxContext);
+            else
+                Status = STATUS_SUCCESS;
+            break;
+        }
+
+        case FilePositionInformation:
+        {
+#ifdef LOG_ENABLED
+            PFILE_POSITION_INFORMATION pInfo = (PFILE_POSITION_INFORMATION)pInfoBuffer;
+            Log(("VBOXSF: MrxSetFileInfo: FilePositionInformation: CurrentByteOffset = 0x%RX64. Unsupported!\n",
+                 pInfo->CurrentByteOffset.QuadPart));
+#endif
+
+            Status = STATUS_INVALID_PARAMETER;
+            break;
+        }
+
+        case FileAllocationInformation:
+        {
+            PFILE_ALLOCATION_INFORMATION pInfo = (PFILE_ALLOCATION_INFORMATION)pInfoBuffer;
+
+            Log(("VBOXSF: MrxSetFileInfo: FileAllocationInformation: new AllocSize = 0x%RX64, FileSize = 0x%RX64\n",
+                 pInfo->AllocationSize.QuadPart, capFcb->Header.FileSize.QuadPart));
+
+            /* Check if the new allocation size changes the file size. */
+            if (pInfo->AllocationSize.QuadPart > capFcb->Header.FileSize.QuadPart)
+            {
+                /* Ignore this request and return success. Shared folders do not distinguish between
+                 * AllocationSize and FileSize.
+                 */
+                Status = STATUS_SUCCESS;
+            }
+            else
+            {
+                /* Treat the request as a EndOfFile update. */
+                LARGE_INTEGER NewAllocationSize;
+                Status = vbsfSetEndOfFile(RxContext, &pInfo->AllocationSize, &NewAllocationSize);
+            }
+
+            break;
+        }
+
+        case FileEndOfFileInformation:
+        {
+            PFILE_END_OF_FILE_INFORMATION pInfo = (PFILE_END_OF_FILE_INFORMATION)pInfoBuffer;
+            LARGE_INTEGER NewAllocationSize;
+
+            Log(("VBOXSF: MrxSetFileInfo: FileEndOfFileInformation: new EndOfFile 0x%RX64, FileSize = 0x%RX64\n",
+                 pInfo->EndOfFile.QuadPart, capFcb->Header.FileSize.QuadPart));
+
+            Status = vbsfSetEndOfFile(RxContext, &pInfo->EndOfFile, &NewAllocationSize);
+
+            Log(("VBOXSF: MrxSetFileInfo: FileEndOfFileInformation: AllocSize = 0x%RX64, Status 0x%08X\n",
+                 NewAllocationSize.QuadPart, Status));
+
+            break;
+        }
+
+        case FileLinkInformation:
+        {
+#ifdef LOG_ENABLED
+            PFILE_LINK_INFORMATION pInfo = (PFILE_LINK_INFORMATION )pInfoBuffer;
+            Log(("VBOXSF: MrxSetFileInfo: FileLinkInformation: ReplaceIfExists = %d, RootDirectory = 0x%x = [%.*ls]. Not implemented!\n",
+                 pInfo->ReplaceIfExists, pInfo->RootDirectory, pInfo->FileNameLength / sizeof(WCHAR), pInfo->FileName));
+#endif
+
+            Status = STATUS_NOT_IMPLEMENTED;
+            break;
+        }
+
+        case FileRenameInformation:
+        {
+#ifdef LOG_ENABLED
+            PFILE_RENAME_INFORMATION pInfo = (PFILE_RENAME_INFORMATION)pInfoBuffer;
+            Log(("VBOXSF: MrxSetFileInfo: FileRenameInformation: ReplaceIfExists = %d, RootDirectory = 0x%x = [%.*ls]\n",
+                 pInfo->ReplaceIfExists, pInfo->RootDirectory, pInfo->FileNameLength / sizeof(WCHAR), pInfo->FileName));
+#endif
+
+            Status = vbsfRename(RxContext, FileRenameInformation, pInfoBuffer, RxContext->Info.Length);
+            break;
+        }
+
+        default:
+            Log(("VBOXSF: MrxSetFileInfo: Not supported FunctionalityRequested %d!\n",
+                 FunctionalityRequested));
+            Status = STATUS_INVALID_PARAMETER;
+            break;
+    }
+
+end:
+    if (pHGCMBuffer)
+        vbsfFreeNonPagedMem(pHGCMBuffer);
+
+    Log(("VBOXSF: MrxSetFileInfo: Returned 0x%08X\n", Status));
+    return Status;
+}
+
+NTSTATUS VBoxMRxSetFileInfoAtCleanup(IN PRX_CONTEXT RxContext)
+{
+    RT_NOREF(RxContext);
+    Log(("VBOXSF: MRxSetFileInfoAtCleanup\n"));
+    return STATUS_SUCCESS;
+}
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/driver/path.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/driver/path.c	(revision 78301)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/driver/path.c	(revision 78302)
@@ -24,6 +24,5 @@
 static NTSTATUS vbsfProcessCreate(PRX_CONTEXT RxContext,
                                   PUNICODE_STRING RemainingName,
-                                  FILE_BASIC_INFORMATION *pFileBasicInfo,
-                                  FILE_STANDARD_INFORMATION *pFileStandardInfo,
+                                  SHFLFSOBJINFO *pInfo,
                                   PVOID EaBuffer,
                                   ULONG EaLength,
@@ -429,31 +428,5 @@
 
     *pHandle = pCreateParms->Handle;
-
-    /* Translate attributes */
-    pFileBasicInfo->FileAttributes = VBoxToNTFileAttributes(pCreateParms->Info.Attr.fMode);
-
-    /* Translate file times */
-    pFileBasicInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pCreateParms->Info.BirthTime); /* ridiculous name */
-    pFileBasicInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pCreateParms->Info.AccessTime);
-    pFileBasicInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&pCreateParms->Info.ModificationTime);
-    pFileBasicInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&pCreateParms->Info.ChangeTime);
-
-    if (!FlagOn(pCreateParms->Info.Attr.fMode, RTFS_DOS_DIRECTORY))
-    {
-        pFileStandardInfo->AllocationSize.QuadPart = pCreateParms->Info.cbAllocated;
-        pFileStandardInfo->EndOfFile.QuadPart = pCreateParms->Info.cbObject;
-        pFileStandardInfo->Directory = FALSE;
-
-        Log(("VBOXSF: vbsfProcessCreate: AllocationSize = 0x%RX64, EndOfFile = 0x%RX64\n",
-             pCreateParms->Info.cbAllocated, pCreateParms->Info.cbObject));
-    }
-    else
-    {
-        pFileStandardInfo->AllocationSize.QuadPart = 0;
-        pFileStandardInfo->EndOfFile.QuadPart = 0;
-        pFileStandardInfo->Directory = TRUE;
-    }
-    pFileStandardInfo->NumberOfLinks = 0;
-    pFileStandardInfo->DeletePending = FALSE;
+    *pInfo = pCreateParms->Info;
 
     vbsfFreeNonPagedMem(pCreateParms);
@@ -489,6 +462,5 @@
     PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
 
-    FILE_BASIC_INFORMATION FileBasicInfo;
-    FILE_STANDARD_INFORMATION FileStandardInfo;
+    SHFLFSOBJINFO Info = {0};
 
     ULONG CreateAction = FILE_CREATED;
@@ -531,10 +503,7 @@
     }
 
-    FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
-
     Status = vbsfProcessCreate(RxContext,
                                RemainingName,
-                               &FileBasicInfo,
-                               &FileStandardInfo,
+                               &Info,
                                RxContext->Create.EaBuffer,
                                RxContext->Create.EaLength,
@@ -550,5 +519,5 @@
 
     Log(("VBOXSF: MRxCreate: EOF is 0x%RX64 AllocSize is 0x%RX64\n",
-         FileStandardInfo.EndOfFile.QuadPart, FileStandardInfo.AllocationSize.QuadPart));
+         Info.cbObject, Info.cbAllocated));
 
     RxContext->pFobx = RxCreateNetFobx(RxContext, SrvOpen);
@@ -567,15 +536,26 @@
     if (capFcb->OpenCount == 0)
     {
-        FCB_INIT_PACKET InitPacket;
+        FCB_INIT_PACKET               InitPacket;
+        FILE_NETWORK_OPEN_INFORMATION Data;
+        ULONG                         NumberOfLinks = 0; /** @todo ?? */
+        Data.CreationTime.QuadPart   = RTTimeSpecGetNtTime(&Info.BirthTime);
+        Data.LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&Info.AccessTime);
+        Data.LastWriteTime.QuadPart  = RTTimeSpecGetNtTime(&Info.ModificationTime);
+        Data.ChangeTime.QuadPart     = RTTimeSpecGetNtTime(&Info.ChangeTime);
+        Data.AllocationSize.QuadPart = Info.cbAllocated;
+        Data.EndOfFile.QuadPart      = Info.cbObject;
+        Data.FileAttributes          = VBoxToNTFileAttributes(Info.Attr.fMode);
         RxFormInitPacket(InitPacket,
-                         &FileBasicInfo.FileAttributes,
-                         &FileStandardInfo.NumberOfLinks,
-                         &FileBasicInfo.CreationTime,
-                         &FileBasicInfo.LastAccessTime,
-                         &FileBasicInfo.LastWriteTime,
-                         &FileBasicInfo.ChangeTime,
-                         &FileStandardInfo.AllocationSize,
-                         &FileStandardInfo.EndOfFile,
-                         &FileStandardInfo.EndOfFile);
+                         &Data.FileAttributes,
+                         &NumberOfLinks,
+                         &Data.CreationTime,
+                         &Data.LastAccessTime,
+                         &Data.LastWriteTime,
+                         &Data.ChangeTime,
+                         &Data.AllocationSize,
+                         &Data.EndOfFile,
+                         &Data.EndOfFile);
+        /** @todo r=bird: Use FileTypeDirectory/RDBSS_NTC_STORAGE_TYPE_DIRECTORY here
+         *        for directories? */
         RxFinishFcbInitialization(capFcb, RDBSS_STORAGE_NTC(FileTypeFile), &InitPacket);
     }
@@ -598,19 +578,16 @@
     }
 
-    Log(("VBOXSF: MRxCreate: FileBasicInformation: CreationTime   %RX64\n", FileBasicInfo.CreationTime.QuadPart));
-    Log(("VBOXSF: MRxCreate: FileBasicInformation: LastAccessTime %RX64\n", FileBasicInfo.LastAccessTime.QuadPart));
-    Log(("VBOXSF: MRxCreate: FileBasicInformation: LastWriteTime  %RX64\n", FileBasicInfo.LastWriteTime.QuadPart));
-    Log(("VBOXSF: MRxCreate: FileBasicInformation: ChangeTime     %RX64\n", FileBasicInfo.ChangeTime.QuadPart));
-    Log(("VBOXSF: MRxCreate: FileBasicInformation: FileAttributes %RX32\n", FileBasicInfo.FileAttributes));
-
     pVBoxFobx->hFile = Handle;
     pVBoxFobx->pSrvCall = RxContext->Create.pSrvCall;
-    pVBoxFobx->FileStandardInfo = FileStandardInfo;
-    pVBoxFobx->FileBasicInfo = FileBasicInfo;
-    pVBoxFobx->fKeepCreationTime = FALSE;
-    pVBoxFobx->fKeepLastAccessTime = FALSE;
-    pVBoxFobx->fKeepLastWriteTime = FALSE;
-    pVBoxFobx->fKeepChangeTime = FALSE;
-    pVBoxFobx->SetFileInfoOnCloseFlags = 0;
+    pVBoxFobx->Info = Info;
+    vbsfNtCopyInfoToLegacy(pVBoxFobx, &Info);
+    Log(("VBOXSF: MRxCreate: FileBasicInformation: CreationTime   %RX64\n", pVBoxFobx->FileBasicInfo.CreationTime.QuadPart));
+    Log(("VBOXSF: MRxCreate: FileBasicInformation: LastAccessTime %RX64\n", pVBoxFobx->FileBasicInfo.LastAccessTime.QuadPart));
+    Log(("VBOXSF: MRxCreate: FileBasicInformation: LastWriteTime  %RX64\n", pVBoxFobx->FileBasicInfo.LastWriteTime.QuadPart));
+    Log(("VBOXSF: MRxCreate: FileBasicInformation: ChangeTime     %RX64\n", pVBoxFobx->FileBasicInfo.ChangeTime.QuadPart));
+    Log(("VBOXSF: MRxCreate: FileBasicInformation: FileAttributes %RX32\n", pVBoxFobx->FileBasicInfo.FileAttributes));
+    if (!(Info.Attr.fMode & RTFS_DOS_DIRECTORY))
+        Log(("VBOXSF: MRxCreate: AllocationSize = %#RX64, EndOfFile = %#RX64\n",
+             Info.cbAllocated, Info.cbObject));
 
     if (!RxIsFcbAcquiredExclusive(capFcb))
@@ -675,9 +652,9 @@
 }
 
-NTSTATUS vbsfSetFileInfo(PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension,
-                         PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension,
-                         PMRX_VBOX_FOBX pVBoxFobx,
-                         PFILE_BASIC_INFORMATION pInfo,
-                         BYTE SetAttrFlags)
+static NTSTATUS vbsfSetFileInfoOnClose(PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension,
+                                       PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension,
+                                       PMRX_VBOX_FOBX pVBoxFobx,
+                                       PFILE_BASIC_INFORMATION pInfo,
+                                       BYTE SetAttrFlags)
 {
     NTSTATUS Status = STATUS_SUCCESS;
@@ -689,10 +666,10 @@
     uint32_t cbBuffer = 0;
 
-    Log(("VBOXSF: vbsfSetFileInfo: SetAttrFlags 0x%02X\n", SetAttrFlags));
-    Log(("VBOXSF: vbsfSetFileInfo: FileBasicInformation: CreationTime   %RX64\n", pInfo->CreationTime.QuadPart));
-    Log(("VBOXSF: vbsfSetFileInfo: FileBasicInformation: LastAccessTime %RX64\n", pInfo->LastAccessTime.QuadPart));
-    Log(("VBOXSF: vbsfSetFileInfo: FileBasicInformation: LastWriteTime  %RX64\n", pInfo->LastWriteTime.QuadPart));
-    Log(("VBOXSF: vbsfSetFileInfo: FileBasicInformation: ChangeTime     %RX64\n", pInfo->ChangeTime.QuadPart));
-    Log(("VBOXSF: vbsfSetFileInfo: FileBasicInformation: FileAttributes %RX32\n", pInfo->FileAttributes));
+    Log(("VBOXSF: vbsfSetFileInfoOnClose: SetAttrFlags 0x%02X\n", SetAttrFlags));
+    Log(("VBOXSF: vbsfSetFileInfoOnClose: FileBasicInformation: CreationTime   %RX64\n", pInfo->CreationTime.QuadPart));
+    Log(("VBOXSF: vbsfSetFileInfoOnClose: FileBasicInformation: LastAccessTime %RX64\n", pInfo->LastAccessTime.QuadPart));
+    Log(("VBOXSF: vbsfSetFileInfoOnClose: FileBasicInformation: LastWriteTime  %RX64\n", pInfo->LastWriteTime.QuadPart));
+    Log(("VBOXSF: vbsfSetFileInfoOnClose: FileBasicInformation: ChangeTime     %RX64\n", pInfo->ChangeTime.QuadPart));
+    Log(("VBOXSF: vbsfSetFileInfoOnClose: FileBasicInformation: FileAttributes %RX32\n", pInfo->FileAttributes));
 
     if (SetAttrFlags == 0)
@@ -721,5 +698,5 @@
     if (pInfo->ChangeTime.QuadPart && (SetAttrFlags & VBOX_FOBX_F_INFO_CHANGE_TIME) != 0)
         RTTimeSpecSetNtTime(&pSHFLFileInfo->ChangeTime, pInfo->ChangeTime.QuadPart);
-    if (pInfo->FileAttributes && (SetAttrFlags & VBOX_FOBX_F_INFO_ATTRIBUTES) != 0)
+    if (pInfo->FileAttributes && (SetAttrFlags & VBOX_FOBX_F_INFO_ATTRIBUTES) != 0) /// @todo r=bird: never ever set.
         pSHFLFileInfo->Attr.fMode = NTToVBoxFileAttributes(pInfo->FileAttributes);
 
@@ -763,9 +740,9 @@
          * to cancel any effect of the file read/write operations on the host.
          */
-        Status = vbsfSetFileInfo(pDeviceExtension,
-                                 pNetRootExtension,
-                                 pVBoxFobx,
-                                 &pVBoxFobx->FileBasicInfo,
-                                 pVBoxFobx->SetFileInfoOnCloseFlags);
+        Status = vbsfSetFileInfoOnClose(pDeviceExtension,
+                                        pNetRootExtension,
+                                        pVBoxFobx,
+                                        &pVBoxFobx->FileBasicInfo,
+                                        pVBoxFobx->SetFileInfoOnCloseFlags);
     }
 
@@ -865,5 +842,5 @@
     vrc = VbglR0SfRemove(&pDeviceExtension->hgcmClient, &pNetRootExtension->map,
                          ParsedPath,
-                         (pVBoxFobx->FileStandardInfo.Directory) ? SHFL_REMOVE_DIR : SHFL_REMOVE_FILE);
+                         pVBoxFobx->Info.Attr.fMode & RTFS_DOS_DIRECTORY ? SHFL_REMOVE_DIR : SHFL_REMOVE_FILE);
 
     if (ParsedPath)
@@ -937,5 +914,5 @@
 
     /* Call host. */
-    flags = pVBoxFobx->FileStandardInfo.Directory? SHFL_RENAME_DIR : SHFL_RENAME_FILE;
+    flags = pVBoxFobx->Info.Attr.fMode & RTFS_DOS_DIRECTORY ? SHFL_RENAME_DIR : SHFL_RENAME_FILE;
     if (RenameInformation->ReplaceIfExists)
         flags |= SHFL_RENAME_REPLACE_IF_EXISTS;
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.c	(revision 78301)
+++ 	(revision )
@@ -1,1666 +1,0 @@
-/* $Id$ */
-/** @file
- * VirtualBox Windows Guest Shared Folders - File System Driver initialization and generic routines
- */
-
-/*
- * Copyright (C) 2012-2019 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#include "vbsf.h"
-
-
-/*
- * The current state of the driver.
- */
-typedef enum _MRX_VBOX_STATE_
-{
-    MRX_VBOX_STARTABLE,
-    MRX_VBOX_START_IN_PROGRESS,
-    MRX_VBOX_STARTED
-} MRX_VBOX_STATE, *PMRX_VBOX_STATE;
-
-static MRX_VBOX_STATE VBoxMRxState = MRX_VBOX_STARTABLE;
-
-/*
- * The VBoxSF dispatch table.
- */
-static struct _MINIRDR_DISPATCH VBoxMRxDispatch;
-
-/*
- * The VBoxSF device object.
- */
-PRDBSS_DEVICE_OBJECT VBoxMRxDeviceObject;
-
-static NTSTATUS VBoxMRxFsdDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
-{
-    NTSTATUS Status;
-#ifdef LOG_ENABLED
-    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
-    Log(("VBOXSF: MRxFsdDispatch: major %d, minor %d: %s\n",
-         IrpSp->MajorFunction, IrpSp->MinorFunction, MajorFunctionString(IrpSp->MajorFunction, IrpSp->MinorFunction)));
-#endif
-
-    if (DeviceObject != (PDEVICE_OBJECT)VBoxMRxDeviceObject)
-    {
-        Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
-        Irp->IoStatus.Information = 0;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-        Log(("VBOXSF: MRxFsdDispatch: Invalid device request detected %p %p\n",
-             DeviceObject, (PDEVICE_OBJECT)VBoxMRxDeviceObject));
-
-        return STATUS_INVALID_DEVICE_REQUEST;
-    }
-
-    Status = RxFsdDispatch((PRDBSS_DEVICE_OBJECT)VBoxMRxDeviceObject, Irp);
-    Log(("VBOXSF: MRxFsdDispatch: Returned 0x%X\n", Status));
-    return Status;
-}
-
-static void VBoxMRxUnload(IN PDRIVER_OBJECT DriverObject)
-{
-    NTSTATUS Status;
-    UNICODE_STRING UserModeDeviceName;
-
-    Log(("VBOXSF: MRxUnload\n"));
-
-    if (VBoxMRxDeviceObject)
-    {
-        PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
-        pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)VBoxMRxDeviceObject + sizeof(RDBSS_DEVICE_OBJECT));
-        VbglR0SfDisconnect(&pDeviceExtension->hgcmClient);
-    }
-
-    VbglR0SfTerm();
-
-    if (VBoxMRxDeviceObject)
-    {
-        PRX_CONTEXT RxContext;
-        RxContext = RxCreateRxContext(NULL, VBoxMRxDeviceObject, RX_CONTEXT_FLAG_IN_FSP);
-
-        if (RxContext != NULL)
-        {
-            Status = RxStopMinirdr(RxContext, &RxContext->PostRequest);
-
-            if (Status == STATUS_SUCCESS)
-            {
-                MRX_VBOX_STATE State;
-
-                State = (MRX_VBOX_STATE)InterlockedCompareExchange((LONG *)&VBoxMRxState, MRX_VBOX_STARTABLE, MRX_VBOX_STARTED);
-
-                if (State != MRX_VBOX_STARTABLE)
-                    Status = STATUS_REDIRECTOR_STARTED;
-            }
-
-            RxDereferenceAndDeleteRxContext(RxContext);
-        }
-        else
-            Status = STATUS_INSUFFICIENT_RESOURCES;
-
-        RxUnregisterMinirdr(VBoxMRxDeviceObject);
-    }
-
-    RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
-    Status = IoDeleteSymbolicLink(&UserModeDeviceName);
-    if (Status != STATUS_SUCCESS)
-        Log(("VBOXSF: MRxUnload: IoDeleteSymbolicLink Status 0x%08X\n", Status));
-
-    RxUnload(DriverObject);
-
-    Log(("VBOXSF: MRxUnload: VBoxSF.sys driver object %p unloaded\n", DriverObject));
-}
-
-static void vbsfInitMRxDispatch(void)
-{
-    Log(("VBOXSF: vbsfInitMRxDispatch: Called.\n"));
-
-    ZeroAndInitializeNodeType(&VBoxMRxDispatch, RDBSS_NTC_MINIRDR_DISPATCH, sizeof(MINIRDR_DISPATCH));
-
-    VBoxMRxDispatch.MRxFlags = (RDBSS_MANAGE_NET_ROOT_EXTENSION | RDBSS_MANAGE_FOBX_EXTENSION);
-
-    VBoxMRxDispatch.MRxSrvCallSize = 0;
-    VBoxMRxDispatch.MRxNetRootSize = sizeof(MRX_VBOX_NETROOT_EXTENSION);
-    VBoxMRxDispatch.MRxVNetRootSize = 0;
-    VBoxMRxDispatch.MRxFcbSize = 0;
-    VBoxMRxDispatch.MRxSrvOpenSize = 0;
-    VBoxMRxDispatch.MRxFobxSize = sizeof(MRX_VBOX_FOBX);
-
-    VBoxMRxDispatch.MRxStart = VBoxMRxStart;
-    VBoxMRxDispatch.MRxStop = VBoxMRxStop;
-
-    VBoxMRxDispatch.MRxCreate = VBoxMRxCreate;
-    VBoxMRxDispatch.MRxCollapseOpen = VBoxMRxCollapseOpen;
-    VBoxMRxDispatch.MRxShouldTryToCollapseThisOpen = VBoxMRxShouldTryToCollapseThisOpen;
-    VBoxMRxDispatch.MRxFlush = VBoxMRxFlush;
-    VBoxMRxDispatch.MRxTruncate = VBoxMRxTruncate;
-    VBoxMRxDispatch.MRxCleanupFobx = VBoxMRxCleanupFobx;
-    VBoxMRxDispatch.MRxCloseSrvOpen = VBoxMRxCloseSrvOpen;
-    VBoxMRxDispatch.MRxDeallocateForFcb = VBoxMRxDeallocateForFcb;
-    VBoxMRxDispatch.MRxDeallocateForFobx = VBoxMRxDeallocateForFobx;
-    VBoxMRxDispatch.MRxForceClosed = VBoxMRxForceClosed;
-
-    VBoxMRxDispatch.MRxQueryDirectory = VBoxMRxQueryDirectory;
-    VBoxMRxDispatch.MRxQueryFileInfo = VBoxMRxQueryFileInfo;
-    VBoxMRxDispatch.MRxSetFileInfo = VBoxMRxSetFileInfo;
-    VBoxMRxDispatch.MRxSetFileInfoAtCleanup = VBoxMRxSetFileInfoAtCleanup;
-    VBoxMRxDispatch.MRxQueryEaInfo = VBoxMRxQueryEaInfo;
-    VBoxMRxDispatch.MRxSetEaInfo = VBoxMRxSetEaInfo;
-    VBoxMRxDispatch.MRxQuerySdInfo = VBoxMRxQuerySdInfo;
-    VBoxMRxDispatch.MRxSetSdInfo = VBoxMRxSetSdInfo;
-    VBoxMRxDispatch.MRxQueryVolumeInfo = VBoxMRxQueryVolumeInfo;
-
-    VBoxMRxDispatch.MRxComputeNewBufferingState = VBoxMRxComputeNewBufferingState;
-
-    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_READ] = VBoxMRxRead;
-    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_WRITE] = VBoxMRxWrite;
-    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_SHAREDLOCK] = VBoxMRxLocks;
-    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_EXCLUSIVELOCK] = VBoxMRxLocks;
-    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK] = VBoxMRxLocks;
-    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK_MULTIPLE] = VBoxMRxLocks;
-    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_FSCTL] = VBoxMRxFsCtl;
-    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_IOCTL] = VBoxMRxIoCtl;
-    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_NOTIFY_CHANGE_DIRECTORY] = VBoxMRxNotifyChangeDirectory;
-
-    VBoxMRxDispatch.MRxExtendForCache = VBoxMRxExtendStub;
-    VBoxMRxDispatch.MRxExtendForNonCache = VBoxMRxExtendStub;
-    VBoxMRxDispatch.MRxCompleteBufferingStateChangeRequest = VBoxMRxCompleteBufferingStateChangeRequest;
-
-    VBoxMRxDispatch.MRxCreateVNetRoot = VBoxMRxCreateVNetRoot;
-    VBoxMRxDispatch.MRxFinalizeVNetRoot = VBoxMRxFinalizeVNetRoot;
-    VBoxMRxDispatch.MRxFinalizeNetRoot = VBoxMRxFinalizeNetRoot;
-    VBoxMRxDispatch.MRxUpdateNetRootState = VBoxMRxUpdateNetRootState;
-    VBoxMRxDispatch.MRxExtractNetRootName = VBoxMRxExtractNetRootName;
-
-    VBoxMRxDispatch.MRxCreateSrvCall = VBoxMRxCreateSrvCall;
-    VBoxMRxDispatch.MRxSrvCallWinnerNotify = VBoxMRxSrvCallWinnerNotify;
-    VBoxMRxDispatch.MRxFinalizeSrvCall = VBoxMRxFinalizeSrvCall;
-
-    VBoxMRxDispatch.MRxDevFcbXXXControlFile = VBoxMRxDevFcbXXXControlFile;
-
-    Log(("VBOXSF: vbsfInitMRxDispatch: Success.\n"));
-    return;
-}
-
-static BOOL vboxIsPrefixOK (const WCHAR *FilePathName, ULONG PathNameLength)
-{
-    BOOL PrefixOK;
-
-    /* The FilePathName here looks like: \vboxsrv\... */
-    if (PathNameLength >= 8 * sizeof (WCHAR)) /* Number of bytes in '\vboxsrv' unicode string. */
-    {
-        PrefixOK =  (FilePathName[0] == L'\\');
-        PrefixOK &= (FilePathName[1] == L'V') || (FilePathName[1] == L'v');
-        PrefixOK &= (FilePathName[2] == L'B') || (FilePathName[2] == L'b');
-        PrefixOK &= (FilePathName[3] == L'O') || (FilePathName[3] == L'o');
-        PrefixOK &= (FilePathName[4] == L'X') || (FilePathName[4] == L'x');
-        PrefixOK &= (FilePathName[5] == L'S') || (FilePathName[5] == L's');
-        /* Both vboxsvr & vboxsrv are now accepted */
-        if ((FilePathName[6] == L'V') || (FilePathName[6] == L'v'))
-        {
-            PrefixOK &= (FilePathName[6] == L'V') || (FilePathName[6] == L'v');
-            PrefixOK &= (FilePathName[7] == L'R') || (FilePathName[7] == L'r');
-        }
-        else
-        {
-            PrefixOK &= (FilePathName[6] == L'R') || (FilePathName[6] == L'r');
-            PrefixOK &= (FilePathName[7] == L'V') || (FilePathName[7] == L'v');
-        }
-        if (PathNameLength > 8 * sizeof (WCHAR))
-        {
-            /* There is something after '\vboxsrv'. */
-            PrefixOK &= (FilePathName[8] == L'\\') || (FilePathName[8] == 0);
-        }
-    }
-    else
-        PrefixOK = FALSE;
-
-    return PrefixOK;
-}
-
-static NTSTATUS VBoxMRXDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
-{
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    QUERY_PATH_REQUEST *pReq = NULL;
-    QUERY_PATH_REQUEST_EX *pReqEx = NULL;
-    QUERY_PATH_RESPONSE *pResp = NULL;
-
-    BOOL PrefixOK = FALSE;
-
-    PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
-
-    /* Make a local copy, it will be needed after the Irp completion. */
-    ULONG IoControlCode = pStack->Parameters.DeviceIoControl.IoControlCode;
-
-    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)pDevObj + sizeof(RDBSS_DEVICE_OBJECT));
-
-    Log(("VBOXSF: MRXDeviceControl: pDevObj %p, pDeviceExtension %p, code %x\n",
-         pDevObj, pDevObj->DeviceExtension, IoControlCode));
-
-    switch (IoControlCode)
-    {
-        case IOCTL_REDIR_QUERY_PATH_EX: /* Vista */
-        case IOCTL_REDIR_QUERY_PATH:    /* XP and earlier */
-        {
-            /* This IOCTL is intercepted for 2 reasons:
-             * 1) Claim the vboxsvr and vboxsrv prefixes. All name-based operations for them
-             *    will be routed to the VBox provider automatically without any prefix resolution
-             *    since the prefix is already in the prefix cache.
-             * 2) Reject other prefixes immediately to speed up the UNC path resolution a bit,
-             *    because RDBSS will not be involved then.
-             */
-
-            const WCHAR *FilePathName = NULL;
-            ULONG PathNameLength = 0;
-
-            if (pIrp->RequestorMode != KernelMode)
-            {
-                /* MSDN: Network redirectors should only honor kernel-mode senders of this IOCTL, by verifying
-                 * that RequestorMode member of the IRP structure is KernelMode.
-                 */
-                Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH(_EX): not kernel mode!!!\n",
-                      pStack->Parameters.DeviceIoControl.InputBufferLength));
-                /* Continue to RDBSS. */
-                break;
-            }
-
-            if (IoControlCode == IOCTL_REDIR_QUERY_PATH)
-            {
-                Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH: Called (pid %x).\n", IoGetCurrentProcess()));
-
-                if (pStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(QUERY_PATH_REQUEST))
-                {
-                    Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH: short input buffer %d.\n",
-                          pStack->Parameters.DeviceIoControl.InputBufferLength));
-                    /* Continue to RDBSS. */
-                    break;
-                }
-
-                pReq = (QUERY_PATH_REQUEST *)pStack->Parameters.DeviceIoControl.Type3InputBuffer;
-
-                Log(("VBOXSF: MRxDeviceControl: PathNameLength = %d.\n", pReq->PathNameLength));
-                Log(("VBOXSF: MRxDeviceControl: SecurityContext = %p.\n", pReq->SecurityContext));
-                Log(("VBOXSF: MRxDeviceControl: FilePathName = %.*ls.\n", pReq->PathNameLength / sizeof (WCHAR), pReq->FilePathName));
-
-                FilePathName = pReq->FilePathName;
-                PathNameLength = pReq->PathNameLength;
-            }
-            else
-            {
-                Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH_EX: Called.\n"));
-
-                if (pStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(QUERY_PATH_REQUEST_EX))
-                {
-                    Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH_EX: short input buffer %d.\n",
-                          pStack->Parameters.DeviceIoControl.InputBufferLength));
-                    /* Continue to RDBSS. */
-                    break;
-                }
-
-                pReqEx = (QUERY_PATH_REQUEST_EX *)pStack->Parameters.DeviceIoControl.Type3InputBuffer;
-
-                Log(("VBOXSF: MRxDeviceControl: pSecurityContext = %p.\n", pReqEx->pSecurityContext));
-                Log(("VBOXSF: MRxDeviceControl: EaLength = %d.\n", pReqEx->EaLength));
-                Log(("VBOXSF: MRxDeviceControl: pEaBuffer = %p.\n", pReqEx->pEaBuffer));
-                Log(("VBOXSF: MRxDeviceControl: PathNameLength = %d.\n", pReqEx->PathName.Length));
-                Log(("VBOXSF: MRxDeviceControl: FilePathName = %.*ls.\n", pReqEx->PathName.Length / sizeof (WCHAR), pReqEx->PathName.Buffer));
-
-                FilePathName = pReqEx->PathName.Buffer;
-                PathNameLength = pReqEx->PathName.Length;
-            }
-
-            pResp = (QUERY_PATH_RESPONSE *)pIrp->UserBuffer;
-
-            PrefixOK = vboxIsPrefixOK (FilePathName, PathNameLength);
-            Log(("VBOXSF: MRxDeviceControl PrefixOK %d\n", PrefixOK));
-
-            if (!PrefixOK)
-            {
-                /* Immediately fail the IOCTL with STATUS_BAD_NETWORK_NAME as recommended by MSDN.
-                 * No need to involve RDBSS.
-                 */
-                Status = STATUS_BAD_NETWORK_NAME;
-
-                pIrp->IoStatus.Status = Status;
-                pIrp->IoStatus.Information = 0;
-
-                IoCompleteRequest(pIrp, IO_NO_INCREMENT);
-
-                Log(("VBOXSF: MRxDeviceControl: returned STATUS_BAD_NETWORK_NAME\n"));
-                return Status;
-            }
-
-            Log(("VBOXSF: MRxDeviceControl pResp %p verifying the path.\n", pResp));
-            if (pResp)
-            {
-                /* Always claim entire \vboxsrv prefix. The LengthAccepted initially is equal to entire path.
-                 * Here it is assigned to the length of \vboxsrv prefix.
-                 */
-                pResp->LengthAccepted = 8 * sizeof (WCHAR);
-
-                Status = STATUS_SUCCESS;
-
-                pIrp->IoStatus.Status = Status;
-                pIrp->IoStatus.Information = 0;
-
-                IoCompleteRequest(pIrp, IO_NO_INCREMENT);
-
-                Log(("VBOXSF: MRxDeviceControl: claiming the path.\n"));
-                return Status;
-            }
-
-            /* No pResp pointer, should not happen. Just a precaution. */
-            Status = STATUS_INVALID_PARAMETER;
-
-            pIrp->IoStatus.Status = Status;
-            pIrp->IoStatus.Information = 0;
-
-            IoCompleteRequest(pIrp, IO_NO_INCREMENT);
-
-            Log(("VBOXSF: MRxDeviceControl: returned STATUS_INVALID_PARAMETER\n"));
-            return Status;
-        }
-
-        default:
-            break;
-    }
-
-    /* Pass the IOCTL to RDBSS. */
-    if (pDeviceExtension && pDeviceExtension->pfnRDBSSDeviceControl)
-    {
-        Log(("VBOXSF: MRxDeviceControl calling RDBSS %p\n", pDeviceExtension->pfnRDBSSDeviceControl));
-        Status = pDeviceExtension->pfnRDBSSDeviceControl (pDevObj, pIrp);
-        Log(("VBOXSF: MRxDeviceControl RDBSS status 0x%08X\n", Status));
-    }
-    else
-    {
-        /* No RDBSS, should not happen. Just a precaution. */
-        Status = STATUS_NOT_IMPLEMENTED;
-
-        pIrp->IoStatus.Status = Status;
-        pIrp->IoStatus.Information = 0;
-
-        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
-
-        Log(("VBOXSF: MRxDeviceControl: returned STATUS_NOT_IMPLEMENTED\n"));
-    }
-
-    return Status;
-}
-
-/**
- * Intercepts IRP_MJ_CREATE to workaround a RDBSS quirk.
- *
- * Our RDBSS library will return STATUS_OBJECT_NAME_INVALID when FILE_NON_DIRECTORY_FILE
- * is set and the path ends with a slash.  NTFS and FAT will fail with
- * STATUS_OBJECT_NAME_NOT_FOUND if the final component does not exist or isn't a directory,
- * STATUS_OBJECT_PATH_NOT_FOUND if some path component doesn't exist or isn't a directory,
- * or STATUS_ACCESS_DENIED if the final component is a directory.
- *
- * So, our HACK is to drop the trailing slash and set an unused flag in the ShareAccess
- * parameter to tell vbsfProcessCreate about it.
- *
- */
-static NTSTATUS VBoxHookMjCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
-{
-    PMRX_VBOX_DEVICE_EXTENSION  pDevExt  = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)pDevObj + sizeof(RDBSS_DEVICE_OBJECT));
-    PIO_STACK_LOCATION          pStack   = IoGetCurrentIrpStackLocation(pIrp);
-    PFILE_OBJECT                pFileObj = pStack->FileObject;
-    NTSTATUS                    rcNt;
-
-    Log(("VBOXSF: VBoxHookMjCreate: pDevObj %p, pDevExt %p, pFileObj %p, options %#x, attr %#x, share %#x, ealength %#x, secctx %p\n",
-         pDevObj, pDevObj->DeviceExtension, pFileObj, pStack->Parameters.Create.Options, pStack->Parameters.Create.FileAttributes,
-         pStack->Parameters.Create.ShareAccess, pStack->Parameters.Create.EaLength, pStack->Parameters.Create.SecurityContext));
-    if (pFileObj)
-        Log(("VBOXSF: VBoxHookMjCreate: FileName=%.*ls\n", pFileObj->FileName.Length / sizeof(WCHAR), pFileObj->FileName.Buffer));
-
-    /*
-     * Check if we need to apply the hack.  If we do, we grab a reference to
-     * the file object to be absolutely sure it's around for the cleanup work.
-     */
-    AssertMsg(!(pStack->Parameters.Create.ShareAccess & VBOX_MJ_CREATE_SLASH_HACK), ("%#x\n", pStack->Parameters.Create.ShareAccess));
-    if (   (pStack->Parameters.Create.Options & (FILE_NON_DIRECTORY_FILE | FILE_DIRECTORY_FILE)) == FILE_NON_DIRECTORY_FILE
-        && pFileObj
-        && pFileObj->FileName.Length > 18
-        && pFileObj->FileName.Buffer
-        && pFileObj->FileName.Buffer[pFileObj->FileName.Length / sizeof(WCHAR) - 1] == '\\'
-        && pFileObj->FileName.Buffer[pFileObj->FileName.Length / sizeof(WCHAR) - 2] != '\\')
-    {
-        NTSTATUS rcNtRef = ObReferenceObjectByPointer(pFileObj, (ACCESS_MASK)0, *IoFileObjectType, KernelMode);
-        pFileObj->FileName.Length -= 2;
-        pStack->Parameters.Create.ShareAccess |= VBOX_MJ_CREATE_SLASH_HACK; /* secret flag for vbsfProcessCreate */
-
-        rcNt = pDevExt->pfnRDBSSCreate(pDevObj, pIrp);
-
-        if (rcNt != STATUS_PENDING)
-            pStack->Parameters.Create.ShareAccess &= ~VBOX_MJ_CREATE_SLASH_HACK;
-        if (NT_SUCCESS(rcNtRef))
-        {
-            pFileObj->FileName.Length += 2;
-            ObDereferenceObject(pFileObj);
-        }
-
-        Log(("VBOXSF: VBoxHookMjCreate: returns %#x (hacked; rcNtRef=%#x)\n", rcNt, rcNtRef));
-    }
-    /*
-     * No hack needed.
-     */
-    else
-    {
-        rcNt = pDevExt->pfnRDBSSCreate(pDevObj, pIrp);
-        Log(("VBOXSF: VBoxHookMjCreate: returns %#x\n", rcNt));
-    }
-    return rcNt;
-}
-
-NTSTATUS DriverEntry(IN PDRIVER_OBJECT  DriverObject,
-                     IN PUNICODE_STRING RegistryPath)
-{
-    NTSTATUS Status;
-    UNICODE_STRING VBoxMRxName;
-    UNICODE_STRING UserModeDeviceName;
-    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = NULL;
-    ULONG i;
-    int vrc;
-    VBGLSFCLIENT hgcmClient;
-
-    Log(("VBOXSF: DriverEntry: Driver object %p\n", DriverObject));
-
-    if (!DriverObject)
-    {
-        Log(("VBOXSF: DriverEntry: driver object is NULL.\n"));
-        return STATUS_UNSUCCESSFUL;
-    }
-
-    /* Initialize VBox subsystem. */
-    vrc = VbglR0SfInit();
-    if (RT_FAILURE(vrc))
-    {
-        Log(("VBOXSF: DriverEntry: ERROR while initializing VBox subsystem (%Rrc)!\n", vrc));
-        return STATUS_UNSUCCESSFUL;
-    }
-
-    /* Connect the HGCM client */
-    RT_ZERO(hgcmClient);
-    vrc = VbglR0SfConnect(&hgcmClient);
-    if (RT_FAILURE(vrc))
-    {
-        Log(("VBOXSF: DriverEntry: ERROR while connecting to host (%Rrc)!\n",
-             vrc));
-        VbglR0SfTerm();
-        return STATUS_UNSUCCESSFUL;
-    }
-
-    /* Init the driver object. */
-    DriverObject->DriverUnload = VBoxMRxUnload;
-    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
-    {
-        DriverObject->MajorFunction[i] = (PDRIVER_DISPATCH)VBoxMRxFsdDispatch;
-    }
-
-    /* Forward to RDBSS. */
-    Status = RxDriverEntry(DriverObject, RegistryPath);
-    if (Status != STATUS_SUCCESS)
-    {
-        Log(("VBOXSF: DriverEntry: RxDriverEntry failed: 0x%08X\n", Status));
-        goto failure;
-    }
-
-    __try
-    {
-        Log(("VBOXSF: DriverEntry: RxRegisterMinirdr: calling VBoxMRxDeviceObject %p\n",
-             VBoxMRxDeviceObject));
-
-        RtlInitUnicodeString(&VBoxMRxName, DD_MRX_VBOX_FS_DEVICE_NAME_U);
-
-        /* Don use RX_REGISTERMINI_FLAG_DONT_PROVIDE_UNCS or else
-         * UNC mappings don't work (including Windows explorer browsing).
-         */
-        Status = RxRegisterMinirdr(&VBoxMRxDeviceObject,
-                                   DriverObject,
-                                   &VBoxMRxDispatch,
-                                   RX_REGISTERMINI_FLAG_DONT_PROVIDE_MAILSLOTS,
-                                   &VBoxMRxName,
-                                   sizeof(MRX_VBOX_DEVICE_EXTENSION),
-                                   FILE_DEVICE_NETWORK_FILE_SYSTEM,
-                                   FILE_REMOTE_DEVICE);
-
-        Log(("VBOXSF: DriverEntry: RxRegisterMinirdr: returned 0x%08X VBoxMRxDeviceObject %p\n",
-             Status, VBoxMRxDeviceObject));
-
-        if (Status!=STATUS_SUCCESS)
-        {
-            Log(("VBOXSF: DriverEntry: RxRegisterMinirdr failed: 0x%08X\n", Status ));
-            try_return((void)Status);
-        }
-
-        /* Init the device extension.
-         * NOTE: the device extension actually points to fields
-         * in the RDBSS_DEVICE_OBJECT. Our space is past the end
-         * of this struct!!
-         */
-        pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)VBoxMRxDeviceObject + sizeof(RDBSS_DEVICE_OBJECT));
-
-        pDeviceExtension->pDeviceObject = VBoxMRxDeviceObject;
-
-        for (i = 0; i < RT_ELEMENTS(pDeviceExtension->cLocalConnections); i++)
-        {
-            pDeviceExtension->cLocalConnections[i] = FALSE;
-        }
-
-        /* Mutex for synchronizining our connection list */
-        ExInitializeFastMutex(&pDeviceExtension->mtxLocalCon);
-
-        /* The device object has been created. Need to setup a symbolic
-         * link so that the device may be accessed from a Win32 user mode
-         * application.
-         */
-
-        RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
-        Log(("VBOXSF: DriverEntry: Calling IoCreateSymbolicLink\n"));
-        Status = IoCreateSymbolicLink(&UserModeDeviceName, &VBoxMRxName);
-        if (Status != STATUS_SUCCESS)
-        {
-            Log(("VBOXSF: DriverEntry: IoCreateSymbolicLink: 0x%08X\n",
-                 Status));
-            try_return((void)Status);
-        }
-        Log(("VBOXSF: DriverEntry: Symbolic link created.\n"));
-
-        /*
-         * Build the dispatch tables for the minirdr
-         */
-        vbsfInitMRxDispatch();
-
-    try_exit:
-         ;
-    }
-    __finally
-    {
-        ;
-    }
-
-    if (Status != STATUS_SUCCESS)
-    {
-        Log(("VBOXSF: DriverEntry: VBoxSF.sys failed to start with Status = 0x%08X\n",
-             Status));
-        goto failure;
-    }
-
-    AssertPtr(pDeviceExtension);
-    pDeviceExtension->hgcmClient = hgcmClient;
-
-    /* The redirector driver must intercept the IOCTL to avoid VBOXSVR name resolution
-     * by other redirectors. These additional name resolutions cause long delays.
-     */
-    Log(("VBOXSF: DriverEntry: VBoxMRxDeviceObject = %p, rdbss %p, devext %p\n",
-         VBoxMRxDeviceObject, DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL], pDeviceExtension));
-    pDeviceExtension->pfnRDBSSDeviceControl = DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL];
-    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxMRXDeviceControl;
-
-    /* Intercept IRP_MJ_CREATE to fix incorrect (wrt NTFS, FAT, ++) return
-     * codes for NtOpenFile("r:\\asdf\\", FILE_NON_DIRECTORY_FILE).
-     */
-    pDeviceExtension->pfnRDBSSCreate = DriverObject->MajorFunction[IRP_MJ_CREATE];
-    DriverObject->MajorFunction[IRP_MJ_CREATE] = VBoxHookMjCreate;
-
-
-    /** @todo start the redirector here RxStartMiniRdr. */
-
-    Log(("VBOXSF: DriverEntry: Init successful!\n"));
-    return STATUS_SUCCESS;
-
-failure:
-
-    Log(("VBOXSF: DriverEntry: Failure! Status = 0x%08X\n", Status));
-
-    VbglR0SfDisconnect(&hgcmClient);
-    VbglR0SfTerm();
-
-    if (VBoxMRxDeviceObject)
-    {
-        RxUnregisterMinirdr(VBoxMRxDeviceObject);
-        VBoxMRxDeviceObject = NULL;
-    }
-
-    return Status;
-}
-
-NTSTATUS VBoxMRxStart(PRX_CONTEXT RxContext, IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject)
-{
-    NTSTATUS Status;
-    MRX_VBOX_STATE CurrentState;
-    RT_NOREF(RxContext, RxDeviceObject);
-
-    Log(("VBOXSF: MRxStart\n"));
-
-    CurrentState = (MRX_VBOX_STATE)InterlockedCompareExchange((PLONG)&VBoxMRxState, MRX_VBOX_STARTED, MRX_VBOX_START_IN_PROGRESS);
-
-    if (CurrentState == MRX_VBOX_START_IN_PROGRESS)
-    {
-        Log(("VBOXSF: MRxStart: Start in progress -> started\n"));
-        Status = STATUS_SUCCESS;
-    }
-    else if (VBoxMRxState == MRX_VBOX_STARTED)
-    {
-        Log(("VBOXSF: MRxStart: Already started\n"));
-        Status = STATUS_REDIRECTOR_STARTED;
-    }
-    else
-    {
-        Log(("VBOXSF: MRxStart: Bad state! VBoxMRxState = %d\n", VBoxMRxState));
-        Status = STATUS_UNSUCCESSFUL;
-    }
-
-    return Status;
-}
-
-NTSTATUS VBoxMRxStop(PRX_CONTEXT RxContext, IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject)
-{
-    RT_NOREF(RxContext, RxDeviceObject);
-    Log(("VBOXSF: MRxStop\n"));
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS VBoxMRxIoCtl(IN OUT PRX_CONTEXT RxContext)
-{
-    RT_NOREF(RxContext);
-    Log(("VBOXSF: MRxIoCtl: IoControlCode = 0x%08X\n", RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode));
-    return STATUS_INVALID_DEVICE_REQUEST;
-}
-
-NTSYSAPI NTSTATUS NTAPI ZwSetSecurityObject(IN HANDLE Handle,
-                                            IN SECURITY_INFORMATION SecurityInformation,
-                                            IN PSECURITY_DESCRIPTOR SecurityDescriptor);
-
-NTSTATUS VBoxMRxDevFcbXXXControlFile(IN OUT PRX_CONTEXT RxContext)
-{
-    NTSTATUS Status = STATUS_SUCCESS;
-    RxCaptureFobx;
-    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
-    PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
-
-    Log(("VBOXSF: MRxDevFcbXXXControlFile: MajorFunction = 0x%02X\n",
-         RxContext->MajorFunction));
-
-    switch (RxContext->MajorFunction)
-    {
-        case IRP_MJ_FILE_SYSTEM_CONTROL:
-        {
-            Log(("VBOXSF: MRxDevFcbXXXControlFile: IRP_MN_USER_FS_REQUEST: 0x%08X\n",
-                 LowIoContext->ParamsFor.FsCtl.MinorFunction));
-            Status = STATUS_INVALID_DEVICE_REQUEST;
-            break;
-        }
-
-        case IRP_MJ_DEVICE_CONTROL:
-        {
-            Log(("VBOXSF: MRxDevFcbXXXControlFile: IRP_MJ_DEVICE_CONTROL: InputBuffer %p/%d, OutputBuffer %p/%d\n",
-                 LowIoContext->ParamsFor.IoCtl.pInputBuffer,
-                 LowIoContext->ParamsFor.IoCtl.InputBufferLength,
-                 LowIoContext->ParamsFor.IoCtl.pOutputBuffer,
-                 LowIoContext->ParamsFor.IoCtl.OutputBufferLength));
-
-            switch (LowIoContext->ParamsFor.IoCtl.IoControlCode)
-            {
-                case IOCTL_MRX_VBOX_ADDCONN:
-                {
-                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_ADDCONN\n"));
-                    Status = vbsfCreateConnection(RxContext, &RxContext->PostRequest);
-                    break;
-                }
-
-                case IOCTL_MRX_VBOX_DELCONN:
-                {
-                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_DELCONN\n"));
-                    Status = vbsfDeleteConnection(RxContext, &RxContext->PostRequest);
-                    break;
-                }
-
-                case IOCTL_MRX_VBOX_GETLIST:
-                {
-                    ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
-                    uint8_t *pu8Out = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
-
-                    BOOLEAN fLocked = FALSE;
-
-                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST\n"));
-
-                    RxContext->InformationToReturn = 0;
-
-                    if (   !pDeviceExtension
-                        || cbOut < _MRX_MAX_DRIVE_LETTERS)
-                    {
-                        Status = STATUS_INVALID_PARAMETER;
-                        break;
-                    }
-
-                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST: Copying local connections\n"));
-
-                    fLocked = ExTryToAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
-
-                    __try
-                    {
-                        RtlCopyMemory(pu8Out, pDeviceExtension->cLocalConnections, _MRX_MAX_DRIVE_LETTERS);
-                        RxContext->InformationToReturn = _MRX_MAX_DRIVE_LETTERS;
-                    }
-                    __except(EXCEPTION_EXECUTE_HANDLER)
-                    {
-                        Status = STATUS_INVALID_PARAMETER;
-                    }
-
-                    if (fLocked)
-                    {
-                        ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
-                        fLocked = FALSE;
-                    }
-
-                    break;
-                }
-
-                /*
-                 * Returns the root IDs of shared folder mappings.
-                 */
-                case IOCTL_MRX_VBOX_GETGLOBALLIST:
-                {
-                    ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
-                    uint8_t *pu8Out = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
-
-                    int vrc;
-                    SHFLMAPPING mappings[_MRX_MAX_DRIVE_LETTERS];
-                    uint32_t cMappings = RT_ELEMENTS(mappings);
-
-                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALLIST\n"));
-
-                    RxContext->InformationToReturn = 0;
-
-                    if (   !pDeviceExtension
-                        || cbOut < _MRX_MAX_DRIVE_LETTERS)
-                    {
-                        Status = STATUS_INVALID_PARAMETER;
-                        break;
-                    }
-
-                    vrc = VbglR0SfQueryMappings(&pDeviceExtension->hgcmClient, mappings, &cMappings);
-                    if (vrc == VINF_SUCCESS)
-                    {
-                        __try
-                        {
-                            uint32_t i;
-
-                            RtlZeroMemory(pu8Out, _MRX_MAX_DRIVE_LETTERS);
-
-                            for (i = 0; i < RT_MIN(cMappings, cbOut); i++)
-                            {
-                                pu8Out[i] = mappings[i].root;
-                                pu8Out[i] |= 0x80; /* mark active */ /** @todo fix properly */
-                            }
-
-                            RxContext->InformationToReturn = _MRX_MAX_DRIVE_LETTERS;
-                        }
-                        __except(EXCEPTION_EXECUTE_HANDLER)
-                        {
-                            Status = STATUS_INVALID_PARAMETER;
-                        }
-                    }
-                    else
-                    {
-                        Status = VBoxErrorToNTStatus(vrc);
-                        Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALLIST failed: 0x%08X\n",
-                             Status));
-                    }
-
-                    break;
-                }
-
-                /*
-                 * Translates a local connection name (e.g. drive "S:") to the
-                 * corresponding remote name (e.g. \\vboxsrv\share).
-                 */
-                case IOCTL_MRX_VBOX_GETCONN:
-                {
-                    ULONG cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
-                    PWCHAR pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
-                    ULONG cbRemoteName = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
-                    PWCHAR pwcRemoteName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
-
-                    BOOLEAN fMutexAcquired = FALSE;
-
-                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN\n"));
-
-                    RxContext->InformationToReturn = 0;
-
-                    if (   !pDeviceExtension
-                        || cbConnectName < sizeof(WCHAR))
-                    {
-                        Status = STATUS_INVALID_PARAMETER;
-                        break;
-                    }
-
-                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Looking up connection name and connections\n"));
-
-                    __try
-                    {
-                        uint32_t idx = *pwcConnectName - L'A';
-
-                        Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: ConnectName = %.*ls, Len = %d, Index = %d\n",
-                             cbConnectName / sizeof(WCHAR), pwcConnectName, cbConnectName, idx));
-
-                        if (idx < RTL_NUMBER_OF(pDeviceExtension->wszLocalConnectionName))
-                        {
-                            ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
-                            fMutexAcquired = TRUE;
-
-                            if (pDeviceExtension->wszLocalConnectionName[idx])
-                            {
-                                ULONG cbLocalConnectionName = pDeviceExtension->wszLocalConnectionName[idx]->Length;
-
-                                Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName = %.*ls\n",
-                                     cbLocalConnectionName / sizeof(WCHAR), pDeviceExtension->wszLocalConnectionName[idx]->Buffer));
-
-                                if ((pDeviceExtension->cLocalConnections[idx]) && (cbLocalConnectionName <= cbRemoteName))
-                                {
-                                    RtlZeroMemory(pwcRemoteName, cbRemoteName);
-                                    RtlCopyMemory(pwcRemoteName,
-                                                  pDeviceExtension->wszLocalConnectionName[idx]->Buffer,
-                                                  cbLocalConnectionName);
-
-                                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Remote name = %.*ls, Len = %d\n",
-                                         cbLocalConnectionName / sizeof(WCHAR), pwcRemoteName, cbLocalConnectionName));
-                                }
-                                else
-                                {
-                                    Status = STATUS_BUFFER_TOO_SMALL;
-                                }
-
-                                RxContext->InformationToReturn = cbLocalConnectionName;
-                            }
-                            else
-                            {
-                                Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName is NULL!\n"));
-                                Status = STATUS_BAD_NETWORK_NAME;
-                            }
-                        }
-                        else
-                        {
-                            Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Index is invalid!\n"));
-                            Status = STATUS_INVALID_PARAMETER;
-                        }
-                    }
-                    __except(EXCEPTION_EXECUTE_HANDLER)
-                    {
-                        Status = STATUS_INVALID_PARAMETER;
-                    }
-
-                    if (fMutexAcquired)
-                    {
-                        ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
-                        fMutexAcquired = FALSE;
-                    }
-
-                    break;
-                }
-
-                case IOCTL_MRX_VBOX_GETGLOBALCONN:
-                {
-                    ULONG cbConnectId = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
-                    uint8_t *pu8ConnectId = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
-                    ULONG cbRemoteName = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
-                    PWCHAR pwcRemoteName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
-
-                    int vrc;
-                    PSHFLSTRING pString;
-
-                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN\n"));
-
-                    RxContext->InformationToReturn = 0;
-
-                    if (   !pDeviceExtension
-                        || cbConnectId < sizeof(uint8_t))
-                    {
-                        Status = STATUS_INVALID_PARAMETER;
-                        break;
-                    }
-
-                    /* Allocate empty string where the host can store cbRemoteName bytes. */
-                    Status = vbsfShflStringFromUnicodeAlloc(&pString, NULL, (uint16_t)cbRemoteName);
-                    if (Status != STATUS_SUCCESS)
-                        break;
-
-                    __try
-                    {
-                        Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Connection ID = %d\n",
-                             *pu8ConnectId));
-
-                        vrc = VbglR0SfQueryMapName(&pDeviceExtension->hgcmClient,
-                                                   *pu8ConnectId & ~0x80 /** @todo fix properly */,
-                                                   pString, ShflStringSizeOfBuffer(pString));
-                        if (   vrc == VINF_SUCCESS
-                            && pString->u16Length < cbRemoteName)
-                        {
-                            RtlCopyMemory(pwcRemoteName, pString->String.ucs2, pString->u16Length);
-                            Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Returned name = %.*ls, Len = %d\n",
-                                 pString->u16Length / sizeof(WCHAR), pwcRemoteName, pString->u16Length));
-                            RxContext->InformationToReturn = pString->u16Length;
-                        }
-                        else
-                        {
-                            Status = STATUS_BAD_NETWORK_NAME;
-                        }
-                    }
-                    __except(EXCEPTION_EXECUTE_HANDLER)
-                    {
-                        Status = STATUS_INVALID_PARAMETER;
-                    }
-
-                    vbsfFreeNonPagedMem(pString);
-
-                    break;
-                }
-
-                case IOCTL_MRX_VBOX_START:
-                {
-                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: capFobx %p\n",
-                         capFobx));
-
-                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: process: current 0x%X, RDBSS 0x%X\n",
-                         IoGetCurrentProcess(), RxGetRDBSSProcess()));
-
-                    switch (VBoxMRxState)
-                    {
-                        case MRX_VBOX_STARTABLE:
-
-                            Log(("VBOXSF: MRxDevFcbXXXControlFile: MRX_VBOX_STARTABLE\n"));
-
-                            if (capFobx)
-                            {
-                                Status = STATUS_INVALID_DEVICE_REQUEST;
-                                break;;
-                            }
-
-                            InterlockedCompareExchange((PLONG)&VBoxMRxState, MRX_VBOX_START_IN_PROGRESS, MRX_VBOX_STARTABLE);
-
-                        case MRX_VBOX_START_IN_PROGRESS:
-                            Status = RxStartMinirdr(RxContext, &RxContext->PostRequest);
-
-                            Log(("VBOXSF: MRxDevFcbXXXControlFile: MRX_VBOX_START_IN_PROGRESS RxStartMiniRdr Status 0x%08X, post %d\n",
-                                 Status, RxContext->PostRequest));
-
-                            if (Status == STATUS_REDIRECTOR_STARTED)
-                            {
-                                Status = STATUS_SUCCESS;
-                                break;
-                            }
-
-                            if (   Status == STATUS_PENDING
-                                && RxContext->PostRequest == TRUE)
-                            {
-                                /* Will be restarted in RDBSS process. */
-                                Status = STATUS_MORE_PROCESSING_REQUIRED;
-                                break;
-                            }
-
-                            /* Allow restricted users to use shared folders; works only in XP and Vista. (@@todo hack) */
-                            if (Status == STATUS_SUCCESS)
-                            {
-                                SECURITY_DESCRIPTOR SecurityDescriptor;
-                                OBJECT_ATTRIBUTES InitializedAttributes;
-                                HANDLE hDevice;
-                                IO_STATUS_BLOCK IoStatusBlock;
-                                UNICODE_STRING UserModeDeviceName;
-
-                                RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
-
-                                /* Create empty security descriptor */
-                                RtlZeroMemory (&SecurityDescriptor, sizeof (SecurityDescriptor));
-                                Status = RtlCreateSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
-                                if (Status != STATUS_SUCCESS)
-                                {
-                                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: RtlCreateSecurityDescriptor failed with 0x%08X!\n",
-                                         Status));
-                                    return Status;
-                                }
-
-                                RtlZeroMemory (&InitializedAttributes, sizeof (InitializedAttributes));
-                                InitializeObjectAttributes(&InitializedAttributes, &UserModeDeviceName, OBJ_KERNEL_HANDLE, 0, 0);
-
-                                /* Open our symbolic link device name */
-                                Status = ZwOpenFile(&hDevice, WRITE_DAC, &InitializedAttributes, &IoStatusBlock, 0, 0);
-                                if (Status != STATUS_SUCCESS)
-                                {
-                                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwOpenFile %ls failed with 0x%08X!\n",
-                                         DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U, Status));
-                                    return Status;
-                                }
-
-                                /* Override the discretionary access control list (DACL) settings */
-                                Status = ZwSetSecurityObject(hDevice, DACL_SECURITY_INFORMATION, &SecurityDescriptor);
-                                if (Status != STATUS_SUCCESS)
-                                {
-                                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwSetSecurityObject failed with 0x%08X!\n",
-                                         Status));
-                                    return Status;
-                                }
-
-                                Status = ZwClose(hDevice);
-                                if (Status != STATUS_SUCCESS)
-                                {
-                                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwClose failed with 0x%08X\n",
-                                         Status));
-                                    return Status;
-                                }
-                            }
-                            break;
-
-                        case MRX_VBOX_STARTED:
-                            Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_STARTED: Already started\n"));
-                            Status = STATUS_SUCCESS;
-                            break;
-
-                        default:
-                            Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Invalid state (%d)!\n",
-                                 VBoxMRxState));
-                            Status = STATUS_INVALID_PARAMETER;
-                            break;
-                    }
-
-                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Returned 0x%08X\n",
-                         Status));
-                    break;
-                }
-
-                case IOCTL_MRX_VBOX_STOP:
-                {
-                    MRX_VBOX_STATE CurrentState;
-
-                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: capFobx %p\n",
-                         capFobx));
-
-                    if (capFobx)
-                    {
-                        Status = STATUS_INVALID_DEVICE_REQUEST;
-                        break;
-                    }
-
-                    if (RxContext->RxDeviceObject->NumberOfActiveFcbs > 0)
-                    {
-                        Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Open handles = %d\n",
-                             RxContext->RxDeviceObject->NumberOfActiveFcbs));
-                        Status = STATUS_REDIRECTOR_HAS_OPEN_HANDLES;
-                        break;
-                    }
-
-                    CurrentState = (MRX_VBOX_STATE)InterlockedCompareExchange((PLONG) & VBoxMRxState, MRX_VBOX_STARTABLE, MRX_VBOX_STARTED);
-
-                    Status = RxStopMinirdr(RxContext, &RxContext->PostRequest);
-                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Returned 0x%08X\n",
-                         Status));
-
-                    if (Status == STATUS_PENDING && RxContext->PostRequest == TRUE)
-                        Status = STATUS_MORE_PROCESSING_REQUIRED;
-                    break;
-                }
-
-                default:
-                    Status = STATUS_INVALID_DEVICE_REQUEST;
-                    break;
-            }
-            break;
-        }
-
-        case IRP_MJ_INTERNAL_DEVICE_CONTROL:
-        {
-            Status = STATUS_INVALID_DEVICE_REQUEST;
-            break;
-        }
-
-        default:
-            Log(("VBOXSF: MRxDevFcbXXXControlFile: unimplemented major function 0x%02X\n",
-                 RxContext->MajorFunction));
-            Status = STATUS_INVALID_DEVICE_REQUEST;
-            break;
-    }
-
-    Log(("VBOXSF: MRxDevFcbXXXControlFile: Status = 0x%08X, Info = 0x%08X\n",
-         Status, RxContext->InformationToReturn));
-
-    return Status;
-}
-
-static NTSTATUS vbsfVerifyConnectionName(PUNICODE_STRING ConnectionName)
-{
-    /* Check that the connection name is valid:
-     * "\Device\VBoxMiniRdr\;X:\vboxsvr\sf"
-     */
-    NTSTATUS Status = STATUS_BAD_NETWORK_NAME;
-
-    ULONG i;
-    PWCHAR pwc;
-    PWCHAR pwc1;
-
-    static PWCHAR spwszPrefix = L"\\Device\\VBoxMiniRdr\\;";
-
-    /* Unicode chars in the string. */
-    ULONG cConnectionName = ConnectionName->Length / sizeof(WCHAR);
-    ULONG cRemainingName;
-
-    /* Check that the name starts with correct prefix. */
-    pwc1 = &spwszPrefix[0];
-    pwc = ConnectionName->Buffer;
-    for (i = 0; i < cConnectionName; i++, pwc1++, pwc++)
-    {
-        if (*pwc1 == 0 || *pwc == 0 || *pwc1 != *pwc)
-            break;
-    }
-
-    cRemainingName = cConnectionName - i;
-
-    Log(("VBOXSF: vbsfVerifyConnectionName: prefix %d remaining %d [%.*ls]\n",
-         *pwc1 == 0, cRemainingName, cRemainingName, &ConnectionName->Buffer[i]));
-
-    if (*pwc1 == 0)
-    {
-        /* pwc should point to a drive letter followed by ':\' that is at least 3 chars more. */
-        if (cRemainingName >= 3)
-        {
-           if (   pwc[0] >= L'A' && pwc[0] <= L'Z'
-               && pwc[1] == L':')
-           {
-               pwc += 2;
-               cRemainingName -= 2;
-
-               /** @todo should also check that the drive letter corresponds to the name. */
-               if (vboxIsPrefixOK(pwc, cRemainingName * sizeof (WCHAR)))
-                   Status = STATUS_SUCCESS;
-           }
-        }
-    }
-
-    return Status;
-}
-
-static HANDLE vbsfOpenConnectionHandle(PUNICODE_STRING ConnectionName, NTSTATUS *prcNt)
-{
-    NTSTATUS Status;
-    IO_STATUS_BLOCK IoStatusBlock;
-    OBJECT_ATTRIBUTES ObjectAttributes;
-
-    HANDLE Handle = INVALID_HANDLE_VALUE;
-
-    Log(("VBOXSF: vbsfOpenConnectionHandle: ConnectionName = %.*ls\n",
-         ConnectionName->Length / sizeof(WCHAR), ConnectionName->Buffer));
-
-    Status = vbsfVerifyConnectionName(ConnectionName);
-
-    if (NT_SUCCESS(Status))
-    {
-        /* Have to create a OBJ_KERNEL_HANDLE. Otherwise the driver verifier on Windows 7 bugchecks. */
-        InitializeObjectAttributes(&ObjectAttributes,
-                                   ConnectionName,
-                                   OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
-                                   NULL,
-                                   NULL);
-
-        Status = ZwCreateFile(&Handle,
-                              SYNCHRONIZE,
-                              &ObjectAttributes,
-                              &IoStatusBlock,
-                              NULL,
-                              FILE_ATTRIBUTE_NORMAL,
-                              FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                              FILE_OPEN_IF,
-                              FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
-                              NULL,
-                              0);
-    }
-
-    if (   Status != STATUS_SUCCESS
-        || Handle == INVALID_HANDLE_VALUE)
-    {
-        Log(("VBOXSF: vbsfOpenConnectionHandle: ZwCreateFile failed status 0x%08X or invalid handle!\n", Status));
-        if (prcNt)
-            *prcNt = !NT_SUCCESS(Status) ? Status : STATUS_UNSUCCESSFUL;
-        Handle = INVALID_HANDLE_VALUE;
-    }
-
-    return Handle;
-}
-
-NTSTATUS vbsfCreateConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp)
-{
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
-
-    PLOWIO_CONTEXT LowIoContext;
-    ULONG cbConnectName;
-    PWCHAR pwcConnectName;
-
-    HANDLE Handle;
-    UNICODE_STRING FileName;
-
-    BOOLEAN fMutexAcquired = FALSE;
-
-    Log(("VBOXSF: vbsfCreateConnection\n"));
-
-    if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT))
-    {
-        Log(("VBOXSF: vbsfCreateConnection: post to file system process\n"));
-        *PostToFsp = TRUE;
-        return STATUS_PENDING;
-    }
-
-    pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
-    if (!pDeviceExtension)
-        return STATUS_INVALID_PARAMETER;
-
-    LowIoContext = &RxContext->LowIoContext;
-    cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
-    pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
-
-    if (cbConnectName == 0 || !pwcConnectName)
-    {
-        Log(("VBOXSF: vbsfCreateConnection: Connection name / length is invalid!\n"));
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    __try
-    {
-        Log(("VBOXSF: vbsfCreateConnection: Name = %.*ls, Len = %d\n",
-             cbConnectName / sizeof(WCHAR), pwcConnectName, cbConnectName));
-
-        FileName.Buffer = pwcConnectName;
-        FileName.Length = (USHORT)cbConnectName;
-        FileName.MaximumLength = (USHORT)cbConnectName;
-
-        Handle = vbsfOpenConnectionHandle(&FileName, NULL);
-
-        if (Handle != INVALID_HANDLE_VALUE)
-        {
-            PWCHAR pwc;
-            ULONG i;
-
-            ZwClose(Handle);
-
-            /* Skip the "\Device\VBoxMiniRdr\;X:" of the string "\Device\VBoxMiniRdr\;X:\vboxsrv\sf" */
-            pwc = pwcConnectName;
-            for (i = 0; i < cbConnectName; i += sizeof(WCHAR))
-            {
-                if (*pwc == L':')
-                    break;
-                pwc++;
-            }
-
-            if (i >= sizeof(WCHAR) && i < cbConnectName)
-            {
-                pwc--; /* Go back to the drive letter, "X" for example. */
-
-                if (*pwc >= L'A' && *pwc <= L'Z') /* Are we in range? */
-                {
-                    uint32_t idx = *pwc - L'A'; /* Get the index based on the driver letter numbers (26). */
-
-                    if (idx >= RTL_NUMBER_OF(pDeviceExtension->cLocalConnections))
-                    {
-                        Log(("VBOXSF: vbsfCreateConnection: Index 0x%x is invalid!\n",
-                             idx));
-                        Status = STATUS_BAD_NETWORK_NAME;
-                    }
-                    else
-                    {
-                        ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
-                        fMutexAcquired = TRUE;
-
-                        if (pDeviceExtension->wszLocalConnectionName[idx] != NULL)
-                        {
-                            Log(("VBOXSF: vbsfCreateConnection: LocalConnectionName at index %d is NOT empty!\n",
-                                 idx));
-                        }
-
-                        pDeviceExtension->wszLocalConnectionName[idx] = (PUNICODE_STRING)vbsfAllocNonPagedMem(sizeof(UNICODE_STRING) + cbConnectName);
-
-                        if (!pDeviceExtension->wszLocalConnectionName[idx])
-                        {
-                            Log(("VBOXSF: vbsfCreateConnection: LocalConnectionName at index %d NOT allocated!\n",
-                                 idx));
-                            Status = STATUS_INSUFFICIENT_RESOURCES;
-                        }
-                        else
-                        {
-                            PUNICODE_STRING pRemoteName = pDeviceExtension->wszLocalConnectionName[idx];
-
-                            pRemoteName->Buffer = (PWSTR)(pRemoteName + 1);
-                            pRemoteName->Length = (USHORT)(cbConnectName - i - sizeof(WCHAR));
-                            pRemoteName->MaximumLength = pRemoteName->Length;
-                            RtlCopyMemory(&pRemoteName->Buffer[0], pwc+2, pRemoteName->Length);
-
-                            Log(("VBOXSF: vbsfCreateConnection: RemoteName %.*ls, Len = %d\n",
-                                 pRemoteName->Length / sizeof(WCHAR), pRemoteName->Buffer, pRemoteName->Length));
-
-                            pDeviceExtension->cLocalConnections[idx] = TRUE;
-                        }
-
-                        ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
-                        fMutexAcquired = FALSE;
-                    }
-                }
-            }
-            else
-            {
-                Log(("VBOXSF: vbsfCreateConnection: bad format\n"));
-                Status = STATUS_BAD_NETWORK_NAME;
-            }
-        }
-        else
-        {
-            Log(("VBOXSF: vbsfCreateConnection: connection was not found\n"));
-            Status = STATUS_BAD_NETWORK_NAME;
-        }
-    }
-    __except(EXCEPTION_EXECUTE_HANDLER)
-    {
-        Status = STATUS_INVALID_PARAMETER;
-    }
-
-    if (fMutexAcquired)
-    {
-        ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
-        fMutexAcquired = FALSE;
-    }
-
-    return Status;
-}
-
-NTSTATUS vbsfDeleteConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp)
-{
-    NTSTATUS Status;
-    UNICODE_STRING FileName;
-    HANDLE Handle;
-    PLOWIO_CONTEXT LowIoContext;
-    PWCHAR pwcConnectName;
-    ULONG cbConnectName;
-    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
-
-    BOOLEAN fMutexAcquired = FALSE;
-
-    Log(("VBOXSF: vbsfDeleteConnection\n"));
-
-    if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT))
-    {
-        Log(("VBOXSF: vbsfDeleteConnection: post to file system process\n"));
-        *PostToFsp = TRUE;
-        return STATUS_PENDING;
-    }
-
-    LowIoContext = &RxContext->LowIoContext;
-    pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
-    cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
-
-    pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
-    if (!pDeviceExtension)
-        return STATUS_INVALID_PARAMETER;
-
-    __try
-    {
-        Log(("VBOXSF: vbsfDeleteConnection: pwcConnectName = %.*ls\n",
-             cbConnectName / sizeof(WCHAR), pwcConnectName));
-
-        FileName.Buffer = pwcConnectName;
-        FileName.Length = (USHORT)cbConnectName;
-        FileName.MaximumLength = (USHORT)cbConnectName;
-
-        Handle = vbsfOpenConnectionHandle(&FileName, &Status);
-        if (Handle != INVALID_HANDLE_VALUE)
-        {
-            PFILE_OBJECT pFileObject;
-            Status = ObReferenceObjectByHandle(Handle, 0L, NULL, KernelMode, (PVOID *)&pFileObject, NULL);
-
-            Log(("VBOXSF: vbsfDeleteConnection: ObReferenceObjectByHandle Status 0x%08X\n",
-                 Status));
-
-            if (NT_SUCCESS(Status))
-            {
-                PFOBX Fobx = (PFOBX)pFileObject->FsContext2;
-                Log(("VBOXSF: vbsfDeleteConnection: Fobx %p\n", Fobx));
-
-                if (Fobx && NodeType(Fobx) == RDBSS_NTC_V_NETROOT)
-                {
-                    PV_NET_ROOT VNetRoot = (PV_NET_ROOT)Fobx;
-
-                    Status = RxFinalizeConnection(VNetRoot->NetRoot, VNetRoot, TRUE);
-                }
-                else
-                {
-                    Log(("VBOXSF: vbsfDeleteConnection: wrong FsContext2\n"));
-                    Status = STATUS_INVALID_DEVICE_REQUEST;
-                }
-
-                ObDereferenceObject(pFileObject);
-            }
-
-            ZwClose(Handle);
-
-            if (NT_SUCCESS(Status))
-            {
-                PWCHAR pwc;
-                ULONG i;
-
-                /* Skip the "\Device\VBoxMiniRdr\;X:" of the string "\Device\VBoxMiniRdr\;X:\vboxsrv\sf" */
-                pwc = pwcConnectName;
-                for (i = 0; i < cbConnectName; i += sizeof(WCHAR))
-                {
-                    if (*pwc == L':')
-                    {
-                        break;
-                    }
-                    pwc++;
-                }
-
-                if (i >= sizeof(WCHAR) && i < cbConnectName)
-                {
-                    pwc--;
-
-                    if (*pwc >= L'A' && *pwc <= L'Z')
-                    {
-                        uint32_t idx = *pwc - L'A';
-
-                        if (idx >= RTL_NUMBER_OF(pDeviceExtension->cLocalConnections))
-                        {
-                            Log(("VBOXSF: vbsfDeleteConnection: Index 0x%x is invalid!\n",
-                                 idx));
-                            Status = STATUS_BAD_NETWORK_NAME;
-                        }
-                        else
-                        {
-                            ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
-                            fMutexAcquired = TRUE;
-
-                            pDeviceExtension->cLocalConnections[idx] = FALSE;
-
-                            /* Free saved name */
-                            if (pDeviceExtension->wszLocalConnectionName[idx])
-                            {
-                                vbsfFreeNonPagedMem(pDeviceExtension->wszLocalConnectionName[idx]);
-                                pDeviceExtension->wszLocalConnectionName[idx] = NULL;
-                            }
-
-                            ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
-                            fMutexAcquired = FALSE;
-
-                            Log(("VBOXSF: vbsfDeleteConnection: deleted index 0x%x\n",
-                                 idx));
-                        }
-                    }
-                }
-                else
-                {
-                    Log(("VBOXSF: vbsfCreateConnection: bad format\n"));
-                    Status = STATUS_BAD_NETWORK_NAME;
-                }
-            }
-        }
-    }
-    __except(EXCEPTION_EXECUTE_HANDLER)
-    {
-        Status = STATUS_INVALID_PARAMETER;
-    }
-
-    if (fMutexAcquired)
-    {
-        ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
-        fMutexAcquired = FALSE;
-    }
-
-    Log(("VBOXSF: vbsfDeleteConnection: Status 0x%08X\n", Status));
-    return Status;
-}
-
-NTSTATUS VBoxMRxQueryEaInfo(IN OUT PRX_CONTEXT RxContext)
-{
-    RT_NOREF(RxContext);
-    Log(("VBOXSF: MRxQueryEaInfo: Ea buffer len remaining is %d\n", RxContext->Info.LengthRemaining));
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS VBoxMRxSetEaInfo(IN OUT PRX_CONTEXT RxContext)
-{
-    RT_NOREF(RxContext);
-    Log(("VBOXSF: MRxSetEaInfo\n"));
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS VBoxMRxFsCtl(IN OUT PRX_CONTEXT RxContext)
-{
-    RT_NOREF(RxContext);
-    Log(("VBOXSF: MRxFsCtl\n"));
-    return STATUS_INVALID_DEVICE_REQUEST;
-}
-
-NTSTATUS VBoxMRxNotifyChangeDirectory(IN OUT PRX_CONTEXT RxContext)
-{
-    RT_NOREF(RxContext);
-    Log(("VBOXSF: MRxNotifyChangeDirectory\n"));
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS vbsfQuerySdInfo(PVOID pvBuffer, ULONG cbBuffer, SECURITY_INFORMATION SecurityInformation, ULONG *pcbOut)
-{
-    /* What a public SMB share would return. */
-    static SID_IDENTIFIER_AUTHORITY sIA = SECURITY_NT_AUTHORITY;
-    #define SUB_AUTHORITY_COUNT 2
-    static const ULONG saSubAuthorityOwner[] = { SECURITY_NT_NON_UNIQUE, DOMAIN_USER_RID_GUEST   };
-    static const ULONG saSubAuthorityGroup[] = { SECURITY_NT_NON_UNIQUE, DOMAIN_GROUP_RID_GUESTS };
-
-    SECURITY_DESCRIPTOR_RELATIVE *pSD = (SECURITY_DESCRIPTOR_RELATIVE *)pvBuffer;
-    ULONG cbSD = 0; /* Size of returned security descriptor. */
-    ULONG cbAdd; /* How many bytes to add to the buffer for each component of the security descriptor. */
-
-    cbAdd = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
-    if (cbSD + cbAdd <= cbBuffer)
-    {
-        pSD->Revision = SECURITY_DESCRIPTOR_REVISION1;
-        pSD->Sbz1     = 0;
-        pSD->Control  = SE_SELF_RELATIVE;
-        pSD->Owner    = 0;
-        pSD->Group    = 0;
-        pSD->Sacl     = 0;
-        pSD->Dacl     = 0;
-    }
-    cbSD += cbAdd;
-
-    if (SecurityInformation & OWNER_SECURITY_INFORMATION)
-    {
-        cbAdd = RT_UOFFSETOF(SID, SubAuthority) + SUB_AUTHORITY_COUNT * sizeof(ULONG);
-        if (cbSD + cbAdd <= cbBuffer)
-        {
-            SID *pSID = (SID *)((uint8_t *)pSD + cbSD);
-            pSID->Revision            = 1;
-            pSID->SubAuthorityCount   = SUB_AUTHORITY_COUNT;
-            pSID->IdentifierAuthority = sIA;
-            memcpy(pSID->SubAuthority, saSubAuthorityOwner, SUB_AUTHORITY_COUNT * sizeof(ULONG));
-
-            pSD->Owner = cbSD;
-        }
-        cbSD += cbAdd;
-    }
-
-    if (SecurityInformation & GROUP_SECURITY_INFORMATION)
-    {
-        cbAdd = RT_UOFFSETOF(SID, SubAuthority) + SUB_AUTHORITY_COUNT * sizeof(ULONG);
-        if (cbSD + cbAdd <= cbBuffer)
-        {
-            SID *pSID = (SID *)((uint8_t *)pSD + cbSD);
-            pSID->Revision            = 1;
-            pSID->SubAuthorityCount   = SUB_AUTHORITY_COUNT;
-            pSID->IdentifierAuthority = sIA;
-            memcpy(pSID->SubAuthority, saSubAuthorityGroup, SUB_AUTHORITY_COUNT * sizeof(ULONG));
-
-            pSD->Group = cbSD;
-        }
-        cbSD += cbAdd;
-    }
-
-    #undef SUB_AUTHORITY_COUNT
-
-    *pcbOut = cbSD;
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS VBoxMRxQuerySdInfo(IN OUT PRX_CONTEXT RxContext)
-{
-    NTSTATUS Status;
-
-    PVOID pvBuffer = RxContext->Info.Buffer;
-    ULONG cbBuffer = RxContext->Info.LengthRemaining;
-    SECURITY_INFORMATION SecurityInformation = RxContext->QuerySecurity.SecurityInformation;
-
-    ULONG cbSD = 0;
-
-    Log(("VBOXSF: MRxQuerySdInfo: Buffer %p, Length %d, SecurityInformation 0x%x\n",
-         pvBuffer, cbBuffer, SecurityInformation));
-
-    Status = vbsfQuerySdInfo(pvBuffer, cbBuffer, SecurityInformation, &cbSD);
-    if (NT_SUCCESS(Status))
-    {
-        RxContext->InformationToReturn = cbSD;
-        if (RxContext->InformationToReturn > cbBuffer)
-        {
-            Status = STATUS_BUFFER_OVERFLOW;
-        }
-    }
-
-    Log(("VBOXSF: MRxQuerySdInfo: Status 0x%08X, InformationToReturn %d\n",
-         Status, RxContext->InformationToReturn));
-    return Status;
-}
-
-NTSTATUS VBoxMRxSetSdInfo(IN OUT struct _RX_CONTEXT * RxContext)
-{
-    RT_NOREF(RxContext);
-    Log(("VBOXSF: MRxSetSdInfo\n"));
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-/*
- * WML stubs which are referenced by rdbsslib.
- */
-NTSTATUS WmlTinySystemControl(IN OUT PVOID pWmiLibInfo, IN PVOID pDevObj, IN PVOID pIrp)
-{
-    RT_NOREF(pWmiLibInfo, pDevObj, pIrp);
-    return STATUS_WMI_GUID_NOT_FOUND;
-}
-
-ULONG WmlTrace(IN ULONG ulType, IN PVOID pTraceUuid, IN ULONG64 ullLogger, ...)
-{
-    RT_NOREF(ulType, pTraceUuid, ullLogger);
-    return STATUS_SUCCESS;
-}
-
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.cpp	(revision 78302)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.cpp	(revision 78302)
@@ -0,0 +1,1691 @@
+/* $Id$ */
+/** @file
+ * VirtualBox Windows Guest Shared Folders - File System Driver initialization and generic routines
+ */
+
+/*
+ * Copyright (C) 2012-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "vbsf.h"
+
+
+/**
+ * The current state of the driver.
+ */
+typedef enum _MRX_VBOX_STATE_
+{
+    MRX_VBOX_STARTABLE,
+    MRX_VBOX_START_IN_PROGRESS,
+    MRX_VBOX_STARTED
+} MRX_VBOX_STATE, *PMRX_VBOX_STATE;
+
+static MRX_VBOX_STATE VBoxMRxState = MRX_VBOX_STARTABLE;
+
+/**
+ * The VBoxSF dispatch table.
+ */
+static struct _MINIRDR_DISPATCH VBoxMRxDispatch;
+
+/**
+ * The VBoxSF device object.
+ */
+PRDBSS_DEVICE_OBJECT VBoxMRxDeviceObject;
+
+uint64_t g_abPadding111[256] = {0};
+/** The shared folder service client structure. */
+VBGLSFCLIENT g_SfClient;
+/** VMMDEV_HVF_XXX (set during init). */
+uint32_t     g_fHostFeatures = 0;
+/** Last valid shared folders function number. */
+uint32_t     g_uSfLastFunction = SHFL_FN_SET_FILE_SIZE;
+/** Shared folders features (SHFL_FEATURE_XXX). */
+uint64_t     g_fSfFeatures = 0;
+uint64_t g_abPadding222[256] = {0};
+
+
+
+static NTSTATUS VBoxMRxFsdDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    NTSTATUS Status;
+#ifdef LOG_ENABLED
+    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
+    Log(("VBOXSF: MRxFsdDispatch: major %d, minor %d: %s\n",
+         IrpSp->MajorFunction, IrpSp->MinorFunction, MajorFunctionString(IrpSp->MajorFunction, IrpSp->MinorFunction)));
+#endif
+
+    if (DeviceObject != (PDEVICE_OBJECT)VBoxMRxDeviceObject)
+    {
+        Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
+        Irp->IoStatus.Information = 0;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        Log(("VBOXSF: MRxFsdDispatch: Invalid device request detected %p %p\n",
+             DeviceObject, (PDEVICE_OBJECT)VBoxMRxDeviceObject));
+
+        return STATUS_INVALID_DEVICE_REQUEST;
+    }
+
+    Status = RxFsdDispatch((PRDBSS_DEVICE_OBJECT)VBoxMRxDeviceObject, Irp);
+    Log(("VBOXSF: MRxFsdDispatch: Returned 0x%X\n", Status));
+    return Status;
+}
+
+static void VBoxMRxUnload(IN PDRIVER_OBJECT DriverObject)
+{
+    NTSTATUS Status;
+    UNICODE_STRING UserModeDeviceName;
+
+    Log(("VBOXSF: MRxUnload\n"));
+
+    if (VBoxMRxDeviceObject)
+    {
+        PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
+        pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)VBoxMRxDeviceObject + sizeof(RDBSS_DEVICE_OBJECT));
+    }
+
+    if (VBoxMRxDeviceObject)
+    {
+        PRX_CONTEXT RxContext;
+        RxContext = RxCreateRxContext(NULL, VBoxMRxDeviceObject, RX_CONTEXT_FLAG_IN_FSP);
+
+        if (RxContext != NULL)
+        {
+            Status = RxStopMinirdr(RxContext, &RxContext->PostRequest);
+
+            if (Status == STATUS_SUCCESS)
+            {
+                MRX_VBOX_STATE State;
+
+                State = (MRX_VBOX_STATE)InterlockedCompareExchange((LONG *)&VBoxMRxState, MRX_VBOX_STARTABLE, MRX_VBOX_STARTED);
+
+                if (State != MRX_VBOX_STARTABLE)
+                    Status = STATUS_REDIRECTOR_STARTED;
+            }
+
+            RxDereferenceAndDeleteRxContext(RxContext);
+        }
+        else
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+
+        RxUnregisterMinirdr(VBoxMRxDeviceObject);
+    }
+
+    RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
+    Status = IoDeleteSymbolicLink(&UserModeDeviceName);
+    if (Status != STATUS_SUCCESS)
+        Log(("VBOXSF: MRxUnload: IoDeleteSymbolicLink Status 0x%08X\n", Status));
+
+    RxUnload(DriverObject);
+
+    VbglR0SfDisconnect(&g_SfClient);
+    VbglR0SfTerm();
+
+    Log(("VBOXSF: MRxUnload: VBoxSF.sys driver object %p unloaded\n", DriverObject));
+}
+
+static void vbsfInitMRxDispatch(void)
+{
+    Log(("VBOXSF: vbsfInitMRxDispatch: Called.\n"));
+
+    ZeroAndInitializeNodeType(&VBoxMRxDispatch, RDBSS_NTC_MINIRDR_DISPATCH, sizeof(MINIRDR_DISPATCH));
+
+    VBoxMRxDispatch.MRxFlags = (RDBSS_MANAGE_NET_ROOT_EXTENSION | RDBSS_MANAGE_FOBX_EXTENSION);
+
+    VBoxMRxDispatch.MRxSrvCallSize = 0;
+    VBoxMRxDispatch.MRxNetRootSize = sizeof(MRX_VBOX_NETROOT_EXTENSION);
+    VBoxMRxDispatch.MRxVNetRootSize = 0;
+    VBoxMRxDispatch.MRxFcbSize = 0;
+    VBoxMRxDispatch.MRxSrvOpenSize = 0;
+    VBoxMRxDispatch.MRxFobxSize = sizeof(MRX_VBOX_FOBX);
+
+    VBoxMRxDispatch.MRxStart = VBoxMRxStart;
+    VBoxMRxDispatch.MRxStop = VBoxMRxStop;
+
+    VBoxMRxDispatch.MRxCreate = VBoxMRxCreate;
+    VBoxMRxDispatch.MRxCollapseOpen = VBoxMRxCollapseOpen;
+    VBoxMRxDispatch.MRxShouldTryToCollapseThisOpen = VBoxMRxShouldTryToCollapseThisOpen;
+    VBoxMRxDispatch.MRxFlush = VBoxMRxFlush;
+    VBoxMRxDispatch.MRxTruncate = VBoxMRxTruncate;
+    VBoxMRxDispatch.MRxCleanupFobx = VBoxMRxCleanupFobx;
+    VBoxMRxDispatch.MRxCloseSrvOpen = VBoxMRxCloseSrvOpen;
+    VBoxMRxDispatch.MRxDeallocateForFcb = VBoxMRxDeallocateForFcb;
+    VBoxMRxDispatch.MRxDeallocateForFobx = VBoxMRxDeallocateForFobx;
+    VBoxMRxDispatch.MRxForceClosed = VBoxMRxForceClosed;
+
+    VBoxMRxDispatch.MRxQueryDirectory = VBoxMRxQueryDirectory;
+    VBoxMRxDispatch.MRxQueryFileInfo = VBoxMRxQueryFileInfo;
+    VBoxMRxDispatch.MRxSetFileInfo = VBoxMRxSetFileInfo;
+    VBoxMRxDispatch.MRxSetFileInfoAtCleanup = VBoxMRxSetFileInfoAtCleanup;
+    VBoxMRxDispatch.MRxQueryEaInfo = VBoxMRxQueryEaInfo;
+    VBoxMRxDispatch.MRxSetEaInfo = VBoxMRxSetEaInfo;
+    VBoxMRxDispatch.MRxQuerySdInfo = VBoxMRxQuerySdInfo;
+    VBoxMRxDispatch.MRxSetSdInfo = VBoxMRxSetSdInfo;
+    VBoxMRxDispatch.MRxQueryVolumeInfo = VBoxMRxQueryVolumeInfo;
+
+    VBoxMRxDispatch.MRxComputeNewBufferingState = VBoxMRxComputeNewBufferingState;
+
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_READ] = VBoxMRxRead;
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_WRITE] = VBoxMRxWrite;
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_SHAREDLOCK] = VBoxMRxLocks;
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_EXCLUSIVELOCK] = VBoxMRxLocks;
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK] = VBoxMRxLocks;
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK_MULTIPLE] = VBoxMRxLocks;
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_FSCTL] = VBoxMRxFsCtl;
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_IOCTL] = VBoxMRxIoCtl;
+    VBoxMRxDispatch.MRxLowIOSubmit[LOWIO_OP_NOTIFY_CHANGE_DIRECTORY] = VBoxMRxNotifyChangeDirectory;
+
+    VBoxMRxDispatch.MRxExtendForCache = VBoxMRxExtendStub;
+    VBoxMRxDispatch.MRxExtendForNonCache = VBoxMRxExtendStub;
+    VBoxMRxDispatch.MRxCompleteBufferingStateChangeRequest = VBoxMRxCompleteBufferingStateChangeRequest;
+
+    VBoxMRxDispatch.MRxCreateVNetRoot = VBoxMRxCreateVNetRoot;
+    VBoxMRxDispatch.MRxFinalizeVNetRoot = VBoxMRxFinalizeVNetRoot;
+    VBoxMRxDispatch.MRxFinalizeNetRoot = VBoxMRxFinalizeNetRoot;
+    VBoxMRxDispatch.MRxUpdateNetRootState = VBoxMRxUpdateNetRootState;
+    VBoxMRxDispatch.MRxExtractNetRootName = VBoxMRxExtractNetRootName;
+
+    VBoxMRxDispatch.MRxCreateSrvCall = VBoxMRxCreateSrvCall;
+    VBoxMRxDispatch.MRxSrvCallWinnerNotify = VBoxMRxSrvCallWinnerNotify;
+    VBoxMRxDispatch.MRxFinalizeSrvCall = VBoxMRxFinalizeSrvCall;
+
+    VBoxMRxDispatch.MRxDevFcbXXXControlFile = VBoxMRxDevFcbXXXControlFile;
+
+    Log(("VBOXSF: vbsfInitMRxDispatch: Success.\n"));
+    return;
+}
+
+static BOOL vboxIsPrefixOK (const WCHAR *FilePathName, ULONG PathNameLength)
+{
+    BOOL PrefixOK;
+
+    /* The FilePathName here looks like: \vboxsrv\... */
+    if (PathNameLength >= 8 * sizeof (WCHAR)) /* Number of bytes in '\vboxsrv' unicode string. */
+    {
+        PrefixOK =  (FilePathName[0] == L'\\');
+        PrefixOK &= (FilePathName[1] == L'V') || (FilePathName[1] == L'v');
+        PrefixOK &= (FilePathName[2] == L'B') || (FilePathName[2] == L'b');
+        PrefixOK &= (FilePathName[3] == L'O') || (FilePathName[3] == L'o');
+        PrefixOK &= (FilePathName[4] == L'X') || (FilePathName[4] == L'x');
+        PrefixOK &= (FilePathName[5] == L'S') || (FilePathName[5] == L's');
+        /* Both vboxsvr & vboxsrv are now accepted */
+        if ((FilePathName[6] == L'V') || (FilePathName[6] == L'v'))
+        {
+            PrefixOK &= (FilePathName[6] == L'V') || (FilePathName[6] == L'v');
+            PrefixOK &= (FilePathName[7] == L'R') || (FilePathName[7] == L'r');
+        }
+        else
+        {
+            PrefixOK &= (FilePathName[6] == L'R') || (FilePathName[6] == L'r');
+            PrefixOK &= (FilePathName[7] == L'V') || (FilePathName[7] == L'v');
+        }
+        if (PathNameLength > 8 * sizeof (WCHAR))
+        {
+            /* There is something after '\vboxsrv'. */
+            PrefixOK &= (FilePathName[8] == L'\\') || (FilePathName[8] == 0);
+        }
+    }
+    else
+        PrefixOK = FALSE;
+
+    return PrefixOK;
+}
+
+static NTSTATUS VBoxMRXDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    QUERY_PATH_REQUEST *pReq = NULL;
+    QUERY_PATH_REQUEST_EX *pReqEx = NULL;
+    QUERY_PATH_RESPONSE *pResp = NULL;
+
+    BOOL PrefixOK = FALSE;
+
+    PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
+
+    /* Make a local copy, it will be needed after the Irp completion. */
+    ULONG IoControlCode = pStack->Parameters.DeviceIoControl.IoControlCode;
+
+    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)pDevObj + sizeof(RDBSS_DEVICE_OBJECT));
+
+    Log(("VBOXSF: MRXDeviceControl: pDevObj %p, pDeviceExtension %p, code %x\n",
+         pDevObj, pDevObj->DeviceExtension, IoControlCode));
+
+    switch (IoControlCode)
+    {
+        case IOCTL_REDIR_QUERY_PATH_EX: /* Vista */
+        case IOCTL_REDIR_QUERY_PATH:    /* XP and earlier */
+        {
+            /* This IOCTL is intercepted for 2 reasons:
+             * 1) Claim the vboxsvr and vboxsrv prefixes. All name-based operations for them
+             *    will be routed to the VBox provider automatically without any prefix resolution
+             *    since the prefix is already in the prefix cache.
+             * 2) Reject other prefixes immediately to speed up the UNC path resolution a bit,
+             *    because RDBSS will not be involved then.
+             */
+
+            const WCHAR *FilePathName = NULL;
+            ULONG PathNameLength = 0;
+
+            if (pIrp->RequestorMode != KernelMode)
+            {
+                /* MSDN: Network redirectors should only honor kernel-mode senders of this IOCTL, by verifying
+                 * that RequestorMode member of the IRP structure is KernelMode.
+                 */
+                Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH(_EX): not kernel mode!!!\n",
+                      pStack->Parameters.DeviceIoControl.InputBufferLength));
+                /* Continue to RDBSS. */
+                break;
+            }
+
+            if (IoControlCode == IOCTL_REDIR_QUERY_PATH)
+            {
+                Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH: Called (pid %x).\n", IoGetCurrentProcess()));
+
+                if (pStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(QUERY_PATH_REQUEST))
+                {
+                    Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH: short input buffer %d.\n",
+                          pStack->Parameters.DeviceIoControl.InputBufferLength));
+                    /* Continue to RDBSS. */
+                    break;
+                }
+
+                pReq = (QUERY_PATH_REQUEST *)pStack->Parameters.DeviceIoControl.Type3InputBuffer;
+
+                Log(("VBOXSF: MRxDeviceControl: PathNameLength = %d.\n", pReq->PathNameLength));
+                Log(("VBOXSF: MRxDeviceControl: SecurityContext = %p.\n", pReq->SecurityContext));
+                Log(("VBOXSF: MRxDeviceControl: FilePathName = %.*ls.\n", pReq->PathNameLength / sizeof (WCHAR), pReq->FilePathName));
+
+                FilePathName = pReq->FilePathName;
+                PathNameLength = pReq->PathNameLength;
+            }
+            else
+            {
+                Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH_EX: Called.\n"));
+
+                if (pStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(QUERY_PATH_REQUEST_EX))
+                {
+                    Log(("VBOXSF: MRxDeviceControl: IOCTL_REDIR_QUERY_PATH_EX: short input buffer %d.\n",
+                          pStack->Parameters.DeviceIoControl.InputBufferLength));
+                    /* Continue to RDBSS. */
+                    break;
+                }
+
+                pReqEx = (QUERY_PATH_REQUEST_EX *)pStack->Parameters.DeviceIoControl.Type3InputBuffer;
+
+                Log(("VBOXSF: MRxDeviceControl: pSecurityContext = %p.\n", pReqEx->pSecurityContext));
+                Log(("VBOXSF: MRxDeviceControl: EaLength = %d.\n", pReqEx->EaLength));
+                Log(("VBOXSF: MRxDeviceControl: pEaBuffer = %p.\n", pReqEx->pEaBuffer));
+                Log(("VBOXSF: MRxDeviceControl: PathNameLength = %d.\n", pReqEx->PathName.Length));
+                Log(("VBOXSF: MRxDeviceControl: FilePathName = %.*ls.\n", pReqEx->PathName.Length / sizeof (WCHAR), pReqEx->PathName.Buffer));
+
+                FilePathName = pReqEx->PathName.Buffer;
+                PathNameLength = pReqEx->PathName.Length;
+            }
+
+            pResp = (QUERY_PATH_RESPONSE *)pIrp->UserBuffer;
+
+            PrefixOK = vboxIsPrefixOK (FilePathName, PathNameLength);
+            Log(("VBOXSF: MRxDeviceControl PrefixOK %d\n", PrefixOK));
+
+            if (!PrefixOK)
+            {
+                /* Immediately fail the IOCTL with STATUS_BAD_NETWORK_NAME as recommended by MSDN.
+                 * No need to involve RDBSS.
+                 */
+                Status = STATUS_BAD_NETWORK_NAME;
+
+                pIrp->IoStatus.Status = Status;
+                pIrp->IoStatus.Information = 0;
+
+                IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+
+                Log(("VBOXSF: MRxDeviceControl: returned STATUS_BAD_NETWORK_NAME\n"));
+                return Status;
+            }
+
+            Log(("VBOXSF: MRxDeviceControl pResp %p verifying the path.\n", pResp));
+            if (pResp)
+            {
+                /* Always claim entire \vboxsrv prefix. The LengthAccepted initially is equal to entire path.
+                 * Here it is assigned to the length of \vboxsrv prefix.
+                 */
+                pResp->LengthAccepted = 8 * sizeof (WCHAR);
+
+                Status = STATUS_SUCCESS;
+
+                pIrp->IoStatus.Status = Status;
+                pIrp->IoStatus.Information = 0;
+
+                IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+
+                Log(("VBOXSF: MRxDeviceControl: claiming the path.\n"));
+                return Status;
+            }
+
+            /* No pResp pointer, should not happen. Just a precaution. */
+            Status = STATUS_INVALID_PARAMETER;
+
+            pIrp->IoStatus.Status = Status;
+            pIrp->IoStatus.Information = 0;
+
+            IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+
+            Log(("VBOXSF: MRxDeviceControl: returned STATUS_INVALID_PARAMETER\n"));
+            return Status;
+        }
+
+        default:
+            break;
+    }
+
+    /* Pass the IOCTL to RDBSS. */
+    if (pDeviceExtension && pDeviceExtension->pfnRDBSSDeviceControl)
+    {
+        Log(("VBOXSF: MRxDeviceControl calling RDBSS %p\n", pDeviceExtension->pfnRDBSSDeviceControl));
+        Status = pDeviceExtension->pfnRDBSSDeviceControl (pDevObj, pIrp);
+        Log(("VBOXSF: MRxDeviceControl RDBSS status 0x%08X\n", Status));
+    }
+    else
+    {
+        /* No RDBSS, should not happen. Just a precaution. */
+        Status = STATUS_NOT_IMPLEMENTED;
+
+        pIrp->IoStatus.Status = Status;
+        pIrp->IoStatus.Information = 0;
+
+        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+
+        Log(("VBOXSF: MRxDeviceControl: returned STATUS_NOT_IMPLEMENTED\n"));
+    }
+
+    return Status;
+}
+
+/**
+ * Intercepts IRP_MJ_CREATE to workaround a RDBSS quirk.
+ *
+ * Our RDBSS library will return STATUS_OBJECT_NAME_INVALID when FILE_NON_DIRECTORY_FILE
+ * is set and the path ends with a slash.  NTFS and FAT will fail with
+ * STATUS_OBJECT_NAME_NOT_FOUND if the final component does not exist or isn't a directory,
+ * STATUS_OBJECT_PATH_NOT_FOUND if some path component doesn't exist or isn't a directory,
+ * or STATUS_ACCESS_DENIED if the final component is a directory.
+ *
+ * So, our HACK is to drop the trailing slash and set an unused flag in the ShareAccess
+ * parameter to tell vbsfProcessCreate about it.
+ *
+ */
+static NTSTATUS VBoxHookMjCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
+{
+    PMRX_VBOX_DEVICE_EXTENSION  pDevExt  = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)pDevObj + sizeof(RDBSS_DEVICE_OBJECT));
+    PIO_STACK_LOCATION          pStack   = IoGetCurrentIrpStackLocation(pIrp);
+    PFILE_OBJECT                pFileObj = pStack->FileObject;
+    NTSTATUS                    rcNt;
+
+    Log(("VBOXSF: VBoxHookMjCreate: pDevObj %p, pDevExt %p, pFileObj %p, options %#x, attr %#x, share %#x, ealength %#x, secctx %p\n",
+         pDevObj, pDevObj->DeviceExtension, pFileObj, pStack->Parameters.Create.Options, pStack->Parameters.Create.FileAttributes,
+         pStack->Parameters.Create.ShareAccess, pStack->Parameters.Create.EaLength, pStack->Parameters.Create.SecurityContext));
+    if (pFileObj)
+        Log(("VBOXSF: VBoxHookMjCreate: FileName=%.*ls\n", pFileObj->FileName.Length / sizeof(WCHAR), pFileObj->FileName.Buffer));
+
+    /*
+     * Check if we need to apply the hack.  If we do, we grab a reference to
+     * the file object to be absolutely sure it's around for the cleanup work.
+     */
+    AssertMsg(!(pStack->Parameters.Create.ShareAccess & VBOX_MJ_CREATE_SLASH_HACK), ("%#x\n", pStack->Parameters.Create.ShareAccess));
+    if (   (pStack->Parameters.Create.Options & (FILE_NON_DIRECTORY_FILE | FILE_DIRECTORY_FILE)) == FILE_NON_DIRECTORY_FILE
+        && pFileObj
+        && pFileObj->FileName.Length > 18
+        && pFileObj->FileName.Buffer
+        && pFileObj->FileName.Buffer[pFileObj->FileName.Length / sizeof(WCHAR) - 1] == '\\'
+        && pFileObj->FileName.Buffer[pFileObj->FileName.Length / sizeof(WCHAR) - 2] != '\\')
+    {
+        NTSTATUS rcNtRef = ObReferenceObjectByPointer(pFileObj, (ACCESS_MASK)0, *IoFileObjectType, KernelMode);
+        pFileObj->FileName.Length -= 2;
+        pStack->Parameters.Create.ShareAccess |= VBOX_MJ_CREATE_SLASH_HACK; /* secret flag for vbsfProcessCreate */
+
+        rcNt = pDevExt->pfnRDBSSCreate(pDevObj, pIrp);
+
+        if (rcNt != STATUS_PENDING)
+            pStack->Parameters.Create.ShareAccess &= ~VBOX_MJ_CREATE_SLASH_HACK;
+        if (NT_SUCCESS(rcNtRef))
+        {
+            pFileObj->FileName.Length += 2;
+            ObDereferenceObject(pFileObj);
+        }
+
+        Log(("VBOXSF: VBoxHookMjCreate: returns %#x (hacked; rcNtRef=%#x)\n", rcNt, rcNtRef));
+    }
+    /*
+     * No hack needed.
+     */
+    else
+    {
+        rcNt = pDevExt->pfnRDBSSCreate(pDevObj, pIrp);
+        Log(("VBOXSF: VBoxHookMjCreate: returns %#x\n", rcNt));
+    }
+    return rcNt;
+}
+
+NTSTATUS DriverEntry(IN PDRIVER_OBJECT  DriverObject,
+                     IN PUNICODE_STRING RegistryPath)
+{
+    NTSTATUS Status;
+    UNICODE_STRING VBoxMRxName;
+    UNICODE_STRING UserModeDeviceName;
+    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = NULL;
+    ULONG i;
+    int vrc;
+
+    Log(("VBOXSF: DriverEntry: Driver object %p\n", DriverObject));
+
+    if (!DriverObject)
+    {
+        Log(("VBOXSF: DriverEntry: driver object is NULL.\n"));
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    /* Initialize VBox subsystem. */
+    vrc = VbglR0SfInit();
+    if (RT_FAILURE(vrc))
+    {
+        Log(("VBOXSF: DriverEntry: ERROR while initializing VBox subsystem (%Rrc)!\n", vrc));
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    /* Connect the HGCM client */
+    vrc = VbglR0SfConnect(&g_SfClient);
+    if (RT_FAILURE(vrc))
+    {
+        Log(("VBOXSF: DriverEntry: ERROR while connecting to host (%Rrc)!\n",
+             vrc));
+        VbglR0SfTerm();
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    vrc = VbglR0QueryHostFeatures(&g_fHostFeatures);
+    if (RT_FAILURE(vrc))
+    {
+        LogRel(("vboxsf: VbglR0QueryHostFeatures failed: vrc=%Rrc (ignored)\n", vrc));
+        g_fHostFeatures = 0;
+    }
+    VbglR0SfHostReqQueryFeaturesSimple(&g_fSfFeatures, &g_uSfLastFunction);
+    LogRel(("VBoxSF: g_fHostFeatures=%#x g_fSfFeatures=%#RX64 g_uSfLastFunction=%u\n",
+            g_fHostFeatures, g_fSfFeatures, g_uSfLastFunction));
+
+    /* Init the driver object. */
+    DriverObject->DriverUnload = VBoxMRxUnload;
+    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
+    {
+        DriverObject->MajorFunction[i] = (PDRIVER_DISPATCH)VBoxMRxFsdDispatch;
+    }
+
+    /* Forward to RDBSS. */
+    Status = RxDriverEntry(DriverObject, RegistryPath);
+    if (Status != STATUS_SUCCESS)
+    {
+        Log(("VBOXSF: DriverEntry: RxDriverEntry failed: 0x%08X\n", Status));
+        goto failure;
+    }
+
+    __try
+    {
+        Log(("VBOXSF: DriverEntry: RxRegisterMinirdr: calling VBoxMRxDeviceObject %p\n",
+             VBoxMRxDeviceObject));
+
+        RtlInitUnicodeString(&VBoxMRxName, DD_MRX_VBOX_FS_DEVICE_NAME_U);
+
+        /* Don use RX_REGISTERMINI_FLAG_DONT_PROVIDE_UNCS or else
+         * UNC mappings don't work (including Windows explorer browsing).
+         */
+        Status = RxRegisterMinirdr(&VBoxMRxDeviceObject,
+                                   DriverObject,
+                                   &VBoxMRxDispatch,
+                                   RX_REGISTERMINI_FLAG_DONT_PROVIDE_MAILSLOTS,
+                                   &VBoxMRxName,
+                                   sizeof(MRX_VBOX_DEVICE_EXTENSION),
+                                   FILE_DEVICE_NETWORK_FILE_SYSTEM,
+                                   FILE_REMOTE_DEVICE);
+
+        Log(("VBOXSF: DriverEntry: RxRegisterMinirdr: returned 0x%08X VBoxMRxDeviceObject %p\n",
+             Status, VBoxMRxDeviceObject));
+
+        if (Status!=STATUS_SUCCESS)
+        {
+            Log(("VBOXSF: DriverEntry: RxRegisterMinirdr failed: 0x%08X\n", Status ));
+            try_return((void)Status);
+        }
+
+        /* Init the device extension.
+         * NOTE: the device extension actually points to fields
+         * in the RDBSS_DEVICE_OBJECT. Our space is past the end
+         * of this struct!!
+         */
+        pDeviceExtension = (PMRX_VBOX_DEVICE_EXTENSION)((PBYTE)VBoxMRxDeviceObject + sizeof(RDBSS_DEVICE_OBJECT));
+
+        pDeviceExtension->pDeviceObject = VBoxMRxDeviceObject;
+
+        for (i = 0; i < RT_ELEMENTS(pDeviceExtension->cLocalConnections); i++)
+        {
+            pDeviceExtension->cLocalConnections[i] = FALSE;
+        }
+
+        /* Mutex for synchronizining our connection list */
+        ExInitializeFastMutex(&pDeviceExtension->mtxLocalCon);
+
+        /* The device object has been created. Need to setup a symbolic
+         * link so that the device may be accessed from a Win32 user mode
+         * application.
+         */
+
+        RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
+        Log(("VBOXSF: DriverEntry: Calling IoCreateSymbolicLink\n"));
+        Status = IoCreateSymbolicLink(&UserModeDeviceName, &VBoxMRxName);
+        if (Status != STATUS_SUCCESS)
+        {
+            Log(("VBOXSF: DriverEntry: IoCreateSymbolicLink: 0x%08X\n",
+                 Status));
+            try_return((void)Status);
+        }
+        Log(("VBOXSF: DriverEntry: Symbolic link created.\n"));
+
+        /*
+         * Build the dispatch tables for the minirdr
+         */
+        vbsfInitMRxDispatch();
+
+    try_exit:
+         ;
+    }
+    __finally
+    {
+        ;
+    }
+
+    if (Status != STATUS_SUCCESS)
+    {
+        Log(("VBOXSF: DriverEntry: VBoxSF.sys failed to start with Status = 0x%08X\n",
+             Status));
+        goto failure;
+    }
+
+    AssertPtr(pDeviceExtension);
+    pDeviceExtension->hgcmClient = g_SfClient;
+
+    /* The redirector driver must intercept the IOCTL to avoid VBOXSVR name resolution
+     * by other redirectors. These additional name resolutions cause long delays.
+     */
+    Log(("VBOXSF: DriverEntry: VBoxMRxDeviceObject = %p, rdbss %p, devext %p\n",
+         VBoxMRxDeviceObject, DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL], pDeviceExtension));
+    pDeviceExtension->pfnRDBSSDeviceControl = DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL];
+    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxMRXDeviceControl;
+
+    /* Intercept IRP_MJ_CREATE to fix incorrect (wrt NTFS, FAT, ++) return
+     * codes for NtOpenFile("r:\\asdf\\", FILE_NON_DIRECTORY_FILE).
+     */
+    pDeviceExtension->pfnRDBSSCreate = DriverObject->MajorFunction[IRP_MJ_CREATE];
+    DriverObject->MajorFunction[IRP_MJ_CREATE] = VBoxHookMjCreate;
+
+
+    /** @todo start the redirector here RxStartMiniRdr. */
+
+    Log(("VBOXSF: DriverEntry: Init successful!\n"));
+    return STATUS_SUCCESS;
+
+failure:
+
+    Log(("VBOXSF: DriverEntry: Failure! Status = 0x%08X\n", Status));
+
+    VbglR0SfDisconnect(&g_SfClient);
+    VbglR0SfTerm();
+
+    if (VBoxMRxDeviceObject)
+    {
+        RxUnregisterMinirdr(VBoxMRxDeviceObject);
+        VBoxMRxDeviceObject = NULL;
+    }
+
+    return Status;
+}
+
+NTSTATUS VBoxMRxStart(PRX_CONTEXT RxContext, IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject)
+{
+    NTSTATUS Status;
+    MRX_VBOX_STATE CurrentState;
+    RT_NOREF(RxContext, RxDeviceObject);
+
+    Log(("VBOXSF: MRxStart\n"));
+
+    CurrentState = (MRX_VBOX_STATE)InterlockedCompareExchange((PLONG)&VBoxMRxState, MRX_VBOX_STARTED, MRX_VBOX_START_IN_PROGRESS);
+
+    if (CurrentState == MRX_VBOX_START_IN_PROGRESS)
+    {
+        Log(("VBOXSF: MRxStart: Start in progress -> started\n"));
+        Status = STATUS_SUCCESS;
+    }
+    else if (VBoxMRxState == MRX_VBOX_STARTED)
+    {
+        Log(("VBOXSF: MRxStart: Already started\n"));
+        Status = STATUS_REDIRECTOR_STARTED;
+    }
+    else
+    {
+        Log(("VBOXSF: MRxStart: Bad state! VBoxMRxState = %d\n", VBoxMRxState));
+        Status = STATUS_UNSUCCESSFUL;
+    }
+
+    return Status;
+}
+
+NTSTATUS VBoxMRxStop(PRX_CONTEXT RxContext, IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject)
+{
+    RT_NOREF(RxContext, RxDeviceObject);
+    Log(("VBOXSF: MRxStop\n"));
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS VBoxMRxIoCtl(IN OUT PRX_CONTEXT RxContext)
+{
+    RT_NOREF(RxContext);
+    Log(("VBOXSF: MRxIoCtl: IoControlCode = 0x%08X\n", RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode));
+    return STATUS_INVALID_DEVICE_REQUEST;
+}
+
+NTSYSAPI NTSTATUS NTAPI ZwSetSecurityObject(IN HANDLE Handle,
+                                            IN SECURITY_INFORMATION SecurityInformation,
+                                            IN PSECURITY_DESCRIPTOR SecurityDescriptor);
+
+NTSTATUS VBoxMRxDevFcbXXXControlFile(IN OUT PRX_CONTEXT RxContext)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    RxCaptureFobx;
+    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
+    PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
+
+    Log(("VBOXSF: MRxDevFcbXXXControlFile: MajorFunction = 0x%02X\n",
+         RxContext->MajorFunction));
+
+    switch (RxContext->MajorFunction)
+    {
+        case IRP_MJ_FILE_SYSTEM_CONTROL:
+        {
+            Log(("VBOXSF: MRxDevFcbXXXControlFile: IRP_MN_USER_FS_REQUEST: 0x%08X\n",
+                 LowIoContext->ParamsFor.FsCtl.MinorFunction));
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+            break;
+        }
+
+        case IRP_MJ_DEVICE_CONTROL:
+        {
+            Log(("VBOXSF: MRxDevFcbXXXControlFile: IRP_MJ_DEVICE_CONTROL: InputBuffer %p/%d, OutputBuffer %p/%d\n",
+                 LowIoContext->ParamsFor.IoCtl.pInputBuffer,
+                 LowIoContext->ParamsFor.IoCtl.InputBufferLength,
+                 LowIoContext->ParamsFor.IoCtl.pOutputBuffer,
+                 LowIoContext->ParamsFor.IoCtl.OutputBufferLength));
+
+            switch (LowIoContext->ParamsFor.IoCtl.IoControlCode)
+            {
+                case IOCTL_MRX_VBOX_ADDCONN:
+                {
+                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_ADDCONN\n"));
+                    Status = vbsfCreateConnection(RxContext, &RxContext->PostRequest);
+                    break;
+                }
+
+                case IOCTL_MRX_VBOX_DELCONN:
+                {
+                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_DELCONN\n"));
+                    Status = vbsfDeleteConnection(RxContext, &RxContext->PostRequest);
+                    break;
+                }
+
+                case IOCTL_MRX_VBOX_GETLIST:
+                {
+                    ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
+                    uint8_t *pu8Out = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
+
+                    BOOLEAN fLocked = FALSE;
+
+                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST\n"));
+
+                    RxContext->InformationToReturn = 0;
+
+                    if (   !pDeviceExtension
+                        || cbOut < _MRX_MAX_DRIVE_LETTERS)
+                    {
+                        Status = STATUS_INVALID_PARAMETER;
+                        break;
+                    }
+
+                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETLIST: Copying local connections\n"));
+
+                    fLocked = ExTryToAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
+
+                    __try
+                    {
+                        RtlCopyMemory(pu8Out, pDeviceExtension->cLocalConnections, _MRX_MAX_DRIVE_LETTERS);
+                        RxContext->InformationToReturn = _MRX_MAX_DRIVE_LETTERS;
+                    }
+                    __except(EXCEPTION_EXECUTE_HANDLER)
+                    {
+                        Status = STATUS_INVALID_PARAMETER;
+                    }
+
+                    if (fLocked)
+                    {
+                        ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
+                        fLocked = FALSE;
+                    }
+
+                    break;
+                }
+
+                /*
+                 * Returns the root IDs of shared folder mappings.
+                 */
+                case IOCTL_MRX_VBOX_GETGLOBALLIST:
+                {
+                    ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
+                    uint8_t *pu8Out = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
+
+                    int vrc;
+                    SHFLMAPPING mappings[_MRX_MAX_DRIVE_LETTERS];
+                    uint32_t cMappings = RT_ELEMENTS(mappings);
+
+                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALLIST\n"));
+
+                    RxContext->InformationToReturn = 0;
+
+                    if (   !pDeviceExtension
+                        || cbOut < _MRX_MAX_DRIVE_LETTERS)
+                    {
+                        Status = STATUS_INVALID_PARAMETER;
+                        break;
+                    }
+
+                    vrc = VbglR0SfQueryMappings(&pDeviceExtension->hgcmClient, mappings, &cMappings);
+                    if (vrc == VINF_SUCCESS)
+                    {
+                        __try
+                        {
+                            uint32_t i;
+
+                            RtlZeroMemory(pu8Out, _MRX_MAX_DRIVE_LETTERS);
+
+                            for (i = 0; i < RT_MIN(cMappings, cbOut); i++)
+                            {
+                                pu8Out[i] = mappings[i].root;
+                                pu8Out[i] |= 0x80; /* mark active */ /** @todo fix properly */
+                            }
+
+                            RxContext->InformationToReturn = _MRX_MAX_DRIVE_LETTERS;
+                        }
+                        __except(EXCEPTION_EXECUTE_HANDLER)
+                        {
+                            Status = STATUS_INVALID_PARAMETER;
+                        }
+                    }
+                    else
+                    {
+                        Status = VBoxErrorToNTStatus(vrc);
+                        Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALLIST failed: 0x%08X\n",
+                             Status));
+                    }
+
+                    break;
+                }
+
+                /*
+                 * Translates a local connection name (e.g. drive "S:") to the
+                 * corresponding remote name (e.g. \\vboxsrv\share).
+                 */
+                case IOCTL_MRX_VBOX_GETCONN:
+                {
+                    ULONG cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
+                    PWCHAR pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
+                    ULONG cbRemoteName = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
+                    PWCHAR pwcRemoteName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
+
+                    BOOLEAN fMutexAcquired = FALSE;
+
+                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN\n"));
+
+                    RxContext->InformationToReturn = 0;
+
+                    if (   !pDeviceExtension
+                        || cbConnectName < sizeof(WCHAR))
+                    {
+                        Status = STATUS_INVALID_PARAMETER;
+                        break;
+                    }
+
+                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Looking up connection name and connections\n"));
+
+                    __try
+                    {
+                        uint32_t idx = *pwcConnectName - L'A';
+
+                        Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: ConnectName = %.*ls, Len = %d, Index = %d\n",
+                             cbConnectName / sizeof(WCHAR), pwcConnectName, cbConnectName, idx));
+
+                        if (idx < RTL_NUMBER_OF(pDeviceExtension->wszLocalConnectionName))
+                        {
+                            ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
+                            fMutexAcquired = TRUE;
+
+                            if (pDeviceExtension->wszLocalConnectionName[idx])
+                            {
+                                ULONG cbLocalConnectionName = pDeviceExtension->wszLocalConnectionName[idx]->Length;
+
+                                Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName = %.*ls\n",
+                                     cbLocalConnectionName / sizeof(WCHAR), pDeviceExtension->wszLocalConnectionName[idx]->Buffer));
+
+                                if ((pDeviceExtension->cLocalConnections[idx]) && (cbLocalConnectionName <= cbRemoteName))
+                                {
+                                    RtlZeroMemory(pwcRemoteName, cbRemoteName);
+                                    RtlCopyMemory(pwcRemoteName,
+                                                  pDeviceExtension->wszLocalConnectionName[idx]->Buffer,
+                                                  cbLocalConnectionName);
+
+                                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Remote name = %.*ls, Len = %d\n",
+                                         cbLocalConnectionName / sizeof(WCHAR), pwcRemoteName, cbLocalConnectionName));
+                                }
+                                else
+                                {
+                                    Status = STATUS_BUFFER_TOO_SMALL;
+                                }
+
+                                RxContext->InformationToReturn = cbLocalConnectionName;
+                            }
+                            else
+                            {
+                                Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: LocalConnectionName is NULL!\n"));
+                                Status = STATUS_BAD_NETWORK_NAME;
+                            }
+                        }
+                        else
+                        {
+                            Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETCONN: Index is invalid!\n"));
+                            Status = STATUS_INVALID_PARAMETER;
+                        }
+                    }
+                    __except(EXCEPTION_EXECUTE_HANDLER)
+                    {
+                        Status = STATUS_INVALID_PARAMETER;
+                    }
+
+                    if (fMutexAcquired)
+                    {
+                        ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
+                        fMutexAcquired = FALSE;
+                    }
+
+                    break;
+                }
+
+                case IOCTL_MRX_VBOX_GETGLOBALCONN:
+                {
+                    ULONG cbConnectId = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
+                    uint8_t *pu8ConnectId = (uint8_t *)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
+                    ULONG cbRemoteName = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
+                    PWCHAR pwcRemoteName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
+
+                    int vrc;
+                    PSHFLSTRING pString;
+
+                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN\n"));
+
+                    RxContext->InformationToReturn = 0;
+
+                    if (   !pDeviceExtension
+                        || cbConnectId < sizeof(uint8_t))
+                    {
+                        Status = STATUS_INVALID_PARAMETER;
+                        break;
+                    }
+
+                    /* Allocate empty string where the host can store cbRemoteName bytes. */
+                    Status = vbsfShflStringFromUnicodeAlloc(&pString, NULL, (uint16_t)cbRemoteName);
+                    if (Status != STATUS_SUCCESS)
+                        break;
+
+                    __try
+                    {
+                        Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Connection ID = %d\n",
+                             *pu8ConnectId));
+
+                        vrc = VbglR0SfQueryMapName(&pDeviceExtension->hgcmClient,
+                                                   *pu8ConnectId & ~0x80 /** @todo fix properly */,
+                                                   pString, ShflStringSizeOfBuffer(pString));
+                        if (   vrc == VINF_SUCCESS
+                            && pString->u16Length < cbRemoteName)
+                        {
+                            RtlCopyMemory(pwcRemoteName, pString->String.ucs2, pString->u16Length);
+                            Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_GETGLOBALCONN: Returned name = %.*ls, Len = %d\n",
+                                 pString->u16Length / sizeof(WCHAR), pwcRemoteName, pString->u16Length));
+                            RxContext->InformationToReturn = pString->u16Length;
+                        }
+                        else
+                        {
+                            Status = STATUS_BAD_NETWORK_NAME;
+                        }
+                    }
+                    __except(EXCEPTION_EXECUTE_HANDLER)
+                    {
+                        Status = STATUS_INVALID_PARAMETER;
+                    }
+
+                    vbsfFreeNonPagedMem(pString);
+
+                    break;
+                }
+
+                case IOCTL_MRX_VBOX_START:
+                {
+                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: capFobx %p\n",
+                         capFobx));
+
+                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: process: current 0x%X, RDBSS 0x%X\n",
+                         IoGetCurrentProcess(), RxGetRDBSSProcess()));
+
+                    switch (VBoxMRxState)
+                    {
+                        case MRX_VBOX_STARTABLE:
+
+                            Log(("VBOXSF: MRxDevFcbXXXControlFile: MRX_VBOX_STARTABLE\n"));
+
+                            if (capFobx)
+                            {
+                                Status = STATUS_INVALID_DEVICE_REQUEST;
+                                break;;
+                            }
+
+                            InterlockedCompareExchange((PLONG)&VBoxMRxState, MRX_VBOX_START_IN_PROGRESS, MRX_VBOX_STARTABLE);
+
+                        case MRX_VBOX_START_IN_PROGRESS:
+                            Status = RxStartMinirdr(RxContext, &RxContext->PostRequest);
+
+                            Log(("VBOXSF: MRxDevFcbXXXControlFile: MRX_VBOX_START_IN_PROGRESS RxStartMiniRdr Status 0x%08X, post %d\n",
+                                 Status, RxContext->PostRequest));
+
+                            if (Status == STATUS_REDIRECTOR_STARTED)
+                            {
+                                Status = STATUS_SUCCESS;
+                                break;
+                            }
+
+                            if (   Status == STATUS_PENDING
+                                && RxContext->PostRequest == TRUE)
+                            {
+                                /* Will be restarted in RDBSS process. */
+                                Status = STATUS_MORE_PROCESSING_REQUIRED;
+                                break;
+                            }
+
+                            /* Allow restricted users to use shared folders; works only in XP and Vista. (@@todo hack) */
+                            if (Status == STATUS_SUCCESS)
+                            {
+                                SECURITY_DESCRIPTOR SecurityDescriptor;
+                                OBJECT_ATTRIBUTES InitializedAttributes;
+                                HANDLE hDevice;
+                                IO_STATUS_BLOCK IoStatusBlock;
+                                UNICODE_STRING UserModeDeviceName;
+
+                                RtlInitUnicodeString(&UserModeDeviceName, DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U);
+
+                                /* Create empty security descriptor */
+                                RtlZeroMemory (&SecurityDescriptor, sizeof (SecurityDescriptor));
+                                Status = RtlCreateSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
+                                if (Status != STATUS_SUCCESS)
+                                {
+                                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: RtlCreateSecurityDescriptor failed with 0x%08X!\n",
+                                         Status));
+                                    return Status;
+                                }
+
+                                RtlZeroMemory (&InitializedAttributes, sizeof (InitializedAttributes));
+                                InitializeObjectAttributes(&InitializedAttributes, &UserModeDeviceName, OBJ_KERNEL_HANDLE, 0, 0);
+
+                                /* Open our symbolic link device name */
+                                Status = ZwOpenFile(&hDevice, WRITE_DAC, &InitializedAttributes, &IoStatusBlock, 0, 0);
+                                if (Status != STATUS_SUCCESS)
+                                {
+                                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwOpenFile %ls failed with 0x%08X!\n",
+                                         DD_MRX_VBOX_USERMODE_SHADOW_DEV_NAME_U, Status));
+                                    return Status;
+                                }
+
+                                /* Override the discretionary access control list (DACL) settings */
+                                Status = ZwSetSecurityObject(hDevice, DACL_SECURITY_INFORMATION, &SecurityDescriptor);
+                                if (Status != STATUS_SUCCESS)
+                                {
+                                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwSetSecurityObject failed with 0x%08X!\n",
+                                         Status));
+                                    return Status;
+                                }
+
+                                Status = ZwClose(hDevice);
+                                if (Status != STATUS_SUCCESS)
+                                {
+                                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_START_IN_PROGRESS: ZwClose failed with 0x%08X\n",
+                                         Status));
+                                    return Status;
+                                }
+                            }
+                            break;
+
+                        case MRX_VBOX_STARTED:
+                            Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: MRX_VBOX_STARTED: Already started\n"));
+                            Status = STATUS_SUCCESS;
+                            break;
+
+                        default:
+                            Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Invalid state (%d)!\n",
+                                 VBoxMRxState));
+                            Status = STATUS_INVALID_PARAMETER;
+                            break;
+                    }
+
+                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_START: Returned 0x%08X\n",
+                         Status));
+                    break;
+                }
+
+                case IOCTL_MRX_VBOX_STOP:
+                {
+                    MRX_VBOX_STATE CurrentState;
+
+                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: capFobx %p\n",
+                         capFobx));
+
+                    if (capFobx)
+                    {
+                        Status = STATUS_INVALID_DEVICE_REQUEST;
+                        break;
+                    }
+
+                    if (RxContext->RxDeviceObject->NumberOfActiveFcbs > 0)
+                    {
+                        Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Open handles = %d\n",
+                             RxContext->RxDeviceObject->NumberOfActiveFcbs));
+                        Status = STATUS_REDIRECTOR_HAS_OPEN_HANDLES;
+                        break;
+                    }
+
+                    CurrentState = (MRX_VBOX_STATE)InterlockedCompareExchange((PLONG) & VBoxMRxState, MRX_VBOX_STARTABLE, MRX_VBOX_STARTED);
+
+                    Status = RxStopMinirdr(RxContext, &RxContext->PostRequest);
+                    Log(("VBOXSF: MRxDevFcbXXXControlFile: IOCTL_MRX_VBOX_STOP: Returned 0x%08X\n",
+                         Status));
+
+                    if (Status == STATUS_PENDING && RxContext->PostRequest == TRUE)
+                        Status = STATUS_MORE_PROCESSING_REQUIRED;
+                    break;
+                }
+
+                default:
+                    Status = STATUS_INVALID_DEVICE_REQUEST;
+                    break;
+            }
+            break;
+        }
+
+        case IRP_MJ_INTERNAL_DEVICE_CONTROL:
+        {
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+            break;
+        }
+
+        default:
+            Log(("VBOXSF: MRxDevFcbXXXControlFile: unimplemented major function 0x%02X\n",
+                 RxContext->MajorFunction));
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+            break;
+    }
+
+    Log(("VBOXSF: MRxDevFcbXXXControlFile: Status = 0x%08X, Info = 0x%08X\n",
+         Status, RxContext->InformationToReturn));
+
+    return Status;
+}
+
+static NTSTATUS vbsfVerifyConnectionName(PUNICODE_STRING ConnectionName)
+{
+    /* Check that the connection name is valid:
+     * "\Device\VBoxMiniRdr\;X:\vboxsvr\sf"
+     */
+    NTSTATUS Status = STATUS_BAD_NETWORK_NAME;
+
+    ULONG i;
+    PWCHAR pwc;
+    PWCHAR pwc1;
+
+    static PWCHAR spwszPrefix = L"\\Device\\VBoxMiniRdr\\;";
+
+    /* Unicode chars in the string. */
+    ULONG cConnectionName = ConnectionName->Length / sizeof(WCHAR);
+    ULONG cRemainingName;
+
+    /* Check that the name starts with correct prefix. */
+    pwc1 = &spwszPrefix[0];
+    pwc = ConnectionName->Buffer;
+    for (i = 0; i < cConnectionName; i++, pwc1++, pwc++)
+    {
+        if (*pwc1 == 0 || *pwc == 0 || *pwc1 != *pwc)
+            break;
+    }
+
+    cRemainingName = cConnectionName - i;
+
+    Log(("VBOXSF: vbsfVerifyConnectionName: prefix %d remaining %d [%.*ls]\n",
+         *pwc1 == 0, cRemainingName, cRemainingName, &ConnectionName->Buffer[i]));
+
+    if (*pwc1 == 0)
+    {
+        /* pwc should point to a drive letter followed by ':\' that is at least 3 chars more. */
+        if (cRemainingName >= 3)
+        {
+           if (   pwc[0] >= L'A' && pwc[0] <= L'Z'
+               && pwc[1] == L':')
+           {
+               pwc += 2;
+               cRemainingName -= 2;
+
+               /** @todo should also check that the drive letter corresponds to the name. */
+               if (vboxIsPrefixOK(pwc, cRemainingName * sizeof (WCHAR)))
+                   Status = STATUS_SUCCESS;
+           }
+        }
+    }
+
+    return Status;
+}
+
+static HANDLE vbsfOpenConnectionHandle(PUNICODE_STRING ConnectionName, NTSTATUS *prcNt)
+{
+    NTSTATUS Status;
+    IO_STATUS_BLOCK IoStatusBlock;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+
+    HANDLE Handle = INVALID_HANDLE_VALUE;
+
+    Log(("VBOXSF: vbsfOpenConnectionHandle: ConnectionName = %.*ls\n",
+         ConnectionName->Length / sizeof(WCHAR), ConnectionName->Buffer));
+
+    Status = vbsfVerifyConnectionName(ConnectionName);
+
+    if (NT_SUCCESS(Status))
+    {
+        /* Have to create a OBJ_KERNEL_HANDLE. Otherwise the driver verifier on Windows 7 bugchecks. */
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   ConnectionName,
+                                   OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+                                   NULL,
+                                   NULL);
+
+        Status = ZwCreateFile(&Handle,
+                              SYNCHRONIZE,
+                              &ObjectAttributes,
+                              &IoStatusBlock,
+                              NULL,
+                              FILE_ATTRIBUTE_NORMAL,
+                              FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                              FILE_OPEN_IF,
+                              FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
+                              NULL,
+                              0);
+    }
+
+    if (   Status != STATUS_SUCCESS
+        || Handle == INVALID_HANDLE_VALUE)
+    {
+        Log(("VBOXSF: vbsfOpenConnectionHandle: ZwCreateFile failed status 0x%08X or invalid handle!\n", Status));
+        if (prcNt)
+            *prcNt = !NT_SUCCESS(Status) ? Status : STATUS_UNSUCCESSFUL;
+        Handle = INVALID_HANDLE_VALUE;
+    }
+
+    return Handle;
+}
+
+NTSTATUS vbsfCreateConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
+
+    PLOWIO_CONTEXT LowIoContext;
+    ULONG cbConnectName;
+    PWCHAR pwcConnectName;
+
+    HANDLE Handle;
+    UNICODE_STRING FileName;
+
+    BOOLEAN fMutexAcquired = FALSE;
+
+    Log(("VBOXSF: vbsfCreateConnection\n"));
+
+    if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT))
+    {
+        Log(("VBOXSF: vbsfCreateConnection: post to file system process\n"));
+        *PostToFsp = TRUE;
+        return STATUS_PENDING;
+    }
+
+    pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
+    if (!pDeviceExtension)
+        return STATUS_INVALID_PARAMETER;
+
+    LowIoContext = &RxContext->LowIoContext;
+    cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
+    pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
+
+    if (cbConnectName == 0 || !pwcConnectName)
+    {
+        Log(("VBOXSF: vbsfCreateConnection: Connection name / length is invalid!\n"));
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    __try
+    {
+        Log(("VBOXSF: vbsfCreateConnection: Name = %.*ls, Len = %d\n",
+             cbConnectName / sizeof(WCHAR), pwcConnectName, cbConnectName));
+
+        FileName.Buffer = pwcConnectName;
+        FileName.Length = (USHORT)cbConnectName;
+        FileName.MaximumLength = (USHORT)cbConnectName;
+
+        Handle = vbsfOpenConnectionHandle(&FileName, NULL);
+
+        if (Handle != INVALID_HANDLE_VALUE)
+        {
+            PWCHAR pwc;
+            ULONG i;
+
+            ZwClose(Handle);
+
+            /* Skip the "\Device\VBoxMiniRdr\;X:" of the string "\Device\VBoxMiniRdr\;X:\vboxsrv\sf" */
+            pwc = pwcConnectName;
+            for (i = 0; i < cbConnectName; i += sizeof(WCHAR))
+            {
+                if (*pwc == L':')
+                    break;
+                pwc++;
+            }
+
+            if (i >= sizeof(WCHAR) && i < cbConnectName)
+            {
+                pwc--; /* Go back to the drive letter, "X" for example. */
+
+                if (*pwc >= L'A' && *pwc <= L'Z') /* Are we in range? */
+                {
+                    uint32_t idx = *pwc - L'A'; /* Get the index based on the driver letter numbers (26). */
+
+                    if (idx >= RTL_NUMBER_OF(pDeviceExtension->cLocalConnections))
+                    {
+                        Log(("VBOXSF: vbsfCreateConnection: Index 0x%x is invalid!\n",
+                             idx));
+                        Status = STATUS_BAD_NETWORK_NAME;
+                    }
+                    else
+                    {
+                        ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
+                        fMutexAcquired = TRUE;
+
+                        if (pDeviceExtension->wszLocalConnectionName[idx] != NULL)
+                        {
+                            Log(("VBOXSF: vbsfCreateConnection: LocalConnectionName at index %d is NOT empty!\n",
+                                 idx));
+                        }
+
+                        pDeviceExtension->wszLocalConnectionName[idx] = (PUNICODE_STRING)vbsfAllocNonPagedMem(sizeof(UNICODE_STRING) + cbConnectName);
+
+                        if (!pDeviceExtension->wszLocalConnectionName[idx])
+                        {
+                            Log(("VBOXSF: vbsfCreateConnection: LocalConnectionName at index %d NOT allocated!\n",
+                                 idx));
+                            Status = STATUS_INSUFFICIENT_RESOURCES;
+                        }
+                        else
+                        {
+                            PUNICODE_STRING pRemoteName = pDeviceExtension->wszLocalConnectionName[idx];
+
+                            pRemoteName->Buffer = (PWSTR)(pRemoteName + 1);
+                            pRemoteName->Length = (USHORT)(cbConnectName - i - sizeof(WCHAR));
+                            pRemoteName->MaximumLength = pRemoteName->Length;
+                            RtlCopyMemory(&pRemoteName->Buffer[0], pwc+2, pRemoteName->Length);
+
+                            Log(("VBOXSF: vbsfCreateConnection: RemoteName %.*ls, Len = %d\n",
+                                 pRemoteName->Length / sizeof(WCHAR), pRemoteName->Buffer, pRemoteName->Length));
+
+                            pDeviceExtension->cLocalConnections[idx] = TRUE;
+                        }
+
+                        ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
+                        fMutexAcquired = FALSE;
+                    }
+                }
+            }
+            else
+            {
+                Log(("VBOXSF: vbsfCreateConnection: bad format\n"));
+                Status = STATUS_BAD_NETWORK_NAME;
+            }
+        }
+        else
+        {
+            Log(("VBOXSF: vbsfCreateConnection: connection was not found\n"));
+            Status = STATUS_BAD_NETWORK_NAME;
+        }
+    }
+    __except(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = STATUS_INVALID_PARAMETER;
+    }
+
+    if (fMutexAcquired)
+    {
+        ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
+        fMutexAcquired = FALSE;
+    }
+
+    return Status;
+}
+
+NTSTATUS vbsfDeleteConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp)
+{
+    NTSTATUS Status;
+    UNICODE_STRING FileName;
+    HANDLE Handle;
+    PLOWIO_CONTEXT LowIoContext;
+    PWCHAR pwcConnectName;
+    ULONG cbConnectName;
+    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension;
+
+    BOOLEAN fMutexAcquired = FALSE;
+
+    Log(("VBOXSF: vbsfDeleteConnection\n"));
+
+    if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT))
+    {
+        Log(("VBOXSF: vbsfDeleteConnection: post to file system process\n"));
+        *PostToFsp = TRUE;
+        return STATUS_PENDING;
+    }
+
+    LowIoContext = &RxContext->LowIoContext;
+    pwcConnectName = (PWCHAR)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
+    cbConnectName = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
+
+    pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
+    if (!pDeviceExtension)
+        return STATUS_INVALID_PARAMETER;
+
+    __try
+    {
+        Log(("VBOXSF: vbsfDeleteConnection: pwcConnectName = %.*ls\n",
+             cbConnectName / sizeof(WCHAR), pwcConnectName));
+
+        FileName.Buffer = pwcConnectName;
+        FileName.Length = (USHORT)cbConnectName;
+        FileName.MaximumLength = (USHORT)cbConnectName;
+
+        Handle = vbsfOpenConnectionHandle(&FileName, &Status);
+        if (Handle != INVALID_HANDLE_VALUE)
+        {
+            PFILE_OBJECT pFileObject;
+            Status = ObReferenceObjectByHandle(Handle, 0L, NULL, KernelMode, (PVOID *)&pFileObject, NULL);
+
+            Log(("VBOXSF: vbsfDeleteConnection: ObReferenceObjectByHandle Status 0x%08X\n",
+                 Status));
+
+            if (NT_SUCCESS(Status))
+            {
+                PFOBX Fobx = (PFOBX)pFileObject->FsContext2;
+                Log(("VBOXSF: vbsfDeleteConnection: Fobx %p\n", Fobx));
+
+                if (Fobx && NodeType(Fobx) == RDBSS_NTC_V_NETROOT)
+                {
+                    PV_NET_ROOT VNetRoot = (PV_NET_ROOT)Fobx;
+
+#ifdef __cplusplus /* C version points at NET_ROOT, C++ points at MRX_NET_ROOT. Weird. */
+                    Status = RxFinalizeConnection((PNET_ROOT)VNetRoot->pNetRoot, VNetRoot, TRUE);
+#else
+                    Status = RxFinalizeConnection(VNetRoot->NetRoot, VNetRoot, TRUE);
+#endif
+                }
+                else
+                {
+                    Log(("VBOXSF: vbsfDeleteConnection: wrong FsContext2\n"));
+                    Status = STATUS_INVALID_DEVICE_REQUEST;
+                }
+
+                ObDereferenceObject(pFileObject);
+            }
+
+            ZwClose(Handle);
+
+            if (NT_SUCCESS(Status))
+            {
+                PWCHAR pwc;
+                ULONG i;
+
+                /* Skip the "\Device\VBoxMiniRdr\;X:" of the string "\Device\VBoxMiniRdr\;X:\vboxsrv\sf" */
+                pwc = pwcConnectName;
+                for (i = 0; i < cbConnectName; i += sizeof(WCHAR))
+                {
+                    if (*pwc == L':')
+                    {
+                        break;
+                    }
+                    pwc++;
+                }
+
+                if (i >= sizeof(WCHAR) && i < cbConnectName)
+                {
+                    pwc--;
+
+                    if (*pwc >= L'A' && *pwc <= L'Z')
+                    {
+                        uint32_t idx = *pwc - L'A';
+
+                        if (idx >= RTL_NUMBER_OF(pDeviceExtension->cLocalConnections))
+                        {
+                            Log(("VBOXSF: vbsfDeleteConnection: Index 0x%x is invalid!\n",
+                                 idx));
+                            Status = STATUS_BAD_NETWORK_NAME;
+                        }
+                        else
+                        {
+                            ExAcquireFastMutex(&pDeviceExtension->mtxLocalCon);
+                            fMutexAcquired = TRUE;
+
+                            pDeviceExtension->cLocalConnections[idx] = FALSE;
+
+                            /* Free saved name */
+                            if (pDeviceExtension->wszLocalConnectionName[idx])
+                            {
+                                vbsfFreeNonPagedMem(pDeviceExtension->wszLocalConnectionName[idx]);
+                                pDeviceExtension->wszLocalConnectionName[idx] = NULL;
+                            }
+
+                            ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
+                            fMutexAcquired = FALSE;
+
+                            Log(("VBOXSF: vbsfDeleteConnection: deleted index 0x%x\n",
+                                 idx));
+                        }
+                    }
+                }
+                else
+                {
+                    Log(("VBOXSF: vbsfCreateConnection: bad format\n"));
+                    Status = STATUS_BAD_NETWORK_NAME;
+                }
+            }
+        }
+    }
+    __except(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = STATUS_INVALID_PARAMETER;
+    }
+
+    if (fMutexAcquired)
+    {
+        ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon);
+        fMutexAcquired = FALSE;
+    }
+
+    Log(("VBOXSF: vbsfDeleteConnection: Status 0x%08X\n", Status));
+    return Status;
+}
+
+NTSTATUS VBoxMRxQueryEaInfo(IN OUT PRX_CONTEXT RxContext)
+{
+    RT_NOREF(RxContext);
+    Log(("VBOXSF: MRxQueryEaInfo: Ea buffer len remaining is %d\n", RxContext->Info.LengthRemaining));
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS VBoxMRxSetEaInfo(IN OUT PRX_CONTEXT RxContext)
+{
+    RT_NOREF(RxContext);
+    Log(("VBOXSF: MRxSetEaInfo\n"));
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS VBoxMRxFsCtl(IN OUT PRX_CONTEXT RxContext)
+{
+    RT_NOREF(RxContext);
+    Log(("VBOXSF: MRxFsCtl\n"));
+    return STATUS_INVALID_DEVICE_REQUEST;
+}
+
+NTSTATUS VBoxMRxNotifyChangeDirectory(IN OUT PRX_CONTEXT RxContext)
+{
+    RT_NOREF(RxContext);
+    Log(("VBOXSF: MRxNotifyChangeDirectory\n"));
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS vbsfQuerySdInfo(PVOID pvBuffer, ULONG cbBuffer, SECURITY_INFORMATION SecurityInformation, ULONG *pcbOut)
+{
+    /* What a public SMB share would return. */
+    static SID_IDENTIFIER_AUTHORITY sIA = SECURITY_NT_AUTHORITY;
+    #define SUB_AUTHORITY_COUNT 2
+    static const ULONG saSubAuthorityOwner[] = { SECURITY_NT_NON_UNIQUE, DOMAIN_USER_RID_GUEST   };
+    static const ULONG saSubAuthorityGroup[] = { SECURITY_NT_NON_UNIQUE, DOMAIN_GROUP_RID_GUESTS };
+
+    SECURITY_DESCRIPTOR_RELATIVE *pSD = (SECURITY_DESCRIPTOR_RELATIVE *)pvBuffer;
+    ULONG cbSD = 0; /* Size of returned security descriptor. */
+    ULONG cbAdd; /* How many bytes to add to the buffer for each component of the security descriptor. */
+
+    cbAdd = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
+    if (cbSD + cbAdd <= cbBuffer)
+    {
+        pSD->Revision = SECURITY_DESCRIPTOR_REVISION1;
+        pSD->Sbz1     = 0;
+        pSD->Control  = SE_SELF_RELATIVE;
+        pSD->Owner    = 0;
+        pSD->Group    = 0;
+        pSD->Sacl     = 0;
+        pSD->Dacl     = 0;
+    }
+    cbSD += cbAdd;
+
+    if (SecurityInformation & OWNER_SECURITY_INFORMATION)
+    {
+        cbAdd = RT_UOFFSETOF(SID, SubAuthority) + SUB_AUTHORITY_COUNT * sizeof(ULONG);
+        if (cbSD + cbAdd <= cbBuffer)
+        {
+            SID *pSID = (SID *)((uint8_t *)pSD + cbSD);
+            pSID->Revision            = 1;
+            pSID->SubAuthorityCount   = SUB_AUTHORITY_COUNT;
+            pSID->IdentifierAuthority = sIA;
+            memcpy(pSID->SubAuthority, saSubAuthorityOwner, SUB_AUTHORITY_COUNT * sizeof(ULONG));
+
+            pSD->Owner = cbSD;
+        }
+        cbSD += cbAdd;
+    }
+
+    if (SecurityInformation & GROUP_SECURITY_INFORMATION)
+    {
+        cbAdd = RT_UOFFSETOF(SID, SubAuthority) + SUB_AUTHORITY_COUNT * sizeof(ULONG);
+        if (cbSD + cbAdd <= cbBuffer)
+        {
+            SID *pSID = (SID *)((uint8_t *)pSD + cbSD);
+            pSID->Revision            = 1;
+            pSID->SubAuthorityCount   = SUB_AUTHORITY_COUNT;
+            pSID->IdentifierAuthority = sIA;
+            memcpy(pSID->SubAuthority, saSubAuthorityGroup, SUB_AUTHORITY_COUNT * sizeof(ULONG));
+
+            pSD->Group = cbSD;
+        }
+        cbSD += cbAdd;
+    }
+
+    #undef SUB_AUTHORITY_COUNT
+
+    *pcbOut = cbSD;
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS VBoxMRxQuerySdInfo(IN OUT PRX_CONTEXT RxContext)
+{
+    NTSTATUS Status;
+
+    PVOID pvBuffer = RxContext->Info.Buffer;
+    ULONG cbBuffer = RxContext->Info.LengthRemaining;
+    SECURITY_INFORMATION SecurityInformation = RxContext->QuerySecurity.SecurityInformation;
+
+    ULONG cbSD = 0;
+
+    Log(("VBOXSF: MRxQuerySdInfo: Buffer %p, Length %d, SecurityInformation 0x%x\n",
+         pvBuffer, cbBuffer, SecurityInformation));
+
+    Status = vbsfQuerySdInfo(pvBuffer, cbBuffer, SecurityInformation, &cbSD);
+    if (NT_SUCCESS(Status))
+    {
+        RxContext->InformationToReturn = cbSD;
+        if (RxContext->InformationToReturn > cbBuffer)
+        {
+            Status = STATUS_BUFFER_OVERFLOW;
+        }
+    }
+
+    Log(("VBOXSF: MRxQuerySdInfo: Status 0x%08X, InformationToReturn %d\n",
+         Status, RxContext->InformationToReturn));
+    return Status;
+}
+
+NTSTATUS VBoxMRxSetSdInfo(IN OUT struct _RX_CONTEXT * RxContext)
+{
+    RT_NOREF(RxContext);
+    Log(("VBOXSF: MRxSetSdInfo\n"));
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+/*
+ * WML stubs which are referenced by rdbsslib.
+ */
+extern "C" NTSTATUS WmlTinySystemControl(IN OUT PVOID pWmiLibInfo, IN PVOID pDevObj, IN PVOID pIrp)
+{
+    RT_NOREF(pWmiLibInfo, pDevObj, pIrp);
+    return STATUS_WMI_GUID_NOT_FOUND;
+}
+
+extern "C" ULONG WmlTrace(IN ULONG ulType, IN PVOID pTraceUuid, IN ULONG64 ullLogger, ...)
+{
+    RT_NOREF(ulType, pTraceUuid, ullLogger);
+    return STATUS_SUCCESS;
+}
+
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.h	(revision 78301)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.h	(revision 78302)
@@ -43,4 +43,9 @@
 #include "vbsfhlp.h"
 #include "vbsfshared.h"
+#ifdef __cplusplus /* mixes code and variables */
+# include <VBox/VBoxGuestLibSharedFoldersInline.h>
+#endif
+
+RT_C_DECLS_BEGIN
 
 extern PRDBSS_DEVICE_OBJECT VBoxMRxDeviceObject;
@@ -76,4 +81,12 @@
 
 } MRX_VBOX_DEVICE_EXTENSION, *PMRX_VBOX_DEVICE_EXTENSION;
+#ifdef RT_ARCH_AMD64
+AssertCompileMemberOffset(MRX_VBOX_DEVICE_EXTENSION, cLocalConnections, 8);
+AssertCompileMemberOffset(MRX_VBOX_DEVICE_EXTENSION, wszLocalConnectionName, 0x28);
+AssertCompileMemberOffset(MRX_VBOX_DEVICE_EXTENSION, mtxLocalCon, 0xF8);
+AssertCompileMemberSize(MRX_VBOX_DEVICE_EXTENSION, mtxLocalCon, 7 * 8);
+AssertCompileMemberOffset(MRX_VBOX_DEVICE_EXTENSION, hgcmClient, 0x130);
+AssertCompileMemberOffset(MRX_VBOX_DEVICE_EXTENSION, pfnRDBSSDeviceControl, 0x130 + 16);
+#endif
 
 /*
@@ -95,13 +108,20 @@
 #define VBOX_FOBX_F_INFO_ATTRIBUTES      0x10
 
-/*
+/**
  * The shared folders file extension.
  */
-typedef struct _MRX_VBOX_FOBX_
+typedef struct MRX_VBOX_FOBX
 {
-    SHFLHANDLE hFile;
-    PMRX_SRV_CALL pSrvCall;
-    FILE_BASIC_INFORMATION FileBasicInfo;
-    FILE_STANDARD_INFORMATION FileStandardInfo;
+    /** The host file handle. */
+    SHFLHANDLE                  hFile;
+    PMRX_SRV_CALL               pSrvCall;
+    /** The RTTimeSystemNanoTS value when Info was retrieved, 0 to force update. */
+    uint64_t                    nsUpToDate;
+    /** Cached object info. */
+    SHFLFSOBJINFO               Info;
+    /** NT version of Info.
+     * @todo try eliminate  */
+    FILE_BASIC_INFORMATION      FileBasicInfo;
+
     BOOLEAN fKeepCreationTime;
     BOOLEAN fKeepLastAccessTime;
@@ -216,3 +236,8 @@
                              PMRX_VBOX_FOBX pVBoxFobx);
 
+void     vbsfNtCopyInfoToLegacy(PMRX_VBOX_FOBX pVBoxFobx, PCSHFLFSOBJINFO pInfo);
+
+
+RT_C_DECLS_END
+
 #endif /* !GA_INCLUDED_SRC_WINNT_SharedFolders_driver_vbsf_h */
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsfhlp.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsfhlp.h	(revision 78301)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsfhlp.h	(revision 78302)
@@ -28,4 +28,5 @@
 #include <VBox/VBoxGuestLibSharedFolders.h>
 
+RT_C_DECLS_BEGIN
 
 void     vbsfHlpSleep(ULONG ulMillies);
@@ -45,4 +46,6 @@
 NTSTATUS vbsfShflStringFromUnicodeAlloc(PSHFLSTRING *ppShflString, const WCHAR *pwc, uint16_t cb);
 
+RT_C_DECLS_END
+
 #endif /* !GA_INCLUDED_SRC_WINNT_SharedFolders_driver_vbsfhlp_h */
 
