From: Vibhav Pant vibhavp@gmail.com
--- dlls/bluetoothapis/main.c | 214 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 205 insertions(+), 9 deletions(-)
diff --git a/dlls/bluetoothapis/main.c b/dlls/bluetoothapis/main.c index 6cdc84f6b6f..727d13118f5 100644 --- a/dlls/bluetoothapis/main.c +++ b/dlls/bluetoothapis/main.c @@ -48,15 +48,200 @@ struct bluetooth_find_radio_handle DWORD idx; };
+struct bluetooth_find_device_handle +{ + BLUETOOTH_DEVICE_SEARCH_PARAMS params; + BTH_DEVICE_INFO_LIST *device_list; + SIZE_T idx; +}; + +static const char *debugstr_BLUETOOTH_DEVICE_SEARCH_PARAMS( const BLUETOOTH_DEVICE_SEARCH_PARAMS *params ) +{ + if (!params || params->dwSize != sizeof( *params )) + return wine_dbg_sprintf("%p", params ); + + return wine_dbg_sprintf( "{ %ld %d %d %d %d %d %u %p }", params->dwSize, params->fReturnAuthenticated, + params->fReturnRemembered, params->fReturnUnknown, params->fReturnConnected, + params->fIssueInquiry, (UINT)params->cTimeoutMultiplier, params->hRadio ); +} + +static BOOL radio_set_inquiry( HANDLE radio, BOOL enable ) +{ + DWORD bytes; + + return DeviceIoControl( radio, enable ? IOCTL_WINEBTH_RADIO_START_DISCOVERY : IOCTL_WINEBTH_RADIO_STOP_DISCOVERY, + NULL, 0, NULL, 0, &bytes, NULL ); +} + +static BOOL radio_get_devices( HANDLE radio, BTH_DEVICE_INFO_LIST **devices ) +{ + BTH_DEVICE_INFO_LIST *list; + BOOL success; + DWORD bytes, size; + void *ptr; + + list = malloc( sizeof( *list ) ); + if (!list) + { + SetLastError( ERROR_OUTOFMEMORY ); + return FALSE; + } + + success = DeviceIoControl( radio, IOCTL_BTH_GET_DEVICE_INFO, list, sizeof( *list ), list, sizeof( *list ), &bytes, + NULL ); + if (!success) + { + free( list ); + return FALSE; + } + if (!list->numOfDevices) + { + free( list ); + SetLastError( ERROR_NO_MORE_ITEMS ); + return FALSE; + } + if (list->numOfDevices == 1) + { + *devices = list; + return TRUE; + } + + size = sizeof( *list ) + (list->numOfDevices - 1) * sizeof( list->deviceList[0] ); + ptr = realloc( list, size ); + if (!ptr) + { + free( list ); + SetLastError( ERROR_OUTOFMEMORY ); + return FALSE; + } + list = ptr; + success = DeviceIoControl( radio, IOCTL_BTH_GET_DEVICE_INFO, list, sizeof( *list ), list, size, &bytes, NULL ); + if (!success) + { + free( list ); + return FALSE; + } + *devices = list; + return TRUE; +} + +static void device_info_from_bth_info( BLUETOOTH_DEVICE_INFO *info, const BTH_DEVICE_INFO *bth_info ) +{ + union { + BTH_ADDR addr; + BYTE bytes[8]; + } raw_addr = {.addr = bth_info->address}; + DWORD i; + + memset( info, 0, sizeof( *info )); + info->dwSize = sizeof( *info ); + + if (bth_info->flags & BDIF_ADDRESS) + for (i = 2; i < 8; i++) + info->Address.rgBytes[i - 2] = raw_addr.bytes[i]; + + info->ulClassofDevice = bth_info->classOfDevice; + info->fConnected = !!(bth_info->flags & BDIF_CONNECTED); + info->fRemembered = !!(bth_info->flags & BDIF_PERSONAL); + info->fAuthenticated = !!(bth_info->flags & BDIF_PAIRED); + + if (bth_info->flags & BDIF_NAME) + MultiByteToWideChar( CP_ACP, 0, bth_info->name, -1, info->szName, ARRAY_SIZE( info->szName ) ); +} + +static BOOL device_find_set_next( struct bluetooth_find_device_handle *find, BLUETOOTH_DEVICE_INFO *info ) +{ + while (find->idx < find->device_list->numOfDevices) + { + const BTH_DEVICE_INFO *bth_info; + + bth_info = &find->device_list->deviceList[find->idx++]; + if (find->params.fReturnAuthenticated != !!(bth_info->flags & BDIF_PAIRED)) + continue; + if (find->params.fReturnRemembered != !!(bth_info->flags & BDIF_PERSONAL)) + continue; + if (find->params.fReturnUnknown && bth_info->flags & BDIF_PERSONAL) + continue; + if (find->params.fReturnConnected != !!(bth_info->flags & BDIF_CONNECTED)) + continue; + + device_info_from_bth_info( info, bth_info ); + /* If the user is looking for unknown devices as part of device inquiry, or wants connected devices, + * we can set stLastSeen to the current UTC time. */ + if ((find->params.fIssueInquiry && find->params.fReturnUnknown) || find->params.fReturnConnected) + GetSystemTime( &info->stLastSeen ); + else + FIXME( "semi-stub!\n" ); + return TRUE; + } + + return FALSE; +} + /********************************************************************* * BluetoothFindFirstDevice */ -HBLUETOOTH_DEVICE_FIND WINAPI BluetoothFindFirstDevice(BLUETOOTH_DEVICE_SEARCH_PARAMS *params, - BLUETOOTH_DEVICE_INFO *info) +HBLUETOOTH_DEVICE_FIND WINAPI BluetoothFindFirstDevice( BLUETOOTH_DEVICE_SEARCH_PARAMS *params, + BLUETOOTH_DEVICE_INFO *info ) { - FIXME("(%p %p): stub!\n", params, info); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return NULL; + struct bluetooth_find_device_handle *hfind; + BTH_DEVICE_INFO_LIST *device_list; + BOOL success; + + TRACE( "(%s %p)\n", debugstr_BLUETOOTH_DEVICE_SEARCH_PARAMS( params ), info ); + + if (!params || !info) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return NULL; + } + if (params->dwSize != sizeof( *params ) || info->dwSize != sizeof( *info )) + { + SetLastError( ERROR_REVISION_MISMATCH ); + return NULL; + } + if (params->fIssueInquiry && params->cTimeoutMultiplier > 48) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return NULL; + } + if (!params->hRadio) + { + /* TODO: Perform device inquiry on all local radios */ + FIXME( "semi-stub!\n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + return NULL; + } + + if (!radio_set_inquiry( params->hRadio, TRUE )) + return NULL; + Sleep( params->cTimeoutMultiplier * 1280 ); + radio_set_inquiry( params->hRadio, FALSE ); + + success = radio_get_devices( params->hRadio, &device_list ); + if (!success) + return NULL; + + hfind = malloc( sizeof( *hfind ) ); + if (!hfind) + { + free( device_list ); + SetLastError( ERROR_OUTOFMEMORY ); + return NULL; + } + + memcpy( hfind, params, sizeof( *params ) ); + hfind->device_list = device_list; + hfind->idx = 0; + if (!device_find_set_next( hfind, info )) + { + free( hfind->device_list ); + free( hfind ); + SetLastError( ERROR_NO_MORE_ITEMS ); + return NULL; + } + SetLastError( ERROR_SUCCESS ); + return hfind; }
/********************************************************************* @@ -130,11 +315,22 @@ BOOL WINAPI BluetoothFindRadioClose( HBLUETOOTH_RADIO_FIND find_handle ) /********************************************************************* * BluetoothFindDeviceClose */ -BOOL WINAPI BluetoothFindDeviceClose(HBLUETOOTH_DEVICE_FIND find) +BOOL WINAPI BluetoothFindDeviceClose( HBLUETOOTH_DEVICE_FIND find_handle ) { - FIXME("(%p): stub!\n", find); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + struct bluetooth_find_device_handle *find = find_handle; + + TRACE( "(%p)\n", find_handle ); + + if (!find_handle) + { + SetLastError( ERROR_INVALID_HANDLE ); + return FALSE; + } + + free( find->device_list ); + free( find ); + SetLastError( ERROR_SUCCESS ); + return TRUE; }
/*********************************************************************