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

📄 sdpcommon.cpp

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// SdpCommon.cpp: Commonly used functions...


#include <windows.h>
#include <bthapi.h>
#include <bt_sdp.h>
#include <svsutil.hxx>
#include "..\sdpcommon\sdpcommon.h"

#if defined (WINCE_EMULATION)
#include <assert.h>
#else
#define assert ASSERT
#endif


inline USHORT RtlUshortByteSwap(IN USHORT Source) {
    USHORT swapped;
    swapped = ((Source) << (8 * 1)) | ((Source) >> (8 * 1));
    return swapped;
}

inline ULONG RtlUlongByteSwap(IN ULONG Source) {
	ULONG swapped;

	swapped = ((Source)              << (8 * 3)) |  ((Source & 0x0000FF00) << (8 * 1)) |
	          ((Source & 0x00FF0000) >> (8 * 1)) |  ((Source)              >> (8 * 3));

	return swapped;
}

inline ULONGLONG RtlByteSwap64(ULONGLONG Source) {
	ULONGLONG swapped;
	
	swapped = (ULONGLONG) (RtlUlongByteSwap((ULONG)(Source >> 32))) << 32;
	swapped = swapped | (RtlUlongByteSwap((ULONG)(Source & 0x00000000FFFFFFFF)));
	return swapped;
}

ISdpStream * AllocateSdpStream(void);
void FreeSdpStream(ISdpStream *pStream);


ISdpRecord *CreateSDPRecordFromStream(UCHAR *szResponse, DWORD cbResponse) {
	ISdpRecord *pIRecord = NULL;

	if (FAILED(CoCreateInstance(__uuidof(SdpRecord),NULL,CLSCTX_INPROC_SERVER,
	                        __uuidof(ISdpRecord),(LPVOID *) &pIRecord))) {
		return NULL;
	}

	if (FAILED(pIRecord->CreateFromStream(szResponse,cbResponse))) {
		pIRecord->Release();
		return NULL;
	}
	return pIRecord;
}

// 
// Takes a raw stream ServiceAttribute response from the server and converts 
// it into an array of ISdpRecord elements to facilitate manipulation.
// 
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
    )
{
    HRESULT hres = E_FAIL;

    *pppSdpRecords = NULL;
    *pNumRecords = 0;

    ISdpStream *pIStream = NULL;

    if (NULL == (pIStream = AllocateSdpStream()))
    	return E_FAIL;

    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) {
        FreeSdpStream(pIStream);
        pIStream = NULL;
    }

	return hres;
}

//
//  Routines related to parsing an SDP format into human readable form.
//


const WCHAR *attribIdTable[] = {
	L"Record Handle",
	L"Class ID List",
	L"Record State",
	L"Service ID",
	L"Protocol Descriptor List",
	L"Browse Group List",
	L"Language Base",
	L"Service Info Time To Live",
	L"Service Availability",
	L"Bluetooth Profile Descriptor List",
	L"Document URL",
	L"Client Executable URL",
	L"Icon URL"
};

static const WCHAR *cszUnknownAttrib = L"Unknown Attribute";
static const WCHAR *cszMaxAttribID   = L"Maximum Attribute Value";

const WCHAR *GetAttribFromID(USHORT usAttribId) {
	if (usAttribId == 0xFFFF)
		return cszMaxAttribID;

	if (usAttribId > SDP_ATTRIB_ICON_URL)
		return cszUnknownAttrib;

	return attribIdTable[usAttribId];
}

// 
// Functions to process attribute IDs
// 

void PrintMisformatted(PFN_SDPPRINT pfnPrint, PVOID pvContext) {
	pfnPrint(pvContext,TRUE,L"Entry is misformatted\n");
}

typedef void (*PFN_SDPPRINT_ATTRIB)(UCHAR *pStream, ULONG size, PFN_SDPPRINT pfnPrint, PVOID pvContext);

// Given a stream, creates an ISdpStream element and verifies.
BOOL LoadAndValidate(ISdpStream **ppSdpStream, UCHAR **ppStream, ULONG *pSize, BOOL fVerifyIsSequence) {
	*ppSdpStream = AllocateSdpStream();
	ULONG_PTR sdpError;
	int iIndex = 0;

	SDP_TYPE type = SDP_TYPE_NIL;
	SDP_SPECIFICTYPE specType;
	ULONG storageSize;

	if (!(*ppSdpStream))
		return FALSE;

	if (FAILED((*ppSdpStream)->Validate(*ppStream,*pSize,&sdpError)))
		return FALSE;

	if (fVerifyIsSequence) {
		(*ppSdpStream)->RetrieveElementInfo(*ppStream,&type,&specType,pSize,&storageSize,ppStream);

		if (type != SDP_TYPE_SEQUENCE)
			return FALSE;
	}
	return TRUE;
}

BOOL GetIntFromStream(ISdpStream *pSdpStream, UCHAR *pStream, ULONG size, ULONG *pulVal) {
	SDP_TYPE type;
	SDP_SPECIFICTYPE specType = SDP_ST_NONE;
	ULONG storageSize;
	ULONG recordSize;

	pSdpStream->RetrieveElementInfo(pStream,&type,&specType,&recordSize,&storageSize,&pStream);
	if (specType != SDP_ST_UINT32)
		return FALSE;

	pSdpStream->RetrieveUint32(pStream,pulVal);
	*pulVal = RtlUlongByteSwap(*pulVal);
	return TRUE;
}

void SdpPrintAttribRecordHandle(UCHAR *pStream, ULONG size, PFN_SDPPRINT pfnPrint, PVOID pvContext) {
	ISdpStream *pSdpStream = NULL;
	int iIndex = 0;

	ULONG recordHandle;

	if (! LoadAndValidate(&pSdpStream,&pStream,&size,FALSE)) {
		pfnPrint(pvContext,TRUE,L"Attribute Record misformatted\n");
		goto done;
	}

	if ( ! GetIntFromStream(pSdpStream,pStream,size,&recordHandle)) {
		pfnPrint(pvContext,TRUE,L"  Element is not a UINT32\n");
		goto done;
	}

	pfnPrint(pvContext,FALSE,L"  Record Handle = 0x%08x\n",recordHandle);
done:
	if (pSdpStream)
		FreeSdpStream(pSdpStream);
}


#define MIN_PROTOCOL_UUID16	      SDP_PROTOCOL_UUID16
#define MAX_PROTOCOL_UUID16	      WSP_PROTOCOL_UUID16

const WCHAR cszUnknownUUID[] = L"Unknown UUID";


const WCHAR *g_rgszProtocolUUIDs[] = {
	L"SDP",
	L"UDP",
	L"RFCOMM",
	L"TCP",
	L"TCSBIN",
	L"TCSAT",
	cszUnknownUUID,
	L"OBEX",
	L"IP",
	L"FTP",
	cszUnknownUUID,
	L"HTTP",
	cszUnknownUUID,
	L"WSP"
};
const WCHAR g_szL2CAPProtUUID[] = L"L2CAP";


const WCHAR g_szServiceDiscovery[]     = L"Service Discovery Server";
const WCHAR g_szBrowseGroup[]          = L"Browse Group Descriptor";
const WCHAR g_szPublicBrowseGroup[]    = L"Public Browse Group";
const WCHAR g_szSerialPort[]           = L"Serial Port";
const WCHAR g_szLanAccess[]            = L"LAN Access using PPP";
const WCHAR g_szDialupNetworkService[] = L"Dialup Networking Service";
const WCHAR g_szIRMC[]                 = L"IR MC Sync";
const WCHAR g_szObexPush[]             = L"Obex Push";
const WCHAR g_szObexFile[]             = L"Obex File Transfer";
const WCHAR g_szIRMCSync[]             = L"IR MC Sync Command";
const WCHAR g_szHeadset[]              = L"Headset";
const WCHAR g_szCordlessTelephone[]    = L"Cordless Telephone";
const WCHAR g_szIntercomn[]            = L"Intercom";
const WCHAR g_szFax[]                  = L"Fax";
const WCHAR g_szHeadsetAudioGateway[]  = L"Headset Audio Gateway";

const WCHAR g_szPNP[]                  = L"PnP Information";
const WCHAR g_szGNetworking[]          = L"Generic Networking";
const WCHAR g_szGFileTransfer[]        = L"Generic File Transfer";
const WCHAR g_szGAudio[]               = L"Generic Audio";
const WCHAR g_szGTelephone[]           = L"Generic Telephony";


const WCHAR * GetUUIDString(ULONG ulGUID) {
	if (ulGUID == L2CAP_PROTOCOL_UUID16)
		return g_szL2CAPProtUUID;

	if ((ulGUID >= MIN_PROTOCOL_UUID16) && (ulGUID <= MAX_PROTOCOL_UUID16))
		return g_rgszProtocolUUIDs[ulGUID-MIN_PROTOCOL_UUID16];

	switch (ulGUID) {
	case ServiceDiscoveryServerServiceClassID_UUID16:
		return g_szServiceDiscovery ;
		break;
		
	case BrowseGroupDescriptorServiceClassID_UUID16:
		return g_szBrowseGroup ;
		break;

	case PublicBrowseGroupServiceClassID_UUID16:
		return g_szPublicBrowseGroup ;
		break;

	case SerialPortServiceClassID_UUID16:
		return g_szSerialPort ;
		break;

	case LANAccessUsingPPPServiceClassID_UUID16:
		return g_szLanAccess;
		break;

	case DialupNetworkingServiceClassID_UUID16:
		return g_szDialupNetworkService;
		break;

	case IrMCSyncServiceClassID_UUID16:
		return g_szIRMC;
		break;

	case OBEXObjectPushServiceClassID_UUID16:
		return g_szObexPush;
		break;

	case OBEXFileTransferServiceClassID_UUID16:
		return g_szObexFile ;
		break;

	case IrMcSyncCommandServiceClassID_UUID16:
		return g_szIRMCSync ;
		break;

	case HeadsetServiceClassID_UUID16:
		return g_szHeadset;
		break;

	case CordlessServiceClassID_UUID16:
		return g_szCordlessTelephone ;
		break;

	case IntercomServiceClassID_UUID16:
		return g_szIntercomn;
		break;

	case FaxServiceClassID_UUID16:
		return g_szFax ;
		break;

	case HeadsetAudioGatewayServiceClassID_UUID16:
		return g_szHeadsetAudioGateway ;
		break;

	case PnPInformationServiceClassID_UUID16:
		return g_szPNP;
		break;

	case GenericNetworkingServiceClassID_UUID16:
		return g_szGNetworking;
		break;

	case GenericFileTransferServiceClassID_UUID16:
		return g_szGFileTransfer;
		break;

	case GenericAudioServiceClassID_UUID16:
		return g_szGAudio;
		break;

	case GenericTelephonyServiceClassID_UUID16:
		return g_szGTelephone;
		break;

		default:
			break;
	}

	return cszUnknownUUID;
}

void SdpByteSwapUuid128(GUID *uuid128From, GUID *uuid128To)
{
    uuid128To->Data1 = RtlUlongByteSwap(uuid128From->Data1);
    uuid128To->Data2 = RtlUshortByteSwap(uuid128From->Data2);
    uuid128To->Data3 = RtlUshortByteSwap(uuid128From->Data3);
    memcpy(uuid128To->Data4, uuid128From->Data4, sizeof(uuid128From->Data4)); 
}

// Looks up UUID in a stream, returns one of #define xxx_UUID16 values in bt_sdp.h on success,
// otherwise will return 0
ULONG FindUUIDType(SDP_SPECIFICTYPE specType, ISdpStream *pSdpStream, PUCHAR uuidRecord) {
	ULONG ulGUID;

	// 
	switch (specType) {
		case SDP_ST_UUID128:
		{
			GUID uuid;
			pSdpStream->RetrieveUuid128(uuidRecord,&uuid);
			SdpByteSwapUuid128(&uuid,&uuid);
			ulGUID = uuid.Data1; // don't do byte swap, SdpByteSwapUuid128 did it already for us.

			// Make sure that the base of this is same as base BT UUID.  If not we don't know what it is.
			uuid.Data1 = 0;
			if (0 != memcmp(&uuid,&Bluetooth_Base_UUID,sizeof(GUID))) {
				return 0;
			}
		}
		break;

		case SDP_ST_UUID32:
		{
			pSdpStream->RetrieveUint32(uuidRecord,&ulGUID);
			ulGUID = RtlUlongByteSwap(ulGUID);
		}
		break;

		case SDP_ST_UUID16:
		{

⌨️ 快捷键说明

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