Exemplo n.º 1
0
NTSTATUS
PvfsCreateDirDoSysOpen(
    IN PVOID pContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PPVFS_PENDING_CREATE pCreateContext = (PPVFS_PENDING_CREATE)pContext;
    PIRP pIrp = pCreateContext->pIrpContext->pIrp;
    IRP_ARGS_CREATE Args = pIrp->Args.Create;
    int fd = -1;
    int unixFlags = 0;
    PIO_CREATE_SECURITY_CONTEXT pSecCtx = Args.SecurityContext;
    FILE_CREATE_RESULT CreateResult = 0;
    IO_MATCH_FILE_SPEC FileSpec = {0};
    WCHAR wszPattern[2] = {L'*', 0x0 };
    PIO_SECURITY_CONTEXT_PROCESS_INFORMATION pProcess = NULL;
    PBOOLEAN pbEnableAbe = NULL;
    ULONG ulEcpSize = 0;

    pProcess = IoSecurityGetProcessInfo(pSecCtx);

    /* Fail any create that requires setting the security but doesn't
       have the Unix uid/gid information */

    if ((pCreateContext->SetPropertyFlags & PVFS_SET_PROP_SECURITY) &&
        (pProcess == NULL))
    {
        ntError = STATUS_ACCESS_DENIED;
        BAIL_ON_NT_STATUS(ntError);
    }

    /* Do the open() */

    ntError = MapPosixOpenFlags(
                  &unixFlags,
                  pCreateContext->GrantedAccess,
                  Args);
    BAIL_ON_NT_STATUS(ntError);

    if (!pCreateContext->bFileExisted)
    {
        ntError = PvfsSysMkDir(
                      pCreateContext->pszDiskFilename,
                      (mode_t)gPvfsDriverConfig.CreateDirectoryMode);
        BAIL_ON_NT_STATUS(ntError);
    }

    /* Open the DIR* and then open a fd based on that */

    ntError = PvfsAllocateMemory(
                  (PVOID)&pCreateContext->pCcb->pDirContext,
                  sizeof(PVFS_DIRECTORY_CONTEXT));
    BAIL_ON_NT_STATUS(ntError);

    pCreateContext->pCcb->pszFilename = pCreateContext->pszDiskFilename;
    pCreateContext->pszDiskFilename = NULL;

    ntError = IoRtlEcpListFind(
                  pIrp->Args.Create.EcpList,
                  SRV_ECP_TYPE_ABE,
                  OUT_PPVOID(&pbEnableAbe),
                  &ulEcpSize);
    if (ntError != STATUS_NOT_FOUND)
    {
        BAIL_ON_NT_STATUS(ntError);

        if (ulEcpSize != sizeof(BOOLEAN))
        {
            ntError = STATUS_INVALID_PARAMETER;
            BAIL_ON_NT_STATUS(ntError);
        }

        if (*pbEnableAbe)
        {
            pCreateContext->pCcb->EcpFlags |= PVFS_ECP_ENABLE_ABE;
        }
    }

    do
    {
        ntError = PvfsSysOpen(
                      &fd,
                      pCreateContext->pCcb->pszFilename,
                      0,
                      0);

    } while (ntError == STATUS_MORE_PROCESSING_REQUIRED);
    BAIL_ON_NT_STATUS(ntError);

    /* Save our state */

    pCreateContext->pCcb->fd = fd;
    pCreateContext->pCcb->ShareFlags = Args.ShareAccess;
    pCreateContext->pCcb->AccessGranted = pCreateContext->GrantedAccess;
    pCreateContext->pCcb->CreateOptions = Args.CreateOptions;

    ntError = PvfsAddCCBToFCB(pCreateContext->pFcb, pCreateContext->pCcb);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsSaveFileDeviceInfo(pCreateContext->pCcb);
    BAIL_ON_NT_STATUS(ntError);

    if ((pCreateContext->SetPropertyFlags & PVFS_SET_PROP_SECURITY) && pSecCtx)
    {
        /* Unix Security */

        ntError = PvfsSysChown(
                      pCreateContext->pCcb,
                      pProcess->Uid,
                      pProcess->Gid);
        BAIL_ON_NT_STATUS(ntError);

        /* Security Descriptor */

        ntError = PvfsCreateFileSecurity(
                      pCreateContext->pCcb->pUserToken,
                      pCreateContext->pCcb,
                      Args.SecurityDescriptor,
                      TRUE);
        BAIL_ON_NT_STATUS(ntError);
    }

    if ((pCreateContext->SetPropertyFlags & PVFS_SET_PROP_ATTRIB) &&
        (Args.FileAttributes != 0))
    {
        ntError = PvfsSetFileAttributes(
                      pCreateContext->pCcb,
                      Args.FileAttributes);
        BAIL_ON_NT_STATUS(ntError);
    }

    /* Save the delete-on-close flag to the FCB */

    if (Args.CreateOptions & FILE_DELETE_ON_CLOSE)
    {
        LwRtlUnicodeStringInit(&FileSpec.Pattern, wszPattern);

        ntError = PvfsEnumerateDirectory(pCreateContext->pCcb, &FileSpec, 1, FALSE);
        if (ntError == STATUS_SUCCESS)
        {
            ntError = STATUS_DIRECTORY_NOT_EMPTY;
            BAIL_ON_NT_STATUS(ntError);
        }

        pCreateContext->pCcb->bPendingDeleteHandle = TRUE;
    }

    ntError = PvfsStoreCCB(pIrp->FileHandle, pCreateContext->pCcb);
    BAIL_ON_NT_STATUS(ntError);

    PvfsInitializeZctSupport(pCreateContext->pCcb, pIrp->FileHandle);

    CreateResult = PvfsSetCreateResult(
                       Args.CreateDisposition,
                       pCreateContext->bFileExisted,
                       STATUS_SUCCESS);

    if (CreateResult == FILE_CREATED)
    {
        PvfsNotifyScheduleFullReport(
            pCreateContext->pCcb->pFcb,
            FILE_NOTIFY_CHANGE_FILE_NAME,
            FILE_ACTION_ADDED,
            pCreateContext->pCcb->pszFilename);
    }

    /* The CCB has been handled off to the FileHandle so make sure
       we don't think we still own it */

    pCreateContext->pCcb = NULL;

cleanup:
    pIrp->IoStatusBlock.CreateResult = CreateResult;

    return ntError;

error:
    CreateResult = PvfsSetCreateResult(
                       Args.CreateDisposition,
                       pCreateContext->bFileExisted,
                       ntError);

    if (fd != -1)
    {
        PSTR pszRemovePath = NULL;

        /* Pick up where we started the pathname */

        pszRemovePath = pCreateContext->pszDiskFilename ?
                        pCreateContext->pszDiskFilename :
                        pCreateContext->pCcb->pszFilename;

        PvfsCleanupFailedCreate(
            fd,
            pszRemovePath,
            !pCreateContext->bFileExisted);
    }

    goto cleanup;
}
Exemplo n.º 2
0
NTSTATUS
PvfsCreateFileDoSysOpen(
    IN PVOID pContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PPVFS_PENDING_CREATE pCreateContext = (PPVFS_PENDING_CREATE)pContext;
    PIRP pIrp = pCreateContext->pIrpContext->pIrp;
    IRP_ARGS_CREATE Args = pIrp->Args.Create;
    int fd = -1;
    int unixFlags = 0;
    PIO_CREATE_SECURITY_CONTEXT pSecCtx = Args.SecurityContext;
    FILE_CREATE_RESULT CreateResult = 0;
    PIO_SECURITY_CONTEXT_PROCESS_INFORMATION pProcess = NULL;

    pProcess = IoSecurityGetProcessInfo(pSecCtx);

    /* Fail any create that requires setting the security but doesn't
       have the Unix uid/gid information */

    if ((pCreateContext->SetPropertyFlags & PVFS_SET_PROP_SECURITY) &&
        (pProcess == NULL))
    {
        ntError = STATUS_ACCESS_DENIED;
        BAIL_ON_NT_STATUS(ntError);
    }

    ntError = PvfsEnforceShareMode(
                   pCreateContext->pFcb,
                   Args.ShareAccess,
                   pCreateContext->GrantedAccess);
    BAIL_ON_NT_STATUS(ntError);

    /* Do the open() */

    ntError = MapPosixOpenFlags(&unixFlags, pCreateContext->GrantedAccess, Args);
    BAIL_ON_NT_STATUS(ntError);

    do
    {
        ntError = PvfsSysOpen(
                      &fd,
                      pCreateContext->pszDiskFilename,
                      unixFlags,
                      (mode_t)gPvfsDriverConfig.CreateFileMode);

    } while (ntError == STATUS_MORE_PROCESSING_REQUIRED);
    BAIL_ON_NT_STATUS(ntError);

    /* Perform preallocation is requested */

    if (Args.AllocationSize > 0)
    {
        BOOLEAN bAllocate = FALSE;

        switch (Args.CreateDisposition)
        {
        case FILE_SUPERSEDE:
        case FILE_CREATE:
        case FILE_OVERWRITE:
        case FILE_OVERWRITE_IF:
            bAllocate = TRUE;
            break;

        case FILE_OPEN_IF:
            if (!pCreateContext->bFileExisted)
            {
                bAllocate = TRUE;
            }
            break;
        }

        if (bAllocate)
        {
            ntError = PvfsSysFtruncate(fd, (off_t)Args.AllocationSize);
            BAIL_ON_NT_STATUS(ntError);
        }
    }

    /* Save our state */

    pCreateContext->pCcb->fd = fd;
    pCreateContext->pCcb->ShareFlags = Args.ShareAccess;
    pCreateContext->pCcb->AccessGranted = pCreateContext->GrantedAccess;
    pCreateContext->pCcb->CreateOptions = Args.CreateOptions;

    pCreateContext->pCcb->pszFilename = pCreateContext->pszDiskFilename;
    pCreateContext->pszDiskFilename = NULL;

    ntError = PvfsAddCCBToFCB(pCreateContext->pFcb, pCreateContext->pCcb);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsSaveFileDeviceInfo(pCreateContext->pCcb);
    BAIL_ON_NT_STATUS(ntError);

    /* CCB is now complete */

    if ((pCreateContext->SetPropertyFlags & PVFS_SET_PROP_SECURITY) && pSecCtx)
    {
        /* Unix Security */

        ntError = PvfsSysChown(
                      pCreateContext->pCcb,
                      pProcess->Uid,
                      pProcess->Gid);
        BAIL_ON_NT_STATUS(ntError);

        /* Security Descriptor */

        ntError = PvfsCreateFileSecurity(
                      pCreateContext->pCcb->pUserToken,
                      pCreateContext->pCcb,
                      Args.SecurityDescriptor,
                      FALSE);
        BAIL_ON_NT_STATUS(ntError);
    }

    if ((pCreateContext->SetPropertyFlags & PVFS_SET_PROP_ATTRIB) &&
        (Args.FileAttributes != 0))
    {
        ntError = PvfsSetFileAttributes(
                      pCreateContext->pCcb,
                      Args.FileAttributes);
        BAIL_ON_NT_STATUS(ntError);
    }

    /* Save the delete-on-close flag to the FCB */

    if (Args.CreateOptions & FILE_DELETE_ON_CLOSE)
    {
        pCreateContext->pCcb->bPendingDeleteHandle = TRUE;
    }

    ntError = PvfsStoreCCB(pIrp->FileHandle, pCreateContext->pCcb);
    BAIL_ON_NT_STATUS(ntError);

    PvfsInitializeZctSupport(pCreateContext->pCcb, pIrp->FileHandle);

    CreateResult = PvfsSetCreateResult(
                       Args.CreateDisposition,
                       pCreateContext->bFileExisted,
                       STATUS_SUCCESS);

    if (CreateResult == FILE_CREATED)
    {
        PvfsNotifyScheduleFullReport(
            pCreateContext->pCcb->pFcb,
            FILE_NOTIFY_CHANGE_FILE_NAME,
            FILE_ACTION_ADDED,
            pCreateContext->pCcb->pszFilename);
    }

    /* The CCB has been handled off to the FileHandle so make sure
       we don't think we still own it */

    pCreateContext->pCcb = NULL;

cleanup:
    pIrp->IoStatusBlock.CreateResult = CreateResult;

    return ntError;

error:
    CreateResult = PvfsSetCreateResult(
                       Args.CreateDisposition,
                       pCreateContext->bFileExisted,
                       ntError);

    if (fd != -1)
    {
        PSTR pszRemovePath = NULL;

        /* Pick up where we started the pathname */

        pszRemovePath = pCreateContext->pszDiskFilename ?
                        pCreateContext->pszDiskFilename :
                        pCreateContext->pCcb->pszFilename;

        PvfsCleanupFailedCreate(
            fd,
            pszRemovePath,
            !pCreateContext->bFileExisted);
    }

    goto cleanup;
}
Exemplo n.º 3
0
static
NTSTATUS
PvfsCreateDirOpen(
    PPVFS_IRP_CONTEXT pIrpContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    IRP_ARGS_CREATE Args = pIrpContext->pIrp->Args.Create;
    PPVFS_PENDING_CREATE pCreateCtx = NULL;
    PVFS_STAT Stat = {0};

    ntError = PvfsAllocateCreateContext(&pCreateCtx, pIrpContext);
    BAIL_ON_NT_STATUS(ntError);

    if (IsSetFlag(
            pCreateCtx->OriginalFileName->NameOptions,
            PVFS_FILE_NAME_OPTION_DEFINED_STREAM_TYPE))
    {
        // Disallow named streams here (shouldn't happen) and "::$DATA"
        ntError = STATUS_NOT_A_DIRECTORY;
        BAIL_ON_NT_STATUS(ntError);
    }

    ntError = PvfsLookupPath2(
                  &pCreateCtx->ResolvedFileName,
                  &Stat,
                  pCreateCtx->OriginalFileName,
                  IsSetFlag(Args.FileName.IoNameOptions, IO_NAME_OPTION_CASE_SENSITIVE));
    BAIL_ON_NT_STATUS(ntError);

    if (!S_ISDIR(Stat.s_mode))
    {
        ntError = STATUS_NOT_A_DIRECTORY;
        BAIL_ON_NT_STATUS(ntError);
    }

    ntError = PvfsAccessCheckFile(
                  pCreateCtx->pCcb->pUserToken,
                  pCreateCtx->ResolvedFileName,
                  Args.DesiredAccess,
                  &pCreateCtx->GrantedAccess);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCheckDosAttributes(
                  Args,
                  pCreateCtx->bFileExisted ? pCreateCtx->ResolvedFileName : NULL,
                  pCreateCtx->GrantedAccess);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCheckShareMode(
                  pCreateCtx->ResolvedFileName,
                  Args.ShareAccess,
                  pCreateCtx->GrantedAccess,
                  &pCreateCtx->pScb);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCreateFileCheckPendingDelete(pCreateCtx->pScb);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCheckQuotaFile(&Args, pCreateCtx->pCcb);
    BAIL_ON_NT_STATUS(ntError);

    pCreateCtx->bFileExisted = TRUE;

    ntError = PvfsAddCCBToSCB(pCreateCtx->pScb, pCreateCtx->pCcb);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCreateDirDoSysOpen(pCreateCtx);
    BAIL_ON_NT_STATUS(ntError);

cleanup:
    PvfsFreeCreateContext(OUT_PPVOID(&pCreateCtx));

    return ntError;

error:
    if (ntError != STATUS_PENDING)
    {
        pIrpContext->pIrp->IoStatusBlock.CreateResult =
            PvfsSetCreateResult(
                Args.CreateDisposition,
                pCreateCtx ? pCreateCtx->bFileExisted : FALSE,
                ntError);
    }

    if (pCreateCtx &&
        pCreateCtx->pCcb &&
        pCreateCtx->pCcb->pDirContext &&
        pCreateCtx->pCcb->pDirContext->pDir)
    {
        PvfsSysCloseDir(pCreateCtx->pCcb->pDirContext->pDir);
    }

    goto cleanup;
}
Exemplo n.º 4
0
static
NTSTATUS
PvfsCreateDirOpenIf(
    PPVFS_IRP_CONTEXT pIrpContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    IRP_ARGS_CREATE Args = pIrpContext->pIrp->Args.Create;
    PPVFS_PENDING_CREATE pCreateCtx = NULL;
    PVFS_STAT statPath = { 0 };
    PVFS_STAT statFile = { 0 };
    PPVFS_FILE_NAME directoryName = NULL;
    PPVFS_FILE_NAME resolvedDirName = NULL;
    PPVFS_FILE_NAME relativeFileName = NULL;

    ntError = PvfsAllocateCreateContext(&pCreateCtx, pIrpContext);
    BAIL_ON_NT_STATUS(ntError);

    if (IsSetFlag(
            pCreateCtx->OriginalFileName->NameOptions,
            PVFS_FILE_NAME_OPTION_DEFINED_STREAM_TYPE))
    {
        // Disallow named streams here (shouldn't happen) and "::$DATA"
        ntError = STATUS_NOT_A_DIRECTORY;
        BAIL_ON_NT_STATUS(ntError);
    }

    ntError = PvfsSplitFileNamePath(
                  &directoryName,
                  &relativeFileName,
                  pCreateCtx->OriginalFileName);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsLookupPath2(
                  &resolvedDirName,
                  &statPath,
                  directoryName,
                  IsSetFlag(Args.FileName.IoNameOptions, IO_NAME_OPTION_CASE_SENSITIVE));
    BAIL_ON_NT_STATUS(ntError);

    /* Check for file existence */

    ntError = PvfsLookupFile2(
                  &pCreateCtx->ResolvedFileName,
                  &statFile,
                  directoryName,
                  relativeFileName,
                  IsSetFlag(Args.FileName.IoNameOptions, IO_NAME_OPTION_CASE_SENSITIVE));
    pCreateCtx->bFileExisted = NT_SUCCESS(ntError) ? TRUE : FALSE;

    if (!pCreateCtx->bFileExisted)
    {
        ntError = PvfsAppendFileName(
                      &pCreateCtx->ResolvedFileName,
                      resolvedDirName,
                      relativeFileName);
        BAIL_ON_NT_STATUS(ntError);

        ntError = PvfsAccessCheckFile(
                      pCreateCtx->pCcb->pUserToken,
                      resolvedDirName,
                      FILE_ADD_SUBDIRECTORY,
                      &pCreateCtx->GrantedAccess);
        BAIL_ON_NT_STATUS(ntError);

        pCreateCtx->GrantedAccess = PvfsGetGrantedAccessForNewObject(
                                            Args.DesiredAccess);
    }
    else
    {
        if (!S_ISDIR(statFile.s_mode))
        {
            ntError = STATUS_NOT_A_DIRECTORY;
            BAIL_ON_NT_STATUS(ntError);
        }

        ntError = PvfsAccessCheckFile(
                      pCreateCtx->pCcb->pUserToken,
                      pCreateCtx->ResolvedFileName,
                      Args.DesiredAccess,
                      &pCreateCtx->GrantedAccess);
        BAIL_ON_NT_STATUS(ntError);
    }

    ntError = PvfsCheckDosAttributes(
                  Args,
                  pCreateCtx->bFileExisted ? pCreateCtx->ResolvedFileName : NULL,
                  pCreateCtx->GrantedAccess);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCheckShareMode(
                  pCreateCtx->ResolvedFileName,
                  Args.ShareAccess,
                  pCreateCtx->GrantedAccess,
                  &pCreateCtx->pScb);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCreateFileCheckPendingDelete(pCreateCtx->pScb);
    BAIL_ON_NT_STATUS(ntError);

    if (!pCreateCtx->bFileExisted)
    {
        pCreateCtx->SetPropertyFlags = PVFS_SET_PROP_SECURITY|
                                       PVFS_SET_PROP_ATTRIB;
    }

    ntError = PvfsAddCCBToSCB(pCreateCtx->pScb, pCreateCtx->pCcb);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCreateDirDoSysOpen(pCreateCtx);
    BAIL_ON_NT_STATUS(ntError);

cleanup:
    PvfsFreeCreateContext(OUT_PPVOID(&pCreateCtx));

    if (directoryName)
    {
        PvfsFreeFileName(directoryName);
    }
    if (relativeFileName)
    {
        PvfsFreeFileName(relativeFileName);
    }
    if (resolvedDirName)
    {
        PvfsFreeFileName(resolvedDirName);
    }

    return ntError;

error:
    if (ntError != STATUS_PENDING)
    {
        pIrpContext->pIrp->IoStatusBlock.CreateResult =
            PvfsSetCreateResult(
                Args.CreateDisposition,
                pCreateCtx ? pCreateCtx->bFileExisted : FALSE,
                ntError);
    }

    if (pCreateCtx &&
        pCreateCtx->pCcb &&
        pCreateCtx->pCcb->pDirContext &&
        pCreateCtx->pCcb->pDirContext->pDir)
    {
        PvfsSysCloseDir(pCreateCtx->pCcb->pDirContext->pDir);
    }

    goto cleanup;
}
Exemplo n.º 5
0
static
NTSTATUS
PvfsCreateDirCreate(
    PPVFS_IRP_CONTEXT pIrpContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    IRP_ARGS_CREATE Args = pIrpContext->pIrp->Args.Create;
    PPVFS_PENDING_CREATE pCreateCtx = NULL;
    PVFS_STAT statPath = { 0 };
    PPVFS_FILE_NAME directoryName = NULL;
    PPVFS_FILE_NAME relativeFileName = NULL;
    PPVFS_FILE_NAME resolvedDirName = NULL;

    ntError = PvfsAllocateCreateContext(&pCreateCtx, pIrpContext);
    BAIL_ON_NT_STATUS(ntError);

    if (IsSetFlag(
            pCreateCtx->OriginalFileName->NameOptions,
            PVFS_FILE_NAME_OPTION_DEFINED_STREAM_TYPE))
    {
        // Disallow named streams here (shouldn't happen) and "::$DATA"
        ntError = STATUS_NOT_A_DIRECTORY;
        BAIL_ON_NT_STATUS(ntError);
    }

    /* We expect this call to fail with OBJECT_NAME_NOT_FOUND */

    ntError = PvfsLookupPath2(
                  &pCreateCtx->ResolvedFileName,
                  &statPath,
                  pCreateCtx->OriginalFileName,
                  IsSetFlag(Args.FileName.IoNameOptions, IO_NAME_OPTION_CASE_SENSITIVE));
    switch (ntError)
    {
    case STATUS_SUCCESS:
        ntError = STATUS_OBJECT_NAME_COLLISION;
        break;
    case STATUS_OBJECT_NAME_NOT_FOUND:
        ntError = STATUS_SUCCESS;
        break;
    default:
        /* do nothing */
        break;
    }
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsSplitFileNamePath(
                  &directoryName,
                  &relativeFileName,
                  pCreateCtx->OriginalFileName);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsLookupPath2(
                  &resolvedDirName,
                  &statPath,
                  directoryName,
                  IsSetFlag(Args.FileName.IoNameOptions, IO_NAME_OPTION_CASE_SENSITIVE));
    if (ntError == STATUS_OBJECT_NAME_NOT_FOUND)
    {
        ntError = STATUS_OBJECT_PATH_NOT_FOUND;
    }

    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsAppendFileName(
                  &pCreateCtx->ResolvedFileName,
                  resolvedDirName,
                  relativeFileName);
    BAIL_ON_NT_STATUS(ntError);

    /* check parent here */

    ntError = PvfsAccessCheckFile(
                  pCreateCtx->pCcb->pUserToken,
                  resolvedDirName,
                  FILE_ADD_SUBDIRECTORY,
                  &pCreateCtx->GrantedAccess);
    BAIL_ON_NT_STATUS(ntError);

    pCreateCtx->GrantedAccess = PvfsGetGrantedAccessForNewObject(
                                        Args.DesiredAccess);

    ntError = PvfsCheckDosAttributes(
                  Args,
                  NULL,  /* New directory */
                  pCreateCtx->GrantedAccess);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCheckShareMode(
                  pCreateCtx->ResolvedFileName,
                  Args.ShareAccess,
                  pCreateCtx->GrantedAccess,
                  &pCreateCtx->pScb);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCreateFileCheckPendingDelete(pCreateCtx->pScb);
    BAIL_ON_NT_STATUS(ntError);

    pCreateCtx->bFileExisted = FALSE;
    pCreateCtx->SetPropertyFlags = PVFS_SET_PROP_SECURITY|PVFS_SET_PROP_ATTRIB;

    ntError = PvfsAddCCBToSCB(pCreateCtx->pScb, pCreateCtx->pCcb);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCreateDirDoSysOpen(pCreateCtx);
    BAIL_ON_NT_STATUS(ntError);

cleanup:
    PvfsFreeCreateContext(OUT_PPVOID(&pCreateCtx));

    if (directoryName)
    {
        PvfsFreeFileName(directoryName);
    }
    if (relativeFileName)
    {
        PvfsFreeFileName(relativeFileName);
    }
    if (resolvedDirName)
    {
        PvfsFreeFileName(resolvedDirName);
    }

    return ntError;

error:
    if (ntError != STATUS_PENDING)
    {
        pIrpContext->pIrp->IoStatusBlock.CreateResult =
            PvfsSetCreateResult(
                Args.CreateDisposition,
                pCreateCtx ? pCreateCtx->bFileExisted : FALSE,
                ntError);
    }

    if (pCreateCtx &&
        pCreateCtx->pCcb &&
        pCreateCtx->pCcb->pDirContext &&
        pCreateCtx->pCcb->pDirContext->pDir)
    {
        PvfsSysCloseDir(pCreateCtx->pCcb->pDirContext->pDir);
    }

    goto cleanup;
}