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; }
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; }
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; }