Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/bluetoothapis/tests/device.c
5968 views
1
/*
2
* Tests for Bluetooth device methods
3
*
4
* Copyright 2025 Vibhav Pant
5
*
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19
*/
20
21
#include <stdarg.h>
22
23
#include <windef.h>
24
#include <winbase.h>
25
#include <winnls.h>
26
#include <winuser.h>
27
28
#include <bthsdpdef.h>
29
#include <bluetoothapis.h>
30
31
#include <wine/debug.h>
32
#include <wine/test.h>
33
34
#include "resource.h"
35
36
extern void test_for_all_radios( const char *file, int line, void (*test)( HANDLE radio, void *data ), void *data );
37
38
static const char *debugstr_bluetooth_address( const BYTE *addr )
39
{
40
return wine_dbg_sprintf( "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] );
41
}
42
43
static DWORD(WINAPI *pBluetoothAuthenticateDeviceEx)( HWND, HANDLE, BLUETOOTH_DEVICE_INFO *,
44
BLUETOOTH_OOB_DATA_INFO *, AUTHENTICATION_REQUIREMENTS );
45
46
static const char *debugstr_BLUETOOTH_DEVICE_INFO( const BLUETOOTH_DEVICE_INFO *info )
47
{
48
WCHAR last_seen[256];
49
WCHAR last_used[256];
50
51
last_seen[0] = last_used[0] = 0;
52
53
GetTimeFormatEx( NULL, TIME_FORCE24HOURFORMAT, &info->stLastSeen, NULL, last_seen, ARRAY_SIZE( last_seen ) );
54
GetTimeFormatEx( NULL, TIME_FORCE24HOURFORMAT, &info->stLastUsed, NULL, last_used, ARRAY_SIZE( last_used ) );
55
56
return wine_dbg_sprintf( "{ Address: %s ulClassOfDevice: %#lx fConnected: %d fRemembered: %d fAuthenticated: %d "
57
"stLastSeen: %s stLastUsed: %s szName: %s }",
58
debugstr_bluetooth_address( info->Address.rgBytes ), info->ulClassofDevice,
59
info->fConnected, info->fRemembered, info->fAuthenticated, debugstr_w( last_seen ),
60
debugstr_w( last_used ), debugstr_w( info->szName ) );
61
}
62
63
void test_radio_BluetoothFindFirstDevice( HANDLE radio, void *data )
64
{
65
BLUETOOTH_DEVICE_SEARCH_PARAMS search_params;
66
BLUETOOTH_DEVICE_INFO device_info;
67
HBLUETOOTH_DEVICE_FIND hfind;
68
DWORD err, exp;
69
BOOL success;
70
71
search_params.dwSize = sizeof( search_params );
72
search_params.cTimeoutMultiplier = 200;
73
search_params.fIssueInquiry = TRUE;
74
search_params.fReturnUnknown = TRUE;
75
search_params.hRadio = radio;
76
device_info.dwSize = sizeof( device_info );
77
SetLastError( 0xdeadbeef );
78
hfind = BluetoothFindFirstDevice( &search_params, &device_info );
79
ok( !hfind, "Expected %p to be NULL\n", hfind );
80
err = GetLastError();
81
ok( err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER );
82
83
search_params.cTimeoutMultiplier = 5;
84
search_params.fIssueInquiry = winetest_interactive;
85
SetLastError( 0xdeadbeef );
86
hfind = BluetoothFindFirstDevice( &search_params, &device_info );
87
err = GetLastError();
88
exp = hfind ? ERROR_SUCCESS : ERROR_NO_MORE_ITEMS;
89
todo_wine_if( !radio ) ok( err == exp, "%lu != %lu\n", err, exp );
90
91
if (hfind)
92
{
93
success = BluetoothFindDeviceClose( hfind );
94
ok( success, "BluetoothFindDeviceClose failed: %lu\n", GetLastError() );
95
}
96
}
97
98
void test_BluetoothFindFirstDevice( void )
99
{
100
BLUETOOTH_DEVICE_SEARCH_PARAMS search_params = {0};
101
BLUETOOTH_DEVICE_INFO device_info = {0};
102
HBLUETOOTH_DEVICE_FIND hfind;
103
DWORD err;
104
105
SetLastError( 0xdeadbeef );
106
hfind = BluetoothFindFirstDevice( NULL, NULL );
107
ok( !hfind, "Expected %p to be NULL\n", hfind );
108
err = GetLastError();
109
ok( err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER );
110
111
SetLastError( 0xdeadbeef );
112
hfind = BluetoothFindFirstDevice( &search_params, NULL );
113
ok( !hfind, "Expected %p to be NULL\n", hfind );
114
err = GetLastError();
115
ok( err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER );
116
117
SetLastError( 0xdeadbeef );
118
hfind = BluetoothFindFirstDevice( &search_params, &device_info );
119
ok( !hfind, "Expected %p to be NULL\n", hfind );
120
err = GetLastError();
121
ok( err == ERROR_REVISION_MISMATCH, "%lu != %d\n", err, ERROR_REVISION_MISMATCH );
122
123
test_for_all_radios( __FILE__, __LINE__, test_radio_BluetoothFindFirstDevice, NULL );
124
}
125
126
void test_radio_BluetoothFindNextDevice( HANDLE radio, void *data )
127
{
128
BLUETOOTH_DEVICE_SEARCH_PARAMS search_params = *(BLUETOOTH_DEVICE_SEARCH_PARAMS *)data;
129
BLUETOOTH_DEVICE_INFO info = {0};
130
HBLUETOOTH_DEVICE_FIND hfind;
131
BOOL success;
132
DWORD err, i = 0;
133
134
search_params.hRadio = radio;
135
info.dwSize = sizeof( info );
136
137
SetLastError( 0xdeadbeef );
138
hfind = BluetoothFindFirstDevice( &search_params, &info );
139
err = GetLastError();
140
ok( !!hfind || err == ERROR_NO_MORE_ITEMS, "BluetoothFindFirstDevice failed: %lu\n", GetLastError() );
141
if (!hfind)
142
{
143
skip( "No devices found.\n" );
144
return;
145
}
146
147
for (;;)
148
{
149
BLUETOOTH_DEVICE_INFO info2 = {0};
150
BOOL matches;
151
152
matches = (info.fConnected && search_params.fReturnConnected)
153
|| (info.fAuthenticated && search_params.fReturnAuthenticated)
154
|| (info.fRemembered && search_params.fReturnRemembered)
155
|| (!info.fRemembered && search_params.fReturnUnknown);
156
ok( matches, "Device does not match filter constraints\n" );
157
trace( "device %lu: %s\n", i, debugstr_BLUETOOTH_DEVICE_INFO( &info ) );
158
159
info2.dwSize = sizeof( info2 );
160
info2.Address = info.Address;
161
err = BluetoothGetDeviceInfo( radio, &info2 );
162
ok( !err, "BluetoothGetDeviceInfo failed: %lu\n", err );
163
ok( !memcmp( info2.Address.rgBytes, info.Address.rgBytes, sizeof( info.Address.rgBytes ) ), "%s != %s\n",
164
debugstr_bluetooth_address( info2.Address.rgBytes ), debugstr_bluetooth_address( info.Address.rgBytes ) );
165
ok( !wcscmp( info2.szName, info.szName ), "%s != %s\n", debugstr_w( info2.szName ), debugstr_w( info.szName ) );
166
ok( info2.fAuthenticated == info.fAuthenticated, "%d != %d\n", info.fAuthenticated, info.fAuthenticated );
167
ok( info2.fRemembered == info.fRemembered, "%d != %d\n", info.fRemembered, info.fRemembered );
168
ok( info2.fAuthenticated == info.fAuthenticated, "%d != %d\n", info.fAuthenticated, info.fAuthenticated );
169
170
memset( &info, 0, sizeof( info ));
171
info.dwSize = sizeof( info );
172
SetLastError( 0xdeadbeef );
173
success = BluetoothFindNextDevice( hfind, &info );
174
err = GetLastError();
175
ok( success || err == ERROR_NO_MORE_ITEMS, "BluetoothFindNextDevice failed: %lu\n", err );
176
if (!success)
177
break;
178
}
179
180
success = BluetoothFindDeviceClose( hfind );
181
ok( success, "BluetoothFindDeviceClose failed: %lu\n", GetLastError() );
182
}
183
184
void test_BluetoothFindNextDevice( void )
185
{
186
BLUETOOTH_DEVICE_SEARCH_PARAMS params = {0};
187
DWORD err;
188
BOOL ret;
189
190
SetLastError( 0xdeadbeef );
191
ret = BluetoothFindNextDevice( NULL, NULL );
192
ok( !ret, "Expected BluetoothFindNextDevice to return FALSE\n" );
193
err = GetLastError();
194
ok( err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE );
195
196
params.dwSize = sizeof( params );
197
params.fReturnUnknown = TRUE;
198
params.fReturnRemembered = TRUE;
199
params.fReturnConnected = TRUE;
200
params.fReturnAuthenticated = TRUE;
201
202
if (winetest_interactive)
203
{
204
params.fIssueInquiry = TRUE;
205
params.cTimeoutMultiplier = 5;
206
}
207
208
test_for_all_radios( __FILE__, __LINE__, test_radio_BluetoothFindNextDevice, &params );
209
}
210
211
void test_BluetoothFindDeviceClose( void )
212
{
213
DWORD err;
214
215
SetLastError( 0xdeadbeef );
216
ok( !BluetoothFindDeviceClose( NULL ), "Expected BluetoothFindDeviceClose to return FALSE\n" );
217
err = GetLastError();
218
ok( err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE );
219
}
220
221
static HANDLE auth_events[2];
222
223
static void test_auth_callback_params( int line, const BLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS *auth_params )
224
{
225
ok_( __FILE__, line )( !!auth_params, "Expected authentication params to not be NULL\n" );
226
if (auth_params)
227
{
228
ULARGE_INTEGER ft = {0};
229
230
trace_( __FILE__, line )( "Device: %s\n", debugstr_BLUETOOTH_DEVICE_INFO( &auth_params->deviceInfo ) );
231
trace_( __FILE__, line )( "Method: %#x\n", auth_params->authenticationMethod );
232
trace_( __FILE__, line )( "Numeric value: %lu\n", auth_params->Numeric_Value );
233
234
SystemTimeToFileTime( &auth_params->deviceInfo.stLastSeen, (FILETIME *)&ft );
235
ok( ft.QuadPart, "Expected stLastSeen to be greater than zero\n" );
236
ft.QuadPart = 0;
237
SystemTimeToFileTime( &auth_params->deviceInfo.stLastUsed, (FILETIME *)&ft );
238
ok( ft.QuadPart, "Expected stLastUsed to be greater than zero\n" );
239
}
240
}
241
242
static CALLBACK BOOL auth_ex_callback( void *data, BLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS *auth_params )
243
{
244
char msg[400];
245
246
test_auth_callback_params( __LINE__, auth_params );
247
if (auth_params)
248
{
249
DWORD ret, exp;
250
BLUETOOTH_AUTHENTICATE_RESPONSE resp = {0};
251
252
/* Invalid parameters with an active registration */
253
ret = BluetoothSendAuthenticationResponseEx( NULL, NULL );
254
ok( ret == ERROR_INVALID_PARAMETER, "%lu != %d\n", ret, ERROR_INVALID_PARAMETER );
255
256
resp.bthAddressRemote.ullLong = 0xdeadbeefcafe;
257
ret = BluetoothSendAuthenticationResponseEx( NULL, &resp );
258
ok( ret == ERROR_INVALID_PARAMETER, "%lu != %d\n", ret, ERROR_INVALID_PARAMETER );
259
260
/* Non-existent device. */
261
resp.authMethod = auth_params->authenticationMethod;
262
ret = BluetoothSendAuthenticationResponseEx( NULL, &resp );
263
ok( ret == ERROR_DEVICE_NOT_CONNECTED, "%lu != %d\n", ret, ERROR_DEVICE_NOT_CONNECTED );
264
265
/* Invalid auth method */
266
resp.bthAddressRemote = auth_params->deviceInfo.Address;
267
resp.authMethod = 0xdeadbeef;
268
ret = BluetoothSendAuthenticationResponseEx( NULL, &resp );
269
ok( ret == ERROR_INVALID_PARAMETER, "%lu != %d\n", ret, ERROR_INVALID_PARAMETER );
270
271
resp.authMethod = auth_params->authenticationMethod;
272
resp.numericCompInfo.NumericValue = auth_params->Numeric_Value;
273
274
snprintf( msg, ARRAY_SIZE( msg ), "Accept auth request from %s (address %s, method %d, passkey %lu)?",
275
debugstr_w( auth_params->deviceInfo.szName ),
276
debugstr_bluetooth_address( auth_params->deviceInfo.Address.rgBytes ),
277
auth_params->authenticationMethod, auth_params->Numeric_Value );
278
ret = MessageBoxA( NULL, msg, __FILE__, MB_YESNO );
279
ok( ret, "MessageBoxA failed: %lu\n", GetLastError() );
280
281
resp.negativeResponse = ret != IDYES;
282
283
ret = BluetoothSendAuthenticationResponseEx( NULL, &resp );
284
exp = resp.negativeResponse ? ERROR_NOT_AUTHENTICATED : ERROR_SUCCESS;
285
todo_wine_if( auth_params->authenticationMethod != BLUETOOTH_AUTHENTICATION_METHOD_NUMERIC_COMPARISON )
286
ok( ret == exp, "%lu != %lu\n", ret, exp );
287
288
ret = BluetoothSendAuthenticationResponseEx( NULL, &resp );
289
todo_wine_if( auth_params->authenticationMethod != BLUETOOTH_AUTHENTICATION_METHOD_NUMERIC_COMPARISON )
290
ok( ret == ERROR_NOT_READY, "%lu != %d\n", ret, ERROR_NOT_READY );
291
}
292
SetEvent( auth_events[0] );
293
return TRUE;
294
}
295
296
static CALLBACK BOOL auth_ex_callback_2( void *data, BLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS *auth_params )
297
{
298
test_auth_callback_params( __LINE__, auth_params );
299
SetEvent( auth_events[1] );
300
return TRUE;
301
}
302
303
static void test_BluetoothRegisterForAuthenticationEx( void )
304
{
305
HBLUETOOTH_AUTHENTICATION_REGISTRATION hreg = NULL, hreg2 = NULL;
306
BLUETOOTH_DEVICE_INFO info;
307
BOOL success;
308
DWORD err;
309
310
err = BluetoothRegisterForAuthenticationEx( NULL, NULL, NULL, NULL );
311
ok( err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER );
312
313
info.dwSize = sizeof( info ) + 1;
314
err = BluetoothRegisterForAuthenticationEx( &info, &hreg, NULL, NULL );
315
ok( err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER );
316
317
BluetoothEnableIncomingConnections( NULL, TRUE );
318
BluetoothEnableDiscovery( NULL, TRUE );
319
320
err = BluetoothRegisterForAuthenticationEx( NULL, &hreg, auth_ex_callback, NULL );
321
ok( !err, "BluetoothRegisterForAuthenticationEx failed: %lu\n", err );
322
ok( !!hreg, "Handle was not filled\n" );
323
324
err = BluetoothRegisterForAuthenticationEx( NULL, &hreg2, auth_ex_callback_2, NULL );
325
ok( !err, "BluetoothRegisterForAuthenticationEx failed: %lu\n", err );
326
ok( !!hreg2, "Handle was not filled\n" );
327
328
trace( "Waiting for incoming authentication requests.\n" );
329
err = WaitForMultipleObjects( 2, auth_events, TRUE, 60000 );
330
ok( !err, "WaitForMultipleObjects failed: %lu\n", err );
331
332
success = BluetoothUnregisterAuthentication( hreg );
333
ok( success, "BluetoothUnregisterAuthentication failed: %lu\n", GetLastError() );
334
success = BluetoothUnregisterAuthentication( hreg2 );
335
ok( success, "BluetoothUnregisterAuthentication failed: %lu\n", GetLastError() );
336
337
BluetoothEnableDiscovery( NULL, FALSE );
338
}
339
340
341
static void test_radio_BluetoothSendAuthenticationResponseEx( HANDLE radio , void *data )
342
{
343
BLUETOOTH_AUTHENTICATE_RESPONSE resp = {0};
344
DWORD ret;
345
346
ret = BluetoothSendAuthenticationResponseEx( radio, NULL );
347
348
ok( ret == ERROR_INVALID_PARAMETER || (!radio && ret == ERROR_NO_MORE_ITEMS),
349
"%lu != %d\n", ret, ERROR_INVALID_PARAMETER );
350
351
ret = BluetoothSendAuthenticationResponseEx( radio, &resp );
352
ok( ret == ERROR_INVALID_PARAMETER || (!radio && ret == ERROR_NO_MORE_ITEMS),
353
"%lu != %d\n", ret, ERROR_INVALID_PARAMETER );
354
355
resp.bthAddressRemote.ullLong = 0xdeadbeefcafe;
356
ret = BluetoothSendAuthenticationResponseEx( radio, &resp );
357
ok( ret == ERROR_INVALID_PARAMETER || (!radio && ret == ERROR_NO_MORE_ITEMS),
358
"%lu != %d\n", ret, ERROR_INVALID_PARAMETER );
359
}
360
361
/* Test BluetoothSendAuthenticationResponseEx when no authentication registrations exist. */
362
static void test_BluetoothSendAuthenticationResponseEx( void )
363
{
364
test_radio_BluetoothSendAuthenticationResponseEx( NULL, (void *)__LINE__ );
365
test_for_all_radios( __FILE__, __LINE__, test_radio_BluetoothSendAuthenticationResponseEx, NULL );
366
}
367
368
static void test_radio_BluetoothRemoveDevice( HANDLE radio, void *data )
369
{
370
BLUETOOTH_DEVICE_SEARCH_PARAMS search_params = {0};
371
BLUETOOTH_DEVICE_INFO device_info = {0};
372
HBLUETOOTH_DEVICE_FIND find;
373
DWORD err;
374
375
device_info.dwSize = sizeof( device_info );
376
search_params.dwSize = sizeof( search_params );
377
search_params.fReturnAuthenticated = TRUE;
378
search_params.fReturnRemembered = TRUE;
379
search_params.fReturnUnknown = TRUE;
380
search_params.fReturnConnected = TRUE;
381
search_params.hRadio = radio;
382
383
find = BluetoothFindFirstDevice( &search_params, &device_info );
384
err = GetLastError();
385
ok( find || err == ERROR_NO_MORE_ITEMS, "BluetoothFindFirstDevice failed: %lu\n", err );
386
if (!find)
387
{
388
skip( "No devices found.\n" );
389
return;
390
}
391
392
do {
393
DWORD exp;
394
winetest_push_context( "%s (%s)", debugstr_w( device_info.szName ),
395
debugstr_bluetooth_address( device_info.Address.rgBytes ) );
396
err = BluetoothRemoveDevice( &device_info.Address );
397
exp = device_info.fRemembered ? ERROR_SUCCESS : ERROR_NOT_FOUND;
398
ok( err == exp, "%lu != %lu\n", err, exp );
399
err = BluetoothGetDeviceInfo( radio, &device_info );
400
ok( !err || err == ERROR_NOT_FOUND, "BluetoothGetDeviceInfo failed: %lu\n", err );
401
if (!err)
402
ok( !device_info.fRemembered, "%d != %d\n", device_info.fRemembered, 0 );
403
winetest_pop_context();
404
} while (BluetoothFindNextDevice( find, &device_info ));
405
406
BluetoothFindDeviceClose( find );
407
}
408
409
static void test_BluetoothRemoveDevice( void )
410
{
411
DWORD err;
412
BLUETOOTH_ADDRESS addr_zeros = {0};
413
414
err = BluetoothRemoveDevice( &addr_zeros );
415
ok( err == ERROR_NOT_FOUND, "%lu != %d\n", err, ERROR_NOT_FOUND );
416
417
test_for_all_radios( __FILE__, __LINE__, test_radio_BluetoothRemoveDevice, NULL );
418
}
419
420
static BLUETOOTH_DEVICE_INFO *devices;
421
422
static SIZE_T find_devices( int line, HANDLE radio )
423
{
424
BLUETOOTH_DEVICE_SEARCH_PARAMS params = {0};
425
HBLUETOOTH_DEVICE_FIND find;
426
SIZE_T devices_len;
427
DWORD ret;
428
429
devices_len = 1;
430
params.dwSize = sizeof( params );
431
params.cTimeoutMultiplier = 5;
432
params.fIssueInquiry = TRUE;
433
params.fReturnAuthenticated = FALSE;
434
params.fReturnRemembered = FALSE;
435
params.fReturnUnknown = TRUE;
436
params.fReturnConnected = TRUE;
437
params.hRadio = radio;
438
439
devices = calloc( 1, sizeof( *devices ) );
440
devices->dwSize = sizeof( *devices );
441
find = BluetoothFindFirstDevice( &params, devices );
442
ret = GetLastError();
443
ok_( __FILE__, line )( !!find || ret == ERROR_NO_MORE_ITEMS, "BluetoothFindFirstDevice failed: %lu\n", ret );
444
445
if (!find)
446
{
447
devices_len = 0;
448
free( devices );
449
return devices_len;
450
}
451
452
for (;;)
453
{
454
BOOL success;
455
BLUETOOTH_DEVICE_INFO info = {.dwSize = sizeof( info )};
456
457
success = BluetoothFindNextDevice( find, &info );
458
ret = GetLastError();
459
ok_( __FILE__, line )( success || ret == ERROR_NO_MORE_ITEMS, "BluetoothFindNextDevice failed: %lu\n", ret );
460
if (!success)
461
break;
462
if (info.fAuthenticated)
463
continue;
464
devices = realloc( devices, (devices_len + 1) * sizeof( *devices ) );
465
devices[devices_len++] = info;
466
}
467
468
BluetoothFindDeviceClose( find );
469
return devices_len;
470
}
471
472
static BLUETOOTH_ADDRESS selected_device;
473
static SIZE_T devices_len;
474
static HANDLE device_selected_event;
475
476
static CALLBACK INT_PTR dialog_proc( HWND dialog, UINT msg, WPARAM wparam, LPARAM lparam )
477
{
478
switch (msg)
479
{
480
case WM_INITDIALOG:
481
{
482
HWND devices_list = GetDlgItem( dialog, IDC_CBO_DEVICES );
483
WCHAR device_desc[300];
484
SIZE_T i;
485
486
for (i = 0; i < devices_len; i++)
487
{
488
BYTE *addr = devices[i].Address.rgBytes;
489
swprintf( device_desc, ARRAY_SIZE( device_desc ), L"%s (%02x:%02x:%02x:%02x:%02x:%02x)", devices[i].szName,
490
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] );
491
SendMessageW( devices_list, CB_ADDSTRING, 0, (LPARAM)device_desc );
492
}
493
return TRUE;
494
}
495
case WM_COMMAND:
496
switch (LOWORD( wparam ))
497
{
498
case IDC_CBO_DEVICES:
499
{
500
if (HIWORD( wparam ) == CBN_SELCHANGE)
501
{
502
int idx = SendMessageA( (HWND)lparam, CB_GETCURSEL, 0, 0 );
503
if (idx != CB_ERR)
504
selected_device = devices[idx].Address;
505
SetEvent(device_selected_event);
506
EndDialog( dialog, 0 );
507
return TRUE;
508
}
509
break;
510
}
511
case IDCANCEL:
512
SetEvent(device_selected_event);
513
EndDialog( dialog, 0 );
514
return TRUE;
515
default:
516
break;
517
}
518
default:
519
break;
520
}
521
522
return FALSE;
523
}
524
525
static BOOL get_remote_device_interactive( int line, HANDLE radio, BLUETOOTH_ADDRESS *device_addr )
526
{
527
devices_len = find_devices( line, radio );
528
if (!devices_len)
529
return FALSE;
530
531
selected_device.ullLong = 0;
532
533
DialogBoxA( NULL, MAKEINTRESOURCEA( IDD_DEVICESDLG ), NULL, dialog_proc );
534
WaitForSingleObject( device_selected_event, INFINITE );
535
*device_addr = selected_device;
536
free( devices );
537
return !!selected_device.ullLong;
538
}
539
540
static void test_radio_BluetoothAuthenticateDeviceEx( HANDLE radio, void *data )
541
{
542
HBLUETOOTH_AUTHENTICATION_REGISTRATION auth_reg;
543
BLUETOOTH_DEVICE_INFO device_info = {0};
544
DWORD ret;
545
546
device_info.dwSize = sizeof( device_info );
547
if (!get_remote_device_interactive( __LINE__, radio, &device_info.Address ))
548
{
549
skip( "Could not select device.\n" );
550
return;
551
}
552
553
ret = pBluetoothAuthenticateDeviceEx( NULL, radio, &device_info, NULL, 0xdeadbeef );
554
ok( ret == ERROR_INVALID_PARAMETER, "%lu != %d\n", ret, ERROR_INVALID_PARAMETER );
555
556
/* Test authenticating without a registered auth callback, which triggers a wizard UI. */
557
ret = pBluetoothAuthenticateDeviceEx( NULL, radio, &device_info, NULL, MITMProtectionRequiredGeneralBonding );
558
ok( !ret, "BluetoothAuthenticateDeviceEx failed: %lu\n", ret );
559
560
memset( &device_info, 0, sizeof( device_info ) );
561
device_info.dwSize = sizeof( device_info );
562
if (!get_remote_device_interactive( __LINE__, radio, &device_info.Address ))
563
{
564
skip( "Could not select device.\n" );
565
return;
566
}
567
ret = BluetoothRegisterForAuthenticationEx( &device_info, &auth_reg, auth_ex_callback, NULL );
568
ok( !ret, "BluetoothRegisterForAuthenticationEx failed: %lu\n", ret );
569
if (ret)
570
{
571
skip( "BluetoothRegisterForAuthenticationEx failed.\n" );
572
return;
573
}
574
/* Test authentication with a registered callback. */
575
ret = pBluetoothAuthenticateDeviceEx( NULL, radio, &device_info, NULL, MITMProtectionRequiredGeneralBonding );
576
ok( !ret, "BluetoothAuthenticateDeviceEx failed: %lu\n", ret );
577
if (ret)
578
{
579
BluetoothUnregisterAuthentication( auth_reg );
580
skip( "BluetoothAuthenticateDeviceEx failed.\n" );
581
return;
582
}
583
ret = WaitForSingleObject( auth_events[0], 60000 );
584
ok ( !ret, "WaitForSginleObject value: %lu\n", ret );
585
586
BluetoothUnregisterAuthentication( auth_reg );
587
}
588
589
static void test_BluetoothAuthenticateDeviceEx( void )
590
{
591
DWORD ret;
592
593
if (!pBluetoothAuthenticateDeviceEx)
594
{
595
skip( "BluetoothAuthenticateDeviceEx is not available.\n" );
596
return;
597
}
598
599
ret = pBluetoothAuthenticateDeviceEx( NULL, NULL, NULL, NULL, 0xdeadbeef );
600
ok( ret == ERROR_INVALID_PARAMETER, "%lu != %d\n", ret, ERROR_INVALID_PARAMETER );
601
ret = pBluetoothAuthenticateDeviceEx( NULL, NULL, NULL, NULL, MITMProtectionRequiredGeneralBonding );
602
ok( ret == ERROR_INVALID_PARAMETER, "%lu != %d\n", ret, ERROR_INVALID_PARAMETER );
603
604
if (!winetest_interactive)
605
return;
606
607
device_selected_event = CreateEventA( NULL, FALSE, FALSE, NULL );
608
test_for_all_radios( __FILE__, __LINE__, test_radio_BluetoothAuthenticateDeviceEx, NULL );
609
610
CloseHandle( device_selected_event );
611
}
612
613
START_TEST( device )
614
{
615
auth_events[0] = CreateEventA( NULL, FALSE, FALSE, NULL );
616
auth_events[1] = CreateEventA( NULL, FALSE, FALSE, NULL );
617
618
pBluetoothAuthenticateDeviceEx =
619
(void *)GetProcAddress( LoadLibraryA( "bthprops.cpl" ), "BluetoothAuthenticateDeviceEx" );
620
621
test_BluetoothFindFirstDevice();
622
test_BluetoothFindDeviceClose();
623
test_BluetoothFindNextDevice();
624
625
if (winetest_interactive)
626
test_BluetoothRegisterForAuthenticationEx();
627
test_BluetoothSendAuthenticationResponseEx();
628
test_BluetoothAuthenticateDeviceEx();
629
test_BluetoothRemoveDevice();
630
631
CloseHandle( auth_events[0] );
632
CloseHandle( auth_events[1] );
633
}
634
635