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

📄 kdhandle.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 2 页
字号:
        cBufFields = cFields;
    else if (cBufFields < cFields)
        status = STATUS_BUFFER_TOO_SMALL;

    pHandleFields->out.cFields = cBufFields;

    // Copy over fields
    j = 0;
    for(i = 0; i < lengthof(g_pGenericDesc) && cBufFields > 0; i++, j++, cBufFields--)
    {
        pHandleFields->out.pFieldDesc[j].nType = g_pGenericDesc[i].nType;
        pHandleFields->out.pFieldDesc[j].nFieldId = g_pGenericDesc[i].nFieldId;
    }

    for(i = 0; i < pAPIDesc->cEntries && cBufFields > 0; i++, j++, cBufFields--)
    {
        pHandleFields->out.pFieldDesc[j].nType = pAPIDesc->pDesc[i].nType;
        pHandleFields->out.pFieldDesc[j].nFieldId = pAPIDesc->pDesc[i].nFieldId;
    }

CommonExit:
    DEBUGGERMSG(KDZONE_HANDLEEX, (L"--KdQueryHandleFields\r\n"));

    return status;
}

/*++

Routine Name:

    KdQueryOneHandle

Routine Description:

    This routine fetches information for a specific handle. To determine which
    fields will be present in the data, use KdQueryHandleFields with pid=-1 and
    api=1 << handle->pci->type.

Arguments:

    hHandle         - [in]     Handle to query
    pHandleBuffer   - [out]    Pointer to results buffer
    nBufLen         - [in]     Length of pHandleBuffer buffer in bytes

    Unlike other routines, this one does not expect the caller to fill out the
    in structure in pHandleBuffer.

Return Value:

    STATUS_SUCCESS                  Success
    STATUS_INVALID_PARAMETER        hHandle is invalid
    STATUS_BUFFER_TOO_SMALL         Insufficient buffer space

--*/
NTSTATUS KdQueryOneHandle(HANDLE hHandle, PDBGKD_HANDLE_GET_DATA pHandleBuffer, UINT nBufLen)
{
    HDATA *phHandle = KdHandleToPtr(hHandle);
    PCKD_API_DESC pAPIDesc;
    UINT cFields, nMinLen;

    if (phHandle == NULL)
        return STATUS_INVALID_PARAMETER;

    pAPIDesc = &g_pTypeMap[phHandle->pci->type];
    cFields = lengthof(g_pGenericDesc) + pAPIDesc->cEntries;
    nMinLen = sizeof(pHandleBuffer->out) + (sizeof(DBGKD_HANDLE_FIELD_DATA) * cFields);
    if (nBufLen < nMinLen)
        return STATUS_BUFFER_TOO_SMALL;

    // This is a little tricky. The API filter causes handle-specific fields to
    // show up. We don't need a PID filter. Limiting the buffer size causes
    // only one handle to be returned. Setting the start point to the handle we
    // want information on causes it to get information for our specific
    // handle.
    pHandleBuffer->in.nPIDFilter = -1;
    pHandleBuffer->in.nAPIFilter = 1 << phHandle->pci->type;
    pHandleBuffer->in.hStart = (HANDLE) phHandle;
    return KdQueryHandleList(pHandleBuffer, nMinLen);
}

/*++

Routine Name:

    KdQueryHandleList

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:

    pHandleBuffer   - [in/out] Pointer to results buffer
    nBufLen         - [in]     Length of pHandleBuffer buffer in bytes

    The caller should fill out the "in" structure in pHandleBuffer 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 an error is
    returned, the contents of pHandleBuffer are undefined.

    The actual buffer size is allowed to vary, so use nBufLen to indicate the
    size of pHandleBuffer (including headers).

Return Value:

    STATUS_SUCCESS                  Success
    STATUS_INVALID_PARAMETER        pHandleBuffer.in.hStart is invalid

--*/
NTSTATUS KdQueryHandleList(PDBGKD_HANDLE_GET_DATA pHandleBuffer, UINT nBufLen)
{
    HDATA *pCurHandle;
    PDBGKD_HANDLE_FIELD_DATA pCurField;
    PCKD_API_DESC pAPIDesc;
    NTSTATUS status;
    HDATA hTemp;
    UINT32 nPIDFilter, nAPIFilter;
    UINT i, j, cBufFields;

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

    // Not having buffer space for the headers is an error. We must have enough
    // space for both input and output data!
    if (nBufLen < sizeof(*pHandleBuffer))
    {
        status = STATUS_INVALID_PARAMETER;
        goto CommonExit;
    }

    // Save some input parameters and zero the buffer
    pCurHandle = (HDATA *) pHandleBuffer->in.hStart;
    nPIDFilter = pHandleBuffer->in.nPIDFilter;
    nAPIFilter = pHandleBuffer->in.nAPIFilter;
    memset(pHandleBuffer, 0, nBufLen);

    DEBUGGERMSG(KDZONE_HANDLEEX, (L"  PID Mask: %08lX, API Mask: %08lX, Start=%08p\r\n",
                nPIDFilter, nAPIFilter, pCurHandle));

    // Compute number of DBGKD_HANDLE_FIELD_DATA entries in the buffer
    cBufFields = (nBufLen - sizeof(pHandleBuffer->out)) / sizeof(DBGKD_HANDLE_FIELD_DATA);

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

    // NULL handle means start at the beginning
    if (pCurHandle == NULL)
        pCurHandle = (HDATA *) pHandleList->linkage.fwd;

    // Test the waters...
    if (KdpMoveMemory(&hTemp, pCurHandle, sizeof(HDATA)) < sizeof(HDATA))
    {
        status = STATUS_INVALID_PARAMETER;
        goto CommonExit;
    }

    pHandleBuffer->out.cFields = 0;

    for(i = 0; i < cBufFields; i++)
        pHandleBuffer->out.pFields[i].fValid = 0;

    // Seems like a valid pointer, so lets start blasting data.
    pCurField = pHandleBuffer->out.pFields;
    for(; pCurHandle != pHandleList; pCurHandle = (HDATA *) pCurHandle->linkage.fwd)
    {
        // Verify that handle matches both filters
        if ((nPIDFilter & pCurHandle->lock) == 0 ||
            (nAPIFilter & (1 << pCurHandle->pci->type)) == 0)
            continue;

        // Cache description of handle-specific data. If we're not doing
        // handle-specific data, cache the NULL descriptor to simplify the
        // processing code.
        if ((nAPIFilter & (nAPIFilter - 1)) == 0 &&
            pCurHandle->pci->type < lengthof(g_pTypeMap))
            pAPIDesc = &g_pTypeMap[pCurHandle->pci->type];
        else
            pAPIDesc = &g_descNull;

        // If we don't have enough space to process this handle, we'll come
        // back to it.
        if (cBufFields < (lengthof(g_pGenericDesc) + pAPIDesc->cEntries))
            break;

        for(i = 0, j = 0; i < lengthof(g_pGenericDesc); i++, j++)
            KdHandleGetField(&pCurField[j], &g_pGenericDesc[i], pCurHandle);

        // Skip app-specific data. This happens for instance on threads
        // that die. The pointer is no longer valid, but the handle doesn't
        // disappear while apps have a reference to it.
        if (pAPIDesc->pfnValidateHandle(pCurHandle))
        {
            for(i = 0; i < pAPIDesc->cEntries; i++, j++)
                KdHandleGetField(&pCurField[j], &pAPIDesc->pDesc[i], pCurHandle->pvObj);
        }

        // Now update buffer & length
        i = (lengthof(g_pGenericDesc) + pAPIDesc->cEntries);
        cBufFields -= i;
        pCurField += i;
        pHandleBuffer->out.cFields += i;
    }

    // We don't want to traverse the list all over again!
    if (pCurHandle == pHandleList)
        pCurHandle = NULL;

    // We broke out on the current handle, so we should resume
    pHandleBuffer->out.hContinue = (HANDLE) pCurHandle;

    DEBUGGERMSG(KDZONE_HANDLEEX, (L"  Next Handle: %08p\r\n", pCurHandle));

    status = STATUS_SUCCESS;

CommonExit:
    DEBUGGERMSG(KDZONE_HANDLEEX, (L"--KdQueryHandleList\r\n"));

    return status;
}

/*++

Routine Name:

    _CountTrailingZeros

Routine Description:

    This is a clever function to extract the zero-based index of the
    least-significant one bit in nMask. If we ever get an intrinsic for this,
    this function should go away promptly.

Arguments:

    nMask           - [in]     Bitmask to extract least-significant one from

Return Value:

    Zero-based index of the least-significant one

--*/
#pragma warning(push)
#pragma warning(disable:4146)
static UINT _CountTrailingZeros(UINT32 nMask)
{
#if !_INTRINSIC_IS_SUPPORTED(_CountLeadingZeros)
    nMask = (nMask & -nMask) - 1;
    return (UINT) g_abCntLeadTbl32[((g_nCntLeadMagic32 * nMask) >> 27) & 0x1F];
#else
    return ((sizeof(UINT32) * CHAR_BIT) - (_CountLeadingZeros(nMask & -nMask) + 1));
#endif /* !_INTRINSIC_IS_SUPPORTED(_CountLeadingZeros) */
}
#pragma warning(pop)

/*++

Routine Name:

    KdHandleGetField

Routine Description:

    This function interprets a KD_HANDLE_DESC and extracts the datum into a
    DBGKD_HANDLE_FIELD_DATA structure.

Arguments:

    pField          - [out]    Buffer that receives the datum
    pDesc           - [in]     Description of datum to read
    pvStruct        - [in]     Pointer to structure to read datum from

Return Value:

    Zero-based index of the least-significant one

--*/
static void KdHandleGetField(PDBGKD_HANDLE_FIELD_DATA pField, PCKD_HANDLE_DESC pDesc, LPCVOID pvStruct)
{
    UINT32 nData;
    BOOL fSigned;

    pField->nFieldId = pDesc->nFieldId;

    if (pDesc->pfnReadField != NULL)
    {
        pField->nData = pDesc->pfnReadField(pvStruct);
    }
    else
    {
        // move pointer to field
        pvStruct = (LPCVOID)((DWORD) pvStruct + pDesc->nOffset);

        fSigned = (pDesc->nType == KD_FIELD_SINT ? TRUE : FALSE);
        switch(pDesc->nSize)
        {
        case 1:
            if (fSigned)
                nData = (UINT32) *((signed __int8 *) pvStruct);
            else
                nData = (UINT32) *((unsigned __int8 *) pvStruct);

            break;
        case 2:
            if (fSigned)
                nData = (UINT32) *((signed __int16 *) pvStruct);
            else
                nData = (UINT32) *((unsigned __int16 *) pvStruct);

            break;
        case 4:
            if (fSigned)
                nData = (UINT32) *((signed __int32 *) pvStruct);
            else
                nData = (UINT32) *((unsigned __int32 *) pvStruct);

            break;
        default:
            CODE_NEVER_REACHED();
        }

        pField->nData = nData;
    }

    pField->fValid = 1;
}

static BOOL KdDontValidate(HDATA *ph)
{
    return TRUE;
}

static BOOL KdValidateThread(HDATA *ph)
{
    PROCESS *pProc;
    THREAD *pThread;
    UINT32 nRefKey;

    for(nRefKey = ph->lock; nRefKey != 0; nRefKey &= (nRefKey - 1))
    {
        pProc = &kdProcArray[_CountTrailingZeros(nRefKey)];

        for(pThread = pProc->pTh; pThread != NULL; pThread = pThread->pNextInProc)
        {
            if (pThread->hTh == ph->hValue)
                return TRUE;
        }
    }

    return FALSE;
}

static BOOL KdValidateProcess(HDATA *ph)
{
    UINT i;

    for(i = 0; i < MAX_PROCESSES; i++)
    {
        if (kdProcArray[i].hProc == ph->hValue)
            return TRUE;
    }

    return FALSE;
}

static UINT32 KdReadGlobalRefCount(HANDLE hHandle)
{
    const HDATA *pHandle = (const HDATA *) hHandle;
    UINT i, c;

    // typedef union REFINFO
    // {
    //     ulong count;
    //     FULLREF *pFr;
    // } REFINFO;
    //
    // When count < 0x10000, the handle is owned by 1 process and the count
    // corresponds to the reference count in that process. When
    // count >= 0x10000, the pFr field is used for reference counting.
    if (pHandle->ref.count < 0x10000)
        return pHandle->ref.count;

    // Sum up the number of references in each process
    c = 0;
    for(i = 0; i < MAX_PROCESSES; i++)
        c += pHandle->ref.pFr->usRefs[i];

    return c;
}

static UINT32 KdReadHandleType(PCVOID pvData)
{
    UINT nType = ((const HDATA *) pvData)->pci->type;

    if (nType == HT_CRITSEC)
        return (UINT32) L"Crit Sec";
    else if (nType == HT_MANUALEVENT)
        return (UINT32) L"Manual Event";
    else if (nType < lengthof(g_apszHandleTypeNames))
        return (UINT32) g_apszHandleTypeNames[nType];

    DEBUGGERMSG(KDZONE_HANDLEEX, (L"  KdReadHandleType: hHandle=%08lX, unknown type=%u\r\n", pvData, nType));

    return (UINT32) L"?";
}

static UINT32 KdReadHandleName(PCVOID pvData)
{
    const HDATA *phHandle = (const HDATA *) pvData;

    switch(phHandle->pci->type)
    {
    case HT_EVENT:
    {
        const EVENT *pEvent = (const EVENT *) phHandle->pvObj;
        return (UINT32)(pEvent->name == NULL ? NULL : pEvent->name->name);
    }
    case HT_MUTEX:
    {
        const MUTEX *pMutex = (const MUTEX *) phHandle->pvObj;
        return (UINT32)(pMutex->name == NULL ? NULL : pMutex->name->name);
    }
    case HT_SEMAPHORE:
    {
        const SEMAPHORE *pSem = (const SEMAPHORE *) phHandle->pvObj;
        return (UINT32)(pSem->name == NULL ? NULL : pSem->name->name);
    }
    case SH_CURPROC:
        return (UINT32)((PROCESS *) phHandle->pvObj)->lpszProcName;
    default:
        return (UINT32) L"";
    }
}

static UINT32 KdReadThreadPID(PCVOID pvData)
{
    return (UINT32)(((const THREAD *) pvData)->pOwnerProc->procnum);
}

static UINT32 KdReadMutexOwner(PCVOID pvData)
{
    return (UINT32)(((const MUTEX *) pvData)->pOwner->hTh);
}

⌨️ 快捷键说明

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