示例#1
0
static
NTSTATUS
SrvRenameFile(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS                   ntStatus     = 0;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V1   pCtxSmb1     = pCtxProtocol->pSmb1Context;
    PSRV_TRANS2_STATE_SMB_V1   pTrans2State = NULL;

    pTrans2State = (PSRV_TRANS2_STATE_SMB_V1)pCtxSmb1->hState;

    if (!pTrans2State->pData2)
    {
        ntStatus = SrvUnmarshalRenameInformation(pExecContext);
        BAIL_ON_NT_STATUS(ntStatus);
    }

    if (pTrans2State->pRootDir)
    {
        ((PFILE_RENAME_INFORMATION)pTrans2State->pData2)->RootDirectory =
                                                  pTrans2State->pRootDir->hFile;
    }
    else if (!pTrans2State->hDir)
    {
        wchar16_t wszBackSlash[] = { '\\', 0 };

        PFILE_RENAME_INFORMATION pRenameInfo    =
                        (PFILE_RENAME_INFORMATION)pTrans2State->pData2;

        if (*pRenameInfo->FileName == wszBackSlash[0])
        {
            ntStatus = STATUS_NOT_SUPPORTED;
        }
        else if (pTrans2State->pFile)
        {
            ntStatus = SrvGetParentPath(
                            &pTrans2State->pFile->pFilename->Name,
                            &pTrans2State->dirPath.Name);
        }
        else if (pTrans2State->hFile)
        {
            ntStatus = SrvGetParentPath(
                            &pTrans2State->fileName.Name,
                            &pTrans2State->dirPath.Name);
        }
        else
        {
            ntStatus = STATUS_INVALID_PARAMETER;
        }
        BAIL_ON_NT_STATUS(ntStatus);

        pTrans2State->dirPath.RootFileHandle = pTrans2State->pTree->hFile;

        // Catch failed CreateFile calls when they come back around

        ntStatus = pTrans2State->ioStatusBlock.Status;
        BAIL_ON_NT_STATUS(ntStatus);

        SrvPrepareTrans2StateAsync(pTrans2State, pExecContext);

        ntStatus = SrvIoCreateFile(
                                pTrans2State->pTree->pShareInfo,
                                &pTrans2State->hDir,
                                pTrans2State->pAcb,
                                &pTrans2State->ioStatusBlock,
                                pCtxSmb1->pSession->pIoSecurityContext,
                                &pTrans2State->dirPath,
                                pTrans2State->pSecurityDescriptor,
                                pTrans2State->pSecurityQOS,
                                GENERIC_READ,
                                0,
                                FILE_ATTRIBUTE_NORMAL,
                                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                                FILE_OPEN,
                                FILE_DIRECTORY_FILE,
                                NULL, /* EA Buffer */
                                0,    /* EA Length */
                                pTrans2State->pEcpList
                                );
        BAIL_ON_NT_STATUS(ntStatus);

        SrvReleaseTrans2StateAsync(pTrans2State); // completed synchronously
    }

    if (!pTrans2State->pRootDir)
    {
        ((PFILE_RENAME_INFORMATION)pTrans2State->pData2)->RootDirectory =
                                                            pTrans2State->hDir;
    }

    if (!pTrans2State->bSetInfoAttempted)
    {
        pTrans2State->bSetInfoAttempted = TRUE;

        SrvPrepareTrans2StateAsync(pTrans2State, pExecContext);

        ntStatus = IoSetInformationFile(
                    (pTrans2State->pFile ? pTrans2State->pFile->hFile :
                                           pTrans2State->hFile),
                    pTrans2State->pAcb,
                    &pTrans2State->ioStatusBlock,
                    (PFILE_RENAME_INFORMATION)pTrans2State->pData2,
                    pTrans2State->usBytesAllocated,
                    FileRenameInformation);
        BAIL_ON_NT_STATUS(ntStatus);

        SrvReleaseTrans2StateAsync(pTrans2State); // completed synchronously
    }

error:

    return ntStatus;
}
示例#2
0
NTSTATUS
SrvProcessOpenAndX(
    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;
    PLWIO_SRV_SESSION          pSession     = NULL;
    PLWIO_SRV_TREE             pTree        = NULL;
    PSRV_OPEN_STATE_SMB_V1     pOpenState   = NULL;
    BOOLEAN                    bInLock      = FALSE;

    pOpenState = (PSRV_OPEN_STATE_SMB_V1)pCtxSmb1->hState;
    if (pOpenState)
    {
        InterlockedIncrement(&pOpenState->refCount);
    }
    else
    {
        ULONG               iMsg        = pCtxSmb1->iMsg;
        PSRV_MESSAGE_SMB_V1 pSmbRequest = &pCtxSmb1->pRequests[iMsg];
        PBYTE pBuffer          = pSmbRequest->pBuffer + pSmbRequest->usHeaderSize;
        ULONG ulOffset         = pSmbRequest->usHeaderSize;
        ULONG ulBytesAvailable = pSmbRequest->ulMessageSize - pSmbRequest->usHeaderSize;
        POPEN_REQUEST_HEADER pRequestHeader = NULL; // Do not free
        PWSTR                pwszFilename = NULL;   // Do not free

        if (pCtxSmb1->pFile)
        {
            ntStatus = STATUS_INVALID_NETWORK_RESPONSE;
            BAIL_ON_NT_STATUS(ntStatus);
        }

        ntStatus = SrvConnectionFindSession_SMB_V1(
                            pCtxSmb1,
                            pConnection,
                            pSmbRequest->pHeader->uid,
                            &pSession);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvSetStatSessionInfo(pExecContext, pSession);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvSessionFindTree_SMB_V1(
                        pCtxSmb1,
                        pSession,
                        pSmbRequest->pHeader->tid,
                        &pTree);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = WireUnmarshallOpenRequest(
                        pBuffer,
                        ulBytesAvailable,
                        ulOffset,
                        &pRequestHeader,
                        &pwszFilename);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvBuildOpenState(
                        pExecContext,
                        pRequestHeader,
                        pwszFilename,
                        &pOpenState);
        BAIL_ON_NT_STATUS(ntStatus);

        pCtxSmb1->hState = pOpenState;
        InterlockedIncrement(&pOpenState->refCount);
        pCtxSmb1->pfnStateRelease = &SrvReleaseOpenStateHandle;
    }

    LWIO_LOCK_MUTEX(bInLock, &pOpenState->mutex);

    switch (pOpenState->stage)
    {
        case SRV_OPEN_STAGE_SMB_V1_INITIAL:

            SRV_LOG_CALL_DEBUG(
                    pExecContext->pLogContext,
                    SMB_PROTOCOL_VERSION_1,
                    pCtxSmb1->pRequests[pCtxSmb1->iMsg].pHeader->command,
                    &SrvLogOpenState_SMB_V1,
                    pOpenState);

            pOpenState->stage = SRV_OPEN_STAGE_SMB_V1_OPEN_FILE_COMPLETED;

            SrvPrepareOpenStateAsync(pOpenState, pExecContext);

            ntStatus = SrvIoCreateFile(
                            pOpenState->pTree->pShareInfo,
                            &pOpenState->hFile,
                            pOpenState->pAcb,
                            &pOpenState->ioStatusBlock,
                            pSession->pIoSecurityContext,
                            pOpenState->pFilename,
                            pOpenState->pSecurityDescriptor,
                            pOpenState->pSecurityQOS,
                            pOpenState->ulDesiredAccessMask,
                            pOpenState->pRequestHeader->ulAllocationSize,
                            pOpenState->pRequestHeader->usFileAttributes,
                            pOpenState->usShareAccess,
                            pOpenState->ulCreateDisposition,
                            pOpenState->usCreateOptions,
                            NULL, /* EA Buffer */
                            0,    /* EA Length */
                            pOpenState->pEcpList);
            BAIL_ON_NT_STATUS(ntStatus);

            SrvReleaseOpenStateAsync(pOpenState); // completed synchronously

            // intentional fall through

        case SRV_OPEN_STAGE_SMB_V1_OPEN_FILE_COMPLETED:

            ntStatus = pOpenState->ioStatusBlock.Status;
            BAIL_ON_NT_STATUS(ntStatus);

            pOpenState->ulCreateAction =
                            pOpenState->ioStatusBlock.CreateResult;

            ntStatus = SrvTreeCreateFile(
                            pOpenState->pTree,
                            pOpenState->pwszFilename,
                            &pOpenState->hFile,
                            &pOpenState->pFilename,
                            pOpenState->pRequestHeader->usDesiredAccess,
                            pOpenState->pRequestHeader->ulAllocationSize,
                            pOpenState->pRequestHeader->usFileAttributes,
                            pOpenState->usShareAccess,
                            pOpenState->ulCreateDisposition,
                            pOpenState->usCreateOptions,
                            &pOpenState->pFile);
            BAIL_ON_NT_STATUS(ntStatus);

            pOpenState->pFile->pfnCancelAsyncOperationsFile = SrvCancelFileAsyncOperations;

            pOpenState->stage = SRV_OPEN_STAGE_SMB_V1_ATTEMPT_QUERY_INFO;

            // intentional fall through

        case SRV_OPEN_STAGE_SMB_V1_ATTEMPT_QUERY_INFO:

            ntStatus = SrvQueryFileOpenInformation(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            pOpenState->stage = SRV_OPEN_STAGE_SMB_V1_REQUEST_OPLOCK;

            // intentional fall through

        case SRV_OPEN_STAGE_SMB_V1_REQUEST_OPLOCK:

            ntStatus = SrvRequestOpenXOplocks(pExecContext);
            // Don't fail on the account on not being granted an oplock

            pOpenState->stage = SRV_OPEN_STAGE_SMB_V1_QUERY_INFO_COMPLETED;

            // intentional fall through

        case SRV_OPEN_STAGE_SMB_V1_QUERY_INFO_COMPLETED:

            ntStatus = pOpenState->ioStatusBlock.Status;
            BAIL_ON_NT_STATUS(ntStatus);

            if (!pOpenState->pFile->hCancellableBRLStateList)
            {
                PSRV_BYTE_RANGE_LOCK_STATE_LIST pBRLStateList = NULL;

                ntStatus = SrvCreatePendingLockStateList(&pBRLStateList);
                BAIL_ON_NT_STATUS(ntStatus);

                pOpenState->pFile->hCancellableBRLStateList =
                                (HANDLE)pBRLStateList;

                pOpenState->pFile->pfnFreeBRLStateList =
                                &SrvFreePendingLockStateListHandle;
            }

            ntStatus = SrvBuildOpenResponse(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            ntStatus = SrvElementsRegisterResource(
                            &pOpenState->pFile->resource,
                            NULL);
            BAIL_ON_NT_STATUS(ntStatus);

            pOpenState->stage = SRV_OPEN_STAGE_SMB_V1_DONE;

            // intentional fall through

        case SRV_OPEN_STAGE_SMB_V1_DONE:

            if (pOpenState->pRequestHeader->usDesiredAccess & FILE_READ_DATA)
            {
                pOpenState->pFile->ulPermissions |= SRV_PERM_FILE_READ;
            }
            if (pOpenState->pRequestHeader->usDesiredAccess & FILE_WRITE_DATA)
            {
                pOpenState->pFile->ulPermissions |= SRV_PERM_FILE_WRITE;
            }
            if (pOpenState->ulCreateAction == FILE_CREATED)
            {
                pOpenState->pFile->ulPermissions |= SRV_PERM_FILE_CREATE;
            }

            // transfer file so we do not run it down
            pCtxSmb1->pFile = pOpenState->pFile;
            pOpenState->pFile = NULL;

            break;
    }

cleanup:

    if (pTree)
    {
        SrvTreeRelease(pTree);
    }

    if (pSession)
    {
        SrvSessionRelease(pSession);
    }

    if (pOpenState)
    {
        LWIO_UNLOCK_MUTEX(bInLock, &pOpenState->mutex);

        SrvReleaseOpenState(pOpenState);
    }

    return ntStatus;

error:

    switch (ntStatus)
    {
        case STATUS_PENDING:

            // TODO: Add an indicator to the file object to trigger a
            //       cleanup if the connection gets closed and all the
            //       files involved have to be closed

            break;

        default:

            if (pOpenState)
            {
                SrvReleaseOpenStateAsync(pOpenState);
            }

            break;
    }

    goto cleanup;
}
示例#3
0
NTSTATUS
SrvProcessTrans2SetPathInformation(
    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_TRANS2_STATE_SMB_V1   pTrans2State = NULL;
    ACCESS_MASK                accessMask   = 0;

    pTrans2State = (PSRV_TRANS2_STATE_SMB_V1)pCtxSmb1->hState;

    switch (pTrans2State->stage)
    {
        case SRV_TRANS2_STAGE_SMB_V1_INITIAL:

            ntStatus = SrvUnmarshallSetPathInfoParams(
                            pTrans2State->pParameters,
                            pTrans2State->pRequestHeader->parameterCount,
                            &pTrans2State->pSmbInfoLevel,
                            &pTrans2State->pwszFilename);
            BAIL_ON_NT_STATUS(ntStatus);

            ntStatus = SrvConnectionFindSession_SMB_V1(
                            pCtxSmb1,
                            pConnection,
                            pSmbRequest->pHeader->uid,
                            &pTrans2State->pSession);
            BAIL_ON_NT_STATUS(ntStatus);

            ntStatus = SrvSetStatSessionInfo(
                            pExecContext,
                            pTrans2State->pSession);
            BAIL_ON_NT_STATUS(ntStatus);

            ntStatus = SrvSessionFindTree_SMB_V1(
                            pCtxSmb1,
                            pTrans2State->pSession,
                            pSmbRequest->pHeader->tid,
                            &pTrans2State->pTree);
            BAIL_ON_NT_STATUS(ntStatus);

            ntStatus = SrvBuildTreeRelativePath(
                            pTrans2State->pTree,
                            pTrans2State->pwszFilename,
                            &pTrans2State->fileName);
            BAIL_ON_NT_STATUS(ntStatus);

            pTrans2State->stage = SRV_TRANS2_STAGE_SMB_V1_CREATE_FILE_COMPLETED;

            SrvPrepareTrans2StateAsync(pTrans2State, pExecContext);

            accessMask = SrvGetPathAccessMask(pExecContext);

            ntStatus = SrvIoCreateFile(
                            pTrans2State->pTree->pShareInfo,
                            &pTrans2State->hFile,
                            pTrans2State->pAcb,
                            &pTrans2State->ioStatusBlock,
                            pTrans2State->pSession->pIoSecurityContext,
                            &pTrans2State->fileName,
                            pTrans2State->pSecurityDescriptor,
                            pTrans2State->pSecurityQOS,
                            accessMask,
                            0,
                            FILE_ATTRIBUTE_NORMAL,
                            FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                            FILE_OPEN,
                            0,
                            NULL, /* EA Buffer */
                            0,    /* EA Length */
                            pTrans2State->pEcpList
                            );
            BAIL_ON_NT_STATUS(ntStatus);

            SrvReleaseTrans2StateAsync(pTrans2State); // completed synchronously

            // intentional fall through

        case SRV_TRANS2_STAGE_SMB_V1_CREATE_FILE_COMPLETED:

            pTrans2State->stage = SRV_TRANS2_STAGE_SMB_V1_ATTEMPT_IO;

            // intentional fall through

        case SRV_TRANS2_STAGE_SMB_V1_ATTEMPT_IO:

            ntStatus = pTrans2State->ioStatusBlock.Status;
            BAIL_ON_NT_STATUS(ntStatus);

            ntStatus = SrvSetPathInfo(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            pTrans2State->stage = SRV_TRANS2_STAGE_SMB_V1_IO_COMPLETE;

            // intentional fall through

        case SRV_TRANS2_STAGE_SMB_V1_IO_COMPLETE:

            ntStatus = pTrans2State->ioStatusBlock.Status;
            BAIL_ON_NT_STATUS(ntStatus);

            pTrans2State->stage = SRV_TRANS2_STAGE_SMB_V1_BUILD_RESPONSE;

            // intentional fall through

        case SRV_TRANS2_STAGE_SMB_V1_BUILD_RESPONSE:

            ntStatus = SrvBuildSetInfoResponse(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            pTrans2State->stage = SRV_TRANS2_STAGE_SMB_V1_DONE;

            // intentional fall through

        case SRV_TRANS2_STAGE_SMB_V1_DONE:

            break;

        default:

            ntStatus = STATUS_INTERNAL_ERROR;
            BAIL_ON_NT_STATUS(ntStatus);

            break;
    }

cleanup:

    return ntStatus;

error:

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

    pRenameState = (PSRV_RENAME_STATE_SMB_V1)pCtxSmb1->hState;

    ntStatus = pRenameState->ioStatusBlock.Status;
    BAIL_ON_NT_STATUS(ntStatus);

    if (!pRenameState->hDir)
    {
        SrvPrepareRenameStateAsync(pRenameState, pExecContext);

        ntStatus = SrvIoCreateFile(
                        pCtxSmb1->pTree->pShareInfo,
                        &pRenameState->hDir,
                        pRenameState->pAcb,
                        &pRenameState->ioStatusBlock,
                        pCtxSmb1->pSession->pIoSecurityContext,
                        &pRenameState->dirPath,
                        pRenameState->pSecurityDescriptor,
                        pRenameState->pSecurityQOS,
                        GENERIC_READ,
                        0,
                        FILE_ATTRIBUTE_NORMAL,
                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                        FILE_OPEN,
                        FILE_DIRECTORY_FILE,
                        NULL, /* EA Buffer */
                        0,    /* EA Length */
                        pRenameState->pDirEcpList
                        );
        BAIL_ON_NT_STATUS(ntStatus);

        SrvReleaseRenameStateAsync(pRenameState); // completed synchronously
    }

    if (!pRenameState->hFile)
    {
        SrvPrepareRenameStateAsync(pRenameState, pExecContext);

        ntStatus = SrvIoCreateFile(
                        pCtxSmb1->pTree->pShareInfo,
                        &pRenameState->hFile,
                        pRenameState->pAcb,
                        &pRenameState->ioStatusBlock,
                        pCtxSmb1->pSession->pIoSecurityContext,
                        &pRenameState->oldName,
                        pRenameState->pSecurityDescriptor,
                        pRenameState->pSecurityQOS,
                        DELETE,
                        0,
                        FILE_ATTRIBUTE_NORMAL,
                        FILE_SHARE_READ,
                        FILE_OPEN,
                        0,
                        NULL, /* EA Buffer */
                        0,    /* EA Length */
                        pRenameState->pFileEcpList
                        );
        BAIL_ON_NT_STATUS(ntStatus);

        SrvReleaseRenameStateAsync(pRenameState); // completed synchronously
    }

    if (!pRenameState->pFileRenameInfo)
    {
        pRenameState->ulDataLen =
                sizeof(FILE_RENAME_INFORMATION) +
                wc16slen(pRenameState->newName.FileName) * sizeof(wchar16_t);

        ntStatus = SrvAllocateMemory(
                        pRenameState->ulDataLen,
                        (PVOID*)&pRenameState->pData);
        BAIL_ON_NT_STATUS(ntStatus);

        pRenameState->pFileRenameInfo =
                    (PFILE_RENAME_INFORMATION)pRenameState->pData;

        pRenameState->pFileRenameInfo->ReplaceIfExists = FALSE;
        pRenameState->pFileRenameInfo->RootDirectory   = pRenameState->hDir;
        pRenameState->pFileRenameInfo->FileNameLength  =
                wc16slen(pRenameState->newName.FileName) * sizeof(wchar16_t);
        memcpy( (PBYTE)pRenameState->pFileRenameInfo->FileName,
                (PBYTE)pRenameState->newName.FileName,
                pRenameState->pFileRenameInfo->FileNameLength);

        SrvPrepareRenameStateAsync(pRenameState, pExecContext);

        ntStatus = IoSetInformationFile(
                        pRenameState->hFile,
                        pRenameState->pAcb,
                        &pRenameState->ioStatusBlock,
                        pRenameState->pFileRenameInfo,
                        pRenameState->ulDataLen,
                        FileRenameInformation);
        BAIL_ON_NT_STATUS(ntStatus);

        SrvReleaseRenameStateAsync(pRenameState); // completed synchronously
    }

cleanup:

    return ntStatus;

error:

    goto cleanup;
}
示例#5
0
NTSTATUS
SrvFinderCreateSearchSpace(
    IN  IO_FILE_HANDLE  hRootFileHandle,
    IN  PSRV_SHARE_INFO pShareInfo,
    IN  PIO_CREATE_SECURITY_CONTEXT pIoSecurityContext,
    IN  HANDLE         hFinderRepository,
    IN  PWSTR          pwszFilesystemPath,
    IN  PWSTR          pwszSearchPattern,
    IN  SMB_FILE_ATTRIBUTES usSearchAttrs,
    IN  USHORT         usFlags,
    IN  ULONG          ulSearchStorageType,
    IN  SMB_INFO_LEVEL infoLevel,
    IN  BOOLEAN        bUseLongFilenames,
    IN  ACCESS_MASK    accessMask,
    OUT PHANDLE        phFinder,
    OUT PUSHORT        pusSearchId
    )
{
    NTSTATUS ntStatus = 0;
    IO_FILE_HANDLE      hFile = NULL;
    IO_STATUS_BLOCK     ioStatusBlock = {0};
    IO_FILE_NAME        fileName = {0};
    PVOID               pSecurityDescriptor = NULL;
    PVOID               pSecurityQOS = NULL;
    PSRV_FINDER_REPOSITORY pFinderRepository = NULL;
    PSRV_SEARCH_SPACE pSearchSpace = NULL;
    USHORT   usCandidateSearchId = 0;
    BOOLEAN  bFound = FALSE;
    BOOLEAN  bInLock = FALSE;
    PIO_ECP_LIST pEcpList = NULL;
    FILE_CREATE_OPTIONS createOptions = 0;

    pFinderRepository = (PSRV_FINDER_REPOSITORY)hFinderRepository;

    fileName.RootFileHandle = hRootFileHandle;

    ntStatus = LwRtlUnicodeStringInitEx(&fileName.Name, pwszFilesystemPath);
    BAIL_ON_NT_STATUS(ntStatus);

    if (pShareInfo->Flags & SHARE_INFO_FLAG_ABE_ENABLED)
    {
        ntStatus = IoRtlEcpListAllocate(&pEcpList);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvIoPrepareAbeEcpList(pEcpList);
        BAIL_ON_NT_STATUS(ntStatus);
    }

    if (usFlags & SMB_FIND_WITH_BACKUP_INTENT)
    {
        createOptions |= FILE_OPEN_FOR_BACKUP_INTENT;
    }

    ntStatus = SrvIoCreateFile(
                    pShareInfo,
                    &hFile,
                    NULL,
                    &ioStatusBlock,
                    pIoSecurityContext,
                    &fileName,
                    pSecurityDescriptor,
                    pSecurityQOS,
                    accessMask,
                    0,
                    FILE_ATTRIBUTE_NORMAL,
                    FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                    FILE_OPEN,
                    createOptions,
                    NULL, /* EA Buffer */
                    0,    /* EA Length */
                    pEcpList);
    BAIL_ON_NT_STATUS(ntStatus);

    LWIO_LOCK_MUTEX(bInLock, &pFinderRepository->mutex);

    usCandidateSearchId = pFinderRepository->usNextSearchId;

    do
    {
        PSRV_SEARCH_SPACE pSearchSpace = NULL;

	// 0 is not a valid search id

        if (!usCandidateSearchId || (usCandidateSearchId == UINT16_MAX))
        {
            usCandidateSearchId = 1;
        }

        ntStatus = LwRtlRBTreeFind(
                        pFinderRepository->pSearchSpaceCollection,
                        &usCandidateSearchId,
                        (PVOID*)&pSearchSpace);
        if (ntStatus == STATUS_NOT_FOUND)
        {
            ntStatus = STATUS_SUCCESS;
            bFound = TRUE;
        }
	else
	{
            usCandidateSearchId++;
	}

        BAIL_ON_NT_STATUS(ntStatus);

    } while ((usCandidateSearchId != pFinderRepository->usNextSearchId) && !bFound);

    if (!bFound)
    {
        ntStatus = STATUS_TOO_MANY_OPENED_FILES;
        BAIL_ON_NT_STATUS(ntStatus);
    }

    ntStatus = SrvAllocateMemory(
                    sizeof(SRV_SEARCH_SPACE),
                    (PVOID*)&pSearchSpace);
    BAIL_ON_NT_STATUS(ntStatus);

    pSearchSpace->refCount = 1;

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

    pSearchSpace->usSearchId = usCandidateSearchId;

    ntStatus = LwRtlRBTreeAdd(
                    pFinderRepository->pSearchSpaceCollection,
                    &pSearchSpace->usSearchId,
                    pSearchSpace);
    BAIL_ON_NT_STATUS(ntStatus);

    pSearchSpace->hFile = hFile;
    hFile = NULL;
    pSearchSpace->infoLevel = infoLevel;
    pSearchSpace->usSearchAttrs = usSearchAttrs;
    pSearchSpace->ulSearchStorageType = ulSearchStorageType;
    pSearchSpace->bUseLongFilenames = bUseLongFilenames;

    ntStatus = SrvAllocateStringW(
                    pwszSearchPattern,
                    &pSearchSpace->pwszSearchPattern);
    BAIL_ON_NT_STATUS(ntStatus);

    InterlockedIncrement(&pSearchSpace->refCount);

    pFinderRepository->usNextSearchId = usCandidateSearchId + 1;

    *phFinder = pSearchSpace;
    *pusSearchId = usCandidateSearchId;

cleanup:

    LWIO_UNLOCK_MUTEX(bInLock, &pFinderRepository->mutex);

    if (pEcpList)
    {
        IoRtlEcpListFree(&pEcpList);
    }

    return ntStatus;

error:

    *phFinder = NULL;
    *pusSearchId = 0;

    if (pSearchSpace)
    {
        SrvFinderReleaseSearchSpace(pSearchSpace);
    }

    if (hFile)
    {
        IoCloseFile(hFile);
    }

    goto cleanup;
}
示例#6
0
NTSTATUS
SrvProcessCheckDirectory(
    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;
    PLWIO_SRV_SESSION          pSession       = NULL;
    PLWIO_SRV_TREE             pTree          = NULL;
    PSRV_CHECKDIR_STATE_SMB_V1 pCheckdirState = NULL;
    BOOLEAN                    bInLock        = FALSE;

    pCheckdirState = (PSRV_CHECKDIR_STATE_SMB_V1)pCtxSmb1->hState;
    if (pCheckdirState)
    {
        InterlockedIncrement(&pCheckdirState->refCount);
    }
    else
    {
        ULONG               iMsg         = pCtxSmb1->iMsg;
        PSRV_MESSAGE_SMB_V1 pSmbRequest  = &pCtxSmb1->pRequests[iMsg];
        PBYTE pBuffer          = pSmbRequest->pBuffer + pSmbRequest->usHeaderSize;
        ULONG ulOffset         = pSmbRequest->usHeaderSize;
        ULONG ulBytesAvailable = pSmbRequest->ulMessageSize - pSmbRequest->usHeaderSize;
        PWSTR pwszPathFragment = NULL; // Do not free
        PSMB_CHECK_DIRECTORY_REQUEST_HEADER pRequestHeader = NULL;// Do not free

        ntStatus = SrvConnectionFindSession_SMB_V1(
                        pCtxSmb1,
                        pConnection,
                        pSmbRequest->pHeader->uid,
                        &pSession);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvSetStatSessionInfo(pExecContext, pSession);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvSessionFindTree_SMB_V1(
                        pCtxSmb1,
                        pSession,
                        pSmbRequest->pHeader->tid,
                        &pTree);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = WireUnmarshallCheckDirectoryRequest(
                        pBuffer,
                        ulBytesAvailable,
                        ulOffset,
                        &pRequestHeader,
                        &pwszPathFragment);
        BAIL_ON_NT_STATUS(ntStatus);

        if (!pwszPathFragment || !*pwszPathFragment)
        {
            ntStatus = STATUS_INVALID_PARAMETER;
            BAIL_ON_NT_STATUS(ntStatus);
        }

        ntStatus = SrvBuildCheckdirState(
                        pRequestHeader,
                        pwszPathFragment,
                        &pCheckdirState);
        BAIL_ON_NT_STATUS(ntStatus);

        pCtxSmb1->hState = pCheckdirState;
        InterlockedIncrement(&pCheckdirState->refCount);
        pCtxSmb1->pfnStateRelease = &SrvReleaseCheckdirStateHandle;
    }

    LWIO_LOCK_MUTEX(bInLock, &pCheckdirState->mutex);

    switch (pCheckdirState->stage)
    {
        case SRV_CHECKDIR_STAGE_SMB_V1_INITIAL:

            SRV_LOG_CALL_DEBUG(
                    pExecContext->pLogContext,
                    SMB_PROTOCOL_VERSION_1,
                    pCtxSmb1->pRequests[pCtxSmb1->iMsg].pHeader->command,
                    &SrvLogCheckDirState_SMB_V1,
                    pCheckdirState);

            ntStatus = SrvBuildTreeRelativePath(
                            pCtxSmb1->pTree,
                            pCheckdirState->pwszPathFragment,
                            &pCheckdirState->fileName);
            BAIL_ON_NT_STATUS(ntStatus);

            pCheckdirState->stage = SRV_CHECKDIR_STAGE_SMB_V1_ATTEMPT_CHECK;

            // Intentional fall through

        case SRV_CHECKDIR_STAGE_SMB_V1_ATTEMPT_CHECK:

            // Catch failed CreateFile calls when they come back around

            ntStatus = pCheckdirState->ioStatusBlock.Status;
            BAIL_ON_NT_STATUS(ntStatus);

            if (!pCheckdirState->hFile)
            {
                SrvPrepareCheckdirStateAsync(pCheckdirState, pExecContext);

                ntStatus = SrvIoCreateFile(
                                pCtxSmb1->pTree->pShareInfo,
                                &pCheckdirState->hFile,
                                pCheckdirState->pAcb,
                                &pCheckdirState->ioStatusBlock,
                                pCtxSmb1->pSession->pIoSecurityContext,
                                &pCheckdirState->fileName,
                                pCheckdirState->pSecurityDescriptor,
                                pCheckdirState->pSecurityQOS,
                                FILE_LIST_DIRECTORY,
                                0, /* allocation size */
                                FILE_ATTRIBUTE_NORMAL,
                                FILE_SHARE_READ|FILE_SHARE_WRITE,
                                FILE_OPEN,
                                FILE_DIRECTORY_FILE,
                                NULL, /* EA Buffer */
                                0,    /* EA Length */
                                pCheckdirState->pEcpList);
                BAIL_ON_NT_STATUS(ntStatus);

                SrvReleaseCheckdirStateAsync(pCheckdirState); // completed sync
            }

            pCheckdirState->stage = SRV_CHECKDIR_STAGE_SMB_V1_BUILD_RESPONSE;

            // intentional fall through

        case SRV_CHECKDIR_STAGE_SMB_V1_BUILD_RESPONSE:

            ntStatus = pCheckdirState->ioStatusBlock.Status;
            BAIL_ON_NT_STATUS(ntStatus);

            ntStatus = SrvBuildCheckDirectoryResponse(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            pCheckdirState->stage = SRV_CHECKDIR_STAGE_SMB_V1_DONE;

            // intentional fall through

        case SRV_CHECKDIR_STAGE_SMB_V1_DONE:

            break;
    }

cleanup:

    if (pTree)
    {
        SrvTreeRelease(pTree);
    }

    if (pSession)
    {
        SrvSessionRelease(pSession);
    }

    if (pCheckdirState)
    {
        LWIO_UNLOCK_MUTEX(bInLock, &pCheckdirState->mutex);

        SrvReleaseCheckdirState(pCheckdirState);
    }

    return ntStatus;

error:

    switch (ntStatus)
    {
        case STATUS_PENDING:

            // TODO: Add an indicator to the file object to trigger a
            //       cleanup if the connection gets closed and all the
            //       files involved have to be closed

            break;

        default:

            if (pCheckdirState)
            {
                SrvReleaseCheckdirStateAsync(pCheckdirState);
            }

            break;
    }

    goto cleanup;
}
示例#7
0
static
NTSTATUS
SrvDeleteSingleFile(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS                   ntStatus     = STATUS_SUCCESS;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V1   pCtxSmb1     = pCtxProtocol->pSmb1Context;
    PSRV_DELETE_STATE_SMB_V1   pDeleteState = NULL;
    wchar16_t                  wszDot[]     = {'.',  0};

    pDeleteState = (PSRV_DELETE_STATE_SMB_V1)pCtxSmb1->hState;

    if (!pDeleteState->bPendingCreate)
    {
        if ((SMBWc16sCmp(pDeleteState->pwszSearchPattern2, wszDot) == 0))
        {
            ntStatus = STATUS_OBJECT_NAME_INVALID;
            BAIL_ON_NT_STATUS(ntStatus);
        }

        ntStatus = SrvBuildFilePath(
                        pDeleteState->pwszFilesystemPath,
                        pDeleteState->pwszSearchPattern2,
                        &pDeleteState->fileName.Name);
        BAIL_ON_NT_STATUS(ntStatus);

        pDeleteState->fileName.RootFileHandle = pDeleteState->pTree->hFile;

        SrvPrepareDeleteStateAsync(pDeleteState, pExecContext);

        pDeleteState->bPendingCreate = TRUE;

        ntStatus = SrvIoCreateFile(
                        pDeleteState->pTree->pShareInfo,
                        &pDeleteState->hFile,
                        pDeleteState->pAcb,
                        &pDeleteState->ioStatusBlock,
                        pDeleteState->pSession->pIoSecurityContext,
                        &pDeleteState->fileName,
                        pDeleteState->pSecurityDescriptor,
                        pDeleteState->pSecurityQOS,
                        DELETE,
                        0,
                        FILE_ATTRIBUTE_NORMAL,
                        FILE_NO_SHARE,
                        FILE_OPEN,
                        FILE_DELETE_ON_CLOSE|FILE_NON_DIRECTORY_FILE,
                        NULL,
                        0,
                        pDeleteState->pEcpList);
        BAIL_ON_NT_STATUS(ntStatus);

        SrvReleaseDeleteStateAsync(pDeleteState); // completed sync
    }

    pDeleteState->bPendingCreate = FALSE;

    ntStatus = pDeleteState->ioStatusBlock.Status;
    BAIL_ON_NT_STATUS(ntStatus);

    if (pDeleteState->hFile)
    {
        IoCloseFile(pDeleteState->hFile);
        pDeleteState->hFile = NULL;
    }

cleanup:

    return ntStatus;

error:

    /* Have to do some error mapping here to match WinXP */

    switch (ntStatus)
    {
        case STATUS_PENDING:
        case STATUS_ACCESS_DENIED:
        case STATUS_FILE_IS_A_DIRECTORY:
        case STATUS_SHARING_VIOLATION:
        case STATUS_OBJECT_NAME_INVALID:

            break;

        case STATUS_OBJECT_NAME_NOT_FOUND:
        case STATUS_NO_SUCH_FILE:

            ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;

            break;

        default:

            ntStatus = STATUS_CANNOT_DELETE;

            break;
    }

    goto cleanup;
}
示例#8
0
static
NTSTATUS
SrvDeleteFiles(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS                   ntStatus     = STATUS_SUCCESS;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V1   pCtxSmb1     = pCtxProtocol->pSmb1Context;
    PSRV_DELETE_STATE_SMB_V1   pDeleteState = NULL;
    PWSTR                      pwszFilename = NULL;
    wchar16_t wszDot[]                      = {'.',  0};

    pDeleteState = (PSRV_DELETE_STATE_SMB_V1)pCtxSmb1->hState;

    if (pDeleteState->bPendingCreate)
    {
        pDeleteState->bPendingCreate = FALSE;

        ntStatus = pDeleteState->ioStatusBlock.Status;
        BAIL_ON_NT_STATUS(ntStatus);

        IoCloseFile(pDeleteState->hFile);
        pDeleteState->hFile = NULL;

        pDeleteState->bDeletedFile = TRUE;

        pDeleteState->iResult++;
    }

    for (;;)
    {
        for (   ;
                pDeleteState->iResult < pDeleteState->usSearchResultCount;
                pDeleteState->iResult++)
        {
            BOOLEAN bEligibleForDelete = FALSE;
            FILE_ATTRIBUTES ulIncludeAttributes = 0;

            if (!pDeleteState->pResult)
            {
                pDeleteState->pResult =
                    (PSMB_FIND_FILE_BOTH_DIRECTORY_INFO_HEADER)pDeleteState->pData;
            }
            else if (pDeleteState->pResult->NextEntryOffset)
            {
                PBYTE pTmp = (PBYTE)pDeleteState->pResult +
                                pDeleteState->pResult->NextEntryOffset;

                pDeleteState->pResult =
                            (PSMB_FIND_FILE_BOTH_DIRECTORY_INFO_HEADER)pTmp;
            }
            else
            {
                ntStatus = STATUS_INTERNAL_ERROR;
                BAIL_ON_NT_STATUS(ntStatus);
            }

            if (pwszFilename)
            {
                SrvFreeMemory(pwszFilename);
                pwszFilename = NULL;
            }

            ulIncludeAttributes =
                SMB_FILE_ATTRIBUTES_TO_NATIVE(pDeleteState->usSearchAttributes);

            bEligibleForDelete =
                    (IsSetFlag(pDeleteState->pResult->FileAttributes,
                               ulIncludeAttributes & (FILE_ATTRIBUTE_DIRECTORY |
                                                      FILE_ATTRIBUTE_HIDDEN |
                                                      FILE_ATTRIBUTE_SYSTEM))) ||
                    (!IsSetFlag(pDeleteState->pResult->FileAttributes,
                                         (FILE_ATTRIBUTE_DIRECTORY |
                                          FILE_ATTRIBUTE_HIDDEN |
                                          FILE_ATTRIBUTE_SYSTEM)));

            if (!bEligibleForDelete)
            {
                if (!pDeleteState->bPathHasWildCards)
                {
                    if ((SMBWc16sCmp(pDeleteState->pwszSearchPattern2, wszDot) == 0))
                    {
                        ntStatus = STATUS_OBJECT_NAME_INVALID;
                    }
                    else if (IsSetFlag(pDeleteState->pResult->FileAttributes,
                                        FILE_ATTRIBUTE_DIRECTORY))
                    {
                        ntStatus = STATUS_FILE_IS_A_DIRECTORY;
                    }
                    else
                    {
                        ntStatus = STATUS_NO_SUCH_FILE;
                    }
                    BAIL_ON_NT_STATUS(ntStatus);
                }
                continue;
            }

            if (pDeleteState->bUseLongFilenames)
            {
                ntStatus = SrvAllocateMemory(
                                pDeleteState->pResult->FileNameLength + sizeof(wchar16_t),
                                (PVOID*)&pwszFilename);
                BAIL_ON_NT_STATUS(ntStatus);

                memcpy((PBYTE)pwszFilename,
                       (PBYTE)pDeleteState->pResult->FileName,
                       pDeleteState->pResult->FileNameLength);
            }
            else
            {
                ntStatus = SrvAllocateMemory(
                                pDeleteState->pResult->ShortNameLength + sizeof(wchar16_t),
                                (PVOID*)&pwszFilename);
                BAIL_ON_NT_STATUS(ntStatus);

                memcpy((PBYTE)pwszFilename,
                       (PBYTE)pDeleteState->pResult->ShortName,
                       pDeleteState->pResult->ShortNameLength);
            }

            if (SMBWc16sCmp(pwszFilename, wszDot) == 0)
            {
                ntStatus = STATUS_OBJECT_NAME_INVALID;
                BAIL_ON_NT_STATUS(ntStatus);
            }

            SRV_FREE_UNICODE_STRING(&pDeleteState->fileName.Name);

            ntStatus = SrvBuildFilePath(
                            pDeleteState->pwszFilesystemPath,
                            pwszFilename,
                            &pDeleteState->fileName.Name);
            BAIL_ON_NT_STATUS(ntStatus);

            pDeleteState->fileName.RootFileHandle = pDeleteState->pTree->hFile;

            SrvPrepareDeleteStateAsync(pDeleteState, pExecContext);

            pDeleteState->bPendingCreate = TRUE;

            ntStatus = SrvIoCreateFile(
                            pDeleteState->pTree->pShareInfo,
                            &pDeleteState->hFile,
                            pDeleteState->pAcb,
                            &pDeleteState->ioStatusBlock,
                            pDeleteState->pSession->pIoSecurityContext,
                            &pDeleteState->fileName,
                            pDeleteState->pSecurityDescriptor,
                            pDeleteState->pSecurityQOS,
                            DELETE,
                            0,
                            FILE_ATTRIBUTE_NORMAL,
                            FILE_NO_SHARE,
                            FILE_OPEN,
                            FILE_DELETE_ON_CLOSE|FILE_NON_DIRECTORY_FILE,
                            NULL,
                            0,
                            pDeleteState->pEcpList);
            BAIL_ON_NT_STATUS(ntStatus);

            SrvReleaseDeleteStateAsync(pDeleteState); // completed sync

            pDeleteState->bPendingCreate = FALSE;

            IoCloseFile(pDeleteState->hFile);
            pDeleteState->hFile = NULL;

            pDeleteState->bDeletedFile = TRUE;
        }

        if (pDeleteState->bEndOfSearch)
        {
            break;
        }

        if (pDeleteState->pData)
        {
            SrvFreeMemory(pDeleteState->pData);
            pDeleteState->pData = NULL;
        }

        pDeleteState->iResult = 0;
        pDeleteState->pResult = NULL;

        ntStatus = SrvFinderGetSearchResults(
                        pDeleteState->hSearchSpace,
                        FALSE,                 /* bReturnSingleEntry   */
                        FALSE,                 /* bRestartScan         */
                        10,                    /* Desired search count */
                        UINT16_MAX,            /* Max data count       */
                        pDeleteState->usDataOffset,
                        &pDeleteState->pData,
                        &pDeleteState->usDataLen,
                        &pDeleteState->usSearchResultCount,
                        &pDeleteState->bEndOfSearch);

        if (ntStatus == STATUS_NO_MORE_MATCHES)
        {
            ntStatus = STATUS_ASSERTION_FAILURE;
            BAIL_ON_NT_STATUS(ntStatus);
        }

        if (ntStatus == STATUS_NO_SUCH_FILE)
        {
            ntStatus = STATUS_SUCCESS;
            break;
        }
    }

    if (!pDeleteState->bDeletedFile)
    {
        if (pDeleteState->bPathHasWildCards)
        {
            ntStatus = STATUS_NO_SUCH_FILE;
        }
        else
        {
            ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
        }
        BAIL_ON_NT_STATUS(ntStatus);
    }

cleanup:

    if (pwszFilename)
    {
        SrvFreeMemory(pwszFilename);
    }

    return ntStatus;

error:

    /* Have to do some error mapping here to match WinXP */

    switch (ntStatus)
    {
        case STATUS_PENDING:
        case STATUS_ACCESS_DENIED:
        case STATUS_FILE_IS_A_DIRECTORY:
        case STATUS_SHARING_VIOLATION:
        case STATUS_OBJECT_NAME_NOT_FOUND:
        case STATUS_OBJECT_NAME_INVALID:
        case STATUS_NO_SUCH_FILE:

            break;

        default:

            ntStatus = STATUS_CANNOT_DELETE;

            break;
    }

    goto cleanup;
}