static VOID SrvExecuteFlushAsyncCB_SMB_V2( PVOID pContext ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_EXEC_CONTEXT pExecContext = (PSRV_EXEC_CONTEXT)pContext; PSRV_PROTOCOL_EXEC_CONTEXT pProtocolContext = pExecContext->pProtocolContext; PSRV_FLUSH_STATE_SMB_V2 pFlushState = NULL; BOOLEAN bInLock = FALSE; pFlushState = (PSRV_FLUSH_STATE_SMB_V2)pProtocolContext->pSmb2Context->hState; LWIO_LOCK_MUTEX(bInLock, &pFlushState->mutex); if (pFlushState->pAcb->AsyncCancelContext) { IoDereferenceAsyncCancelContext(&pFlushState->pAcb->AsyncCancelContext); } pFlushState->pAcb = NULL; LWIO_UNLOCK_MUTEX(bInLock, &pFlushState->mutex); ntStatus = SrvProdConsEnqueue(gProtocolGlobals_SMB_V2.pWorkQueue, pContext); if (ntStatus != STATUS_SUCCESS) { LWIO_LOG_ERROR("Failed to enqueue execution context [status:0x%x]", ntStatus); SrvReleaseExecContext(pExecContext); } }
static VOID SrvReleaseFlushStateAsync_SMB_V2( PSRV_FLUSH_STATE_SMB_V2 pFlushState ) { if (pFlushState->pAcb) { pFlushState->acb.Callback = NULL; if (pFlushState->pAcb->CallbackContext) { PSRV_EXEC_CONTEXT pExecContext = NULL; pExecContext = (PSRV_EXEC_CONTEXT)pFlushState->pAcb->CallbackContext; SrvReleaseExecContext(pExecContext); pFlushState->pAcb->CallbackContext = NULL; } if (pFlushState->pAcb->AsyncCancelContext) { IoDereferenceAsyncCancelContext( &pFlushState->pAcb->AsyncCancelContext); } pFlushState->pAcb = NULL; } }
static VOID SrvExecuteGetInfoAsyncCB_SMB_V2( PVOID pContext ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_EXEC_CONTEXT pExecContext = (PSRV_EXEC_CONTEXT)pContext; PSRV_PROTOCOL_EXEC_CONTEXT pProtocolContext = pExecContext->pProtocolContext; PSRV_GET_INFO_STATE_SMB_V2 pGetInfoState = NULL; BOOLEAN bInLock = FALSE; pGetInfoState = (PSRV_GET_INFO_STATE_SMB_V2)pProtocolContext->pSmb2Context->hState; LWIO_LOCK_MUTEX(bInLock, &pGetInfoState->mutex); if (pGetInfoState->pAcb && pGetInfoState->pAcb->AsyncCancelContext) { IoDereferenceAsyncCancelContext(&pGetInfoState->pAcb->AsyncCancelContext); } pGetInfoState->pAcb = NULL; LWIO_UNLOCK_MUTEX(bInLock, &pGetInfoState->mutex); ntStatus = SrvProtocolExecute(pExecContext); // (!NT_SUCCESS(ntStatus)) - Error has already been logged SrvReleaseExecContext(pExecContext); return; }
VOID SrvReleaseGetInfoStateAsync_SMB_V2( PSRV_GET_INFO_STATE_SMB_V2 pGetInfoState ) { if (pGetInfoState->pAcb) { pGetInfoState->acb.Callback = NULL; if (pGetInfoState->pAcb->CallbackContext) { PSRV_EXEC_CONTEXT pExecContext = NULL; pExecContext = (PSRV_EXEC_CONTEXT)pGetInfoState->pAcb->CallbackContext; SrvReleaseExecContext(pExecContext); pGetInfoState->pAcb->CallbackContext = NULL; } if (pGetInfoState->pAcb->AsyncCancelContext) { IoDereferenceAsyncCancelContext( &pGetInfoState->pAcb->AsyncCancelContext); } pGetInfoState->pAcb = NULL; } }
static VOID SrvUnblockOneWorker( IN PSMB_PROD_CONS_QUEUE pWorkQueue ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_EXEC_CONTEXT pExecContext = NULL; ntStatus = SrvBuildEmptyExecContext(&pExecContext); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvProdConsEnqueue(pWorkQueue, pExecContext); BAIL_ON_NT_STATUS(ntStatus); cleanup: return; error: if (pExecContext) { SrvReleaseExecContext(pExecContext); } goto cleanup; }
VOID SrvReleaseExecContextHandle( IN HANDLE hExecContext ) { SrvReleaseExecContext((PSRV_EXEC_CONTEXT)hExecContext); }
static VOID SrvReleaseOpenStateAsync( PSRV_OPEN_STATE_SMB_V1 pOpenState ) { if (pOpenState->pAcb) { pOpenState->acb.Callback = NULL; if (pOpenState->pAcb->CallbackContext) { PSRV_EXEC_CONTEXT pExecContext = NULL; pExecContext = (PSRV_EXEC_CONTEXT)pOpenState->pAcb->CallbackContext; SrvReleaseExecContext(pExecContext); pOpenState->pAcb->CallbackContext = NULL; } if (pOpenState->pAcb->AsyncCancelContext) { IoDereferenceAsyncCancelContext( &pOpenState->pAcb->AsyncCancelContext); } pOpenState->pAcb = NULL; } }
static VOID SrvReleaseRenameStateAsync( PSRV_RENAME_STATE_SMB_V1 pRenameState ) { if (pRenameState->pAcb) { pRenameState->acb.Callback = NULL; if (pRenameState->pAcb->CallbackContext) { PSRV_EXEC_CONTEXT pExecContext = NULL; pExecContext = (PSRV_EXEC_CONTEXT)pRenameState->pAcb->CallbackContext; SrvReleaseExecContext(pExecContext); pRenameState->pAcb->CallbackContext = NULL; } if (pRenameState->pAcb->AsyncCancelContext) { IoDereferenceAsyncCancelContext( &pRenameState->pAcb->AsyncCancelContext); } pRenameState->pAcb = NULL; } }
static VOID SrvReleaseCheckdirStateAsync( PSRV_CHECKDIR_STATE_SMB_V1 pCheckdirState ) { if (pCheckdirState->pAcb) { pCheckdirState->acb.Callback = NULL; if (pCheckdirState->pAcb->CallbackContext) { PSRV_EXEC_CONTEXT pExecContext = NULL; pExecContext = (PSRV_EXEC_CONTEXT)pCheckdirState->pAcb->CallbackContext; SrvReleaseExecContext(pExecContext); pCheckdirState->pAcb->CallbackContext = NULL; } if (pCheckdirState->pAcb->AsyncCancelContext) { IoDereferenceAsyncCancelContext( &pCheckdirState->pAcb->AsyncCancelContext); } pCheckdirState->pAcb = NULL; } }
VOID SrvReleaseDeleteStateAsync( PSRV_DELETE_STATE_SMB_V1 pDeleteState ) { if (pDeleteState->pAcb) { pDeleteState->acb.Callback = NULL; if (pDeleteState->pAcb->CallbackContext) { PSRV_EXEC_CONTEXT pExecContext = NULL; pExecContext = (PSRV_EXEC_CONTEXT)pDeleteState->pAcb->CallbackContext; SrvReleaseExecContext(pExecContext); pDeleteState->pAcb->CallbackContext = NULL; } if (pDeleteState->pAcb->AsyncCancelContext) { IoDereferenceAsyncCancelContext( &pDeleteState->pAcb->AsyncCancelContext); } pDeleteState->pAcb = NULL; } }
NTSTATUS SrvBuildEmptyExecContext( OUT PSRV_EXEC_CONTEXT* ppContext ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_EXEC_CONTEXT pContext = NULL; ntStatus = SrvAllocateMemory(sizeof(SRV_EXEC_CONTEXT), (PVOID*)&pContext); BAIL_ON_NT_STATUS(ntStatus); pthread_mutex_init(&pContext->execMutex, NULL); pContext->pExecMutex = &pContext->execMutex; ntStatus = SrvLogContextCreate(&pContext->pLogContext); BAIL_ON_NT_STATUS(ntStatus); pContext->refCount = 1; pContext->bInternal = TRUE; *ppContext = pContext; cleanup: return ntStatus; error: *ppContext = NULL; if (pContext) { SrvReleaseExecContext(pContext); } goto cleanup; }
static NTSTATUS SrvNotifyBuildExecContext( PSRV_CHANGE_NOTIFY_STATE_SMB_V1 pNotifyState, PSRV_EXEC_CONTEXT* ppExecContext ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_EXEC_CONTEXT pExecContext = NULL; PSMB_PACKET pSmbRequest = NULL; PBYTE pParams = NULL; ULONG ulParamLength = 0; PBYTE pData = NULL; ULONG ulDataLen = 0; ULONG ulDataOffset = 0; PBYTE pBuffer = NULL; ULONG ulBytesAvailable = 0; ULONG ulOffset = 0; USHORT usBytesUsed = 0; USHORT usTotalBytesUsed = 0; PSMB_HEADER pHeader = NULL; // Do not free PBYTE pWordCount = NULL; // Do not free PANDX_HEADER pAndXHeader = NULL; // Do not free PUSHORT pSetup = NULL; UCHAR ucSetupCount = 0; ULONG ulParameterOffset = 0; ULONG ulNumPackageBytesUsed = 0; SMB_NOTIFY_CHANGE_HEADER notifyRequestHeader = {0}; ntStatus = SMBPacketAllocate( pNotifyState->pConnection->hPacketAllocator, &pSmbRequest); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SMBPacketBufferAllocate( pNotifyState->pConnection->hPacketAllocator, (64 * 1024) + 4096, &pSmbRequest->pRawBuffer, &pSmbRequest->bufferLen); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvInitPacket_SMB_V1(pSmbRequest, TRUE); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvBuildExecContext( pNotifyState->pConnection, pSmbRequest, TRUE, &pExecContext); BAIL_ON_NT_STATUS(ntStatus); pSmbRequest->sequence = pNotifyState->ulRequestSequence; pBuffer = pSmbRequest->pRawBuffer; ulBytesAvailable = pSmbRequest->bufferLen; if (ulBytesAvailable < sizeof(NETBIOS_HEADER)) { ntStatus = STATUS_INVALID_NETWORK_RESPONSE; BAIL_ON_NT_STATUS(ntStatus); } pBuffer += sizeof(NETBIOS_HEADER); ulBytesAvailable -= sizeof(NETBIOS_HEADER); ntStatus = SrvMarshalHeader_SMB_V1( pBuffer, ulOffset, ulBytesAvailable, COM_NT_TRANSACT, pNotifyState->ioStatusBlock.Status, FALSE, /* not a response */ pNotifyState->usTid, pNotifyState->ulPid, pNotifyState->usUid, pNotifyState->usMid, pNotifyState->pConnection->serverProperties.bRequireSecuritySignatures, &pHeader, &pWordCount, &pAndXHeader, &usBytesUsed); BAIL_ON_NT_STATUS(ntStatus); pBuffer += usBytesUsed; ulOffset += usBytesUsed; ulBytesAvailable -= usBytesUsed; usTotalBytesUsed += usBytesUsed; notifyRequestHeader.usFid = pNotifyState->usFid; pSetup = (PUSHORT)¬ifyRequestHeader; ucSetupCount = sizeof(notifyRequestHeader)/sizeof(USHORT); *pWordCount = 18 + ucSetupCount; ntStatus = WireMarshallNtTransactionRequest( pBuffer, ulBytesAvailable, ulOffset, SMB_SUB_COMMAND_NT_TRANSACT_NOTIFY_CHANGE, pSetup, ucSetupCount, pParams, ulParamLength, pData, ulDataLen, &ulDataOffset, &ulParameterOffset, &ulNumPackageBytesUsed); BAIL_ON_NT_STATUS(ntStatus); // pBuffer += ulNumPackageBytesUsed; // ulOffset += ulNumPackageBytesUsed; // ulBytesAvailable -= ulNumPackageBytesUsed; usTotalBytesUsed += ulNumPackageBytesUsed; pSmbRequest->bufferUsed += usTotalBytesUsed; ntStatus = SMBPacketMarshallFooter(pSmbRequest); BAIL_ON_NT_STATUS(ntStatus); *ppExecContext = pExecContext; cleanup: if (pSmbRequest) { SMBPacketRelease( pNotifyState->pConnection->hPacketAllocator, pSmbRequest); } return ntStatus; error: *ppExecContext = NULL; if (pExecContext) { SrvReleaseExecContext(pExecContext); } goto cleanup; }
static VOID SrvNotifyAsyncCB( PVOID pContext ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_EXEC_CONTEXT pExecContext = NULL; BOOLEAN bInLock = FALSE; PSRV_CHANGE_NOTIFY_STATE_SMB_V1 pNotifyState = (PSRV_CHANGE_NOTIFY_STATE_SMB_V1)pContext; LWIO_LOCK_MUTEX(bInLock, &pNotifyState->mutex); if (pNotifyState->pAcb->AsyncCancelContext) { IoDereferenceAsyncCancelContext( &pNotifyState->pAcb->AsyncCancelContext); } pNotifyState->pAcb = NULL; LWIO_UNLOCK_MUTEX(bInLock, &pNotifyState->mutex); ntStatus = SrvNotifyBuildExecContext( pNotifyState, &pExecContext); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvProdConsEnqueue( gProtocolGlobals_SMB_V1.pWorkQueue, pExecContext); BAIL_ON_NT_STATUS(ntStatus); pExecContext = NULL; cleanup: LWIO_UNLOCK_MUTEX(bInLock, &pNotifyState->mutex); if (pNotifyState) { SrvNotifyStateRelease(pNotifyState); } if (pExecContext) { SrvReleaseExecContext(pExecContext); } return; error: LWIO_LOG_ERROR("Error: Failed processing change notify call back " "[status:0x%x]", ntStatus); // TODO: indicate error on file handle somehow goto cleanup; }