-- v3: bluetoothapis: Implement BluetoothFindFirstRadio, BluetoothFindNextRadio, BluetoothFindRadioClose. bluetoothapis/tests: Add tests for BluetoothFindRadioClose. bluetoothapis/tests: Add tests for BluetoothFindNextRadio. bluetoothapis/tests: Add tests for BluetoothFindFirstRadio. bluetoothapis/tests: Fix potential test failure from memcmp'ing uninitialized bytes.
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..5f83c9d54e4 --- /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 5f83c9d54e4..6954d7c0979 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 6954d7c0979..4afea493ef9 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 | 126 +++++++++++++++++++++++++++---- dlls/bluetoothapis/tests/radio.c | 24 +++--- 3 files changed, 126 insertions(+), 25 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..ec7382e74c8 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,75 @@ 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); - return NULL; + struct bluetooth_find_radio_handle *find; + HANDLE device_ret; + BOOL found; + + 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; + } + + found = BluetoothFindNextRadio( find, &device_ret ); + + if (!found) + { + DWORD err; + err = GetLastError(); + BluetoothFindRadioClose( find ); + find = NULL; + SetLastError( err ); + } + else + *radio = device_ret; + + return find; }
/********************************************************************* * 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 +139,46 @@ 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, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, 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 4afea493ef9..ad8a0616fd9 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 )
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=150109
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: win.c:4070: Test failed: Expected active window 00000000041F0158, got 000000000024017A. win.c:4071: Test failed: Expected focus window 00000000041F0158, got 000000000024017A.
On Sat Nov 30 16:25:40 2024 +0000, Rémi Bernon wrote:
We usually use X as a temporary macro, I don't see why XX is better if not necessary. Also in this case with only a couple of cases and the need to redefine it, it doesn't seem very helpful to have a macro in the first place. The default cases for UINT/INT/UUID also looks wrong. What about:
static SIZE_T sdp_type_size( SDP_TYPE type, SDP_SPECIFICTYPE st ) { switch (type) { case SDP_TYPE_NIL: return 0; case SDP_TYPE_UINT: case SDP_TYPE_INT: case SDP_TYPE_UUID: switch (st) { case SDP_ST_UINT8: case SDP_ST_INT8: return 1; case SDP_ST_UINT16: case SDP_ST_INT16: case SDP_ST_UUID16: return 2; case SDP_ST_UINT32: case SDP_ST_INT32: /* case SDP_ST_UUID32: */ return 4; case SDP_ST_UINT64: case SDP_ST_INT64: return 8; case SDP_ST_UINT128: case SDP_ST_INT128: case SDP_ST_UUID128: return 16; default: FIXME( "Unexpected type %#x/%#x\n", type, st ); return 0; } case SDP_TYPE_BOOLEAN: return 1; case SDP_TYPE_STRING: case SDP_TYPE_SEQUENCE: case SDP_TYPE_ALTERNATIVE: case SDP_TYPE_URL: case SDP_TYPE_CONTAINER: return sizeof(BYTE *) + sizeof(ULONG); default: FIXME( "Unexpected type %#x\n", type ); return 0; } }
I would even be fine with `return 1 << ((st >> 8) & 0x7);` for the INT/UINT/UUID case as it seems to be how specific types are encoded.
Oops, forgot about UINT/INT8. Getting the size from masking the specific type is much cleaner, indeed. I've simplified the function now. As far a `default` in case of an unexpected type value is concerned, it shouldn't be necessary. `test_BluetoothSdpGetElementData` already tests the type and specific type fields, which will catch any unexpected values.