Needed for Revo Scan 5.
-- v5: windows.devices.bluetooth: Partially implement IBluetoothAdapterStatics::GetDeviceSelector(). windows.devices.bluetooth/tests: Add IBluetoothAdapterStatics::GetDeviceSelector() tests. windows.devices.bluetooth: Add IBluetoothAdapterStatics stub interface. windows.devices.bluetooth: Add stub DLL. include: Add windows.devices.bluetooth.idl file.
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
Needed by IBluetoothAdapter in windows.devices.bluetooth.idl. --- include/Makefile.in | 1 + include/windows.devices.radios.idl | 125 +++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 include/windows.devices.radios.idl
diff --git a/include/Makefile.in b/include/Makefile.in index e9f0aa8d5fb..9c135d0a6c7 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -810,6 +810,7 @@ SOURCES = \ windows.devices.enumeration.idl \ windows.devices.haptics.idl \ windows.devices.power.idl \ + windows.devices.radios.idl \ windows.foundation.collections.idl \ windows.foundation.idl \ windows.foundation.metadata.idl \ diff --git a/include/windows.devices.radios.idl b/include/windows.devices.radios.idl new file mode 100644 index 00000000000..ff710d86ae9 --- /dev/null +++ b/include/windows.devices.radios.idl @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2023 Mohamad Al-Jaf + * + * 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 + +import "inspectable.idl"; +import "asyncinfo.idl"; +import "eventtoken.idl"; +import "windowscontracts.idl"; +import "windows.foundation.idl"; + +namespace Windows.Devices.Radios { + typedef enum RadioAccessStatus RadioAccessStatus; + typedef enum RadioKind RadioKind; + typedef enum RadioState RadioState; + + interface IRadio; + interface IRadioStatics; + + runtimeclass Radio; + + declare { + interface Windows.Foundation.Collections.IIterable<Windows.Devices.Radios.Radio *>; + interface Windows.Foundation.Collections.IIterator<Windows.Devices.Radios.Radio *>; + interface Windows.Foundation.Collections.IVectorView<Windows.Devices.Radios.Radio *>; + interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Devices.Radios.Radio *>; + interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Devices.Radios.RadioAccessStatus>; + interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Foundation.Collections.IVectorView<Windows.Devices.Radios.Radio *> *>; + interface Windows.Foundation.IAsyncOperation<Windows.Devices.Radios.Radio *>; + interface Windows.Foundation.IAsyncOperation<Windows.Devices.Radios.RadioAccessStatus>; + interface Windows.Foundation.IAsyncOperation<Windows.Foundation.Collections.IVectorView<Windows.Devices.Radios.Radio *> *>; + interface Windows.Foundation.TypedEventHandler<Windows.Devices.Radios.Radio *, IInspectable *>; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0) + ] + enum RadioAccessStatus + { + Unspecified = 0, + Allowed = 1, + DeniedByUser = 2, + DeniedBySystem = 3, + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0) + ] + enum RadioKind + { + Other = 0, + WiFi = 1, + MobileBroadband = 2, + Bluetooth = 3, + FM = 4, + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0) + ] + enum RadioState + { + Unknown = 0, + On = 1, + Off = 2, + Disabled = 3, + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Radios.Radio), + uuid(252118df-b33e-416a-875f-1cf38ae2d83e) + ] + interface IRadio : IInspectable + { + HRESULT SetStateAsync([in] Windows.Devices.Radios.RadioState value, + [out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Radios.RadioAccessStatus> **retval); + [eventadd] HRESULT StateChanged([in] Windows.Foundation.TypedEventHandler<Windows.Devices.Radios.Radio *, IInspectable *> *handler, + [out, retval] EventRegistrationToken *cookie); + [eventremove] HRESULT StateChanged([in] EventRegistrationToken cookie); + [propget] HRESULT State([out, retval] Windows.Devices.Radios.RadioState **value); + [propget] HRESULT Name([out, retval] HSTRING *value); + [propget] HRESULT Kind([out, retval] Windows.Devices.Radios.RadioKind *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Radios.Radio), + uuid(5fb6a12e-67cb-46ae-aae9-65919f86eff4) + ] + interface IRadioStatics : IInspectable + { + HRESULT GetRadiosAsync([out, retval] Windows.Foundation.IAsyncOperation<Windows.Foundation.Collections.IVectorView<Windows.Devices.Radios.Radio *> *> **value); + HRESULT GetDeviceSelector([out, retval] HSTRING *selector); + [overload("FromIdAsync")] HRESULT FromIdAsync([in] HSTRING id, [out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Radios.Radio *> **value); + HRESULT RequestAccessAsync([out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Radios.RadioAccessStatus> **value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + static(Windows.Devices.Radios.IRadioStatics, Windows.Foundation.UniversalApiContract, 1.0) + ] + runtimeclass Radio + { + [default] interface Windows.Devices.Radios.IRadio; + } +}
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- include/Makefile.in | 1 + include/windows.devices.bluetooth.idl | 89 +++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 include/windows.devices.bluetooth.idl
diff --git a/include/Makefile.in b/include/Makefile.in index 9c135d0a6c7..48f43dfa372 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -807,6 +807,7 @@ SOURCES = \ windef.h \ windns.h \ windot11.h \ + windows.devices.bluetooth.idl \ windows.devices.enumeration.idl \ windows.devices.haptics.idl \ windows.devices.power.idl \ diff --git a/include/windows.devices.bluetooth.idl b/include/windows.devices.bluetooth.idl new file mode 100644 index 00000000000..c3b64ce058a --- /dev/null +++ b/include/windows.devices.bluetooth.idl @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2023 Mohamad Al-Jaf + * + * 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 + +import "inspectable.idl"; +import "asyncinfo.idl"; +import "eventtoken.idl"; +import "windowscontracts.idl"; +import "windows.foundation.idl"; +/* import "windows.devices.bluetooth.genericattributeprofile.idl"; */ +/* import "windows.devices.bluetooth.rfcomm.idl"; */ +import "windows.devices.enumeration.idl"; +import "windows.devices.radios.idl"; +/* import "windows.networking.idl"; */ +import "windows.storage.streams.idl"; + +namespace Windows.Devices.Bluetooth { + interface IBluetoothAdapter; + interface IBluetoothAdapter2; + interface IBluetoothAdapter3; + interface IBluetoothAdapterStatics; + + runtimeclass BluetoothAdapter; + + declare { + interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Devices.Bluetooth.BluetoothAdapter *>; + interface Windows.Foundation.IAsyncOperation<Windows.Devices.Bluetooth.BluetoothAdapter *>; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 4.0), + exclusiveto(Windows.Devices.Bluetooth.BluetoothAdapter), + uuid(7974f04c-5f7a-4a34-9225-a855f84b1a8b) + ] + interface IBluetoothAdapter : IInspectable + { + [propget] HRESULT DeviceId([out, retval] HSTRING *value); + [propget] HRESULT BluetoothAddress([out, retval] UINT64 *value); + [propget] HRESULT IsClassicSupported([out, retval] boolean *value); + [propget] HRESULT IsLowEnergySupported([out, retval] boolean *value); + [propget] HRESULT IsPeripheralRoleSupported([out, retval] boolean *value); + [propget] HRESULT IsCentralRoleSupported([out, retval] boolean *value); + [propget] HRESULT IsAdvertisementOffloadSupported([out, retval] boolean *value); + HRESULT GetRadioAsync([out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Radios.Radio *> **operation); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 4.0), + exclusiveto(Windows.Devices.Bluetooth.BluetoothAdapter), + uuid(8b02fb6a-ac4c-4741-8661-8eab7d17ea9f) + ] + interface IBluetoothAdapterStatics : IInspectable + { + HRESULT GetDeviceSelector([out, retval] HSTRING *result); + HRESULT FromIdAsync([in] HSTRING id, [out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Bluetooth.BluetoothAdapter *> **operation); + HRESULT GetDefaultAsync([out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Bluetooth.BluetoothAdapter *> **operation); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 4.0), + marshaling_behavior(agile), + static(Windows.Devices.Bluetooth.IBluetoothAdapterStatics, Windows.Foundation.UniversalApiContract, 4.0), + threading(both) + ] + runtimeclass BluetoothAdapter + { + [default] interface Windows.Devices.Bluetooth.IBluetoothAdapter; + [contract(Windows.Foundation.UniversalApiContract, 6.0)] interface Windows.Devices.Bluetooth.IBluetoothAdapter2; + [contract(Windows.Foundation.UniversalApiContract, 10.0)] interface Windows.Devices.Bluetooth.IBluetoothAdapter3; + } +}
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- configure.ac | 2 + dlls/windows.devices.bluetooth/Makefile.in | 9 ++ .../bluetoothadapter.c | 116 ++++++++++++++++++ dlls/windows.devices.bluetooth/classes.idl | 23 ++++ dlls/windows.devices.bluetooth/main.c | 55 +++++++++ dlls/windows.devices.bluetooth/private.h | 40 ++++++ .../tests/Makefile.in | 5 + .../tests/bluetooth.c | 87 +++++++++++++ .../windows.devices.bluetooth.spec | 3 + 9 files changed, 340 insertions(+) create mode 100644 dlls/windows.devices.bluetooth/Makefile.in create mode 100644 dlls/windows.devices.bluetooth/bluetoothadapter.c create mode 100644 dlls/windows.devices.bluetooth/classes.idl create mode 100644 dlls/windows.devices.bluetooth/main.c create mode 100644 dlls/windows.devices.bluetooth/private.h create mode 100644 dlls/windows.devices.bluetooth/tests/Makefile.in create mode 100644 dlls/windows.devices.bluetooth/tests/bluetooth.c create mode 100644 dlls/windows.devices.bluetooth/windows.devices.bluetooth.spec
diff --git a/configure.ac b/configure.ac index 90c95c89ffb..c566123fa49 100644 --- a/configure.ac +++ b/configure.ac @@ -3139,6 +3139,8 @@ WINE_CONFIG_MAKEFILE(dlls/win32u/tests) WINE_CONFIG_MAKEFILE(dlls/win87em.dll16,enable_win16) WINE_CONFIG_MAKEFILE(dlls/winaspi.dll16,enable_win16) WINE_CONFIG_MAKEFILE(dlls/windebug.dll16,enable_win16) +WINE_CONFIG_MAKEFILE(dlls/windows.devices.bluetooth) +WINE_CONFIG_MAKEFILE(dlls/windows.devices.bluetooth/tests) WINE_CONFIG_MAKEFILE(dlls/windows.devices.enumeration) WINE_CONFIG_MAKEFILE(dlls/windows.devices.enumeration/tests) WINE_CONFIG_MAKEFILE(dlls/windows.gaming.input) diff --git a/dlls/windows.devices.bluetooth/Makefile.in b/dlls/windows.devices.bluetooth/Makefile.in new file mode 100644 index 00000000000..a7af5a1327d --- /dev/null +++ b/dlls/windows.devices.bluetooth/Makefile.in @@ -0,0 +1,9 @@ +MODULE = windows.devices.bluetooth.dll +IMPORTS = combase + +C_SRCS = \ + bluetoothadapter.c \ + main.c + +IDL_SRCS = \ + classes.idl diff --git a/dlls/windows.devices.bluetooth/bluetoothadapter.c b/dlls/windows.devices.bluetooth/bluetoothadapter.c new file mode 100644 index 00000000000..a165031293a --- /dev/null +++ b/dlls/windows.devices.bluetooth/bluetoothadapter.c @@ -0,0 +1,116 @@ +/* WinRT Windows.Devices.Bluetooth BluetoothAdapter Implementation + * + * Copyright (C) 2023 Mohamad Al-Jaf + * + * 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 bluetoothadapter +{ + IActivationFactory IActivationFactory_iface; + LONG ref; +}; + +static inline struct bluetoothadapter *impl_from_IActivationFactory( IActivationFactory *iface ) +{ + return CONTAINING_RECORD( iface, struct bluetoothadapter, IActivationFactory_iface ); +} + +static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out ) +{ + struct bluetoothadapter *impl = impl_from_IActivationFactory( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IActivationFactory )) + { + *out = &impl->IActivationFactory_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI factory_AddRef( IActivationFactory *iface ) +{ + struct bluetoothadapter *impl = impl_from_IActivationFactory( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI factory_Release( IActivationFactory *iface ) +{ + struct bluetoothadapter *impl = impl_from_IActivationFactory( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static HRESULT WINAPI factory_GetIids( IActivationFactory *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_GetRuntimeClassName( IActivationFactory *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_GetTrustLevel( IActivationFactory *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_ActivateInstance( IActivationFactory *iface, IInspectable **instance ) +{ + FIXME( "iface %p, instance %p stub!\n", iface, instance ); + return E_NOTIMPL; +} + +static const struct IActivationFactoryVtbl factory_vtbl = +{ + factory_QueryInterface, + factory_AddRef, + factory_Release, + /* IInspectable methods */ + factory_GetIids, + factory_GetRuntimeClassName, + factory_GetTrustLevel, + /* IActivationFactory methods */ + factory_ActivateInstance, +}; + +static struct bluetoothadapter bluetoothadapter_statics = +{ + {&factory_vtbl}, + 1, +}; + +IActivationFactory *bluetoothadapter_factory = &bluetoothadapter_statics.IActivationFactory_iface; diff --git a/dlls/windows.devices.bluetooth/classes.idl b/dlls/windows.devices.bluetooth/classes.idl new file mode 100644 index 00000000000..448b3920d4e --- /dev/null +++ b/dlls/windows.devices.bluetooth/classes.idl @@ -0,0 +1,23 @@ +/* + * Runtime Classes for windows.devices.bluetooth.dll + * + * Copyright (C) 2023 Mohamad Al-Jaf + * + * 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 + */ + +#pragma makedep register + +#include "windows.devices.bluetooth.idl" diff --git a/dlls/windows.devices.bluetooth/main.c b/dlls/windows.devices.bluetooth/main.c new file mode 100644 index 00000000000..532c9eeee0b --- /dev/null +++ b/dlls/windows.devices.bluetooth/main.c @@ -0,0 +1,55 @@ +/* WinRT Windows.Devices.Bluetooth Implementation + * + * Copyright (C) 2023 Mohamad Al-Jaf + * + * 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 "initguid.h" +#include "private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(bluetooth); + +static const char *debugstr_hstring( HSTRING hstr ) +{ + const WCHAR *str; + UINT32 len; + if (hstr && !((ULONG_PTR)hstr >> 16)) return "(invalid)"; + str = WindowsGetStringRawBuffer( hstr, &len ); + return wine_dbgstr_wn( str, len ); +} + +HRESULT WINAPI DllGetClassObject( REFCLSID clsid, REFIID riid, void **out ) +{ + FIXME( "clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), out ); + return CLASS_E_CLASSNOTAVAILABLE; +} + +HRESULT WINAPI DllGetActivationFactory( HSTRING classid, IActivationFactory **factory ) +{ + const WCHAR *buffer = WindowsGetStringRawBuffer( classid, NULL ); + + TRACE( "class %s, factory %p.\n", debugstr_hstring(classid), factory ); + + *factory = NULL; + + if (!wcscmp( buffer, RuntimeClass_Windows_Devices_Bluetooth_BluetoothAdapter )) + IActivationFactory_QueryInterface( bluetoothadapter_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 new file mode 100644 index 00000000000..d06bd6139e9 --- /dev/null +++ b/dlls/windows.devices.bluetooth/private.h @@ -0,0 +1,40 @@ +/* WinRT Windows.Devices.Bluetooth Implementation + * + * Copyright (C) 2023 Mohamad Al-Jaf + * + * 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 + */ + +#ifndef __WINE_WINDOWS_DEVICES_BLUETOOTH_PRIVATE_H +#define __WINE_WINDOWS_DEVICES_BLUETOOTH_PRIVATE_H + +#include <stdarg.h> + +#define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "winstring.h" + +#include "activation.h" + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#define WIDL_using_Windows_Devices_Bluetooth +#include "windows.devices.bluetooth.h" + +extern IActivationFactory *bluetoothadapter_factory; + +#endif diff --git a/dlls/windows.devices.bluetooth/tests/Makefile.in b/dlls/windows.devices.bluetooth/tests/Makefile.in new file mode 100644 index 00000000000..7925d0fec9c --- /dev/null +++ b/dlls/windows.devices.bluetooth/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = windows.devices.bluetooth.dll +IMPORTS = combase + +C_SRCS = \ + bluetooth.c diff --git a/dlls/windows.devices.bluetooth/tests/bluetooth.c b/dlls/windows.devices.bluetooth/tests/bluetooth.c new file mode 100644 index 00000000000..bb212ca6ac9 --- /dev/null +++ b/dlls/windows.devices.bluetooth/tests/bluetooth.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2023 Mohamad Al-Jaf + * + * 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 + */ + +#define COBJMACROS +#include "initguid.h" +#include <stdarg.h> + +#include "windef.h" +#include "winbase.h" +#include "winstring.h" + +#include "roapi.h" + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#define WIDL_using_Windows_Devices_Bluetooth +#include "windows.devices.bluetooth.h" + +#include "wine/test.h" + +#define check_interface( obj, iid ) check_interface_( __LINE__, obj, iid ) +static void check_interface_( unsigned int line, void *obj, const IID *iid ) +{ + IUnknown *iface = obj; + IUnknown *unk; + HRESULT hr; + + hr = IUnknown_QueryInterface( iface, iid, (void **)&unk ); + ok_(__FILE__, line)( hr == S_OK, "got hr %#lx.\n", hr ); + IUnknown_Release( unk ); +} + +static void test_BluetoothAdapterStatics(void) +{ + static const WCHAR *bluetoothadapter_statics_name = L"Windows.Devices.Bluetooth.BluetoothAdapter"; + IActivationFactory *factory; + HSTRING str; + HRESULT hr; + LONG ref; + + hr = WindowsCreateString( bluetoothadapter_statics_name, wcslen( bluetoothadapter_statics_name ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = RoGetActivationFactory( str, &IID_IActivationFactory, (void **)&factory ); + WindowsDeleteString( str ); + ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "got hr %#lx.\n", hr ); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip( "%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w( bluetoothadapter_statics_name ) ); + return; + } + + check_interface( factory, &IID_IUnknown ); + check_interface( factory, &IID_IInspectable ); + check_interface( factory, &IID_IAgileObject ); + + ref = IActivationFactory_Release( factory ); + ok( ref == 1, "got ref %ld.\n", ref ); +} + +START_TEST(bluetooth) +{ + HRESULT hr; + + hr = RoInitialize( RO_INIT_MULTITHREADED ); + ok( hr == S_OK, "RoInitialize failed, hr %#lx\n", hr ); + + test_BluetoothAdapterStatics(); + + RoUninitialize(); +} diff --git a/dlls/windows.devices.bluetooth/windows.devices.bluetooth.spec b/dlls/windows.devices.bluetooth/windows.devices.bluetooth.spec new file mode 100644 index 00000000000..31a5eafe950 --- /dev/null +++ b/dlls/windows.devices.bluetooth/windows.devices.bluetooth.spec @@ -0,0 +1,3 @@ +@ stdcall -private DllGetActivationFactory(ptr ptr) +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetClassObject(ptr ptr ptr)
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- .../bluetoothadapter.c | 44 +++++++++++++++++++ dlls/windows.devices.bluetooth/main.c | 2 +- dlls/windows.devices.bluetooth/private.h | 40 +++++++++++++++++ .../tests/bluetooth.c | 6 +++ 4 files changed, 91 insertions(+), 1 deletion(-)
diff --git a/dlls/windows.devices.bluetooth/bluetoothadapter.c b/dlls/windows.devices.bluetooth/bluetoothadapter.c index a165031293a..367cd464e42 100644 --- a/dlls/windows.devices.bluetooth/bluetoothadapter.c +++ b/dlls/windows.devices.bluetooth/bluetoothadapter.c @@ -25,6 +25,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(bluetooth); struct bluetoothadapter { IActivationFactory IActivationFactory_iface; + IBluetoothAdapterStatics IBluetoothAdapterStatics_iface; LONG ref; };
@@ -49,6 +50,13 @@ static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID return S_OK; }
+ if (IsEqualGUID( iid, &IID_IBluetoothAdapterStatics )) + { + *out = &impl->IBluetoothAdapterStatics_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); *out = NULL; return E_NOINTERFACE; @@ -107,9 +115,45 @@ static const struct IActivationFactoryVtbl factory_vtbl = factory_ActivateInstance, };
+DEFINE_IINSPECTABLE( bluetoothadapter_statics, IBluetoothAdapterStatics, struct bluetoothadapter, IActivationFactory_iface ) + +static HRESULT WINAPI bluetoothadapter_statics_GetDeviceSelector( IBluetoothAdapterStatics *iface, HSTRING *result ) +{ + FIXME( "iface %p, result %p stub!\n", iface, result ); + return E_NOTIMPL; +} + +static HRESULT WINAPI bluetoothadapter_statics_FromIdAsync( IBluetoothAdapterStatics *iface, HSTRING id, IAsyncOperation_BluetoothAdapter **operation ) +{ + FIXME( "iface %p, id %s, operation %p stub!\n", iface, debugstr_hstring(id), operation ); + return E_NOTIMPL; +} + +static HRESULT WINAPI bluetoothadapter_statics_GetDefaultAsync( IBluetoothAdapterStatics *iface, IAsyncOperation_BluetoothAdapter **operation ) +{ + FIXME( "iface %p, operation %p stub!\n", iface, operation ); + return E_NOTIMPL; +} + +static const struct IBluetoothAdapterStaticsVtbl bluetoothadapter_statics_vtbl = +{ + bluetoothadapter_statics_QueryInterface, + bluetoothadapter_statics_AddRef, + bluetoothadapter_statics_Release, + /* IInspectable methods */ + bluetoothadapter_statics_GetIids, + bluetoothadapter_statics_GetRuntimeClassName, + bluetoothadapter_statics_GetTrustLevel, + /* IBluetoothAdapterStatics methods */ + bluetoothadapter_statics_GetDeviceSelector, + bluetoothadapter_statics_FromIdAsync, + bluetoothadapter_statics_GetDefaultAsync, +}; + static struct bluetoothadapter bluetoothadapter_statics = { {&factory_vtbl}, + {&bluetoothadapter_statics_vtbl}, 1, };
diff --git a/dlls/windows.devices.bluetooth/main.c b/dlls/windows.devices.bluetooth/main.c index 532c9eeee0b..810b00d90fd 100644 --- a/dlls/windows.devices.bluetooth/main.c +++ b/dlls/windows.devices.bluetooth/main.c @@ -24,7 +24,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(bluetooth);
-static const char *debugstr_hstring( HSTRING hstr ) +const char *debugstr_hstring( HSTRING hstr ) { const WCHAR *str; UINT32 len; diff --git a/dlls/windows.devices.bluetooth/private.h b/dlls/windows.devices.bluetooth/private.h index d06bd6139e9..8840321443e 100644 --- a/dlls/windows.devices.bluetooth/private.h +++ b/dlls/windows.devices.bluetooth/private.h @@ -35,6 +35,46 @@ #define WIDL_using_Windows_Devices_Bluetooth #include "windows.devices.bluetooth.h"
+extern const char *debugstr_hstring( HSTRING hstr ); + extern IActivationFactory *bluetoothadapter_factory;
+#define DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \ + static inline impl_type *impl_from( iface_type *iface ) \ + { \ + return CONTAINING_RECORD( iface, impl_type, iface_mem ); \ + } \ + static HRESULT WINAPI pfx##_QueryInterface( iface_type *iface, REFIID iid, void **out ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_QueryInterface( (IInspectable *)(expr), iid, out ); \ + } \ + static ULONG WINAPI pfx##_AddRef( iface_type *iface ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_AddRef( (IInspectable *)(expr) ); \ + } \ + static ULONG WINAPI pfx##_Release( iface_type *iface ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_Release( (IInspectable *)(expr) ); \ + } \ + static HRESULT WINAPI pfx##_GetIids( iface_type *iface, ULONG *iid_count, IID **iids ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetIids( (IInspectable *)(expr), iid_count, iids ); \ + } \ + static HRESULT WINAPI pfx##_GetRuntimeClassName( iface_type *iface, HSTRING *class_name ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetRuntimeClassName( (IInspectable *)(expr), class_name ); \ + } \ + static HRESULT WINAPI pfx##_GetTrustLevel( iface_type *iface, TrustLevel *trust_level ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetTrustLevel( (IInspectable *)(expr), trust_level ); \ + } +#define DEFINE_IINSPECTABLE( pfx, iface_type, impl_type, base_iface ) \ + DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, &impl->base_iface ) + #endif diff --git a/dlls/windows.devices.bluetooth/tests/bluetooth.c b/dlls/windows.devices.bluetooth/tests/bluetooth.c index bb212ca6ac9..bf9e94dfb69 100644 --- a/dlls/windows.devices.bluetooth/tests/bluetooth.c +++ b/dlls/windows.devices.bluetooth/tests/bluetooth.c @@ -49,6 +49,7 @@ static void check_interface_( unsigned int line, void *obj, const IID *iid ) static void test_BluetoothAdapterStatics(void) { static const WCHAR *bluetoothadapter_statics_name = L"Windows.Devices.Bluetooth.BluetoothAdapter"; + IBluetoothAdapterStatics *bluetoothadapter_statics; IActivationFactory *factory; HSTRING str; HRESULT hr; @@ -70,6 +71,11 @@ static void test_BluetoothAdapterStatics(void) check_interface( factory, &IID_IInspectable ); check_interface( factory, &IID_IAgileObject );
+ hr = IActivationFactory_QueryInterface( factory, &IID_IBluetoothAdapterStatics, (void **)&bluetoothadapter_statics ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + ref = IBluetoothAdapterStatics_Release( bluetoothadapter_statics ); + ok( ref == 2, "got ref %ld.\n", ref ); ref = IActivationFactory_Release( factory ); ok( ref == 1, "got ref %ld.\n", ref ); }
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- .../tests/bluetooth.c | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/dlls/windows.devices.bluetooth/tests/bluetooth.c b/dlls/windows.devices.bluetooth/tests/bluetooth.c index bf9e94dfb69..8ee77bcf4ed 100644 --- a/dlls/windows.devices.bluetooth/tests/bluetooth.c +++ b/dlls/windows.devices.bluetooth/tests/bluetooth.c @@ -34,6 +34,15 @@
#include "wine/test.h"
+const char *debugstr_hstring( HSTRING hstr ) +{ + const WCHAR *str; + UINT32 len; + if (hstr && !((ULONG_PTR)hstr >> 16)) return "(invalid)"; + str = WindowsGetStringRawBuffer( hstr, &len ); + return wine_dbgstr_wn( str, len ); +} + #define check_interface( obj, iid ) check_interface_( __LINE__, obj, iid ) static void check_interface_( unsigned int line, void *obj, const IID *iid ) { @@ -48,11 +57,14 @@ static void check_interface_( unsigned int line, void *obj, const IID *iid )
static void test_BluetoothAdapterStatics(void) { + static const WCHAR *default_res = L"System.Devices.InterfaceClassGuid:="{92383B0E-F90E-4AC9-8D44-8C2D0D0EBDA2}" " + L"AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True"; static const WCHAR *bluetoothadapter_statics_name = L"Windows.Devices.Bluetooth.BluetoothAdapter"; IBluetoothAdapterStatics *bluetoothadapter_statics; IActivationFactory *factory; - HSTRING str; + HSTRING str, default_str; HRESULT hr; + INT32 res; LONG ref;
hr = WindowsCreateString( bluetoothadapter_statics_name, wcslen( bluetoothadapter_statics_name ), &str ); @@ -74,6 +86,18 @@ static void test_BluetoothAdapterStatics(void) hr = IActivationFactory_QueryInterface( factory, &IID_IBluetoothAdapterStatics, (void **)&bluetoothadapter_statics ); ok( hr == S_OK, "got hr %#lx.\n", hr );
+ hr = IBluetoothAdapterStatics_GetDeviceSelector( bluetoothadapter_statics, NULL ); + todo_wine ok( hr == E_POINTER, "got hr %#lx.\n", hr ); + hr = IBluetoothAdapterStatics_GetDeviceSelector( bluetoothadapter_statics, &str ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = WindowsCreateString( default_res, wcslen(default_res), &default_str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = WindowsCompareStringOrdinal( str, default_str, &res ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( !res, "got unexpected string %s.\n", debugstr_hstring(str) ); + + WindowsDeleteString( str ); + WindowsDeleteString( default_str ); ref = IBluetoothAdapterStatics_Release( bluetoothadapter_statics ); ok( ref == 2, "got ref %ld.\n", ref ); ref = IActivationFactory_Release( factory );
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
Needed for Revo Scan 5. --- dlls/windows.devices.bluetooth/bluetoothadapter.c | 9 +++++++-- dlls/windows.devices.bluetooth/tests/bluetooth.c | 8 ++++---- 2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/dlls/windows.devices.bluetooth/bluetoothadapter.c b/dlls/windows.devices.bluetooth/bluetoothadapter.c index 367cd464e42..7bace168719 100644 --- a/dlls/windows.devices.bluetooth/bluetoothadapter.c +++ b/dlls/windows.devices.bluetooth/bluetoothadapter.c @@ -119,8 +119,13 @@ DEFINE_IINSPECTABLE( bluetoothadapter_statics, IBluetoothAdapterStatics, struct
static HRESULT WINAPI bluetoothadapter_statics_GetDeviceSelector( IBluetoothAdapterStatics *iface, HSTRING *result ) { - FIXME( "iface %p, result %p stub!\n", iface, result ); - return E_NOTIMPL; + static const WCHAR *default_res = L"System.Devices.InterfaceClassGuid:="{92383B0E-F90E-4AC9-8D44-8C2D0D0EBDA2}" " + L"AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True"; + + FIXME( "iface %p, result %p semi-stub.\n", iface, result ); + + if (!result) return E_POINTER; + return WindowsCreateString( default_res, wcslen(default_res), result ); }
static HRESULT WINAPI bluetoothadapter_statics_FromIdAsync( IBluetoothAdapterStatics *iface, HSTRING id, IAsyncOperation_BluetoothAdapter **operation ) diff --git a/dlls/windows.devices.bluetooth/tests/bluetooth.c b/dlls/windows.devices.bluetooth/tests/bluetooth.c index 8ee77bcf4ed..dc1b61b6e2f 100644 --- a/dlls/windows.devices.bluetooth/tests/bluetooth.c +++ b/dlls/windows.devices.bluetooth/tests/bluetooth.c @@ -87,14 +87,14 @@ static void test_BluetoothAdapterStatics(void) ok( hr == S_OK, "got hr %#lx.\n", hr );
hr = IBluetoothAdapterStatics_GetDeviceSelector( bluetoothadapter_statics, NULL ); - todo_wine ok( hr == E_POINTER, "got hr %#lx.\n", hr ); + ok( hr == E_POINTER, "got hr %#lx.\n", hr ); hr = IBluetoothAdapterStatics_GetDeviceSelector( bluetoothadapter_statics, &str ); - todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); hr = WindowsCreateString( default_res, wcslen(default_res), &default_str ); ok( hr == S_OK, "got hr %#lx.\n", hr ); hr = WindowsCompareStringOrdinal( str, default_str, &res ); - todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); - todo_wine ok( !res, "got unexpected string %s.\n", debugstr_hstring(str) ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( !res, "got unexpected string %s.\n", debugstr_hstring(str) );
WindowsDeleteString( str ); WindowsDeleteString( default_str );
On Mon Jul 3 10:00:31 2023 +0000, Rémi Bernon wrote:
Nitpick but you could probably already add:
[contract(Windows.Foundation.UniversalApiContract, 6.0)] interface Windows.Devices.Bluetooth.IBluetoothAdapter2; [contract(Windows.Foundation.UniversalApiContract, 10.0)] interface Windows.Devices.Bluetooth.IBluetoothAdapter3;
So that the class definition is complete. It doesn't even need forward declarations but you can add them too if you want, just not the interface definitions.
Sure, added.
For `IBluetoothAdapterStatics::GetDeviceSelector()`, is it appropriate to call the current implementation partial or is it a full one? I'm not sure if there's a situation in which it doesn't return the same HSTRING.
It's called an Advanced Query Syntax (AQS) but there doesn't seem to be an API to actually generate it. Perhaps it's internal to Windows?
Just wondering if I should change the `FIXME` to a `TRACE`.
On Tue Jul 4 06:50:46 2023 +0000, Mohamad Al-Jaf wrote:
For `IBluetoothAdapterStatics::GetDeviceSelector()`, is it appropriate to call the current implementation partial or is it a full one? I'm not sure if there's a situation in which it doesn't return the same HSTRING. It's called an Advanced Query Syntax (AQS) but there doesn't seem to be an API to actually generate it. Perhaps it's internal to Windows? Just wondering if I should change the `FIXME` to a `TRACE`.
If you believe it's not doing anything else feel free to assume it's fully implemented.
This merge request was approved by Rémi Bernon.