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

📄 sdptest.cxx

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CXX
📖 第 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.
//
/**
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.


Abstract:
	Windows CE Bluetooth application sample

**/

#if ! defined (UNDER_CE)
// Needed to get CoInitializeEx()
#define _WIN32_DCOM
#include <stdio.h>
#endif

#include <winsock2.h>
#include <windows.h>

#include <svsutil.hxx>

#include "bt_api.h"
#include "bt_sdp.h"
#include "bt_buffer.h"
#include "bt_ddi.h"
#include "btdc.h"
#include "bthapi.h"


#define BUFFER_SIZE 1500

// CE values
const CLSID CLSID_SdpRecord = {0xACD02BA7,0x9667,0x4085,{0xA1,0x00,0xCC,0x6A,0xCA,0x96,0x21,0xD6}};
const CLSID CLSID_SdpNodeContainer = {0xD5CA76C5,0x0DEE,0x4453,{0x96,0xA1,0xE6,0x03,0xC2,0x40,0x17,0x66}};

#define GUID_FORMAT     "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n"

#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]

BOOL CreateSdpRecord(WCHAR *szFile, UCHAR **ppStream, ULONG *pSize);


#define ADD_ENTRY()      if (pRecord) pRecord->SetAttribute(attribVal, &ndw); \
                         else pCont->AppendNode(&ndw);

#define MAX_HANDLES      50
#define MAX_ATTRIBUTES   50

#define SKIP_WHITESPACE(p)   while (*(p) && iswspace(*(p))) ++(p);



void PrintStream(PUCHAR Stream, ULONG Size)
{
    for (ULONG i = 0; i < Size; i++) {
        printf("%02x, ", (ULONG) Stream[i]);
    }
}

FILE *SdpOpenFile(WCHAR *szFileName) {
	FILE *pFile;
    pFile = _wfopen(szFileName, L"r");
	if (!pFile)
		wprintf(L"Cannot open file: %s\n",szFileName);
	return pFile;
}


#define SDP_RECORD_COMMENT_CHAR  ';'

void SdpReadString(FILE *pf, CHAR *buffer, int iSizeofBuffer) {
    int i;
    for (i = 0; i < iSizeofBuffer; i++)  {
        if (EOF == fscanf(pf, "%c", &buffer[i])) {
            buffer[i] = 0;
            break;
        }

        if (buffer[i] == '\r' || buffer[i] == '\n')  {
            if (buffer[i] == '\r')
                fscanf(pf, "%c", &buffer[i]);
            buffer[i] = 0;
            break;
        }
    }
}

// Handles comments in stream.
BOOL ParseHandleComment(FILE *pf, PSTR szBuffer, DWORD cbBuffer) {
    if (szBuffer[0] != SDP_RECORD_COMMENT_CHAR)
        return FALSE;
 
    int iLen = strlen(szBuffer);
    SdpReadString(pf,szBuffer+iLen,cbBuffer-iLen);

    return TRUE;
}

const BD_ADDR zeroAddr = {0};

void InitWSAQuerySet(WSAQUERYSET *pw, BT_ADDR *pba=NULL, CSADDR_INFO *pcsaBuffer=NULL, SOCKADDR_BTH *psockBT=NULL, LPBLOB pBlob=NULL)  {
	memset(pw,0,sizeof(WSAQUERYSET));
	pw->dwSize      = sizeof(WSAQUERYSET);
	pw->dwNameSpace = NS_BTH;
	pw->lpBlob      = pBlob;

	if (pba)  {
		pw->lpcsaBuffer = pcsaBuffer;
		
		memset(pcsaBuffer,0,sizeof(CSADDR_INFO));
		memset(psockBT,0,sizeof(SOCKADDR_BTH));
		memcpy(&psockBT->btAddr,pba,sizeof(BT_ADDR));
		pcsaBuffer->RemoteAddr.lpSockaddr       = (LPSOCKADDR) psockBT;
		pcsaBuffer->RemoteAddr.iSockaddrLength  = sizeof(SOCKADDR_BTH);
	}
}

BOOL ReadUUIDs(FILE *pFile, SdpQueryUuid* pUUIDs, unsigned short *pcUUIDs, BOOL fEOF)  {
	char           buffer[2048];
	int            i;
	GUID           guid[2];
	*pcUUIDs = 0;

	while (EOF != fscanf(pFile, "%s", buffer))  {
        if (ParseHandleComment(pFile,buffer,sizeof(buffer)))
            continue;

		// When we read in GUIDS + Attrib (fEOF=FALSE) then stop reading GUID at "END"
		if (!fEOF && (_stricmp(buffer,"END") == 0))  {
			if (0 == *pcUUIDs) {
				wprintf(L"Syntax: No UUIDS specified\n");
				return FALSE;
			}
			return TRUE;
		}
		if (*pcUUIDs == MAX_UUIDS_IN_QUERY) {
			wprintf(L"Cannot have > %d UUIDs in ServiceSearch\n",MAX_UUIDS_IN_QUERY);
			return FALSE;
		}

		if (_stricmp(buffer,"UUID16") == 0)  {
			fscanf(pFile, "%x\n", &i);
			pUUIDs[*pcUUIDs].u.uuid16 = (unsigned short) i;
			pUUIDs[*pcUUIDs].uuidType = SDP_ST_UUID16;
		}
		else if (_stricmp(buffer,"UUID32") == 0) {
			fscanf(pFile, "%x\n", &i);
			pUUIDs[*pcUUIDs].u.uuid32 = i;
			pUUIDs[*pcUUIDs].uuidType = SDP_ST_UUID32;
		}
		else if (_stricmp(buffer,"UUID128") == 0) {
			memset(&guid,0,sizeof(guid));
			fscanf(pFile,GUID_FORMAT,GUID_ELEMENTS((&guid[0])));
			pUUIDs[*pcUUIDs].uuidType = SDP_ST_UUID128;
			memcpy(&pUUIDs[*pcUUIDs].u.uuid128,&guid[0],sizeof(guid[0]));
		}
		else {
			wprintf(L"GUID must be prefaced by UUID16, UUID32, or UUID128\n");
			return FALSE;
		}
		*pcUUIDs += 1;
	}

	if (0 == *pcUUIDs) {
		wprintf(L"Syntax: No UUIDS specified\n");
		return FALSE;
	}
	return TRUE;
}

BOOL ReadAttributes(FILE *pFile, unsigned long *pulHandle, SdpAttributeRange *pRange, unsigned long *pcAttributes)  {
	CHAR buffer[2048];

	*pcAttributes = 0;

	if (pulHandle)  {
		do {
			if (EOF == fscanf(pFile,"%s",buffer)) {
				wprintf(L"syntax: Handle syntax in file\r\n");
				return FALSE;
			}
			if (ParseHandleComment(pFile,buffer,sizeof(buffer)))
				continue;

			if (! sscanf(buffer,"%x",pulHandle)) {
				wprintf(L"syntax: Handle syntax in file\r\n");
				return FALSE;
			}
			break;
		} while(1);
	}

	while (EOF != fscanf(pFile,"%s",buffer))  {
        if (ParseHandleComment(pFile,buffer,sizeof(buffer)))
            continue;

		if (! sscanf(buffer,"%x",(unsigned long*)&pRange[*pcAttributes].minAttribute)) {
			wprintf(L"syntax: Min Attrib ID syntax, element #=%d\r\n",*pcAttributes);
			return FALSE;
		}

		if (EOF == fscanf(pFile,"%s",buffer)) {
			wprintf(L"syntax: Max Attrib ID syntax, element #=%d\r\n",*pcAttributes);
			return FALSE;
		}
		
		if (! sscanf(buffer,"%x",(unsigned long*)&pRange[*pcAttributes].maxAttribute)) {
			wprintf(L"syntax: Max Attrib ID syntax, element #=%d\r\n",*pcAttributes);
			return FALSE;
		}

		*pcAttributes = *pcAttributes+1;
	}
	return TRUE;
}


/************************************************************
void TestSdpInquiry(void)
   Performs a device inquiry using the exposed BTH NS Api.

************************************************************/
void TestSdpInquiry(WCHAR *szCmd) {
	WSAQUERYSET         wsaQuery;
	DWORD dwGetNextFlags = LUP_RETURN_ADDR;

	if (0 == wcsnicmp(szCmd,L"-name ",6)) {
		szCmd += 6;
		dwGetNextFlags |= LUP_RETURN_NAME;
	}
	if (0 == wcsnicmp(szCmd,L"-blob",5)) {
		dwGetNextFlags |= LUP_RETURN_BLOB;
	}

	DWORD dwFlags = LUP_CONTAINERS;
	
	InitWSAQuerySet(&wsaQuery);
	BTHNS_INQUIRYBLOB inquiryRestrictions;
#define INQUIRY_GIAC_LAP               0x9e8b33  // unlimited inquiry access mode (GIAC)
	inquiryRestrictions.LAP = INQUIRY_GIAC_LAP;
	inquiryRestrictions.length = 5;
	inquiryRestrictions.num_responses = 3;

	BLOB blob;
	blob.cbSize = sizeof (inquiryRestrictions);
	blob.pBlobData = (BYTE*) &inquiryRestrictions;
	wsaQuery.lpBlob = &blob;

	HANDLE hLookup;
	SetLastError(0);
	int iRet = BthNsLookupServiceBegin(&wsaQuery,dwFlags,&hLookup);
	wprintf(L"BthNsLookupServiceBegin returned 0x%08x,GLE=0x%08x\r\n",iRet,GetLastError());
	if (ERROR_SUCCESS != iRet) {
		return;
	}

	union {
		CHAR szBuf[BUFFER_SIZE];
		SOCKADDR_BTH	__unused;	// properly align buffer to BT_ADDR requirements
	};

	LPWSAQUERYSET pResults = (LPWSAQUERYSET) szBuf;
	DWORD dwLen = sizeof(szBuf);
	DWORD i = 0; 

#if defined (UNDER_CE)
	SetLastError(0);
	while (ERROR_SUCCESS == (iRet = BthNsLookupServiceNext(hLookup,dwGetNextFlags,&dwLen,pResults))) {
		WCHAR *szName;
		PSOCKADDR_BTH pSockAddr;
		BT_ADDR *pba;

		if (! (dwGetNextFlags & LUP_RETURN_NAME)) {
			szName = NULL;
		}
		else {
			szName = pResults->lpszServiceInstanceName;
		}
		pSockAddr = (PSOCKADDR_BTH) pResults->lpcsaBuffer->RemoteAddr.lpSockaddr;
		pba = (BT_ADDR*)&pSockAddr->btAddr;
		
		wprintf(L"BthNsLookupServiceNext (i=%d, retVal=0x%08x) name = %s, pba=%04x%08x\r\n",i,iRet,szName ? szName : L"",GET_NAP((*pba)), GET_SAP((*pba)));
		if (dwGetNextFlags & LUP_RETURN_BLOB) {
			BthInquiryResult *pInquiry = (BthInquiryResult *) pResults->lpBlob->pBlobData;
			if (GET_NAP((pInquiry->ba)) != GET_NAP((*pba)) || 
			    GET_SAP((pInquiry->ba)) != GET_SAP((*pba)) || pResults->lpBlob->cbSize != sizeof(BthInquiryResult)) {
				ASSERT(0);  // if these don't match up then it's a bug.
      		}
			wprintf(L"-->cod=0x%08x,clkofst=0x%04x,PgScanMode=0x%02x,PgScanPeriodMode=0x%02x,PgScanRepMode=0x%02x\r\n",pInquiry->cod,pInquiry->clock_offset,pInquiry->page_scan_mode,pInquiry->page_scan_period_mode, pInquiry->page_scan_repetition_mode);
		}
		dwLen = sizeof(szBuf);
		i++;
	}
	wprintf(L"Final BthNsLookupServiceNext returns 0x%08x,GLE=0x%08x\r\n",iRet,GetLastError());
#endif // UNDER_CE

	SetLastError(0);
	iRet = BthNsLookupServiceEnd(hLookup);
	wprintf(L"BthNsLookupServiceEnd returned 0x%08x,GLE=0x%08x\r\n",iRet,GetLastError());
}


/************************************************************
 TestSdpAddRecord
 
 File format is [ATTRIB Id] [Data Type] [Data]
 Only required AttribID is 1, Seq of UUIDs
 All AttribIDs and numeric values are in hexidecimal.
 Example file: 
 
1    SEQUENCE
     UUID16 FFF
     UUID16 3000
     UUID32 4000000
     END
999 UUID128 12345678-ABCD-AF12-8800-12345678EF12
1001 UINT8 10
1002 UINT16 100
1003 UINT32 40000000
1004 UINT64 4000000000000
1005 UINT128 100 1000
1006 INT8 -10
1007 INT16 -100
1008 INT32 -40000000
1009 INT64 -4000000000000
1010 INT128 -100 1000
1011 UUID16 100
1012 UUID32 40000000
1014 BOOLEAN 1
1015 BOOLEAN 0
1016 STRING Where do you want to go today?
1017 URL http://www.microsoft.com/
1018 Nil
************************************************************/
void TestSdpAddRecord(WCHAR *szCmd) {
	UCHAR *pStream  = NULL;
	ULONG  ulSize   = 0;
	WSAQUERYSET Service;
	CHAR buf[BUFFER_SIZE];
	BLOB blob;
	PBTHNS_SETBLOB addBlob = (PBTHNS_SETBLOB) buf;
	ULONG recordHandle = 0;
	ULONG ulSdpVersion = BTH_SDP_VERSION;

	if (! CreateSdpRecord(szCmd,&pStream,&ulSize))
		return;

	memset(&Service,0,sizeof(Service));
	blob.cbSize    = sizeof(BTHNS_SETBLOB) + ulSize - 1;
	blob.pBlobData = (PBYTE) addBlob;

	addBlob->pRecordHandle  = &recordHandle;
    addBlob->pSdpVersion    = &ulSdpVersion;
	addBlob->fSecurity      = 0;
	addBlob->fOptions       = 0;
	addBlob->ulRecordLength = ulSize;
	memcpy(addBlob->pRecord,pStream,ulSize);
	
	Service.dwSize = sizeof(Service);
	Service.lpBlob = &blob;
	Service.dwNameSpace = NS_BTH;

	SetLastError(0);
	int iErr = BthNsSetService(&Service,RNRSERVICE_REGISTER,0);
	wprintf(L"BthNsSetService returns 0x%08x, record handle = 0x%08x,GLE=0x%08x\r\n",iErr,recordHandle,GetLastError());
}

void TestSdpDelRecord(WCHAR *szCmd) {
	BLOB blob;
	BTHNS_SETBLOB delBlob;
	unsigned long hRec;
	ULONG ulSdpVersion = BTH_SDP_VERSION;
	WSAQUERYSET Service;
	
	if (!GetUI(&szCmd,&hRec))  {
		wprintf(L"Syntax: handle\n");
		return;
	}

	blob.cbSize    = sizeof(BTHNS_SETBLOB);
	blob.pBlobData = (PBYTE) &delBlob;

	memset(&delBlob,0,sizeof(delBlob));
	delBlob.pRecordHandle = &hRec;
    delBlob.pSdpVersion   = &ulSdpVersion;

	memset(&Service,0,sizeof(Service));
	Service.dwSize = sizeof(Service);
	Service.lpBlob = &blob;
	Service.dwNameSpace = NS_BTH;

	SetLastError(0);
	int iErr = BthNsSetService(&Service,RNRSERVICE_DELETE,0);
	wprintf(L"BthNsSetService returns 0x%08x,GLE=0x%08x\r\n",iErr,GetLastError());
}


/************************************************************
TestSdpServiceSearch

 File format is [Data Type] [Guid]  Data Type must be UUID16, UUID32, or UUID128
 Must be at least 1 entry, no more than 12.
 All entries are in hex.
 Example file: 
 
UUID16 FFF
UUID32 4000000
************************************************************/
void TestSdpServiceSearch(WCHAR *szCmd) {
	FILE           *pFile;
	SdpQueryUuid   UUIDs[MAX_UUIDS_IN_QUERY];
	unsigned short cUUIDs;
	unsigned short cMaxHandles = MAX_HANDLES;
	BT_ADDR        bt;
	DWORD          dwFlags = 0;

	// Read Input
	SKIP_WHITESPACE(szCmd);
	if (! GetBA(&szCmd, &bt)) {
		wprintf (L"Syntax: bd_addr\n");
		return;
	}

⌨️ 快捷键说明

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