示例#1
0
NTSTATUS
SrvBuildTreeRelativePath(
    PLWIO_SRV_TREE pTree,
    PWSTR          pwszFilename,
    PIO_FILE_NAME  pFilename
    )
{
    NTSTATUS ntStatus     = STATUS_SUCCESS;
    BOOLEAN  bInLock      = FALSE;
    PWSTR    pwszFilePath = NULL;

    if (SrvTreeIsNamedPipe(pTree))
    {
        LWIO_LOCK_RWMUTEX_SHARED(bInLock, &pTree->pShareInfo->mutex);

        ntStatus = SrvBuildFilePath(
                        pTree->pShareInfo->pwszPath,
                        pwszFilename,
                        &pwszFilePath);
        BAIL_ON_NT_STATUS(ntStatus);
    }
    else
    {
        wchar16_t wszBackslash[] = {'\\', 0};

        if (!IsNullOrEmptyString(pwszFilename) &&
            SMBWc16sCmp(pwszFilename, &wszBackslash[0]))
        {
            ntStatus = SrvBuildFilePath(
                            NULL,
                            pwszFilename,
                            &pwszFilePath);
            BAIL_ON_NT_STATUS(ntStatus);
        }

        LWIO_LOCK_RWMUTEX_SHARED(bInLock, &pTree->pShareInfo->mutex);

        pFilename->RootFileHandle = pTree->hFile;
    }

    pFilename->FileName = pwszFilePath;

cleanup:

    LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->pShareInfo->mutex);

    return ntStatus;

error:

    goto cleanup;
}
示例#2
0
static
NTSTATUS
SrvBuildOpenResponse(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS                    ntStatus          = 0;
    PLWIO_SRV_CONNECTION        pConnection    = pExecContext->pConnection;
    PSRV_PROTOCOL_EXEC_CONTEXT  pCtxProtocol   = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V1    pCtxSmb1        = pCtxProtocol->pSmb1Context;
    ULONG                       iMsg            = pCtxSmb1->iMsg;
    PSRV_MESSAGE_SMB_V1         pSmbRequest     = &pCtxSmb1->pRequests[iMsg];
    PSRV_MESSAGE_SMB_V1         pSmbResponse    = &pCtxSmb1->pResponses[iMsg];
    POPEN_RESPONSE_HEADER       pResponseHeader = NULL; // Do not free
    PBYTE pOutBuffer       = pSmbResponse->pBuffer;
    ULONG ulBytesAvailable = pSmbResponse->ulBytesAvailable;
    ULONG ulOffset         = 0;
    ULONG ulTotalBytesUsed = 0;
    PSRV_OPEN_STATE_SMB_V1 pOpenState = NULL;

    pOpenState = (PSRV_OPEN_STATE_SMB_V1)pCtxSmb1->hState;

    if (!pSmbResponse->ulSerialNum)
    {
        ntStatus = SrvMarshalHeader_SMB_V1(
                        pOutBuffer,
                        ulOffset,
                        ulBytesAvailable,
                        COM_OPEN_ANDX,
                        STATUS_SUCCESS,
                        TRUE,
                        pConnection->serverProperties.Capabilities,
                        pOpenState->pTree->tid,
                        SMB_V1_GET_PROCESS_ID(pSmbRequest->pHeader),
                        pCtxSmb1->pSession->uid,
                        pSmbRequest->pHeader->mid,
                        pConnection->serverProperties.bRequireSecuritySignatures,
                        &pSmbResponse->pHeader,
                        &pSmbResponse->pWordCount,
                        &pSmbResponse->pAndXHeader,
                        &pSmbResponse->usHeaderSize);
    }
    else
    {
        ntStatus = SrvMarshalHeaderAndX_SMB_V1(
                        pOutBuffer,
                        ulOffset,
                        ulBytesAvailable,
                        COM_OPEN_ANDX,
                        &pSmbResponse->pWordCount,
                        &pSmbResponse->pAndXHeader,
                        &pSmbResponse->usHeaderSize);
    }
    BAIL_ON_NT_STATUS(ntStatus);

    pOutBuffer       += pSmbResponse->usHeaderSize;
    ulOffset         += pSmbResponse->usHeaderSize;
    ulBytesAvailable -= pSmbResponse->usHeaderSize;
    ulTotalBytesUsed += pSmbResponse->usHeaderSize;

    *pSmbResponse->pWordCount = 15;

    if (ulBytesAvailable < sizeof(OPEN_RESPONSE_HEADER))
    {
        ntStatus = STATUS_INVALID_BUFFER_SIZE;
        BAIL_ON_NT_STATUS(ntStatus);
    }

    pResponseHeader = (POPEN_RESPONSE_HEADER)pOutBuffer;

    // pOutBuffer       += sizeof(OPEN_RESPONSE_HEADER);
    // ulOffset         += sizeof(OPEN_RESPONSE_HEADER);
    // ulBytesAvailable -= sizeof(OPEN_RESPONSE_HEADER);
    ulTotalBytesUsed += sizeof(OPEN_RESPONSE_HEADER);

    pResponseHeader->usFid        = pOpenState->pFile->fid;
    pResponseHeader->ulServerFid  = pOpenState->pFile->fid;

    pResponseHeader->usOpenAction = pOpenState->ulCreateAction;
    switch (pOpenState->ucOplockLevel)
    {
        case SMB_OPLOCK_LEVEL_I:

            // file is opened only by this user at the current time
            pResponseHeader->usOpenAction |= 0x8000;

            break;

        default:

            pResponseHeader->usOpenAction &= ~0x8000;

            break;
    }

    // TODO: Mirroring this field is close, but probably not exactly correct
    pResponseHeader->usGrantedAccess = pOpenState->pRequestHeader->usDesiredAccess;

    pResponseHeader->usFileAttributes = pOpenState->networkOpenInfo.FileAttributes;

    ntStatus = WireNTTimeToSMBUTime(
                    pOpenState->networkOpenInfo.LastWriteTime,
                    &pResponseHeader->ulLastWriteTime);
    BAIL_ON_NT_STATUS(ntStatus);

    pResponseHeader->ulDataSize = SMB_MIN(  UINT32_MAX,
                                            pOpenState->networkOpenInfo.EndOfFile);

    if (SrvTreeIsNamedPipe(pOpenState->pTree))
    {
        ntStatus = SrvMarshallPipeInfo(
                        pOpenState->pFilePipeInfo,
                        pOpenState->pFilePipeLocalInfo,
                        &pResponseHeader->usDeviceState);
        BAIL_ON_NT_STATUS(ntStatus);

        pResponseHeader->usFileType = (USHORT)pOpenState->filePipeInfo.ReadMode;
    }
    else
    {
        pResponseHeader->usFileType = 0;
        pResponseHeader->usDeviceState = 0;
    }
    pResponseHeader->usReserved  = 0;
    pResponseHeader->usByteCount = 0;

    pSmbResponse->ulMessageSize = ulTotalBytesUsed;

cleanup:

    return ntStatus;

error:

    if (ulTotalBytesUsed)
    {
        pSmbResponse->pHeader = NULL;
        pSmbResponse->pAndXHeader = NULL;
        memset(pSmbResponse->pBuffer, 0, ulTotalBytesUsed);
    }

    pSmbResponse->ulMessageSize = 0;

    goto cleanup;
}
示例#3
0
static
NTSTATUS
SrvRequestOpenXOplocks(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS        ntStatus           = STATUS_SUCCESS;
    SRV_OPLOCK_INFO batchOplockChain[] =
            {
               { IO_OPLOCK_REQUEST_OPLOCK_BATCH,   SMB_OPLOCK_LEVEL_BATCH },
               { SMB_OPLOCK_LEVEL_NONE,            SMB_OPLOCK_LEVEL_NONE  }
            };
    SRV_OPLOCK_INFO exclOplockChain[] =
            {
               { IO_OPLOCK_REQUEST_OPLOCK_LEVEL_1, SMB_OPLOCK_LEVEL_I     },
               { SMB_OPLOCK_LEVEL_NONE,            SMB_OPLOCK_LEVEL_NONE  }
            };
    SRV_OPLOCK_INFO noOplockChain[] =
            {
               { SMB_OPLOCK_LEVEL_NONE,            SMB_OPLOCK_LEVEL_NONE  }
            };
    PSRV_OPLOCK_INFO           pOplockCursor = NULL;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol  = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V1   pCtxSmb1      = pCtxProtocol->pSmb1Context;
    PSRV_OPEN_STATE_SMB_V1     pOpenState  = NULL;
    PSRV_OPLOCK_STATE_SMB_V1   pOplockState  = NULL;
    BOOLEAN                    bContinue     = TRUE;

    pOpenState = (PSRV_OPEN_STATE_SMB_V1)pCtxSmb1->hState;

    if (SrvTreeIsNamedPipe(pOpenState->pTree) ||
        (pOpenState->pNetworkOpenInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
        (!(pOpenState->pRequestHeader->usFlags &
          (SMB_OPLOCK_REQUEST_BATCH|SMB_OPLOCK_REQUEST_EXCLUSIVE))))
    {
        pOplockCursor = &noOplockChain[0];

        goto done;
    }

    ntStatus = SrvBuildOplockState(
                    pExecContext->pConnection,
                    pCtxSmb1->pSession,
                    pCtxSmb1->pTree,
                    pOpenState->pFile,
                    &pOplockState);
    BAIL_ON_NT_STATUS(ntStatus);

    if (pOpenState->pRequestHeader->usFlags & SMB_OPLOCK_REQUEST_BATCH)
    {
        pOplockCursor = &batchOplockChain[0];
    }
    else if (pOpenState->pRequestHeader->usFlags & SMB_OPLOCK_REQUEST_EXCLUSIVE)
    {
        pOplockCursor = &exclOplockChain[0];
    }
    else
    {
        /* We should never get here, since we don't want to uselessly
         * allocate an OplockState; this is handled at the top of the
         * function.
         */
        LWIO_ASSERT(0);
    }

    while (bContinue && (pOplockCursor->oplockRequest != SMB_OPLOCK_LEVEL_NONE))
    {
        pOplockState->oplockBuffer_in.OplockRequestType =
                        pOplockCursor->oplockRequest;

        SrvPrepareOplockStateAsync(pOplockState);

        ntStatus = IoFsControlFile(
                        pOpenState->pFile->hFile,
                        pOplockState->pAcb,
                        &pOplockState->ioStatusBlock,
                        IO_FSCTL_OPLOCK_REQUEST,
                        &pOplockState->oplockBuffer_in,
                        sizeof(pOplockState->oplockBuffer_in),
                        &pOplockState->oplockBuffer_out,
                        sizeof(pOplockState->oplockBuffer_out));
        switch (ntStatus)
        {
            case STATUS_OPLOCK_NOT_GRANTED:

                SrvReleaseOplockStateAsync(pOplockState); // completed sync

                pOplockCursor++;

                break;

            case STATUS_PENDING:
                InterlockedIncrement(&pOplockState->refCount);

                ntStatus = SrvFileSetOplockState(
                               pOpenState->pFile,
                               pOplockState,
                               &SrvCancelOplockStateHandle,
                               &SrvReleaseOplockStateHandle);
                if (ntStatus != STATUS_SUCCESS)
                {
                    InterlockedDecrement(&pOplockState->refCount);
                }
                BAIL_ON_NT_STATUS(ntStatus);

                SrvFileSetOplockLevel(
                        pOpenState->pFile,
                        pOplockCursor->oplockLevel);

                ntStatus = STATUS_SUCCESS;

                bContinue = FALSE;

                break;

            default:

                SrvReleaseOplockStateAsync(pOplockState); // completed sync

                BAIL_ON_NT_STATUS(ntStatus);

                break;
        }
    }

done:

    pOpenState->ucOplockLevel = pOplockCursor->oplockLevel;

cleanup:

    if (pOplockState)
    {
        SrvReleaseOplockState(pOplockState);
    }

    return ntStatus;

error:

    goto cleanup;
}
示例#4
0
static
NTSTATUS
SrvQueryFileOpenInformation(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS                   ntStatus = 0;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V1   pCtxSmb1     = pCtxProtocol->pSmb1Context;
    PSRV_OPEN_STATE_SMB_V1     pOpenState = NULL;

    pOpenState = (PSRV_OPEN_STATE_SMB_V1)pCtxSmb1->hState;

    if (!IoRtlEcpListIsAcknowledged(
            pOpenState->pEcpList,
            SRV_ECP_TYPE_NET_OPEN_INFO))
    {
        if (!pOpenState->pNetworkOpenInfo)
        {
            pOpenState->pNetworkOpenInfo = &pOpenState->networkOpenInfo;

            SrvPrepareOpenStateAsync(pOpenState, pExecContext);

            ntStatus = IoQueryInformationFile(
                            pOpenState->pFile->hFile,
                            pOpenState->pAcb,
                            &pOpenState->ioStatusBlock,
                            pOpenState->pNetworkOpenInfo,
                            sizeof(pOpenState->networkOpenInfo),
                            FileNetworkOpenInformation);
            BAIL_ON_NT_STATUS(ntStatus);

            SrvReleaseOpenStateAsync(pOpenState); // completed synchronously
        }
    }
    else
    {
        pOpenState->pNetworkOpenInfo = &pOpenState->networkOpenInfo;
    }

    if (!(pOpenState->pNetworkOpenInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
    {
        SrvFileBlockIdleTimeout(pOpenState->pFile);
    }
    else
    {
        SrvFileUnblockIdleTimeout(pOpenState->pFile);
    }

    if (SrvTreeIsNamedPipe(pOpenState->pTree))
    {
        if (!IoRtlEcpListIsAcknowledged(
                    pOpenState->pEcpList,
                    SRV_ECP_TYPE_PIPE_INFO))
        {
            if (!pOpenState->pFilePipeInfo)
            {
                pOpenState->pFilePipeInfo = &pOpenState->filePipeInfo;

                SrvPrepareOpenStateAsync(pOpenState, pExecContext);

                ntStatus = IoQueryInformationFile(
                                pOpenState->pFile->hFile,
                                pOpenState->pAcb,
                                &pOpenState->ioStatusBlock,
                                pOpenState->pFilePipeInfo,
                                sizeof(pOpenState->filePipeInfo),
                                FilePipeInformation);
                BAIL_ON_NT_STATUS(ntStatus);

                SrvReleaseOpenStateAsync(pOpenState); // completed synchronously
            }
        }
        else
        {
            pOpenState->pFilePipeInfo = &pOpenState->filePipeInfo;
        }

        if (!IoRtlEcpListIsAcknowledged(
                    pOpenState->pEcpList,
                    SRV_ECP_TYPE_PIPE_LOCAL_INFO))
        {
            if (!pOpenState->pFilePipeLocalInfo)
            {
                pOpenState->pFilePipeLocalInfo = &pOpenState->filePipeLocalInfo;

                SrvPrepareOpenStateAsync(pOpenState, pExecContext);

                ntStatus = IoQueryInformationFile(
                                pOpenState->pFile->hFile,
                                pOpenState->pAcb,
                                &pOpenState->ioStatusBlock,
                                pOpenState->pFilePipeLocalInfo,
                                sizeof(pOpenState->filePipeLocalInfo),
                                FilePipeLocalInformation);
                BAIL_ON_NT_STATUS(ntStatus);

                SrvReleaseOpenStateAsync(pOpenState); // completed synchronously
            }
        }
        else
        {
            pOpenState->pFilePipeLocalInfo = &pOpenState->filePipeLocalInfo;
        }
    }

cleanup:

    return ntStatus;

error:

    goto cleanup;
}
示例#5
0
static
NTSTATUS
SrvBuildOpenState(
    PSRV_EXEC_CONTEXT       pExecContext,
    POPEN_REQUEST_HEADER    pRequestHeader,
    PWSTR                   pwszFilename,
    PSRV_OPEN_STATE_SMB_V1* ppOpenState
    )
{
    NTSTATUS                   ntStatus       = STATUS_SUCCESS;
    PLWIO_SRV_CONNECTION       pConnection    = pExecContext->pConnection;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol   = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V1   pCtxSmb1       = pCtxProtocol->pSmb1Context;
    PSRV_OPEN_STATE_SMB_V1     pOpenState   = NULL;

    ntStatus = SrvAllocateMemory(
                    sizeof(SRV_OPEN_STATE_SMB_V1),
                    (PVOID*)&pOpenState);
    BAIL_ON_NT_STATUS(ntStatus);

    pOpenState->refCount = 1;

    pthread_mutex_init(&pOpenState->mutex, NULL);
    pOpenState->pMutex = &pOpenState->mutex;

    pOpenState->stage = SRV_OPEN_STAGE_SMB_V1_INITIAL;

    // TODO: Handle root fids
    ntStatus = SrvAllocateMemory(
                    sizeof(IO_FILE_NAME),
                    (PVOID*)&pOpenState->pFilename);
    BAIL_ON_NT_STATUS(ntStatus);

    pOpenState->pTree = SrvTreeAcquire(pCtxSmb1->pTree);

    ntStatus = SrvBuildTreeRelativePath(
                    pCtxSmb1->pTree,
                    pwszFilename,
                    pOpenState->pFilename);
    BAIL_ON_NT_STATUS(ntStatus);

    pOpenState->pwszFilename = pwszFilename;

    ntStatus = IoRtlEcpListAllocate(&pOpenState->pEcpList);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = IoRtlEcpListInsert(pOpenState->pEcpList,
                                  SRV_ECP_TYPE_NET_OPEN_INFO,
                                  &pOpenState->networkOpenInfo,
                                  sizeof(pOpenState->networkOpenInfo),
                                  NULL);
    BAIL_ON_NT_STATUS(ntStatus);

    /* For named pipes, we need to pipe some extra data into the npfs driver:
     *  - Session key
     *  - Client principal name
     *  - Client address
     */
    if (SrvTreeIsNamedPipe(pCtxSmb1->pTree))
    {
        ntStatus = SrvConnectionGetNamedPipeSessionKey(
                       pConnection,
                       pOpenState->pEcpList);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvConnectionGetNamedPipeClientAddress(
                       pConnection,
                       pOpenState->pEcpList);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = IoRtlEcpListInsert(pOpenState->pEcpList,
                                      SRV_ECP_TYPE_PIPE_INFO,
                                      &pOpenState->filePipeInfo,
                                      sizeof(pOpenState->filePipeInfo),
                                      NULL);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = IoRtlEcpListInsert(pOpenState->pEcpList,
                                      SRV_ECP_TYPE_PIPE_LOCAL_INFO,
                                      &pOpenState->filePipeLocalInfo,
                                      sizeof(pOpenState->filePipeLocalInfo),
                                      NULL);
        BAIL_ON_NT_STATUS(ntStatus);
    }

    pOpenState->usCreateOptions = FILE_NON_DIRECTORY_FILE;

    pOpenState->usShareAccess = (FILE_SHARE_READ  |
                                 FILE_SHARE_WRITE |
                                 FILE_SHARE_DELETE);

    switch (pRequestHeader->usDesiredAccess & 0x70)
    {
        case 0x00: /* compatibility mode */

            ntStatus = STATUS_INVALID_PARAMETER;
            BAIL_ON_NT_STATUS(ntStatus);

            break;

        case 0x10: /* deny read/write/execute (exclusive) */

            pOpenState->usShareAccess &= (USHORT)~FILE_SHARE_READ;
            pOpenState->usShareAccess &= (USHORT)~FILE_SHARE_WRITE;

            break;

        case 0x20: /* deny write */

            pOpenState->usShareAccess &= (USHORT)~FILE_SHARE_WRITE;

            break;

        case 0x30: /* deny read/execute */

            pOpenState->usShareAccess &= (USHORT)~FILE_SHARE_READ;

            break;

        case 0x40: /* deny none */

            break;
    }

    /* desired access mask */
    switch (pRequestHeader->usDesiredAccess & 0x7)
    {
        case 0x00:

            pOpenState->ulDesiredAccessMask = GENERIC_READ;

            break;

        case 0x01:

            pOpenState->ulDesiredAccessMask = GENERIC_WRITE;

            break;

        case 0x02:

            pOpenState->ulDesiredAccessMask = GENERIC_READ | GENERIC_WRITE;

            break;

        case 0x03:

            pOpenState->ulDesiredAccessMask = (GENERIC_READ  |
                                               GENERIC_EXECUTE);

            break;

        default:

            ntStatus = STATUS_INVALID_PARAMETER;
            BAIL_ON_NT_STATUS(ntStatus);

            break;
    }

    /* action to take if the file exists */
    switch (pRequestHeader->usOpenFunction)
    {
        case 0x0000: /* Weird EXECUTE -> OPEN_IF semantics */

            if ((pOpenState->ulDesiredAccessMask & GENERIC_EXECUTE) == 0) {
                ntStatus = STATUS_INVALID_DISPOSITION;
                BAIL_ON_NT_STATUS(ntStatus);
            }

            pOpenState->ulCreateDisposition = FILE_OPEN_IF;

            break;

        case 0x0001: /* Open file */

            pOpenState->ulCreateDisposition = FILE_OPEN;

            break;

        case 0x0002: /* truncate file */

            pOpenState->ulCreateDisposition = FILE_OVERWRITE;

            break;

        case 0x0010: /* create new file */

            pOpenState->ulCreateDisposition = FILE_CREATE;

            break;

        case 0x0011: /* open or create file */

            pOpenState->ulCreateDisposition = FILE_OPEN_IF;

            break;

        case 0x0012: /* create or truncate */

            pOpenState->ulCreateDisposition = FILE_OVERWRITE_IF;

            break;

        default:

            ntStatus = STATUS_INVALID_DISPOSITION;
            BAIL_ON_NT_STATUS(ntStatus);

            break;
    }

    pOpenState->pRequestHeader = pRequestHeader;

    *ppOpenState = pOpenState;

cleanup:

    return ntStatus;

error:

    *ppOpenState = NULL;

    if (pOpenState)
    {
        SrvFreeOpenState(pOpenState);
    }

    goto cleanup;
}
示例#6
0
static
NTSTATUS
SrvQueryFileOpenInformation(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS                   ntStatus = 0;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V1   pCtxSmb1     = pCtxProtocol->pSmb1Context;
    PSRV_OPEN_STATE_SMB_V1     pOpenState = NULL;

    pOpenState = (PSRV_OPEN_STATE_SMB_V1)pCtxSmb1->hState;

    if (!pOpenState->pFileBasicInfo)
    {
        pOpenState->pFileBasicInfo = &pOpenState->fileBasicInfo;

        SrvPrepareOpenStateAsync(pOpenState, pExecContext);

        ntStatus = IoQueryInformationFile(
                        pOpenState->pFile->hFile,
                        pOpenState->pAcb,
                        &pOpenState->ioStatusBlock,
                        pOpenState->pFileBasicInfo,
                        sizeof(pOpenState->fileBasicInfo),
                        FileBasicInformation);
        BAIL_ON_NT_STATUS(ntStatus);

        SrvReleaseOpenStateAsync(pOpenState); // completed synchronously
    }

    if (!pOpenState->pFileStdInfo)
    {
        pOpenState->pFileStdInfo = &pOpenState->fileStdInfo;

        SrvPrepareOpenStateAsync(pOpenState, pExecContext);

        ntStatus = IoQueryInformationFile(
                        pOpenState->pFile->hFile,
                        pOpenState->pAcb,
                        &pOpenState->ioStatusBlock,
                        pOpenState->pFileStdInfo,
                        sizeof(pOpenState->fileStdInfo),
                        FileStandardInformation);
        BAIL_ON_NT_STATUS(ntStatus);

        SrvReleaseOpenStateAsync(pOpenState); // completed synchronously
    }

    if (SrvTreeIsNamedPipe(pOpenState->pTree))
    {
        if (!pOpenState->pFilePipeInfo)
        {
            pOpenState->pFilePipeInfo = &pOpenState->filePipeInfo;

            SrvPrepareOpenStateAsync(pOpenState, pExecContext);

            ntStatus = IoQueryInformationFile(
                            pOpenState->pFile->hFile,
                            pOpenState->pAcb,
                            &pOpenState->ioStatusBlock,
                            pOpenState->pFilePipeInfo,
                            sizeof(pOpenState->filePipeInfo),
                            FilePipeInformation);
            BAIL_ON_NT_STATUS(ntStatus);

            SrvReleaseOpenStateAsync(pOpenState); // completed synchronously
        }

        if (!pOpenState->pFilePipeLocalInfo)
        {
            pOpenState->pFilePipeLocalInfo = &pOpenState->filePipeLocalInfo;

            SrvPrepareOpenStateAsync(pOpenState, pExecContext);

            ntStatus = IoQueryInformationFile(
                            pOpenState->pFile->hFile,
                            pOpenState->pAcb,
                            &pOpenState->ioStatusBlock,
                            pOpenState->pFilePipeLocalInfo,
                            sizeof(pOpenState->filePipeLocalInfo),
                            FilePipeLocalInformation);
            BAIL_ON_NT_STATUS(ntStatus);

            SrvReleaseOpenStateAsync(pOpenState); // completed synchronously
        }
    }

cleanup:

    return ntStatus;

error:

    goto cleanup;
}