lockmgrapi.cpp

来自「WinCE5.0部分核心源码」· C++ 代码 · 共 552 行 · 第 1/2 页

CPP
552
字号
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//

/*++

Module Name:
    lckmgrapi.cpp

Abstract:
    Core Lock Manager API.  This module is used by the Lock Manager API for
    FSDs/File Systems.

Revision History:

--*/

#include "lockmgrapi.hpp"
#include "lockmgrdbg.hpp"
#include "lockcol.hpp"
#include "lockset.hpp"
#include "locklist.hpp"
#include "lock.hpp"
#include "range.hpp"

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

BOOL RemoveLock(
    CFileLockSet *pFileLockSet,
    DWORD hOwner,
    CRange *pRange
    )
{
    SETFNAME(_T("RemoveLock"));

    CFileLockList *pFileLockList;
    CFileLock *pFileLock;
    BOOL fInsertFileLockList = TRUE;
    BOOL fResult = FALSE;

    PREFAST_DEBUGCHK(NULL != pFileLockSet);
    PREFAST_DEBUGCHK(NULL != hOwner);
    PREFAST_DEBUGCHK(NULL != pRange);

    // remove list, remove lock, delete lock, re-insert list

    pFileLockList = pFileLockSet->Remove(hOwner);
    if (NULL != pFileLockList) {
        PREFAST_DEBUGCHK(NULL == pFileLockList->GetNext());
        pFileLock = pFileLockList->Remove(pRange);
        if (NULL != pFileLock) {
            PREFAST_DEBUGCHK(NULL == pFileLock->GetNext());
            delete pFileLock;
            if (pFileLockList->IsEmpty()) {
                delete pFileLockList;
                fInsertFileLockList = FALSE;
            }
            fResult = TRUE;
        }
        if (fInsertFileLockList) {
            pFileLockSet->Insert(pFileLockList);
        }
    }

    return fResult;
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

PVOID
LXX_CreateLockContainer(
    )
{
    CFileLockCollection *pFileLockCollection = NULL;

    // if malloc fails, null is returned; pass null to caller to indicate failure
    pFileLockCollection = new CFileLockCollection();

    return (PVOID)pFileLockCollection;
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

VOID
LXX_DestroyLockContainer(
    PVOID pvLockContainer
    )
{
    SETFNAME(_T("LXX_DestroyLockContainer"));

    CFileLockCollection *pFileLockCollection;

    if (NULL == pvLockContainer) {
        return;
    }

    // only our FSD-s use lock manager, so we trust pvLockContainer (__try not required)

    pFileLockCollection = (CFileLockCollection *)pvLockContainer;
    if (SIG != pFileLockCollection->GetSignature()) {
        DEBUGMSG(1, (_T("%s failed to destroy lock container; bad lock container\r\n"), pszFname));
        DEBUGCHK(0);
        return;
    }

    delete pFileLockCollection;
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

BOOL
LXX_IsLockContainerEmpty(
    PVOID pvLockContainer
    )
{
    SETFNAME(_T("LXX_IsLockContainerEmpty"));

    CFileLockCollection *pFileLockCollection;

    if (NULL == pvLockContainer) {
        return TRUE;
    }

    pFileLockCollection = (CFileLockCollection *)pvLockContainer;
    if (SIG != pFileLockCollection->GetSignature()) {
        DEBUGMSG(1, (_T("%s failed to check if lock container empty; bad lock container\r\n"), pszFname));
        DEBUGCHK(0);
        return FALSE;
    }

    return pFileLockCollection->IsEmpty();
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

// undo flags

#define DSET   (1 << 0)
#define DLIST  (1 << 1)
#define DRANGE (1 << 2)

LOCKRESULT
LXX_Lock(
    PVOID pvLockContainer,
    DWORD dwFile,
    DWORD dwFlags,
    DWORD dwReserved,
    DWORD nNumberOfBytesToLockLow,
    DWORD nNumberOfBytesToLockHigh,
    LPOVERLAPPED lpOverlapped
    )
{
    SETFNAME(_T("LXX_Lock"));

    CFileLockCollection *pFileLockCollection;
    CFileLockSet *pFileLockSet;
    CFileLockList *pFileLockList;
    CFileLock *pFileLock;
    CRange *pRange;

    DWORD dwUndo = 0;

    LOCKRESULT lrResult = LR_ERROR;

    if (NULL == pvLockContainer) {
        DEBUGMSG(1, (_T("%s failed to install lock; lock container null\r\n"), pszFname));
        return LR_ERROR;
    }
    if (0 == dwFile) {
        DEBUGMSG(1, (_T("%s failed to install lock; file handle null\r\n"), pszFname));
        return LR_ERROR;
    }
    if (0 != dwReserved) {
        DEBUGMSG(1, (_T("%s (warning) dwReserved should be 0\r\n"), pszFname));
    }
    if (NULL == lpOverlapped) {
        DEBUGMSG(1, (_T("%s failed to install lock; overlapped null\r\n"), pszFname));
        return LR_ERROR;
    }
    if ((0 == nNumberOfBytesToLockLow) && (0 == nNumberOfBytesToLockHigh)) {
        DEBUGMSG(1, (_T("%s failed to install lock; bytes to lock 0\r\n"), pszFname));
        return LR_ERROR;
    }

    // only our FSD-s use lock manager, so we trust pvLockContainer (__try not required)

    pFileLockCollection = (CFileLockCollection *)pvLockContainer;
    if (SIG != pFileLockCollection->GetSignature()) {
        DEBUGMSG(1, (_T("%s failed to install lock; bad lock container\r\n"), pszFname));
        DEBUGCHK(0);
        return LR_ERROR;
    }

    // create range

    pRange = new CRange();
    if (NULL == pRange) {
        DEBUGMSG(1, (_T("%s failed to install lock; out of memory (new range)\r\n"), pszFname));
        return LR_ERROR;
    }
    pRange->SetOffset(lpOverlapped->Offset, lpOverlapped->OffsetHigh);
    pRange->SetLength(nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh);
    dwUndo |= DRANGE;

    if (!pRange->IsValid()) {
        DEBUGMSG(1, (_T("%s failed to install lock; range(%I64u, %I64u) invalid\r\n"), pszFname, pRange->GetStart(), pRange->GetFinish()));
        goto exit;
    }

    // test for conflict

    if (NULL != pFileLockCollection->GetExclusive()) {
        if (pFileLockCollection->GetExclusive()->IsConflict(pRange)) {
            if (dwFlags & LOCKFILE_FAIL_IMMEDIATELY) {
                goto exit;
            }
            lrResult = LR_CONFLICT;
            goto exit;
        }
    }

    // this lock does not conflict with an exclusive lock; shared locks can overlap,
    // so we only have to check the shared set if this is an exclusive lock

    if (NULL != pFileLockCollection->GetShared() && (dwFlags & LOCKFILE_EXCLUSIVE_LOCK)) {
        if (pFileLockCollection->GetShared()->IsConflict(pRange)) {
            if (dwFlags & LOCKFILE_FAIL_IMMEDIATELY) {
                goto exit;
            }
            lrResult = LR_CONFLICT;
            goto exit;
        }
    }

    // range does not conflict with existing lock; get appropriate set; create,
    // if necessary

    if (dwFlags & LOCKFILE_EXCLUSIVE_LOCK) {
        if (NULL == pFileLockCollection->GetExclusive()) {
            pFileLockCollection->SetExclusive(new CFileLockSet());
            if (NULL == pFileLockCollection->GetExclusive()) {
                goto exit;
            }
            dwUndo |= DSET;
        }
        pFileLockSet = pFileLockCollection->GetExclusive();
    }
    else {
        if (NULL == pFileLockCollection->GetShared()) {
            pFileLockCollection->SetShared(new CFileLockSet());
            if (NULL == pFileLockCollection->GetShared()) {
                goto exit;
            }
            dwUndo |= DSET;
        }
        pFileLockSet = pFileLockCollection->GetShared();
    }

    // remove owner's list from appropriate set; create, if necessary

    pFileLockList = pFileLockSet->Remove(dwFile);
    if (NULL == pFileLockList) {
        pFileLockList = new CFileLockList();
        if (NULL == pFileLockList) {
            DEBUGMSG(1, (_T("%s failed to install lock; out of memory (new lock list)\r\n"), pszFname));
            goto exit;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?