static VOID SrvSessionTreeRelease( PVOID pTree ) { SrvTreeRelease((PLWIO_SRV_TREE)pTree); }
NTSTATUS SrvSessionCreateTree( PLWIO_SRV_SESSION pSession, PSRV_SHARE_INFO pShareInfo, PLWIO_SRV_TREE* ppTree ) { NTSTATUS ntStatus = 0; PLWIO_SRV_TREE pTree = NULL; BOOLEAN bInLock = FALSE; USHORT tid = 0; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pSession->mutex); ntStatus = SrvSessionUpdateLastActivityTime_inlock(pSession); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvSessionAcquireTreeId_inlock( pSession, &tid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvTreeCreate( tid, pShareInfo, &pTree); BAIL_ON_NT_STATUS(ntStatus); ntStatus = LwRtlRBTreeAdd( pSession->pTreeCollection, &pTree->tid, pTree); BAIL_ON_NT_STATUS(ntStatus); pTree->uid = pSession->uid; pTree->ulConnectionResourceId = pSession->ulConnectionResourceId; *ppTree = SrvTreeAcquire(pTree); cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &pSession->mutex); return ntStatus; error: *ppTree = NULL; if (pTree) { SrvTreeRelease(pTree); } goto cleanup; }
static VOID SrvFreeOpenState( PSRV_OPEN_STATE_SMB_V1 pOpenState ) { if (pOpenState->pAcb && pOpenState->pAcb->AsyncCancelContext) { IoDereferenceAsyncCancelContext( &pOpenState->pAcb->AsyncCancelContext); } if (pOpenState->pEcpList) { IoRtlEcpListFree(&pOpenState->pEcpList); } // TODO: Free the following if set // pSecurityDescriptor; // pSecurityQOS; if (pOpenState->pFilename) { SRV_FREE_UNICODE_STRING(&pOpenState->pFilename->Name); SrvFreeMemory(pOpenState->pFilename); } if (pOpenState->hFile) { IoCloseFile(pOpenState->hFile); } if (pOpenState->pFile) { SrvFileResetOplockState(pOpenState->pFile); SrvFileRundown(pOpenState->pFile); SrvFileRelease(pOpenState->pFile); } if (pOpenState->pTree) { SrvTreeRelease(pOpenState->pTree); } if (pOpenState->pMutex) { pthread_mutex_destroy(&pOpenState->mutex); } SrvFreeMemory(pOpenState); }
NTSTATUS SrvProcessTreeDisconnectAndX( 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]; PBYTE pOutBuffer = pSmbResponse->pBuffer; ULONG ulBytesAvailable = pSmbResponse->ulBytesAvailable; ULONG ulOffset = 0; ULONG ulTotalBytesUsed = 0; PTREE_DISCONNECT_RESPONSE_HEADER pResponseHeader = NULL; // Do not free PLWIO_SRV_SESSION pSession = NULL; PLWIO_SRV_TREE pTree = NULL; 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( pSession, pSmbRequest->pHeader->tid, &pTree); BAIL_ON_NT_STATUS(ntStatus); SrvTreeRundown(pTree); ntStatus = SrvSessionRemoveTree(pSession, pSmbRequest->pHeader->tid); BAIL_ON_NT_STATUS(ntStatus); if (!pSmbResponse->ulSerialNum) { ntStatus = SrvMarshalHeader_SMB_V1( pOutBuffer, ulOffset, ulBytesAvailable, COM_TREE_DISCONNECT, STATUS_SUCCESS, TRUE, pSmbRequest->pHeader->tid, SMB_V1_GET_PROCESS_ID(pSmbRequest->pHeader), 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_TREE_DISCONNECT, &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 = 0; if (ulBytesAvailable < sizeof(TREE_DISCONNECT_RESPONSE_HEADER)) { ntStatus = STATUS_INVALID_BUFFER_SIZE; BAIL_ON_NT_STATUS(ntStatus); } pResponseHeader = (PTREE_DISCONNECT_RESPONSE_HEADER)pOutBuffer; pResponseHeader->byteCount = 0; // pOutBuffer += sizeof(TREE_DISCONNECT_RESPONSE_HEADER); // ulOffset += sizeof(TREE_DISCONNECT_RESPONSE_HEADER); // ulBytesAvailable -= sizeof(TREE_DISCONNECT_RESPONSE_HEADER); ulTotalBytesUsed += sizeof(TREE_DISCONNECT_RESPONSE_HEADER); pSmbResponse->ulMessageSize = ulTotalBytesUsed; cleanup: if (pTree) { SrvTreeRelease(pTree); } if (pSession) { SrvSessionRelease(pSession); } return ntStatus; error: if (ulTotalBytesUsed) { pSmbResponse->pHeader = NULL; pSmbResponse->pAndXHeader = NULL; memset(pSmbResponse->pBuffer, 0, ulTotalBytesUsed); } pSmbResponse->ulMessageSize = 0; goto cleanup; }
NTSTATUS SrvTreeCreate( USHORT tid, PSRV_SHARE_INFO pShareInfo, PLWIO_SRV_TREE* ppTree ) { NTSTATUS ntStatus = 0; PLWIO_SRV_TREE pTree = NULL; LWIO_LOG_DEBUG("Creating Tree [tid: %u]", tid); ntStatus = SrvAllocateMemory(sizeof(LWIO_SRV_TREE), (PVOID*)&pTree); BAIL_ON_NT_STATUS(ntStatus); pTree->refcount = 1; pthread_rwlock_init(&pTree->mutex, NULL); pTree->pMutex = &pTree->mutex; pTree->tid = tid; LWIO_LOG_DEBUG("Associating Tree [object:0x%x][tid:%u]", pTree, tid); pTree->pShareInfo = SrvShareAcquireInfo(pShareInfo); ntStatus = LwRtlRBTreeCreate( &SrvTreeFileCompare, NULL, &SrvTreeFileRelease, &pTree->pFileCollection); BAIL_ON_NT_STATUS(ntStatus); ntStatus = LwRtlRBTreeCreate( &SrvTreeAsyncStateCompare, NULL, &SrvTreeAsyncStateRelease, &pTree->pAsyncStateCollection); BAIL_ON_NT_STATUS(ntStatus); SRV_ELEMENTS_INCREMENT_TREE_CONNECTS; *ppTree = pTree; cleanup: return ntStatus; error: *ppTree = NULL; if (pTree) { SrvTreeRelease(pTree); } goto cleanup; }
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; }
NTSTATUS SrvProcessRename( 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_RENAME_STATE_SMB_V1 pRenameState = NULL; BOOLEAN bInLock = FALSE; pRenameState = (PSRV_RENAME_STATE_SMB_V1)pCtxSmb1->hState; if (pRenameState) { InterlockedIncrement(&pRenameState->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; PSMB_RENAME_REQUEST_HEADER pRequestHeader = NULL; // Do not free PWSTR pwszOldName = NULL; // Do not free PWSTR pwszNewName = 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 = WireUnmarshallRenameRequest( pBuffer, ulBytesAvailable, ulOffset, &pRequestHeader, &pwszOldName, &pwszNewName); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvBuildRenameState( pRequestHeader, pwszOldName, pwszNewName, &pRenameState); BAIL_ON_NT_STATUS(ntStatus); pCtxSmb1->hState = pRenameState; InterlockedIncrement(&pRenameState->refCount); pCtxSmb1->pfnStateRelease = &SrvReleaseRenameStateHandle; } LWIO_LOCK_MUTEX(bInLock, &pRenameState->mutex); switch (pRenameState->stage) { case SRV_RENAME_STAGE_SMB_V1_INITIAL: ntStatus = SrvBuildTreeRelativePath( pCtxSmb1->pTree, pRenameState->pwszOldName, &pRenameState->oldName); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvBuildTreeRelativePath( pCtxSmb1->pTree, NULL, &pRenameState->dirPath); BAIL_ON_NT_STATUS(ntStatus); pRenameState->newName.FileName = pRenameState->pwszNewName; pRenameState->stage = SRV_RENAME_STAGE_SMB_V1_ATTEMPT_RENAME; // intentional fall through case SRV_RENAME_STAGE_SMB_V1_ATTEMPT_RENAME: ntStatus = SrvExecuteRename(pExecContext); BAIL_ON_NT_STATUS(ntStatus); pRenameState->stage = SRV_RENAME_STAGE_SMB_V1_BUILD_RESPONSE; // intentional fall through case SRV_RENAME_STAGE_SMB_V1_BUILD_RESPONSE: ntStatus = SrvBuildRenameResponse(pExecContext); BAIL_ON_NT_STATUS(ntStatus); pRenameState->stage = SRV_RENAME_STAGE_SMB_V1_DONE; // intentional fall through case SRV_RENAME_STAGE_SMB_V1_DONE: break; } cleanup: if (pSession) { SrvSessionRelease(pSession); } if (pTree) { SrvTreeRelease(pTree); } if (pRenameState) { LWIO_UNLOCK_MUTEX(bInLock, &pRenameState->mutex); SrvReleaseRenameState(pRenameState); } 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 (pRenameState) { SrvReleaseRenameStateAsync(pRenameState); } break; } goto cleanup; }
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; }
static VOID SrvFreeDeleteState( PSRV_DELETE_STATE_SMB_V1 pDeleteState ) { if (pDeleteState->pAcb && pDeleteState->pAcb->AsyncCancelContext) { IoDereferenceAsyncCancelContext( &pDeleteState->pAcb->AsyncCancelContext); } if (pDeleteState->pEcpList) { IoRtlEcpListFree(&pDeleteState->pEcpList); } if (pDeleteState->hSearchSpace) { NTSTATUS ntStatus2 = 0; ntStatus2 = SrvFinderCloseSearchSpace( pDeleteState->pSession->hFinderRepository, pDeleteState->usSearchId); if (ntStatus2) { LWIO_LOG_ERROR("Failed to close search space [Id:%d][code:%d]", pDeleteState->usSearchId, ntStatus2); } SrvFinderReleaseSearchSpace(pDeleteState->hSearchSpace); } if (pDeleteState->pTree) { SrvTreeRelease(pDeleteState->pTree); } if (pDeleteState->pSession) { SrvSessionRelease(pDeleteState->pSession); } if (pDeleteState->pwszFilesystemPath) { SrvFreeMemory(pDeleteState->pwszFilesystemPath); } if (pDeleteState->pwszSearchPattern2) { SrvFreeMemory(pDeleteState->pwszSearchPattern2); } if (pDeleteState->hFile) { IoCloseFile(pDeleteState->hFile); } if (pDeleteState->pData) { SrvFreeMemory(pDeleteState->pData); } SRV_FREE_UNICODE_STRING(&pDeleteState->fileName.Name); if (pDeleteState->pMutex) { pthread_mutex_destroy(&pDeleteState->mutex); } SrvFreeMemory(pDeleteState); }
static VOID SrvFreeOpenState( PSRV_OPEN_STATE_SMB_V1 pOpenState ) { if (pOpenState->pAcb && pOpenState->pAcb->AsyncCancelContext) { IoDereferenceAsyncCancelContext( &pOpenState->pAcb->AsyncCancelContext); } if (pOpenState->pEcpList) { IoRtlEcpListFree(&pOpenState->pEcpList); } // TODO: Free the following if set // pSecurityDescriptor; // pSecurityQOS; if (pOpenState->pFilename) { if (pOpenState->pFilename->FileName) { SrvFreeMemory(pOpenState->pFilename->FileName); } SrvFreeMemory(pOpenState->pFilename); } if (pOpenState->hFile) { IoCloseFile(pOpenState->hFile); } if (pOpenState->bRemoveFileFromTree) { NTSTATUS ntStatus2 = 0; SrvFileResetOplockState(pOpenState->pFile); ntStatus2 = SrvTreeRemoveFile( pOpenState->pTree, pOpenState->pFile->fid); if (ntStatus2) { LWIO_LOG_ERROR("Failed to remove file from tree [Tid:%d][Fid:%d][code:%d]", pOpenState->pTree->tid, pOpenState->pFile->fid, ntStatus2); } } if (pOpenState->pFile) { SrvFileRelease(pOpenState->pFile); } if (pOpenState->pTree) { SrvTreeRelease(pOpenState->pTree); } if (pOpenState->pMutex) { pthread_mutex_destroy(&pOpenState->mutex); } SrvFreeMemory(pOpenState); }