diff options
Diffstat (limited to 'src/VBox/Additions/WINNT/SharedFolders')
4 files changed, 331 insertions, 33 deletions
diff --git a/src/VBox/Additions/WINNT/SharedFolders/driver/VBoxSF.inf b/src/VBox/Additions/WINNT/SharedFolders/driver/VBoxSF.inf index a178c456..f93d7732 100644 --- a/src/VBox/Additions/WINNT/SharedFolders/driver/VBoxSF.inf +++ b/src/VBox/Additions/WINNT/SharedFolders/driver/VBoxSF.inf @@ -1,7 +1,7 @@ ; ; INF file for installing the VirtualBox Windows guest driver ; -; Copyright (C) 2006-2007 Oracle Corporation +; Copyright (C) 2006-2012 Oracle Corporation ; ; This file is part of VirtualBox Open Source Edition (OSE), as ; available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Additions/WINNT/SharedFolders/driver/file.c b/src/VBox/Additions/WINNT/SharedFolders/driver/file.c index f8101cb5..ba39cb3f 100644 --- a/src/VBox/Additions/WINNT/SharedFolders/driver/file.c +++ b/src/VBox/Additions/WINNT/SharedFolders/driver/file.c @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2012 Oracle Corporation + * Copyright (C) 2012-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -19,10 +19,219 @@ #include "vbsf.h" #include <iprt/fs.h> +#include <iprt/mem.h> + + +/* How much data to transfer in one HGCM request. */ +#define VBSF_MAX_READ_WRITE_PAGES 256 + + +typedef int FNVBSFTRANSFERBUFFER(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile, + uint64_t offset, uint32_t *pcbBuffer, + uint8_t *pBuffer, bool fLocked); +typedef FNVBSFTRANSFERBUFFER *PFNVBSFTRANSFERBUFFER; + +typedef int FNVBSFTRANSFERPAGES(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile, + uint64_t offset, uint32_t *pcbBuffer, + uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages); +typedef FNVBSFTRANSFERPAGES *PFNVBSFTRANSFERPAGES; + + +static int vbsfTransferBufferRead(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile, + uint64_t offset, uint32_t *pcbBuffer, + uint8_t *pBuffer, bool fLocked) +{ + return vboxCallRead(pClient, pMap, hFile, offset, pcbBuffer, pBuffer, fLocked); +} + +static int vbsfTransferBufferWrite(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile, + uint64_t offset, uint32_t *pcbBuffer, + uint8_t *pBuffer, bool fLocked) +{ + return vboxCallWrite(pClient, pMap, hFile, offset, pcbBuffer, pBuffer, fLocked); +} + +static int vbsfTransferPagesRead(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile, + uint64_t offset, uint32_t *pcbBuffer, + uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages) +{ + return VbglR0SharedFolderReadPageList(pClient, pMap, hFile, offset, pcbBuffer, offFirstPage, cPages, paPages); +} + +static int vbsfTransferPagesWrite(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile, + uint64_t offset, uint32_t *pcbBuffer, + uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages) +{ + return VbglR0SharedFolderWritePageList(pClient, pMap, hFile, offset, pcbBuffer, offFirstPage, cPages, paPages); +} + + +typedef struct VBSFTRANSFERCTX +{ + PVBSFCLIENT pClient; + PVBSFMAP pMap; + SHFLHANDLE hFile; + uint64_t offset; + uint32_t cbData; + + PMDL pMdl; + uint8_t *pBuffer; + bool fLocked; + + PFNVBSFTRANSFERBUFFER pfnTransferBuffer; + PFNVBSFTRANSFERPAGES pfnTransferPages; +} VBSFTRANSFERCTX; + + +static int vbsfTransferCommon(VBSFTRANSFERCTX *pCtx) +{ + int rc = VINF_SUCCESS; + BOOLEAN fProcessed = FALSE; + + uint32_t cbTransferred = 0; + + uint32_t cbToTransfer; + uint32_t cbIO; + + if (VbglR0CanUsePhysPageList()) + { + ULONG offFirstPage = MmGetMdlByteOffset(pCtx->pMdl); + ULONG cPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(pCtx->pMdl), pCtx->cbData); + ULONG cPagesToTransfer = RT_MIN(cPages, VBSF_MAX_READ_WRITE_PAGES); + RTGCPHYS64 *paPages = (RTGCPHYS64 *)RTMemTmpAlloc(cPagesToTransfer * sizeof(RTGCPHYS64)); + + Log(("VBOXSF: vbsfTransferCommon: using page list: %d pages, offset 0x%03X\n", cPages, offFirstPage)); + + if (paPages) + { + PPFN_NUMBER paPfns = MmGetMdlPfnArray(pCtx->pMdl); + ULONG cPagesTransferred = 0; + cbTransferred = 0; + + while (cPagesToTransfer != 0) + { + ULONG iPage; + cbToTransfer = cPagesToTransfer * PAGE_SIZE - offFirstPage; + + if (cbToTransfer > pCtx->cbData - cbTransferred) + { + cbToTransfer = pCtx->cbData - cbTransferred; + } + + if (cbToTransfer == 0) + { + /* Nothing to transfer. */ + break; + } + + cbIO = cbToTransfer; + + Log(("VBOXSF: vbsfTransferCommon: transferring %d pages at %d; %d bytes at %d\n", + cPagesToTransfer, cPagesTransferred, cbToTransfer, cbTransferred)); + + for (iPage = 0; iPage < cPagesToTransfer; iPage++) + { + paPages[iPage] = (RTGCPHYS64)paPfns[iPage + cPagesTransferred] << PAGE_SHIFT; + } + + rc = pCtx->pfnTransferPages(pCtx->pClient, pCtx->pMap, pCtx->hFile, + pCtx->offset + cbTransferred, &cbIO, + (uint16_t)offFirstPage, (uint16_t)cPagesToTransfer, paPages); + if (RT_FAILURE(rc)) + { + Log(("VBOXSF: vbsfTransferCommon: pfnTransferPages %Rrc, cbTransferred %d\n", rc, cbTransferred)); + + /* If some data was transferred, then it is no error. */ + if (cbTransferred > 0) + { + rc = VINF_SUCCESS; + } + + break; + } + + cbTransferred += cbIO; + + if (cbToTransfer < cbIO) + { + /* Transferred less than requested, do not continue with the possibly remaining data. */ + break; + } + + cPagesTransferred += cPagesToTransfer; + offFirstPage = 0; + + cPagesToTransfer = cPages - cPagesTransferred; + if (cPagesToTransfer > VBSF_MAX_READ_WRITE_PAGES) + { + cPagesToTransfer = VBSF_MAX_READ_WRITE_PAGES; + } + } + + RTMemTmpFree(paPages); + + fProcessed = TRUE; + } + } + + if (fProcessed != TRUE) + { + /* Split large transfers. */ + cbTransferred = 0; + cbToTransfer = RT_MIN(pCtx->cbData, VBSF_MAX_READ_WRITE_PAGES * PAGE_SIZE); + + /* Page list not supported or a fallback. */ + Log(("VBOXSF: vbsfTransferCommon: using linear address\n")); + + while (cbToTransfer != 0) + { + cbIO = cbToTransfer; + + Log(("VBOXSF: vbsfTransferCommon: transferring %d bytes at %d\n", + cbToTransfer, cbTransferred)); + + rc = pCtx->pfnTransferBuffer(pCtx->pClient, pCtx->pMap, pCtx->hFile, + pCtx->offset + cbTransferred, &cbIO, + pCtx->pBuffer + cbTransferred, true /* locked */); + + if (RT_FAILURE(rc)) + { + Log(("VBOXSF: vbsfTransferCommon: pfnTransferBuffer %Rrc, cbTransferred %d\n", rc, cbTransferred)); + + /* If some data was transferred, then it is no error. */ + if (cbTransferred > 0) + { + rc = VINF_SUCCESS; + } + + break; + } + + cbTransferred += cbIO; + + if (cbToTransfer < cbIO) + { + /* Transferred less than requested, do not continue with the possibly remaining data. */ + break; + } + + cbToTransfer = pCtx->cbData - cbTransferred; + if (cbToTransfer > VBSF_MAX_READ_WRITE_PAGES * PAGE_SIZE) + { + cbToTransfer = VBSF_MAX_READ_WRITE_PAGES * PAGE_SIZE; + } + } + } + + pCtx->cbData = cbTransferred; + + return rc; +} static NTSTATUS vbsfReadInternal(IN PRX_CONTEXT RxContext) { NTSTATUS Status = STATUS_SUCCESS; + VBSFTRANSFERCTX ctx; RxCaptureFcb; RxCaptureFobx; @@ -80,9 +289,20 @@ static NTSTATUS vbsfReadInternal(IN PRX_CONTEXT RxContext) return STATUS_INVALID_PARAMETER; } - /* @todo Split large reads. */ - vboxRC = vboxCallRead(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, - ByteOffset, &ByteCount, (uint8_t *)pbUserBuffer, true /* locked */); + 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); @@ -136,6 +356,7 @@ NTSTATUS VBoxMRxRead(IN PRX_CONTEXT RxContext) static NTSTATUS vbsfWriteInternal(IN PRX_CONTEXT RxContext) { NTSTATUS Status = STATUS_SUCCESS; + VBSFTRANSFERCTX ctx; RxCaptureFcb; RxCaptureFobx; @@ -174,9 +395,20 @@ static NTSTATUS vbsfWriteInternal(IN PRX_CONTEXT RxContext) return STATUS_INVALID_PARAMETER; } - /* @todo Split large writes. */ - vboxRC = vboxCallWrite(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, - ByteOffset, &ByteCount, (uint8_t *)pbUserBuffer, true /* locked */); + 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); @@ -318,7 +550,7 @@ NTSTATUS VBoxMRxFlush (IN PRX_CONTEXT RxContext) Status = VBoxErrorToNTStatus(vboxRC); - Log(("VBOXSF: MRxFlush: Returned 0x%08X\n", + Log(("VBOXSF: MRxFlush: Returned 0x%08X\n", Status)); return Status; } diff --git a/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.c b/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.c index 6381dfe2..35f441e7 100644 --- a/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.c +++ b/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.c @@ -1049,6 +1049,62 @@ NTSTATUS VBoxMRxDevFcbXXXControlFile(IN OUT PRX_CONTEXT RxContext) 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 Status; @@ -1060,24 +1116,29 @@ static HANDLE vbsfOpenConnectionHandle(PUNICODE_STRING ConnectionName) Log(("VBOXSF: vbsfOpenConnectionHandle: ConnectionName = %.*ls\n", ConnectionName->Length / sizeof(WCHAR), ConnectionName->Buffer)); - /* 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); + 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) @@ -1184,7 +1245,7 @@ NTSTATUS vbsfCreateConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp) if (pDeviceExtension->wszLocalConnectionName[idx] == NULL) { - Log(("VBOXSF: vbsfCreateConnection: LocalConnectionName at index %d NOT allocated!\n", + Log(("VBOXSF: vbsfCreateConnection: LocalConnectionName at index %d NOT allocated!\n", idx)); Status = STATUS_INSUFFICIENT_RESOURCES; } @@ -1265,8 +1326,9 @@ NTSTATUS vbsfDeleteConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp) if (NT_SUCCESS(Status)) { PFOBX Fobx = (PFOBX)pFileObject->FsContext2; + Log(("VBOXSF: vbsfDeleteConnection: Fobx %p\n", Fobx)); - if (NodeType(Fobx) == RDBSS_NTC_V_NETROOT) + if (Fobx && NodeType(Fobx) == RDBSS_NTC_V_NETROOT) { PV_NET_ROOT VNetRoot = (PV_NET_ROOT)Fobx; @@ -1328,6 +1390,9 @@ NTSTATUS vbsfDeleteConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp) } ExReleaseFastMutex(&pDeviceExtension->mtxLocalCon); + + Log(("VBOXSF: vbsfDeleteConnection: deleted index 0x%x\n", + idx)); } } } @@ -1338,6 +1403,7 @@ NTSTATUS vbsfDeleteConnection(IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp) } } + Log(("VBOXSF: vbsfDeleteConnection: Status 0x%08X\n", Status)); return Status; } diff --git a/src/VBox/Additions/WINNT/SharedFolders/np/vboxmrxnp.cpp b/src/VBox/Additions/WINNT/SharedFolders/np/vboxmrxnp.cpp index 453c4402..d0500a8d 100644 --- a/src/VBox/Additions/WINNT/SharedFolders/np/vboxmrxnp.cpp +++ b/src/VBox/Additions/WINNT/SharedFolders/np/vboxmrxnp.cpp @@ -258,7 +258,7 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner, } } - + if (dwStatus == WN_SUCCESS) { /* Append the remote name. */ @@ -732,7 +732,7 @@ DWORD APIENTRY NPOpenEnum(DWORD dwScope, if (dwStatus != WN_SUCCESS) { - Log(("VBOXNP: NPOpenEnum: Returned error 0x%08X\n", + Log(("VBOXNP: NPOpenEnum: Returned error 0x%08X\n", dwStatus)); if (pCtx) { @@ -859,7 +859,7 @@ DWORD APIENTRY NPEnumResource(HANDLE hEnum, *pDst++ = L'\\'; CopyMemory(pDst, RemoteName, cbRemoteName); pDst += cbRemoteName / sizeof(WCHAR); - + pNetResource->lpComment = NULL; pNetResource->lpProvider = pDst; @@ -1597,7 +1597,7 @@ BOOL WINAPI DllMain(HINSTANCE hDLLInst, switch (fdwReason) { case DLL_PROCESS_ATTACH: - RTR3InitDll(0); + RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE); VbglR3Init(); LogRel(("VBOXNP: DLL loaded.\n")); break; |
