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