-- v8: bluetoothapis: Implement BluetoothFindFirstRadio, BluetoothFindNextRadio, BluetoothFindRadioClose.
From: Vibhav Pant vibhavp@gmail.com
--- dlls/bluetoothapis/tests/sdp.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/dlls/bluetoothapis/tests/sdp.c b/dlls/bluetoothapis/tests/sdp.c index 6f3bba8360f..af22de9b665 100644 --- a/dlls/bluetoothapis/tests/sdp.c +++ b/dlls/bluetoothapis/tests/sdp.c @@ -33,6 +33,26 @@ static const char *debugstr_SDP_ELEMENT_DATA( const SDP_ELEMENT_DATA *data ) data->data.uint128.LowPart, data->data.uint128.HighPart ); }
+/* Returns the exact number of bytes we need to compare to test equality between the 'data' fields of two + * SDP_ELEMENT_DATA. */ +static SIZE_T sdp_type_size( SDP_TYPE type, SDP_SPECIFICTYPE st ) +{ + + switch (type) + { + case SDP_TYPE_NIL: + return 0; + case SDP_TYPE_BOOLEAN: + return sizeof( UCHAR ); + case SDP_TYPE_INT: + case SDP_TYPE_UINT: + case SDP_TYPE_UUID: + return 1 << ((st >> 8) & 0x7); + default: /* Container/Sequence-like types. */ + return sizeof( BYTE * ) + sizeof( ULONG ); + } +} + static void test_BluetoothSdpGetElementData( BYTE *stream, SIZE_T size, DWORD error, const SDP_ELEMENT_DATA *sdp_data ) { @@ -47,7 +67,7 @@ static void test_BluetoothSdpGetElementData( BYTE *stream, SIZE_T size, DWORD er ok( result.specificType == sdp_data->specificType, "%#x != %#x.\n", sdp_data->specificType, result.specificType ); - ok( !memcmp( &sdp_data->data, &result.data, sizeof( result.data ) ), + ok( !memcmp( &sdp_data->data, &result.data, sdp_type_size( result.type, result.specificType ) ), "%s != %s.\n", debugstr_SDP_ELEMENT_DATA( sdp_data ), debugstr_SDP_ELEMENT_DATA( &result ) ); }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/bluetoothapis/tests/Makefile.in | 1 + dlls/bluetoothapis/tests/radio.c | 71 ++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 dlls/bluetoothapis/tests/radio.c
diff --git a/dlls/bluetoothapis/tests/Makefile.in b/dlls/bluetoothapis/tests/Makefile.in index c2e8bc0377a..c7d6567f578 100644 --- a/dlls/bluetoothapis/tests/Makefile.in +++ b/dlls/bluetoothapis/tests/Makefile.in @@ -2,4 +2,5 @@ TESTDLL = bluetoothapis.dll IMPORTS = bluetoothapis
SOURCES = \ + radio.c \ sdp.c diff --git a/dlls/bluetoothapis/tests/radio.c b/dlls/bluetoothapis/tests/radio.c new file mode 100644 index 00000000000..8243c4a5d24 --- /dev/null +++ b/dlls/bluetoothapis/tests/radio.c @@ -0,0 +1,71 @@ +/* + * Tests for Bluetooth radio methods + * + * Copyright 2024 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 <stdarg.h> + +#include <windef.h> +#include <winbase.h> + +#include <bthsdpdef.h> +#include <bluetoothapis.h> + +#include <wine/test.h> + +void test_BluetoothFindFirstRadio( void ) +{ + HANDLE radio, dummy = (HANDLE)0xdeadbeef; + BLUETOOTH_FIND_RADIO_PARAMS find_params; + HBLUETOOTH_RADIO_FIND find; + DWORD err, exp; + + radio = dummy; + SetLastError( 0xdeadbeef ); + find = BluetoothFindFirstRadio( NULL, &radio ); + ok( !find, "Expected %p to be NULL\n", find ); + err = GetLastError(); + todo_wine ok( err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER ); + todo_wine ok( radio == dummy, "%p != %p\n", radio, dummy ); + + radio = dummy; + find_params.dwSize = 0; + SetLastError( 0xdeadbeef ); + find = BluetoothFindFirstRadio( &find_params, &radio ); + ok( !find, "Expected %p to be NULL\n", find ); + err = GetLastError(); + todo_wine ok( err == ERROR_REVISION_MISMATCH, "%lu != %d\n", err, ERROR_REVISION_MISMATCH ); + todo_wine ok( radio == dummy, "%p != %p\n", radio, dummy ); + + find_params.dwSize = sizeof( find_params ); + SetLastError( 0xdeadbeef ); + find = BluetoothFindFirstRadio( &find_params, &radio ); + err = GetLastError(); + exp = find ? ERROR_SUCCESS : ERROR_NO_MORE_ITEMS; + todo_wine ok( err == exp, "%lu != %lu\n", err, exp ); + if (find) + { + CloseHandle( radio ); + todo_wine ok( BluetoothFindRadioClose( find ), "BluetoothFindRadioClose failed: %lu\n", GetLastError() ); + } +} + +START_TEST( radio ) +{ + test_BluetoothFindFirstRadio(); +}
From: Vibhav Pant vibhavp@gmail.com
--- dlls/bluetoothapis/tests/radio.c | 41 ++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+)
diff --git a/dlls/bluetoothapis/tests/radio.c b/dlls/bluetoothapis/tests/radio.c index 8243c4a5d24..b9e50a2c97d 100644 --- a/dlls/bluetoothapis/tests/radio.c +++ b/dlls/bluetoothapis/tests/radio.c @@ -65,7 +65,48 @@ void test_BluetoothFindFirstRadio( void ) } }
+void test_BluetoothFindNextRadio( void ) +{ + HANDLE radio, dummy = (HANDLE)0xdeadbeef; + BLUETOOTH_FIND_RADIO_PARAMS find_params; + HBLUETOOTH_RADIO_FIND find; + DWORD err; + BOOL ret; + + find_params.dwSize = sizeof( find_params ); + find = BluetoothFindFirstRadio( &find_params, &radio ); + if (!find) + { + skip( "No Bluetooth radios found.\n" ); + return; + } + CloseHandle( radio ); + + radio = dummy; + SetLastError( 0xdeadbeef ); + ret = BluetoothFindNextRadio( NULL, &radio ); + todo_wine ok( !ret, "Expected BluetoothFindNextRadio to return FALSE\n" ); + err = GetLastError(); + todo_wine ok( err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE ); + todo_wine ok( radio == dummy, "%p != %p\n", radio, dummy ); + + for(;;) + { + SetLastError( 0xdeadbeef ); + ret = BluetoothFindNextRadio( find, &radio ); + if (!ret) + { + err = GetLastError(); + todo_wine ok( err == ERROR_NO_MORE_ITEMS, "%lu != %d\n", err, ERROR_NO_MORE_ITEMS ); + break; + } + CloseHandle( radio ); + } + todo_wine ok( BluetoothFindRadioClose( find ), "BluetoothFindRadioClose failed: %lu\n", GetLastError() ); +} + START_TEST( radio ) { test_BluetoothFindFirstRadio(); + test_BluetoothFindNextRadio(); }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/bluetoothapis/tests/radio.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/dlls/bluetoothapis/tests/radio.c b/dlls/bluetoothapis/tests/radio.c index b9e50a2c97d..9dccb885b00 100644 --- a/dlls/bluetoothapis/tests/radio.c +++ b/dlls/bluetoothapis/tests/radio.c @@ -105,8 +105,19 @@ void test_BluetoothFindNextRadio( void ) todo_wine ok( BluetoothFindRadioClose( find ), "BluetoothFindRadioClose failed: %lu\n", GetLastError() ); }
+void test_BluetoothFindRadioClose( void ) +{ + DWORD err; + + SetLastError( 0xdeadbeef ); + ok( !BluetoothFindRadioClose( NULL ), "Expected BluetoothFindRadioClose to return FALSE\n" ); + err = GetLastError(); + todo_wine ok( err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE ); +} + START_TEST( radio ) { test_BluetoothFindFirstRadio(); test_BluetoothFindNextRadio(); + test_BluetoothFindRadioClose(); }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/bluetoothapis/Makefile.in | 1 + dlls/bluetoothapis/main.c | 117 +++++++++++++++++++++++++++---- dlls/bluetoothapis/tests/radio.c | 24 +++---- 3 files changed, 118 insertions(+), 24 deletions(-)
diff --git a/dlls/bluetoothapis/Makefile.in b/dlls/bluetoothapis/Makefile.in index 1fd74074703..3e2e230fe55 100644 --- a/dlls/bluetoothapis/Makefile.in +++ b/dlls/bluetoothapis/Makefile.in @@ -1,5 +1,6 @@ MODULE = bluetoothapis.dll IMPORTLIB = bluetoothapis +IMPORTS = setupapi
EXTRADLLFLAGS = -Wb,--prefer-native
diff --git a/dlls/bluetoothapis/main.c b/dlls/bluetoothapis/main.c index 5d9087a9a47..076d758eb1a 100644 --- a/dlls/bluetoothapis/main.c +++ b/dlls/bluetoothapis/main.c @@ -22,13 +22,25 @@ #include <stdarg.h> #include <windef.h> #include <winbase.h> +#include <winuser.h> +#include <winreg.h>
#include "wine/debug.h" #include "bthsdpdef.h" #include "bluetoothapis.h" +#include "setupapi.h" + +#include "initguid.h" +#include "bthdef.h"
WINE_DEFAULT_DEBUG_CHANNEL(bluetoothapis);
+struct bluetooth_find_radio_handle +{ + HDEVINFO devinfo; + DWORD idx; +}; + /********************************************************************* * BluetoothFindFirstDevice */ @@ -43,22 +55,69 @@ HBLUETOOTH_DEVICE_FIND WINAPI BluetoothFindFirstDevice(BLUETOOTH_DEVICE_SEARCH_P /********************************************************************* * BluetoothFindFirstRadio */ -HBLUETOOTH_RADIO_FIND WINAPI BluetoothFindFirstRadio(BLUETOOTH_FIND_RADIO_PARAMS *params, HANDLE *radio) +HBLUETOOTH_RADIO_FIND WINAPI BluetoothFindFirstRadio( BLUETOOTH_FIND_RADIO_PARAMS *params, HANDLE *radio ) { - FIXME("(%p %p): stub!\n", params, radio); - *radio = NULL; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + struct bluetooth_find_radio_handle *find; + HANDLE device_ret; + DWORD err; + + TRACE( "(%p, %p)\n", params, radio ); + + if (!params) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return NULL; + } + if (params->dwSize != sizeof( *params )) + { + SetLastError( ERROR_REVISION_MISMATCH ); + return NULL; + } + if (!(find = calloc( 1, sizeof( *find ) ))) + { + SetLastError( ERROR_OUTOFMEMORY ); + return NULL; + } + + find->devinfo = SetupDiGetClassDevsW( &GUID_BTHPORT_DEVICE_INTERFACE, NULL, NULL, + DIGCF_PRESENT | DIGCF_DEVICEINTERFACE ); + if (find->devinfo == INVALID_HANDLE_VALUE) + { + free( find ); + return NULL; + } + + if (BluetoothFindNextRadio( find, &device_ret )) + { + *radio = device_ret; + return find; + } + + err = GetLastError(); + BluetoothFindRadioClose( find ); + SetLastError( err ); return NULL; }
/********************************************************************* * BluetoothFindRadioClose */ -BOOL WINAPI BluetoothFindRadioClose(HBLUETOOTH_RADIO_FIND find) +BOOL WINAPI BluetoothFindRadioClose( HBLUETOOTH_RADIO_FIND find_handle ) { - FIXME("(%p): stub!\n", find); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + struct bluetooth_find_radio_handle *find = find_handle; + + TRACE( "(%p)\n", find_handle ); + + if (!find_handle) + { + SetLastError( ERROR_INVALID_HANDLE ); + return FALSE; + } + + SetupDiDestroyDeviceInfoList( find->devinfo ); + free( find ); + SetLastError( ERROR_SUCCESS ); + return TRUE; }
/********************************************************************* @@ -74,11 +133,45 @@ BOOL WINAPI BluetoothFindDeviceClose(HBLUETOOTH_DEVICE_FIND find) /********************************************************************* * BluetoothFindNextRadio */ -BOOL WINAPI BluetoothFindNextRadio(HBLUETOOTH_RADIO_FIND find, HANDLE *radio) +BOOL WINAPI BluetoothFindNextRadio( HBLUETOOTH_RADIO_FIND find_handle, HANDLE *radio ) { - FIXME("(%p, %p): stub!\n", find, radio); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + char buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof( WCHAR )]; + struct bluetooth_find_radio_handle *find = find_handle; + SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_detail = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)buffer; + SP_DEVICE_INTERFACE_DATA iface_data; + HANDLE device_ret; + BOOL found; + + TRACE( "(%p, %p)\n", find_handle, radio ); + + if (!find_handle) + { + SetLastError( ERROR_INVALID_HANDLE ); + return FALSE; + } + + iface_detail->cbSize = sizeof( *iface_detail ); + iface_data.cbSize = sizeof( iface_data ); + found = FALSE; + while (SetupDiEnumDeviceInterfaces( find->devinfo, NULL, &GUID_BTHPORT_DEVICE_INTERFACE, find->idx++, + &iface_data )) + { + if (!SetupDiGetDeviceInterfaceDetailW( find->devinfo, &iface_data, iface_detail, sizeof( buffer ), NULL, + NULL )) + continue; + device_ret = CreateFileW( iface_detail->DevicePath, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); + if (device_ret != INVALID_HANDLE_VALUE) + { + found = TRUE; + break; + } + } + + if (found) + *radio = device_ret; + + return found; }
/********************************************************************* diff --git a/dlls/bluetoothapis/tests/radio.c b/dlls/bluetoothapis/tests/radio.c index 9dccb885b00..c175f110b5c 100644 --- a/dlls/bluetoothapis/tests/radio.c +++ b/dlls/bluetoothapis/tests/radio.c @@ -40,8 +40,8 @@ void test_BluetoothFindFirstRadio( void ) find = BluetoothFindFirstRadio( NULL, &radio ); ok( !find, "Expected %p to be NULL\n", find ); err = GetLastError(); - todo_wine ok( err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER ); - todo_wine ok( radio == dummy, "%p != %p\n", radio, dummy ); + ok( err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER ); + ok( radio == dummy, "%p != %p\n", radio, dummy );
radio = dummy; find_params.dwSize = 0; @@ -49,19 +49,19 @@ void test_BluetoothFindFirstRadio( void ) find = BluetoothFindFirstRadio( &find_params, &radio ); ok( !find, "Expected %p to be NULL\n", find ); err = GetLastError(); - todo_wine ok( err == ERROR_REVISION_MISMATCH, "%lu != %d\n", err, ERROR_REVISION_MISMATCH ); - todo_wine ok( radio == dummy, "%p != %p\n", radio, dummy ); + ok( err == ERROR_REVISION_MISMATCH, "%lu != %d\n", err, ERROR_REVISION_MISMATCH ); + ok( radio == dummy, "%p != %p\n", radio, dummy );
find_params.dwSize = sizeof( find_params ); SetLastError( 0xdeadbeef ); find = BluetoothFindFirstRadio( &find_params, &radio ); err = GetLastError(); exp = find ? ERROR_SUCCESS : ERROR_NO_MORE_ITEMS; - todo_wine ok( err == exp, "%lu != %lu\n", err, exp ); + ok( err == exp, "%lu != %lu\n", err, exp ); if (find) { CloseHandle( radio ); - todo_wine ok( BluetoothFindRadioClose( find ), "BluetoothFindRadioClose failed: %lu\n", GetLastError() ); + ok( BluetoothFindRadioClose( find ), "BluetoothFindRadioClose failed: %lu\n", GetLastError() ); } }
@@ -85,10 +85,10 @@ void test_BluetoothFindNextRadio( void ) radio = dummy; SetLastError( 0xdeadbeef ); ret = BluetoothFindNextRadio( NULL, &radio ); - todo_wine ok( !ret, "Expected BluetoothFindNextRadio to return FALSE\n" ); + ok( !ret, "Expected BluetoothFindNextRadio to return FALSE\n" ); err = GetLastError(); - todo_wine ok( err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE ); - todo_wine ok( radio == dummy, "%p != %p\n", radio, dummy ); + ok( err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE ); + ok( radio == dummy, "%p != %p\n", radio, dummy );
for(;;) { @@ -97,12 +97,12 @@ void test_BluetoothFindNextRadio( void ) if (!ret) { err = GetLastError(); - todo_wine ok( err == ERROR_NO_MORE_ITEMS, "%lu != %d\n", err, ERROR_NO_MORE_ITEMS ); + ok( err == ERROR_NO_MORE_ITEMS, "%lu != %d\n", err, ERROR_NO_MORE_ITEMS ); break; } CloseHandle( radio ); } - todo_wine ok( BluetoothFindRadioClose( find ), "BluetoothFindRadioClose failed: %lu\n", GetLastError() ); + ok( BluetoothFindRadioClose( find ), "BluetoothFindRadioClose failed: %lu\n", GetLastError() ); }
void test_BluetoothFindRadioClose( void ) @@ -112,7 +112,7 @@ void test_BluetoothFindRadioClose( void ) SetLastError( 0xdeadbeef ); ok( !BluetoothFindRadioClose( NULL ), "Expected BluetoothFindRadioClose to return FALSE\n" ); err = GetLastError(); - todo_wine ok( err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE ); + ok( err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE ); }
START_TEST( radio )