c++ - Crash when connecting to Bluetooth device via WinAPI Socket (Access violation reading location 0x00000004) -


i think last hope. have got here bluetooth device (it sensor more precisely) want connect , read data from. device offers spp (serial port profile). avoid problem of reliable mapping bluetooth addresses , virtual serial ports (com ports), going use sockets.

unfortunately application crashes before returning winapi function connect(...) with: 0xc0000005: access violation reading location 0x00000004, no error code.

but, , weird, when right-click on bluetooth system tray icon to show available devices, device shows being authenticated , connected. list empty before, of course.

my os windows 7 64 bit, ide visual studio 2010, microsoft bluetooth stack. code find , connect device:

#include <iostream> #include <string> #include <algorithm> #include <cassert>  #define win32_lean_and_mean  #include <windows.h> #include <bluetoothapis.h> #include <winsock2.h> #include <ws2bth.h>    bool auth_callback_ex(lpvoid pvparam, pbluetooth_authentication_callback_params authparams) {     bluetooth_authenticate_response response;     response.bthaddressremote = authparams->deviceinfo.address;     response.authmethod = authparams->authenticationmethod; // == bluetooth_authentication_method_legacy      uchar pin[] = "1234";     std::copy(pin, pin+sizeof(pin), response.pininfo.pin);     response.pininfo.pinlength = sizeof(pin)-1; //excluding '\0'      response.negativeresponse = false;       hresult err = bluetoothsendauthenticationresponseex(null, &response);     if (err)     {         std::cout << "bluetoothsendauthenticationresponseex error = " << err << std::endl;     }      return true; }   int main() {     bluetooth_device_search_params btsearchparams;      btsearchparams.dwsize = sizeof(bluetooth_device_search_params);     btsearchparams.ctimeoutmultiplier = 5;  //5*1.28s search timeout     btsearchparams.fissueinquiry = true;    //new inquiry      //return known , unknown devices     btsearchparams.freturnauthenticated = true;     btsearchparams.freturnconnected = true;     btsearchparams.freturnremembered = true;     btsearchparams.freturnunknown = true;      btsearchparams.hradio = null;   //search on local radios        bluetooth_device_info btdeviceinfo;     zeromemory(&btdeviceinfo, sizeof(bluetooth_device_info));   //"initialize"      btdeviceinfo.dwsize = sizeof(bluetooth_device_info);      hbluetooth_device_find btdevicefindhandle = null;      btdevicefindhandle = bluetoothfindfirstdevice(&btsearchparams, &btdeviceinfo);     if(btdevicefindhandle)     {          hbluetooth_authentication_registration authcallbackhandle = null;          dword err = bluetoothregisterforauthenticationex(&btdeviceinfo, &authcallbackhandle, &auth_callback_ex, null);           if (err != error_success)         {             dword err = getlasterror();             std::cout << "bluetoothregisterforauthentication error" << err << std::endl;          }          /////////////// socket         wsadata wsadata;         err = wsastartup(makeword(2,2), &wsadata);         if (err)         {             std::cout << "wsastartup error = " << err << std::endl;         }           // create bt socket         socket s = socket (af_bth, sock_stream, bthproto_rfcomm);         assert(s != invalid_socket);    //wsagetlasterror //throw // runtime check release?          sockaddr_bth btsockaddr;         btsockaddr.addressfamily = af_bth;         btsockaddr.btaddr = btdeviceinfo.address.ulllong;         btsockaddr.serviceclassid = rfcomm_protocol_uuid; //serialportserviceclass_uuid (no difference)         btsockaddr.port = bt_port_any;           err = connect(s, reinterpret_cast<sockaddr*>(&btsockaddr), sizeof(sockaddr_bth));          /* <--- never got far --> */          if (err)         {             dword wsaerr = wsagetlasterror();             std::cout << "connect error = " << wsaerr << std::endl;          }         else         {             //err = shutdown(s, sd_both);              err = closesocket(s);             if (err)             {                 std::cout << "closesocket error = " << err << std::endl;             }         }          wsacleanup();         ///////////////socket           bool ok = bluetoothunregisterauthentication(authcallbackhandle);         if (!ok)         {             dword err = getlasterror();             std::cout << "bluetoothunregisterauthentication error" << err << std::endl;          }            ok = bluetoothfinddeviceclose(btdevicefindhandle);         if (!ok)         {             dword err = getlasterror();             std::cout << "bluetoothdeviceclose error" << err << std::endl;          }     }     else     {         dword err = getlasterror();         std::cout << "bluetoothfindfirstdevice error" << err << std::endl;      }       std::cin.get(); } 

i have made few more observations:

  • the authentication callback , bluetoothsendauthenticationresponseex function working fine, there no error given back.
  • if not install authentication callback (bluetoothregisterforauthenticationex) , therefore have manually enter pin (the ui shows automatically while trying connect), connect function returns , works fine, too. got data (the recv part omitted in snippet).
  • if search , pair manually (bluetooth tray icon -> add device), fine, too. service , virtual serial port installed. data come via putty.

so somewhere between calling authentication callback , end of connect function going wrong. maybe when trying structure data via pointer, should not null, plus offset.

or doing wrong? there missing? thanks...

the problem function using wrong calling convention. according msdn, need use callback macro, in:

bool callback auth_callback_ex(lpvoid pvparam, pbluetooth_authentication_callback_params authparams) 

having wrong calling convention result in stack mismatch on return, cause access violation inside ms bluetooth code when can't find local variables.

or result in parameters function being jumbled. if authparams , pvparam swapped, because cdecl calling convention expects args pushed right left , stdcall pushes them left right, you'd null in authparams, , authparams->deviceinfo.address try read address 0x04.

the compiler should have caught this. compile maximum warnings turned on (/w4). you'll have ignore warnings unknown pragma, bug in header i'm reporting microsoft (misspelled #pragma deprecated).

unfortunately there's a second bug in header, more serious, of not specifying calling convention explicitly, result work correctly on x86 (32-bit code) if /gz used. yuck!


followup: in sdk headers shipped vs2013, both issues fixed.


Comments

Popular posts from this blog

c# - SharpSVN - How to get the previous revision? -

c++ - Is it possible to compile a VST on linux? -

url - Querystring manipulation of email Address in PHP -