* @brief     : 与内核通信IPC的用户层代码
DWORD 
UcIpc::RecvMsg(
    IN CKxEUCAllocator* allocator,
    IN BOOL bChannel,
IN OUT PULONG pulPort,
    IN OUT PBYTE* ppInBuf1,
    IN OUT PULONG pulInBufLen1,
    IN OUT PBYTE* ppInBuf2,
    IN OUT PULONG pulInBufLen2,
    IN DWORD Timeout
)
/*++
Routine Description:

接受数据。
共享内存被分为两大块,分别用做Channel1和Channel2。
其中每块Channel又有pInBuf1和pInBuf2.
当bChannel==TRUE时,拷贝至前KE_IPC_BUF_MAX_SIZE区域 Arguments: pInBuf2 - 一般这块buf用做时间校检。可为空
--*/
{
DWORD         nStatus = IPC_COM_ERROR;
HANDLE        hRecvEvent = NULL;
HANDLE        hSendEvent = NULL;
PBYTE         pAddr         = NULL;
PBYTE   pNewOutBuf = NULL;
KeIpcMsgHead  MsgHead = {0};
HANDLE   ArrEvent[2] = {0};
CHAR   Md5[UC_IPC_MD5_SIZE] = {0};
if (!ppInBuf1 || !pulInBufLen1 || !pulPort
|| !m_bInitFlag) {goto _Exit_;} if (bChannel)
{
hRecvEvent = m_hRecvEventC1;
hSendEvent = m_hSendEventC1;
pAddr = m_pMapFileBuf;
}
else
{
hRecvEvent = m_hRecvEventC2;
hSendEvent = m_hSendEventC2;
pAddr = m_pMapFileBuf + m_BufSize;
}

ArrEvent[0] = hSendEvent;
ArrEvent[1] = m_hEndEvent; //////////////////////////////////////////////////////////////////////////???????? bug
  nStatus = WaitForMultipleObjects(2, ArrEvent,
  FALSE, Timeout);
  if(nStatus != WAIT_OBJECT_0) {nStatus = IPC_COM_WAIT_FAIL; goto _Exit_;} memcpy(&MsgHead, pAddr, sizeof(KeIpcMsgHead));    if ( bChannel && (MsgHead.ulInBufLen1 + MsgHead.ulInBufLen2
        + sizeof(KeIpcMsgHead) > m_BufSize) ||
        !bChannel && (MsgHead.ulInBufLen1 + MsgHead.ulInBufLen2
        + sizeof(KeIpcMsgHead) > m_BufSize2) )
{
        OutputDebugStringA("TOO_SMALL\n");
nStatus = IPC_COM_BUF_TOO_SMALL; 
goto _Exit_;
} // 如果调用方不接受第二个参数,就不用申请相应空间了
if (pulInBufLen2 && ppInBuf2)
{
pNewOutBuf = (PBYTE)allocator->Alloc ( 
MsgHead.ulInBufLen1 + MsgHead.ulInBufLen2);
}
else
{
pNewOutBuf = (PBYTE)allocator->Alloc ( 
MsgHead.ulInBufLen1);
}
if (!pNewOutBuf) {nStatus = IPC_COM_ERROR_MEM_ALLOT; goto _Exit_;} memcpy(pNewOutBuf, pAddr + sizeof(KeIpcMsgHead), 
MsgHead.ulInBufLen1);
MDString (pNewOutBuf, MsgHead.ulInBufLen1, Md5);
if (strncmp(MsgHead.Md5, Md5, UC_IPC_MD5_SIZE))
{
OutputDebugStringA("Md5 Fail\n");
nStatus = IPC_COM_ERROR_MEM_ALLOT;
goto _Exit_;
} *pulPort = MsgHead.ulPort;
*ppInBuf1 = pNewOutBuf;
*pulInBufLen1 = MsgHead.ulInBufLen1; if (pulInBufLen2 && ppInBuf2)
{
memcpy(
pNewOutBuf + MsgHead.ulInBufLen1, 
pAddr + sizeof(KeIpcMsgHead) + MsgHead.ulInBufLen1, 
MsgHead.ulInBufLen2
);
*ppInBuf2 = pNewOutBuf + MsgHead.ulInBufLen1;
*pulInBufLen2 = MsgHead.ulInBufLen2;
}

nStatus = IPC_COM_SUCCEED;
SetEvent(hRecvEvent);_Exit_:

return nStatus;
}我看它可以获得系统里的所有程序打开文件的信息。然后根据对应的要保护的程序列表过滤。
这些信息都在ppInBuf1里面。
好像是用的内核通信的技术?
可以告诉我他用的什么原理吗?
我该怎么弄明白这段代码?

解决方案 »

  1.   

    哦DWORD
    UcIpc::CommunicationWorker( 
    LPVOID lpPrarm 
    )
    /*++
        Routine Description:
        每个端口将开启一个此线程,用做处理驱动传过来的消息通过注册的回调处理后传回去--*/
    {
    CKxEUCAllocator allocator;
    UcIpc* pUcIpc = (UcIpc*)lpPrarm;
    PBYTE pInBuf1 = NULL;
    ULONG pulInBufLen1 = 0;
    PBYTE pCheckTime = NULL;
    ULONG pulCheckTimeLen = 0;
    PBYTE pvReplyData = NULL;
    DWORD dwDataLengthRet = 0;
    ULONG ulPort = 0;
    NTSTATUS nStatus = IPC_COM_ERROR;
    DWORD           dwCallBackRet   = 0; if (!pUcIpc) {return 0;} while ( pUcIpc->m_bInitFlag )
    {
            // m_pCallbackRoutine中曾经由于不好的编程习惯未设置返回dwDataLengthRet的值导致崩溃
            // 故在此每次循环重新初始化一次.
            pInBuf1 = NULL;
            pulInBufLen1 = 0;
            pCheckTime = NULL;
            pulCheckTimeLen = 0;
            pvReplyData = NULL;
            dwDataLengthRet = 0;
            ulPort = 0;
            nStatus = IPC_COM_ERROR;
            dwCallBackRet   = 0; nStatus = pUcIpc->RecvMsg(
    &allocator,
    TRUE,
    &ulPort,
    &pInBuf1,
    &pulInBufLen1,
    &pCheckTime,
    &pulCheckTimeLen,
    UC_IPC_TIME_OUT
    );
    if (IPC_COM_SUCCEED != nStatus)
            {
                if (IPC_COM_WAIT_FAIL != nStatus)
                {
                    WCHAR wszTime[127 + 1] = {0};
                    wsprintfW(wszTime, L"RecvMsg fail!! %x\n", nStatus);
                    OutputDebugStringW(wszTime);
                }
              
                continue;
            }

            // 如果没有UC_IPC_DRIVER_MARK位,表示不是从驱动传来的
            if (!(ulPort & UC_IPC_DRIVER_MARK)) {continue;}
            ulPort &= ~UC_IPC_DRIVER_MARK; if (pUcIpc->m_pCallbackRoutine)            //这个回调函数用来到显示数据
    {
    pUcIpc->m_pCallbackRoutine(
    &allocator,             // 返回数据使用的分配器
    pInBuf1,                // 数据
    pulInBufLen1,           // 数据长度
    pUcIpc->m_pvParam,      // 回调的自定义参数
    (PVOID*)&pvReplyData,   // 返回的数据, 如果不需要返回则ppvDataRet == NULL
    &dwDataLengthRet);      // 返回的数据长度, 如果不需要返回则pdwDataLengthRet == NULL); if (UC_IPC_DRIVER_NEED_REPLY == ulPort)
    {
                    /////////////////////////////////////////////////////////////////////////
                    // 下面这段检测数据头的代码本来不属于统一通信。但原来统一通信传递的数据都有个没用的
                    // 数据头,只好在这里去掉。
    //                 if (dwDataLengthRet <= sizeof(KXE_COMM_PACKET_HEADER))
    //                 {
                        // 如果不带数据头,则随便传个脏数据。
                        // 驱动中可由UC_IPC_DRIVER_ZERO_LEN获知
                        nStatus = pUcIpc->SendMsg(
                            FALSE,
                            UC_IPC_DRIVER_ZERO_LEN,
                            (PBYTE)&pvReplyData,     // 无用的脏数据
                            sizeof(PVOID*),
                            pCheckTime,
                            pulCheckTimeLen,
                            UC_IPC_TIME_OUT
                            );
    //                 }
    //                 else
    //                 {
    //                     pvReplyData += sizeof(KXE_COMM_PACKET_HEADER);
    //                     dwDataLengthRet -= sizeof(KXE_COMM_PACKET_HEADER);
    //                     nStatus = pUcIpc->SendMsg(
    //                         FALSE,
    //                         0 != dwDataLengthRet ? UC_IPC_DRIVER_NON : UC_IPC_DRIVER_ZERO_LEN,
    //                         0 != dwDataLengthRet ? (PBYTE)pvReplyData : (PBYTE)&pvReplyData, // 如果为零,随便传个脏数据
    //                         0 != dwDataLengthRet ? dwDataLengthRet : sizeof(PVOID*),
    //                         pCheckTime,
    //                         pulCheckTimeLen,
    //                         UC_IPC_TIME_OUT
    //                         );
    //                     //OutputDebugStringW(L"SendMsg Over\n\n");
    //                 }
    }
    } allocator.Clear();
    } return 0;
    }
      

  2.   


    DWORD 
    UcIpc::SendMsg(
        IN BOOL bChannel,
        IN ULONG ulPort,
        IN PBYTE pInBuf1,
        IN ULONG ulInBufLen1,
        IN OPTIONAL PBYTE pInBuf2,
        IN OPTIONAL ULONG ulInBufLen2,
        IN DWORD Timeout
    )
    /*++
    Routine Description:

    发送数据。
    共享内存被分为两大块,分别用做Channel1和Channel2。
    其中每块Channel又有pInBuf1和pInBuf2.
    当bChannel==TRUE时,拷贝至前KE_IPC_BUF_MAX_SIZE区域 Arguments: pulPort - 以前表示端口。目前采用每个UcIpc绑定一个端口,故此字段做通知驱动采取某些特殊操作的标准 pInBuf2 - 一般这块buf用做时间校检。可为空
    --*/
    {
    NTSTATUS      nStatus = IPC_COM_ERROR;
    HANDLE        hRecvEvent = NULL;
    HANDLE        hSendEvent = NULL;
    PBYTE         pAddr         = NULL;
    KeIpcMsgHead  MsgHead = {0};
    HANDLE   ArrEvent[2] = {0};    WCHAR DbgStr[200] = {0}; if ((!pInBuf1 || !m_bInitFlag)) {
    OutputDebugStringA("UcIpc::SendMsg invail !\n");
    goto _Exit_;
    } if (bChannel && (ulInBufLen1 + ulInBufLen2
    + sizeof(KeIpcMsgHead) > m_BufSize) ||
            !bChannel && (ulInBufLen1 + ulInBufLen2
            + sizeof(KeIpcMsgHead) > m_BufSize2) )
    {
            swprintf(DbgStr, L"UcIpc::SendMsg IPC_COM_BUF_TOO_SMALL %x, %x, %x!!\n", ulInBufLen1, m_BufSize2, m_nIpcAddr);
    OutputDebugStringW(DbgStr);
    nStatus = IPC_COM_BUF_TOO_SMALL;
    goto _Exit_;
    }

    if (bChannel)
    {
    hRecvEvent = m_hRecvEventC1;
    hSendEvent = m_hSendEventC1;
    pAddr = m_pMapFileBuf;
    }
    else
    {
    hRecvEvent = m_hRecvEventC2;
    hSendEvent = m_hSendEventC2;
    pAddr = m_pMapFileBuf + m_BufSize;
    } ArrEvent[0] = hRecvEvent;
    ArrEvent[1] = m_hEndEvent;
    nStatus = WaitForMultipleObjects(2, ArrEvent,
      FALSE, Timeout);
    if(WAIT_OBJECT_0 != nStatus) {
    //OutputDebugStringA("UcIpc::SendMsg wait fail!\n");
    nStatus = IPC_COM_WAIT_FAIL; goto _Exit_;}    // 一个channel中的共享内存中的结构如下:
        // +--------------------+
        // |    KeIpcMsgHead    |
        // +--------------------+
        // |    Buf1            |
        // +--------------------+
        // |    Buf2            |
        // +--------------------+
    MsgHead.ulPort = ulPort;
    MsgHead.ulInBufLen1 = ulInBufLen1;
    MsgHead.ulInBufLen2 = ulInBufLen2;
    MDString (pInBuf1, ulInBufLen1, MsgHead.Md5); memcpy(pAddr, &MsgHead, sizeof(KeIpcMsgHead));
    memcpy(pAddr + sizeof(KeIpcMsgHead), 
    pInBuf1, ulInBufLen1);
    memcpy(pAddr + sizeof(KeIpcMsgHead) + ulInBufLen1,
    pInBuf2, ulInBufLen2);

    nStatus = IPC_COM_SUCCEED;
    //OutputDebugStringA("UcIpc::SendMsg succeed!\n");
    SetEvent(hSendEvent);_Exit_:

    return nStatus;
    }
      

  3.   

    这个都是一个文件里面的.#define UC_IPC_EVENT_RECV_C2 L"Global\\{F25FB848-C89D-42fc-9005-1854F5187777}" // Channel 2
    wstTemp = UC_IPC_EVENT_SEND_C2;
    wstTemp += wProtocolType;
    m_hSendEventC2 = ::CreateEventW(m_pSendSAC2, FALSE, FALSE, wstTemp.c_str());
    if (!m_hSendEventC2)
    {
    m_hSendEventC2 = ::OpenEventW(EVENT_ALL_ACCESS, FALSE, wstTemp.c_str());
    if (!m_hSendEventC2) {goto _Exit_;}
    } wstTemp = UC_IPC_EVENT_RECV_C2;
    wstTemp += wProtocolType;
    m_hRecvEventC2 = ::CreateEventW(m_pRecvSAC2, FALSE, TRUE, wstTemp.c_str());
    if (!m_hRecvEventC2)
    {
    m_hRecvEventC2 = ::OpenEventW(EVENT_ALL_ACCESS, FALSE, wstTemp.c_str());
    if (!m_hRecvEventC2) {goto _Exit_;}
    }    wstTemp = UC_IPC_FILEMAPNAME_C1;
        wstTemp += wProtocolType;
    m_bInitFlag = InitMap(wstTemp.c_str(), ulSize + ulSize2);
    if (!m_bInitFlag) {goto _Exit_;} m_hWork = CreateThread(
    NULL,
    0,
    UcIpc::CommunicationWorker,.....
    //////////////////////////////
    BOOL
    UcIpc::InitMap(
    IN LPCWSTR szMapName,
    IN ULONG ulSize
        )
    {
        m_hMapFile = ::CreateFileMappingW(
            INVALID_HANDLE_VALUE,               // use paging file
            m_pMapSA,                           // default security 
            PAGE_READWRITE,                     // read/write access
            0,                                  // max. object size 
            ulSize,     // buffer size  
            szMapName);     // name of mapping object
    if (!m_hMapFile)
    {
    m_hMapFile = ::OpenFileMappingW(
    FILE_MAP_ALL_ACCESS,            // read/write access
    TRUE,                           // do not inherit the name
    szMapName); // name of mapping object
    }
    if (!m_hMapFile) {return FALSE;}

        m_pMapFileBuf = (BYTE*) ::MapViewOfFile(
    m_hMapFile, // handle to map object
            FILE_MAP_ALL_ACCESS, // read/write permission
            0,                    
            0,                    
            ulSize);
    if (!m_pMapFileBuf) {return FALSE;}
    memset(m_pMapFileBuf, 0x0, ulSize); return TRUE;
    }
      

  4.   

    这一句把数据复制出来了.
    memcpy(&MsgHead, pAddr, sizeof(KeIpcMsgHead));
    pAddr就是m_pMapFileBuf=MapViewOfFile()的地址.
    难道是
    wstTemp = "Global\{C82FCCB5-4070-4a60-A627-FF1143DE4BEF}0"     有特殊意义???