Index: trunk/src/VBox/Additions/WINNT/SharedFolders/driver/path.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/driver/path.c	(revision 78284)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/driver/path.c	(revision 78285)
@@ -49,4 +49,5 @@
         ULONG DeleteOnClose :1;
         ULONG TemporaryFile :1;
+        ULONG SlashHack :1;
     } bf;
 
@@ -112,6 +113,9 @@
         bf.TemporaryFile = TRUE;
 
-    Log(("VBOXSF: vbsfProcessCreate: bf.TemporaryFile %d, bf.CreateDirectory %d, bf.DirectoryFile = %d\n",
-         (ULONG)bf.TemporaryFile, (ULONG)bf.CreateDirectory, (ULONG)bf.DirectoryFile));
+    bf.SlashHack = RxContext->CurrentIrpSp
+                && (RxContext->CurrentIrpSp->Parameters.Create.ShareAccess & VBOX_MJ_CREATE_SLASH_HACK);
+
+    Log(("VBOXSF: vbsfProcessCreate: bf.TemporaryFile %d, bf.CreateDirectory %d, bf.DirectoryFile = %d, bf.SlashHack = %d\n",
+         bf.TemporaryFile, bf.CreateDirectory, bf.DirectoryFile, bf.SlashHack));
 
     /* Check consistency in specified flags. */
@@ -125,4 +129,5 @@
     if (bf.DirectoryFile && bf.NonDirectoryFile)
     {
+        /** @todo r=bird: Check if FILE_DIRECTORY_FILE+FILE_NON_DIRECTORY_FILE really is illegal in all combinations... */
         Log(("VBOXSF: vbsfProcessCreate: Unsupported combination: dir && !dir\n"));
         Status = STATUS_INVALID_PARAMETER;
@@ -252,8 +257,21 @@
         Log(("VBOXSF: vbsfProcessCreate: RemainingName->Length = %d\n", RemainingName->Length));
 
-        Status = vbsfShflStringFromUnicodeAlloc(&ParsedPath, RemainingName->Buffer, RemainingName->Length);
-        if (Status != STATUS_SUCCESS)
-        {
-            goto failure;
+
+        if (!bf.SlashHack)
+        {
+            Status = vbsfShflStringFromUnicodeAlloc(&ParsedPath, RemainingName->Buffer, RemainingName->Length);
+            if (Status != STATUS_SUCCESS)
+                goto failure;
+        }
+        else
+        {
+            /* Add back the slash we had to hide from RDBSS. */
+            Status = vbsfShflStringFromUnicodeAlloc(&ParsedPath, NULL, RemainingName->Length + sizeof(RTUTF16));
+            if (Status != STATUS_SUCCESS)
+                goto failure;
+            memcpy(ParsedPath->String.utf16, RemainingName->Buffer, RemainingName->Length);
+            ParsedPath->String.utf16[RemainingName->Length / sizeof(RTUTF16)] = '\\';
+            ParsedPath->String.utf16[RemainingName->Length / sizeof(RTUTF16) + 1] = '\0';
+            ParsedPath->u16Length = RemainingName->Length + sizeof(RTUTF16);
         }
 
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.c	(revision 78284)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.c	(revision 78285)
@@ -398,4 +398,69 @@
 }
 
+/**
+ * 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)
@@ -542,4 +607,11 @@
     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. */
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.h	(revision 78284)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.h	(revision 78285)
@@ -70,6 +70,8 @@
     VBGLSFCLIENT hgcmClient;
 
-    /* Saved pointer to the original IRP_MJ_DEVICE_CONTROL handler. */
+    /** Saved pointer to the original IRP_MJ_DEVICE_CONTROL handler. */
     NTSTATUS (* pfnRDBSSDeviceControl) (PDEVICE_OBJECT pDevObj, PIRP pIrp);
+    /** Saved pointer to the original IRP_MJ_CREATE handler. */
+    NTSTATUS (NTAPI * pfnRDBSSCreate)(PDEVICE_OBJECT pDevObj, PIRP pIrp);
 
 } MRX_VBOX_DEVICE_EXTENSION, *PMRX_VBOX_DEVICE_EXTENSION;
@@ -121,4 +123,9 @@
         (((pFobx) == NULL) ? NULL : (PMRX_VBOX_FOBX)((pFobx)->Context))
 
+/** HACK ALERT: Special Create.ShareAccess indicating trailing slash for
+ * non-directory IRP_MJ_CREATE request.
+ * Set by VBoxHookMjCreate, used by VBoxMRxCreate. */
+#define VBOX_MJ_CREATE_SLASH_HACK   UINT16_C(0x0400)
+
 /*
  * Prototypes for the dispatch table routines.
Index: trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsfhlp.c
===================================================================
--- trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsfhlp.c	(revision 78284)
+++ trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsfhlp.c	(revision 78285)
@@ -186,4 +186,8 @@
         case VERR_NOT_SUPPORTED:
             Status = STATUS_NOT_SUPPORTED;
+            break;
+
+        case VERR_INVALID_NAME:
+            Status = STATUS_OBJECT_NAME_INVALID;
             break;
 
@@ -409,12 +413,12 @@
 
     PSHFLSTRING pShflString;
-    ULONG ulShflStringSize;
+    ULONG cbShflString;
 
     /* Calculate length required for the SHFL structure: header + chars + nul. */
-    ulShflStringSize = SHFLSTRING_HEADER_SIZE + cb + sizeof(WCHAR);
-    pShflString = (PSHFLSTRING)vbsfAllocNonPagedMem(ulShflStringSize);
+    cbShflString = SHFLSTRING_HEADER_SIZE + cb + sizeof(WCHAR);
+    pShflString = (PSHFLSTRING)vbsfAllocNonPagedMem(cbShflString);
     if (pShflString)
     {
-        if (ShflStringInitBuffer(pShflString, ulShflStringSize))
+        if (ShflStringInitBuffer(pShflString, cbShflString))
         {
             if (pwc)
@@ -428,4 +432,5 @@
             else
             {
+                /** @todo r=bird: vbsfAllocNonPagedMem already zero'ed it...   */
                 RtlZeroMemory(pShflString->String.ucs2, cb + sizeof(WCHAR));
                 pShflString->u16Length = 0; /* without terminating null */
