int MASdpEnumAttrs(LPBYTE pSDPStream, ULONG streamSize, std::vector<MAUUID>* pUUIDs) { //should fill serv.uuids with what we're looking for, if everything went well. //GLE(BluetoothSdpEnumAttributes(pSDPStream, streamSize, // BtEnumAttributesCallback, pUUIDs)); HRESULT hres; ISdpStream *pIStream = NULL; ISdpRecord **pSdpRecords = NULL; // Create a stream object. HRES(CoCreateInstance(__uuidof(SdpStream),NULL,CLSCTX_INPROC_SERVER, __uuidof(ISdpStream),(LPVOID *) &pIStream)); // Ensure that the stream is valid and is well formed. hres = pIStream->Validate(pSDPStream,streamSize,NULL); if(FAILED(hres)) { LOG("SdpStream validation failed: 0x%08X\n", hres); //not good; we should return a proper MoSync error code, but the current MASdpEnumAttrs //interface doesn't allow it. return false; } SdpWalkListener walker(pUUIDs); #if 0 HRES(pIStream->Walk(pSDPStream, streamSize, &walker)); //ISdpNodeContainer::CreateFromStream( return true; #endif // Ensure that the sequence of the stream is valid and is well formed. #if 1 ULONG numRecords; hres = pIStream->VerifySequenceOf(pSDPStream,streamSize, SDP_TYPE_SEQUENCE,NULL,&numRecords); LOGBT("%i SDP records\n", numRecords); if (SUCCEEDED(hres) && numRecords > 0) { //Allocate memory for the SDP record buffer. pSdpRecords = (ISdpRecord **) CoTaskMemAlloc(sizeof(ISdpRecord*) * (numRecords)); if (pSdpRecords != NULL) { // Retrieve the SDP records from the stream. hres = pIStream->RetrieveRecords(pSDPStream, streamSize,pSdpRecords,&numRecords); if(SUCCEEDED(hres)) { //SdpWalkListener *walkListener = new SdpWalkListener(pUUIDs); for(unsigned int i = 0; i < numRecords; i++) { LOGBT("SDP Walk %i\n", i); pSdpRecords[i]->Walk(&walker);//walkListener); } } CoTaskMemFree(pSdpRecords); pSdpRecords = NULL; numRecords = 0; } else { LOGBT("Bluetooth Service discovery: Out of Memory\n"); hres = E_OUTOFMEMORY; } } else { LOGBT("pIStream->VerifySequenceOf failed\n"); } #endif return SUCCEEDED(hres); }
HRESULT FindRFCOMMChannel (unsigned char *pStream, int cStream, unsigned long *nChannel) { ISdpRecord **pRecordArg = NULL; int cRecordArg = 0; ISdpStream *pIStream = NULL; HRESULT hr = 0; ULONG ulError = 0; *nChannel = 0; hr = CoCreateInstance(__uuidof(SdpStream),NULL, CLSCTX_INPROC_SERVER, __uuidof(ISdpStream),(LPVOID *) &pIStream); if ( FAILED(hr) || pIStream == NULL ) return hr; hr = pIStream->Validate (pStream, cStream,&ulError); if (SUCCEEDED(hr)) { hr = pIStream->VerifySequenceOf(pStream, cStream, SDP_TYPE_SEQUENCE,NULL, (ULONG *)&cRecordArg); if (SUCCEEDED(hr) && cRecordArg > 0) { pRecordArg = (ISdpRecord **) CoTaskMemAlloc(sizeof(ISdpRecord*) * cRecordArg); if (pRecordArg != NULL) { hr = pIStream->RetrieveRecords(pStream, cStream, pRecordArg,(ULONG *) &cRecordArg); if ( FAILED(hr) ) { CoTaskMemFree(pRecordArg); pRecordArg = NULL; cRecordArg = 0; } } else { hr = E_OUTOFMEMORY; } } } if (pIStream != NULL) { pIStream->Release(); pIStream = NULL; } if ( FAILED(hr) ) return hr; for (int i = 0; (*nChannel == 0) && (i < cRecordArg); i++) { ISdpRecord *pRecord = pRecordArg[i]; // contains SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST data, // if available NodeData protocolList; if (ERROR_SUCCESS != pRecord->GetAttribute(SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST, &protocolList) || (protocolList.type != SDP_TYPE_CONTAINER)) { if (protocolList.type == SDP_TYPE_STRING) CoTaskMemFree(protocolList.u.str.val); else if (protocolList.type == SDP_TYPE_URL) CoTaskMemFree(protocolList.u.url.val); continue; } ISdpNodeContainer *pRecordContainer = protocolList.u.container; int cProtocols = 0; NodeData protocolDescriptor; pRecordContainer->GetNodeCount((DWORD *)&cProtocols); for (int j = 0; (nChannel == 0) && (j < cProtocols); j++) { pRecordContainer->GetNode(j,&protocolDescriptor); if (protocolDescriptor.type != SDP_TYPE_CONTAINER) continue; ISdpNodeContainer *pProtocolContainer = protocolDescriptor.u.container; int cProtocolAtoms = 0; pProtocolContainer->GetNodeCount((DWORD *)&cProtocolAtoms); for (int k = 0; (nChannel == 0) && (k < cProtocolAtoms); k++) { NodeData nodeAtom; pProtocolContainer->GetNode(k,&nodeAtom); if (IsRfcommUuid(&nodeAtom)) { if (k+1 == cProtocolAtoms) { // Error: Channel ID should follow RFCOMM uuid break; } NodeData channelID; pProtocolContainer->GetNode(k+1,&channelID); switch(channelID.specificType) { case SDP_ST_UINT8: *nChannel = channelID.u.uint8; break; case SDP_ST_INT8: *nChannel = channelID.u.int8; break; case SDP_ST_UINT16: *nChannel = channelID.u.uint16; break; case SDP_ST_INT16: *nChannel = channelID.u.int16; break; case SDP_ST_UINT32: *nChannel = channelID.u.uint32; break; case SDP_ST_INT32: *nChannel = channelID.u.int32; break; default: *nChannel = 0; } break; } } } if (protocolList.type == SDP_TYPE_STRING) CoTaskMemFree(protocolList.u.str.val); else if (protocolList.type == SDP_TYPE_URL) CoTaskMemFree(protocolList.u.url.val); } // cleanup for (int i = 0; i < cRecordArg; i++) pRecordArg[i]->Release(); CoTaskMemFree(pRecordArg); return (*nChannel != 0) ? S_OK : S_FALSE; }
int handleSdpResponse(std::vector<BtService>* services, LPWSAQUERYSET pQs) { //set up SdpStream HRESULT hres; ISdpStream *pIStream = NULL; //ISdpRecord **pSdpRecords = NULL; // Create a stream object. HRES(CoCreateInstance(__uuidof(SdpStream),NULL,CLSCTX_INPROC_SERVER, __uuidof(ISdpStream), (LPVOID *)&pIStream)); BYTE* pSDPStream = pQs->lpBlob->pBlobData; ULONG streamSize = pQs->lpBlob->cbSize; DUMPHEX(pSDPStream); DUMPHEX(streamSize); DUMPHEX(pIStream); // Ensure that the stream is valid and is well formed. hres = pIStream->Validate(pSDPStream, streamSize, NULL); if(FAILED(hres)) { LOG("SdpStream validation failed: 0x%08X\n", hres); return CONNERR_GENERIC; } //get list of Records int numRecords; hres = pIStream->VerifySequenceOf(pSDPStream, streamSize, SDP_TYPE_SEQUENCE, NULL, (ULONG*)&numRecords); LOGBT("SdpStream verification result: 0x%08X\n", hres); if(FAILED(hres) || numRecords<=0) { LOG("SdpStream verification failed: 0x%08X, numRecords: %d\n", hres, numRecords); return CONNERR_GENERIC; } LOGBT("%i SDP records\n", numRecords); //pSdpRecords = (ISdpRecord **) CoTaskMemAlloc(sizeof(ISdpRecord*) * (numRecords)); Array<ISdpRecord*> pSdpRecords(numRecords); MYASSERT(pSdpRecords != NULL, ERR_OOM); // Retrieve the SDP records from the stream. hres = pIStream->RetrieveRecords(pSDPStream, streamSize, pSdpRecords.p(), (ULONG *) &numRecords); if(FAILED(hres)) { LOG("SdpStream retrieval failed: 0x%08X\n", hres); return CONNERR_GENERIC; } //one Service per Record //Walk //store results in *services for(int i = 0; i < numRecords; i++) { LOGBT("SDP Walk %i\n", i); BtService serv; MySdpWalk walk(serv); hres = pSdpRecords[i]->Walk(&walk); if(FAILED(hres)) { LOG("SdpStream walk failed: 0x%08X\n", hres); return CONNERR_GENERIC; } services->push_back(serv); } return 1; }