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

📄 obexbthtransport.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "common.h"
#include "CObex.h"
#include "ObexBTHTransport.h"
#include "BTHTransportSocket.h"
#include "bt_api.h"
#include <initguid.h>
#include "bt_sdp.h"
#include "bthapi.h"
#include "PropertyBag.h"
#include "PropertyBagEnum.h"

#include "ObexStrings.h"

#define OBEX_PROTOCOL_UUID 8

LPSOCKET CObexBTHTransport::pSocket = 0;

#define GUID_FORMAT     L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"
#define GUID_FORMAT_SEP L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x};"
#define GUID_ELEMENTS(p) \
    p.Data1,                 p.Data2,    p.Data3,\
    p.Data4[0], p.Data4[1], p.Data4[2], p.Data4[3],\
    p.Data4[4], p.Data4[5], p.Data4[6], p.Data4[7]

struct BT_UUID16_LIST
{
    GUID uuid;
    BT_UUID16_LIST *pNext;
};

struct BT_CHANNEL_LIST
{
    ULONG ulChannel;    
    BT_UUID16_LIST *pUUIDList;
    BT_CHANNEL_LIST *pNext;
};


//code stolen from btdc\sdptest.cxx & sdpsearch
static BOOL IsRfcommUuid(NodeData *pNode)  {
    if (pNode->type != SDP_TYPE_UUID)
        return FALSE;

    if (pNode->specificType == SDP_ST_UUID16)
        return (pNode->u.uuid16 == RFCOMM_PROTOCOL_UUID16);
    else if (pNode->specificType == SDP_ST_UUID32)
        return (pNode->u.uuid32 == RFCOMM_PROTOCOL_UUID16);
    else if (pNode->specificType == SDP_ST_UUID128)
        return (0 == memcmp(&RFCOMM_PROTOCOL_UUID,&pNode->u.uuid128,sizeof(GUID)));

    return FALSE;
}

static BOOL GetChannel (NodeData *pChannelNode, ULONG *pulChannel) {
    if (pChannelNode->specificType == SDP_ST_UINT8)
        *pulChannel = pChannelNode->u.uint8;
    else if (pChannelNode->specificType == SDP_ST_INT8)
        *pulChannel = pChannelNode->u.int8;
    else if (pChannelNode->specificType == SDP_ST_UINT16)
        *pulChannel = pChannelNode->u.uint16;
    else if (pChannelNode->specificType == SDP_ST_INT16)
        *pulChannel = pChannelNode->u.int16;
    else if (pChannelNode->specificType == SDP_ST_UINT32)
        *pulChannel = pChannelNode->u.uint32;
    else if (pChannelNode->specificType == SDP_ST_INT32)
        *pulChannel = pChannelNode->u.int32;
    else
        return FALSE; // misformatted response.

    return TRUE;
}

// Frees memory associated with one BT_CHANNEL_LIST entry; 
// does not adjust next pointers (caller does this)
static void DeleteBtChannelListNode(BT_CHANNEL_LIST *pChannel) {
    BT_UUID16_LIST *pList = pChannel->pUUIDList;

    while (pList) {
        BT_UUID16_LIST *pDelNode = pList;
        pList = pDelNode->pNext;
        delete pDelNode;        
    }

    delete pChannel;
}

static STDMETHODIMP
ServiceAndAttributeSearchParse(
    UCHAR *szResponse,             // in - response returned from SDP ServiceAttribute query
    DWORD cbResponse,            // in - length of response
    ISdpRecord ***pppSdpRecords, // out - array of pSdpRecords
    ULONG *pNumRecords           // out - number of elements in pSdpRecords
    )
{
    DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::ServiceAndAttributeSearchParse()\n"));    
    
    HRESULT hres = E_FAIL;

    *pppSdpRecords = NULL;
    *pNumRecords = 0;

    ISdpStream *pIStream = NULL;

    hres = CoCreateInstance(__uuidof(SdpStream),NULL,CLSCTX_INPROC_SERVER,
                            __uuidof(ISdpStream),(LPVOID *) &pIStream);

    if ((FAILED(hres)) || (!pIStream))
    {
        DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::ServiceAndAttributeSearchParse() -- CoCreate failed\n"));    
        return hres; 
    }

    hres = pIStream->Validate(szResponse,cbResponse,NULL);

    if (SUCCEEDED(hres)) {
        hres = pIStream->VerifySequenceOf(szResponse,cbResponse,
                                          SDP_TYPE_SEQUENCE,NULL,pNumRecords);

        if (SUCCEEDED(hres) && *pNumRecords > 0) {
            *pppSdpRecords = (ISdpRecord **) CoTaskMemAlloc(sizeof(ISdpRecord*) * (*pNumRecords));

            if (pppSdpRecords != NULL) {
                hres = pIStream->RetrieveRecords(szResponse,cbResponse,*pppSdpRecords,pNumRecords);

                if (!SUCCEEDED(hres)) {
                    CoTaskMemFree(*pppSdpRecords);
                    *pppSdpRecords = NULL;
                    *pNumRecords = 0;
                }
            }
            else {
                hres = E_OUTOFMEMORY;
            }
        }
    }

    if (pIStream != NULL) {
        pIStream->Release();
        pIStream = NULL;
    }

    if(FAILED(hres))
        DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::ServiceAndAttributeSearchParse() -- FAILED\n"));    
    
    return hres;
}

static HRESULT GetRFCOMMChannel(UCHAR *szBuf, DWORD cbResponse, BT_CHANNEL_LIST **pBTCList) {
    PREFAST_ASSERT(szBuf && pBTCList);
    DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::GetRFCOMMChannel()\n"));    
        
    ISdpRecord **pRecordArg;
    ISdpRecord *pRecord = NULL;
    ISdpStream *pIStream = NULL;

    BT_CHANNEL_LIST *pChannList = NULL;
    *pBTCList = pChannList;
    
    ULONG ulRecords = 0;
    ULONG i,j,k;
    ULONG  ulChannelId = 0;

    HRESULT hres = CoCreateInstance(__uuidof(SdpStream),NULL,CLSCTX_INPROC_SERVER,
                            __uuidof(ISdpStream),(LPVOID *) &pIStream);
    if ((FAILED(hres)) || (!pIStream))
    {
            DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::CoCreateInstance() FAILED\n"));
            return hres;
    }
   
    if (ERROR_SUCCESS != ServiceAndAttributeSearchParse(szBuf,cbResponse,&pRecordArg,&ulRecords))
        goto done;

    for (i = 0; i < ulRecords; i++) 
    {
        BOOL fHaveChannelID = FALSE;
        pRecord = pRecordArg[i];    // particular record to examine in this loop
        NodeData  protocolList;     // contains SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST data, if available
        NodeData  UUIDList;            // contains SD_
        BT_UUID16_LIST *pUUIDList = NULL;

        //
        //  Ask for the SDP attributes (CLASS list and PROTOCOL DESCRIPTOR LIST)
        //
        if (ERROR_SUCCESS != pRecord->GetAttribute(SDP_ATTRIB_CLASS_ID_LIST,&UUIDList) ||
            (UUIDList.type != SDP_TYPE_CONTAINER))
        {
            continue;
        }
        
        if (ERROR_SUCCESS != pRecord->GetAttribute(SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST,&protocolList) ||
            (protocolList.type != SDP_TYPE_CONTAINER))
        {
            continue;
        }

        //
        //  Go after the UUID(s) -- put them in a list
        //
        ISdpNodeContainer *pUUIDContainer = UUIDList.u.container;
        DWORD cUUIDs = 0;
        NodeData ndUUID;
        pUUIDContainer->GetNodeCount(&cUUIDs);
        

        for(j=0; j<cUUIDs; j++)
        {
            pUUIDContainer->GetNode(j,&ndUUID);
            
            BT_UUID16_LIST *pNew = new BT_UUID16_LIST();
            if( !pNew )
            {
                 //clean up UUID list 
                while(pUUIDList)
                {
                    BT_UUID16_LIST *pDel = pUUIDList;
                    pUUIDList = pUUIDList->pNext;
                    delete pDel;
                }

                 hres = E_OUTOFMEMORY;
                 goto done;
            }
            pNew->pNext = pUUIDList;
            pIStream->NormalizeUuid(&ndUUID, &pNew->uuid);
            pUUIDList = pNew;            
        }
        
        
        //
        //  Go after the channel
        //
        ISdpNodeContainer *pRecordContainer = protocolList.u.container;
        DWORD cProtocols = 0;
        NodeData protocolDescriptor; // information about a specific protocol (i.e. L2CAP, RFCOMM, ...)

        pRecordContainer->GetNodeCount(&cProtocols);
        for (j = 0; j < cProtocols; j++) 
        {
            pRecordContainer->GetNode(j,&protocolDescriptor);

            if (protocolDescriptor.type != SDP_TYPE_CONTAINER)
                continue;                

            ISdpNodeContainer *pProtocolContainer = protocolDescriptor.u.container;
            DWORD cProtocolAtoms = 0;
            pProtocolContainer->GetNodeCount(&cProtocolAtoms);

            for (k = 0; k < cProtocolAtoms; k++) 
            {
                NodeData nodeAtom;  // individual data element, such as what protocol this is or RFCOMM channel id.

                pProtocolContainer->GetNode(k,&nodeAtom);

                if (IsRfcommUuid(&nodeAtom))  
                {
                    if (k+1 == cProtocolAtoms) 
                    {
                        // misformatted response.  Channel ID should follow RFCOMM uuid
                        break;
                    }
                    NodeData channelID;
                    pProtocolContainer->GetNode(k+1,&channelID);

                    if (GetChannel(&channelID,&ulChannelId)) 
                    {
                        //see if there is an existing node with the same channelID
                        BT_CHANNEL_LIST *pTemp = pChannList;
                        while(pTemp && pTemp->ulChannel != ulChannelId)
                            pTemp = pTemp->pNext;

                        //if the channel doesnt exist, make a new one
                        if(!pTemp)
                        {
                            pTemp = new BT_CHANNEL_LIST();
                            if( !pTemp )
                            {
                                //clean up UUID list 
                                while(pUUIDList)
                                {
                                    BT_UUID16_LIST *pDel = pUUIDList;
                                    pUUIDList = pUUIDList->pNext;
                                    delete pDel;
                                }
                     
                                hres = E_OUTOFMEMORY;
                                goto done;
                            }

                            pTemp->ulChannel = ulChannelId;
                            pTemp->pNext = pChannList;
                            pTemp->pUUIDList = pUUIDList;
                            pChannList = pTemp;                            
                        }

                        //if it DOES exist, chain the UUID list onto the old node
                        else
                        {
                            BT_UUID16_LIST *pLastNode = pUUIDList;
                            while(pLastNode && pLastNode->pNext)
                                pLastNode = pLastNode->pNext;

                            if(pLastNode)
                            {
                                SVSUTIL_ASSERT(!pLastNode->pNext);

                                pLastNode->pNext = pTemp->pUUIDList;
                                pTemp->pUUIDList = pUUIDList;
                            }                        
                        }

                        fHaveChannelID = TRUE;
                        pUUIDList = NULL;
                    }
            
                    break; // formatting error
                }
            }
            if(fHaveChannelID)
                break;
        }

        //
        //  Cleanup the UUID list... NOTE: this means that we DIDNT get a channelID

⌨️ 快捷键说明

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