Поместим на форму компонент TactionList и изменим его
свойство Name на ActionList. Теперь два раза щелкнем по ActionList и в появившемся окне редактора свойств добавим две TAction со следующими свойствами: 
Caption — Connectable, Name — acConnectable; Caption — Discoverable, Name — acDiscoverable.
На панель Panel добавим две TButton и установим свойства:
Action — acConnectable, Name — btConnectable; Action — acDiscoverable, Name
—  btDiscoverable.

Напишем вот такой обработчик события OnUpdate у acConnectable: 

procedure TfmMain.acConnectableUpdate(Sender: TObject);
var
SelectedItem: TListItem;
SelectedNode: TTreeNode;
begin
SelectedNode := TreeView.Selected;
SelectedItem := ListView.Selected;

with TAction(Sender) do 
begin
Enabled := Assigned(SelectedNode) and Assigned(SelectedItem) and (SelectedNode.ImageIndex = -1);

if Enabled then
if StrToBool(SelectedItem.SubItems[4])
then Caption := ‘Not conn.’
else Caption := ‘Connectable’;
end;
end; 

И то же самое напишем для обработчика события OnUpdate — acDiscoverable: 

procedure TfmMain.acDiscoverableUpdate(Sender: TObject);
var
SelectedItem: TListItem;
SelectedNode: TTreeNode;
begin
SelectedNode := TreeView.Selected;
SelectedItem := ListView.Selected;

with TAction(Sender) do 
begin
Enabled := Assigned(SelectedNode) and Assigned(SelectedItem) and (SelectedNode.ImageIndex = -1);

if Enabled then 
if StrToBool(SelectedItem.SubItems[5])
then Caption := ‘Not disc.’
else Caption := ‘Discoverable’;
end;
end; 

Теперь обработчик события OnExecute для acConnectable: 

procedure TfmMain.acConnectableExecute(Sender: TObject);
var
SelectedItem: TListItem;
begin
SelectedItem := ListView.Selected;

if Assigned(SelectedItem) then
if not BluetoothEnableIncomingConnections(Integer(SelectedItem.Data), TAction(Sender).Caption = ‘Not conn.’) 
then MessageDlg(‘Unable to change Radio state’, mtError, [mbOK], 0)
else TreeViewChange(TreeView, TreeView.Selected);
end; 

Такой же обработчик напишем и для OnExecute — acDiscoverable: 

procedure TfmMain.acConnectableExecute(Sender: TObject);
var
SelectedItem: TListItem;
begin
SelectedItem := ListView.Selected;

if Assigned(SelectedItem) then
if not BluetoothEnableDiscovery(Integer(SelectedItem.Data), TAction(Sender).Caption = ‘Not disc.’) 
then MessageDlg(‘Unable to change Radio state’, mtError, [mbOK], 0)
else TreeViewChange(TreeView, TreeView.Selected);
end; 

Вывод окна свойств устройства

Важно: Если Windows сам использует радиомодуль, то он не даст поменять статус, хотя и функция выполнится без ошибок!

Здесь мы ввели две новые функции:

BluetoothEnableInfomingConnection — функция разрешает/запрещает подключения к локальному радиомодулю Bluetooth.

Объявление функции: 

function BluetoothEnableIncomingConnections(
hRadio : THandle;
fEnabled : BOOL): BOOL; stdcall; 

Параметры:

hRadio — Handle радиомодуля, статус которого мы хотим изменить. Если 0, то меняем у всех. 
fEnabled  — TRUE – разрешаем подключения; FALSE – запрещаем. 

Возвращаемые значения: 

TRUE — если вызов успешен и статус изменен, 
FALSE — в противном случае. 

BluetoothEnableDiscovery — функция разрешает/запрещает обнаружение локального радиомодуля Bluetooth

Объявление функции: 

function BluetoothEnableDiscovery(
hRadio : THandle;
fEnabled : BOOL): BOOL; stdcall; 

Параметры: 

hRadio — Handle радиомодуля, статус которого мы хотим изменить. Если 0, то меняем у всех. 
fEnabled — TRUE – разрешаем обнаружение; FALSE – запрещаем. 

Возвращаемые значения: 

TRUE — если вызов успешен и статус изменен, 
FALSE — в противном случае. 

Теперь давайте научимся выводить системное окно свойств устройства Bluetooth. Для этого добавим к ActionList еще один TAction.
Добавим на Panel кнопку TButton с такими свойствами:
Action — acProperty, Name — btProperty.

Теперь напишем такой обработчик событий OnUpdate у acProperty: 

procedure TfmMain.acPropertyUpdate(Sender: TObject);
var
SelectedNode: TTreeNode;
SelectedItem: TListItem;
begin
SelectedNode := TreeView.Selected;
SelectedItem := ListView.Selected;

TAction(Sender).Enabled := Assigned(SelectedNode) and
Assigned(SelectedItem) and
(SelectedNode.ImageIndex > 0);
end; 

И обработчик OnExecute для нее же: 

procedure TfmMain.acPropertyExecute(Sender: TObject);
var
Info: BLUETOOTH_DEVICE_INFO;
begin
Info := BLUETOOTH_DEVICE_INFO(ListView.Selected.Data^);
BluetoothDisplayDeviceProperties(Handle, Info);
end; 

Важно: В исходном виде в файле JwaBluetoothAPIs функция BluetoothDisplayDeviceProperties объявлена не верно. Второй параметр должен быть указателем, а там он передается как структура. Я исправил функцию так, чтобы он передавался как var-параметр (по ссылке). Используйте модуль JwaBluetoothAPIs из этого примера, чтобы не возникало ошибок доступа к памяти.

Важно: Ни в этой процедуре, ни ранее, ни далее я не провожу проверку ошибок, чтобы не загромождать код лишними подробностями. В реальном приложении НЕОБХОДИМО проверять возвращаемые функциями значения и указатели.

И так, в этом коде есть новая функция, выделенная жирным шрифтом.

BluetoothDisplayDeviceProperty — функция выводит стандартное окно свойств устройства Bluetooth.

Объявление функции: 

function BluetoothEnableDiscovery(
hwndParent : HWND;
var pbtdi : PBLUETOOTH_DEVICE_INFO): BOOL; stdcall; 

Важно: В оригинале функция выглядит вот так: 

function BluetoothEnableDiscovery(
hwndParent : HWND;
pbtdi : PBLUETOOTH_DEVICE_INFO): BOOL; stdcall;

Это не верно, так как в документации Microsoft указано, что параметр pbtdi должен передаваться как указатель (что подразумевает запись PBLUETOOTH_DEVICE_INFO), но как я писал выше, этот тип ошибочен. Он не является указателем. Я изменил функцию так, как показано выше (так она и должна быть, если не менять определение типа). 

Параметры: hwndParent Handle родительского окна, которому будет принадлежать диалог свойств. Может быть 0, тогда родительским выбирается окно Desktop. 

pbtdi Указатель на структуру BLUETOOTH_DEVICE_INFO в которой содержится адрес требуемого устройства. 

Возвращаемые значения: 

TRUE — если вызов успешен 
FALSE — в противном случае (код ошибки можно узнать вызовом функции GetLastError). 

Выбор устройства 

Рассмотрим, как вызвать окно диалога выбора устройства.

Добавим в наш проект на Panel еще одну кнопку TButton и установите ее свойства как в таблице:
Caption — Select, Name — btSelect .

Напишем вот такой обработчик события OnClick у этой кнопки: 

procedure TfmMain.btSelectClick(Sender: TObject);
var
ASelParams: BLUETOOTH_SELECT_DEVICE_PARAMS;
ASelParamsSize: dword;
begin
ASelParamsSize := SizeOf(BLUETOOTH_SELECT_DEVICE_PARAMS);
FillChar(ASelParams, ASelParamsSize, 0);
with ASelParams do 
begin
dwSize := ASelParamsSize;
hwndParent := Handle;
fShowRemembered := True;
fAddNewDeviceWizard := True;
end;

BluetoothSelectDevices(@ASelParams);
BluetoothSelectDevicesFree(@ASelParams);
end 

В этой части кода две новые функции.

BluetoothSelectDevices — функция разрешает/запрещает обнаружение локального радиомодуля Bluetooth.

Объявление функции: 

function BluetoothSelectDevices(
pbtsdp : PBLUETOOTH_SELECT_DEVICE_PARAMS): BOOL; stdcall; 

Параметры: pbtsdp Описание смотрите ниже в описании структуры. 

Возвращаемые значения:

Если функция вернула TRUE, то пользователь выбрал устройства. Pbtsdp^.pDevices будет указывать на корректные данные. После вызова необходимо проверить флаги fAuthenticated и fRemembered, что бы удостовериться в корректности данных. Для освобождения памяти используйте функцию BluetoothSelectDevicesFree, только если функция вернет TRUE.

Вернет FALSE если вызов прошел не удачно. Используйте GetLastError для получения дополнительных сведений. Возможные ошибки: 

ERROR_CANCELLED — Пользователь отменил выбор устройства. 
ERROR_INVALID_PARAMETER — Параметр pbsdp равен nil. 
ERROR_REVISION_MISMATCH — Структура, переданная в pbsdp неизвестного или неверного размера. 

BLUETOOTH_SELECT_DEVICE_PARAMS

Объявление: 

BLUETOOTH_SELECT_DEVICE_PARAMS = record
dwSize : DWORD;
cNumOfClasses : ULONG;
prgClassOfDevices : PBlueToothCodPairs; 
pszInfo : LPWSTR; 
hwndParent : HWND; 
fForceAuthentication : BOOL;
fShowAuthenticated : BOOL;
fShowRemembered : BOOL;
fShowUnknown : BOOL;
fAddNewDeviceWizard : BOOL;
fSkipServicesPage : BOOL; 
pfnDeviceCallback : PFN_DEVICE_CALLBACK;
pvParam : Pointer;
cNumDevices : DWORD;
pDevices : __PBLUETOOTH_DEVICE_INFO; 
end; 

Члены: 

wSize — Должен быть равен размеру структуры (dwSize := SizeOf(BLUETOOTH_RADIO_INFO)) 
cNumOfClasses — Входной параметр. Количество записей в массиве prgClassOfDevice. Если 0, то ищутся все устройства. 
prgClassOfDevices — Входной параметр. Массив COD (классов устройств), которые необходимо искать. 
pszInfo — Входной параметр. Если не nil, то задает текст заголовка окна выбора устройства. 
hwndParent — Входной параметр. Handle родительского окна для диалога выбора устройства. Если 0, то родителем будет Desktop. 
fForceAuthentication — Входной параметр. Если TRUE, то требует принудительной авторизации устройств. 
fShowAuthenticated — Входной параметр. Если TRUE, то авторизованные устройства будут доступны для выбора. 
fShowRemembered — Входной параметр. Если TRUE, то запомненные устройства будут доступны для выбора. 
fShowUnknown — Входной параметр. Если TRUE, то неизвестные (неавторизованные и не запомненные) устройства будут доступны для выбора. 
fAddNewDeviceWizard — Входной параметр. Если TRUE, то запускает мастер добавления нового устройства. 
fSkipServicesPage — Входной параметр. Если TRUE, то пропускает страницу Сервисы в мастере. 
pfnDeviceCallback — Входной параметр. Если не nil, то является указателем на функцию обратного вызова, которая вызывается для каждого найденного устройства. Если функция вернет TRUE, то устройства добавляется в список, если нет, то устройство игнорируется. 
pvParam — Входной параметр. Его значение будет передано функции pfnDeviceCallback в качестве параметра pvParam. 
cNumDevices — Как входной параметр – количество устройств, которое требуется вернуть. Если 0, то нет ограничений. Как выходной параметр – количество возвращенных устройств (выбранных). 
pDevices — Выходной параметр. Указатель на массив структур BLUETOOTH_DEVICE_INFO. Для его освобождения используйте функцию
BluetoothSelectDevicesFree.

Важно: В оригинале этот параметр объявлен как PBLUETOOTH_DEVICE_INFO. По этому поводу здесь много комментариев. 

BluetoothSelectDevicesFree — функция должна вызываться, только если вызов BluetoothSelectDevices был успешен. Эта функция освобождает память и ресурсы, задействованные функцией BluetoothSelectDevices в структуре BLUETOOTH_SELECT_DEVICE_PARAMS.

Объявление функции: 

function BluetoothSelectDevices(
pbtsdp : PBLUETOOTH_SELECT_DEVICE_PARAMS): BOOL; stdcall; 

Параметры: pbtsdp Описание смотрите выше в описании структуры. 

Возвращаемые значения: 

TRUE — если вызов успешен, 
FALSE — нечего освобождать. 

Управление сервисами 

Для управления сервисами Microsoft Bluetooth API предоставляет функцию:

BluetoothSetServiceState — включает или выключает указанный сервис для устройства Bluetooth. Система проецирует сервис Bluetooth на соответствующий драйвер. При отключении сервиса – драйвер удаляется. При его включении – драйвер устанавливается. Если выполняется включение не поддерживаемого сервиса, то драйвер не будет установлен.

Объявление функции: 

function BluetoothSetServiceState(
hRadio : Thandle;
var pbtdi : PBLUETOOTH_DEVICE_INFO;
const pGuidService : TGUID;
dwServiceFlags : DWORD): DWORD; stdcall; 

Параметры: 

hRadio — Описатель радиомодуля. 
pbtdi — Указатель на структуру BLUETOOTH_DEVICE_INFO. 
pGuidService — GUID сервиса, который необходимо включить/выключить. 
dwServiceFlags — Флаги управления сервисом:

BLUETOOTH_SERVICE_DISABLE – отключает сервис;
BLUETOOTH_SERVICE_ENABLE – включает сервис. 

Возвращает ERROR_SUCCESS если вызов прошел успешно. Если вызов не удался вернет один из следующих кодов:

ERROR_INVALID_PARAMETER — Неверные флаги в dwServiceFlags 
ERROR_SERVICE_DOES_NOT_EXIST — Указанный сервис не поддерживается 

Важно: В оригинале (см. примечание выше) функция выглядит вот так: 

function BluetoothSetServiceState(
hRadio : Thandle;
pbtdi : PBLUETOOTH_DEVICE_INFO;
const pGuidService : TGUID;
dwServiceFlags : DWORD): DWORD; stdcall; 

Это не верно, так как в документации Microsoft указано, что параметр pbtdi должен передаваться как указатель (что подразумевает запись PBLUETOOTH_DEVICE_INFO), но как я писал выше, этот тип ошибочен. Он не является указателем. Я изменил функцию так, как показано выше (так она и должна быть, если не менять определение типа). 

Как использовать функцию? Давайте добавим к ActionList еще одну TAction с такими свойствами:
Caption — Disable, Name — acEnable. И добавим на Panel еще одну кнопку TButton, установив у нее следующие свойства:
Action — acEnable, Name — btEnable.

В обработчике события OnUpdate для acEnable напишем вот такой код: 

procedure TfmMain.acEnableUpdate(Sender: TObject);
var
SelectedNode: TTreeNode;
SelectedItem: TListItem;
begin
SelectedNode := TreeView.Selected;
SelectedItem := ListView.Selected;

TAction(Sender).Enabled := Assigned(SelectedNode) and
Assigned(SelectedItem) and
(SelectedNode.ImageIndex = -2);
end; 

А в обработчике OnExecute для acEnable вот такой код: 

procedure TfmMain.acEnableExecute(Sender: TObject);
var
GUID: TGUID;
begin
GUID := StringToGUID(ListView.Selected.Caption);
BluetoothSetServiceState(TreeView.Selected.Parent.ImageIndex,
BLUETOOTH_DEVICE_INFO(TreeView.Selected.Data^),
GUID, 
BLUETOOTH_SERVICE_DISABLE);
end; 

Важно: После нажатия на кнопку btEnable сервис будет удален из системы. Включить его можно будет через окно свойств устройства Bluetooth.

Как определять отключенные сервисы рассмотрим в серии про передачу данных через Bluetooth.

Удаление устройств 

Для удаления устройств используется функция:

BluetoothRemoveDevice — функция удаляет авторизацию между компьютером и устройством Bluetooth. Так же очищает кэш-записи об этом устройстве.

Объявление функции: 

function BluetoothRemoveDevice(
var pAddress : BLUETOOTH_ADDRESS): DWORD; stdcall; 

Параметры: 

hAddress — Адрес устройства, которое удаляется. 

Возвращаемые значения: 

ERROR_SUCCESS — устройство удалено 
ERROR_NOT_FOUND — устройство не найдено 

Давайте попробуем. Добавим в ActionList TAction со следующими свойствами:
Caption — Remove, Name — acRemove. И на Panel кнопку TButton со свойствами:
Action — acRemove, Name — btRemove.

В обработчике OnUpdate для acRemove напишем следующий код: 

procedure TfmMain.acRemoveUpdate(Sender: TObject);
begin
TAction(Sender).Enabled := acProperty.Enabled;
end; 

А для события OnExecute вот такой код: 

procedure TfmMain.acRemoveExecute(Sender: TObject);
var
Info: BLUETOOTH_DEVICE_INFO;
Res: dword;
begin
Info := BLUETOOTH_DEVICE_INFO(ListView.Selected.Data^);
Res := BluetoothRemoveDevice(Info.Address);
if Res <> ERROR_SUCCESS then
MessageDlg(‘Device not found’, mtError, [mbOK], 0);
TreeViewChange(TreeView, TreeView.Selected);
end; 

Процедура выполняется достаточно долго, так что не думайте, что программа зависла.

Важно: Устройство удаляется из списка. Однако, если уже иметь адрес устройства, то можно получить о нем информацию.

Есть еще одно функция, которая связана с BluetoothRemoveDevice. Это:

BluetoothUpdateDeviceRecord — функция обновляет данные об устройстве в кэше.

Объявление функции: 

function BluetoothUpdateDeviceRecord(
var pbtdi : BLUETOOTH_DEVICE_INFO): DWORD; stdcall; 

Параметры: 

pbtdu — Указатель на структуру BLUETOOTH_DEVICE_INFO. 

В ней должны быть заполнены поля:
dwSize – размер структуры;
Address – адрес устройства;
szName – новое имя устройства. 

Возвращаемые значения: 

ERROR_SUCCESS — Функция выполнена успешно 
ERROR_INVALID_PARAMETER — Указатель pbtdi=nil. (Для варианта в Delphi не реально, так как указатель мы получаем из структуры, передавая ее как var-параметр). 
ERROR_REVISION_MISMATCH — Размер структуры в dwSize не правильный 

Попробуем использовать и ее. Схема стандартная: TAction к ActionList, TButton на
Panel: 
Caption — Update 
Name — acUpdate 

Action — acUpdate 
Name — btUpdate 

Код: 

procedure TfmMain.acUpdateUpdate(Sender: TObject);
begin
TAction(Sender).Enabled := acProperty.Enabled;
end; procedure TfmMain.acUpdateExecute(Sender: TObject);
var
Info: BLUETOOTH_DEVICE_INFO;
Res: dword;
NewName: string;
begin
if InputQuery(‘Имя устройства’, ‘Новое имя’, NewName) then begin
lstrcpyW(Info.szName, PWideChar(WideString(NewName)));
Res := BluetoothUpdateDeviceRecord(Info);
if Res <> ERROR_SUCCESS then RaiseLastOsError;
TreeViewChange(TreeView, TreeView.Selected);
end;
end; 

Как видите, все просто. 

Итак, удалять устройства мы умеем. Давайте теперь научимся добавлять их. Для этого Bluetooth API предоставляет две функции:

BluetoothAuthenticateDevice — отправляет запрос на авторизацию удаленному устройству Bluetooth. Есть два режима авторизации: «Wizrd mode» и «Blind Mode».

«Wizard Mode» запускается, когда параметр pszPasskey = nil. В этом случае открывается окно «Мастера подключения». У пользователя будет запрошен пароль, который будет отправлен в запросе на авторизацию удаленному устройству. Пользователь будет оповещен системой об успешном или не успешном выполнении авторизации и получит возможность попытаться авторизировать устройства еще раз.

«Blind Mode» вызывается, когда pszPasskey <> nil. В этом случае пользователь не увидит никакого мастера. Вам необходимо программно запросить код авторизации (pszPasskey) и уведомить пользователя о результате.

Объявление функции: 

function BluetoothAuthenticateDevice(
hwndParent : HWND;
hRadio : THandle;
pbtdi : BLUETOOTH_DEVICE_INFO;
pszPasskey : PWideChar;
ulPasskeyLength : ULONG): DWORD; stdcall; 

Параметры: 

hwndParent — Handle родительского окна. Если 0, то родительским окном станет окно Desktop. 
hRadio — Handle локального радиомодуля. Если 0, то авторизация будет проведена на всех радиомодулях. Если хотя бы один пройдет авторизацию, функция выполнится успешно. 
pbdti — Информация об устройстве, на котором необходимо авторизироваться. 
pszPasskey — PIN для авторизации. Если nil, то вызывается мастер авторизации (описано выше). Важно: pszPasskey не NULL-терминированная строка! 
ulPasskeyLength — Длина строки в байтах. Должна быть меньше либо равна BLUETOOTH_MAX_PASSKEY_SIZE * SizeOf(WCHAR). 

Возвращаемые значения: 

ERROR_SUCCESS — Функция выполнена успешно 
ERROR_CANCELLED — Пользователь отменил процесс авторизации 
ERROR_INVALID_PARAMETER — Структура pbtdi не верна 
ERROR_NO_MORE_ITEMS — Устройство в pbtdi уже авторизированно 

Аналогичная функция:

BluetoothAuthenticateMultipleDevices — позволяет авторизироваться сразу на нескольких устройствах при помощи одной копии «Мастера авторизации».

Объявление функции: 

function BluetoothAuthenticateMultipleDevices(
hwndParent : HWND;
hRadio : THandle;
cDevices : DWORD;
rgpbtdi : __PBLUETOOTH_DEVICE_INFO): DWORD; stdcall; 

Параметры: 

hwndParent — Handle родительского окна. Если 0, то родительским окном станет окно Desktop. 
hRadio — Handle локального радиомодуля. Если 0, то авторизация будет проведена на всех радиомодулях. Если хотя бы один пройдет авторизацию, функция выполнится успешно. 
cDevices — Количество элементов в массиве rgpbtdi. 
rgpbtdi — Массив структур BLUETOOTH_DEVICE_INFO, в котором представлены устройства для авторизации. 

Возвращаемые значения: 

ERROR_SUCCESS — Функция выполнена успешно. Проверьте флаг fAuthenticated у каждого устройства, что бы знать, какие прошли авторизацию. 
ERROR_CANCELLED — Пользователь отменил процесс авторизации. Проверьте флаг fAuthenticated у каждого устройства, что бы знать, какие прошли авторизацию. 
ERROR_INVALID_PARAMETER — Один или несколько элементов массива rgpbtdi не верны. 
ERROR_NO_MORE_ITEMS — Все устройства в массиве уже авторизированны. 

Важно: В оригинале функция выглядит вот так: 

function BluetoothAuthenticateMultipleDevices(
hwndParent : HWND;
hRadio : THandle;
cDevices : DWORD;
pbtdi : PBLUETOOTH_DEVICE_INFO): DWORD; stdcall; 

Это не верно, так как в документации Microsoft указано, что параметр rgpbtdi должен передаваться как указатель (что подразумевает запись PBLUETOOTH_DEVICE_INFO), но как я писал выше, этот тип ошибочен. Он не является указателем. Я изменил функцию так, как показано выше. По поводу типа __PBLUETOOTH_DEVICE_INFO я писал выше. 

Описывать с примером, как использовать эти функции не буду, так как они тривиальны (если вы прочитали все вышеизложенное). Остались последние три функции, которые мы не рассмотрели:

BluetoothRegisterForAuthentication — регистрирует функцию обратного вызова, которая будет вызываться на запрос устройства об авторизации. Если несколько приложений зарегистрировало такую функцию, то будет вызвана функция в последнем приложении.

Объявление функции: 

function BluetoothRegisterForAuthentication(
var pbtdi : PBLUETOOTH_DEVICE_INFO;
var phRegHandle : HBLUETOOTH_AUTHENTICATION_REGISTRATION;
pfnCallback : PFN_AUTHENTICATION_CALLBACK;
pvParam : Pointer): DWORD; stdcall; 

Параметры: 

pbtdi — Указатель на BLUETOOTH_DEVICE_INFO. Используется адрес устройства, для которого регистрируется функция. Обратите внимание на параметр. В оригинале он опять передается не как указатель. 
phRegHandle — Указатель, куда будет возвращен Handle регистрации, которой потом используется в BluetoothUnregisterAuthentication. 
pfnCallback — Функция обратного вызова. 
pvParam — Опциональный параметр, который без изменения передается в функцию обратного вызова. 

Возвращаемые значения: 

ERROR_SUCCESS — Функция выполнена успешно. 
ERROR_OUTOFMEMORY — Недостаточно памяти. 

BluetoothUnregisterAuthentication — удаляет функцию обратного вызова, зарегистрированную функцией BluetoothRegisterForAuthentication и закрывает Handle.

Объявление функции: 

function BluetoothUnregisterAuthentication(
hRegHandle : HBLUETOOTH_AUTHENTICATION_REGISTRATION): BOOL; stdcall; 

Параметры: 

hRegHandle — Handle регистрации, полученный функцией BluetoothRegisterForAuthentication. 

Возвращаемые значения:

Вернет TRUE, если вызов успешен и FALSE в случае неудачи. Используйте GetLastError для получения дополнительной информации.

BluetoothSendAuthenticationResponse — эта функция должна вызываться из функции обратного вызова при запросе авторизации удаленным устройством для передачи PIN.

Объявление функции: 

function BluetoothSendAuthenticationResponse(
hRadio : THandle;
pbtdi : PBLUETOOTH_DEVICE_INFO;
pszPasskey : LPWSTR): DWORD; stdcall; 

Параметры: 

hRadio — Handle радиомодуля, для которого проводим авторизацию. Если 0, то пытаемся на всех. 
pbtdi — Указатель на BLUETOOTH_DEVICE_INFO с данными об устройстве, от которого поступил запрос на авторизацию. Может быть тот же указатель, который передан в функцию обратного вызова. 
pszPasskey — Указатель на UNICODE строку, в которой содержится ключ авторизации (PIN). 

Возвращаемые значения: 

ERROR_SUCCESS — Функция выполнена успешно. 
ERROR_CANCELLED — Устройство отвергло авторизационный код (PIN). Так же, возможно, имеются проблемы со связью 
E_FAIL — Устройство вернуло ошибку авторизации. 

И, наконец, функция обратного вызова:

PFN_AUTHENTICATION_CALLBACK

Описание этой функции дано выше. Здесь приведу лишь определеннее.

Объявление функции: 

PFN_AUTHENTICATION_CALLBACK =
function(pvParam : Pointer;
pDevice : PBLUETOOTH_DEVICE_INFO): BOOL; stdcall; 

Параметры: 

pvParam — Указатель на параметр, который мы передали в BluetoothRegisterForAuthentication. 
pDevice — Указатель на BLUETOOTH_DEVICE_INFO с данными об устройстве, от которого поступил запрос на авторизацию. 

Заключение 

На этот раз все. Мы рассмотрели все функции Bluetooth API от Microsoft. Также мы научились управлять устройствами и радиомодулями Bluetooth, проводить авторизацию и получать информацию об этих устройствах.

Но актуальным остается вопрос, который мне многие задают. Как же все-таки передавать данные между устройствами
Bluetooth? Ответ на этот вопрос читайте в следующей
статье. Конечно, можно было бы всю эту информацию уместить в эти статьи, но объем ее не сравним с предоставленным здесь. Так что наберитесь терпения. Я постараюсь надолго не задерживать с выходом новой серии.
Полностью рабочий пример, рассмотренный в этой статье, вы можете
скачать здесь.

Я буду рад любым замечаниям и пожеланиям по данной теме.

P.S. Внимательно относитесь к сторонним библиотекам. Как видите, в JWALIB оказалось много ошибок, которые порой загоняют в тупик. Я минут 20 смотрел на Access Violation, пока не понял, в чем дело.

Оставить мнение

Check Also

Капкан на лису. Выполняем произвольный код из PDF через уязвимость в Foxit Reader

Foxit Reader — популярная программа для просмотра PDF. Занимает мало, работает быстро и дл…