📄 obexbthtransport.cpp
字号:
//
// 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 + -