📄 sdpns.cxx
字号:
SetLastError(WSASERVICE_NOT_FOUND);
return SOCKET_ERROR;
}
if (!CheckQuerySet(pSet,BTHNS_SET_SERVICE,dwFlags,op)) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsSetService: ERROR_INVALID_PARAMETER\r\n"));
gpBthNS->Unlock();
SetLastError(WSAEINVAL);
return SOCKET_ERROR;
}
PBTHNS_SETBLOB pSetBlob = (PBTHNS_SETBLOB) pSet->lpBlob->pBlobData;
int iRet;
// Since these BthNsHandles operate loBthNsHandley, they are blocking.
if (op == RNRSERVICE_REGISTER)
iRet = gpBthNS->sdp_if.sdp_AddRecord(gpBthNS->hSDP,pSetBlob->pRecord,pSetBlob->ulRecordLength,(HANDLE*)(pSetBlob->pRecordHandle));
else {
SVSUTIL_ASSERT(op == RNRSERVICE_DELETE);
iRet = gpBthNS->sdp_if.sdp_RemoveRecord(gpBthNS->hSDP,(HANDLE)(*(pSetBlob->pRecordHandle)));
}
gpBthNS->Unlock();
if (iRet != ERROR_SUCCESS) {
iRet = MapErrorCodeToWinsockErr(iRet,TRUE);
SetLastError(iRet);
return SOCKET_ERROR;
}
return ERROR_SUCCESS;
}
//
// WSA Interface functions
//
#define MAX_SEARCH_HANDLES 0xFFFF
#define INQUIRY_GIAC_LAP 0x9e8b33 // unlimited inquiry access mode (GIAC)
#define INQUIRY_DURATION 0x08
#define INQUIRY_MAX_RESPONSES 0x20
int BthNsLookupServiceBegin(LPWSAQUERYSET pQuerySet, DWORD dwFlags, LPHANDLE lphLookup) {
int iRes = ERROR_INTERNAL_ERROR;
unsigned short cid = 0;
BthNsHandle *pBthNsHandle = NULL;
IFDBG(DebugOut(DEBUG_SDP_TRACE,L"BthNsLookupServiceBegin entered\r\n"));
if (! gpBthNS) {
IFDBG(DebugOut(DEBUG_ERROR, L"BthNsLookupServiceBegin:: WSASERVICE_NOT_FOUND\n"));
SetLastError(WSASERVICE_NOT_FOUND);
return SOCKET_ERROR;
}
gpBthNS->Lock();
if (gpBthNS->eStage != Running) {
IFDBG(DebugOut(DEBUG_ERROR, L"BthNsLookupServiceBegin:: WSASERVICE_NOT_FOUND\n"));
gpBthNS->Unlock();
SetLastError(WSASERVICE_NOT_FOUND);
return SOCKET_ERROR;
}
if (!CheckQuerySet(pQuerySet,BTHNS_LOOKUP_SERVICE_BEGIN,dwFlags) || !lphLookup) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsLookupServiceBegin: WSAEINVAL\r\n"));
gpBthNS->Unlock();
SetLastError(WSAEINVAL);
return SOCKET_ERROR;
}
if (NULL == (pBthNsHandle = AllocBthNsHandle(pQuerySet, dwFlags,&iRes))) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsLookupServiceBegin: ERROR_OUTOFMEMORY\r\n"));
gpBthNS->Unlock();
SetLastError(iRes);
return SOCKET_ERROR;
}
if (dwFlags & LUP_CONTAINERS) {
// device inquiry
// If pInquiryBlob is NULL, then use default values.
PBTHNS_INQUIRYBLOB pInquiryBlob = (PBTHNS_INQUIRYBLOB) ( pQuerySet->lpBlob ? pQuerySet->lpBlob->pBlobData : NULL);
pBthNsHandle->LAP = pInquiryBlob ? pInquiryBlob->LAP : INQUIRY_GIAC_LAP;
pBthNsHandle->cDuration = pInquiryBlob ? pInquiryBlob->length : INQUIRY_DURATION;
// WinXP doesn't support pInquiryBlob->num_responses field. To avoid
// potential porting issues (i.e. an app on XP doesn't set this and on porting
// it's a garbage value on CE) we ignore it.
// pBthNsHandle->cMaxResp = pInquiryBlob ? pInquiryBlob->num_responses : INQUIRY_MAX_RESPONSES;
pBthNsHandle->cMaxResp = INQUIRY_MAX_RESPONSES;
pBthNsHandle->fInquiryStatus = INQUIRY_PENDING;
}
gpBthNS->Unlock();
*lphLookup = (HANDLE) pBthNsHandle;
IFDBG(DebugOut(DEBUG_SDP_TRACE,L"BthNsLookupServiceBegin returns ERROR_SUCCESS\r\n"));
return ERROR_SUCCESS;
}
int PerformInquiry (BthNsHandle *pBthNsHandle) {
unsigned long LAP = pBthNsHandle->LAP;
unsigned int cMaxResp = pBthNsHandle->cMaxResp;
unsigned int cDuration = pBthNsHandle->cDuration;
unsigned int cDevices = 0;
BthInquiryResult *pInquiryResults = (BthInquiryResult *) g_funcAlloc(cMaxResp*sizeof(BthInquiryResult),g_pvAllocData);
if (!pInquiryResults) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsLookupServiceBegin: ERROR_OUTOFMEMORY\r\n"));
gpBthNS->Unlock();
SetLastError(WSA_NOT_ENOUGH_MEMORY);
return SOCKET_ERROR;
}
memset(pInquiryResults,0,cMaxResp*sizeof(BthInquiryResult));
pBthNsHandle->fInquiryStatus = INQUIRY_INPROGRESS;
gpBthNS->AddRef();
gpBthNS->Unlock();
int iResult = BthPerformInquiry(LAP,cDuration,0,
cMaxResp,&cDevices,pInquiryResults);
gpBthNS->Lock();
gpBthNS->DelRef();
if (! FindBthNsHandle(pBthNsHandle)) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsLookupServiceBegin: handle (0x%08x) invalid after BthPerformInquiry()\r\n",pBthNsHandle));
g_funcFree(pInquiryResults,g_pvAllocData);
gpBthNS->Unlock();
SetLastError(WSA_E_CANCELLED);
return SOCKET_ERROR;
}
pBthNsHandle->fInquiryStatus = INQUIRY_COMPLETED;
if ((ERROR_SUCCESS != iResult)) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsLookupServiceBegin: BthPerformInquiry returns 0x%08x\r\n",iResult));
g_funcFree(pInquiryResults,g_pvAllocData);
gpBthNS->Unlock();
SetLastError(WSAENETDOWN);
return SOCKET_ERROR;
}
SVSUTIL_ASSERT(cDevices <= cMaxResp);
if (cDevices > cMaxResp)
cDevices = cMaxResp;
pBthNsHandle->cDevices = cDevices;
pBthNsHandle->pInquiryResults = pInquiryResults;
return ERROR_SUCCESS;
}
// supported Contairer flags for dwFlags param in BthNsLookupServiceNext
#define BTHNS_LOOKUP_SERVICE_NEXT_CONTAINER_FLAGS (LUP_RETURN_NAME | LUP_RETURN_ADDR | LUP_RETURN_BLOB | BTHNS_LUP_RESET_ITERATOR | BTHNS_LUP_NO_ADVANCE)
int BthNsLookupServiceNext(HANDLE hLookup, DWORD dwFlags, LPDWORD lpdwBufferLength, LPWSAQUERYSET pResults) {
int iRes = ERROR_INTERNAL_ERROR;
unsigned short cid = 0;
BOOL fLocal;
DWORD cbRequired = 0;
PBTHNS_RESTRICTIONBLOB pResBlob = NULL;
ULONG type;
BOOL fDisconnect = FALSE;
Call *pCall = NULL;
IFDBG(DebugOut(DEBUG_SDP_TRACE,L"BthNsLookupServiceNext entered\r\n"));
if (!lpdwBufferLength) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsLookupServiceNext: params misformatted, ERROR_INVALID_PARAMETER\r\n"));
SetLastError(WSAEINVAL);
return SOCKET_ERROR;
}
if (!gpBthNS) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsLookupServiceNext:: ERROR_SERVICE_DOES_NOT_EXIST\r\n"));
SetLastError(WSASERVICE_NOT_FOUND);
return SOCKET_ERROR;
}
gpBthNS->Lock();
if (gpBthNS->eStage != Running) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsLookupServiceNext:: ERROR_SERVICE_NOT_ACTIVE\r\n"));
gpBthNS->Unlock();
SetLastError(WSASERVICE_NOT_FOUND);
return SOCKET_ERROR;
}
BthNsHandle *pBthNsHandle = FindBthNsHandle((BthNsHandle *) hLookup);
if (!pBthNsHandle) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsSetService: BthNsHandle not found, ERROR_INVALID_PARAMETER\r\n"));
gpBthNS->Unlock();
SetLastError(WSA_INVALID_HANDLE);
return SOCKET_ERROR;
}
//
// Device Inquiry
//
if (pBthNsHandle->dwFlags & LUP_CONTAINERS) {
if (pBthNsHandle->fInquiryStatus == INQUIRY_PENDING) {
if (PerformInquiry (pBthNsHandle) == SOCKET_ERROR) // If error, it unlocks
return SOCKET_ERROR;
}
if (! __SDP_IS_ALIGNED(pResults, 8))
DebugOut(DEBUG_SDP_TRACE, L"SDP: Unaligned remote address in structure - FIX THE APP!\n");
if (dwFlags & ~(BTHNS_LOOKUP_SERVICE_NEXT_CONTAINER_FLAGS)) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsLookupServiceNext flags are invalid (=0x%08x)",dwFlags));
gpBthNS->Unlock();
SetLastError(WSAEFAULT);
return SOCKET_ERROR;
}
// WinCE allows iterator list to be reset, allowing list to be traveresed again.
if (dwFlags & BTHNS_LUP_RESET_ITERATOR) {
pBthNsHandle->iDeviceIterator = 0;
gpBthNS->Unlock();
return ERROR_SUCCESS;
}
if (pBthNsHandle->iDeviceIterator >= pBthNsHandle->cDevices) {
gpBthNS->Unlock();
SetLastError(WSA_E_NO_MORE);
return SOCKET_ERROR;
}
cbRequired = sizeof(WSAQUERYSET);
if (dwFlags & LUP_RETURN_NAME)
cbRequired += BD_MAXNAME * sizeof(WCHAR);
if (dwFlags & LUP_RETURN_ADDR) {
cbRequired = __SDP_ALIGN(cbRequired, 4);
cbRequired = __SDP_ALIGN((cbRequired + sizeof(CSADDR_INFO)), 8) + 2 * sizeof(SOCKADDR_BTH);
}
// Note: WinCE returns a different data structure on this call than NT, by design.
if (dwFlags & LUP_RETURN_BLOB) {
cbRequired = __SDP_ALIGN(cbRequired, 4);
cbRequired = __SDP_ALIGN((cbRequired + sizeof(LPBLOB)), 8) + sizeof(BthInquiryResult);
}
if (cbRequired > *lpdwBufferLength) {
IFDBG(DebugOut(DEBUG_SDP_TRACE,L"BthNsLookupServiceNext: %d bytes passed in, %d required\r\n",*lpdwBufferLength,cbRequired));
*lpdwBufferLength = cbRequired;
gpBthNS->Unlock();
SetLastError(WSA_NOT_ENOUGH_MEMORY);
return SOCKET_ERROR;
}
if (!pResults) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsLookupServiceNext: params misformatted, ERROR_INVALID_PARAMETER\r\n"));
gpBthNS->Unlock();
SetLastError(WSAEINVAL);
return SOCKET_ERROR;
}
__try {
CHAR *pBase = (CHAR*)pResults;
unsigned int uiOffsetCounter = sizeof(WSAQUERYSET);
memset(pResults,0,sizeof(*pResults));
pResults->dwSize = sizeof(WSAQUERYSETW);
pResults->lpServiceClassId = 0;
pResults->dwNameSpace = NS_BTH;
if (dwFlags & LUP_RETURN_NAME) {
// we don't query for names in WSALookupBegin, so we need to do it here.
BT_ADDR ba = pBthNsHandle->pInquiryResults[pBthNsHandle->iDeviceIterator].ba;
unsigned int cbReceived = 0;
WCHAR wszDeviceName[BD_MAXNAME];
memset (wszDeviceName, 0, sizeof(wszDeviceName));
gpBthNS->AddRef();
gpBthNS->Unlock();
iRes = BthRemoteNameQuery(&ba, SVSUTIL_ARRLEN(wszDeviceName), &cbReceived, wszDeviceName);
gpBthNS->Lock();
gpBthNS->DelRef();
if (! FindBthNsHandle((BthNsHandle *) hLookup)) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsLookupServiceNext: handle (0x%08x) invalid after BthRemoteNameQuery()\r\n",hLookup));
gpBthNS->Unlock();
SetLastError(WSA_E_CANCELLED);
return SOCKET_ERROR;
}
// in the event of error, don't fail, just leave field NULL.
if (iRes == ERROR_SUCCESS) {
pResults->lpszServiceInstanceName = (WCHAR *)(pBase + uiOffsetCounter);
wcsncpy (pResults->lpszServiceInstanceName, wszDeviceName, BD_MAXNAME);
}
uiOffsetCounter += BD_MAXNAME * sizeof(WCHAR);
}
if (dwFlags & LUP_RETURN_ADDR) {
int uiOffsetCounterStart = uiOffsetCounter = __SDP_ALIGN(uiOffsetCounter, 4);
PCSADDR_INFO pAddrInfo = (PCSADDR_INFO)(pBase + uiOffsetCounter);
pResults->lpcsaBuffer = pAddrInfo;
pResults->dwNumberOfCsAddrs = 1;
uiOffsetCounter = __SDP_ALIGN(uiOffsetCounter + sizeof(CSADDR_INFO), 8);
PSOCKADDR_BTH pLocal = (PSOCKADDR_BTH)(pBase + uiOffsetCounter);
PSOCKADDR_BTH pRemote = pLocal + 1;
uiOffsetCounter += 2 * sizeof(SOCKADDR_BTH);
memset (pBase + uiOffsetCounterStart, 0, uiOffsetCounter - uiOffsetCounterStart);
pAddrInfo->iSocketType = SOCK_STREAM;
pAddrInfo->LocalAddr.lpSockaddr = (PSOCKADDR)pLocal;
pAddrInfo->LocalAddr.iSockaddrLength = sizeof(*pLocal);
pLocal->addressFamily = AF_BT;
BthReadLocalAddr (&pLocal->btAddr);
pAddrInfo->RemoteAddr.lpSockaddr = (PSOCKADDR)pRemote;
pAddrInfo->RemoteAddr.iSockaddrLength = sizeof(*pRemote);
pRemote->addressFamily = AF_BT;
memcpy(&pRemote->btAddr, &pBthNsHandle->pInquiryResults[pBthNsHandle->iDeviceIterator].ba, sizeof(BT_ADDR));
}
if (dwFlags & LUP_RETURN_BLOB) {
uiOffsetCounter = __SDP_ALIGN(uiOffsetCounter, 4);
pResults->lpBlob = (LPBLOB)(pBase + uiOffsetCounter);
pResults->lpBlob->cbSize = sizeof(BthInquiryResult);
uiOffsetCounter = __SDP_ALIGN(uiOffsetCounter + sizeof(BLOB), 8);
pResults->lpBlob->pBlobData = (PBYTE) (pBase + uiOffsetCounter);
memcpy(pResults->lpBlob->pBlobData,(BthInquiryResult *)&pBthNsHandle->pInquiryResults[pBthNsHandle->iDeviceIterator],sizeof(BthInquiryResult));
uiOffsetCounter += sizeof(BthInquiryResult);
}
SVSUTIL_ASSERT (uiOffsetCounter == cbRequired);
} __except (1) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsLookupServiceNext: Exception!\n"));
gpBthNS->Unlock();
return ERROR_INVALID_PARAMETER;
}
// CE offers the option of not advancing iterator, so app may query for
// more detailed info on this BT addr if it so desires.
if (! (dwFlags & BTHNS_LUP_NO_ADVANCE))
pBthNsHandle->iDeviceIterator++;
gpBthNS->Unlock();
return ERROR_SUCCESS;
}
//
// Service Search
//
if (pBthNsHandle->fNoMoreData) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsLookupServiceNext: WSA_E_NO_MORE\r\n"));
gpBthNS->Unlock();
SetLastError(WSA_E_NO_MORE);
return SOCKET_ERROR;
}
if (! pBthNsHandle->fNetSearchComplete) {
fLocal = pBthNsHandle->fLocal;
if (NULL == (pCall = AllocCall(pBthNsHandle))) {
IFDBG(DebugOut(DEBUG_ERROR,L"BthNsLookupServiceNext: WSA_NOT_ENOUGH_MEMORY\r\n"));
gpBthNS->Unlock();
SetLastError(WSA_NOT_ENOUGH_MEMORY);
return SOCKET_ERROR;
}
// Below this point we may have to disconnect, so goto done for common exit pt.
if (!fLocal) {
iRes = SDPConnectBlocking(pCall,&pBthNsHandle->b);
SVSUTIL_ASSERT(gpBthNS->IsLocked());
if (iRes != ERROR_SUCCESS) {
iRes = WSASERVICE_NOT_FOUND;
goto done;
}
if (NULL == (pCall = FindCall(pCall)) || (pCall->iResult != ERROR_SUCCESS)) {
iRes = pCall ? WSASERVICE_NOT_FOUND : WSA_E_CANCELLED;
goto done;
}
fDisconnect = TRUE;
cid = pCall->cid;
if (NULL == (pBthNsHandle = FindBthNsHandle(pBthNsHandle))) {
iRes = WSA_E_CANCELLED;
goto done;
}
}
pResBlob = pBthNsHandle->pResBlob;
// To determine which type of inquiery to perform, if we have pResBlob do
// what's specifed there. If we don't we use the GUID set in ServiceClassId on
// BthNsLookupServiceBegin call. On CE to keep bc we assume SDP_SERVICE_SEARCH_REQUEST,
// however if we're in XP compat mode then we do a SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST
// with all attributes.
if (pResBlob)
type = pResBlob->type;
else if (pBthNsHandle->fXPCompatMode)
type = SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST;
else
type = SDP_SERVICE_SEARCH_REQUEST;
SVSUTIL_ASSERT( (fLocal && !cid) || (!fLocal && cid));
// If no restrictions were set, use ServiceClassId to fill out a default
// restriction blob.
SdpQueryUuid UUID[2];
SdpQueryUuid *pUUIDs;
SdpAttributeRange Range;
SdpAttributeRange *pRange;
int numAttributes;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -