NTSTATUS LwNtCreateNamedPipeFile( OUT PIO_FILE_HANDLE FileHandle, IN OUT OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PIO_FILE_NAME FileName, IN OPTIONAL PVOID SecurityDescriptor, // TBD IN OPTIONAL PVOID SecurityQualityOfService, // TBD IN ACCESS_MASK DesiredAccess, IN FILE_SHARE_FLAGS ShareAccess, IN FILE_CREATE_DISPOSITION CreateDisposition, IN FILE_CREATE_OPTIONS CreateOptions, IN FILE_PIPE_TYPE_MASK NamedPipeType, IN FILE_PIPE_READ_MODE_MASK ReadMode, IN FILE_PIPE_COMPLETION_MODE_MASK CompletionMode, IN ULONG MaximumInstances, IN ULONG InboundQuota, IN ULONG OutboundQuota, IN OPTIONAL PLONG64 DefaultTimeout ) { NTSTATUS status = 0; int EE = 0; PIO_ECP_LIST ecpList = NULL; PIO_ECP_NAMED_PIPE pPipeParams = NULL; PCREATEPIPE_CONTEXT pContext = NULL; status = RTL_ALLOCATE(&pPipeParams, IO_ECP_NAMED_PIPE, sizeof(*pPipeParams)); GOTO_CLEANUP_ON_STATUS_EE(status, EE); status = IoRtlEcpListAllocate(&ecpList); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pPipeParams->NamedPipeType = NamedPipeType; pPipeParams->ReadMode = ReadMode; pPipeParams->CompletionMode = CompletionMode; pPipeParams->MaximumInstances = MaximumInstances; pPipeParams->InboundQuota = InboundQuota; pPipeParams->OutboundQuota = OutboundQuota; if (DefaultTimeout) { pPipeParams->DefaultTimeout = *DefaultTimeout; pPipeParams->HaveDefaultTimeout = TRUE; } status = IoRtlEcpListInsert(ecpList, IO_ECP_TYPE_NAMED_PIPE, pPipeParams, sizeof(*pPipeParams), LwRtlMemoryFree); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pPipeParams = NULL; if (AsyncControlBlock) { status = RTL_ALLOCATE(&pContext, CREATEPIPE_CONTEXT, sizeof(*pContext)); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pContext->pEcpList = ecpList; pContext->pChain = AsyncControlBlock; pContext->AsyncControl.Callback = LwNtCreateNamedPipeComplete; pContext->AsyncControl.CallbackContext = pContext; AsyncControlBlock = &pContext->AsyncControl; } status = NtCreateFile( FileHandle, AsyncControlBlock, IoStatusBlock, FileName, SecurityDescriptor, SecurityQualityOfService, DesiredAccess, 0, 0, ShareAccess, CreateDisposition, CreateOptions, NULL, 0, ecpList, NULL); if (pContext) { pContext->pChain->AsyncCancelContext = pContext->AsyncControl.AsyncCancelContext; } cleanup: if (status != STATUS_PENDING) { if (pContext) { IoRtlEcpListFree(&pContext->pEcpList); RTL_FREE(&pContext); } else { IoRtlEcpListFree(&ecpList); } IoStatusBlock->Status = status; RTL_FREE(&pPipeParams); } LOG_LEAVE_IF_STATUS_EE(status, EE); return status; }
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; }