⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kdhandle.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// 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:

    kdhandle.c

Abstract:

    This module contains code to implement handle queries and deletions.

--*/
// C4200: nonstandard extension used : zero-sized array in struct/union
#pragma warning(disable:4200)

// C4228: nonstandard extension used : qualifiers after comma in declarator list are ignored
#pragma warning(disable:4228)

#include <cmnintrin.h>
#include "kdp.h"

// We pull in these from filesys.h
typedef struct fsopenfile_t
{
    DWORD filepos;
    struct fsopenfile_t *next;
    WORD flags;
    HANDLE hFile;
    HANDLE hNotify;
} fsopenfile_t;

#ifdef _DEBUG
#define CODE_NEVER_REACHED()        ASSERT(0)
#else
#define CODE_NEVER_REACHED()        __assume(0)
#endif /* _DEBUG */

// Declare a KD_HANDLE_DESC that describes a field inside a structure
// id = one of the KD_HDATA_xxx IDs
// t = one of the KD_FIELD_xxx type IDs
// s = structure name
// p = field name in above structure
#define DESC_OFF(id,t,s,p)          {NULL, offsetof(s, p), sizeof(((s *) NULL)->p), id, t}

// Declare KD_HANDLE_DESC for data returned by a callback function
// id = one of the KD_HDATA_xxx IDs
// t = one of the KD_FIELD_xxx type IDs
// f = function to call to get the data
#define DESC_FUN(id,t,f)            {f, 0, 0, id, t}

// Declare KD_API_DESC
// p = KD_API_DESC array (KD_API_DESC[], not KD_API_DESC*)
// f = function to validate extra handle data for this particular API
#define APIDESC(p,f)                {p, lengthof(p), f}

// Declare an empty KD_API_DESC
// p = KD_API_DESC array (KD_API_DESC[], not KD_API_DESC*)
// f = function to validate extra handle data for this particular API
//
// Note that p and f are ignored; this is used as a placeholder. Once the API
// has a description, change APINULL -> APIDESC macro and you're good to go.
#define APINULL(p,f)                {NULL, 0, KdDontValidate}

typedef struct _KD_HANDLE_DESC
{
    // For extremely special fields that are annoying to encode. If this is
    // NULL, we copy a 4-byte variable at the specified offset.
    UINT32 (* pfnReadField)(PCVOID pvData);

    size_t nOffset;
    size_t nSize;
    UINT16 nFieldId;
    UINT16 nType;
} KD_HANDLE_DESC;

typedef KD_HANDLE_DESC *PKD_HANDLE_DESC;
typedef const KD_HANDLE_DESC *PCKD_HANDLE_DESC;

typedef struct
{
    PCKD_HANDLE_DESC pDesc;
    UINT cEntries;
    BOOL (* pfnValidateHandle)(HDATA *ph);
} KD_API_DESC;

typedef KD_API_DESC *PKD_API_DESC;
typedef const KD_API_DESC *PCKD_API_DESC;

// Function to extract position of least-significant one
static UINT _CountTrailingZeros(UINT32 nMask);

// Function to convert a KD_HANDLE_DESC into a DBGKD_HANDLE_FIELD_DATA
static void KdHandleGetField(PDBGKD_HANDLE_FIELD_DATA pField, PCKD_HANDLE_DESC pDesc, LPCVOID pvStruct);

// Some handle validation helper functions
static BOOL KdDontValidate(HDATA *ph);
static BOOL KdValidateThread(HDATA *ph);
static BOOL KdValidateProcess(HDATA *ph);

// Some handle data helper functions
static UINT32 KdReadGlobalRefCount(PCVOID pvData);
static UINT32 KdReadHandleType(PCVOID pvData);
static UINT32 KdReadHandleName(PCVOID pvData);
static UINT32 KdReadThreadPID(PCVOID pvData);
static UINT32 KdReadMutexOwner(PCVOID pvData);

// Constants for _CountTrailingZeros emulation
#if !_INTRINSIC_IS_SUPPORTED(_CountLeadingZeros)
static const UINT32 g_nCntLeadMagic32 = 0xF04653AE;
static const BYTE g_abCntLeadTbl32[32] =
{0,  31, 4,  5,  6,  10, 7,  15, 11, 20, 8,  18, 16, 25, 12, 27,
 21, 30, 3,  9,  14, 19, 17, 24, 26, 29, 2,  13, 23, 28, 1,  22};
#endif /* !_INTRINSIC_IS_SUPPORTED(_CountLeadingZeros) */

// Describe the HDATA structure.
static const KD_HANDLE_DESC g_pGenericDesc[] =
{DESC_OFF(KD_HDATA_HANDLE,         KD_FIELD_HANDLE,   HDATA,      hValue),
 DESC_OFF(KD_HDATA_AKY,            KD_FIELD_BITS,     HDATA,      lock),
 DESC_FUN(KD_HDATA_REFCNT,         KD_FIELD_UINT,     KdReadGlobalRefCount),
 DESC_FUN(KD_HDATA_TYPE,           KD_FIELD_WIDE_STR, KdReadHandleType),
 DESC_FUN(KD_HDATA_NAME,           KD_FIELD_WIDE_STR, KdReadHandleName)};

// These descriptors correspond to handle types (_HDATA.pci->type)
//static const KD_HANDLE_DESC g_pWin32Desc[] = {};

static const KD_HANDLE_DESC g_pThreadDesc[] =
{DESC_OFF(KD_HDATA_THREAD_SUSPEND, KD_FIELD_UINT,     THREAD,       bSuspendCnt),
 DESC_FUN(KD_HDATA_THREAD_PID,     KD_FIELD_UINT,     KdReadThreadPID),
 DESC_OFF(KD_HDATA_THREAD_BPRIO,   KD_FIELD_UINT,     THREAD,       bBPrio),
 DESC_OFF(KD_HDATA_THREAD_CPRIO,   KD_FIELD_UINT,     THREAD,       bCPrio),
 DESC_OFF(KD_HDATA_THREAD_KTIME,   KD_FIELD_UINT,     THREAD,       dwKernTime),
 DESC_OFF(KD_HDATA_THREAD_UTIME,   KD_FIELD_UINT,     THREAD,       dwUserTime)};

static const KD_HANDLE_DESC g_pProcessDesc[] =
{DESC_OFF(KD_HDATA_PROC_PID,       KD_FIELD_UINT,     PROCESS,      procnum),
 DESC_OFF(KD_HDATA_PROC_TRUST,     KD_FIELD_UINT,     PROCESS,      bTrustLevel),
 DESC_OFF(KD_HDATA_PROC_VMBASE,    KD_FIELD_PTR,      PROCESS,      dwVMBase),
 DESC_OFF(KD_HDATA_PROC_BASEPTR,   KD_FIELD_PTR,      PROCESS,      BasePtr),
 DESC_OFF(KD_HDATA_PROC_CMDLINE,   KD_FIELD_WIDE_STR, PROCESS,      pcmdline)};

static const KD_HANDLE_DESC g_pEventDesc[] =
{DESC_OFF(KD_HDATA_EVENT_STATE,    KD_FIELD_BOOL,     EVENT,        state),
 DESC_OFF(KD_HDATA_EVENT_RESET,    KD_FIELD_BOOL,     EVENT,        manualreset)};

static const KD_HANDLE_DESC g_pMutexDesc[] =
{DESC_OFF(KD_HDATA_MUTEX_LOCKCNT,  KD_FIELD_UINT,     MUTEX,        LockCount),
 DESC_FUN(KD_HDATA_MUTEX_OWNER,    KD_FIELD_HANDLE,   KdReadMutexOwner)};

//static const KD_HANDLE_DESC g_pAPISetDesc[] = {};

//static const KD_HANDLE_DESC g_pFileDesc[] = {};
//static const KD_HANDLE_DESC g_pFindDesc[] = {};
//static const KD_HANDLE_DESC g_pDBFileDesc[] = {};
//static const KD_HANDLE_DESC g_pDBFindDesc[] = {};
//static const KD_HANDLE_DESC g_pSocketDesc[] = {};
//static const KD_HANDLE_DESC g_pInterfaceDesc[] = {};

static const KD_HANDLE_DESC g_pSemaphoreDesc[] =
{DESC_OFF(KD_HDATA_SEM_COUNT,      KD_FIELD_SINT,     SEMAPHORE,    lCount),
 DESC_OFF(KD_HDATA_SEM_MAXCOUNT,   KD_FIELD_SINT,     SEMAPHORE,    lMaxCount)};

//static const KD_HANDLE_DESC g_pFSMapDesc[] = {};
//static const KD_HANDLE_DESC g_pWNetEnumDesc[] = {};

// NULL API set (no API-specific data). This is useful for simplifying the code
// later on.
const KD_API_DESC g_descNull = {NULL, 0, KdDontValidate};

static BOOL KdDontValidate(HDATA *ph);
static BOOL KdValidateThread(HDATA *ph);
static BOOL KdValidateProcess(HDATA *ph);

// APINULL macros correspond to unimplemented descriptors
KD_API_DESC g_pTypeMap[] =
{APINULL(g_pWin32Desc,     KdDontValidate),     // 0  = SH_WIN32
 APIDESC(g_pThreadDesc,    KdValidateThread),   // 1  = SH_CURTHREAD
 APIDESC(g_pProcessDesc,   KdValidateProcess),  // 2  = SH_CURPROC
 APINULL(g_pKWin32Desc,    KdDontValidate),     // 3  = SH_KWIN32
 APIDESC(g_pEventDesc,     KdDontValidate),     // 4  = HT_EVENT
 APIDESC(g_pMutexDesc,     KdDontValidate),     // 5  = HT_MUTEX
 APINULL(g_pAPISetDesc,    KdDontValidate),     // 6  = HT_APISET
 APINULL(g_pFileDesc,      KdDontValidate),     // 7  = HT_FILE
 APINULL(g_pFindDesc,      KdDontValidate),     // 8  = HT_FIND
 APINULL(g_pDBFileDesc,    KdDontValidate),     // 9  = HT_DBFILE
 APINULL(g_pDBFindDesc,    KdDontValidate),     // 10 = HT_DBFIND
 APINULL(g_pSocketDesc,    KdDontValidate),     // 11 = HT_SOCKET
 APINULL(g_pInterfaceDesc, KdDontValidate),     // 12 = HT_INTERFACE
 APIDESC(g_pSemaphoreDesc, KdDontValidate),     // 13 = HT_SEMAPHORE
 APINULL(g_pFSMapDesc,     KdDontValidate),     // 14 = HT_FSMAP
 APINULL(g_pWNetEnumDesc,  KdDontValidate),     // 15 = HT_WNETENUM
};

static LPCWSTR g_apszHandleTypeNames[] =
{L"Win32",
 L"Thread",
 L"Process",
 L"[Unused]",
 L"Event",
 L"Mutex",
 L"API set",
 L"File",
 L"Find",
 L"DB File",
 L"DB Find",
 L"Socket",
 L"Interface",
 L"Semaphore",
 L"FS Map",
 L"WNet Enum",
};

/*++

Routine Name:

    KdHandleToPtr

Routine Description:

    This routine converts a Windows CE HANDLE into the associated HDATA
    structure.

Arguments:

    hHandle         - [in]     Handle to convert

Return Value:

    If the handle is invalid, this routine returns NULL. Otherwise it returns
    a pointer to the HDATA structure for the handle.

--*/
HDATA *KdHandleToPtr(HANDLE hHandle)
{
    HDATA *phCurHandle;

    for(phCurHandle = (HDATA *) pHandleList->linkage.fwd;
        phCurHandle != pHandleList;
        phCurHandle = (HDATA *) phCurHandle->linkage.fwd)
    {
        if (phCurHandle->hValue == hHandle)
        {
            DEBUGGERMSG(KDZONE_HANDLEEX, (L"KdHandleToPtr: Handle %08p = HDATA@%08p\r\n", hHandle, phCurHandle));
            return phCurHandle;
        }
    }

    DEBUGGERMSG(KDZONE_HANDLEEX, (L"KdHandleToPtr: Handle %08p not valid\r\n", hHandle));

    return NULL;
}

/*++

Routine Name:

    KdValidateHandle

Routine Description:

    This routine verifies that a handle is valid.

Arguments:

    hHandle         - [in]     Handle to check

Return Value:

    TRUE    Handle is valid
    FALSE   Handle is invalid

--*/
BOOL KdValidateHandle(HANDLE hHandle)
{
    HDATA *phCurHandle;
    UINT nType;

    DEBUGGERMSG(KDZONE_HANDLEEX, (L"KdValidateHandlePtr: Validating handle %08p\r\n", hHandle));

    phCurHandle = KdHandleToPtr(hHandle);
    if (phCurHandle == NULL)
        return FALSE;

    nType = phCurHandle->pci->type;
    if (nType < lengthof(g_pTypeMap) &&
        !g_pTypeMap[nType].pfnValidateHandle(phCurHandle))
        return FALSE;

    return TRUE;
}

/*++

Routine Name:

    KdValidateHandlePtr

Routine Description:

    This routine verifies that a pointer to a handle is valid.

Arguments:

    phHandle        - [in]     Handle to check

Return Value:

    TRUE    Handle is valid
    FALSE   Handle is invalid

--*/
BOOL KdValidateHandlePtr(HDATA *phHandle)
{
    HDATA *phCurHandle;
    UINT nType;

    DEBUGGERMSG(KDZONE_HANDLEEX, (L"KdValidateHandlePtr: Validating handle pointer %08p\r\n", phHandle));

    for(phCurHandle = (HDATA *) pHandleList->linkage.fwd;
        phCurHandle != pHandleList;
        phCurHandle = (HDATA *) phCurHandle->linkage.fwd)
    {
        if (phCurHandle == phHandle)
            break;
    }

    if (phCurHandle == pHandleList)
        return FALSE;

    nType = phHandle->pci->type;
    if (nType < lengthof(g_pTypeMap) &&
        !g_pTypeMap[nType].pfnValidateHandle(phHandle))
        return FALSE;

    return TRUE;
}

/*++

Routine Name:

    KdGetProcHandleRef

Routine Description:

    This routine obtains the reference count for a particular process on an
    arbitrary handle.

Arguments:

    hHandle         - [in]     Handle to check
    nPID            - [in]     Process ID to obtain reference count for

Return Value:

    Number of references or -1 on invalid input

--*/
UINT KdGetProcHandleRef(HDATA *phHandle, UINT nPID)
{
    if (nPID >= MAX_PROCESSES)
        return -1;
    else if (phHandle->ref.count >= 0x10000)
        return phHandle->ref.pFr->usRefs[nPID];
    else if ((phHandle->lock & (1 << nPID)) != 0)
        return phHandle->ref.count;
    else
        return 0;
}

/*++

Routine Name:

    KdQueryHandleFields

Routine Description:

    This routine traverses the kernel handle list. It returns in the buffer a
    list of handles matching specific APIs or owned by specific processes.

Arguments:

    pHandleFields   - [in/out] List of common fields for the handles
    cbBufLen        - [in]     Length of pHandleFields buffer in bytes

    The caller should fill out the "in" structure in pHandleFields according to
    its description. The "out" structure is used to return results. See kdp.h
    for more information about how this structure is used. If the length of the
    buffer indicates that pHandleFields.out.nFields is valid, it will always
    contain the number of fields on return. If the buffer is too small to hold
    all data available, STATUS_BUFFER_TOO_SMALL will be returned and the buffer
    will be filled with part of the data. For any other error, the contents of
    pHandleFields is undefined.

Return Value:

    STATUS_SUCCESS                  Success
    STATUS_INVALID_PARAMETER        Buffer lacks space for in/out headers
    STATUS_BUFFER_TOO_SMALL         Buffer is not large enough

--*/
NTSTATUS KdQueryHandleFields(PDBGKD_HANDLE_DESC_DATA pHandleFields,
                             UINT cbBufLen)
{
    const UINT32 nAPIFilter = pHandleFields->in.nAPIFilter;
    NTSTATUS status = STATUS_SUCCESS;
    PCKD_API_DESC pAPIDesc;
    UINT i, j, cFields, cBufFields;

    DEBUGGERMSG(KDZONE_HANDLEEX, (L"++KdQueryHandleFields\r\n"));

    DEBUGGERMSG(KDZONE_HANDLEEX, (L"  PID Mask: %08lX, API Mask: %08lX\r\n",
                pHandleFields->in.nPIDFilter, pHandleFields->in.nAPIFilter));

    if (cbBufLen < sizeof(*pHandleFields))
    {
        status = STATUS_INVALID_PARAMETER;
        goto CommonExit;
    }

    // Compute number of fields buffer has space for
    cBufFields = (cbBufLen - sizeof(pHandleFields->out)) / sizeof(DBGKD_HANDLE_FIELD_DESC);

    DEBUGGERMSG(KDZONE_HANDLEEX, (L"  Buffer (addr=%08p, length=%u) has room for %u fields\r\n", pHandleFields, cbBufLen, cBufFields));

    // If we're only looking at a single API, add some extra fields
    if ((nAPIFilter & (nAPIFilter - 1)) == 0)
        pAPIDesc = &g_pTypeMap[_CountTrailingZeros(nAPIFilter)];
    else
        pAPIDesc = &g_descNull;

    cFields = lengthof(g_pGenericDesc) + pAPIDesc->cEntries;
    if (cBufFields > cFields)

⌨️ 快捷键说明

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