{*******************************************************}
{                                                       }
{       nrCommLib Communication Library for Delphi      }
{       BlueTooth Win32 API (XP) handler                }
{       Copyright (c) 1997-2011 Roman Novgorodov        }
{       v9.27                                           }
{       last update: 03 Jan 2006                        }
{                                                       }
{       e-mail:noro@deepsoftware.com                    }
{       DeepSoftware                                    }
{       http://www.deepsoftware.com/                    }
{                                                       }
{*******************************************************}
{$I nrcommlib.inc}
unit nrbtw32;
interface
uses  windows, winsock;

const

  BLUETOOTH_MAX_NAME_SIZE             = 248;
  BLUETOOTH_MAX_PASSKEY_SIZE          = 16;
  BLUETOOTH_MAX_PASSKEY_BUFFER_SIZE   = BLUETOOTH_MAX_PASSKEY_SIZE + 1;
  BTH_ADDR_STRING_SIZE                = 12;
  BLUETOOTH_NULL_ADDRESS              = 0;
  GUID_NULL                             :TGUID = '{00000000-0000-0000-0000-000000000000}';
  L2CAP_PROTOCOL_UUID                   :TGUID = '{00000100-0000-1000-8000-00805F9B34FB}';
  
  DialupNetworkingServiceClass_UUID     :TGUID = '{00001103-0000-1000-8000-00805F9B34FB}';
  SerialPortServiceClass_UUID           :TGUID = '{00001101-0000-1000-8000-00805F9B34FB}';
  OBEXObjectPushServiceClass_UUID       :TGUID = '{00001105-0000-1000-8000-00805F9B34FB}';
  OBEXFileTransferServiceClass_UUID     :TGUID = '{00001106-0000-1000-8000-00805F9B34FB}';
  HeadsetServiceClass_UUID              :TGUID = '{00001108-0000-1000-8000-00805F9B34FB}';
  CordlessTelephonyServiceClass_UUID    :TGUID = '{00001109-0000-1000-8000-00805F9B34FB}';
  AudioSourceServiceClass_UUID          :TGUID = '{0000110A-0000-1000-8000-00805F9B34FB}';
  AudioSinkServiceClass_UUID            :TGUID = '{0000110B-0000-1000-8000-00805F9B34FB}';
  FaxServiceClass_UUID                  :TGUID = '{00001111-0000-1000-8000-00805F9B34FB}';
  WAPServiceClass_UUID                  :TGUID = '{00001113-0000-1000-8000-00805F9B34FB}';
  WAPClientServiceClass_UUID            :TGUID = '{00001114-0000-1000-8000-00805F9B34FB}';
  HandsfreeServiceClass_UUID            :TGUID = '{0000111E-0000-1000-8000-00805F9B34FB}';
  HandsfreeAudioGatewayServiceClass_UUID:TGUID = '{0000111F-0000-1000-8000-00805F9B34FB}';
  HumanInterfaceDeviceServiceClass_UUID :TGUID = '{00001124-0000-1000-8000-00805F9B34FB}';
  GenericNetworkingServiceClass_UUID    :TGUID = '{00001201-0000-1000-8000-00805F9B34FB}';
  GenericFileTransferServiceClass_UUID  :TGUID = '{00001202-0000-1000-8000-00805F9B34FB}';
  GenericAudioServiceClass_UUID         :TGUID = '{00001203-0000-1000-8000-00805F9B34FB}';
  GenericTelephonyServiceClass_UUID     :TGUID = '{00001204-0000-1000-8000-00805F9B34FB}';

  SVCID_BTH_PROVIDER                    :TGUID = '{06aa63e0-7d60-41ff-afb2-3ee6d2d9392d}';

  AF_BTH                              = 32;
  BT_PORT_ANY                         = -1;
  BT_PORT_MIN                         = 1;
  BT_PORT_MAX                         = $ffff;
  BT_PORT_DYN_FIRST                   = $1001;
  BTHPROTO_RFCOMM                     = $0003;

  NS_BTH                              = 16;

  BLUETOOTH_SERVICE_DISABLE           = 00;
  BLUETOOTH_SERVICE_ENABLE            = 01;
//  BLUETOOTH_SERVICE_MASK              = BLUETOOTH_ENABLE_SERVICE or BLUETOOTH_DISABLE_SERVICE;

  LUP_DEEP                              = $0001;
  LUP_CONTAINERS                        = $0002;
  LUP_NOCONTAINERS                      = $0004;
  LUP_NEAREST                           = $0008;
  LUP_RETURN_NAME                       = $0010;
  LUP_RETURN_TYPE                       = $0020;
  LUP_RETURN_VERSION                    = $0040;
  LUP_RETURN_COMMENT                    = $0080;
  LUP_RETURN_ADDR                       = $0100;
  LUP_RETURN_BLOB                       = $0200;
  LUP_RETURN_ALIASES                    = $0400;
  LUP_RETURN_QUERY_STRING               = $0800;
  LUP_RETURN_ALL                        = $0FF0;
  LUP_RES_SERVICE                       = $8000;
  LUP_FLUSHCACHE                        = $1000;
  LUP_FLUSHPREVIOUS                     = $2000;


Type
 
  //  {$A8} this directive does not work in old delphi ...

  {$IFDEF GEN3}
    Int64=array[0..1]of integer;
  {$ENDIF}
  
  BTH_ADDR = int64;

  SOCKADDR_BTH = packed record
    addressFamily       :word;            // Always AF_BTH
    btAddr              :BTH_ADDR;        // Bluetooth device address
    serviceClassId      :TGUID;           // [OPTIONAL] system will query SDP for port
    port                :dword;           // RFCOMM channel or L2CAP PSM
  end;

  BLUETOOTH_ADDRESS = record
    case byte of
      0: (ullLong: BTH_ADDR);
      1: (rgBytes: array [0..5] of byte);
  end;

  BLUETOOTH_FIND_RADIO_PARAMS = record
    dwSize: DWORD;
  end;

  BLUETOOTH_RADIO_INFO = record
    dwSize:DWORD;
    dwSize2:DWORD;    // align field :-)
    address:BLUETOOTH_ADDRESS;
    szName: array [0 .. (BLUETOOTH_MAX_NAME_SIZE-1)] of WideChar;
    ulClassofDevice:DWORD;
    lmpSubversion:word;
    manufacturer:word;
  end;

  BLUETOOTH_DEVICE_SEARCH_PARAMS = record
    dwSize  : DWORD;                        //  IN  sizeof this structure
    fReturnAuthenticated        : BOOL;     //  IN  return authenticated devices
    fReturnRemembered           : BOOL;     //  IN  return remembered devices
    fReturnUnknown              : BOOL;     //  IN  return unknown devices
    fReturnConnected            : BOOL;     //  IN  return connected devices
    fIssueInquiry               : BOOL;     //  IN  issue a new inquiry
    cTimeoutMultiplier          : byte;     //  IN  timeout for the inquiry
    bAl                         : byte;     //  align field :-)
    wAl	                        : word;     //  align field :-)
    hRadio                      : THandle;    //  IN  handle to radio to enumerate - NULL == all radios will be searched
  end;


  BLUETOOTH_DEVICE_INFO = record
    dwSize              :dword;              //  size, in bytes, of this structure - must be the sizeof(BLUETOOTH_DEVICE_INFO)
    dwSize2		:DWORD;    	     //  align field :-)
    Address             :BLUETOOTH_ADDRESS;  //  Bluetooth address
    ulClassofDevice     :dword;              //  Bluetooth "Class of Device"
    fConnected          :BOOL;               //  Device connected/in use
    fRemembered         :BOOL;               //  Device remembered
    fAuthenticated      :BOOL;               //  Device authenticated/paired/bonded
    stLastSeen          :TSYSTEMTIME;        //  Last time the device was seen
    stLastUsed          :TSYSTEMTIME;        //  Last time the device was used for other than RNR, inquiry, or SDP
    szName:array [0..BLUETOOTH_MAX_NAME_SIZE-1] of WCHAR;  //  Name of the device
  end;
  PBLUETOOTH_DEVICE_INFO = ^BLUETOOTH_DEVICE_INFO;

  BLUETOOTH_COD_PAIRS = record
    ulCODMask           : ULONG;                          //  ClassOfDevice mask to compare
    pcszDescription     : PWideChar;                    //  Descriptive string of mask
  end;
  PBLUETOOTH_COD_PAIRS = ^BLUETOOTH_COD_PAIRS;

  BLUETOOTH_SELECT_DEVICE_PARAMS = record
    dwSize              : DWORD;                 //  IN  sizeof this structure
    cNumOfClasses       : dword;                 //  IN  Number in prgClassOfDevice - if ZERO search for all devices
    prgClassOfDevices   : PBLUETOOTH_COD_PAIRS;  //  IN  Array of CODs to find.

    pszInfo             : PWideChar;             //  IN  If not NULL, sets the "information" text
    hwndParent          : THAndle;                 //  IN  parent window - NULL == no parent

    fForceAuthentication: BOOL;                  //  IN  If TRUE, authenication will be forced before returning
    fShowAuthenticated  : BOOL;                  //  IN  If TRUE, authenticated devices will be shown in the picker
    fShowRemembered     : BOOL;                  //  IN  If TRUE, remembered devices will be shown in the picker
    fShowUnknown        : BOOL;                  //  IN  If TRUE, unknown devices that are not authenticated or "remember" will be shown.

    fAddNewDeviceWizard : BOOL;                  //  IN  If TRUE, invokes the add new device wizard.
    fSkipServicesPage   : BOOL;                  //  IN  If TRUE, skips the "Services" page in the wizard.

    pfnDeviceCallback   : pointer;                 //  IN  If non-NULL, a callback that will be called for each device. If the
                                                 //      the callback returns TRUE, the item will be added. If the callback is
                                                 //      is FALSE, the item will not be shown.
    pvParam             : pointer;                 //  IN  Parameter to be passed to pfnDeviceCallback as the pvParam.

    cNumDevices         : DWORD;                 //  IN  number calles wants - ZERO == no limit.
                                                 //  OUT the number of devices returned.
    pDevices            : PBLUETOOTH_DEVICE_INFO; //  OUT pointer to an array for BLUETOOTH_DEVICE_INFOs.
                                                 //      call BluetoothSelectDevicesFree() to free
  end;


  BLOB          = record
    cbSize      :dword;
    pBlobData   :pointer;
  end;
  PBLOB         =^BLOB;

  SOCKET_ADDRESS        = record
    lpSockaddr          :PSOCKADDR;
    iSockaddrLength     :integer;
  end;
  PSOCKET_ADDRESS       = ^SOCKET_ADDRESS;


  CSADDR_INFO   = record
    LocalAddr   :SOCKET_ADDRESS;
    RemoteAddr  :SOCKET_ADDRESS;
    iSocketType :integer;
    iProtocol   :integer;
  end;
  PCSADDR_INFO  =  ^CSADDR_INFO;


  AFPROTOCOLS   = record
    iAddressFamily      :integer;
    iProtocol           :integer;
  end;
  PAFPROTOCOLS  = ^AFPROTOCOLS;


  PSOCKADDR_BTH = ^SOCKADDR_BTH;

  WSAECOMPARATOR        = (COMP_EQUAL, COMP_NOTLESS);
  WSAVersion    = record
    dwVersion           :DWORD;
    ecHow               :WSAECOMPARATOR;
  end;
  PWSAVERSION   = ^WSAVERSION;


  WSAQUERYSET   = record
    dwSize                      :DWORD;
    lpszServiceInstanceName     :PAnsiChar;
    lpServiceClassId            :PGUID;
    lpVersion                   :PWSAVERSION;
    lpszComment                 :PAnsiChar;
    dwNameSpace                 :DWORD;
    lpNSProviderId              :PGUID;
    lpszContext                 :PAnsiChar;
    dwNumberOfProtocols         :dword;
    lpafpProtocols              :PAFPROTOCOLS;
    lpszQueryString             :PAnsiChar;
    dwNumberOfCsAddrs           :dword;
    lpcsaBuffer                 :PCSADDR_INFO;
    dwOutputFlags               :dword;
    lpBlob                      :PBLOB;
  end;

  PWSAQUERYSET           = ^WSAQUERYSET;

  //functions ...

  function BluetoothFindFirstRadio( var btfrp:BLUETOOTH_FIND_RADIO_PARAMS;
                                    var hRadio:THandle):THandle;
  function BluetoothFindNextRadio(hFind:THandle; var hRadio:THandle):boolean;
  function BluetoothFindRadioClose(hFind:THandle):boolean;
  function BluetoothGetRadioInfo(hRadio : THandle; var RadioInfo:BLUETOOTH_RADIO_INFO):dword;
  function BluetoothFindFirstDevice(var pbtsp:BLUETOOTH_DEVICE_SEARCH_PARAMS;
                                    var pbtdi:BLUETOOTH_DEVICE_INFO ):THandle;
  function BluetoothFindNextDevice(hFind:THandle; var pbtdi:BLUETOOTH_DEVICE_INFO):boolean;
  function BluetoothFindDeviceClose(hFind:THandle):boolean;

  function BluetoothIsConnectable(hRadio:THandle):boolean;
  function BluetoothIsDiscoverable(hRadio:THandle):boolean;

  function BluetoothEnableDiscovery(hRadio:THandle; fEnabled:boolean):boolean;
  function BluetoothEnableIncomingConnections(hRadio:THandle; fEnabled:boolean):boolean;
  function BluetoothDisplayDeviceProperties(hwndParent:THandle;
                  var pbtdi: BLUETOOTH_DEVICE_INFO):boolean;

  function BluetoothSelectDevices(var pbtsdp:BLUETOOTH_SELECT_DEVICE_PARAMS):boolean;
  function BluetoothSelectDevicesFree(var pbtsdp:BLUETOOTH_SELECT_DEVICE_PARAMS):boolean;

  function BluetoothRemoveDevice(var pAddress:BLUETOOTH_ADDRESS):dword;

  function BluetoothUpdateDeviceRecord(var pbtdi:BLUETOOTH_DEVICE_INFO):dword;

  function BluetoothEnumerateInstalledServices(hRadio:THandle;
              var pbtdi: BLUETOOTH_DEVICE_INFO; var pcServices:integer;
              pGuidServices:pointer):dword;

  function BluetoothSetServiceState(hRadio:THandle;
             var pbtdi : BLUETOOTH_DEVICE_INFO;
             pGuidService : PGUID; dwServiceFlags: DWORD):dword;

  function BluetoothAuthenticateDevice(hwndParent:THandle; hRadio:THandle;
                                        var pbtdi:BLUETOOTH_DEVICE_INFO;
                                        pszPasskey:PWideChar;
                                        ulPasskeyLength:ULONG):dword;

  function connect(aSck:integer; addr:pointer; sz:integer):integer;
           stdcall; external 'wsock32.dll' name 'connect';
  function bind(aSck:integer; addr:pointer; sz:integer):integer;
           stdcall; external 'wsock32.dll' name 'bind';
  function getsockname(aSck:integer; addr:pointer; sz:integer):integer;
           stdcall; external 'wsock32.dll' name 'getsockname';

  function WSALookupServiceBegin(lpqsRestrictions:PWSAQUERYSET; dwControlFlags:dword; var lphLookup:THandle):integer;
//           stdcall; external 'Ws2_32.dll' name 'WSALookupServiceBeginA';
  function WSALookupServiceNext(hLookup:THandle; dwControlFlags:dword;var lpdwBufferLength :dword;
           lpqsResults:PWSAQUERYSET):integer;
//           stdcall; external 'Ws2_32.dll' name 'WSALookupServiceNextA';
  function WSALookupServiceEnd(hLookup:THandle):integer;
           //stdcall; external 'Ws2_32.dll' name 'WSALookupServiceEnd';


  function AllocBTAPI:boolean;

implementation

var
  hBTDLL  : THandle  = 0;
  hWS2DLL : THandle  = 0;

const
  BTDll         = 'irprops.cpl';
  WS2Dll        = 'Ws2_32.dll';

function AllocBTAPI:boolean;
begin
  if hBTDLL = 0 then hBTDLL := LoadLibrary(BTDll);
  Result := hBTDLL <> 0 ;
end;

function AllocWS2:boolean;
begin
  if hWS2DLL = 0 then hWS2DLL := LoadLibrary(WS2Dll);
  Result := hWS2DLL <> 0 ;
end;

procedure FreeBTAPI;
begin
  if hBTDLL <> 0 then FreeLibrary(hBTDLL);
  hBTDLL := 0;
  if hWS2DLL <> 0 then FreeLibrary(hWS2DLL);
  hWS2DLL := 0;
end;

function BluetoothFindFirstRadio(
    var btfrp:BLUETOOTH_FIND_RADIO_PARAMS;
    var hRadio:THandle):THandle;
var p: function(var btfrp:BLUETOOTH_FIND_RADIO_PARAMS; var hRadio:THandle):THandle; stdcall;
begin
  Result := 0;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothFindFirstRadio');
    if @p <> nil then Result := p(btfrp,hRadio);
  end;
end;

function BluetoothFindNextRadio(hFind:THandle; var hRadio:THandle):boolean;
var p: function(hFind:THandle; var hRadio:THandle):boolean; stdcall;
begin
  Result := False;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothFindNextRadio');
    if @p <> nil then Result := p(hFind,hRadio);
  end;
end;


function BluetoothFindRadioClose(hFind:THandle):boolean;
var p: function(hFind:THandle):boolean; stdcall;
begin
  Result := False;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothFindRadioClose');
    if @p <> nil then Result := p(hFind);
  end;
end;

function BluetoothGetRadioInfo(hRadio:THandle;
         var RadioInfo: BLUETOOTH_RADIO_INFO):dword;
var p: function(hRadio:THandle; var RadioInfo: BLUETOOTH_RADIO_INFO):dword; stdcall;
begin
  Result := ERROR_INVALID_PARAMETER;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothGetRadioInfo');
    if @p <> nil then Result := p(hRadio,RadioInfo);
  end;
end;

function BluetoothFindFirstDevice(var pbtsp:BLUETOOTH_DEVICE_SEARCH_PARAMS;
    var pbtdi:BLUETOOTH_DEVICE_INFO ):THandle;
var p: function(var pbtsp:BLUETOOTH_DEVICE_SEARCH_PARAMS;
                var pbtdi:BLUETOOTH_DEVICE_INFO):THandle; stdcall;
begin
  Result := 0;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothFindFirstDevice');
    if @p <> nil
      then Result := p(pbtsp,pbtdi);
  end;
end;

function BluetoothFindNextDevice(hFind:THandle; var pbtdi:BLUETOOTH_DEVICE_INFO):boolean;
var p: function(hFind:THandle; var pbtdi:BLUETOOTH_DEVICE_INFO):boolean; stdcall;
begin
  Result := False;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothFindNextDevice');
    if @p <> nil then Result := p(hFind,pbtdi);
  end;
end;

function BluetoothFindDeviceClose(hFind:THandle):boolean;
var p: function(hFind:THandle):boolean; stdcall;
begin
  Result := False;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothFindDeviceClose');
    if @p <> nil then Result := p(hFind);
  end;
end;

function BluetoothIsConnectable(hRadio:THandle):boolean;
var p: function(hRadio:THandle):boolean; stdcall;
begin
  Result := False;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothIsConnectable');
    if @p <> nil then Result := p(hRadio);
  end;
end;

function BluetoothIsDiscoverable(hRadio:THandle):boolean;
var p: function(hRadio:THandle):boolean; stdcall;
begin
  Result := False;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothIsDiscoverable');
    if @p <> nil then Result := p(hRadio);
  end;
end;

function BluetoothEnableDiscovery(hRadio:THandle; fEnabled:boolean):boolean;
var p: function(hRadio:THandle;fEnabled:boolean):boolean; stdcall;
begin
  Result := False;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothEnableDiscovery');
    if @p <> nil then Result := p(hRadio,fEnabled);
  end;
end;

function BluetoothEnableIncomingConnections(hRadio:THandle; fEnabled:boolean):boolean;
var p: function(hRadio:THandle;fEnabled:boolean):boolean; stdcall;
begin
  Result := False;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothEnableIncomingConnections');
    if @p <> nil then Result := p(hRadio,fEnabled);
  end;
end;

function BluetoothDisplayDeviceProperties(hwndParent:THandle;
                  var pbtdi: BLUETOOTH_DEVICE_INFO):boolean;
var p: function(hwndParent:THandle;var pbtdi: BLUETOOTH_DEVICE_INFO):boolean; stdcall;
begin
  Result := False;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothDisplayDeviceProperties');
    if @p <> nil then Result := p(hwndParent,pbtdi);
  end;
end;

function BluetoothRemoveDevice(var pAddress:BLUETOOTH_ADDRESS):dword;
var p: function(var pAddress:BLUETOOTH_ADDRESS):dword; stdcall;
begin
  Result := 0;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothRemoveDevice');
    if @p <> nil then Result := p(pAddress);
  end;
end;

function BluetoothSelectDevices(var pbtsdp:BLUETOOTH_SELECT_DEVICE_PARAMS):boolean;
var p: function(var pbtsdp:BLUETOOTH_SELECT_DEVICE_PARAMS):boolean; stdcall;
begin
  Result := False;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothSelectDevices');
    if @p <> nil then Result := p(pbtsdp);
  end;
end;

function BluetoothSelectDevicesFree(var pbtsdp:BLUETOOTH_SELECT_DEVICE_PARAMS):boolean;
var p: function(var pbtsdp:BLUETOOTH_SELECT_DEVICE_PARAMS):boolean; stdcall;
begin
  Result := False;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothSelectDevicesFree');
    if @p <> nil then Result := p(pbtsdp);
  end;
end;

function BluetoothUpdateDeviceRecord(var pbtdi:BLUETOOTH_DEVICE_INFO):dword;
var p: function(var pbtdi:BLUETOOTH_DEVICE_INFO):dword; stdcall;
begin
  Result := 0;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothUpdateDeviceRecord');
    if @p <> nil then Result := p(pbtdi);
  end;
end;

function BluetoothEnumerateInstalledServices(hRadio:THandle;
               var pbtdi:BLUETOOTH_DEVICE_INFO; var pcServices:integer;
                pGuidServices:pointer):dword;
var p: function(hRadio:THandle;
                var pbtdi: BLUETOOTH_DEVICE_INFO; var pcServices:integer;
                pGuidServices:pointer):dword; stdcall;
begin
  Result := 0;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothEnumerateInstalledServices');
    if @p <> nil then Result := p(hRadio,pbtdi,pcServices,pGuidServices);
  end;
end;

function BluetoothSetServiceState(hRadio:THandle; var pbtdi : BLUETOOTH_DEVICE_INFO;
             pGuidService : PGUID; dwServiceFlags: DWORD):dword;
var p: function(hRadio:THandle; var pbtdi : BLUETOOTH_DEVICE_INFO;
           pGuidService : PGUID; dwServiceFlags: DWORD):dword; stdcall;
begin
  Result := 0;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothSetServiceState');
    if @p <> nil then Result := p(hRadio,pbtdi, pGuidService, dwServiceFlags);
  end;
end;

function BluetoothAuthenticateDevice(hwndParent:THandle; hRadio:THandle;
                                        var pbtdi:BLUETOOTH_DEVICE_INFO; 
                                        pszPasskey:PWideChar;
                                        ulPasskeyLength:ULONG):dword;
var p: function(hwndParent:THandle; hRadio:THandle;
                var pbtdi:BLUETOOTH_DEVICE_INFO;
                pszPasskey:PWideChar; ulPasskeyLength:ULONG):dword; stdcall;
begin
  Result := 0;
  if AllocBTAPI then begin
    @p:=GetProcAddress(hBTDLL,'BluetoothAuthenticateDevice');
    if @p <> nil then Result := p(hwndParent, hRadio, pbtdi, pszPasskey, ulPasskeyLength);
  end;
end;

function WSALookupServiceBegin(lpqsRestrictions:PWSAQUERYSET; dwControlFlags:dword; var lphLookup:THandle):integer;
var p:  function (lpqsRestrictions:PWSAQUERYSET; dwControlFlags:dword; var lphLookup:THandle):integer;
           stdcall;
begin
  Result := 0;
  if AllocWS2 then begin
    @p:=GetProcAddress(hWS2DLL,'WSALookupServiceBeginA');
    if @p <> nil then Result := p(lpqsRestrictions, dwControlFlags, lphLookup);
  end;
end;


function WSALookupServiceNext(hLookup:THandle; dwControlFlags:dword;var lpdwBufferLength :dword;
           lpqsResults:PWSAQUERYSET):integer;
var p:  function (hLookup: THandle; dwControlFlags:dword;var lpdwBufferLength :dword;
           lpqsResults:PWSAQUERYSET):integer; stdcall;
begin
  Result := 0;
  if AllocWS2 then begin
    @p:=GetProcAddress(hWS2DLL,'WSALookupServiceNextA');
    if @p <> nil then Result := p(hLookup,dwControlFlags,lpdwBufferLength,lpqsResults);
  end;
end;

function WSALookupServiceEnd(hLookup:THandle):integer;
var p: function (hLookup:THandle):integer; stdcall;
begin
  Result := 0;
  if AllocWS2 then begin
    @p:=GetProcAddress(hWS2DLL,'WSALookupServiceEnd');
    if @p <> nil then Result := p(hLookup);
  end;
end;

initialization

finalization
  FreeBTAPI;
end.
