private static void RemoveService(IntPtr handle, byte[] sdpRecord) { BTHNS_SETBLOB blob = new BTHNS_SETBLOB(sdpRecord); blob.Handle = handle; WSAQUERYSET qs = new WSAQUERYSET(); qs.dwSize = WqsOffset.StructLength_60; qs.dwNameSpace = WqsOffset.NsBth_16; System.Diagnostics.Debug.Assert(Marshal.SizeOf(qs) == qs.dwSize, "WSAQUERYSET SizeOf == dwSize"); GCHandle hBlob = GCHandle.Alloc(blob.ToByteArray(), GCHandleType.Pinned); BLOB b = new BLOB(blob.Length, GCHandleHelper.AddrOfPinnedObject(hBlob)); GCHandle hb = GCHandle.Alloc(b, GCHandleType.Pinned); qs.lpBlob = hb.AddrOfPinnedObject(); try { int hresult = NativeMethods.WSASetService(ref qs, WSAESETSERVICEOP.RNRSERVICE_DELETE, 0); BluetoothClient.ThrowSocketExceptionForHR(hresult); } finally { hb.Free(); hBlob.Free(); //release blob and associated GCHandles blob.Dispose(); } }
private static IntPtr SetService(byte[] sdpRecord, ServiceClass cod) { BTHNS_SETBLOB blob = new BTHNS_SETBLOB(sdpRecord); //added for XP - adds class of device bits #if WinXP blob.CodService = (uint)cod; #endif WSAQUERYSET qs = new WSAQUERYSET(); qs.dwSize = WqsOffset.StructLength_60; qs.dwNameSpace = WqsOffset.NsBth_16; System.Diagnostics.Debug.Assert(Marshal.SizeOf(qs) == qs.dwSize, "WSAQUERYSET SizeOf == dwSize"); GCHandle hBlob = GCHandle.Alloc(blob.ToByteArray(), GCHandleType.Pinned); BLOB b = new BLOB(blob.Length, GCHandleHelper.AddrOfPinnedObject(hBlob)); GCHandle hb = GCHandle.Alloc(b, GCHandleType.Pinned); qs.lpBlob = hb.AddrOfPinnedObject(); try { int hresult = NativeMethods.WSASetService(ref qs, WSAESETSERVICEOP.RNRSERVICE_REGISTER, 0); BluetoothClient.ThrowSocketExceptionForHR(hresult); } finally { hb.Free(); hBlob.Free(); } IntPtr handle = blob.Handle; blob.Dispose(); return handle; }
/// <summary> /// Discovers accessible Bluetooth devices and returns their names and addresses. /// </summary> /// <param name="maxDevices">The maximum number of devices to get information about.</param> /// <param name="authenticated">True to return previously authenticated/paired devices.</param> /// <param name="remembered">True to return remembered devices.</param> /// <param name="unknown">True to return previously unknown devices.</param> /// <returns>An array of BluetoothDeviceInfo objects describing the devices discovered.</returns> public BluetoothDeviceInfo[] DiscoverDevices(int maxDevices, bool authenticated, bool remembered, bool unknown) { WqsOffset.AssertCheckLayout(); CsaddrInfoOffsets.AssertCheckLayout(); // int discoveredDevices = 0; ArrayList al = new ArrayList(); int handle = 0; int lookupresult = 0; #if WinCE if(unknown) { #endif byte[] buffer = new byte[1024]; BitConverter.GetBytes(WqsOffset.StructLength_60).CopyTo(buffer, WqsOffset.dwSize_0); BitConverter.GetBytes(WqsOffset.NsBth_16).CopyTo(buffer, WqsOffset.dwNameSpace_20); int bufferlen = buffer.Length; BTHNS_INQUIRYBLOB bib = new BTHNS_INQUIRYBLOB(); bib.LAP = 0x9E8B33; #if WinCE bib.length = Convert.ToInt16(inquiryLength.TotalSeconds / 1.28); bib.num_responses = Convert.ToInt16(maxDevices); #else bib.length = Convert.ToByte(inquiryLength.TotalSeconds); #endif GCHandle hBib = GCHandle.Alloc(bib, GCHandleType.Pinned); IntPtr pBib = hBib.AddrOfPinnedObject(); BLOB b = new BLOB(8, pBib); GCHandle hBlob = GCHandle.Alloc(b, GCHandleType.Pinned); Marshal32.WriteIntPtr(buffer, WqsOffset.lpBlob_56, hBlob.AddrOfPinnedObject()); //start looking for Bluetooth devices LookupFlags flags = LookupFlags.Containers; #if WinXP //ensure cache is cleared on XP when looking for new devices if(unknown) { flags |= LookupFlags.FlushCache; } #endif lookupresult = NativeMethods.WSALookupServiceBegin(buffer, flags, out handle); hBlob.Free(); hBib.Free(); while(discoveredDevices < maxDevices && lookupresult != -1) { #if WinCE lookupresult = NativeMethods.WSALookupServiceNext(handle, LookupFlags.ReturnAddr | LookupFlags.ReturnBlob , ref bufferlen, buffer); #else lookupresult = NativeMethods.WSALookupServiceNext(handle, LookupFlags.ReturnAddr , ref bufferlen, buffer); #endif if (lookupresult != -1) { //increment found count discoveredDevices++; //status #if WinXP BTHNS_RESULT status = (BTHNS_RESULT)BitConverter.ToInt32(buffer, WqsOffset.dwOutputFlags_52); bool devAuthd = ((status & BTHNS_RESULT.Authenticated) == BTHNS_RESULT.Authenticated); bool devRembd = ((status & BTHNS_RESULT.Remembered) == BTHNS_RESULT.Remembered); if (devAuthd && !devRembd) { System.Diagnostics.Debug.WriteLine("Win32 BT disco: Auth'd but NOT Remembered."); } bool devUnkwn = !devRembd && !devAuthd; bool include = (authenticated && devAuthd) || (remembered && devRembd) || (unknown && devUnkwn); if (include) #else if(true) #endif { #if WinCE IntPtr lpBlob = (IntPtr)BitConverter.ToInt32(buffer, 56); BLOB ib = (BLOB)Marshal.PtrToStructure(lpBlob, typeof(BLOB)); BthInquiryResult bir = (BthInquiryResult)Marshal.PtrToStructure(ib.pBlobData, typeof(BthInquiryResult)); #endif //struct CSADDR_INFO { // SOCKET_ADDRESS LocalAddr; // SOCKET_ADDRESS RemoteAddr; // INT iSocketType; // INT iProtocol; //} //struct SOCKET_ADDRESS { // LPSOCKADDR lpSockaddr; // INT iSockaddrLength; //} //pointer to outputbuffer IntPtr bufferptr = Marshal32.ReadIntPtr(buffer, WqsOffset.lpcsaBuffer_48); //remote socket address IntPtr sockaddrptr = Marshal32.ReadIntPtr(bufferptr, CsaddrInfoOffsets.OffsetRemoteAddr_lpSockaddr_8); //remote socket len int sockaddrlen = Marshal.ReadInt32(bufferptr, CsaddrInfoOffsets.OffsetRemoteAddr_iSockaddrLength_12); SocketAddress btsa = new SocketAddress(AddressFamily32.Bluetooth, sockaddrlen); for(int sockbyte = 0; sockbyte < sockaddrlen; sockbyte++) { btsa[sockbyte] = Marshal.ReadByte(sockaddrptr, sockbyte); } BluetoothEndPoint bep = new BluetoothEndPoint(null, BluetoothService.Empty); bep = (BluetoothEndPoint)bep.Create(btsa); //new deviceinfo BluetoothDeviceInfo newdevice; #if WinCE newdevice = new BluetoothDeviceInfo(bep.Address, bir.cod); #else newdevice = new BluetoothDeviceInfo(bep.Address); #endif //add to discovered list al.Add(newdevice); } } } #if WinCE } #endif //stop looking if(handle!=0) { lookupresult = NativeMethods.WSALookupServiceEnd(handle); } #if WinCE //open bluetooth device key RegistryKey devkey = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Bluetooth\\Device"); bool addFromRegistry = authenticated || remembered; if (devkey != null) { //enumerate the keys foreach (string devid in devkey.GetSubKeyNames()) { BluetoothAddress address; if (BluetoothAddress.TryParse(devid, out address)) { //get friendly name RegistryKey thisdevkey = devkey.OpenSubKey(devid); string name = thisdevkey.GetValue("name", "").ToString(); uint classOfDevice = Convert.ToUInt32(thisdevkey.GetValue("class", 0)); thisdevkey.Close(); //add to collection BluetoothDeviceInfo thisdevice = new BluetoothDeviceInfo(address, name, classOfDevice, true); int devindex = al.IndexOf(thisdevice); if (devindex == -1) { //if we intended to search for authenticated devices add this one to the collection if (addFromRegistry) { al.Add(thisdevice); } } else { if (addFromRegistry) { //set authenticated flag on existing discovered device ((BluetoothDeviceInfo)al[devindex]).Authenticated = true; } else { //we want to exclude already authenticated devices so remove it from the collection al.RemoveAt(devindex); } } } } devkey.Close(); } #endif //return results if(al.Count == 0) { //special case for empty collection return new BluetoothDeviceInfo[0]{}; } return (BluetoothDeviceInfo[])al.ToArray(typeof(BluetoothDeviceInfo)); }