/**
 * Get information about host VFS object.
 *
 * @param mp           Mount point data
 * @param pSHFLDPath   Path to VFS object within mounted shared folder
 * @param Info         Returned info
 *
 * @return  0 on success, error code otherwise.
 */
int
vboxvfs_get_info_internal(mount_t mp, PSHFLSTRING pSHFLDPath, PSHFLFSOBJINFO Info)
{
    vboxvfs_mount_t        *pMount;
    SHFLCREATEPARMS         parms;

    int rc;

    AssertReturn(mp, EINVAL);
    AssertReturn(pSHFLDPath, EINVAL);
    AssertReturn(Info, EINVAL);

    pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); AssertReturn(pMount, EINVAL);

    parms.Handle = 0;
    parms.Info.cbObject = 0;
    parms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;

    rc = vboxCallCreate(&g_vboxSFClient, &pMount->pMap, pSHFLDPath, &parms);
    if (rc == 0)
    {
        *Info = parms.Info;
    }

    return rc;
}
/**
 * Open existing VBoxVFS object and return its handle.
 *
 * @param pMount   Mount session data.
 * @param pPath             VFS path to the object relative to mount point.
 * @param fFlags            For directory object it should be
 *                          SHFL_CF_DIRECTORY and 0 for any other object.
 * @param pHandle           Returned handle.
 *
 * @return 0 on success, error code otherwise.
 */
int
vboxvfs_open_internal(vboxvfs_mount_t *pMount, PSHFLSTRING pPath, uint32_t fFlags, SHFLHANDLE *pHandle)
{
    SHFLCREATEPARMS parms;

    int rc;

    AssertReturn(pMount,      EINVAL);
    AssertReturn(pPath,                EINVAL);
    AssertReturn(pHandle,              EINVAL);

    bzero(&parms, sizeof(parms));

    vboxvfs_g2h_mode_dump_inernal(fFlags);

    parms.Handle        = SHFL_HANDLE_NIL;
    parms.Info.cbObject = 0;
    parms.CreateFlags   = fFlags;

    rc = vboxCallCreate(&g_vboxSFClient, &pMount->pMap, pPath, &parms);
    if (RT_SUCCESS(rc))
    {
        *pHandle = parms.Handle;
    }
    else
    {
        PDEBUG("vboxvfs_open_internal() failed: %d", rc);
    }

    return rc;
}
Beispiel #3
0
int sf_stat(const char *caller, struct sf_glob_info *sf_g,
            SHFLSTRING *path, PSHFLFSOBJINFO result, int ok_to_fail)
{
    int rc;
    SHFLCREATEPARMS params;
    NOREF(caller);

    TRACE();

    RT_ZERO(params);
    params.Handle = SHFL_HANDLE_NIL;
    params.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
    LogFunc(("sf_stat: calling vboxCallCreate, file %s, flags %#x\n",
             path->String.utf8, params.CreateFlags));
    rc = vboxCallCreate(&client_handle, &sf_g->map, path, &params);
    if (rc == VERR_INVALID_NAME)
    {
        /* this can happen for names like 'foo*' on a Windows host */
        return -ENOENT;
    }
    if (RT_FAILURE(rc))
    {
        LogFunc(("vboxCallCreate(%s) failed.  caller=%s, rc=%Rrc\n",
                    path->String.utf8, rc, caller));
        return -EPROTO;
    }
    if (params.Result != SHFL_FILE_EXISTS)
    {
        if (!ok_to_fail)
            LogFunc(("vboxCallCreate(%s) file does not exist.  caller=%s, result=%d\n",
                        path->String.utf8, params.Result, caller));
        return -ENOENT;
    }

    *result = params.Info;
    return 0;
}
Beispiel #4
0
/**
 * Open a regular file.
 *
 * @param inode         the inode
 * @param file          the file
 * @returns 0 on success, Linux error code otherwise
 */
static int sf_reg_open(struct inode *inode, struct file *file)
{
    int rc, rc_linux = 0;
    struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
    struct sf_reg_info *sf_r;
    SHFLCREATEPARMS params;

    TRACE();
    BUG_ON(!sf_g);
    BUG_ON(!sf_i);

    LogFunc(("open %s\n", sf_i->path->String.utf8));

    sf_r = kmalloc(sizeof(*sf_r), GFP_KERNEL);
    if (!sf_r)
    {
        LogRelFunc(("could not allocate reg info\n"));
        return -ENOMEM;
    }

    /* Already open? */
    if (sf_i->handle != SHFL_HANDLE_NIL)
    {
        /*
         * This inode was created with sf_create_aux(). Check the CreateFlags:
         * O_CREAT, O_TRUNC: inherent true (file was just created). Not sure
         * about the access flags (SHFL_CF_ACCESS_*).
         */
        sf_i->force_restat = 1;
        sf_r->handle = sf_i->handle;
        sf_i->handle = SHFL_HANDLE_NIL;
        sf_i->file = file;
        file->private_data = sf_r;
        return 0;
    }

    RT_ZERO(params);
    params.Handle = SHFL_HANDLE_NIL;
    /* We check the value of params.Handle afterwards to find out if
     * the call succeeded or failed, as the API does not seem to cleanly
     * distinguish error and informational messages.
     *
     * Furthermore, we must set params.Handle to SHFL_HANDLE_NIL to
     * make the shared folders host service use our fMode parameter */

    if (file->f_flags & O_CREAT)
    {
        LogFunc(("O_CREAT set\n"));
        params.CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW;
        /* We ignore O_EXCL, as the Linux kernel seems to call create
           beforehand itself, so O_EXCL should always fail. */
        if (file->f_flags & O_TRUNC)
        {
            LogFunc(("O_TRUNC set\n"));
            params.CreateFlags |= (  SHFL_CF_ACT_OVERWRITE_IF_EXISTS
                                   | SHFL_CF_ACCESS_WRITE);
        }
        else
            params.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS;
    }
    else
    {
        params.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW;
        if (file->f_flags & O_TRUNC)
        {
            LogFunc(("O_TRUNC set\n"));
            params.CreateFlags |= (  SHFL_CF_ACT_OVERWRITE_IF_EXISTS
                    | SHFL_CF_ACCESS_WRITE);
        }
    }

    if (!(params.CreateFlags & SHFL_CF_ACCESS_READWRITE))
    {
        switch (file->f_flags & O_ACCMODE)
        {
            case O_RDONLY:
                params.CreateFlags |= SHFL_CF_ACCESS_READ;
                break;

            case O_WRONLY:
                params.CreateFlags |= SHFL_CF_ACCESS_WRITE;
                break;

            case O_RDWR:
                params.CreateFlags |= SHFL_CF_ACCESS_READWRITE;
                break;

            default:
                BUG ();
        }
    }

    if (file->f_flags & O_APPEND)
    {
        LogFunc(("O_APPEND set\n"));
        params.CreateFlags |= SHFL_CF_ACCESS_APPEND;
    }

    params.Info.Attr.fMode = inode->i_mode;
    LogFunc(("sf_reg_open: calling vboxCallCreate, file %s, flags=%#x, %#x\n",
              sf_i->path->String.utf8 , file->f_flags, params.CreateFlags));
    rc = vboxCallCreate(&client_handle, &sf_g->map, sf_i->path, &params);
    if (RT_FAILURE(rc))
    {
        LogFunc(("vboxCallCreate failed flags=%d,%#x rc=%Rrc\n",
                  file->f_flags, params.CreateFlags, rc));
        kfree(sf_r);
        return -RTErrConvertToErrno(rc);
    }

    if (SHFL_HANDLE_NIL == params.Handle)
    {
        switch (params.Result)
        {
            case SHFL_PATH_NOT_FOUND:
            case SHFL_FILE_NOT_FOUND:
                rc_linux = -ENOENT;
                break;
            case SHFL_FILE_EXISTS:
                rc_linux = -EEXIST;
                break;
            default:
                break;
        }
    }

    sf_i->force_restat = 1;
    sf_r->handle = params.Handle;
    sf_i->file = file;
    file->private_data = sf_r;
    return rc_linux;
}
Beispiel #5
0
/**
 * Create a new regular file / directory.
 *
 * @param parent        inode of the directory
 * @param dentry        directory cache entry
 * @param mode          file mode
 * @param fDirectory    true if directory, false otherwise
 * @returns 0 on success, Linux error code otherwise
 */
static int sf_create_aux(struct inode *parent, struct dentry *dentry,
                         umode_t mode, int fDirectory)
{
    int rc, err;
    SHFLCREATEPARMS params;
    SHFLSTRING *path;
    struct sf_inode_info *sf_i = GET_INODE_INFO(parent);
    struct sf_glob_info *sf_g = GET_GLOB_INFO(parent->i_sb);

    TRACE();
    BUG_ON(!sf_i);
    BUG_ON(!sf_g);

    err = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path);
    if (err)
        goto fail0;

    RT_ZERO(params);
    params.Handle = SHFL_HANDLE_NIL;
    params.CreateFlags = 0
                       | SHFL_CF_ACT_CREATE_IF_NEW
                       | SHFL_CF_ACT_FAIL_IF_EXISTS
                       | SHFL_CF_ACCESS_READWRITE
                       | (fDirectory ? SHFL_CF_DIRECTORY : 0)
                       ;
    params.Info.Attr.fMode = 0
                           | (fDirectory ? RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE)
                           | (mode & S_IRWXUGO)
                           ;
    params.Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING;

    LogFunc(("sf_create_aux: calling vboxCallCreate, folder %s, flags %#x\n",
              path->String.utf8, params.CreateFlags));
    rc = vboxCallCreate(&client_handle, &sf_g->map, path, &params);
    if (RT_FAILURE(rc))
    {
        if (rc == VERR_WRITE_PROTECT)
        {
            err = -EROFS;
            goto fail1;
        }
        err = -EPROTO;
        LogFunc(("(%d): vboxCallCreate(%s) failed rc=%Rrc\n",
                    fDirectory, sf_i->path->String.utf8, rc));
        goto fail1;
    }

    if (params.Result != SHFL_FILE_CREATED)
    {
        err = -EPERM;
        LogFunc(("(%d): could not create file %s result=%d\n",
                    fDirectory, sf_i->path->String.utf8, params.Result));
        goto fail1;
    }

    err = sf_instantiate(parent, dentry, path, &params.Info,
                         fDirectory ? SHFL_HANDLE_NIL : params.Handle);
    if (err)
    {
        LogFunc(("(%d): could not instantiate dentry for %s err=%d\n",
                    fDirectory, sf_i->path->String.utf8, err));
        goto fail2;
    }

    /*
     * Don't close this handle right now. We assume that the same file is
     * opened with sf_reg_open() and later closed with sf_reg_close(). Save
     * the handle in between. Does not apply to directories. True?
     */
    if (fDirectory)
    {
        rc = vboxCallClose(&client_handle, &sf_g->map, params.Handle);
        if (RT_FAILURE(rc))
            LogFunc(("(%d): vboxCallClose failed rc=%Rrc\n", fDirectory, rc));
    }

    sf_i->force_restat = 1;
    return 0;

fail2:
    rc = vboxCallClose(&client_handle, &sf_g->map, params.Handle);
    if (RT_FAILURE(rc))
        LogFunc(("(%d): vboxCallClose failed rc=%Rrc\n", fDirectory, rc));

fail1:
    kfree(path);

fail0:
    return err;
}
Beispiel #6
0
/**
 * Open a directory. Read the complete content into a buffer.
 *
 * @param inode     inode
 * @param file      file
 * @returns 0 on success, Linux error code otherwise
 */
static int sf_dir_open(struct inode *inode, struct file *file)
{
    int rc;
    int err;
    struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
    struct sf_dir_info *sf_d;
    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
    SHFLCREATEPARMS params;

    TRACE();
    BUG_ON(!sf_g);
    BUG_ON(!sf_i);

    if (file->private_data)
    {
        LogFunc(("sf_dir_open() called on already opened directory '%s'\n",
                sf_i->path->String.utf8));
        return 0;
    }

    sf_d = sf_dir_info_alloc();
    if (!sf_d)
    {
        LogRelFunc(("could not allocate directory info for '%s'\n",
                    sf_i->path->String.utf8));
        return -ENOMEM;
    }

    RT_ZERO(params);
    params.Handle = SHFL_HANDLE_NIL;
    params.CreateFlags = 0
                       | SHFL_CF_DIRECTORY
                       | SHFL_CF_ACT_OPEN_IF_EXISTS
                       | SHFL_CF_ACT_FAIL_IF_NEW
                       | SHFL_CF_ACCESS_READ
                       ;

    LogFunc(("sf_dir_open(): calling vboxCallCreate, folder %s, flags %#x\n",
             sf_i->path->String.utf8, params.CreateFlags));
    rc = vboxCallCreate(&client_handle, &sf_g->map, sf_i->path, &params);
    if (RT_SUCCESS(rc))
    {
        if (params.Result == SHFL_FILE_EXISTS)
        {
            err = sf_dir_read_all(sf_g, sf_i, sf_d, params.Handle);
            if (!err)
                file->private_data = sf_d;
        }
        else
            err = -ENOENT;

        rc = vboxCallClose(&client_handle, &sf_g->map, params.Handle);
        if (RT_FAILURE(rc))
            LogFunc(("sf_dir_open(): vboxCallClose(%s) after err=%d failed rc=%Rrc\n",
                     sf_i->path->String.utf8, err, rc));
    }
    else
        err = -EPERM;

    if (err)
        sf_dir_info_free(sf_d);

    return err;
}
Beispiel #7
0
/**
 * Extract element ([dir]->f_pos) from the directory [dir] into [d_name].
 *
 * @returns 0 for success, 1 for end reached, Linux error code otherwise.
 */
static int sf_getdent(struct file *dir, char d_name[NAME_MAX], int *d_type)
{
    loff_t cur;
    struct sf_glob_info *sf_g;
    struct sf_dir_info *sf_d;
    struct sf_inode_info *sf_i;
    struct inode *inode;
    struct list_head *pos, *list;

    TRACE();

    inode = GET_F_DENTRY(dir)->d_inode;
    sf_i = GET_INODE_INFO(inode);
    sf_g = GET_GLOB_INFO(inode->i_sb);
    sf_d = dir->private_data;

    BUG_ON(!sf_g);
    BUG_ON(!sf_d);
    BUG_ON(!sf_i);

    if (sf_i->force_reread)
    {
        int rc;
        int err;
        SHFLCREATEPARMS params;

        RT_ZERO(params);
        params.Handle = SHFL_HANDLE_NIL;
        params.CreateFlags = 0
                           | SHFL_CF_DIRECTORY
                           | SHFL_CF_ACT_OPEN_IF_EXISTS
                           | SHFL_CF_ACT_FAIL_IF_NEW
                           | SHFL_CF_ACCESS_READ
                           ;

        LogFunc(("sf_getdent: calling vboxCallCreate, folder %s, flags %#x\n",
                  sf_i->path->String.utf8, params.CreateFlags));
        rc = vboxCallCreate(&client_handle, &sf_g->map, sf_i->path, &params);
        if (RT_FAILURE(rc))
        {
            LogFunc(("vboxCallCreate(%s) failed rc=%Rrc\n",
                        sf_i->path->String.utf8, rc));
            return -EPERM;
        }

        if (params.Result != SHFL_FILE_EXISTS)
        {
            LogFunc(("directory %s does not exist\n", sf_i->path->String.utf8));
            sf_dir_info_free(sf_d);
            return -ENOENT;
        }

        sf_dir_info_empty(sf_d);
        err = sf_dir_read_all(sf_g, sf_i, sf_d, params.Handle);
        rc = vboxCallClose(&client_handle, &sf_g->map, params.Handle);
        if (RT_FAILURE(rc))
            LogFunc(("vboxCallClose(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc));
        if (err)
            return err;

        sf_i->force_reread = 0;
    }

    cur = 0;
    list = &sf_d->info_list;
    list_for_each(pos, list)
    {
        struct sf_dir_buf *b;
        SHFLDIRINFO *info;
        loff_t i;

        b = list_entry(pos, struct sf_dir_buf, head);
        if (dir->f_pos >= cur + b->cEntries)
        {
            cur += b->cEntries;
            continue;
        }

        for (i = 0, info = b->buf; i < dir->f_pos - cur; ++i)
        {
            size_t size;

            size = offsetof(SHFLDIRINFO, name.String) + info->name.u16Size;
            info = (SHFLDIRINFO *) ((uintptr_t) info + size);
        }

        *d_type = sf_get_d_type(info->Info.Attr.fMode);

        return sf_nlscpy(sf_g, d_name, NAME_MAX,
                         info->name.String.utf8, info->name.u16Length);
    }

    return 1;
}
Beispiel #8
0
int sf_setattr(struct dentry *dentry, struct iattr *iattr)
{
    struct sf_glob_info *sf_g;
    struct sf_inode_info *sf_i;
    SHFLCREATEPARMS params;
    SHFLFSOBJINFO info;
    uint32_t cbBuffer;
    int rc, err;

    TRACE();

    sf_g = GET_GLOB_INFO(dentry->d_inode->i_sb);
    sf_i = GET_INODE_INFO(dentry->d_inode);
    err  = 0;

    RT_ZERO(params);
    params.Handle = SHFL_HANDLE_NIL;
    params.CreateFlags = SHFL_CF_ACT_OPEN_IF_EXISTS
                       | SHFL_CF_ACT_FAIL_IF_NEW
                       | SHFL_CF_ACCESS_ATTR_WRITE;

    /* this is at least required for Posix hosts */
    if (iattr->ia_valid & ATTR_SIZE)
        params.CreateFlags |= SHFL_CF_ACCESS_WRITE;

    rc = vboxCallCreate(&client_handle, &sf_g->map, sf_i->path, &params);
    if (RT_FAILURE(rc))
    {
        LogFunc(("vboxCallCreate(%s) failed rc=%Rrc\n",
                 sf_i->path->String.utf8, rc));
        err = -RTErrConvertToErrno(rc);
        goto fail2;
    }
    if (params.Result != SHFL_FILE_EXISTS)
    {
        LogFunc(("file %s does not exist\n", sf_i->path->String.utf8));
        err = -ENOENT;
        goto fail1;
    }

    /* Setting the file size and setting the other attributes has to be
     * handled separately, see implementation of vbsfSetFSInfo() in
     * vbsf.cpp */
    if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME))
    {
#define mode_set(r) ((iattr->ia_mode & (S_##r)) ? RTFS_UNIX_##r : 0)

        RT_ZERO(info);
        if (iattr->ia_valid & ATTR_MODE)
        {
            info.Attr.fMode  = mode_set(ISUID);
            info.Attr.fMode |= mode_set(ISGID);
            info.Attr.fMode |= mode_set(IRUSR);
            info.Attr.fMode |= mode_set(IWUSR);
            info.Attr.fMode |= mode_set(IXUSR);
            info.Attr.fMode |= mode_set(IRGRP);
            info.Attr.fMode |= mode_set(IWGRP);
            info.Attr.fMode |= mode_set(IXGRP);
            info.Attr.fMode |= mode_set(IROTH);
            info.Attr.fMode |= mode_set(IWOTH);
            info.Attr.fMode |= mode_set(IXOTH);

            if (iattr->ia_mode & S_IFDIR)
                info.Attr.fMode |= RTFS_TYPE_DIRECTORY;
            else
                info.Attr.fMode |= RTFS_TYPE_FILE;
        }

        if (iattr->ia_valid & ATTR_ATIME)
            sf_timespec_from_ftime(&info.AccessTime, &iattr->ia_atime);
        if (iattr->ia_valid & ATTR_MTIME)
            sf_timespec_from_ftime(&info.ModificationTime, &iattr->ia_mtime);
        /* ignore ctime (inode change time) as it can't be set from userland anyway */

        cbBuffer = sizeof(info);
        rc = vboxCallFSInfo(&client_handle, &sf_g->map, params.Handle,
                SHFL_INFO_SET | SHFL_INFO_FILE, &cbBuffer,
                (PSHFLDIRINFO)&info);
        if (RT_FAILURE(rc))
        {
            LogFunc(("vboxCallFSInfo(%s, FILE) failed rc=%Rrc\n",
                        sf_i->path->String.utf8, rc));
            err = -RTErrConvertToErrno(rc);
            goto fail1;
        }
    }

    if (iattr->ia_valid & ATTR_SIZE)
    {
        RT_ZERO(info);
        info.cbObject = iattr->ia_size;
        cbBuffer = sizeof(info);
        rc = vboxCallFSInfo(&client_handle, &sf_g->map, params.Handle,
                            SHFL_INFO_SET | SHFL_INFO_SIZE, &cbBuffer,
                            (PSHFLDIRINFO)&info);
        if (RT_FAILURE(rc))
        {
            LogFunc(("vboxCallFSInfo(%s, SIZE) failed rc=%Rrc\n",
                        sf_i->path->String.utf8, rc));
            err = -RTErrConvertToErrno(rc);
            goto fail1;
        }
    }

    rc = vboxCallClose(&client_handle, &sf_g->map, params.Handle);
    if (RT_FAILURE(rc))
        LogFunc(("vboxCallClose(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc));

    return sf_inode_revalidate(dentry);

fail1:
    rc = vboxCallClose(&client_handle, &sf_g->map, params.Handle);
    if (RT_FAILURE(rc))
        LogFunc(("vboxCallClose(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc));

fail2:
    return err;
}
Beispiel #9
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;
}