file.c revision f6c43e9fc1e5cc41195ac222ad185905e33fe08d
/** @file
*
* VirtualBox Windows Guest Shared Folders
*
* File System Driver file routines
*/
/*
* 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;
* 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"
/* How much data to transfer in one HGCM request. */
#define VBSF_MAX_READ_WRITE_PAGES 256
typedef FNVBSFTRANSFERBUFFER *PFNVBSFTRANSFERBUFFER;
typedef FNVBSFTRANSFERPAGES *PFNVBSFTRANSFERPAGES;
{
}
{
}
{
return VbglR0SharedFolderReadPageList(pClient, pMap, hFile, offset, pcbBuffer, offFirstPage, cPages, paPages);
}
{
return VbglR0SharedFolderWritePageList(pClient, pMap, hFile, offset, pcbBuffer, offFirstPage, cPages, paPages);
}
typedef struct VBSFTRANSFERCTX
{
bool fLocked;
{
int rc = VINF_SUCCESS;
uint32_t cbTransferred = 0;
if (VbglR0CanUsePhysPageList())
{
Log(("VBOXSF: vbsfTransferCommon: using page list: %d pages, offset 0x%03X\n", cPages, offFirstPage));
if (paPages)
{
ULONG cPagesTransferred = 0;
cbTransferred = 0;
while (cPagesToTransfer != 0)
{
{
}
if (cbToTransfer == 0)
{
/* Nothing to transfer. */
break;
}
cbIO = cbToTransfer;
Log(("VBOXSF: vbsfTransferCommon: transferring %d pages at %d; %d bytes at %d\n",
{
}
if (RT_FAILURE(rc))
{
/* 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;
}
offFirstPage = 0;
{
}
}
fProcessed = TRUE;
}
}
if (fProcessed != TRUE)
{
/* Split large transfers. */
cbTransferred = 0;
/* 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",
if (RT_FAILURE(rc))
{
/* 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;
}
{
}
}
}
return rc;
}
{
int vboxRC;
Log(("VBOXSF: vbsfReadInternal: AsyncIo = %d, Fcb->FileSize = 0x%RX64\n",
Log(("VBOXSF: vbsfReadInternal: UserBuffer %p, BufferMdl %p\n",
Log(("VBOXSF: vbsfReadInternal: ByteCount 0x%X, ByteOffset 0x%RX64, FileSize 0x%RX64\n",
/* @todo check if this is necessary. */
#ifdef FCB_STATE_READCACHING_ENABLED /* Correct spelling for Vista 6001 SDK. */
#else
#endif
{
if (ByteOffset >= FileSize)
{
Log(("VBOXSF: vbsfReadInternal: EOF\n"));
return STATUS_END_OF_FILE;
}
{
}
}
/* @todo read 0 bytes == always success? */
|| ByteCount == 0)
{
AssertFailed();
return STATUS_INVALID_PARAMETER;
}
if (Status != STATUS_SUCCESS)
{
/* Nothing read. */
ByteCount = 0;
}
Log(("VBOXSF: vbsfReadInternal: Status = 0x%08X, ByteCount = 0x%X\n",
return Status;
}
{
Log(("VBOXSF: vbsfReadWorker: calling the worker\n"));
Log(("VBOXSF: vbsfReadWorker: Status 0x%08X\n",
}
{
Log(("VBOXSF: MRxRead: RxDispatchToWorkerThread: Status 0x%08X\n",
Status));
if (Status == STATUS_SUCCESS)
{
}
return Status;
}
{
int vboxRC;
Log(("VBOXSF: vbsfWriteInternal: AsyncIo = %d, Fcb->FileSize = 0x%RX64\n",
Log(("VBOXSF: vbsfWriteInternal: UserBuffer %p, BufferMdl %p\n",
Log(("VBOXSF: vbsfWriteInternal: ByteCount is 0x%X, ByteOffset is 0x%RX64, FileSize 0x%RX64\n",
/* @todo allow to write 0 bytes. */
|| ByteCount == 0)
{
AssertFailed();
return STATUS_INVALID_PARAMETER;
}
if (Status != STATUS_SUCCESS)
{
/* Nothing written. */
ByteCount = 0;
}
Log(("VBOXSF: vbsfWriteInternal: Status = 0x%08X, ByteCount = 0x%X\n",
return Status;
}
{
Log(("VBOXSF: vbsfWriteWorker: calling the worker\n"));
Log(("VBOXSF: vbsfWriteWorker: Status 0x%08X\n",
}
{
Log(("VBOXSF: MRxWrite: RxDispatchToWorkerThread: Status 0x%08X\n",
Status));
if (Status == STATUS_SUCCESS)
{
}
return Status;
}
{
int vboxRC;
Log(("VBOXSF: MRxLocks: Operation %d\n",
switch (LowIoContext->Operation)
{
default:
AssertMsgFailed(("VBOXSF: MRxLocks: Unsupported lock/unlock type %d detected!\n",
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",
return STATUS_NOT_IMPLEMENTED;
case LOWIO_OP_SHAREDLOCK:
break;
case LOWIO_OP_EXCLUSIVELOCK:
break;
case LOWIO_OP_UNLOCK:
break;
}
{
}
else
{
}
Log(("VBOXSF: MRxLocks: Returned 0x%08X\n",
Status));
return Status;
}
{
Log(("VBOXSF: MRxCompleteBufferingStateChangeRequest: not implemented\n"));
return STATUS_NOT_IMPLEMENTED;
}
{
int vboxRC;
Log(("VBOXSF: MRxFlush\n"));
/* Do the actual flushing of file buffers */
Log(("VBOXSF: MRxFlush: Returned 0x%08X\n",
Status));
return Status;
}
{
int vboxRC;
Log(("VBOXSF: vbsfSetEndOfFile: New size = %RX64 (%p), pNewAllocationSize = %p\n",
cbBuffer = sizeof(SHFLFSOBJINFO);
{
AssertFailed();
return STATUS_INSUFFICIENT_RESOURCES;
}
Log(("VBOXSF: vbsfSetEndOfFile: vboxCallFSInfo returned %Rrc\n",
vboxRC));
if (Status == STATUS_SUCCESS)
{
Log(("VBOXSF: vbsfSetEndOfFile: vboxCallFSInfo new allocation size = %RX64\n",
pObjInfo->cbAllocated));
/* Return new allocation size */
}
if (pObjInfo)
{
}
Log(("VBOXSF: vbsfSetEndOfFile: Returned 0x%08X\n",
Status));
return Status;
}
{
/* Note: On Windows hosts vbsfSetEndOfFile returns ACCESS_DENIED if the file has been
* opened in APPEND mode. Writes to a file will extend it anyway, therefore it is
* better to not call the host at all and tell the caller that the file was extended.
*/
Log(("VBOXSF: MRxExtendStub: new size = %RX64\n",
pNewFileSize->QuadPart));
return STATUS_SUCCESS;
}