Beispiel #1
0
NTSTATUS
SrvReadConfig(
    PLWIO_SRV_CONFIG pConfig
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    LWIO_SRV_CONFIG srvConfig = {0};
    PLWIO_CONFIG_REG pReg = NULL;
    BOOLEAN bUsePolicy = TRUE;

    ntStatus = SrvInitConfig(&srvConfig);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = LwIoOpenConfig(
                    "Services\\lwio\\Parameters\\Drivers\\srv",
                    "Policy\\Services\\lwio\\Parameters\\Drivers\\srv",
                    &pReg);
    if (ntStatus)
    {
        LWIO_LOG_ERROR("Failed to access device configuration [error code: %u]",
                       ntStatus);

        ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
    }
    BAIL_ON_NT_STATUS(ntStatus);

    /* Ignore error as it may not exist; we can still use default. */
    LwIoReadConfigBoolean(
            pReg,
            "BootstrapDefaultSharePath",
            bUsePolicy,
            &srvConfig.bBootstrapDefaultSharePath);

    /* Ignore error as it may not exist; we can still use default. */
    LwIoReadConfigDword(
            pReg,
            "MonitorIntervalMinutes",
            bUsePolicy,
            LWIO_SRV_DEFAULT_MONITOR_INTERVAL_MINS_MIN,
            LWIO_SRV_DEFAULT_MONITOR_INTERVAL_MINS_MAX,
            &srvConfig.ulMonitorIntervalMinutes);

    ntStatus = SrvTransferConfigContents(&srvConfig, pConfig);
    BAIL_ON_NT_STATUS(ntStatus);

cleanup:

    if (pReg)
    {
        LwIoCloseConfig(pReg);
    }

    SrvFreeConfigContents(&srvConfig);

    return ntStatus;

error:

    goto cleanup;
}
Beispiel #2
0
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);
    }
}
Beispiel #3
0
static
VOID
SrvDriverShutdown(
    IN IO_DRIVER_HANDLE hDriver
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;

    ntStatus = SrvShutdown();
    BAIL_ON_NT_STATUS(ntStatus);

    if (gSMBSrvGlobals.hDevice)
    {
        IoDeviceDelete(&gSMBSrvGlobals.hDevice);
    }

cleanup:

    return;

error:

    if (ntStatus)
    {
        LWIO_LOG_ERROR("[srv] driver failed to stop. [code: %d]", ntStatus);
    }

    goto cleanup;
}
Beispiel #4
0
NTSTATUS
SrvStatsConfigRead(
    PSRV_STATISTICS_CONFIG pConfig
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    SRV_STATISTICS_CONFIG config = { 0 };
    PLWIO_CONFIG_REG pReg = NULL;
    BOOLEAN bUsePolicy = TRUE;

    ntStatus = SrvStatsConfigInitContents(&config);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = LwIoOpenConfig(
                "Services\\lwio\\Parameters\\Drivers\\srv\\statistics",
                "Policy\\Services\\lwio\\Parameters\\Drivers\\srv\\statistics",
                &pReg);
    if (ntStatus)
    {
        LWIO_LOG_ERROR(
            "Failed to access device statistics configuration [error code: %u]",
            ntStatus);

        ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
    }
    BAIL_ON_NT_STATUS(ntStatus);

    /* Ignore error as it may not exist; we can still use default. */
    LwIoReadConfigString(
            pReg,
            "Path",
            bUsePolicy,
            &config.pszProviderPath);

    LwIoReadConfigBoolean(
            pReg,
            "EnableLogging",
            bUsePolicy,
            &config.bEnableLogging);

    ntStatus = SrvStatsConfigTransferContents(&config, pConfig);
    BAIL_ON_NT_STATUS(ntStatus);

cleanup:

    if (pReg)
    {
        LwIoCloseConfig(pReg);
    }

    return ntStatus;

error:

    SrvStatsConfigFreeContents(&config);

    goto cleanup;
}
Beispiel #5
0
static
NTSTATUS
SrvShareBootstrapDiskRoot(
    IN OUT PLWIO_SRV_SHARE_ENTRY_LIST pShareList
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    wchar16_t wszFileRootName[] = {'C','$',0};
    PSTR  pszDefaultSharePath = NULL;
    PWSTR pwszFileSystemRoot = NULL;
    PSRV_SHARE_INFO pShareInfo = NULL;

    ntStatus = SrvShareFindByName(
                        pShareList,
                        &wszFileRootName[0],
                        &pShareInfo);
    if (ntStatus == STATUS_NOT_FOUND)
    {
        wchar16_t wszDesc[] =
                        {'D','e','f','a','u','l','t',' ','S','h','a','r','e',0};
        wchar16_t wszServiceType[] = LWIO_SRV_SHARE_STRING_ID_DISK_W;

        ntStatus = SrvGetDefaultSharePath(&pszDefaultSharePath);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvMbsToWc16s(pszDefaultSharePath, &pwszFileSystemRoot);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvCreateDefaultSharePath(pwszFileSystemRoot);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvShareAdd(
                        pShareList,
                        &wszFileRootName[0],
                        pwszFileSystemRoot,
                        &wszDesc[0],
                        NULL,
                        0,
                        &wszServiceType[0],
                        0);
    }
    BAIL_ON_NT_STATUS(ntStatus);

cleanup:

    SRV_SAFE_FREE_MEMORY(pszDefaultSharePath);
    SRV_SAFE_FREE_MEMORY(pwszFileSystemRoot);

    return ntStatus;

error:

    LWIO_LOG_ERROR("Failed to bootstrap default shares. [error code: %d]",
                   ntStatus);

    goto cleanup;
}
Beispiel #6
0
static
void
smb_display_status_1(
    PCSTR     pszId,
    OM_uint32 code,
    int       type
    )
{
    OM_uint32 min_stat;
    gss_buffer_desc msg;
    OM_uint32 msg_ctx;

    if ( code == 0 )
    {
        return;
    }

    msg_ctx = 0;
    while (1)
    {
        (void) gss_display_status(&min_stat, code,
                                  type, GSS_C_NULL_OID,
                                  &msg_ctx, &msg);

        switch(code)
        {
#ifdef WIN32
            case SEC_E_OK:
            case SEC_I_CONTINUE_NEEDED:
#else
            case GSS_S_COMPLETE:
            case GSS_S_CONTINUE_NEEDED:
#endif
                LWIO_LOG_VERBOSE("GSS-API error calling %s: %d (%s)\n",
                        pszId, code,
                        LWIO_SAFE_LOG_STRING((char *)msg.value));
                break;

            default:

                LWIO_LOG_ERROR("GSS-API error calling %s: %d (%s)\n",
                        pszId, code,
                        LWIO_SAFE_LOG_STRING((char *)msg.value));
        }

        (void) gss_release_buffer(&min_stat, &msg);

        if (!msg_ctx)
            break;
    }
}
Beispiel #7
0
static
NTSTATUS
SrvShareBootstrapNamedPipeRoot(
    IN OUT PLWIO_SRV_SHARE_ENTRY_LIST pShareList
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    wchar16_t wszPipeRootName[] = {'I','P','C','$',0};
    PSRV_SHARE_INFO pShareInfo = NULL;

    ntStatus = SrvShareFindByName(
                    pShareList,
                    &wszPipeRootName[0],
                    &pShareInfo);
    if (ntStatus == STATUS_NOT_FOUND)
    {
        wchar16_t wszPipeSystemRoot[] = LWIO_SRV_PIPE_SYSTEM_ROOT_W;
        wchar16_t wszServiceType[] = LWIO_SRV_SHARE_STRING_ID_IPC_W;
        wchar16_t wszDesc[] = {'R','e','m','o','t','e',' ','I','P','C',0};

        ntStatus = SrvShareAdd(
                            pShareList,
                            &wszPipeRootName[0],
                            &wszPipeSystemRoot[0],
                            &wszDesc[0],
                            NULL,
                            0,
                            &wszServiceType[0],
                            0);
        BAIL_ON_NT_STATUS(ntStatus);
    }

cleanup:

    if (pShareInfo)
    {
        SrvShareReleaseInfo(pShareInfo);
    }

    return ntStatus;

error:

    LWIO_LOG_ERROR("Failed to bootstrap default IPC$ shares. [error code: %d]",
                   ntStatus);

    goto cleanup;
}
Beispiel #8
0
VOID
RdrTree2Release(
    RDR_TREE2 *pTree
    )
{
    BOOLEAN bInLock = FALSE;
    LW_TASK_EVENT_MASK dummy = 0;
    LONG64 llDummy = 0;

    LWIO_LOCK_MUTEX(bInLock, &pTree->pSession->mutex);

    assert(pTree->refCount > 0);

    if (--pTree->refCount == 0)
    {
        if (pTree->state != RDR_TREE_STATE_READY || !RdrSocketIsValid(pTree->pSession->pSocket))
        {
            RdrTree2Unlink(pTree);
            LWIO_UNLOCK_MUTEX(bInLock, &pTree->pSession->mutex);
            RdrTree2Free(pTree);
        }
        else
        {
            LWIO_LOG_VERBOSE("Tree %p is eligible for reaping", pTree);

            LWIO_UNLOCK_MUTEX(bInLock, &pTree->pSession->mutex);

            if (LwRtlCreateTask(
                    gRdrRuntime.pThreadPool,
                    &pTree->pTimeout,
                    gRdrRuntime.pTreeTimerGroup,
                    RdrTree2Timeout,
                    pTree) == STATUS_SUCCESS)
            {
                LwRtlWakeTask(pTree->pTimeout);
            }
            else
            {
                LWIO_LOG_ERROR("Could not create timer for tree %p; disconnecting immediately");
                RdrTree2Timeout(NULL, pTree, LW_TASK_EVENT_TIME, &dummy, &llDummy);
            }
        }
    }
    else
    {
        LWIO_UNLOCK_MUTEX(bInLock, &pTree->pSession->mutex);
    }
}
Beispiel #9
0
NTSTATUS
PvfsMapUnixErrnoToNtStatus(
    int err
    )
{
    NTSTATUS ntError = LwErrnoToNtStatus(err);

    if (ntError == (NTSTATUS)-1)
    {
        LWIO_LOG_ERROR(
            "%s: Unable to map Unix errno (%d) to an NTSTATUS error.\n",
            PVFS_LOG_HEADER,
            err);
    }

    return ntError;
}
Beispiel #10
0
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);
}
Beispiel #11
0
static
NTSTATUS
SrvShareDbCreate(
    VOID
    )
{
    NTSTATUS ntStatus = 0;
    PSRV_SHARE_DB_CONTEXT pDbContext = NULL;
    PSTR pszError = NULL;
    BOOLEAN bExists = FALSE;
    PCSTR pszShareDBPath = LWIO_SRV_SHARE_DB;
    PCSTR pszShareDBDir = LWIO_SRV_DB_DIR;
    BOOLEAN bInLock = FALSE;

    ntStatus = SMBCheckFileExists(pszShareDBPath, &bExists);
    BAIL_ON_NT_STATUS(ntStatus);

    // TODO: Implement an upgrade scenario
    if (bExists)
    {
       goto cleanup;
    }

    ntStatus = SMBCheckDirectoryExists(pszShareDBDir, &bExists);
    BAIL_ON_NT_STATUS(ntStatus);

    if (!bExists)
    {
        mode_t cacheDirMode = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;

        /* Allow go+rx to the base folder */
        ntStatus = SMBCreateDirectory(pszShareDBDir, cacheDirMode);
        BAIL_ON_NT_STATUS(ntStatus);
    }

    /* restrict access to u+rwx to the db folder */
    ntStatus = SMBChangeOwnerAndPermissions(pszShareDBDir, 0, 0, S_IRWXU);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = SrvShareDbAcquireContext(&pDbContext);
    BAIL_ON_NT_STATUS(ntStatus);

    LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &gShareRepository_lwshare.dbMutex);

    ntStatus = sqlite3_exec(
                       pDbContext->pDbHandle,
                       DB_QUERY_CREATE_SHARES_TABLE,
                       NULL,
                       NULL,
                       &pszError);
    BAIL_ON_LWIO_SRV_SQLITE_ERROR_DB(ntStatus, pDbContext->pDbHandle);

    ntStatus = SMBChangeOwnerAndPermissions(
                    pszShareDBPath,
                    0,
                    0,
                    S_IRWXU);
    BAIL_ON_NT_STATUS(ntStatus);

cleanup:

    if (pDbContext)
    {
        SrvShareDbReleaseContext(pDbContext);
    }

    LWIO_UNLOCK_RWMUTEX(bInLock, &gShareRepository_lwshare.dbMutex);

    return ntStatus;

error:

    if (pszError)
    {
       LWIO_LOG_ERROR("%s", pszError);
       sqlite3_free(pszError);
    }

    goto cleanup;
}
Beispiel #12
0
static
VOID
IopIrpCompleteInternal(
    IN OUT PIRP pIrp,
    IN BOOLEAN IsAsyncCompletion
    )
{
    PIRP_INTERNAL irpInternal = IopIrpGetInternal(pIrp);

    IopIrpAcquireCancelLock(pIrp);

    LWIO_ASSERT_MSG(IS_BOTH_OR_NEITHER(IsAsyncCompletion, IsSetFlag(irpInternal->Flags, IRP_FLAG_PENDING)), "IRP pending state is inconsistent.");
    LWIO_ASSERT_MSG(IsSetFlag(irpInternal->Flags, IRP_FLAG_DISPATCHED), "IRP cannot be completed unless it was properly dispatched.");
    LWIO_ASSERT_MSG(!IsSetFlag(irpInternal->Flags, IRP_FLAG_COMPLETE), "IRP cannot be completed more than once.");

    //
    // Note that the IRP may be CANCEL_PENDING or CANCELLED, but that
    // is ok.  In fact, completion may have been called in response
    // to cancellation.
    //

    SetFlag(irpInternal->Flags, IRP_FLAG_COMPLETE);

    IopIrpReleaseCancelLock(pIrp);

    IopFileObjectRemoveDispatched(pIrp->FileHandle, pIrp->Type);

    LWIO_ASSERT(IsValidStatusForIrpType(pIrp->IoStatusBlock.Status, pIrp->Type));

    switch (pIrp->Type)
    {
    case IRP_TYPE_CREATE:
    case IRP_TYPE_CREATE_NAMED_PIPE:
        if ((STATUS_SUCCESS == pIrp->IoStatusBlock.Status) ||
            (STATUS_OPLOCK_BREAK_IN_PROGRESS == pIrp->IoStatusBlock.Status))
        {
            // Handle special success processing having to do with file handle.
            // ISSUE-May not need lock since it should be only reference
            IopFileObjectLock(pIrp->FileHandle);
            SetFlag(pIrp->FileHandle->Flags, FILE_OBJECT_FLAG_CREATE_DONE);
            IopFileObjectUnlock(pIrp->FileHandle);

            IopFileObjectReference(pIrp->FileHandle);
            if (IsAsyncCompletion && irpInternal->Completion.IsAsyncCall)
            {
                *irpInternal->Completion.Async.OpOut.Create.pFileHandle = pIrp->FileHandle;
            }
        }
        break;

    case IRP_TYPE_CLOSE:
        if (STATUS_SUCCESS == pIrp->IoStatusBlock.Status)
        {
            PIO_FILE_OBJECT pFileObject = NULL;

            SetFlag(pIrp->FileHandle->Flags, FILE_OBJECT_FLAG_CLOSE_DONE);

            // Note that we must delete the reference from the create
            // w/o removing the file object value from the IRP (which
            // will be removed when the IRP is freed).

            pFileObject = pIrp->FileHandle;
            IopFileObjectDereference(&pFileObject);
        }
        else
        {
            LWIO_LOG_ERROR("Unable to close file object, status = 0x%08x",
                           pIrp->IoStatusBlock.Status);
        }
        break;

    case IRP_TYPE_READ:
    case IRP_TYPE_WRITE:
        if (IRP_ZCT_OPERATION_PREPARE == pIrp->Args.ReadWrite.ZctOperation)
        {
            if (STATUS_SUCCESS == pIrp->IoStatusBlock.Status)
            {
                LWIO_ASSERT(pIrp->Args.ReadWrite.ZctCompletionContext);

                if (IsAsyncCompletion && irpInternal->Completion.IsAsyncCall)
                {
                    PIRP pCompletionIrp = irpInternal->Completion.Async.OpOut.PrepareZctReadWrite.pCompletionIrp;
                    PVOID pCompletionContext = IopIrpSaveZctIrp(
                                                    pIrp->FileHandle,
                                                    pCompletionIrp,
                                                    pIrp->Args.ReadWrite.ZctCompletionContext);
                    *irpInternal->Completion.Async.OpOut.PrepareZctReadWrite.pCompletionContext = pCompletionContext;
                }
            }
            if (irpInternal->Completion.IsAsyncCall)
            {
                IopIrpDereference(&irpInternal->Completion.Async.OpOut.PrepareZctReadWrite.pCompletionIrp);
            }
        }
        break;
    }

    if (IsAsyncCompletion)
    {
        if (irpInternal->Completion.IsAsyncCall)
        {
            *irpInternal->Completion.Async.pIoStatusBlock = pIrp->IoStatusBlock;
            irpInternal->Completion.Async.Callback(
                    irpInternal->Completion.Async.CallbackContext);
        }
        else
        {
            LwRtlSetEvent(irpInternal->Completion.Sync.Event);
        }

        //
        // Release reference from IoIrpMarkPending().
        //

        IopIrpDereference(&pIrp);
    }
}
Beispiel #13
0
static NTSTATUS
PvfsDoZctSpliceWriteIo(
    IN PPVFS_ZCT_CONTEXT pZctContext,
    IN ULONG BufferLength,
    IN LONG64 Offset,
    OUT PULONG pBytesWritten
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    LONG64 currentOffset = Offset;
    ULONG totalBytesWritten = 0;

    while (totalBytesWritten < BufferLength)
    {
        ULONG bytesWritten = 0;

        // Using SPLICE_F_NONBLOCK because would block
        // on non-blocking pipe otherwise.
        ntError = PvfsSysSplice(pZctContext->PipeFds[0],
                                NULL,
                                pZctContext->pCcb->fd,
                                &currentOffset,
                                BufferLength - totalBytesWritten,
                                SPLICE_F_MOVE | SPLICE_F_NONBLOCK,
                                &bytesWritten);
        if (ntError == STATUS_MORE_PROCESSING_REQUIRED)
        {
            continue;
        }
        if (ntError == STATUS_RETRY)
        {
            // splice returned EAGAIN.  This normally
            // happens if the pipe buffer is not bit enough.
            // This should never happen due to the splice
            // pipe buffer check in PvfsCreateZctContext.
            // In write completion, there is nothing we can
            // do about it except to log.
            LWIO_LOG_ERROR("Unexpected splice failure with EAGAIN/STATUS_RETRY");
        }
        BAIL_ON_NT_STATUS(ntError);

        /* Check for EOF */
        if (bytesWritten == 0) {
            break;
        }

        totalBytesWritten += bytesWritten;
    }

    /* Can only get here is the loop was completed successfully */

cleanup:
    *pBytesWritten = totalBytesWritten;

    return ntError;

error:
    totalBytesWritten = 0;

    goto cleanup;
}
Beispiel #14
0
static
PVOID
SrvTimerMain(
    IN  PVOID pData
    )
{
    NTSTATUS status = 0;
    PSRV_TIMER_CONTEXT pContext = (PSRV_TIMER_CONTEXT)pData;
    PSRV_TIMER_REQUEST pTimerRequest = NULL;
    LONG64 llCurTime = 0LL;
    BOOLEAN bInLock = FALSE;

    LWIO_LOG_DEBUG("Srv timer starting");

    LWIO_LOCK_MUTEX(bInLock, &pContext->mutex);

    while (!SrvTimerMustStop_inlock(pContext))
    {
        int errCode = 0;
        BOOLEAN bRetryWait = FALSE;

        // If we have a current timer request, check if it is time to service it
        if (pTimerRequest)
        {
            status = WireGetCurrentNTTime(&llCurTime);
            BAIL_ON_NT_STATUS(status);

            if (llCurTime >= pTimerRequest->llExpiry &&
                !pTimerRequest->bCanceled)
            {
                SrvTimerDetachRequest_inlock(pContext, pTimerRequest);

                LWIO_UNLOCK_MUTEX(bInLock, &pContext->mutex);

                if (pTimerRequest->pfnTimerExpiredCB)
                {
                    // Timer has not been canceled
                    pTimerRequest->pfnTimerExpiredCB(
                                        pTimerRequest,
                                        pTimerRequest->pUserData);
                }

                LWIO_LOCK_MUTEX(bInLock, &pContext->mutex);
            }

            SrvTimerRelease(pTimerRequest);
            pTimerRequest = NULL;
        }

        // Get the next timer request in queue
        status = SrvTimerGetNextRequest_inlock(pContext, &pTimerRequest);
        if (status == STATUS_NOT_FOUND)
        {
            // If the queue is empty wait for a day or until a request arrives
            struct timespec tsLong = { .tv_sec = time(NULL) + 86400,
                                       .tv_nsec = 0 };

            status = STATUS_SUCCESS;

            do
            {
                bRetryWait = FALSE;

                errCode = pthread_cond_timedwait(
                                &pContext->event,
                                &pContext->mutex,
                                &tsLong);

                if (errCode == ETIMEDOUT)
                {
                    if (time(NULL) < tsLong.tv_sec)
                    {
                        bRetryWait = TRUE;
                        continue;
                    }

                    break;
                }

                status = LwErrnoToNtStatus(errCode);
                BAIL_ON_NT_STATUS(status);

            } while (bRetryWait && !SrvTimerMustStop_inlock(pContext));

            continue;
        }
        BAIL_ON_NT_STATUS(status);

        // At this point, we have a timer request - wait for its specified time
        do
        {
            struct timespec ts = {.tv_sec = 0, .tv_nsec = 0};
            bRetryWait = FALSE;

            status = WireNTTimeToTimeSpec(pTimerRequest->llExpiry, &ts);
            BAIL_ON_NT_STATUS(status);

            errCode = pthread_cond_timedwait(
                            &pContext->event,
                            &pContext->mutex,
                            &ts);
            if (errCode == ETIMEDOUT)
            {
                status = WireGetCurrentNTTime(&llCurTime);
                BAIL_ON_NT_STATUS(status);

                if (llCurTime < pTimerRequest->llExpiry)
                {
                    bRetryWait = TRUE;
                    continue;
                }

                break;
            }

            status = LwErrnoToNtStatus(errCode);
            BAIL_ON_NT_STATUS(status);

        } while (bRetryWait && !SrvTimerMustStop_inlock(pContext));
    }

cleanup:

    LWIO_UNLOCK_MUTEX(bInLock, &pContext->mutex);

    if (pTimerRequest)
    {
        SrvTimerRelease(pTimerRequest);
    }

    LWIO_LOG_DEBUG("Srv timer stopping");

    return NULL;

error:

    LWIO_LOG_ERROR("Srv timer stopping due to error [%d]", status);

    goto cleanup;
}

static
NTSTATUS
SrvTimerGetNextRequest_inlock(
    IN  PSRV_TIMER_CONTEXT  pContext,
    OUT PSRV_TIMER_REQUEST* ppTimerRequest
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PSRV_TIMER_REQUEST pTimerRequest = NULL;

    if (!pContext->pRequests)
    {
        status = STATUS_NOT_FOUND;
        BAIL_ON_NT_STATUS(status);
    }

    pTimerRequest = pContext->pRequests;

    InterlockedIncrement(&pTimerRequest->refCount);

    *ppTimerRequest = pTimerRequest;

cleanup:

    return status;

error:

    *ppTimerRequest = NULL;

    goto cleanup;
}

static
NTSTATUS
SrvTimerDetachRequest_inlock(
    IN OUT PSRV_TIMER_CONTEXT pContext,
    IN OUT PSRV_TIMER_REQUEST pTimerRequest
    )
{
    if (pTimerRequest->pPrev)
    {
        pTimerRequest->pPrev->pNext = pTimerRequest->pNext;

        if (pTimerRequest->pNext)
        {
            pTimerRequest->pNext->pPrev = pTimerRequest->pPrev;
        }
    }
    else
    {
        pContext->pRequests = pTimerRequest->pNext;

        if (pTimerRequest->pNext)
        {
            pTimerRequest->pNext->pPrev = NULL;
        }
    }

    pTimerRequest->pPrev = NULL;
    pTimerRequest->pNext = NULL;

    // Removed from timer queue
    InterlockedDecrement(&pTimerRequest->refCount);

    return STATUS_SUCCESS;
}

NTSTATUS
SrvTimerPostRequestSpecific(
    IN  PSRV_TIMER             pTimer,
    IN  LONG64                 llExpiry,
    IN  PVOID                  pUserData,
    IN  PFN_SRV_TIMER_CALLBACK pfnTimerExpiredCB,
    OUT PSRV_TIMER_REQUEST*    ppTimerRequest
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PSRV_TIMER_REQUEST pTimerRequest = NULL;
    PSRV_TIMER_REQUEST pTimerIter = NULL;
    PSRV_TIMER_REQUEST pPrev = NULL;
    BOOLEAN bInLock = FALSE;

    if (!llExpiry)
    {
        status = STATUS_INVALID_PARAMETER_1;
        BAIL_ON_NT_STATUS(status);
    }
    if (!pfnTimerExpiredCB)
    {
        status = STATUS_INVALID_PARAMETER_3;
        BAIL_ON_NT_STATUS(status);
    }

    status = SrvAllocateMemory(
                    sizeof(SRV_TIMER_REQUEST),
                    (PVOID*)&pTimerRequest);
    BAIL_ON_NT_STATUS(status);

    pTimerRequest->refCount = 1;

    pTimerRequest->llExpiry = llExpiry;
    pTimerRequest->pUserData = pUserData;
    pTimerRequest->pfnTimerExpiredCB = pfnTimerExpiredCB;
    pTimerRequest->bCanceled = FALSE;

    LWIO_LOCK_MUTEX(bInLock, &pTimer->context.mutex);

    for (pTimerIter = pTimer->context.pRequests;
         pTimerIter && (pTimerIter->llExpiry <= llExpiry);
         pPrev = pTimerIter, pTimerIter = pTimerIter->pNext);

    if (!pPrev)
    {
        pTimerRequest->pNext = pTimer->context.pRequests;
        if (pTimer->context.pRequests)
        {
            pTimer->context.pRequests->pPrev = pTimerRequest;
        }
        pTimer->context.pRequests = pTimerRequest;
    }
    else
    {
        pTimerRequest->pNext = pPrev->pNext;
        pTimerRequest->pPrev = pPrev;
        pPrev->pNext = pTimerRequest;
        if (pTimerRequest->pNext)
        {
            pTimerRequest->pNext->pPrev = pTimerRequest;
        }
    }

    // +1 for timer queue
    InterlockedIncrement(&pTimerRequest->refCount);

    LWIO_UNLOCK_MUTEX(bInLock, &pTimer->context.mutex);

    pthread_cond_signal(&pTimer->context.event);

    // +1 for caller
    InterlockedIncrement(&pTimerRequest->refCount);

    *ppTimerRequest = pTimerRequest;

cleanup:

    LWIO_UNLOCK_MUTEX(bInLock, &pTimer->context.mutex);

    if (pTimerRequest)
    {
        SrvTimerRelease(pTimerRequest);
    }

    return status;

error:

    *ppTimerRequest = NULL;

    goto cleanup;
}
Beispiel #15
0
NTSTATUS
SrvProcessNotify_SMB_V2(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS                   ntStatus     = STATUS_SUCCESS;
    PLWIO_SRV_CONNECTION       pConnection  = pExecContext->pConnection;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V2   pCtxSmb2     = pCtxProtocol->pSmb2Context;
    ULONG                      iMsg         = pCtxSmb2->iMsg;
    PSRV_MESSAGE_SMB_V2        pSmbRequest  = &pCtxSmb2->pRequests[iMsg];
    PLWIO_SRV_SESSION_2        pSession     = NULL;
    PLWIO_SRV_TREE_2           pTree        = NULL;
    BOOLEAN                    bInLock      = FALSE;
    PSRV_NOTIFY_STATE_SMB_V2   pNotifyState = NULL;
    PLWIO_ASYNC_STATE          pAsyncState       = NULL;
    BOOLEAN                    bUnregisterAsync          = FALSE;
    PSRV_NOTIFY_REQUEST_STATE_SMB_V2 pNotifyRequestState = NULL;

    pNotifyRequestState = (PSRV_NOTIFY_REQUEST_STATE_SMB_V2)pCtxSmb2->hState;
    if (pNotifyRequestState)
    {
        InterlockedIncrement(&pNotifyRequestState->refCount);
    }
    else
    {
        PSMB2_NOTIFY_CHANGE_HEADER pRequestHeader = NULL; // Do not free

        ntStatus = SrvConnection2FindSession_SMB_V2(
                        pCtxSmb2,
                        pConnection,
                        pSmbRequest->pHeader->ullSessionId,
                        &pSession);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvSetStatSession2Info(pExecContext, pSession);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvSession2FindTree_SMB_V2(
                        pCtxSmb2,
                        pSession,
                        pSmbRequest->pHeader->ulTid,
                        &pTree);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SMB2UnmarshalNotifyRequest(pSmbRequest, &pRequestHeader);
        BAIL_ON_NT_STATUS(ntStatus);

        SRV_LOG_DEBUG(
                pExecContext->pLogContext,
                SMB_PROTOCOL_VERSION_2,
                pSmbRequest->pHeader->command,
                "Change notify request params: "
                "command(%u),uid(%llu),cmd-seq(%llu),pid(%u),tid(%u),"
                "credits(%u),flags(0x%x),chain-offset(%u),"
                "file-id(persistent:0x%x,volatile:0x%x),"
                "flags(0x%x),completion-filter(%u),output-buffer-length(%u)",
                pSmbRequest->pHeader->command,
                (long long)pSmbRequest->pHeader->ullSessionId,
                (long long)pSmbRequest->pHeader->ullCommandSequence,
                pSmbRequest->pHeader->ulPid,
                pSmbRequest->pHeader->ulTid,
                pSmbRequest->pHeader->usCredits,
                pSmbRequest->pHeader->ulFlags,
                pSmbRequest->pHeader->ulChainOffset,
                (long long)pRequestHeader->fid.ullPersistentId,
                (long long)pRequestHeader->fid.ullVolatileId,
                pRequestHeader->usFlags,
                pRequestHeader->ulCompletionFilter,
                pRequestHeader->ulOutputBufferLength);

        ntStatus = SrvBuildNotifyRequestState_SMB_V2(
                        pRequestHeader,
                        &pNotifyRequestState);
        BAIL_ON_NT_STATUS(ntStatus);

        pCtxSmb2->hState = pNotifyRequestState;
        InterlockedIncrement(&pNotifyRequestState->refCount);
        pCtxSmb2->pfnStateRelease = &SrvReleaseNotifyRequestStateHandle_SMB_V2;

        ntStatus = SrvTree2FindFile_SMB_V2(
                        pCtxSmb2,
                        pTree,
                        &pRequestHeader->fid,
                        &pNotifyRequestState->pFile);
        BAIL_ON_NT_STATUS(ntStatus);
    }

    LWIO_LOCK_MUTEX(bInLock, &pNotifyRequestState->mutex);

    switch (pNotifyRequestState->stage)
    {
        case SRV_NOTIFY_STAGE_SMB_V2_INITIAL:

             if (pNotifyRequestState->pRequestHeader->ulOutputBufferLength >
                 SMB_CN_MAX_BUFFER_SIZE)
             {
                 ntStatus = STATUS_INVALID_PARAMETER;
                 BAIL_ON_NT_STATUS(ntStatus);
             }

             // A change notify request can occur as the only message in
             // a request, or the last in a chained request
             if (pCtxSmb2->iMsg != (pCtxSmb2->ulNumRequests - 1))
             {
                 ntStatus = STATUS_INTERNAL_ERROR;
                 BAIL_ON_NT_STATUS(ntStatus);
             }

             ntStatus = SrvConnection2CreateAsyncState(
                             pConnection,
                             COM2_NOTIFY,
                             &SrvCancelNotifyState_SMB_V2,
                             &SrvNotifyStateReleaseHandle_SMB_V2,
                             &pAsyncState);
             BAIL_ON_NT_STATUS(ntStatus);

             bUnregisterAsync = TRUE;

             ntStatus = SrvNotifyCreateState_SMB_V2(
                             pAsyncState->ullAsyncId,
                             pExecContext->pConnection,
                             pCtxSmb2->pSession,
                             pCtxSmb2->pTree,
                             pNotifyRequestState->pFile,
                             pSmbRequest->pHeader->usEpoch,
                             pSmbRequest->pHeader->ullCommandSequence,
                             pSmbRequest->pHeader->ulPid,
                             pNotifyRequestState->pRequestHeader->ulCompletionFilter,
                             (pNotifyRequestState->pRequestHeader->usFlags &
                                     SMB2_NOTIFY_FLAGS_WATCH_TREE),
                             pNotifyRequestState->pRequestHeader->ulOutputBufferLength,
                             &pNotifyState);
             BAIL_ON_NT_STATUS(ntStatus);

             pAsyncState->hAsyncState =
                                 SrvNotifyStateAcquire_SMB_V2(pNotifyState);

             pNotifyRequestState->stage = SRV_NOTIFY_STAGE_SMB_V2_ATTEMPT_IO;

             // intentional fall through

        case SRV_NOTIFY_STAGE_SMB_V2_ATTEMPT_IO:

            ntStatus = SrvExecuteChangeNotify_SMB_V2(
                            pExecContext,
                            pNotifyState);
            switch (ntStatus)
            {
                case STATUS_PENDING:

                {
                    // TODO: Might have to cancel the entire operation
                    //
                    NTSTATUS ntStatus2 = SrvBuildInterimResponse_SMB_V2(
                                                pExecContext,
                                                pNotifyState->ullAsyncId);
                    if (ntStatus2 != STATUS_SUCCESS)
                    {
                        LWIO_LOG_ERROR(
                                "Failed to create interim response [code:0x%8x]",
                                ntStatus2);
                    }

                    bUnregisterAsync = FALSE;
                }

                    break;

                case STATUS_SUCCESS:

                    // completed synchronously; remove asynchronous state
                    //
                    SrvConnection2RemoveAsyncState(
                            pConnection,
                            pAsyncState->ullAsyncId);

                    pNotifyState->ullAsyncId = 0LL;

                    bUnregisterAsync = FALSE;

                    break;

                default:

                    break;
            }
            BAIL_ON_NT_STATUS(ntStatus);

            pNotifyRequestState->stage = SRV_NOTIFY_STAGE_SMB_V2_BUILD_RESPONSE;

            // intentional fall through

        case SRV_NOTIFY_STAGE_SMB_V2_BUILD_RESPONSE:

            ntStatus = SrvBuildNotifyResponse_SMB_V2(
                            pExecContext,
                            pNotifyState);
            BAIL_ON_NT_STATUS(ntStatus);

            pNotifyRequestState->stage = SRV_NOTIFY_STAGE_SMB_V2_DONE;

            // intentional fall through

        case SRV_NOTIFY_STAGE_SMB_V2_DONE:

            break;
    }

cleanup:

    if (pNotifyRequestState)
    {
        LWIO_UNLOCK_MUTEX(bInLock, &pNotifyRequestState->mutex);

        SrvReleaseNotifyRequestState_SMB_V2(pNotifyRequestState);
    }

    if (pNotifyState)
    {
        if (bUnregisterAsync)
        {
            SrvConnection2RemoveAsyncState(
                    pConnection,
                    pNotifyState->ullAsyncId);
        }

        SrvNotifyStateRelease_SMB_V2(pNotifyState);
    }

    if (pAsyncState)
    {
        SrvAsyncStateRelease(pAsyncState);
    }

    if (pTree)
    {
        SrvTree2Release(pTree);
    }

    if (pSession)
    {
        SrvSession2Release(pSession);
    }

    return ntStatus;

error:

    switch (ntStatus)
    {
        case STATUS_PENDING:

            break;

        default:

            if (pNotifyState)
            {
                SrvReleaseNotifyStateAsync_SMB_V2(pNotifyState);
            }

            break;
    }

    goto cleanup;
}
Beispiel #16
0
NTSTATUS
SrvShareDbAcquireContext(
    PSRV_SHARE_DB_CONTEXT* ppDbContext
    )
{
    NTSTATUS ntStatus = 0;
    BOOLEAN bInLock = FALSE;
    PSRV_SHARE_DB_GLOBALS pGlobals = &gShareRepository_lwshare;
    PSRV_SHARE_DB_CONTEXT pDbContext = NULL;

    LWIO_LOCK_MUTEX(bInLock, &pGlobals->mutex);

    if (pGlobals->ulNumDbContexts)
    {
        pDbContext = pGlobals->pDbContextList;
        pGlobals->pDbContextList = pGlobals->pDbContextList->pNext;
        pDbContext->pNext = NULL;

        pGlobals->ulNumDbContexts--;

        LWIO_UNLOCK_MUTEX(bInLock, &pGlobals->mutex);
    }
    else
    {
        PCSTR pszShareDbPath = LWIO_SRV_SHARE_DB;

        ntStatus = SrvAllocateMemory(
                        sizeof(SRV_SHARE_DB_CONTEXT),
                        (PVOID*)&pDbContext);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = sqlite3_open(
                        pszShareDbPath,
                        &pDbContext->pDbHandle);
        if (ntStatus)
        {
            LWIO_LOG_ERROR("Sqlite3 Error (code: %d): %s",
                                    ntStatus,
                                    "Failed to open database handle""");
            ntStatus = STATUS_INTERNAL_DB_ERROR;
        }
        BAIL_ON_NT_STATUS(ntStatus);
    }

    *ppDbContext = pDbContext;

cleanup:

    LWIO_UNLOCK_MUTEX(bInLock, &pGlobals->mutex);

    return ntStatus;

error:

    *ppDbContext = NULL;

    if (pDbContext)
    {
        SrvShareDbFreeContext(pDbContext);
    }

    goto cleanup;
}
Beispiel #17
0
static
NTSTATUS
SrvGetDefaultSharePath(
    PSTR* ppszFileSystemRoot
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PSTR     pszDefaultSharePath = NULL;
    PSTR     pszFileSystemRoot = NULL;
    PSTR     pszCursor = NULL;
    BOOLEAN  bUsePolicy = TRUE;
    CHAR     szTmpFSRoot[] = LWIO_SRV_FILE_SYSTEM_ROOT_A;
    PLWIO_CONFIG_REG pReg = NULL;

    ntStatus = LwIoOpenConfig(
                        "Services\\lwio\\Parameters\\Drivers\\srv",
                        "Policy\\Services\\lwio\\Parameters\\Drivers\\srv",
                        &pReg);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = LwIoReadConfigString(
                    pReg,
                    "DefaultSharePath",
                    bUsePolicy,
                    &pszDefaultSharePath);
    BAIL_ON_NT_STATUS(ntStatus);

    if (IsNullOrEmptyString(pszDefaultSharePath) ||
            ((*pszDefaultSharePath != '/') &&
             (*pszDefaultSharePath != '\\')))
    {
        LWIO_LOG_ERROR("Error: Default share path configured is not an absolute path");

        ntStatus = STATUS_INVALID_PARAMETER;
        BAIL_ON_NT_STATUS(ntStatus);
    }

    ntStatus = SrvAllocateStringPrintf(
                    &pszFileSystemRoot,
                    "%s%s%s",
                    &szTmpFSRoot[0],
                    (((szTmpFSRoot[strlen(&szTmpFSRoot[0])-1] == '/') ||
                      (szTmpFSRoot[strlen(&szTmpFSRoot[0])-1] == '\\')) ? "" : "\\"),
                    IsNullOrEmptyString(pszDefaultSharePath+1) ? "" : pszDefaultSharePath+1);
    BAIL_ON_NT_STATUS(ntStatus);

    for (pszCursor = pszFileSystemRoot; pszCursor && *pszCursor; pszCursor++)
    {
        if (*pszCursor == '/')
        {
            *pszCursor = '\\';
        }
    }

    *ppszFileSystemRoot = pszFileSystemRoot;

cleanup:

    if (pReg)
    {
        LwIoCloseConfig(pReg);
    }

    RTL_FREE(&pszDefaultSharePath);

    return ntStatus;

error:

    *ppszFileSystemRoot = NULL;

    LWIO_LOG_ERROR("Failed to access device configuration [error code: %u]",
                   ntStatus);

    ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;

    goto cleanup;
}
Beispiel #18
0
static
NTSTATUS
PvfsRenameFile(
    PPVFS_CCB pCcb,
    PPVFS_FILE_NAME pNewFileName
    )
{
    NTSTATUS ntError = STATUS_SUCCESS;
    PPVFS_CB_TABLE scbTable = &gPvfsDriverState.ScbTable;
    PPVFS_CB_TABLE_ENTRY pTargetBucket = NULL;
    PPVFS_CB_TABLE_ENTRY pCurrentBucket = NULL;
    BOOLEAN renameLock = FALSE;
    BOOLEAN targetBucketLock = FALSE;
    BOOLEAN currentBucketLock = FALSE;
    PPVFS_FCB pFcb = NULL;
    PLW_LIST_LINKS scbCursorLink = NULL;
    PPVFS_SCB scbCursor = NULL;
    BOOLEAN scbMutexLock = FALSE;
    BOOLEAN fcbListLocked = FALSE;
    PPVFS_FILE_NAME origTargetFileName = NULL;
    PPVFS_FILE_NAME scbCursorFileName = NULL;
    PSTR origFullStreamName = NULL;
    PSTR newFullStreamName = NULL;

    // The CCB holds out reference down the chain so no need to take a new one
    pFcb = pCcb->pScb->pOwnerFcb;

    ntError = PvfsAllocateFileNameFromScb(&origTargetFileName, pCcb->pScb);
    BAIL_ON_NT_STATUS(ntError);

    LWIO_LOCK_RWMUTEX_EXCLUSIVE(renameLock, &scbTable->rwLock);
    LWIO_LOCK_RWMUTEX_SHARED(fcbListLocked, &pFcb->rwScbLock);

    ntError = PvfsRenameFCB(pFcb, pCcb, pNewFileName);
    BAIL_ON_NT_STATUS(ntError);

    for (scbCursorLink = PvfsListTraverse(pFcb->pScbList, NULL);
         scbCursorLink;
         scbCursorLink = PvfsListTraverse(pFcb->pScbList, scbCursorLink))
    {
        scbCursor = LW_STRUCT_FROM_FIELD(
                          scbCursorLink,
                          PVFS_SCB,
                          FcbList);

        ntError = PvfsAllocateFileNameFromScb(&scbCursorFileName, scbCursor);
        BAIL_ON_NT_STATUS(ntError);

        ntError = PvfsAllocateCStringFromFileName(
                      &newFullStreamName,
                      scbCursorFileName);
        BAIL_ON_NT_STATUS(ntError);

        ntError = PvfsRenameBaseFileName(
                      scbCursorFileName,
                      PvfsGetCStringBaseFileName(origTargetFileName));
        BAIL_ON_NT_STATUS(ntError);

        ntError = PvfsAllocateCStringFromFileName(
                      &origFullStreamName,
                      scbCursorFileName);
        BAIL_ON_NT_STATUS(ntError);

        pCurrentBucket = scbCursor->BaseControlBlock.pBucket;

        ntError = PvfsCbTableGetBucket(&pTargetBucket, scbTable, newFullStreamName);
        BAIL_ON_NT_STATUS(ntError);

        LWIO_LOCK_MUTEX(scbMutexLock, &scbCursor->BaseControlBlock.Mutex);
        LWIO_LOCK_RWMUTEX_EXCLUSIVE(currentBucketLock, &pCurrentBucket->rwLock);
        if (pCurrentBucket != pTargetBucket)
        {
            // Will be moved to a new bucket in the table
            LWIO_LOCK_RWMUTEX_EXCLUSIVE(targetBucketLock, &pTargetBucket->rwLock);
        }

        ntError = PvfsCbTableRemove_inlock(
                      (PPVFS_CONTROL_BLOCK)scbCursor,
                      origFullStreamName);
        LWIO_ASSERT(STATUS_SUCCESS == ntError);

        ntError = PvfsCbTableAdd_inlock(
                      pTargetBucket,
                      newFullStreamName,
                     (PPVFS_CONTROL_BLOCK)scbCursor);
        if (STATUS_SUCCESS != ntError)
        {
            LWIO_LOG_ERROR(
                "Failed to rename stream \"%s\" (%s)\n",
                newFullStreamName,
                LwNtStatusToName(ntError));
        }

        LWIO_UNLOCK_RWMUTEX(targetBucketLock, &pTargetBucket->rwLock);
        LWIO_UNLOCK_RWMUTEX(currentBucketLock, &pCurrentBucket->rwLock);
        LWIO_UNLOCK_MUTEX(scbMutexLock, &scbCursor->BaseControlBlock.Mutex);

        if (origFullStreamName)
        {
            LwRtlCStringFree(&origFullStreamName);
        }
        if (newFullStreamName)
        {
            LwRtlCStringFree(&newFullStreamName);
        }
    }

error:
    LWIO_UNLOCK_MUTEX(scbMutexLock, &scbCursor->BaseControlBlock.Mutex);
    LWIO_UNLOCK_RWMUTEX(targetBucketLock, &pTargetBucket->rwLock);
    LWIO_UNLOCK_RWMUTEX(currentBucketLock, &pCurrentBucket->rwLock);

    LWIO_UNLOCK_RWMUTEX(fcbListLocked, &pFcb->rwScbLock);
    LWIO_UNLOCK_RWMUTEX(renameLock, &scbTable->rwLock);

    if (origTargetFileName)
    {
        PvfsFreeFileName(origTargetFileName);
    }
    if (origFullStreamName)
    {
        LwRtlCStringFree(&origFullStreamName);
    }
    if (newFullStreamName)
    {
        LwRtlCStringFree(&newFullStreamName);
    }

    return ntError;
}
Beispiel #19
0
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);
}
Beispiel #20
0
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;
}
Beispiel #21
0
NTSTATUS
IopFileObjectRundownEx(
    IN OUT PIO_FILE_OBJECT pFileObject,
    IN OPTIONAL PIO_ASYNC_COMPLETE_CALLBACK Callback,
    IN OPTIONAL PVOID CallbackContext,
    OUT PIO_STATUS_BLOCK IoStatusBlock
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    int EE = 0;
    BOOLEAN isLocked = FALSE;
    IO_STATUS_BLOCK ioStatusBlock = { 0 };

    IopFileObjectLock(pFileObject);
    isLocked = TRUE;

    if (IsSetFlag(pFileObject->Flags, FILE_OBJECT_FLAG_CLOSE_DONE))
    {
        LWIO_ASSERT(IsSetFlag(pFileObject->Flags, FILE_OBJECT_FLAG_RUNDOWN));
        // Note that there can be IRP references for completed IRPs sitting
        // around where the caller has not yet gotten rid of the IRP by
        // calling IoDereferenceAsyncCancelContext().  So we cannot assert
        // that (1 == pFileObject->ReferenceCount).  Therefore, we do the
        // next best thing and check DispatchedIrpCount.  Technically, if
        // someone got far enough into a new call that they created an IRP,
        // they will also have a new IRP file objeject reference.  However,
        // the new IRP will fail to dispatch.  While that is a logic bug
        // in the caller, we cannot trap those sorts of bugs via asserts
        // in the I/O manager.
        LWIO_ASSERT(0 == pFileObject->DispatchedIrpCount);

        IopFileObjectUnlock(pFileObject);
        isLocked = FALSE;

        IopFileObjectDereference(&pFileObject);

        status = STATUS_SUCCESS;
        GOTO_CLEANUP_EE(EE);
    }

    if (IsSetFlag(pFileObject->Flags, FILE_OBJECT_FLAG_RUNDOWN))
    {
        LWIO_LOG_ERROR("Attempt to rundown multiple times");
        status = STATUS_FILE_CLOSED;
        GOTO_CLEANUP_EE(EE);
    }

    SetFlag(pFileObject->Flags, FILE_OBJECT_FLAG_RUNDOWN);

    IopFileObjectUnlock(pFileObject);
    isLocked = FALSE;

    // Cancel everything now that rundown flag is set.
    IopIrpCancelFileObject(pFileObject, TRUE);

    // Now check whether we need to wait for rundown.
    IopFileObjectLock(pFileObject);
    isLocked = TRUE;

    if (0 != pFileObject->DispatchedIrpCount)
    {
        // Need to wait

        SetFlag(pFileObject->Flags, FILE_OBJECT_FLAG_RUNDOWN_WAIT);

        if (!Callback)
        {
            // Wait inline for synchronous case

            LwRtlWaitConditionVariable(
                    &pFileObject->Rundown.Condition,
                    &pFileObject->Mutex,
                    NULL);
            LWIO_ASSERT(0 == pFileObject->DispatchedIrpCount);
        }
        else
        {
            // Set up rundown callback for async case

            pFileObject->Rundown.Callback = Callback;
            pFileObject->Rundown.CallbackContext = CallbackContext;
            pFileObject->Rundown.pIoStatusBlock = IoStatusBlock;

            status = STATUS_PENDING;
            GOTO_CLEANUP_EE(EE);
        }
    }

    IopFileObjectUnlock(pFileObject);
    isLocked = FALSE;

    // We can now continue closing.

    status = IopContinueAsyncCloseFile(
                    pFileObject,
                    Callback,
                    CallbackContext,
                    IoStatusBlock);
    GOTO_CLEANUP_ON_STATUS_EE(status, EE);
    
cleanup:
    if (isLocked)
    {
        IopFileObjectUnlock(pFileObject);
    }

    if (status && (STATUS_PENDING != status))
    {
        ioStatusBlock.Status = status;
    }

    if ((STATUS_PENDING != status) && IoStatusBlock)
    {
        *IoStatusBlock = ioStatusBlock;
    }

    // TODO-Perhaps do not ASSERT here because LwRtlInitializeEvent()
    // could have failed if disaptching close IRP synchronously.
    LWIO_ASSERT((STATUS_SUCCESS == status) ||
                (STATUS_PENDING == status) ||
                (STATUS_FILE_CLOSED == status));

    // TODO-Perhaps also remove object from device's file object
    // list such that it cannot be rundown multiple times.  This
    // would avoid the STATUS_FILE_CLOSED above.

    IO_LOG_LEAVE_ON_STATUS_EE(status, EE);
    return status;
}
Beispiel #22
0
static
NTSTATUS
RdrReadConfig(
    PRDR_CONFIG pConfig
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    DWORD dwIdleTimeout = pConfig->usIdleTimeout;
    DWORD dwResponseTimeout = pConfig->usResponseTimeout;
    DWORD dwEchoTimeout = pConfig->usEchoTimeout;
    DWORD dwEchoInterval = pConfig->usEchoInterval;
    DWORD dwConnectTimeout = pConfig->usConnectTimeout;
    DWORD dwMinCreditReserve = pConfig->usMinCreditReserve;

    LWREG_CONFIG_ITEM configItems[] =
    {
        {
            "Smb2Enabled",
            TRUE,
            LwRegTypeBoolean,
            0,
            MAXDWORD,
            NULL,
            &pConfig->bSmb2Enabled,
            NULL
        },
        {
            "SigningEnabled",
            TRUE,
            LwRegTypeBoolean,
            0,
            MAXDWORD,
            NULL,
            &pConfig->bSigningEnabled,
            NULL
        },
        {
            "SigningRequired",
            TRUE,
            LwRegTypeBoolean,
            0,
            MAXDWORD,
            NULL,
            &pConfig->bSigningRequired,
            NULL
        },
        {
            "IdleTimeout",
            TRUE,
            LwRegTypeDword,
            1,
            300,
            NULL,
            &dwIdleTimeout,
            NULL
        },
        {
            "ResponseTimeout",
            TRUE,
            LwRegTypeDword,
            10,
            900,
            NULL,
            &dwResponseTimeout,
            NULL
        },
        {
            "EchoTimeout",
            TRUE,
            LwRegTypeDword,
            5,
            900,
            NULL,
            &dwEchoTimeout,
            NULL
        },
        {
            "EchoInterval",
            TRUE,
            LwRegTypeDword,
            30,
            1800,
            NULL,
            &dwEchoInterval,
            NULL
        },
        {
            "ConnectTimeout",
            TRUE,
            LwRegTypeDword,
            5,
            900,
            NULL,
            &dwConnectTimeout,
            NULL
        },
        {
            "MinCreditReserve",
            TRUE,
            LwRegTypeDword,
            1,
            100,
            NULL,
            &dwMinCreditReserve,
            NULL
        },
    };

    status = NtRegProcessConfig(
                "Services\\lwio\\Parameters\\Drivers\\rdr",
                "Policy\\Services\\lwio\\Parameters\\Drivers\\rdr",
                configItems,
                sizeof(configItems)/sizeof(configItems[0]));
    if (status)
    {
        LWIO_LOG_ERROR("Failed to access device configuration [error code: %u]",
                       status);

        status = STATUS_DEVICE_CONFIGURATION_ERROR;
    }
    BAIL_ON_NT_STATUS(status);

    pConfig->usIdleTimeout = (USHORT)dwIdleTimeout;
    pConfig->usResponseTimeout = (USHORT)dwResponseTimeout;
    pConfig->usEchoTimeout = (USHORT)dwEchoTimeout;
    pConfig->usEchoInterval = (USHORT)dwEchoInterval;
    pConfig->usConnectTimeout = (USHORT)dwConnectTimeout;
    pConfig->usMinCreditReserve = (USHORT)dwMinCreditReserve;

cleanup:
    return status;

error:
    goto cleanup;
}