path.c revision 3c8da05ed8bf0bf8b3b1c67dca89517c92478da0
/** @file
*
* VirtualBox Windows Guest Shared Folders
*
* File System Driver path related routines
*/
/*
* Copyright (C) 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;
* 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"
{
int vboxRC = VINF_SUCCESS;
/* Various boolean flags. */
struct
{
} bf;
if (EaLength)
{
Log(("VBOXSF: vbsfProcessCreate: Unsupported: extended attributes!\n"));
goto failure;
}
{
Log(("VBOXSF: vbsfProcessCreate: Unsupported: paging file!\n"));
goto failure;
}
Log(("VBOXSF: vbsfProcessCreate: FileAttributes = 0x%08x\n",
Log(("VBOXSF: vbsfProcessCreate: CreateOptions = 0x%08x\n",
FileAttributes = (UCHAR)(RxContext->Create.NtCreateParameters.FileAttributes & ~FILE_ATTRIBUTE_NORMAL);
/* We do not support opens by file ids. */
{
Log(("VBOXSF: vbsfProcessCreate: Unsupported: file open by id!\n"));
goto failure;
}
/* Mask out unsupported attribute bits. */
FileAttributes &= (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE);
if (bf.DeleteOnClose)
Log(("VBOXSF: vbsfProcessCreate: Delete on close!\n"));
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);
Log(("VBOXSF: vbsfProcessCreate: bf.TemporaryFile %d, bf.CreateDirectory %d, bf.DirectoryFile = %d\n",
/* 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"));
goto failure;
}
{
Log(("VBOXSF: vbsfProcessCreate: Unsupported combination: dir && !dir\n"));
goto failure;
}
/* Initialize create parameters. */
if (!pCreateParms)
{
goto failure;
}
if (bf.DirectoryFile)
{
if (CreateDisposition != FILE_CREATE && CreateDisposition != FILE_OPEN && CreateDisposition != FILE_OPEN_IF)
{
Log(("VBOXSF: vbsfProcessCreate: Invalid disposition 0x%08X for directory!\n",
goto failure;
}
}
Log(("VBOXSF: vbsfProcessCreate: CreateDisposition = 0x%08X\n",
switch (CreateDisposition)
{
case FILE_SUPERSEDE:
Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW\n"));
break;
case FILE_OPEN:
Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW\n"));
break;
case FILE_CREATE:
Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW\n"));
break;
case FILE_OPEN_IF:
Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW\n"));
break;
case FILE_OVERWRITE:
Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW\n"));
break;
case FILE_OVERWRITE_IF:
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",
goto failure;
}
Log(("VBOXSF: vbsfProcessCreate: DesiredAccess = 0x%08X\n",
Log(("VBOXSF: vbsfProcessCreate: ShareAccess = 0x%08X\n",
ShareAccess));
if (DesiredAccess & FILE_READ_DATA)
{
Log(("VBOXSF: vbsfProcessCreate: FILE_READ_DATA\n"));
}
if (DesiredAccess & FILE_WRITE_DATA)
{
Log(("VBOXSF: vbsfProcessCreate: FILE_WRITE_DATA\n"));
/* FILE_WRITE_DATA means write access regardless of FILE_APPEND_DATA bit.
*/
}
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.
*/
}
else if (ShareAccess & FILE_SHARE_READ)
else if (ShareAccess & FILE_SHARE_WRITE)
/* Set initial allocation size. */
if (FileAttributes == 0)
{
/* Calculate length required for parsed path.
*/
Log(("VBOXSF: vbsfProcessCreate: ParsedPathSize = %d\n",
if (ParsedPath == NULL)
{
goto failure;
}
Log(("VBOXSF: ParsedPath: %.*ls\n",
/* Call host. */
Log(("VBOXSF: vbsfProcessCreate: vboxCallCreate called.\n"));
vboxRC = vboxCallCreate(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, ParsedPath, pCreateParms);
}
Log(("VBOXSF: vbsfProcessCreate: vboxCallCreate returns vboxRC = %Rrc, Result = 0x%x\n",
if (RT_FAILURE(vboxRC))
{
/* Map some VBoxRC to STATUS codes expected by the system. */
switch (vboxRC)
{
case VERR_ALREADY_EXISTS:
{
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:
{
} break;
default:
{
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"));
goto failure;
}
case SHFL_FILE_NOT_FOUND:
{
Log(("VBOXSF: vbsfProcessCreate: File not found\n"));
{
goto failure;
}
Log(("VBOXSF: vbsfProcessCreate: File not found but have a handle!\n"));
goto failure;
break;
}
case SHFL_FILE_EXISTS:
{
Log(("VBOXSF: vbsfProcessCreate: File exists, Handle = 0x%RX64\n",
pCreateParms->Handle));
{
if (CreateDisposition == FILE_CREATE)
{
/* File was not opened because we requested a create. */
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"));
goto failure;
}
/* Existing file was opened. Go check flags and create FCB. */
break;
}
case SHFL_FILE_CREATED:
{
/* A new file was created. */
/* Go check flags and create FCB. */
break;
}
case SHFL_FILE_REPLACED:
{
/* Existing file was replaced or overwriting. */
if (CreateDisposition == FILE_SUPERSEDE)
{
}
else
{
}
/* Go check flags and create FCB. */
break;
}
default:
{
Log(("VBOXSF: vbsfProcessCreate: Invalid CreateResult from host (0x%08X)\n",
pCreateParms->Result));
goto failure;
}
}
/* Check flags. */
{
/* Caller wanted only a file, but the object is a directory. */
Log(("VBOXSF: vbsfProcessCreate: File is a directory!\n"));
goto failure;
}
{
/* Caller wanted only a directory, but the object is not a directory. */
Log(("VBOXSF: vbsfProcessCreate: File is not a directory!\n"));
goto failure;
}
/* Translate attributes */
/* Translate file times */
pFileBasicInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pCreateParms->Info.BirthTime); /* ridiculous name */
{
Log(("VBOXSF: vbsfProcessCreate: AllocationSize = 0x%RX64, EndOfFile = 0x%RX64\n",
}
else
{
}
return Status;
Log(("VBOXSF: vbsfProcessCreate: Returned with status = 0x%08X\n",
Status));
{
}
if (pCreateParms)
{
}
return Status;
}
{
Log(("VBOXSF: MRxCreate: name ptr %p length=%d\n",
if (RemainingName->Length)
{
Log(("VBOXSF: MRxCreate: Attempt to open %.*ls\n",
}
else
{
{
Log(("VBOXSF: MRxCreate: Empty name -> Only backslash used\n"));
}
}
{
Log(("VBOXSF: MRxCreate: netroot type %d not supported\n",
goto Exit;
}
&Handle);
if (Status != STATUS_SUCCESS)
{
Log(("VBOXSF: MRxCreate: vbsfProcessCreate failed 0x%08X\n",
Status));
goto Exit;
}
Log(("VBOXSF: MRxCreate: EOF is 0x%RX64 AllocSize is 0x%RX64\n",
{
Log(("VBOXSF: MRxCreate: RxCreateNetFobx failed\n"));
goto Exit;
}
Log(("VBOXSF: MRxCreate: CreateAction = 0x%08X\n",
CreateAction));
{
}
SrvOpen->BufferingFlags = 0;
Log(("VBOXSF: MRxCreate: VBoxFobx = %p\n",
pVBoxFobx));
if (!pVBoxFobx)
{
Log(("VBOXSF: MRxCreate: no VBoxFobx!\n"));
AssertFailed();
goto Exit;
}
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));
if (!RxIsFcbAcquiredExclusive(capFcb))
{
}
Log(("VBOXSF: MRxCreate: NetRoot is %p, Fcb is %p, SrvOpen is %p, Fobx is %p\n",
Log(("VBOXSF: MRxCreate: return 0x%08X\n",
Status));
Exit:
return Status;
}
{
Log(("VBOXSF: MRxComputeNewBufferingState\n"));
return STATUS_NOT_SUPPORTED;
}
{
Log(("VBOXSF: MRxDeallocateForFcb\n"));
return STATUS_SUCCESS;
}
{
Log(("VBOXSF: MRxDeallocateForFobx\n"));
return STATUS_SUCCESS;
}
{
Log(("VBOXSF: MRxTruncate\n"));
return STATUS_NOT_IMPLEMENTED;
}
{
Log(("VBOXSF: MRxCleanupFobx: pVBoxFobx = %p, Handle = 0x%RX64\n",
{
return STATUS_INVALID_PARAMETER;
}
return STATUS_SUCCESS;
}
{
Log(("VBOXSF: MRxForceClosed\n"));
return STATUS_NOT_IMPLEMENTED;
}
{
int vboxRC;
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));
if (SetAttrFlags == 0)
{
Log(("VBOXSF: vbsfSetFileInfo: nothing to set\n"));
return STATUS_SUCCESS;
}
cbBuffer = sizeof(SHFLFSOBJINFO);
if (pHGCMBuffer == NULL)
{
AssertFailed();
return STATUS_INSUFFICIENT_RESOURCES;
}
/* The properties, that need to be changed, are set to something other than zero */
{
}
{
}
{
}
{
}
{
}
if (vboxRC != VINF_SUCCESS)
{
}
if (pHGCMBuffer)
{
}
Log(("VBOXSF: vbsfSetFileInfo: Returned 0x%08X\n",
Status));
return Status;
}
/*
* Closes an opened file handle of a MRX_VBOX_FOBX.
* Updates file attributes if necessary.
*/
{
int vboxRC;
{
Log(("VBOXSF: vbsfCloseFileHandle: SHFL_HANDLE_NIL\n"));
return STATUS_SUCCESS;
}
Log(("VBOXSF: vbsfCloseFileHandle: 0x%RX64, on close info 0x%02X\n",
{
/* If the file timestamps were set by the user, then update them before closing the handle,
*/
}
if (vboxRC != VINF_SUCCESS)
{
}
Log(("VBOXSF: vbsfCloseFileHandle: Returned 0x%08X\n",
Status));
return Status;
}
{
int vboxRC = 0;
Log(("VBOXSF: MRxCloseSrvOpen: capFcb = %p, capFobx = %p, pVBoxFobx = %p, pSrvOpen = %p\n",
Log(("VBOXSF: MRxCloseSrvOpen: Remaining name = %.*ls, Len = %d\n",
{
return STATUS_INVALID_PARAMETER;
}
{
Log(("VBOXSF: MRxCloseSrvOpen: File was renamed, handle 0x%RX64 ignore close.\n",
return STATUS_SUCCESS;
}
/* Close file */
{
}
{
Log(("VBOXSF: MRxCloseSrvOpen: Delete on close. Open count = %d\n",
/* Remove file or directory if delete action is pending. */
{
}
}
return Status;
}
{
int vboxRC;
Log(("VBOXSF: vbsfRemove: Delete %.*ls. open count = %d\n",
/* Close file first if not already done. */
{
}
/* Calculate length required for parsed path.
*/
Log(("VBOXSF: vbsfRemove: ParsedPathSize %d\n",
if (!ParsedPath)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Log(("VBOXSF: vbsfRemove: Setup ParsedPath\n"));
/* Call host. */
if (ParsedPath)
{
}
if (vboxRC == VINF_SUCCESS)
{
}
if (vboxRC != VINF_SUCCESS)
{
Log(("VBOXSF: vbsfRemove: vboxCallRemove failed with %Rrc\n",
vboxRC));
}
Log(("VBOXSF: vbsfRemove: Returned 0x%08X\n",
Status));
return Status;
}
{
int vboxRC;
Log(("VBOXSF: vbsfRename: FileName = %.*ls\n",
/* Must close the file before renaming it! */
{
}
/* Mark it as renamed, so we do nothing during close */
/* Calculate length required for destination path. */
Log(("VBOXSF: vbsfRename: ParsedPathSize = %d\n",
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Log(("VBOXSF: vbsfRename: Setting up destination path\n"));
Log(("VBOXSF: vbsfRename: Destination path = %.*ls\n",
/* Calculate length required for source path */
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Log(("VBOXSF: vbsfRename: Setting up source path\n"));
Log(("VBOXSF: vbsfRename: Source path = %.*ls\n",
/* Call host. */
{
}
Log(("VBOXSF: vbsfRename: Calling vboxCallRename\n"));
vboxRC = vboxCallRename(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, SrcPath, DestPath, flags);
if (vboxRC != VINF_SUCCESS)
{
Log(("VBOXSF: vbsfRename: vboxCallRename failed with %Rrc\n",
vboxRC));
}
Log(("VBOXSF: vbsfRename: Returned 0x%08X\n",
Status));
return Status;
}
{
Log(("VBOXSF: MRxShouldTryToCollapseThisOpen\n"));
return STATUS_MORE_PROCESSING_REQUIRED;
}
{
Log(("VBOXSF: MRxCollapseOpen\n"));
return STATUS_MORE_PROCESSING_REQUIRED;
}