Example #1
0
static NTSTATUS vbsfWriteInternal(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);

    PLOWIO_CONTEXT LowIoContext  = &RxContext->LowIoContext;

    PMDL BufferMdl = LowIoContext->ParamsFor.ReadWrite.Buffer;
    uint32_t ByteCount = LowIoContext->ParamsFor.ReadWrite.ByteCount;
    RXVBO ByteOffset = LowIoContext->ParamsFor.ReadWrite.ByteOffset;

    PVOID pbUserBuffer = RxLowIoGetBufferAddress(RxContext);

    int vboxRC;

    BOOLEAN AsyncIo = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
    LONGLONG FileSize;

    RxGetFileSizeWithLock((PFCB)capFcb, &FileSize);

    Log(("VBOXSF: vbsfWriteInternal: AsyncIo = %d, Fcb->FileSize = 0x%RX64\n",
         AsyncIo, capFcb->Header.FileSize.QuadPart));
    Log(("VBOXSF: vbsfWriteInternal: UserBuffer %p, BufferMdl %p\n",
         pbUserBuffer, BufferMdl));
    Log(("VBOXSF: vbsfWriteInternal: ByteCount is 0x%X, ByteOffset is 0x%RX64, FileSize 0x%RX64\n",
         ByteCount, ByteOffset, FileSize));

    /* @todo allow to write 0 bytes. */
    if (   BufferMdl == NULL
        || ByteCount == 0)
    {
        AssertFailed();
        return STATUS_INVALID_PARAMETER;
    }

    /* @todo Split large writes. */
    vboxRC = vboxCallWrite(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
                           ByteOffset, &ByteCount, (uint8_t *)pbUserBuffer, true /* locked */);

    Status = VBoxErrorToNTStatus(vboxRC);

    if (Status != STATUS_SUCCESS)
    {
        /* Nothing written. */
        ByteCount = 0;
    }

    RxContext->InformationToReturn = ByteCount;

    Log(("VBOXSF: vbsfWriteInternal: Status = 0x%08X, ByteCount = 0x%X\n",
         Status, ByteCount));

    return Status;
}
Example #2
0
NTSTATUS vbsfSetEndOfFile(IN OUT struct _RX_CONTEXT * RxContext,
                          IN OUT PLARGE_INTEGER pNewFileSize,
                          OUT PLARGE_INTEGER pNewAllocationSize)
{
    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);

    PSHFLFSOBJINFO pObjInfo;
    uint32_t cbBuffer;
    int vboxRC;

    Log(("VBOXSF: vbsfSetEndOfFile: New size = %RX64 (%p), pNewAllocationSize = %p\n",
         pNewFileSize->QuadPart, pNewFileSize, pNewAllocationSize));

    Assert(pVBoxFobx && pNetRootExtension && pDeviceExtension);

    cbBuffer = sizeof(SHFLFSOBJINFO);
    pObjInfo = (SHFLFSOBJINFO *)vbsfAllocNonPagedMem(cbBuffer);
    if (pObjInfo == NULL)
    {
        AssertFailed();
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory(pObjInfo, cbBuffer);
    pObjInfo->cbObject = pNewFileSize->QuadPart;

    vboxRC = vboxCallFSInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
                            SHFL_INFO_SET | SHFL_INFO_SIZE, &cbBuffer, (PSHFLDIRINFO)pObjInfo);

    Log(("VBOXSF: vbsfSetEndOfFile: vboxCallFSInfo returned %Rrc\n",
         vboxRC));

    Status = VBoxErrorToNTStatus(vboxRC);
    if (Status == STATUS_SUCCESS)
    {
        Log(("VBOXSF: vbsfSetEndOfFile: vboxCallFSInfo new allocation size = %RX64\n",
             pObjInfo->cbAllocated));

        /* Return new allocation size */
        pNewAllocationSize->QuadPart = pObjInfo->cbAllocated;
    }

    if (pObjInfo)
    {
        vbsfFreeNonPagedMem(pObjInfo);
    }

    Log(("VBOXSF: vbsfSetEndOfFile: Returned 0x%08X\n",
         Status));
    return Status;
}
Example #3
0
File: file.c Project: carmark/vbox
NTSTATUS VBoxMRxLocks(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);

    PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
    uint32_t fu32Lock = 0;
    int vboxRC;

    Log(("VBOXSF: MRxLocks: Operation %d\n",
         LowIoContext->Operation));

    switch (LowIoContext->Operation)
    {
        default:
            AssertMsgFailed(("VBOXSF: MRxLocks: Unsupported lock/unlock type %d detected!\n",
                             LowIoContext->Operation));
            return STATUS_NOT_IMPLEMENTED;

        case LOWIO_OP_UNLOCK_MULTIPLE:
            /* @todo Remove multiple locks listed in LowIoContext.ParamsFor.Locks.LockList. */
            Log(("VBOXSF: MRxLocks: Unsupported LOWIO_OP_UNLOCK_MULTIPLE!\n",
                 LowIoContext->Operation));
            return STATUS_NOT_IMPLEMENTED;

        case LOWIO_OP_SHAREDLOCK:
            fu32Lock = SHFL_LOCK_SHARED | SHFL_LOCK_PARTIAL;
            break;

        case LOWIO_OP_EXCLUSIVELOCK:
            fu32Lock = SHFL_LOCK_EXCLUSIVE | SHFL_LOCK_PARTIAL;
            break;

        case LOWIO_OP_UNLOCK:
            fu32Lock = SHFL_LOCK_CANCEL | SHFL_LOCK_PARTIAL;
            break;
    }

    if (LowIoContext->ParamsFor.Locks.Flags & LOWIO_LOCKSFLAG_FAIL_IMMEDIATELY)
        fu32Lock |= SHFL_LOCK_NOWAIT;
    else
        fu32Lock |= SHFL_LOCK_WAIT;

    vboxRC = vboxCallLock(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
                          LowIoContext->ParamsFor.Locks.ByteOffset, LowIoContext->ParamsFor.Locks.Length, fu32Lock);

    Status = VBoxErrorToNTStatus(vboxRC);

    Log(("VBOXSF: MRxLocks: Returned 0x%08X\n", Status));
    return Status;
}
Example #4
0
NTSTATUS VBoxMRxCloseSrvOpen(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);
    PMRX_SRV_OPEN pSrvOpen = capFobx->pSrvOpen;

    int vboxRC = 0;
    PUNICODE_STRING RemainingName = NULL;

    Log(("VBOXSF: MRxCloseSrvOpen: capFcb = %p, capFobx = %p, pVBoxFobx = %p, pSrvOpen = %p\n",
          capFcb, capFobx, pVBoxFobx, pSrvOpen));

    RemainingName = pSrvOpen->pAlreadyPrefixedName;

    Log(("VBOXSF: MRxCloseSrvOpen: Remaining name = %.*ls, Len = %d\n",
         RemainingName->Length / sizeof(WCHAR), RemainingName->Buffer, RemainingName->Length));

    if (NULL == pVBoxFobx)
    {
        return STATUS_INVALID_PARAMETER;
    }

    if (FlagOn(pSrvOpen->Flags, (SRVOPEN_FLAG_FILE_RENAMED | SRVOPEN_FLAG_FILE_DELETED)))
    {
        /* If we renamed or delete the file/dir, then it's already closed */
        Assert(pVBoxFobx->hFile == SHFL_HANDLE_NIL);
        Log(("VBOXSF: MRxCloseSrvOpen: File was renamed, handle 0x%RX64 ignore close.\n",
             pVBoxFobx->hFile));
        return STATUS_SUCCESS;
    }

    /* Close file */
    if (pVBoxFobx->hFile != SHFL_HANDLE_NIL)
    {
        vbsfCloseFileHandle(pDeviceExtension, pNetRootExtension, pVBoxFobx);
    }

    if (capFcb->FcbState & FCB_STATE_DELETE_ON_CLOSE)
    {
        Log(("VBOXSF: MRxCloseSrvOpen: Delete on close. Open count = %d\n",
             capFcb->OpenCount));

        /* Remove file or directory if delete action is pending. */
        if (capFcb->OpenCount == 0)
        {
            Status = vbsfRemove(RxContext);
        }
    }

    return Status;
}
Example #5
0
File: file.c Project: carmark/vbox
NTSTATUS VBoxMRxFlush (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);

    int vboxRC;

    Log(("VBOXSF: MRxFlush\n"));

    /* Do the actual flushing of file buffers */
    vboxRC = vboxCallFlush(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile);

    Status = VBoxErrorToNTStatus(vboxRC);

    Log(("VBOXSF: MRxFlush: Returned 0x%08X\n", Status));
    return Status;
}
Example #6
0
NTSTATUS VBoxMRxCreateVNetRoot(IN PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext)
{
    NTSTATUS Status;

    PMRX_V_NET_ROOT pVNetRoot = (PMRX_V_NET_ROOT)pCreateNetRootContext->pVNetRoot;

    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(pCreateNetRootContext->RxContext);
    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(pVNetRoot->pNetRoot);

    PMRX_NET_ROOT pNetRoot = pVNetRoot->pNetRoot;
    PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;

    BOOLEAN fInitializeNetRoot = FALSE;

    Log(("VBOXSF: MRxCreateVNetRoot: pNetRoot = %p, pNetRootExtension = %p, name = [%.*ls]\n",
         pNetRoot, pNetRootExtension, pNetRoot->pNetRootName->Length / sizeof(WCHAR), pNetRoot->pNetRootName->Buffer));

    /* IMPORTANT:
     *
     * This function must always call 'pCreateNetRootContext->Callback(pCreateNetRootContext)' before
     * returning and then return STATUS_PENDING. Otherwise Win64 will hang.
     */

    if (pNetRoot->Type == NET_ROOT_PIPE)
    {
        /* VBoxSF claims everything which starts with '\vboxsrv'.
         *
         * So sometimes the system tries to open \vboxsrv\ipc$ pipe for DFS
         * and fails the application call if an unexpected code is returned.
         *
         * According to MSDN: The Windows client returns STATUS_MORE_PROCESSING_REQUIRED to the calling
         * application to indicate that the path does not correspond to a DFS Namespace.
         */
        pVNetRoot->Context = NULL;

        if (pNetRoot->pNetRootName->Length >= 13 * sizeof (WCHAR)) /* Number of bytes in '\vboxsrv\ipc$' unicode string. */
        {
            const WCHAR *Suffix = &pNetRoot->pNetRootName->Buffer[8]; /* Number of chars in '\vboxsrv' */

            if (   Suffix[0] == L'\\'
                && (Suffix[1] == L'I' || Suffix[1] == L'i')
                && (Suffix[2] == L'P' || Suffix[2] == L'p')
                && (Suffix[3] == L'C' || Suffix[3] == L'c')
                && Suffix[4] == L'$'
               )
            {
                if (   pNetRoot->pNetRootName->Length == 13 * sizeof (WCHAR)
                    || (Suffix[5] == L'\\' || Suffix[5] == 0)
                   )
                {
                    /* It is '\vboxsrv\IPC$[\*]'. */
                    Log(("VBOXSF: MRxCreateVNetRoot: IPC$\n"));
                    Status = STATUS_MORE_PROCESSING_REQUIRED;
                    goto l_Exit;
                }
            }
        }

        /* Fail all other pipe open requests. */
        Log(("VBOXSF: MRxCreateVNetRoot: Pipe open not supported!\n"));
        Status = STATUS_NOT_SUPPORTED;
        goto l_Exit;
    }
    else if (pNetRoot->Type == NET_ROOT_MAILSLOT)
    {
        Log(("VBOXSF: MRxCreateVNetRoot: Mailslot open not supported!\n"));
        pVNetRoot->Context = NULL;
        Status = STATUS_NOT_SUPPORTED;
        goto l_Exit;
    }

    if (!pNetRoot->Context)
    {
        /* MRxNetRootSize is not zero in VBoxSF, so it is expected
         * that the Context, which is NetRootExtension, is already allocated.
         */
        Log(("VBOXSF: MRxCreateVNetRoot: NULL netroot context\n"));
        pVNetRoot->Context = NULL;
        Status = STATUS_NOT_SUPPORTED;
        goto l_Exit;
    }

    /* Detect an already initialized NetRoot.
     * pNetRootExtension is actually the pNetRoot->Context and it is not NULL.
     */
    fInitializeNetRoot = (pNetRootExtension->phgcmClient == NULL);

    Status = STATUS_SUCCESS;

    if (fInitializeNetRoot)
    {
        PWCHAR pRootName;
        ULONG RootNameLength;
        int vboxRC;
        PSHFLSTRING ParsedPath = 0;

        Log(("VBOXSF: MRxCreateVNetRoot: initialize NET_ROOT\n"));

        pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_GOOD;

        RootNameLength = pNetRoot->pNetRootName->Length - pSrvCall->pSrvCallName->Length;
        if (RootNameLength < sizeof(WCHAR))
        {
            /* Refuse a netroot path with an empty shared folder name */
            Log(("VBOXSF: MRxCreateVNetRoot: Empty shared folder name!\n"));
            pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_ERROR;

            Status = STATUS_BAD_NETWORK_NAME;
            goto l_Exit;
        }

        RootNameLength -= sizeof(WCHAR); /* Remove leading backslash. */
        pRootName = (PWCHAR)(pNetRoot->pNetRootName->Buffer + (pSrvCall->pSrvCallName->Length / sizeof(WCHAR)));
        pRootName++; /* Remove leading backslash. */

        /* Strip the trailing \0. Sometimes there is one, sometimes not... */
        if (   RootNameLength >= sizeof(WCHAR)
            && pRootName[RootNameLength / sizeof(WCHAR) - 1] == 0)
            RootNameLength -= sizeof(WCHAR);

        if (!pNetRootExtension->phgcmClient)
        {
            Log(("VBOXSF: MRxCreateVNetRoot: Initialize netroot length = %d, name = %.*ls\n",
                 RootNameLength, RootNameLength / sizeof(WCHAR), pRootName));

            Status = vbsfShflStringFromUnicodeAlloc(&ParsedPath, pRootName, (uint16_t)RootNameLength);
            if (Status != STATUS_SUCCESS)
            {
                goto l_Exit;
            }

            vboxRC = VbglR0SfMapFolder(&pDeviceExtension->hgcmClient, ParsedPath, &pNetRootExtension->map);
            vbsfFreeNonPagedMem(ParsedPath);
            if (vboxRC != VINF_SUCCESS)
            {
                Log(("VBOXSF: MRxCreateVNetRoot: VbglR0SfMapFolder failed with %d\n", vboxRC));
                Status = STATUS_BAD_NETWORK_NAME;
            }
            else
            {
                Status = STATUS_SUCCESS;
                pNetRootExtension->phgcmClient = &pDeviceExtension->hgcmClient;
            }
        }
    }
    else
        Log(("VBOXSF: MRxCreateVNetRoot: Creating V_NET_ROOT on existing NET_ROOT!\n"));

    vbsfUpdateNetRoot(pNetRoot);

l_Exit:
    if (Status != STATUS_PENDING)
    {
        Log(("VBOXSF: MRxCreateVNetRoot: Returning 0x%08X\n", Status));
        pCreateNetRootContext->VirtualNetRootStatus = Status;
        if (fInitializeNetRoot)
            pCreateNetRootContext->NetRootStatus = Status;
        else
            pCreateNetRootContext->NetRootStatus = STATUS_SUCCESS;

        /* Inform RDBSS. */
        pCreateNetRootContext->Callback(pCreateNetRootContext);

        /* RDBSS expects this. */
        Status = STATUS_PENDING;
    }

    Log(("VBOXSF: MRxCreateVNetRoot: Returned STATUS_PENDING\n"));
    return Status;
}
Example #7
0
File: file.c Project: carmark/vbox
static NTSTATUS vbsfWriteInternal(IN PRX_CONTEXT RxContext)
{
    NTSTATUS Status = STATUS_SUCCESS;
    VBSFTRANSFERCTX ctx;

    RxCaptureFcb;
    RxCaptureFobx;

    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);

    PLOWIO_CONTEXT LowIoContext  = &RxContext->LowIoContext;

    PMDL BufferMdl = LowIoContext->ParamsFor.ReadWrite.Buffer;
    uint32_t ByteCount = LowIoContext->ParamsFor.ReadWrite.ByteCount;
    RXVBO ByteOffset = LowIoContext->ParamsFor.ReadWrite.ByteOffset;

    PVOID pbUserBuffer = RxLowIoGetBufferAddress(RxContext);

    int vboxRC;

    BOOLEAN AsyncIo = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
    LONGLONG FileSize;

    RxGetFileSizeWithLock((PFCB)capFcb, &FileSize);

    Log(("VBOXSF: vbsfWriteInternal: AsyncIo = %d, Fcb->FileSize = 0x%RX64\n",
         AsyncIo, capFcb->Header.FileSize.QuadPart));
    Log(("VBOXSF: vbsfWriteInternal: UserBuffer %p, BufferMdl %p\n",
         pbUserBuffer, BufferMdl));
    Log(("VBOXSF: vbsfWriteInternal: ByteCount is 0x%X, ByteOffset is 0x%RX64, FileSize 0x%RX64\n",
         ByteCount, ByteOffset, FileSize));

    /* @todo allow to write 0 bytes. */
    if (   !BufferMdl
        || ByteCount == 0)
    {
        AssertFailed();
        return STATUS_INVALID_PARAMETER;
    }

    ctx.pClient = &pDeviceExtension->hgcmClient;
    ctx.pMap    = &pNetRootExtension->map;
    ctx.hFile   = pVBoxFobx->hFile;
    ctx.offset  = (uint64_t)ByteOffset;
    ctx.cbData  = ByteCount;
    ctx.pMdl    = BufferMdl;
    ctx.pBuffer = (uint8_t *)pbUserBuffer;
    ctx.fLocked = true;
    ctx.pfnTransferBuffer = vbsfTransferBufferWrite;
    ctx.pfnTransferPages = vbsfTransferPagesWrite;

    vboxRC = vbsfTransferCommon(&ctx);

    ByteCount = ctx.cbData;

    Status = VBoxErrorToNTStatus(vboxRC);

    if (Status != STATUS_SUCCESS)
    {
        /* Nothing written. */
        ByteCount = 0;
    }

    RxContext->InformationToReturn = ByteCount;

    Log(("VBOXSF: vbsfWriteInternal: Status = 0x%08X, ByteCount = 0x%X\n",
         Status, ByteCount));

    return Status;
}
Example #8
0
File: file.c Project: carmark/vbox
static NTSTATUS vbsfReadInternal(IN PRX_CONTEXT RxContext)
{
    NTSTATUS Status = STATUS_SUCCESS;
    VBSFTRANSFERCTX ctx;

    RxCaptureFcb;
    RxCaptureFobx;

    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
    PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);

    PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;

    PMDL BufferMdl = LowIoContext->ParamsFor.ReadWrite.Buffer;
    uint32_t ByteCount = LowIoContext->ParamsFor.ReadWrite.ByteCount;
    RXVBO ByteOffset = LowIoContext->ParamsFor.ReadWrite.ByteOffset;

    PVOID pbUserBuffer = RxLowIoGetBufferAddress(RxContext);

    int vboxRC;

    BOOLEAN AsyncIo = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
    LONGLONG FileSize;

    RxGetFileSizeWithLock((PFCB)capFcb, &FileSize);

    Log(("VBOXSF: vbsfReadInternal: AsyncIo = %d, Fcb->FileSize = 0x%RX64\n",
         AsyncIo, capFcb->Header.FileSize.QuadPart));
    Log(("VBOXSF: vbsfReadInternal: UserBuffer %p, BufferMdl %p\n",
         pbUserBuffer, BufferMdl));
    Log(("VBOXSF: vbsfReadInternal: ByteCount 0x%X, ByteOffset 0x%RX64, FileSize 0x%RX64\n",
         ByteCount, ByteOffset, FileSize));

    /* @todo check if this is necessary. */
#ifdef FCB_STATE_READCACHING_ENABLED    /* Correct spelling for Vista 6001 SDK. */
    if (!FlagOn(capFcb->FcbState, FCB_STATE_READCACHING_ENABLED))
#else
    if (!FlagOn(capFcb->FcbState, FCB_STATE_READCACHEING_ENABLED))
#endif
    {
        if (ByteOffset >= FileSize)
        {
            Log(("VBOXSF: vbsfReadInternal: EOF\n"));
            return STATUS_END_OF_FILE;
        }

        if (ByteCount > FileSize - ByteOffset)
            ByteCount = (ULONG)(FileSize - ByteOffset);
    }

    /* @todo read 0 bytes == always success? */
    if (   !BufferMdl
        || ByteCount == 0)
    {
        AssertFailed();
        return STATUS_INVALID_PARAMETER;
    }

    ctx.pClient = &pDeviceExtension->hgcmClient;
    ctx.pMap    = &pNetRootExtension->map;
    ctx.hFile   = pVBoxFobx->hFile;
    ctx.offset  = (uint64_t)ByteOffset;
    ctx.cbData  = ByteCount;
    ctx.pMdl    = BufferMdl;
    ctx.pBuffer = (uint8_t *)pbUserBuffer;
    ctx.fLocked = true;
    ctx.pfnTransferBuffer = vbsfTransferBufferRead;
    ctx.pfnTransferPages = vbsfTransferPagesRead;

    vboxRC = vbsfTransferCommon(&ctx);

    ByteCount = ctx.cbData;

    Status = VBoxErrorToNTStatus(vboxRC);

    if (Status != STATUS_SUCCESS)
    {
        /* Nothing read. */
        ByteCount = 0;
    }

    RxContext->InformationToReturn = ByteCount;

    Log(("VBOXSF: vbsfReadInternal: Status = 0x%08X, ByteCount = 0x%X\n",
         Status, ByteCount));

    return Status;
}
Example #9
0
NTSTATUS vbsfRename(IN PRX_CONTEXT RxContext,
                       IN FILE_INFORMATION_CLASS FileInformationClass,
                       IN PVOID pBuffer,
                       IN ULONG BufferLength)
{
    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);
    PMRX_SRV_OPEN pSrvOpen = capFobx->pSrvOpen;

    PFILE_RENAME_INFORMATION RenameInformation = (PFILE_RENAME_INFORMATION)RxContext->Info.Buffer;
    PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME(pSrvOpen, capFcb);

    int vboxRC;
    PSHFLSTRING SrcPath = 0, DestPath = 0;
    ULONG ParsedPathSize, flags;

    Assert(FileInformationClass == FileRenameInformation);

    Log(("VBOXSF: vbsfRename: FileName = %.*ls\n",
         RenameInformation->FileNameLength / sizeof(WCHAR), &RenameInformation->FileName[0]));

    /* Must close the file before renaming it! */
    if (pVBoxFobx->hFile != SHFL_HANDLE_NIL)
    {
        vbsfCloseFileHandle(pDeviceExtension, pNetRootExtension, pVBoxFobx);
    }

    /* Mark it as renamed, so we do nothing during close */
    SetFlag(pSrvOpen->Flags, SRVOPEN_FLAG_FILE_RENAMED);

    /* Calculate length required for destination path. */
    ParsedPathSize = sizeof(*DestPath) + (RenameInformation->FileNameLength + sizeof(WCHAR));

    Log(("VBOXSF: vbsfRename: ParsedPathSize = %d\n",
         ParsedPathSize));

    DestPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);

    if (NULL == DestPath)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory(DestPath, ParsedPathSize);
    ShflStringInitBuffer(DestPath, ParsedPathSize - sizeof(SHFLSTRING));

    Log(("VBOXSF: vbsfRename: Setting up destination path\n"));

    DestPath->u16Size = (USHORT)(RenameInformation->FileNameLength + sizeof(WCHAR));
    DestPath->u16Length = DestPath->u16Size - sizeof(WCHAR); /* without terminating null */
    RtlCopyMemory(DestPath->String.ucs2, RenameInformation->FileName, DestPath->u16Length);

    Log(("VBOXSF: vbsfRename: Destination path = %.*ls\n",
         DestPath->u16Length / sizeof(WCHAR), &DestPath->String.ucs2[0]));

    /* Calculate length required for source path */
    ParsedPathSize = sizeof(*DestPath) + (RemainingName->Length + sizeof(WCHAR));

    Log(("VBOXSF: vbsfRename: ParsedPathSize = %d\n", ParsedPathSize));

    SrcPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);

    if (NULL == SrcPath)
    {
        vbsfFreeNonPagedMem(DestPath);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory(SrcPath, ParsedPathSize);
    ShflStringInitBuffer(SrcPath, ParsedPathSize - sizeof(SHFLSTRING));

    Log(("VBOXSF: vbsfRename: Setting up source path\n"));

    SrcPath->u16Size = RemainingName->Length + sizeof(WCHAR);
    SrcPath->u16Length = SrcPath->u16Size - sizeof(WCHAR); /* without terminating null */
    RtlCopyMemory(SrcPath->String.ucs2, RemainingName->Buffer, SrcPath->u16Length);

    Log(("VBOXSF: vbsfRename: Source path = %.*ls\n",
         SrcPath->u16Length / sizeof(WCHAR), &SrcPath->String.ucs2[0]));

    /* Call host. */
    flags = pVBoxFobx->FileStandardInfo.Directory? SHFL_RENAME_DIR : SHFL_RENAME_FILE;
    if (RenameInformation->ReplaceIfExists)
    {
        flags |= SHFL_RENAME_REPLACE_IF_EXISTS;
    }

    Log(("VBOXSF: vbsfRename: Calling vboxCallRename\n"));
    vboxRC = vboxCallRename(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, SrcPath, DestPath, flags);

    vbsfFreeNonPagedMem(SrcPath);
    vbsfFreeNonPagedMem(DestPath);

    Status = VBoxErrorToNTStatus(vboxRC);
    if (vboxRC != VINF_SUCCESS)
    {
        Log(("VBOXSF: vbsfRename: vboxCallRename failed with %Rrc\n",
             vboxRC));
    }

    Log(("VBOXSF: vbsfRename: Returned 0x%08X\n",
         Status));
    return Status;
}
Example #10
0
NTSTATUS vbsfRemove(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 RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);

    int vboxRC;
    PSHFLSTRING ParsedPath = NULL;
    ULONG ParsedPathSize;

    Log(("VBOXSF: vbsfRemove: Delete %.*ls. open count = %d\n",
         RemainingName->Length / sizeof(WCHAR), RemainingName->Buffer, capFcb->OpenCount));

    /* Close file first if not already done. */
    if (pVBoxFobx->hFile != SHFL_HANDLE_NIL)
    {
        vbsfCloseFileHandle(pDeviceExtension, pNetRootExtension, pVBoxFobx);
    }

    /* Calculate length required for parsed path.
     */
    ParsedPathSize = sizeof(*ParsedPath) + (RemainingName->Length + sizeof(WCHAR));

    Log(("VBOXSF: vbsfRemove: ParsedPathSize %d\n",
         ParsedPathSize));

    ParsedPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);
    if (!ParsedPath)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    ShflStringInitBuffer(ParsedPath, ParsedPathSize - sizeof(SHFLSTRING));

    Log(("VBOXSF: vbsfRemove: Setup ParsedPath\n"));
    ParsedPath->u16Size = RemainingName->Length + sizeof(WCHAR);
    ParsedPath->u16Length = ParsedPath->u16Size - sizeof(WCHAR); /* without terminating null */
    RtlCopyMemory(ParsedPath->String.ucs2, RemainingName->Buffer, ParsedPath->u16Length);

    /* Call host. */
    vboxRC = vboxCallRemove(&pDeviceExtension->hgcmClient, &pNetRootExtension->map,
                            ParsedPath,
                            (pVBoxFobx->FileStandardInfo.Directory) ? SHFL_REMOVE_DIR : SHFL_REMOVE_FILE);

    if (ParsedPath)
    {
        vbsfFreeNonPagedMem(ParsedPath);
    }

    if (vboxRC == VINF_SUCCESS)
    {
        SetFlag(capFobx->pSrvOpen->Flags, SRVOPEN_FLAG_FILE_DELETED);
    }

    Status = VBoxErrorToNTStatus(vboxRC);
    if (vboxRC != VINF_SUCCESS)
    {
        Log(("VBOXSF: vbsfRemove: vboxCallRemove failed with %Rrc\n",
             vboxRC));
    }

    Log(("VBOXSF: vbsfRemove: Returned 0x%08X\n",
         Status));
    return Status;
}
Example #11
0
static NTSTATUS vbsfProcessCreate(PRX_CONTEXT RxContext,
                                  PUNICODE_STRING RemainingName,
                                  FILE_BASIC_INFORMATION *pFileBasicInfo,
                                  FILE_STANDARD_INFORMATION *pFileStandardInfo,
                                  PVOID EaBuffer,
                                  ULONG EaLength,
                                  ULONG *pulCreateAction,
                                  SHFLHANDLE *pHandle)
{
    NTSTATUS Status = STATUS_SUCCESS;

    RxCaptureFcb;

    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);

    int vboxRC = VINF_SUCCESS;

    /* Various boolean flags. */
    struct
    {
        ULONG CreateDirectory :1;
        ULONG OpenDirectory :1;
        ULONG DirectoryFile :1;
        ULONG NonDirectoryFile :1;
        ULONG DeleteOnClose :1;
        ULONG TemporaryFile :1;
    } bf;

    ACCESS_MASK DesiredAccess;
    ULONG Options;
    UCHAR FileAttributes;
    ULONG ShareAccess;
    ULONG CreateDisposition;
    SHFLCREATEPARMS *pCreateParms = NULL;

    if (EaLength)
    {
        Log(("VBOXSF: vbsfProcessCreate: Unsupported: extended attributes!\n"));
        Status = STATUS_NOT_SUPPORTED;
        goto failure;
    }

    if (BooleanFlagOn(capFcb->FcbState, FCB_STATE_PAGING_FILE))
    {
        Log(("VBOXSF: vbsfProcessCreate: Unsupported: paging file!\n"));
        Status = STATUS_NOT_IMPLEMENTED;
        goto failure;
    }

    Log(("VBOXSF: vbsfProcessCreate: FileAttributes = 0x%08x\n",
         RxContext->Create.NtCreateParameters.FileAttributes));
    Log(("VBOXSF: vbsfProcessCreate: CreateOptions = 0x%08x\n",
         RxContext->Create.NtCreateParameters.CreateOptions));

    RtlZeroMemory (&bf, sizeof (bf));

    DesiredAccess = RxContext->Create.NtCreateParameters.DesiredAccess;
    Options = RxContext->Create.NtCreateParameters.CreateOptions & FILE_VALID_OPTION_FLAGS;
    FileAttributes = (UCHAR)(RxContext->Create.NtCreateParameters.FileAttributes & ~FILE_ATTRIBUTE_NORMAL);
    ShareAccess = RxContext->Create.NtCreateParameters.ShareAccess;

    /* We do not support opens by file ids. */
    if (FlagOn(Options, FILE_OPEN_BY_FILE_ID))
    {
        Log(("VBOXSF: vbsfProcessCreate: Unsupported: file open by id!\n"));
        Status = STATUS_NOT_IMPLEMENTED;
        goto failure;
    }

    /* Mask out unsupported attribute bits. */
    FileAttributes &= (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE);

    bf.DirectoryFile = BooleanFlagOn(Options, FILE_DIRECTORY_FILE);
    bf.NonDirectoryFile = BooleanFlagOn(Options, FILE_NON_DIRECTORY_FILE);
    bf.DeleteOnClose = BooleanFlagOn(Options, FILE_DELETE_ON_CLOSE);
    if (bf.DeleteOnClose)
        Log(("VBOXSF: vbsfProcessCreate: Delete on close!\n"));

    CreateDisposition = RxContext->Create.NtCreateParameters.Disposition;

    bf.CreateDirectory = (BOOLEAN)(bf.DirectoryFile && ((CreateDisposition == FILE_CREATE) || (CreateDisposition == FILE_OPEN_IF)));
    bf.OpenDirectory = (BOOLEAN)(bf.DirectoryFile && ((CreateDisposition == FILE_OPEN) || (CreateDisposition == FILE_OPEN_IF)));
    bf.TemporaryFile = BooleanFlagOn(RxContext->Create.NtCreateParameters.FileAttributes, FILE_ATTRIBUTE_TEMPORARY);

    if (FlagOn(capFcb->FcbState, FCB_STATE_TEMPORARY))
        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));

    /* Check consistency in specified flags. */
    if (bf.TemporaryFile && bf.CreateDirectory) /* Directories with temporary flag set are not allowed! */
    {
        Log(("VBOXSF: vbsfProcessCreate: Not allowed: Temporary directories!\n"));
        Status = STATUS_INVALID_PARAMETER;
        goto failure;
    }

    if (bf.DirectoryFile && bf.NonDirectoryFile)
    {
        Log(("VBOXSF: vbsfProcessCreate: Unsupported combination: dir && !dir\n"));
        Status = STATUS_INVALID_PARAMETER;
        goto failure;
    }

    /* Initialize create parameters. */
    pCreateParms = (SHFLCREATEPARMS *)vbsfAllocNonPagedMem(sizeof(SHFLCREATEPARMS));
    if (!pCreateParms)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto failure;
    }

    RtlZeroMemory(pCreateParms, sizeof (SHFLCREATEPARMS));

    pCreateParms->Handle = SHFL_HANDLE_NIL;
    pCreateParms->Result = SHFL_NO_RESULT;

    if (bf.DirectoryFile)
    {
        if (CreateDisposition != FILE_CREATE && CreateDisposition != FILE_OPEN && CreateDisposition != FILE_OPEN_IF)
        {
            Log(("VBOXSF: vbsfProcessCreate: Invalid disposition 0x%08X for directory!\n",
                 CreateDisposition));
            Status = STATUS_INVALID_PARAMETER;
            goto failure;
        }

        pCreateParms->CreateFlags |= SHFL_CF_DIRECTORY;
    }

    Log(("VBOXSF: vbsfProcessCreate: CreateDisposition = 0x%08X\n",
         CreateDisposition));

    switch (CreateDisposition)
    {
        case FILE_SUPERSEDE:
            pCreateParms->CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
            Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW\n"));
            break;

        case FILE_OPEN:
            pCreateParms->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
            Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW\n"));
            break;

        case FILE_CREATE:
            pCreateParms->CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
            Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW\n"));
            break;

        case FILE_OPEN_IF:
            pCreateParms->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
            Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW\n"));
            break;

        case FILE_OVERWRITE:
            pCreateParms->CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
            Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW\n"));
            break;

        case FILE_OVERWRITE_IF:
            pCreateParms->CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
            Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW\n"));
            break;

        default:
            Log(("VBOXSF: vbsfProcessCreate: Unexpected create disposition: 0x%08X\n",
                 CreateDisposition));
            Status = STATUS_INVALID_PARAMETER;
            goto failure;
    }

    Log(("VBOXSF: vbsfProcessCreate: DesiredAccess = 0x%08X\n",
         DesiredAccess));
    Log(("VBOXSF: vbsfProcessCreate: ShareAccess   = 0x%08X\n",
         ShareAccess));

    if (DesiredAccess & FILE_READ_DATA)
    {
        Log(("VBOXSF: vbsfProcessCreate: FILE_READ_DATA\n"));
        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_READ;
    }

    if (DesiredAccess & FILE_WRITE_DATA)
    {
        Log(("VBOXSF: vbsfProcessCreate: FILE_WRITE_DATA\n"));
        /* FILE_WRITE_DATA means write access regardless of FILE_APPEND_DATA bit.
         */
        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_WRITE;
    }
    else if (DesiredAccess & FILE_APPEND_DATA)
    {
        Log(("VBOXSF: vbsfProcessCreate: FILE_APPEND_DATA\n"));
        /* FILE_APPEND_DATA without FILE_WRITE_DATA means append only mode.
         *
         * Both write and append access flags are required for shared folders,
         * as on Windows FILE_APPEND_DATA implies write access.
         */
        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_WRITE | SHFL_CF_ACCESS_APPEND;
    }

    if (DesiredAccess & FILE_READ_ATTRIBUTES)
        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_ATTR_READ;
    if (DesiredAccess & FILE_WRITE_ATTRIBUTES)
        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_ATTR_WRITE;

    if (ShareAccess & (FILE_SHARE_READ | FILE_SHARE_WRITE))
        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_DENYNONE;
    else if (ShareAccess & FILE_SHARE_READ)
        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_DENYWRITE;
    else if (ShareAccess & FILE_SHARE_WRITE)
        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_DENYREAD;
    else pCreateParms->CreateFlags |= SHFL_CF_ACCESS_DENYALL;

    /* Set initial allocation size. */
    pCreateParms->Info.cbObject = RxContext->Create.NtCreateParameters.AllocationSize.QuadPart;

    if (FileAttributes == 0)
        FileAttributes = FILE_ATTRIBUTE_NORMAL;

    pCreateParms->Info.Attr.fMode = NTToVBoxFileAttributes(FileAttributes);

    {
        PSHFLSTRING ParsedPath;
        ULONG ParsedPathSize;

        /* Calculate length required for parsed path.
         */
        ParsedPathSize = sizeof(*ParsedPath) + (RemainingName->Length + sizeof(WCHAR));

        Log(("VBOXSF: vbsfProcessCreate: ParsedPathSize = %d\n",
             ParsedPathSize));

        ParsedPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);
        if (ParsedPath == NULL)
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            goto failure;
        }

        ShflStringInitBuffer(ParsedPath, ParsedPathSize - sizeof(SHFLSTRING));

        ParsedPath->u16Size = RemainingName->Length + sizeof(WCHAR);
        ParsedPath->u16Length = ParsedPath->u16Size - sizeof(WCHAR); /* without terminating null */
        RtlCopyMemory (ParsedPath->String.ucs2, RemainingName->Buffer, ParsedPath->u16Length);
        Log(("VBOXSF: ParsedPath: %.*ls\n",
             ParsedPath->u16Length / sizeof(WCHAR), ParsedPath->String.ucs2));

        /* Call host. */
        Log(("VBOXSF: vbsfProcessCreate: vboxCallCreate called.\n"));
        vboxRC = vboxCallCreate(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, ParsedPath, pCreateParms);

        vbsfFreeNonPagedMem(ParsedPath);
    }

    Log(("VBOXSF: vbsfProcessCreate: vboxCallCreate returns vboxRC = %Rrc, Result = 0x%x\n",
         vboxRC, pCreateParms->Result));

    if (RT_FAILURE(vboxRC))
    {
        /* Map some VBoxRC to STATUS codes expected by the system. */
        switch (vboxRC)
        {
            case VERR_ALREADY_EXISTS:
            {
                *pulCreateAction = FILE_EXISTS;
                Status = STATUS_OBJECT_NAME_COLLISION;
                goto failure;
            } break;

            /* On POSIX systems, the "mkdir" command returns VERR_FILE_NOT_FOUND when
               doing a recursive directory create. Handle this case. */
            case VERR_FILE_NOT_FOUND:
            {
                pCreateParms->Result = SHFL_PATH_NOT_FOUND;
            } break;

            default:
            {
                *pulCreateAction = FILE_DOES_NOT_EXIST;
                Status = VBoxErrorToNTStatus(vboxRC);
                goto failure;
            } break;
        }
    }

    /*
     * The request succeeded. Analyze host response,
     */
    switch (pCreateParms->Result)
    {
        case SHFL_PATH_NOT_FOUND:
        {
            /* Path to object does not exist. */
            Log(("VBOXSF: vbsfProcessCreate: Path not found\n"));
            *pulCreateAction = FILE_DOES_NOT_EXIST;
            Status = STATUS_OBJECT_PATH_NOT_FOUND;
            goto failure;
        }

        case SHFL_FILE_NOT_FOUND:
        {
            Log(("VBOXSF: vbsfProcessCreate: File not found\n"));
            *pulCreateAction = FILE_DOES_NOT_EXIST;
            if (pCreateParms->Handle == SHFL_HANDLE_NIL)
            {
                Status = STATUS_OBJECT_NAME_NOT_FOUND;
                goto failure;
            }

            Log(("VBOXSF: vbsfProcessCreate: File not found but have a handle!\n"));
            Status = STATUS_UNSUCCESSFUL;
            goto failure;

            break;
        }

        case SHFL_FILE_EXISTS:
        {
            Log(("VBOXSF: vbsfProcessCreate: File exists, Handle = 0x%RX64\n",
                 pCreateParms->Handle));
            if (pCreateParms->Handle == SHFL_HANDLE_NIL)
            {
                *pulCreateAction = FILE_EXISTS;
                if (CreateDisposition == FILE_CREATE)
                {
                    /* File was not opened because we requested a create. */
                    Status = STATUS_OBJECT_NAME_COLLISION;
                    goto failure;
                }

                /* Actually we should not go here, unless we have no rights to open the object. */
                Log(("VBOXSF: vbsfProcessCreate: Existing file was not opened!\n"));
                Status = STATUS_ACCESS_DENIED;
                goto failure;
            }

            *pulCreateAction = FILE_OPENED;

            /* Existing file was opened. Go check flags and create FCB. */
            break;
        }

        case SHFL_FILE_CREATED:
        {
            /* A new file was created. */

            Assert(pCreateParms->Handle != SHFL_HANDLE_NIL);

            *pulCreateAction = FILE_CREATED;

            /* Go check flags and create FCB. */
            break;
        }

        case SHFL_FILE_REPLACED:
        {
            /* Existing file was replaced or overwriting. */

            Assert(pCreateParms->Handle != SHFL_HANDLE_NIL);

            if (CreateDisposition == FILE_SUPERSEDE)
            {
                *pulCreateAction = FILE_SUPERSEDED;
            }
            else
            {
                *pulCreateAction = FILE_OVERWRITTEN;
            }
            /* Go check flags and create FCB. */
            break;
        }

        default:
        {
            Log(("VBOXSF: vbsfProcessCreate: Invalid CreateResult from host (0x%08X)\n",
                 pCreateParms->Result));
            *pulCreateAction = FILE_DOES_NOT_EXIST;
            Status = STATUS_OBJECT_PATH_NOT_FOUND;
            goto failure;
        }
    }

    /* Check flags. */
    if (bf.NonDirectoryFile && FlagOn(pCreateParms->Info.Attr.fMode, RTFS_DOS_DIRECTORY))
    {
        /* Caller wanted only a file, but the object is a directory. */
        Log(("VBOXSF: vbsfProcessCreate: File is a directory!\n"));
        Status = STATUS_FILE_IS_A_DIRECTORY;
        goto failure;
    }

    if (bf.DirectoryFile && !FlagOn(pCreateParms->Info.Attr.fMode, RTFS_DOS_DIRECTORY))
    {
        /* Caller wanted only a directory, but the object is not a directory. */
        Log(("VBOXSF: vbsfProcessCreate: File is not a directory!\n"));
        Status = STATUS_NOT_A_DIRECTORY;
        goto failure;
    }

    *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;

    vbsfFreeNonPagedMem(pCreateParms);

    return Status;

failure:

    Log(("VBOXSF: vbsfProcessCreate: Returned with status = 0x%08X\n",
          Status));

    if (pCreateParms && pCreateParms->Handle != SHFL_HANDLE_NIL)
    {
        vboxCallClose(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pCreateParms->Handle);
        *pHandle = SHFL_HANDLE_NIL;
    }

    if (pCreateParms)
    {
        vbsfFreeNonPagedMem(pCreateParms);
    }

    return Status;
}