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

📄 sdpns.cxx

📁 三星2440原版bsp
💻 CXX
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
//------------------------------------------------------------------------------
// 
//      Bluetooth SDP Name Space Layer
// 
// 
// Module Name:
// 
//      sdpns.cxx
// 
// Abstract:
// 
//      This file implements SDP Name Space handling and inquiry.
// 
// 
//------------------------------------------------------------------------------



#include "common.h"
#include <winsock2.h>
#include <svsutil.hxx>
#include <bt_debug.h>

// declarations and global data
static int bthns_ServiceSearch_Out(void *pCallContext, unsigned long status, unsigned short cReturnedHandles, unsigned long *pHandles);
static int bthns_AttributeSearch_Out(void *pCallContext, unsigned long status, unsigned char *pOutBuf, unsigned long cOutBuf);
static int bthns_ServiceAttributeSearch_Out(void *pCallContext, unsigned long status, unsigned char *pOutBuf, unsigned long cOutBuf);
static int bthns_StackEvent(void *pUserContext, int iEvent, void *pEventContext);
static int bthns_Connect_Out(void *pCallContext, unsigned long status, unsigned short cid);
static int bthns_Disconnect_Out(void *pCallContext, unsigned long status);


// On searching, number of milliseconds to wait for a response before canceling search.
#define  SPD_SEARCH_DEFAULT_TIMEOUT           30000
static DWORD         g_dwSearchTimeout;
static const TCHAR   g_szSDPBaseKey[] = TEXT("Software\\Microsoft\\Bluetooth\\SDP");
static const TCHAR   g_szTimeoutVal[] = TEXT("SearchTimeOut");

struct Call {
	Call          *pNext;
	HANDLE        hEvent;

	// Return values to SDP calls.  Note: Call does NOT free buffers
	int	           iResult;
	unsigned short cid;
	unsigned char  *pClientBuf;       // client output buffer
	unsigned long  cClientBuf;        // sizeof client output buffer.
};

#define INQUIRY_PENDING		1
#define INQUIRY_INPROGRESS	2
#define INQUIRY_COMPLETED	3

struct BthNsHandle {
	// BthNsHandle internals
	BthNsHandle      *pNext;
	Call           *pCall;

	// BthNsHandle's initial values.
	DWORD                  dwFlags;
	PBTHNS_RESTRICTIONBLOB   pResBlob;
	BD_ADDR                b;

	// ServiceClassId and Range are only used when lpServiceClassId != NULL and no RestrcitionBlob set in WSALookupServiceBegin()
	GUID                   ServiceClassId;

	unsigned int           fLocal             : 1; // search to be done on local device
	unsigned int           fNetSearchComplete : 1; // has search been sent across the wire
	unsigned int           fNoMoreData        : 1; // when all data has been sent up to Winsock level.
	unsigned int           fXPCompatMode      : 1; // TRUE if we use XP bluetooth data structures, FALSE if we use legacy WinCE structs.
	unsigned int           fInquiryStatus     : 2; // PENDING/INPROGRESS/DONE
	unsigned char          *pClientBuf;            // client output buffer
	unsigned long          cClientBuf;             // sizeof client output buffer.

	unsigned long          LAP;
	unsigned int           cDuration;
	unsigned int           cMaxResp;

	// results from a device inquiry.
	BthInquiryResult       *pInquiryResults;
	unsigned int           cDevices;
	unsigned int           iDeviceIterator; // when iterating through device list in BthNsLookupServiceNext
};

enum BTHNS_STAGE {
	JustCreated			= 0,
	Initializing,
	Running,
	ShuttingDown
};

class BthNs : public SVSSynch, public SVSRefObj {
public:
	FixedMemDescr	       *pfmdBthNsHandles;
	FixedMemDescr	       *pfmdNSCAlls;
	
	BthNsHandle              *pBthNsHandles;
	Call                   *pCalls;
	

	SDP_INTERFACE          sdp_if;
	HANDLE                 hSDP;
	BTHNS_STAGE            eStage;

	void ReInit(void) {
		pfmdBthNsHandles = NULL;
		pfmdNSCAlls   = NULL;
		pBthNsHandles    = NULL;
		pCalls         = NULL;

		hSDP      = NULL;
		memset(&sdp_if,0,sizeof(sdp_if));

		eStage   = JustCreated;
	}

	BthNs(void) {
		ReInit();
	}
};

BthNs *gpBthNS = NULL;


static BOOL DeleteBthNsHandle(BthNsHandle *pBthNsHandle)  {
	SVSUTIL_ASSERT(gpBthNS->IsLocked());

	BOOL fRet = TRUE;
	
	if (pBthNsHandle == gpBthNS->pBthNsHandles)
		gpBthNS->pBthNsHandles = pBthNsHandle->pNext;
	else {
		BthNsHandle *pParent = gpBthNS->pBthNsHandles;
		while (pParent && (pParent->pNext != pBthNsHandle))
			pParent = pParent->pNext;

		if (pParent)
			pParent->pNext = pBthNsHandle->pNext;
		else
			fRet = FALSE;
	}

	if (fRet) {
		if (pBthNsHandle->pClientBuf)
			ExFreePool(pBthNsHandle->pClientBuf);

		if (pBthNsHandle->pResBlob)
			g_funcFree(pBthNsHandle->pResBlob,g_pvAllocData);

		if (pBthNsHandle->pInquiryResults)
			g_funcFree(pBthNsHandle->pInquiryResults,g_pvAllocData);

		svsutil_FreeFixed(pBthNsHandle, gpBthNS->pfmdBthNsHandles);
	}
	return fRet;
}

static void DeleteCall(Call *pCall) {
	BOOL fFound = TRUE;

	if (pCall == gpBthNS->pCalls)
		gpBthNS->pCalls = pCall->pNext;
	else {
		Call *pParent = gpBthNS->pCalls;
		while (pParent && (pParent->pNext != pCall))
			pParent = pParent->pNext;

		if (pParent)
			pParent->pNext = pCall->pNext;
		else
			fFound = FALSE;
	}

	if (fFound) {
		CloseHandle(pCall->hEvent);
		if (pCall->pClientBuf)
			g_funcFree(pCall->pClientBuf,g_pvAllocData);

		svsutil_FreeFixed(pCall, gpBthNS->pfmdNSCAlls);
	}
}

static BOOL ConvertStringToBdAddr(WCHAR *szAddress, BD_ADDR *pb) {
	DWORD          i;
	LPWSTR         p = szAddress;
	
	for (i=0; i<6 && *p; i++) {
		if (i==0 && *p==L'(') {
			p++;
		}
		
		while (*p && ((*p>=L'0' && *p<=L'9') ||
		      (*p>=L'a' && *p<=L'f') ||
		      (*p>=L'A' && *p<=L'F')))
		{
			((PUCHAR)pb)[5-i] *= 16;

			if (*p>=L'0' && *p<=L'9') {
				((PUCHAR)pb)[5-i] += *p - L'0';
			} 
			else if (*p>=L'a' && *p<=L'f') {
				((PUCHAR)pb)[5-i] += *p + 10 - L'a';
			}
			else {
				((PUCHAR)pb)[5-i] += *p + 10 - L'A';
			}
			p++;
		}

		if (*p==L'(') {
			// This can occur at the start of the string
			// But we're not at the start
			return FALSE;
		} 
		else if (*p==L')') {
			// This can occur at the end only
			if (i<5) {
				return FALSE;
			}
			p++;
		} 
		else if (*p==L'.' || *p==L':') {
			p++;
		} 
		else if (!*p) {
			if (i<5) {
				return FALSE;
			}
		} 
		else {
			return WSAEINVAL;
		}
	}
	return TRUE;
}

static BthNsHandle * AllocBthNsHandle(LPWSAQUERYSET pQuerySet, DWORD dwFlags, int *piError)  {
	SVSUTIL_ASSERT(gpBthNS->IsLocked());
	PBTHNS_RESTRICTIONBLOB pResBlob = (PBTHNS_RESTRICTIONBLOB) ( pQuerySet->lpBlob ? pQuerySet->lpBlob->pBlobData : NULL);
	BOOL fSucces = FALSE;

	BthNsHandle *pBthNsHandle = (BthNsHandle *)svsutil_GetFixed(gpBthNS->pfmdBthNsHandles);
	if (!pBthNsHandle)
		goto done;

	memset(pBthNsHandle,0,sizeof(*pBthNsHandle));


	pBthNsHandle->dwFlags = dwFlags;

	// Get the remote address
	if (dwFlags & LUP_RES_SERVICE) {
		pBthNsHandle->fLocal = TRUE;
	} 
	else if (! (dwFlags & LUP_CONTAINERS)) {
		if (pQuerySet->lpcsaBuffer) {
			// Legacy CE mode, in which lpcsaBuffer is passed.
			SOCKADDR_BTH *pSockBT = (SOCKADDR_BTH *) pQuerySet->lpcsaBuffer->RemoteAddr.lpSockaddr;
#if defined (DEBUG) || defined (_DEBUG)
			if (! __SDP_IS_ALIGNED(pSockBT, 8))
				DebugOut(DEBUG_SDP_TRACE, L"SDP: Unaligned remote address in structure - FIX THE APP!\n");
#endif
			memcpy(&pBthNsHandle->b,(void *)&pSockBT->btAddr,sizeof(pBthNsHandle->b));
		}
		else {	
			// On Windows XP, address is passed as a readable string in lpszContext.  Implement for compat.
			if (! ConvertStringToBdAddr(pQuerySet->lpszContext,&pBthNsHandle->b))
				goto done;

			pBthNsHandle->fXPCompatMode = TRUE;
		}
	}

	// figure out what to query on remote device
	if (! (dwFlags & LUP_CONTAINERS)) {
		if (pResBlob) {
			if (NULL == (pBthNsHandle->pResBlob = (PBTHNS_RESTRICTIONBLOB) g_funcAlloc(pQuerySet->lpBlob->cbSize,g_pvAllocData))) 
				goto done;

			memcpy(pBthNsHandle->pResBlob,pResBlob,pQuerySet->lpBlob->cbSize);
		}
		else {
			memcpy(&pBthNsHandle->ServiceClassId,pQuerySet->lpServiceClassId,sizeof(GUID));
		}
	}

	pBthNsHandle->pNext    = gpBthNS->pBthNsHandles;
	gpBthNS->pBthNsHandles = pBthNsHandle;
	fSucces              = TRUE;
done:
	if (!fSucces) {
		if (pBthNsHandle) {
			SVSUTIL_ASSERT(pBthNsHandle != gpBthNS->pBthNsHandles);
			SVSUTIL_ASSERT(!pBthNsHandle->pResBlob);

			svsutil_FreeFixed(pBthNsHandle, gpBthNS->pfmdBthNsHandles);
			pBthNsHandle = NULL;
			*piError = WSAEINVAL;
		}
		else
			*piError = WSA_NOT_ENOUGH_MEMORY;
	}

	return pBthNsHandle;
}

static Call * AllocCall(BthNsHandle *pBthNsHandle) {
	SVSUTIL_ASSERT(gpBthNS->IsLocked());

	Call *pCall = (Call *)svsutil_GetFixed(gpBthNS->pfmdNSCAlls);
	if (!pCall)
		return NULL;

	memset(pCall,0,sizeof(*pCall));

	if (NULL == (pCall->hEvent = CreateEvent(NULL,FALSE,FALSE,NULL))) {
		svsutil_FreeFixed(pCall, gpBthNS->pfmdNSCAlls);
	}

	pCall->pNext      = gpBthNS->pCalls;
	gpBthNS->pCalls   = pCall;
	pBthNsHandle->pCall = pCall;

	return pCall;
}


static BthNsHandle * FindBthNsHandle (BthNsHandle *pBthNsHandle) {
	BthNsHandle *pTrav = gpBthNS->pBthNsHandles;
	while (pTrav && pBthNsHandle != pTrav)
		pTrav = pTrav->pNext;

	return pTrav;
}

static Call * FindCall (Call *pCall) {
	Call *pTrav = gpBthNS->pCalls;
	while (pTrav && pCall != pTrav)
		pTrav = pTrav->pNext;

	return pTrav;
}


//
// Driver Interface functions
//
int bthns_InitializeOnce(void) {
	IFDBG(DebugOut(DEBUG_SDP_INIT | DEBUG_SDP_TRACE,L"bthns_InitializeOnce()\r\n"));

	if (gpBthNS) {
		IFDBG(DebugOut(DEBUG_ERROR,L"bthns_InitializeOnce:: ERROR_ALREADY_EXISTS\r\n"));
		return ERROR_ALREADY_EXISTS;
	}

	gpBthNS = new BthNs;
	if (!gpBthNS) {
		IFDBG(DebugOut(DEBUG_ERROR,L"bthns_InitializeOnce:: ERROR_OUTOFMEMORY\r\n"));
		return ERROR_OUTOFMEMORY;
	}

	return ERROR_SUCCESS;
}

int bthns_CreateDriverInstance(void)  {
	HKEY hKey;
	IFDBG(DebugOut(DEBUG_SDP_TRACE,L"bthns_CreateDriverInstance entered\r\n"));

	if (! gpBthNS) {
		IFDBG(DebugOut(DEBUG_ERROR, L"bthns_CreateDriverInstance:: ERROR_SERVICE_DOES_NOT_EXIST\n"));
		return ERROR_SERVICE_DOES_NOT_EXIST;
	}

	gpBthNS->Lock();
	if (gpBthNS->eStage != JustCreated) {
		IFDBG(DebugOut(DEBUG_ERROR, L"bthns_CreateDriverInstance:: ERROR_SERVICE_ALREADY_RUNNING\n"));
		gpBthNS->Unlock();
		return ERROR_SERVICE_ALREADY_RUNNING;
	}
	gpBthNS->eStage = Initializing;

	if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, g_szSDPBaseKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
		DWORD dwType;
		DWORD dwSize;

		if ((RegQueryValueEx (hKey, g_szTimeoutVal, 0, &dwType, (LPBYTE)&g_dwSearchTimeout, &dwSize) != ERROR_SUCCESS) ||
		    (dwType != REG_DWORD) || (dwSize != sizeof(g_dwSearchTimeout))) {
		    g_dwSearchTimeout = SPD_SEARCH_DEFAULT_TIMEOUT;
		}
		RegCloseKey (hKey);
	}
	else
		g_dwSearchTimeout = SPD_SEARCH_DEFAULT_TIMEOUT;

	IFDBG(DebugOut(DEBUG_SDP_INIT,L"SDP Default search timeout = 0x%08x milliseconds\r\n",g_dwSearchTimeout));
	SVSUTIL_ASSERT(g_dwSearchTimeout);

	SVSUTIL_ASSERT(! (gpBthNS->pfmdBthNsHandles && gpBthNS->pfmdNSCAlls && 
	                  gpBthNS->pBthNsHandles    && gpBthNS->pCalls));

	gpBthNS->pfmdBthNsHandles = svsutil_AllocFixedMemDescr(sizeof(BthNsHandle), 10);
	gpBthNS->pfmdNSCAlls   = svsutil_AllocFixedMemDescr(sizeof(Call), 10);
	
	if (!gpBthNS->pfmdBthNsHandles || !gpBthNS->pfmdNSCAlls) {
		IFDBG(DebugOut(DEBUG_ERROR, L"bthns_CreateDriverInstance:: ERROR_OUTOFMEMORY\n"));
		gpBthNS->Unlock();
		return ERROR_OUTOFMEMORY;
	}

	SDP_CALLBACKS          c;
	SDP_EVENT_INDICATION   ei;

	memset(&c,0,sizeof(c));
	c.sdp_Connect_Out                = bthns_Connect_Out;
	c.sdp_ServiceSearch_Out          = bthns_ServiceSearch_Out;
	c.sdp_AttributeSearch_Out        = bthns_AttributeSearch_Out;
	c.sdp_ServiceAttributeSearch_Out = bthns_ServiceAttributeSearch_Out;

⌨️ 快捷键说明

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