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

📄 edbgprot.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 4 页
字号:
//
// 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.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:  
    edbgprot.c
    
Abstract:  
    Routines for kernel debug services over Ethernet (KITL).  This file contains
    the core functions to implement the KITL protocol over UDP.
    
Functions:


Notes: 

--*/
#include <windows.h>
#include <types.h>
#include <nkintr.h>
#include <kitl.h>
#include <kitlprot.h>
#include "kernel.h"
#include "kitlp.h"


DWORD SC_WaitForMultiple(DWORD cObjects, CONST HANDLE *lphObjects, BOOL fWaitAll, DWORD dwTimeout);

// time to retransmit if using ticks
#define MIN_POLL_TIME   1000
#define MAX_POLL_TIME   8000

// time to retransmit if using iterations
#define MIN_POLL_ITER   10000
#define MAX_POLL_ITER   1600000

static UCHAR PollRecvBuf[KITL_MTU];

static BOOL ProcessRecvFrame(UCHAR *pFrame, WORD wMsgLen, BOOL fUseSysCalls, PFN_TRANSMIT pfnTransmit, LPVOID pData);
static void KITLDecodeFrame(char *LeadingText, KITL_HDR *pHdr, WORD wLen);
static BOOL ProcessAdminMsg(KITL_HDR *pHdr, WORD wMsgLen, BOOL fUseSysCalls, PFN_TRANSMIT pfnTransmit, LPVOID pData);

extern CRITICAL_SECTION KITLODScs;
extern CRITICAL_SECTION KITLKCallcs;
extern KITLTRANSPORT Kitl;
extern BOOL IsDesktopDbgrExist (void);
extern BOOL KernelIoctl (DWORD , LPVOID , DWORD , LPVOID , DWORD , LPDWORD );


extern DWORD g_dwKeys[];
extern CHAR* g_keyNames[];


#include "..\..\..\..\..\public\common\oak\dbgpub\dbgbrk.c" // For DoDebugBreak()


/* SetClientEvent
 *
 *   Adjust proc permissions to match client and set event
 */
void SetClientEvent(KITL_CLIENT *pClient, HANDLE hEvent)
{
    DWORD OldProcPerms;
    if (pClient->ProcPerms) {
        SWITCHKEY (OldProcPerms, pClient->ProcPerms);
    }
    if (hEvent && !SC_EventModify(hEvent, EVENT_SET)) {
        KITL_DEBUGMSG(ZONE_ERROR,("!SetClientEvent:Error %u setting event %X..\n",GetLastError(),hEvent));
    }
    if (pClient->ProcPerms) {
        SETCURKEY (OldProcPerms);
    }
}

/* ResetClientState
 *
 *   Reset all state associated with client struct.
 *   Must hold client CS while calling this function.
 */
void
ResetClientState(KITL_CLIENT *pClient)
{
    // When system is coming up, we can't make any system calls. 
    UCHAR UseSysCalls = (pClient->State & KITL_USE_SYSCALLS);
    
    // Cancel any timers
    CancelTimersForClient(pClient);
    
    // Reset our state
    pClient->TxSeqNum = 0;
    pClient->AckExpected = 0;
    pClient->RxSeqNum = 0;
    pClient->RxWinEnd = pClient->WindowSize;
    memset(&pClient->TxFrameLen,0,sizeof(pClient->TxFrameLen));
    memset(&pClient->RxFrameLen,0,sizeof(pClient->RxFrameLen));
    pClient->NextRxIndex = 0;
    pClient->State &= ~KITL_SYNCED;

    // Unblock any threads which might be stuck
    if (UseSysCalls) {
        SetClientEvent(pClient,pClient->evTxFull);
        // For now, let recv threads keep blocking. We might want to return an error
        // here, investigate later.
//        SetEvent(pClient->evRecv);
    }
}

static BOOL KITLPollData(BOOL fUseSysCalls, PFN_TRANSMIT pfnTransmit, LPVOID pData)
{
    LPBYTE pRecvBuf = PollRecvBuf;
    
    if (fUseSysCalls && (KITLGlobalState & KITL_ST_MULTITHREADED)
        && !(pRecvBuf = _alloca(KITL_MTU))) {
        KITLOutputDebugString("!KITLPollData: STACK OVERFLOW!\r\n");
        return FALSE;
    }
    HandleRecvInterrupt(pRecvBuf, fUseSysCalls, pfnTransmit, pData);
    return TRUE;
}


static BOOL CheckCfg (KITL_CLIENT *pClient)
{
    return !(pClient->State & KITL_WAIT_CFG);
}

static BOOL RetransmitCfg (KITL_CLIENT *pClient, BOOL fUseSysCalls)
{
    return SendConfig (pClient, FALSE);
}

/* ExchangeConfig
 *
 *   If we have peer address (e.g. for default services, we get this info from eshell at boot),
 *   send config message to peer, indicating the service ID and window size to use.  Otherwise,
 *   do passive connect (desktop app will get device address from eshell, then send us a config
 *   message).
 */
BOOL ExchangeConfig(KITL_CLIENT *pClient)
{
    // When system is coming up, we can't make any system calls. 
    BOOL fUseSysCalls = (pClient->State & KITL_USE_SYSCALLS)? TRUE : FALSE; 

    if (!(pClient->State & KITL_WAIT_CFG))
        return 0 != (pClient->State & KITL_CLIENT_REGISTERED);
    
    KITL_DEBUGMSG(ZONE_INIT,("Waiting for service '%s' to connect..., fUseSysCalls = %d\n", pClient->ServiceName, fUseSysCalls));

    if (fUseSysCalls && (KITLGlobalState & KITL_ST_INT_ENABLED)) { 
        DWORD Timeout = MIN_POLL_TIME;
    
        while (pClient->State & KITL_WAIT_CFG) {

            if (!SendConfig (pClient, FALSE)) {
                return FALSE;
            }

            switch (SC_WaitForMultiple (1, &pClient->evCfg, 0, Timeout)) {
            case WAIT_OBJECT_0:
                return (0 != (pClient->State & KITL_CLIENT_REGISTERED));
                
            case WAIT_TIMEOUT:
                if (Timeout < MAX_POLL_TIME)
                    Timeout <<= 1;
                break;
                
            default:
                KITLOutputDebugString("!ExchangeConfig: WaitForMultipleObjects failed\n");
                return FALSE;
            }
            
        }
        
    } else {

        if (!SendConfig (pClient, FALSE))
            return FALSE;
            
        KITLPollResponse (fUseSysCalls, CheckCfg, RetransmitCfg, pClient);

    }
    return 0 != (pClient->State & KITL_CLIENT_REGISTERED);
}

BOOL SendConfig(KITL_CLIENT *pClient, BOOL fIsResp)
{
    UCHAR *FmtBuf;
    KITL_HDR *pHdr;
    KITL_SVC_CONFIG_DATA *pConfigData;

    FmtBuf = (UCHAR *) _alloca (Kitl.FrmHdrSize   // for transport header
        + sizeof(KITL_HDR)                        // for protocol header
        + sizeof(KITL_SVC_CONFIG_DATA)            // for data
        + Kitl.FrmTlrSize);                       // for transport tailer
    if (!FmtBuf) {
        KITLOutputDebugString ("!SendConfig: Stack overflow\r\n");
        return FALSE;
    }
    pHdr = (KITL_HDR *)(FmtBuf + Kitl.FrmHdrSize);   // pointer to the  protocol header
    pConfigData = (KITL_SVC_CONFIG_DATA *) KITLDATA(pHdr);   // pointer to the data

    // Format protocol header
    pHdr->Id = KITL_ID;
    pHdr->Service = KITL_SVC_ADMIN;
    pHdr->Flags = KITL_FL_FROM_DEV;
    if (fIsResp)
        pHdr->Flags |= KITL_FL_ADMIN_RESP;
    pHdr->SeqNum = 0;
    pHdr->Cmd = KITL_CMD_SVC_CONFIG;

    // Format service config message
    pConfigData->ProtocolVersion = CURRENT_KITL_VERSION;
    strcpy(pConfigData->ServiceName,pClient->ServiceName);
    pConfigData->ServiceId = pClient->ServiceId;
    pConfigData->WindowSize = pClient->WindowSize;
    pConfigData->Flags = pClient->CfgFlags;
    
    if (KITLDebugZone & ZONE_FRAMEDUMP)
        KITLDecodeFrame(">>SendConfig", pHdr, sizeof(KITL_HDR) + sizeof(KITL_SVC_CONFIG_DATA));
    if (!KitlSendFrame (FmtBuf, sizeof(KITL_HDR) + sizeof(KITL_SVC_CONFIG_DATA))) {
        KITLOutputDebugString("!SendConfig: Error in KitlSendFrame\n");
        return FALSE;
    }
    return TRUE;
}

BOOL KITLPollResponse (BOOL fUseSysCalls, PFN_CHECK pfnCheck, PFN_TRANSMIT pfnTransmit, LPVOID pData)
{
    DWORD dwLoopCnt = 0, dwLoopMax = MIN_POLL_ITER;
    DWORD dwStartTime = CurMSec;
    int   nTimeMax = MIN_POLL_TIME;  // start with 1 sec
    BOOL  fUseIter = FALSE, fUseTick = FALSE;

    while (!pfnCheck (pData)) {
        //
        // if we've already connected with desktop, use the desktop
        // "Retransmit" package to determine if we need to retransmit
        //
        if (!(KITLGlobalState & KITL_ST_DESKTOP_CONNECTED)) {
            if (fUseTick) {
                if ((int) (CurMSec - dwStartTime) > nTimeMax) {
                    // retransmit
                    if (!pfnTransmit (pData, fUseSysCalls))
                        return FALSE;
                    dwStartTime = CurMSec;
                    if (nTimeMax < MAX_POLL_TIME)
                        nTimeMax <<= 1;
                }
            } else if (fUseIter || (dwStartTime == CurMSec)) {
                // if time isn't moving for a while, we'll
                // use iteration.
                if (dwLoopCnt ++ > dwLoopMax) {
                    if (!pfnTransmit (pData, fUseSysCalls))
                        return FALSE;
                    if (dwLoopMax < MAX_POLL_ITER)
                        dwLoopMax <<= 1;
                    dwLoopCnt = 0;
                    fUseIter = TRUE;
                }
            } else {
                // time is moving, just use tick from here
                fUseTick = TRUE;
            }
        }
        if (!KITLPollData(fUseSysCalls, pfnTransmit, pData)) {
            return FALSE;
        }
    }
    return TRUE;
}

static BOOL ChkAck (KITL_CLIENT *pClient)
{
    return pClient->AckExpected == pClient->TxSeqNum;
}

static BOOL TranAck (KITL_CLIENT *pClient, BOOL fUseSysCalls)
{
    UCHAR Seq;
    for (Seq = pClient->AckExpected; Seq != pClient->TxSeqNum; SEQ_INC (Seq))
        RetransmitFrame (pClient, (UCHAR) (Seq % pClient->WindowSize), fUseSysCalls);
    return TRUE;
}

/*  @doc   KITL
 *  @func  BOOL | KITLSend | Send a message over debug Ethernet interface.
 *  @rdesc Return TRUE if successful, FALSE if error occurrs.
 *  @comm  Send a message to peer KITL client.  Returns immediately unless the transmit
 *         window is full, or if we're in polling mode, in which case this function will 
 *         block.  Once sent, the message will be retried by the KITL subsystem until 
 *         it is acknowledged by other side.
 *  @xref  <f KITLRegisterClient> <f KITLRecv>
 */
static HANDLE hDbgMsgThread;
extern HANDLE hIntrThread;
extern HANDLE hTimerThread;
BOOL
KITLSend(
    UCHAR Id,               // @parm [IN] - KITL client id (returned from <f KITLRegisterClient>)
    UCHAR *pUserData,       // @parm [IN] - Data to send.
    DWORD dwUserDataLen )   // @parm [IN] - Data length (up to KITL_MAX_DATA_SIZE).
{
    KITL_CLIENT *pClient = KITLClients[Id];
    PKITL_HDR pHdr;
    UCHAR *pFrame, *pData;
    BOOL fRet = TRUE;
    DWORD dwPacketIndex;
    UCHAR PrevSyscallState;
    BOOL  fRestoreClientState = FALSE, fRestoreGlobalState = FALSE;
    BOOL  fUseSysCalls;

    if (!IS_VALID_ID(Id))
        return FALSE;

    // Check that client is registered
    if (!pClient || (pClient->ServiceId != Id))
        return FALSE;

⌨️ 快捷键说明

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