`BluetoothLEAdvertisementWatcher` is required for LE device discovery on WinRT. Several WinRT apps, like Zwift will try getting this interface, and crash if they are not able to.
From: Vibhav Pant vibhavp@gmail.com
--- include/Makefile.in | 1 + ...indows.devices.bluetooth.advertisement.idl | 440 ++++++++++++++++++ include/windows.devices.bluetooth.idl | 42 ++ 3 files changed, 483 insertions(+) create mode 100644 include/windows.devices.bluetooth.advertisement.idl
diff --git a/include/Makefile.in b/include/Makefile.in index 662b149da32..57dd4c3dc26 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -866,6 +866,7 @@ SOURCES = \ windows.applicationmodel.idl \ windows.data.json.idl \ windows.data.xml.dom.idl \ + windows.devices.bluetooth.advertisement.idl \ windows.devices.bluetooth.genericattributeprofile.idl \ windows.devices.bluetooth.idl \ windows.devices.bluetooth.rfcomm.idl \ diff --git a/include/windows.devices.bluetooth.advertisement.idl b/include/windows.devices.bluetooth.advertisement.idl new file mode 100644 index 00000000000..f4c73fa17c3 --- /dev/null +++ b/include/windows.devices.bluetooth.advertisement.idl @@ -0,0 +1,440 @@ +/* + * Copyright 2025 Vibhav Pant + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef __WIDL__ +#pragma winrt ns_prefix +#endif + +#ifndef DO_NO_IMPORTS +import "inspectable.idl"; +import "asyncinfo.idl"; +import "eventtoken.idl"; +import "windowscontracts.idl"; +import "windows.foundation.idl"; +import "windows.storage.streams.idl"; +import "windows.devices.bluetooth.idl"; +#endif + +namespace Windows.Devices.Bluetooth { + typedef enum BluetoothAddressType BluetoothAddressType; + typedef enum BluetoothError BluetoothError; + + runtimeclass BluetoothSignalStrengthFilter; +} + +namespace Windows.Devices.Bluetooth.Advertisement { + typedef enum BluetoothLEAdvertisementFlags BluetoothLEAdvertisementFlags; + typedef enum BluetoothLEAdvertisementWatcherStatus BluetoothLEAdvertisementWatcherStatus; + typedef enum BluetoothLEScanningMode BluetoothLEScanningMode; + typedef enum BluetoothLEAdvertisementType BluetoothLEAdvertisementType; + + interface IBluetoothLEManufacturerData; + interface IBluetoothLEAdvertisementDataSection; + interface IBluetoothLEAdvertisementDataSectionFactory; + interface IBluetoothLEManufacturerData; + interface IBluetoothLEManufacturerDataFactory; + interface IBluetoothLEAdvertisementWatcher; + interface IBluetoothLEAdvertisementFilter; + interface IBluetoothLEAdvertisementReceivedEventArgs; + interface IBluetoothLEAdvertisementReceivedEventArgs2; + interface IBluetoothLEAdvertisementWatcherStoppedEventArgs; + interface IBluetoothLEAdvertisementBytePattern; + interface IBluetoothLEAdvertisementBytePatternFactory; + + runtimeclass BluetoothLEAdvertisement; + runtimeclass BluetoothLEManufacturerData; + runtimeclass BluetoothLEAdvertisementDataSection; + runtimeclass BluetoothLEManufacturerData; + runtimeclass BluetoothLEAdvertisementWatcher; + runtimeclass BluetoothLEAdvertisementFilter; + runtimeclass BluetoothLEAdvertisementReceivedEventArgs; + runtimeclass BluetoothLEAdvertisementWatcherStoppedEventArgs; + runtimeclass BluetoothLEAdvertisementBytePattern; + + declare { + interface Windows.Foundation.IReference<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementFlags>; + interface Windows.Foundation.Collections.IVector<GUID>; + interface Windows.Foundation.Collections.IVector<Windows.Devices.Bluetooth.Advertisement.BluetoothLEManufacturerData *>; + interface Windows.Foundation.Collections.IVector<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementDataSection *>; + interface Windows.Foundation.Collections.IVector<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementBytePattern *>; + interface Windows.Foundation.Collections.IVectorView<GUID>; + interface Windows.Foundation.Collections.IVectorView<Windows.Devices.Bluetooth.Advertisement.BluetoothLEManufacturerData *>; + interface Windows.Foundation.Collections.IVectorView<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementDataSection *>; + interface Windows.Foundation.Collections.IVectorView<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementBytePattern *>; + interface Windows.Foundation.Collections.IIterable<GUID>; + interface Windows.Foundation.Collections.IIterable<Windows.Devices.Bluetooth.Advertisement.BluetoothLEManufacturerData *>; + interface Windows.Foundation.Collections.IIterable<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementDataSection *>; + interface Windows.Foundation.Collections.IIterable<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementBytePattern *>; + interface Windows.Foundation.Collections.IIterator<GUID>; + interface Windows.Foundation.Collections.IIterator<Windows.Devices.Bluetooth.Advertisement.BluetoothLEManufacturerData *>; + interface Windows.Foundation.Collections.IIterator<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementDataSection *>; + interface Windows.Foundation.Collections.IIterator<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementBytePattern *>; + interface Windows.Foundation.TypedEventHandler<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcher *, Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementReceivedEventArgs *>; + interface Windows.Foundation.TypedEventHandler<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcher *, Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcherStoppedEventArgs *>; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + flags + ] + enum BluetoothLEAdvertisementFlags + { + None = 0x00, + LimitedDiscoverableMode = 0x01, + GeneralDiscoverableMode = 0x02, + ClassicNotSupported = 0x04, + DualModeControllerCapable = 0x08, + DualModeHostCapable = 0x10, + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + ] + enum BluetoothLEAdvertisementPublisherStatus + { + Created = 0, + Waiting = 1, + Started = 2, + Stopping = 3, + Stopped = 4, + Aborted = 5, + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + ] + enum BluetoothLEAdvertisementType + { + ConnectableUndirected = 0, + ConnectableDirected = 1, + ScannableUndirected = 2, + NonConnectableUndirected = 3, + ScanResponse = 4, + [contract(Windows.Foundation.UniversalApiContract, 10.0)] + Extended = 5 + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + ] + enum BluetoothLEAdvertisementWatcherStatus + { + Created = 0, + Started = 1, + Stopping = 2, + Stopped = 3, + Aborted = 4, + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + ] + enum BluetoothLEScanningMode + { + Passive = 0, + Active = 1, + [contract(Windows.Foundation.UniversalApiContract, 10.0)] + None = 2, + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisement), + uuid(066fb2b7-33d1-4e7d-8367-cf81d0f79653) + ] + interface IBluetoothLEAdvertisement : IInspectable + { + [propget] HRESULT Flags([out, retval] Windows.Foundation.IReference<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementFlags> **value); + [propput] HRESULT Flags([in] Windows.Foundation.IReference<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementFlags> *value); + [propget] HRESULT LocalName([out, retval] HSTRING *value); + [propput] HRESULT LocalName([in] HSTRING value); + [propget] HRESULT ServiceUuids([out, retval] Windows.Foundation.Collections.IVector<GUID> **value); + [propget] HRESULT ManufacturerData([out, retval] Windows.Foundation.Collections.IVector<Windows.Devices.Bluetooth.Advertisement.BluetoothLEManufacturerData *> **value); + [propget] HRESULT DataSections([out, retval] Windows.Foundation.Collections.IVector<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementDataSection *> **value); + HRESULT GetManufacturerDataByCompanyId([in] UINT16 id, [out, retval] Windows.Foundation.Collections.IVectorView<Windows.Devices.Bluetooth.Advertisement.BluetoothLEManufacturerData *> **value); + HRESULT GetSectionsByType([in] BYTE type, [out, retval] Windows.Foundation.Collections.IVectorView<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementDataSection *> **value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + activatable(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + threading(both) + ] + runtimeclass BluetoothLEAdvertisement + { + [default] interface Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisement; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementDataSection), + uuid(d7213314-3a43-40f9-b6f0-92bfefc34ae3) + ] + interface IBluetoothLEAdvertisementDataSection : IInspectable + { + [propget] HRESULT DataType([out, retval] BYTE *value); + [propput] HRESULT DataType([in] BYTE value); + [propget] HRESULT Data([out, retval] Windows.Storage.Streams.IBuffer **value); + [propput] HRESULT Data([in] Windows.Storage.Streams.IBuffer *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementDataSection), + uuid(e7a40942-a845-4045-bf7e-3e9971db8a6b) + ] + interface IBluetoothLEAdvertisementDataSectionFactory : IInspectable + { + HRESULT Create([in] BYTE type, [in] Windows.Storage.Streams.IBuffer *data, + [out, retval] Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementDataSection **value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + activatable(Windows.Foundation.UniversalApiContract, 1.0), + activatable(Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementDataSectionFactory, Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + threading(both) + ] + runtimeclass BluetoothLEAdvertisementDataSection + { + [default] interface Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementDataSection; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Bluetooth.Advertisement.BluetoothLEManufacturerData), + uuid(912dba18-6963-4533-b061-4694dafb34e5) + ] + interface IBluetoothLEManufacturerData : IInspectable + { + [propget] HRESULT CompanyId([out, retval] UINT16 *value); + [propput] HRESULT CompanyId([in] UINT16 value); + [propget] HRESULT Data([out, retval] Windows.Storage.Streams.IBuffer **value); + [propput] HRESULT Data([in] Windows.Storage.Streams.IBuffer *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Bluetooth.Advertisement.BluetoothLEManufacturerData), + uuid(c09b39f8-319a-441e-8de5-66a81e877a6c) + ] + interface IBluetoothLEManufacturerDataFactory : IInspectable + { + HRESULT Create([in] UINT16 id, [in] Windows.Storage.Streams.IBuffer *data, + [out, retval] Windows.Devices.Bluetooth.Advertisement.BluetoothLEManufacturerData **value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + activatable(Windows.Foundation.UniversalApiContract, 1.0), + activatable(Windows.Devices.Bluetooth.Advertisement.IBluetoothLEManufacturerDataFactory, Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + threading(both) + ] + runtimeclass BluetoothLEManufacturerData + { + [default] interface Windows.Devices.Bluetooth.Advertisement.IBluetoothLEManufacturerData; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcher), + uuid(a6ac336f-f3d3-4297-8d6c-c81ea6623f40) + ] + interface IBluetoothLEAdvertisementWatcher : IInspectable + { + [propget] HRESULT MinSamplingInterval([out, retval] Windows.Foundation.TimeSpan *value); + [propget] HRESULT MaxSamplingInterval([out, retval] Windows.Foundation.TimeSpan *value); + [propget] HRESULT MinOutOfRangeTimeout([out, retval] Windows.Foundation.TimeSpan *value); + [propget] HRESULT MaxOutOfRangeTimeout([out, retval] Windows.Foundation.TimeSpan *value); + [propget] HRESULT Status([out, retval] Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcherStatus *value); + [propget] HRESULT ScanningMode([out, retval] Windows.Devices.Bluetooth.Advertisement.BluetoothLEScanningMode *value); + [propput] HRESULT ScanningMode([in] Windows.Devices.Bluetooth.Advertisement.BluetoothLEScanningMode value); + [propget] HRESULT SignalStrengthFilter([out, retval] Windows.Devices.Bluetooth.BluetoothSignalStrengthFilter **value); + [propput] HRESULT SignalStrengthFilter([in] Windows.Devices.Bluetooth.BluetoothSignalStrengthFilter *value); + [propget] HRESULT AdvertisementFilter([out, retval] Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementFilter **value); + [propput] HRESULT AdvertisementFilter([in] Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementFilter *value); + HRESULT Start(); + HRESULT Stop(); + [eventadd] HRESULT Received([in] Windows.Foundation.TypedEventHandler<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcher *, Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementReceivedEventArgs *> *handler, + [out, retval] EventRegistrationToken *token); + [eventremove] HRESULT Received([in] EventRegistrationToken token); + [eventadd] HRESULT Stopped([in] Windows.Foundation.TypedEventHandler<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcher *, Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcherStoppedEventArgs *> *handler, + [out, retval] EventRegistrationToken *token); + [eventremove] HRESULT Stopped([in] EventRegistrationToken token); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcher), + uuid(01bf26bc-b164-5805-90a3-e8a7997ff225) + ] + interface IBluetoothLEAdvertisementWatcher2 : IInspectable + { + [propget] HRESULT AllowExtendedAdvertisements([out, retval] boolean *value); + [propput] HRESULT AllowExtendedAdvertisements([in] boolean value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcher), + uuid(9aaf2d56-39ac-453e-b32a-85c657e017f1) + ] + interface IBluetoothLEAdvertisementWatcherFactory : IInspectable + { + HRESULT Create([in] Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementFilter *filter, + [out, retval] Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcher **value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + activatable(Windows.Foundation.UniversalApiContract, 1.0), + activatable(Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementWatcherFactory, Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + threading(both) + ] + runtimeclass BluetoothLEAdvertisementWatcher + { + [default] interface Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementWatcher; + [contract(Windows.Foundation.UniversalApiContract, 10.0)] interface Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementWatcher2; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementFilter), + uuid(131eb0d3-d04e-47b1-837e-49405bf6f80f) + ] + interface IBluetoothLEAdvertisementFilter : IInspectable + { + [propget] HRESULT Advertisement([out, retval] Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisement **value); + [propput] HRESULT Advertisement([in] Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisement *value); + [propget] HRESULT BytePatterns([out, retval] Windows.Foundation.Collections.IVector<Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementBytePattern *> **value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + activatable(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + threading(both) + ] + runtimeclass BluetoothLEAdvertisementFilter + { + [default] interface Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementFilter; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementReceivedEventArgs), + uuid(27987ddf-e596-41be-8d43-9e6731d4a913) + ] + interface IBluetoothLEAdvertisementReceivedEventArgs : IInspectable + { + [propget] HRESULT RawSignalStrengthInDBm([out, retval] INT16* value); + [propget] HRESULT BluetoothAddress([out, retval] UINT64 *value); + [propget] HRESULT AdvertisementType([out, retval] Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementType *value); + [propget] HRESULT Timestamp([out, retval] Windows.Foundation.DateTime *value); + [propget] HRESULT Advertisement([out, retval] Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisement **value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementReceivedEventArgs), + uuid(12d9c87b-0399-5f0e-a348-53b02b6b162e) + ] + interface IBluetoothLEAdvertisementReceivedEventArgs2 : IInspectable + { + [propget] HRESULT BluetoothAddressType([out, retval] Windows.Devices.Bluetooth.BluetoothAddressType *value); + [propget] HRESULT TransmitPowerLevelInDBm([out, retval] Windows.Foundation.IReference<INT16> **value); + [propget] HRESULT IsAnonymous([out, retval] boolean *value); + [propget] HRESULT IsConnectable([out, retval] boolean *value); + [propget] HRESULT IsScannable([out, retval] boolean *value); + [propget] HRESULT IsDirected([out, retval] boolean *value); + [propget] HRESULT IsScanResponse([out, retval] boolean *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + threading(both) + ] + runtimeclass BluetoothLEAdvertisementReceivedEventArgs + { + [default] interface Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementReceivedEventArgs; + [contract(Windows.Foundation.UniversalApiContract, 10.0)] interface Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementReceivedEventArgs2; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcherStoppedEventArgs), + uuid(dd40f84d-e7b9-43e3-9c04-0685d085fd8c) + ] + interface IBluetoothLEAdvertisementWatcherStoppedEventArgs : IInspectable + { + [propget] HRESULT Error([out, retval] Windows.Devices.Bluetooth.BluetoothError *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + threading(both) + ] + runtimeclass BluetoothLEAdvertisementWatcherStoppedEventArgs + { + [default] interface Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementWatcherStoppedEventArgs; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementBytePattern), + uuid(fbfad7f2-b9c5-4a08-bc51-502f8ef68a79) + ] + interface IBluetoothLEAdvertisementBytePattern : IInspectable + { + [propget] HRESULT DataType([out, retval] BYTE *value); + [propput] HRESULT DataType([in] BYTE value); + [propget] HRESULT Offset([out, retval] INT16 *value); + [propput] HRESULT Offset([in] INT16 value); + [propget] HRESULT Data([out, retval] Windows.Storage.Streams.IBuffer **value); + [propput] HRESULT Data([in] Windows.Storage.Streams.IBuffer *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementBytePattern), + uuid(c2e24d73-fd5c-4ec3-be2a-9ca6fa11b7bd) + ] + interface IBluetoothLEAdvertisementBytePatternFactory : IInspectable + { + HRESULT Create([in] BYTE type, [in] INT16 offset, [in] Windows.Storage.Streams.IBuffer *data, + [out, retval] Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementBytePattern **value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + activatable(Windows.Foundation.UniversalApiContract, 1.0), + activatable(Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementBytePatternFactory, Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + threading(both) + ] + runtimeclass BluetoothLEAdvertisementBytePattern + { + [default] interface Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementBytePattern; + } +} diff --git a/include/windows.devices.bluetooth.idl b/include/windows.devices.bluetooth.idl index ef14b25ba8c..9e27db46ca2 100644 --- a/include/windows.devices.bluetooth.idl +++ b/include/windows.devices.bluetooth.idl @@ -41,6 +41,7 @@ namespace Windows.Devices.Bluetooth { typedef enum BluetoothMinorClass BluetoothMinorClass; typedef enum BluetoothServiceCapabilities BluetoothServiceCapabilities; typedef enum BluetoothError BluetoothError; + typedef enum BluetoothAddressType BluetoothAddressType;
interface IBluetoothAdapter; interface IBluetoothAdapter2; @@ -65,12 +66,14 @@ namespace Windows.Devices.Bluetooth { interface IBluetoothLEDevice6; interface IBluetoothLEDeviceStatics; interface IBluetoothLEDeviceStatics2; + interface IBluetoothSignalStrengthFilter;
runtimeclass BluetoothAdapter; runtimeclass BluetoothClassOfDevice; runtimeclass BluetoothDevice; runtimeclass BluetoothDeviceId; runtimeclass BluetoothLEDevice; + runtimeclass BluetoothSignalStrengthFilter;
namespace Rfcomm { runtimeclass RfcommDeviceService; @@ -245,6 +248,17 @@ namespace Windows.Devices.Bluetooth { TransportNotSupported = 9, };
+ [ + contract(Windows.Foundation.UniversalApiContract, 2.0) + ] + enum BluetoothAddressType + { + Public = 0, + Random = 1, + [contract(Windows.Foundation.UniversalApiContract, 4.0)] + Unspecified = 2, + }; + [ contract(Windows.Foundation.UniversalApiContract, 4.0), exclusiveto(Windows.Devices.Bluetooth.BluetoothAdapter), @@ -473,4 +487,32 @@ namespace Windows.Devices.Bluetooth { [contract(Windows.Foundation.UniversalApiContract, 13.0)] interface Windows.Devices.Bluetooth.IBluetoothLEDevice6; interface Windows.Foundation.IClosable; } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Bluetooth.BluetoothSignalStrengthFilter), + uuid(df7b7391-6bb5-4cfe-90b1-5d7324edcf7f) + ] + interface IBluetoothSignalStrengthFilter : IInspectable + { + [propget] HRESULT InRangeThresholdInDBm([out, retval] Windows.Foundation.IReference<INT16> **value); + [propput] HRESULT InRangeThresholdInDBm([in] Windows.Foundation.IReference<INT16> *value); + [propget] HRESULT OutOfRangeThresholdInDBm([out, retval] Windows.Foundation.IReference<INT16> **value); + [propput] HRESULT OutOfRangeThresholdInDBm([in] Windows.Foundation.IReference<INT16> *value); + [propget] HRESULT OutOfRangeTimeout([out, retval] Windows.Foundation.IReference<Windows.Foundation.TimeSpan> **value); + [propput] HRESULT OutOfRangeTimeout([in] Windows.Foundation.IReference<Windows.Foundation.TimeSpan> *value); + [propget] HRESULT SamplingInterval([out, retval] Windows.Foundation.IReference<Windows.Foundation.TimeSpan> **value); + [propput] HRESULT SamplingInterval([in] Windows.Foundation.IReference<Windows.Foundation.TimeSpan> *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + activatable(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + threading(both) + ] + runtimeclass BluetoothSignalStrengthFilter + { + [default] interface Windows.Devices.Bluetooth.IBluetoothSignalStrengthFilter; + } }
From: Vibhav Pant vibhavp@gmail.com
--- .../tests/bluetooth.c | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+)
diff --git a/dlls/windows.devices.bluetooth/tests/bluetooth.c b/dlls/windows.devices.bluetooth/tests/bluetooth.c index 5b78e1e176d..17f78c1d8cf 100644 --- a/dlls/windows.devices.bluetooth/tests/bluetooth.c +++ b/dlls/windows.devices.bluetooth/tests/bluetooth.c @@ -32,7 +32,9 @@ #define WIDL_using_Windows_Networking #include "windows.networking.connectivity.h" #include "windows.networking.h" +#define WIDL_using_Windows_Devices_Bluetooth_Advertisement #define WIDL_using_Windows_Devices_Bluetooth +#include "windows.devices.bluetooth.advertisement.h" #include "windows.devices.bluetooth.rfcomm.h" #include "windows.devices.bluetooth.h"
@@ -337,6 +339,102 @@ static void test_BluetoothLEDeviceStatics( void ) IBluetoothLEDeviceStatics_Release( statics ); }
+static void test_BluetoothLEAdvertisementFilter( void ) +{ + static const WCHAR *class_name = RuntimeClass_Windows_Devices_Bluetooth_Advertisement_BluetoothLEAdvertisementFilter; + IVector_BluetoothLEAdvertisementBytePattern *patterns; + IBluetoothLEAdvertisementFilter *filter; + IBluetoothLEAdvertisement *adv; + IInspectable *inspectable; + HSTRING str; + HRESULT hr; + UINT32 len; + + WindowsCreateString( class_name, wcslen( class_name ), &str ); + hr = RoActivateInstance( str, &inspectable ); + WindowsDeleteString( str ); + todo_wine ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "got hr %#lx.\n", hr ); + if (hr == REGDB_E_CLASSNOTREG || hr == CLASS_E_CLASSNOTAVAILABLE) + { + todo_wine win_skip( "%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w( class_name ) ); + return; + } + + check_interface( inspectable, &IID_IUnknown ); + check_interface( inspectable, &IID_IInspectable ); + check_interface( inspectable, &IID_IAgileObject ); + + hr = IInspectable_QueryInterface( inspectable, &IID_IBluetoothLEAdvertisementFilter, (void **)&filter ); + IInspectable_Release( inspectable ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = IBluetoothLEAdvertisementFilter_get_Advertisement( filter, &adv ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( !!adv, "got adv %p\n", adv ); + if (SUCCEEDED( hr )) + { + IVector_BluetoothLEAdvertisementDataSection *sections; + IReference_BluetoothLEAdvertisementFlags *flags; + IVector_BluetoothLEManufacturerData *mfgs; + IVector_GUID *guids; + + check_interface( adv, &IID_IAgileObject ); + + /* Advertisement should be empty */ + flags = (IReference_BluetoothLEAdvertisementFlags *)0xdeadbeef; + hr = IBluetoothLEAdvertisement_get_Flags( adv, &flags ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( !flags, "got flags %p.\n", flags ); + str = NULL; + hr = IBluetoothLEAdvertisement_get_LocalName( adv, &str ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( WindowsIsStringEmpty( str ), "got str %s.\n", debugstr_hstring( str ) ); + + hr = IBluetoothLEAdvertisement_get_ServiceUuids( adv, &guids ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + len = 0xdeadbeef; + hr = IVector_GUID_get_Size( guids, &len ); + IVector_GUID_Release( guids ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( !len, "got len %u.\n", len ); + + hr = IBluetoothLEAdvertisement_get_ManufacturerData( adv, &mfgs ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + len = 0xdeadbeef; + hr = IVector_BluetoothLEManufacturerData_get_Size( mfgs, &len ); + IVector_BluetoothLEManufacturerData_Release( mfgs ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( !len, "got len %u.\n", len ); + + hr = IBluetoothLEAdvertisement_get_DataSections( adv, §ions ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + len = 0xdeadbeef; + hr = IVector_BluetoothLEAdvertisementDataSection_get_Size( sections, &len ); + IVector_BluetoothLEAdvertisementDataSection_Release( sections ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( !len, "got len %u.\n", len ); + + hr = IBluetoothLEAdvertisementFilter_put_Advertisement( filter, adv ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IBluetoothLEAdvertisement_Release( adv ); + } + + hr = IBluetoothLEAdvertisementFilter_get_BytePatterns( filter, &patterns ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + if (SUCCEEDED( hr )) + { + check_interface( patterns, &IID_IAgileObject ); + check_interface( patterns, &IID_IIterable_BluetoothLEAdvertisementBytePattern ); + len = 0xdeadbeef; + hr = IVector_BluetoothLEAdvertisementBytePattern_get_Size( patterns, &len ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( !len, "got len %u.\n", len ); + IVector_BluetoothLEAdvertisementBytePattern_Release( patterns ); + } + + IBluetoothLEAdvertisementFilter_Release( filter ); +} + START_TEST(bluetooth) { HRESULT hr; @@ -347,6 +445,7 @@ START_TEST(bluetooth) test_BluetoothAdapterStatics(); test_BluetoothDeviceStatics(); test_BluetoothLEDeviceStatics(); + test_BluetoothLEAdvertisementFilter();
RoUninitialize(); }
From: Vibhav Pant vibhavp@gmail.com
--- .../tests/bluetooth.c | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+)
diff --git a/dlls/windows.devices.bluetooth/tests/bluetooth.c b/dlls/windows.devices.bluetooth/tests/bluetooth.c index 17f78c1d8cf..57802ff8bff 100644 --- a/dlls/windows.devices.bluetooth/tests/bluetooth.c +++ b/dlls/windows.devices.bluetooth/tests/bluetooth.c @@ -29,6 +29,8 @@ #define WIDL_using_Windows_Foundation #define WIDL_using_Windows_Foundation_Collections #include "windows.foundation.h" +#define WIDL_using_Windows_Storage_Streams +#include "windows.storage.streams.h" #define WIDL_using_Windows_Networking #include "windows.networking.connectivity.h" #include "windows.networking.h" @@ -435,6 +437,76 @@ static void test_BluetoothLEAdvertisementFilter( void ) IBluetoothLEAdvertisementFilter_Release( filter ); }
+static void test_BluetoothLEAdvertisementBytePattern( void ) +{ + static const WCHAR *class_name = RuntimeClass_Windows_Devices_Bluetooth_Advertisement_BluetoothLEAdvertisementBytePattern; + IBluetoothLEAdvertisementBytePattern *pattern; + IInspectable *inspectable; + INT16 int16 = 0; + IBuffer *data; + BYTE byte = 0; + HSTRING str; + HRESULT hr; + + WindowsCreateString( class_name, wcslen( class_name ), &str ); + hr = RoActivateInstance( str, &inspectable ); + WindowsDeleteString( str ); + todo_wine ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "got hr %#lx.\n", hr ); + if (hr == REGDB_E_CLASSNOTREG || hr == CLASS_E_CLASSNOTAVAILABLE) + { + todo_wine win_skip( "%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w( class_name ) ); + return; + } + + check_interface( inspectable, &IID_IUnknown ); + check_interface( inspectable, &IID_IInspectable ); + check_interface( inspectable, &IID_IAgileObject ); + + hr = IInspectable_QueryInterface( inspectable, &IID_IBluetoothLEAdvertisementBytePattern, (void **)&pattern ); + IInspectable_Release( inspectable ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + byte = 0xff; + hr = IBluetoothLEAdvertisementBytePattern_get_DataType( pattern, &byte ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( !byte, "got byte %#x\n", byte ); + hr = IBluetoothLEAdvertisementBytePattern_put_DataType( pattern, 0xff ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + byte = 0; + hr = IBluetoothLEAdvertisementBytePattern_get_DataType( pattern, &byte ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( byte == 0xff, "got byte %#x\n", byte ); + + int16 = 0xffff; + hr = IBluetoothLEAdvertisementBytePattern_get_Offset( pattern, &int16 ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( !int16, "got int16 %#x\n", int16 ); + hr = IBluetoothLEAdvertisementBytePattern_put_Offset( pattern, 0xffff ); + todo_wine ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + hr = IBluetoothLEAdvertisementBytePattern_put_Offset( pattern, 254 ); /* Maximum offset is 253 */ + todo_wine ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + hr = IBluetoothLEAdvertisementBytePattern_put_Offset( pattern, -1 ); + todo_wine ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + hr = IBluetoothLEAdvertisementBytePattern_put_Offset( pattern, 253 ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IBluetoothLEAdvertisementBytePattern_get_Offset( pattern, &int16 ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( int16 == 253, "got int16 %#x\n", int16 ); + + data = NULL; + hr = IBluetoothLEAdvertisementBytePattern_get_Data( pattern, &data ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( !!data, "got data %p\n", data ); + if (data) + { + check_interface( data, &IID_IAgileObject ); + hr = IBluetoothLEAdvertisementBytePattern_put_Data( pattern, data ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + IBuffer_Release( data ); + } + IBluetoothLEAdvertisementBytePattern_Release( pattern ); +} + START_TEST(bluetooth) { HRESULT hr; @@ -446,6 +518,7 @@ START_TEST(bluetooth) test_BluetoothDeviceStatics(); test_BluetoothLEDeviceStatics(); test_BluetoothLEAdvertisementFilter(); + test_BluetoothLEAdvertisementBytePattern();
RoUninitialize(); }
From: Vibhav Pant vibhavp@gmail.com
--- .../tests/bluetooth.c | 137 +++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-)
diff --git a/dlls/windows.devices.bluetooth/tests/bluetooth.c b/dlls/windows.devices.bluetooth/tests/bluetooth.c index 57802ff8bff..cbd6a4aa717 100644 --- a/dlls/windows.devices.bluetooth/tests/bluetooth.c +++ b/dlls/windows.devices.bluetooth/tests/bluetooth.c @@ -25,11 +25,12 @@ #include "winstring.h"
#include "roapi.h" +#define WIDL_using_Windows_Storage_Streams +#include "robuffer.h"
#define WIDL_using_Windows_Foundation #define WIDL_using_Windows_Foundation_Collections #include "windows.foundation.h" -#define WIDL_using_Windows_Storage_Streams #include "windows.storage.streams.h" #define WIDL_using_Windows_Networking #include "windows.networking.connectivity.h" @@ -507,6 +508,139 @@ static void test_BluetoothLEAdvertisementBytePattern( void ) IBluetoothLEAdvertisementBytePattern_Release( pattern ); }
+static void test_BluetoothLEAdvertisementDataSection( void ) +{ + static const WCHAR *class_name = RuntimeClass_Windows_Devices_Bluetooth_Advertisement_BluetoothLEAdvertisementDataSection; + IBluetoothLEAdvertisementDataSectionFactory *section_factory; + IBluetoothLEAdvertisementDataSection *section; + IBufferFactory *buffer_factory; + static const char exp_bytes[] = "Wine is not an emulator."; + IBufferByteAccess *byte_access; + IActivationFactory *factory; + IInspectable *inspectable; + IBuffer *data; + BYTE *bytes; + HSTRING str; + HRESULT hr; + UINT32 len; + BYTE type; + + WindowsCreateString( class_name, wcslen( class_name ), &str ); + hr = RoGetActivationFactory( str, &IID_IActivationFactory, (void **)&factory ); + WindowsDeleteString( str ); + todo_wine ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "got hr %#lx.\n", hr ); + if (hr == REGDB_E_CLASSNOTREG || hr == CLASS_E_CLASSNOTAVAILABLE) + { + todo_wine win_skip( "%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w( class_name ) ); + return; + } + + check_interface( factory, &IID_IAgileObject ); + hr = IActivationFactory_ActivateInstance( factory, &inspectable ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + check_interface( inspectable, &IID_IUnknown ); + check_interface( inspectable, &IID_IInspectable ); + check_interface( inspectable, &IID_IAgileObject ); + + hr = IInspectable_QueryInterface( inspectable, &IID_IBluetoothLEAdvertisementDataSection, (void **)§ion ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IInspectable_Release( inspectable ); + + type = 0xff; + hr = IBluetoothLEAdvertisementDataSection_get_DataType( section, &type ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( !type, "got type %#x\n", type ); + hr = IBluetoothLEAdvertisementDataSection_put_DataType( section, 0xff ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + type = 0; + hr = IBluetoothLEAdvertisementDataSection_get_DataType( section, &type ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( type == 0xff, "got type %#x\n", type ); + + data = NULL; + hr = IBluetoothLEAdvertisementDataSection_get_Data( section, &data ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( !!data, "got data %p\n", data ); + if (SUCCEEDED( hr )) + { + check_interface( data, &IID_IAgileObject ); + len = 0xdeadbeef; + hr = IBuffer_get_Length( data, &len ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( !len, "got len %u\n", len ); + + hr = IBluetoothLEAdvertisementDataSection_put_Data( section, data ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + IBuffer_Release( data ); + } + IBluetoothLEAdvertisementDataSection_Release( section ); + + hr = IActivationFactory_QueryInterface( factory, &IID_IBluetoothLEAdvertisementDataSectionFactory, (void **)§ion_factory ); + IActivationFactory_Release( factory ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + if (FAILED( hr )) + { + skip( "Could not get IBluetoothLEAdvertisementDataSectionFactory.\n" ); + return; + } + + class_name = RuntimeClass_Windows_Storage_Streams_Buffer; + WindowsCreateString( class_name, wcslen( class_name ), &str ); + hr = RoGetActivationFactory( str, &IID_IBufferFactory, (void **)&buffer_factory ); + WindowsDeleteString( str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = IBufferFactory_Create( buffer_factory, sizeof( exp_bytes ), &data ); + IBufferFactory_Release( buffer_factory ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = IBuffer_put_Length( data, sizeof( exp_bytes ) ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = IBuffer_QueryInterface( data, &IID_IBufferByteAccess, (void **)&byte_access ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IBufferByteAccess_Buffer( byte_access, &bytes ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + memcpy( bytes, exp_bytes, sizeof( exp_bytes ) ); + IBufferByteAccess_Release( byte_access ); + + check_interface( section_factory, &IID_IAgileObject ); + hr = IBluetoothLEAdvertisementDataSectionFactory_Create( section_factory, 0xff, data, §ion ); + IBuffer_Release( data ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + if (FAILED( hr )) + { + skip( "Could not create IBluetoothLEAdvertisementDataSection, skipping.\n" ); + return; + } + + type = 0; + hr = IBluetoothLEAdvertisementDataSection_get_DataType( section, &type ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( type == 0xff, "got type %#x\n.", type ); + + hr = IBluetoothLEAdvertisementDataSection_get_Data( section, &data ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + if (SUCCEEDED( hr )) + { + hr = IBuffer_get_Length( data, &len ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( len == sizeof( exp_bytes ), "got len %u.\n", len ); + + hr = IBuffer_QueryInterface( data, &IID_IBufferByteAccess, (void **)&byte_access ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IBufferByteAccess_Buffer( byte_access, &bytes ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + if (len == sizeof( exp_bytes )) + ok( !memcmp( bytes, exp_bytes, len ), "got bytes %s\n", debugstr_an( (const char *)bytes, len ) ); + IBufferByteAccess_Release( byte_access ); + IBuffer_Release( data ); + } + + IBluetoothLEAdvertisementDataSection_Release( section ); +} + START_TEST(bluetooth) { HRESULT hr; @@ -519,6 +653,7 @@ START_TEST(bluetooth) test_BluetoothLEDeviceStatics(); test_BluetoothLEAdvertisementFilter(); test_BluetoothLEAdvertisementBytePattern(); + test_BluetoothLEAdvertisementDataSection();
RoUninitialize(); }
From: Vibhav Pant vibhavp@gmail.com
--- .../tests/bluetooth.c | 458 ++++++++++++++++++ 1 file changed, 458 insertions(+)
diff --git a/dlls/windows.devices.bluetooth/tests/bluetooth.c b/dlls/windows.devices.bluetooth/tests/bluetooth.c index cbd6a4aa717..a286e2987d1 100644 --- a/dlls/windows.devices.bluetooth/tests/bluetooth.c +++ b/dlls/windows.devices.bluetooth/tests/bluetooth.c @@ -16,6 +16,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include "winerror.h" #define COBJMACROS #include "initguid.h" #include <stdarg.h> @@ -134,6 +135,83 @@ static WINAPI IAsyncOperationCompletedHandler_IInspectable *inspectable_async_ha return &impl->iface; }
+struct inspectable_event_handler +{ + ITypedEventHandler_IInspectable_IInspectable iface; + const GUID *iid; + void (*callback)( IInspectable *, IInspectable *, void * ); + void *data; + LONG ref; +}; + +static inline struct inspectable_event_handler *impl_from_ITypedEventHandler_IInspectable_IInspectable( ITypedEventHandler_IInspectable_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct inspectable_event_handler, iface ); +} + +static HRESULT WINAPI inspectable_event_handler_QueryInterface( ITypedEventHandler_IInspectable_IInspectable *iface, REFIID iid, void **out ) +{ + struct inspectable_event_handler *impl = impl_from_ITypedEventHandler_IInspectable_IInspectable( iface ); + + if (winetest_debug > 1) trace( "(%p, %s, %p)\n", iface, debugstr_guid( iid ), out ); + if (IsEqualGUID( iid, &IID_IUnknown ) || IsEqualGUID( iid, &IID_IAgileObject) || IsEqualGUID( iid, impl->iid )) + { + ITypedEventHandler_IInspectable_IInspectable_AddRef((*out = &impl->iface.lpVtbl)); + return S_OK; + } + + *out = NULL; + if (winetest_debug > 1) trace( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + return E_NOINTERFACE; +} + +static ULONG WINAPI inspectable_event_handler_AddRef( ITypedEventHandler_IInspectable_IInspectable *iface ) +{ + struct inspectable_event_handler *impl = impl_from_ITypedEventHandler_IInspectable_IInspectable( iface ); + return InterlockedIncrement( &impl->ref ); +} + +static ULONG WINAPI inspectable_event_handler_Release( ITypedEventHandler_IInspectable_IInspectable *iface ) +{ + struct inspectable_event_handler *impl = impl_from_ITypedEventHandler_IInspectable_IInspectable( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + if (!ref) free( impl ); + return ref; +} + +static HRESULT WINAPI inspectable_event_handler_Invoke( ITypedEventHandler_IInspectable_IInspectable *iface, IInspectable *arg1, IInspectable *arg2 ) +{ + struct inspectable_event_handler *impl = impl_from_ITypedEventHandler_IInspectable_IInspectable( iface ); + + if (winetest_debug > 1) trace( "(%p, %p, %p)\n", iface, arg1, arg2 ); + impl->callback( arg1, arg2, impl->data ); + return S_OK; +} + +static const ITypedEventHandler_IInspectable_IInspectableVtbl inspectable_event_handler_vtbl = { + /* IUnknown */ + inspectable_event_handler_QueryInterface, + inspectable_event_handler_AddRef, + inspectable_event_handler_Release, + /* ITypedEventHandler<IInspectable *, IInspectable *> */ + inspectable_event_handler_Invoke +}; + +static ITypedEventHandler_IInspectable_IInspectable *inspectable_event_handler_create( REFIID iid, void (*callback)( IInspectable *, IInspectable *, void * ), + void *data ) +{ + struct inspectable_event_handler *handler; + + if (!(handler = calloc( 1, sizeof( *handler )))) return NULL; + handler->iface.lpVtbl = &inspectable_event_handler_vtbl; + handler->iid = iid; + handler->callback = callback; + handler->data = data; + handler->ref = 1; + return &handler->iface; +} + static void await_bluetoothledevice( int line, IAsyncOperation_BluetoothLEDevice *async ) { IAsyncOperationCompletedHandler_IInspectable *handler; @@ -641,6 +719,385 @@ static void test_BluetoothLEAdvertisementDataSection( void ) IBluetoothLEAdvertisementDataSection_Release( section ); }
+/* See https://www.bluetooth.com/specifications/assigned-numbers, 2.3, Common Data Types */ +#define BLE_AD_TYPE_FLAGS 0x01 +#define BLE_AD_TYPE_SHORT_LOCAL_NAME 0x08 +#define BLE_AD_TYPE_FULL_LOCAL_NAME 0x09 +#define BLE_AD_TYPE_MFG_SPECIFIC 0xFF + +#define test_advertisement_has_data_type( a, t ) test_advertisement_has_data_type_( __LINE__, (a), (t) ) +static BOOL test_advertisement_has_data_type_( int line, IBluetoothLEAdvertisement *adv, BYTE type ) +{ + IVectorView_BluetoothLEAdvertisementDataSection *section = NULL; + HRESULT hr; + + hr = IBluetoothLEAdvertisement_GetSectionsByType( adv, type, §ion ); + todo_wine ok_(__FILE__, line)( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok_(__FILE__, line)( !!section, "got section %p.\n", section ); + if (SUCCEEDED( hr )) + { + UINT32 len = 0; + + hr = IVectorView_BluetoothLEAdvertisementDataSection_get_Size( section, &len ); + IVectorView_BluetoothLEAdvertisementDataSection_Release( section ); + ok_(__FILE__, line)( hr == S_OK, "got hr %#lx.\n", hr ); + return !!len; + } + + return FALSE; +} + +static const char *debugstr_bluetooth_addr( INT64 addr ) +{ + const BYTE *bytes = (BYTE *)&addr; + return wine_dbg_sprintf( "%02X:%02X:%02X:%02X:%02X:%02X", bytes[5], bytes[4], bytes[3], bytes[2], bytes[1], bytes[0] ); +} + +struct adv_watcher_received_data +{ + LONG *stopped; + DWORD received; +}; + +static void test_watcher_advertisement_received( IInspectable *arg1, IInspectable *arg2, void *user_data ) +{ + IVector_BluetoothLEAdvertisementDataSection *data_sections = NULL; + IReference_BluetoothLEAdvertisementFlags *flags_ref = NULL; + struct adv_watcher_received_data *data = user_data; + IBluetoothLEAdvertisementReceivedEventArgs *event; + IVector_BluetoothLEManufacturerData *mfgs = NULL; + BluetoothLEAdvertisementType adv_type = 6; + IBluetoothLEAdvertisement *adv = NULL; + IVector_GUID *uuids = NULL; + FILETIME timestamp = {0}; + UINT32 len, mfgs_len = 0; + SYSTEMTIME st = {0}; + HSTRING name = NULL; + INT16 signal = 0; + UINT64 addr = 0; + WCHAR buf[256]; + BOOL success; + HRESULT hr; + + ok( !ReadNoFence( data->stopped ), "handler called after watcher was stopped.\n" ); + + data->received += 1; + winetest_push_context( "advertisement %lu", data->received ); + check_interface( arg1, &IID_IBluetoothLEAdvertisementWatcher ); + + hr = IInspectable_QueryInterface( arg2, &IID_IBluetoothLEAdvertisementReceivedEventArgs, (void **)&event ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( !!event, "got event %p.\n", event ); + + hr = IBluetoothLEAdvertisementReceivedEventArgs_get_RawSignalStrengthInDBm( event, &signal ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + trace( "raw signal strength: %d dBm.\n", signal ); + + hr = IBluetoothLEAdvertisementReceivedEventArgs_get_BluetoothAddress( event, &addr ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( addr, "got addr %012I64x\n", addr ); + trace( "address: %I64X (%s)\n", addr, debugstr_bluetooth_addr( addr ) ); + + hr = IBluetoothLEAdvertisementReceivedEventArgs_get_AdvertisementType( event, &adv_type ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( adv_type <= BluetoothLEAdvertisementType_Extended, "got adv_type %d\n", adv_type ); + trace( "advertisement type: %d\n", adv_type ); + + hr = IBluetoothLEAdvertisementReceivedEventArgs_get_Timestamp( event, (DateTime *)×tamp ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + success = FileTimeToSystemTime( ×tamp, &st ); + ok( success, "FileTimeToSystemTime failed: %#lx.\n", GetLastError() ); + success = SystemTimeToTzSpecificLocalTime( NULL, &st, &st ); + ok( success, "SystemTimeToTzSpecificLocalTime failed: %#lx.\n", GetLastError() ); + buf[0] = 0; + GetTimeFormatEx( NULL, TIME_FORCE24HOURFORMAT, &st, NULL, buf, ARRAY_SIZE( buf ) ); + trace("timestamp: %s\n", debugstr_w( buf )); + + hr = IBluetoothLEAdvertisementReceivedEventArgs_get_Advertisement( event, &adv ); + IBluetoothLEAdvertisementReceivedEventArgs_Release( event ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + if (FAILED( hr )) + { + skip( "get_Advertisement failed.\n" ); + winetest_pop_context(); + return; + } + + flags_ref = NULL; + hr = IBluetoothLEAdvertisement_get_Flags( adv, &flags_ref ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + if (flags_ref) + { + BluetoothLEAdvertisementFlags flags = 0; + + hr = IReference_BluetoothLEAdvertisementFlags_get_Value( flags_ref, &flags ); + IReference_BluetoothLEAdvertisementFlags_Release( flags_ref ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + trace( "flags: %#x\n", flags ); + if (flags) + todo_wine ok( test_advertisement_has_data_type( adv, BLE_AD_TYPE_FLAGS ), "missing data section for type %#x\n", BLE_AD_TYPE_FLAGS ); + } + + hr = IBluetoothLEAdvertisement_get_LocalName( adv, &name ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + trace( "name: %s\n", debugstr_hstring( name ) ); + if (!WindowsIsStringEmpty( name )) + todo_wine ok( test_advertisement_has_data_type( adv, BLE_AD_TYPE_SHORT_LOCAL_NAME ) || + test_advertisement_has_data_type( adv, BLE_AD_TYPE_FULL_LOCAL_NAME ), + "missing data sections for type %#x and %#x\n", BLE_AD_TYPE_SHORT_LOCAL_NAME, BLE_AD_TYPE_FULL_LOCAL_NAME ); + + hr = IBluetoothLEAdvertisement_get_ServiceUuids( adv, &uuids ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( !!uuids, "got uuids %p.\n", uuids ); + if (SUCCEEDED( hr )) + { + UINT32 copied = 0, i; + GUID *buf; + + len = 0; + hr = IVector_GUID_get_Size( uuids, &len ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + buf = calloc( len, sizeof( *buf ) ); + hr = IVector_GUID_GetMany( uuids, 0, len, buf, &copied ); + IVector_GUID_Release( uuids ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( copied == len, "got copied %u\n", copied ); + + for (i = 0; i < copied; i++) + trace( "uuids[%u]: %s\n", i, debugstr_guid( &buf[i] ) ); + free( buf ); + } + + hr = IBluetoothLEAdvertisement_get_ManufacturerData( adv, &mfgs ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( !!mfgs, "got mfgs %p.\n", mfgs ); + if (SUCCEEDED( hr )) + { + hr = IVector_BluetoothLEManufacturerData_get_Size( mfgs, &mfgs_len ); + IVector_BluetoothLEManufacturerData_Release( mfgs ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + trace( "manufacturer data sections: %u\n", mfgs_len ); + if (mfgs_len) + todo_wine ok( test_advertisement_has_data_type( adv, BLE_AD_TYPE_MFG_SPECIFIC ), "missing data section for type %#x\n", BLE_AD_TYPE_MFG_SPECIFIC ); + } + + hr = IBluetoothLEAdvertisement_get_DataSections( adv, &data_sections ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( !!data_sections, "got data_sections %p.\n", data_sections ); + if (SUCCEEDED( hr )) + { + UINT32 exp_len = mfgs_len; + + if (!WindowsIsStringEmpty( name )) + exp_len++; + len = 0; + /* All the above properties are derived from the raw data sections, so we can determine how many data sections we can at least expect. */ + hr = IVector_BluetoothLEAdvertisementDataSection_get_Size( data_sections, &len ); + IVector_BluetoothLEAdvertisementDataSection_Release( data_sections ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( len >= exp_len, "got len %u, should be >= %u\n", len, exp_len ); + } + winetest_pop_context(); + WindowsDeleteString( name ); + IBluetoothLEAdvertisement_Release( adv ); +} + +struct adv_watcher_stopped_data +{ + HANDLE event; + LONG called; + BOOLEAN no_radio; +}; + +static void test_watcher_stopped( IInspectable *arg1, IInspectable *arg2, void *param ) +{ + IBluetoothLEAdvertisementWatcherStoppedEventArgs *event; + BluetoothError error = BluetoothError_OtherError; + struct adv_watcher_stopped_data *data = param; + HRESULT hr; + + check_interface( arg1, &IID_IBluetoothLEAdvertisementWatcher ); + + hr = IInspectable_QueryInterface( arg2, &IID_IBluetoothLEAdvertisementWatcherStoppedEventArgs, (void **)&event ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = IBluetoothLEAdvertisementWatcherStoppedEventArgs_get_Error( event, &error ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( error == BluetoothError_Success || error == BluetoothError_RadioNotAvailable, "got error %d.\n", error ); + + if (error == BluetoothError_RadioNotAvailable) + data->no_radio = TRUE; + + ok( InterlockedIncrement( &data->called ) == 1, "handler called more than once.\n" ); + SetEvent( data->event ); +} + +static void test_BluetoothLEAdvertisementWatcher( void ) +{ + const WCHAR *class_name = RuntimeClass_Windows_Devices_Bluetooth_Advertisement_BluetoothLEAdvertisementWatcher; + ITypedEventHandler_IInspectable_IInspectable *received_handler, *stopped_handler; + EventRegistrationToken received_token = {0}, stopped_token = {0}; + struct adv_watcher_received_data received_data = {0}; + struct adv_watcher_stopped_data stopped_data = {0}; + IBluetoothSignalStrengthFilter *sig_filter = NULL; + BluetoothLEAdvertisementWatcherStatus status; + IBluetoothLEAdvertisementWatcher *watcher; + BluetoothLEScanningMode mode; + IInspectable *inspectable; + TimeSpan span; + HSTRING str; + HRESULT hr; + DWORD ret; + + WindowsCreateString( class_name, wcslen( class_name ), &str ); + hr = RoActivateInstance( str, &inspectable ); + WindowsDeleteString( str ); + todo_wine ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "got hr %#lx.\n", hr ); + if (hr == REGDB_E_CLASSNOTREG || hr == CLASS_E_CLASSNOTAVAILABLE) + { + todo_wine win_skip( "%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w( class_name ) ); + return; + } + + check_interface( inspectable, &IID_IUnknown ); + check_interface( inspectable, &IID_IInspectable ); + check_interface( inspectable, &IID_IAgileObject ); + + hr = IInspectable_QueryInterface( inspectable, &IID_IBluetoothLEAdvertisementWatcher, (void **)&watcher ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IInspectable_Release( inspectable ); + + span.Duration = 0; + hr = IBluetoothLEAdvertisementWatcher_get_MinSamplingInterval( watcher, &span ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( span.Duration == 1000000, "got Duration %I64d.\n", span.Duration ); + + span.Duration = 0; + hr = IBluetoothLEAdvertisementWatcher_get_MaxSamplingInterval( watcher, &span ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( span.Duration == 255000000, "got Duration %I64d.\n", span.Duration ); + + span.Duration = 0; + hr = IBluetoothLEAdvertisementWatcher_get_MinOutOfRangeTimeout( watcher, &span ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( span.Duration == 10000000, "got Duration %I64d.\n", span.Duration ); + + span.Duration = 0; + hr = IBluetoothLEAdvertisementWatcher_get_MaxOutOfRangeTimeout( watcher, &span ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( span.Duration == 600000000, "got Duration %I64d.\n", span.Duration ); + + status = BluetoothLEAdvertisementWatcherStatus_Aborted; + hr = IBluetoothLEAdvertisementWatcher_get_Status( watcher, &status ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( status == BluetoothLEAdvertisementWatcherStatus_Created, "got status %u.\n", status ); + + mode = BluetoothLEScanningMode_None; + hr = IBluetoothLEAdvertisementWatcher_get_ScanningMode( watcher, &mode ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( mode == BluetoothLEScanningMode_Passive, "got status %u.\n", status ); + + hr = IBluetoothLEAdvertisementWatcher_get_SignalStrengthFilter( watcher, &sig_filter ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( !!sig_filter, "got sig_filter %p.\n", sig_filter ); + if (SUCCEEDED( hr )) + { + IReference_INT16 *int16; + IReference_TimeSpan *span; + + check_interface( sig_filter, &IID_IAgileObject ); + + int16 = (IReference_INT16 *)0xdeadbeef; + hr = IBluetoothSignalStrengthFilter_get_InRangeThresholdInDBm( sig_filter, &int16 ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( !int16, "got int16 %p.\n", int16 ); + + int16 = (IReference_INT16 *)0xdeadbeef; + hr = IBluetoothSignalStrengthFilter_get_OutOfRangeThresholdInDBm( sig_filter, &int16 ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( !int16, "got int16 %p.\n", int16 ); + + span = (IReference_TimeSpan *)0xdeadbeef; + hr = IBluetoothSignalStrengthFilter_get_OutOfRangeTimeout( sig_filter, &span ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( !span, "got span %p.\n", span ); + + span = (IReference_TimeSpan *)0xdeadbeef; + hr = IBluetoothSignalStrengthFilter_get_SamplingInterval( sig_filter, &span ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( !span, "got span %p.\n", span ); + + IBluetoothSignalStrengthFilter_Release( sig_filter ); + } + + received_data.stopped = &stopped_data.called; + received_handler = inspectable_event_handler_create( &IID_ITypedEventHandler_BluetoothLEAdvertisementWatcher_BluetoothLEAdvertisementReceivedEventArgs, + test_watcher_advertisement_received, &received_data ); + ok( !!received_handler, "inspectable_event_handler_create failed.\n" ); + hr = IBluetoothLEAdvertisementWatcher_add_Received( watcher, + (ITypedEventHandler_BluetoothLEAdvertisementWatcher_BluetoothLEAdvertisementReceivedEventArgs *)received_handler, + &received_token ); + ITypedEventHandler_IInspectable_IInspectable_Release( received_handler ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + + stopped_data.event = CreateEventW( NULL, FALSE, FALSE, NULL ); + ok( !!stopped_data.event, "CreateEventW failed: %lu\n", GetLastError() ); + stopped_handler = inspectable_event_handler_create( &IID_ITypedEventHandler_BluetoothLEAdvertisementWatcher_BluetoothLEAdvertisementWatcherStoppedEventArgs, + test_watcher_stopped, &stopped_data ); + ok( !!stopped_handler, "inspectable_event_handler_create failed.\n" ); + hr = IBluetoothLEAdvertisementWatcher_add_Stopped( watcher, + (ITypedEventHandler_BluetoothLEAdvertisementWatcher_BluetoothLEAdvertisementWatcherStoppedEventArgs *)stopped_handler, + &stopped_token ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + ITypedEventHandler_IInspectable_IInspectable_Release( stopped_handler ); + + hr = IBluetoothLEAdvertisementWatcher_Start( watcher ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + + /* The watcher stops with the error BluetoothError_RadioNotAvailable if no BLE radios are available. */ + ret = WaitForSingleObject( stopped_data.event, 1000 ); + if (!ret) + { + skip( "No Bluetooth radios, skipping.\n" ); + ok( stopped_data.no_radio, "got no_radio %d.\n", stopped_data.no_radio ); + CloseHandle( stopped_data.event ); + IBluetoothLEAdvertisementWatcher_Release( watcher ); + return; + } + + /* Calling Start multiple times seems to not result in any errors. */ + hr = IBluetoothLEAdvertisementWatcher_Start( watcher ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + + /* Usually there are plenty of BLE devices advertising themselves at any given point in most places, but waiting for an extended period of time + * allows testing the watcher with custom advertisements as well. */ + if (winetest_interactive) + SleepEx( 10000, FALSE ); + + hr = IBluetoothLEAdvertisementWatcher_Stop( watcher ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + ret = WaitForSingleObject( stopped_data.event, 5000 ); + todo_wine ok( !ret, "got ret %lu.\n", ret ); + /* The watcher should not have stopped with BluetoothError_RadioNotAvailable. */ + ok( !stopped_data.no_radio, "got no_radio %d.\n", stopped_data.no_radio ); + + /* Calling Stop for a stopped watcher also does not result in any errors, but also does not dispatch any more Stopped events. */ + hr = IBluetoothLEAdvertisementWatcher_Stop( watcher ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + ret = WaitForSingleObject( stopped_data.event, 1000 ); + ok( ret == WAIT_TIMEOUT, "got ret %lu.\n", ret ); + + hr = IBluetoothLEAdvertisementWatcher_remove_Stopped( watcher, stopped_token ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IBluetoothLEAdvertisementWatcher_remove_Received( watcher, received_token ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + + trace( "Received %lu advertisement packets.\n", received_data.received ); + + CloseHandle( stopped_data.event ); + IBluetoothLEAdvertisementWatcher_Release( watcher ); +} + START_TEST(bluetooth) { HRESULT hr; @@ -654,6 +1111,7 @@ START_TEST(bluetooth) test_BluetoothLEAdvertisementFilter(); test_BluetoothLEAdvertisementBytePattern(); test_BluetoothLEAdvertisementDataSection(); + test_BluetoothLEAdvertisementWatcher();
RoUninitialize(); }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/windows.devices.bluetooth/Makefile.in | 1 + .../windows.devices.bluetooth/advertisement.c | 329 ++++++++++++++++++ dlls/windows.devices.bluetooth/classes.idl | 1 + dlls/windows.devices.bluetooth/main.c | 2 + dlls/windows.devices.bluetooth/private.h | 3 + .../tests/bluetooth.c | 4 +- 6 files changed, 338 insertions(+), 2 deletions(-) create mode 100644 dlls/windows.devices.bluetooth/advertisement.c
diff --git a/dlls/windows.devices.bluetooth/Makefile.in b/dlls/windows.devices.bluetooth/Makefile.in index 89f3fc78abc..237a54b04fc 100644 --- a/dlls/windows.devices.bluetooth/Makefile.in +++ b/dlls/windows.devices.bluetooth/Makefile.in @@ -2,6 +2,7 @@ MODULE = windows.devices.bluetooth.dll IMPORTS = combase
SOURCES = \ + advertisement.c \ bluetoothadapter.c \ bluetoothdevice.c \ classes.idl \ diff --git a/dlls/windows.devices.bluetooth/advertisement.c b/dlls/windows.devices.bluetooth/advertisement.c new file mode 100644 index 00000000000..9e08c8873f0 --- /dev/null +++ b/dlls/windows.devices.bluetooth/advertisement.c @@ -0,0 +1,329 @@ +/* windows.Devices.Bluetooth.Advertisement Implementation + * + * Copyright 2025 Vibhav Pant + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL( bluetooth ); + +struct adv_watcher_factory +{ + IActivationFactory IActivationFactory_iface; + LONG ref; +}; + +static inline struct adv_watcher_factory *impl_from_IActivationFactory( IActivationFactory *iface ) +{ + return CONTAINING_RECORD( iface, struct adv_watcher_factory, IActivationFactory_iface ); +} + +static HRESULT WINAPI adv_watcher_factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out ) +{ + struct adv_watcher_factory *impl = impl_from_IActivationFactory( iface ); + + TRACE( "(%p, %s, %p)\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IActivationFactory )) + { + IActivationFactory_AddRef(( *out = &impl->IActivationFactory_iface )); + return S_OK; + } + + *out = NULL; + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + return E_NOINTERFACE; +} + +static ULONG WINAPI adv_watcher_factory_AddRef( IActivationFactory *iface ) +{ + struct adv_watcher_factory *impl = impl_from_IActivationFactory( iface ); + TRACE( "(%p)\n", iface ); + return InterlockedIncrement( &impl->ref ); +} + +static ULONG WINAPI adv_watcher_factory_Release( IActivationFactory *iface ) +{ + struct adv_watcher_factory *impl = impl_from_IActivationFactory( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "(%p)\n", iface ); + return ref; +} + +static HRESULT WINAPI adv_watcher_factory_GetIids( IActivationFactory *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "(%p, %p, %p): stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_factory_GetRuntimeClassName( IActivationFactory *iface, HSTRING *class_name ) +{ + FIXME( "(%p, %p): stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_factory_GetTrustLevel( IActivationFactory *iface, TrustLevel *level ) +{ + FIXME( "(%p, %p): stub!\n", iface, level ); + return E_NOTIMPL; +} + +static HRESULT adv_watcher_create( IBluetoothLEAdvertisementWatcher **watcher ); + +static HRESULT WINAPI adv_watcher_factory_ActivateInstance( IActivationFactory *iface, IInspectable **instance ) +{ + TRACE( "(%p, %p)\n", iface, instance ); + return adv_watcher_create( (IBluetoothLEAdvertisementWatcher **)instance ); +} + +static const struct IActivationFactoryVtbl adv_watcher_factory_vtbl = +{ + adv_watcher_factory_QueryInterface, + adv_watcher_factory_AddRef, + adv_watcher_factory_Release, + /* IInspectable */ + adv_watcher_factory_GetIids, + adv_watcher_factory_GetRuntimeClassName, + adv_watcher_factory_GetTrustLevel, + /* IActivationFactory */ + adv_watcher_factory_ActivateInstance +}; + +static struct adv_watcher_factory adv_watcher_factory = +{ + {&adv_watcher_factory_vtbl}, + 1 +}; + +IActivationFactory *advertisement_watcher_factory = &adv_watcher_factory.IActivationFactory_iface; + +struct adv_watcher +{ + IBluetoothLEAdvertisementWatcher IBluetoothLEAdvertisementWatcher_iface; + LONG ref; +}; + +static inline struct adv_watcher *impl_from_IBluetoothLEAdvertisementWatcher( IBluetoothLEAdvertisementWatcher *iface ) +{ + return CONTAINING_RECORD( iface, struct adv_watcher, IBluetoothLEAdvertisementWatcher_iface ); +} + +static HRESULT WINAPI adv_watcher_QueryInterface( IBluetoothLEAdvertisementWatcher *iface, REFIID iid, void **out ) +{ + struct adv_watcher *impl = impl_from_IBluetoothLEAdvertisementWatcher( iface ); + + TRACE( "(%p, %s, %p)\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IBluetoothLEAdvertisementWatcher )) + { + IBluetoothLEAdvertisementWatcher_AddRef(( *out = &impl->IBluetoothLEAdvertisementWatcher_iface )); + return S_OK; + } + + *out = NULL; + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + return E_NOINTERFACE; +} + +static ULONG WINAPI adv_watcher_AddRef( IBluetoothLEAdvertisementWatcher *iface ) +{ + struct adv_watcher *impl = impl_from_IBluetoothLEAdvertisementWatcher( iface ); + TRACE( "(%p)\n", iface ); + return InterlockedIncrement( &impl->ref ); +} + +static ULONG WINAPI adv_watcher_Release( IBluetoothLEAdvertisementWatcher *iface ) +{ + struct adv_watcher *impl = impl_from_IBluetoothLEAdvertisementWatcher( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "(%p)\n", iface ); + return ref; +} + +static HRESULT WINAPI adv_watcher_GetIids( IBluetoothLEAdvertisementWatcher *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "(%p, %p, %p): stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_GetRuntimeClassName( IBluetoothLEAdvertisementWatcher *iface, HSTRING *class_name ) +{ + FIXME( "(%p, %p): stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_GetTrustLevel( IBluetoothLEAdvertisementWatcher *iface, TrustLevel *level ) +{ + FIXME( "(%p, %p): stub!\n", iface, level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_get_MinSamplingInternal( IBluetoothLEAdvertisementWatcher *iface, TimeSpan *value ) +{ + FIXME( "(%p, %p): stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_get_MaxSamplingInternal( IBluetoothLEAdvertisementWatcher *iface, TimeSpan *value ) +{ + FIXME( "(%p, %p): stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_get_MinOutOfRangeTimeout( IBluetoothLEAdvertisementWatcher *iface, TimeSpan *value ) +{ + FIXME( "(%p, %p): stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_get_MaxOutOfRangeTimeout( IBluetoothLEAdvertisementWatcher *iface, TimeSpan *value ) +{ + FIXME( "(%p, %p): stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_get_Status( IBluetoothLEAdvertisementWatcher *iface, BluetoothLEAdvertisementWatcherStatus *status ) +{ + FIXME( "(%p, %p): stub!\n", iface, status ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_get_ScanningMode( IBluetoothLEAdvertisementWatcher *iface, BluetoothLEScanningMode *value ) +{ + FIXME( "(%p, %p): stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_put_ScanningMode( IBluetoothLEAdvertisementWatcher *iface, BluetoothLEScanningMode value ) +{ + FIXME( "(%p, %d): stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_get_SignalStrengthFilter( IBluetoothLEAdvertisementWatcher *iface, IBluetoothSignalStrengthFilter **filter ) +{ + FIXME( "(%p, %p): stub!\n", iface, filter ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_put_SignalStrengthFilter( IBluetoothLEAdvertisementWatcher *iface, IBluetoothSignalStrengthFilter *filter ) +{ + FIXME( "(%p, %p): stub!\n", iface, filter ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_get_AdvertisementFilter( IBluetoothLEAdvertisementWatcher *iface, IBluetoothLEAdvertisementFilter **filter ) +{ + FIXME( "(%p, %p): stub!\n", iface, filter ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_put_AdvertisementFilter( IBluetoothLEAdvertisementWatcher *iface, IBluetoothLEAdvertisementFilter *filter ) +{ + FIXME( "(%p, %p): stub!\n", iface, filter ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_Start( IBluetoothLEAdvertisementWatcher *iface ) +{ + FIXME( "(%p): stub!\n", iface ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_Stop( IBluetoothLEAdvertisementWatcher *iface ) +{ + FIXME( "(%p): stub!\n", iface ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_add_Received( IBluetoothLEAdvertisementWatcher *iface, + ITypedEventHandler_BluetoothLEAdvertisementWatcher_BluetoothLEAdvertisementReceivedEventArgs *handler, + EventRegistrationToken *token ) +{ + FIXME( "(%p, %p, %p): stub!\n", iface, handler, token ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_remove_Received( IBluetoothLEAdvertisementWatcher *iface, EventRegistrationToken token ) +{ + FIXME( "(%p, %I64x): stub!\n", iface, token.value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI adv_watcher_add_Stopped( IBluetoothLEAdvertisementWatcher *iface, + ITypedEventHandler_BluetoothLEAdvertisementWatcher_BluetoothLEAdvertisementWatcherStoppedEventArgs *handler, + EventRegistrationToken *token ) +{ + FIXME( "(%p, %p, %p): stub!\n", iface, handler, token ); + return E_NOTIMPL; +} + + +static HRESULT WINAPI adv_watcher_remove_Stopped( IBluetoothLEAdvertisementWatcher *iface, EventRegistrationToken token ) +{ + FIXME( "(%p, %I64x): stub!\n", iface, token.value ); + return E_NOTIMPL; +} + +static const IBluetoothLEAdvertisementWatcherVtbl adv_watcher_vtbl = +{ + /* IUnknown */ + adv_watcher_QueryInterface, + adv_watcher_AddRef, + adv_watcher_Release, + /* IInspectable */ + adv_watcher_GetIids, + adv_watcher_GetRuntimeClassName, + adv_watcher_GetTrustLevel, + /* IBluetoothLEAdvertisementWatcher */ + adv_watcher_get_MinSamplingInternal, + adv_watcher_get_MaxSamplingInternal, + adv_watcher_get_MinOutOfRangeTimeout, + adv_watcher_get_MaxOutOfRangeTimeout, + adv_watcher_get_Status, + adv_watcher_get_ScanningMode, + adv_watcher_put_ScanningMode, + adv_watcher_get_SignalStrengthFilter, + adv_watcher_put_SignalStrengthFilter, + adv_watcher_get_AdvertisementFilter, + adv_watcher_put_AdvertisementFilter, + adv_watcher_Start, + adv_watcher_Stop, + adv_watcher_add_Received, + adv_watcher_remove_Received, + adv_watcher_add_Stopped, + adv_watcher_remove_Stopped +}; + +static HRESULT adv_watcher_create( IBluetoothLEAdvertisementWatcher **watcher ) +{ + struct adv_watcher *impl; + + if (!(impl = calloc( 1, sizeof( *impl ) ))) return E_OUTOFMEMORY; + impl->IBluetoothLEAdvertisementWatcher_iface.lpVtbl = &adv_watcher_vtbl; + impl->ref = 1; + *watcher = &impl->IBluetoothLEAdvertisementWatcher_iface; + return S_OK; +} diff --git a/dlls/windows.devices.bluetooth/classes.idl b/dlls/windows.devices.bluetooth/classes.idl index ae2b58ffa2d..a2874370e52 100644 --- a/dlls/windows.devices.bluetooth/classes.idl +++ b/dlls/windows.devices.bluetooth/classes.idl @@ -36,6 +36,7 @@ import "windows.networking.sockets.idl"; import "windows.storage.streams.idl";
#define DO_NO_IMPORTS +#include "windows.devices.bluetooth.advertisement.idl" #include "windows.devices.bluetooth.genericattributeprofile.idl" #include "windows.devices.bluetooth.rfcomm.idl" #include "windows.devices.bluetooth.idl" diff --git a/dlls/windows.devices.bluetooth/main.c b/dlls/windows.devices.bluetooth/main.c index 83fd2100f06..4bfbcd17c8e 100644 --- a/dlls/windows.devices.bluetooth/main.c +++ b/dlls/windows.devices.bluetooth/main.c @@ -44,6 +44,8 @@ HRESULT WINAPI DllGetActivationFactory( HSTRING classid, IActivationFactory **fa IActivationFactory_QueryInterface( bluetoothdevice_statics_factory, &IID_IActivationFactory, (void **)factory ); if (!wcscmp( buffer, RuntimeClass_Windows_Devices_Bluetooth_BluetoothLEDevice )) IActivationFactory_QueryInterface( bluetoothledevice_statics_factory, &IID_IActivationFactory, (void **)factory ); + if (!wcscmp( buffer, RuntimeClass_Windows_Devices_Bluetooth_Advertisement_BluetoothLEAdvertisementWatcher)) + IActivationFactory_QueryInterface( advertisement_watcher_factory, &IID_IActivationFactory, (void **)factory );
if (*factory) return S_OK; return CLASS_E_CLASSNOTAVAILABLE; diff --git a/dlls/windows.devices.bluetooth/private.h b/dlls/windows.devices.bluetooth/private.h index c72488c2edc..66dd1d34131 100644 --- a/dlls/windows.devices.bluetooth/private.h +++ b/dlls/windows.devices.bluetooth/private.h @@ -38,10 +38,13 @@ #define WIDL_using_Windows_Devices_Bluetooth #include "windows.devices.bluetooth.rfcomm.h" #include "windows.devices.bluetooth.h" +#define WIDL_using_Windows_Devices_Bluetooth_Advertisement +#include "windows.devices.bluetooth.advertisement.h"
extern IActivationFactory *bluetoothadapter_factory; extern IActivationFactory *bluetoothdevice_statics_factory; extern IActivationFactory *bluetoothledevice_statics_factory; +extern IActivationFactory *advertisement_watcher_factory;
#define DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \ static inline impl_type *impl_from( iface_type *iface ) \ diff --git a/dlls/windows.devices.bluetooth/tests/bluetooth.c b/dlls/windows.devices.bluetooth/tests/bluetooth.c index a286e2987d1..464ffd467ab 100644 --- a/dlls/windows.devices.bluetooth/tests/bluetooth.c +++ b/dlls/windows.devices.bluetooth/tests/bluetooth.c @@ -952,10 +952,10 @@ static void test_BluetoothLEAdvertisementWatcher( void ) WindowsCreateString( class_name, wcslen( class_name ), &str ); hr = RoActivateInstance( str, &inspectable ); WindowsDeleteString( str ); - todo_wine ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "got hr %#lx.\n", hr ); + ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "got hr %#lx.\n", hr ); if (hr == REGDB_E_CLASSNOTREG || hr == CLASS_E_CLASSNOTAVAILABLE) { - todo_wine win_skip( "%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w( class_name ) ); + win_skip( "%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w( class_name ) ); return; }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/windows.devices.bluetooth/advertisement.c | 10 ++++++---- dlls/windows.devices.bluetooth/tests/bluetooth.c | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/dlls/windows.devices.bluetooth/advertisement.c b/dlls/windows.devices.bluetooth/advertisement.c index 9e08c8873f0..4ab9b094e73 100644 --- a/dlls/windows.devices.bluetooth/advertisement.c +++ b/dlls/windows.devices.bluetooth/advertisement.c @@ -182,14 +182,16 @@ static HRESULT WINAPI adv_watcher_GetTrustLevel( IBluetoothLEAdvertisementWatche
static HRESULT WINAPI adv_watcher_get_MinSamplingInternal( IBluetoothLEAdvertisementWatcher *iface, TimeSpan *value ) { - FIXME( "(%p, %p): stub!\n", iface, value ); - return E_NOTIMPL; + TRACE( "(%p, %p)\n", iface, value ); + value->Duration = 1000000; + return S_OK; }
static HRESULT WINAPI adv_watcher_get_MaxSamplingInternal( IBluetoothLEAdvertisementWatcher *iface, TimeSpan *value ) { - FIXME( "(%p, %p): stub!\n", iface, value ); - return E_NOTIMPL; + TRACE( "(%p, %p)\n", iface, value ); + value->Duration = 255000000; + return S_OK; }
static HRESULT WINAPI adv_watcher_get_MinOutOfRangeTimeout( IBluetoothLEAdvertisementWatcher *iface, TimeSpan *value ) diff --git a/dlls/windows.devices.bluetooth/tests/bluetooth.c b/dlls/windows.devices.bluetooth/tests/bluetooth.c index 464ffd467ab..0772976de87 100644 --- a/dlls/windows.devices.bluetooth/tests/bluetooth.c +++ b/dlls/windows.devices.bluetooth/tests/bluetooth.c @@ -969,13 +969,13 @@ static void test_BluetoothLEAdvertisementWatcher( void )
span.Duration = 0; hr = IBluetoothLEAdvertisementWatcher_get_MinSamplingInterval( watcher, &span ); - todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); - todo_wine ok( span.Duration == 1000000, "got Duration %I64d.\n", span.Duration ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( span.Duration == 1000000, "got Duration %I64d.\n", span.Duration );
span.Duration = 0; hr = IBluetoothLEAdvertisementWatcher_get_MaxSamplingInterval( watcher, &span ); - todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); - todo_wine ok( span.Duration == 255000000, "got Duration %I64d.\n", span.Duration ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( span.Duration == 255000000, "got Duration %I64d.\n", span.Duration );
span.Duration = 0; hr = IBluetoothLEAdvertisementWatcher_get_MinOutOfRangeTimeout( watcher, &span );
From: Vibhav Pant vibhavp@gmail.com
--- dlls/windows.devices.bluetooth/advertisement.c | 10 ++++++---- dlls/windows.devices.bluetooth/tests/bluetooth.c | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/dlls/windows.devices.bluetooth/advertisement.c b/dlls/windows.devices.bluetooth/advertisement.c index 4ab9b094e73..ab0f82dcd45 100644 --- a/dlls/windows.devices.bluetooth/advertisement.c +++ b/dlls/windows.devices.bluetooth/advertisement.c @@ -196,14 +196,16 @@ static HRESULT WINAPI adv_watcher_get_MaxSamplingInternal( IBluetoothLEAdvertise
static HRESULT WINAPI adv_watcher_get_MinOutOfRangeTimeout( IBluetoothLEAdvertisementWatcher *iface, TimeSpan *value ) { - FIXME( "(%p, %p): stub!\n", iface, value ); - return E_NOTIMPL; + TRACE( "(%p, %p)\n", iface, value ); + value->Duration = 10000000; + return S_OK; }
static HRESULT WINAPI adv_watcher_get_MaxOutOfRangeTimeout( IBluetoothLEAdvertisementWatcher *iface, TimeSpan *value ) { - FIXME( "(%p, %p): stub!\n", iface, value ); - return E_NOTIMPL; + TRACE( "(%p, %p)\n", iface, value ); + value->Duration = 600000000; + return S_OK; }
static HRESULT WINAPI adv_watcher_get_Status( IBluetoothLEAdvertisementWatcher *iface, BluetoothLEAdvertisementWatcherStatus *status ) diff --git a/dlls/windows.devices.bluetooth/tests/bluetooth.c b/dlls/windows.devices.bluetooth/tests/bluetooth.c index 0772976de87..9ebe9322c44 100644 --- a/dlls/windows.devices.bluetooth/tests/bluetooth.c +++ b/dlls/windows.devices.bluetooth/tests/bluetooth.c @@ -979,13 +979,13 @@ static void test_BluetoothLEAdvertisementWatcher( void )
span.Duration = 0; hr = IBluetoothLEAdvertisementWatcher_get_MinOutOfRangeTimeout( watcher, &span ); - todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); - todo_wine ok( span.Duration == 10000000, "got Duration %I64d.\n", span.Duration ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( span.Duration == 10000000, "got Duration %I64d.\n", span.Duration );
span.Duration = 0; hr = IBluetoothLEAdvertisementWatcher_get_MaxOutOfRangeTimeout( watcher, &span ); - todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); - todo_wine ok( span.Duration == 600000000, "got Duration %I64d.\n", span.Duration ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( span.Duration == 600000000, "got Duration %I64d.\n", span.Duration );
status = BluetoothLEAdvertisementWatcherStatus_Aborted; hr = IBluetoothLEAdvertisementWatcher_get_Status( watcher, &status );