btgw.cxx

Upload User: nicenough
Upload Date: 2007-05-05
Package Size: 501k
Code Size: 50k
Category: Driver Develop
Development Platform: C++
  1. //
  2. // Copyright (c) Microsoft Corporation.  All rights reserved.
  3. //
  4. //
  5. // Use of this source code is subject to the terms of the Microsoft end-user
  6. // license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
  7. // If you did not accept the terms of the EULA, you are not authorized to use
  8. // this source code. For a copy of the EULA, please see the LICENSE.RTF on your
  9. // install media.
  10. //
  11. /**
  12. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
  13. EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
  14. WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
  15. Abstract:
  16. Windows CE Bluetooth application sample
  17. **/
  18. #include <windows.h>
  19. #include <winsock2.h>
  20. #include <ras.h>
  21. #include <raserror.h>
  22. #include <afdfunc.h>
  23. #include <ws2bth.h>
  24. #include <bt_sdp.h>
  25. #include <bthapi.h>
  26. #include <bt_api.h>
  27. extern "C" DWORD RasIOControl(LPVOID hRasConn, DWORD dwCode, PBYTE pBufIn,
  28.    DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,
  29.    PDWORD pdwActualOut);
  30. #undef WSAGetLastError
  31. #define WSAGetLastError() GetLastError()
  32. //
  33. // Constants & macros
  34. //
  35. //
  36. #define IPADDR(x) ((x>>24) & 0x000000ff), ((x>>16) & 0x000000ff), ((x>>8) & 0x000000ff),  (x & 0x000000ff)
  37. #define CRLF L"rn"
  38. #define CONFIG_NAME L"WinCEBlueGW.config"
  39. #define CONFIG_NAME_SZ (sizeof(CONFIG_NAME)/sizeof(WCHAR) - 1)
  40. #define GW_SLEEP 30
  41. #define SDP_RECORD_SIZE 0x0000004d
  42. #define SDP_CHANNEL_OFFSET 26
  43. static const BYTE rgbSdpRecordLAN[] = {
  44.     0x35, 0x4b, 0x09, 0x00, 0x01, 0x35, 0x03, 0x19,
  45.     0x11, 0x02, 0x09, 0x00, 0x04, 0x35, 0x0c, 0x35,
  46.     0x03, 0x19, 0x01, 0x00, 0x35, 0x05, 0x19, 0x00,
  47.     0x03, 0x08,
  48. 0x01, // server channel goes here (+26)
  49.   0x09, 0x00, 0x06, 0x35, 0x09,
  50.     0x09, 0x65, 0x6e, 0x09, 0x00, 0x6a, 0x09, 0x01,
  51.     0x00, 0x09, 0x00, 0x09, 0x35, 0x08, 0x35, 0x06,
  52.     0x19, 0x11, 0x02, 0x09, 0x01, 0x00, 0x09, 0x01,
  53.     0x00, 0x25, 0x12, 'L',  'a',  'n',  ' ',  'A',
  54.     'c',  'c',  'e',  's',  's',  ' ',  'P',  'r',
  55.     'o',  'f',  'i',  'l',  'e'
  56. };
  57. static const BYTE rgbSdpRecordDUN[] = {
  58.     0x35, 0x4b, 0x09, 0x00, 0x01, 0x35, 0x03, 0x19,
  59.     0x11, 0x03, 0x09, 0x00, 0x04, 0x35, 0x0c, 0x35,
  60.     0x03, 0x19, 0x01, 0x00, 0x35, 0x05, 0x19, 0x00,
  61.     0x03, 0x08,
  62. 0x01, // server channel goes here (+26)
  63.   0x09, 0x00, 0x06, 0x35, 0x09,
  64.     0x09, 0x65, 0x6e, 0x09, 0x00, 0x6a, 0x09, 0x01,
  65.     0x00, 0x09, 0x00, 0x09, 0x35, 0x08, 0x35, 0x06,
  66.     0x19, 0x11, 0x03, 0x09, 0x01, 0x00, 0x09, 0x01,
  67.     0x00, 0x25, 0x12, 'D',  'i',  'a',  'l',  '-',
  68.     'u',  'p',  ' ',  'N',  'e',  't',  'w',  'o',
  69.     'r',  'k',  'i',  'n',  'g'
  70. };
  71. const DWORD bmProhibitAll = RASEO_ProhibitPAP |
  72. RASEO_ProhibitCHAP |
  73. RASEO_ProhibitMsCHAP |
  74. RASEO_ProhibitMsCHAP2 |
  75. RASEO_ProhibitEAP;
  76. //
  77. // Data types
  78. //
  79. //
  80. struct Port {
  81. Port *pNext;
  82. unsigned int fOld : 1;
  83. unsigned int fModem : 1;
  84. int index;
  85. int index2;
  86. unsigned char channel;
  87. HANDLE hDevice; // Primary port
  88. HANDLE hDevice2; // Secondary port (when primary is a filter)
  89. HANDLE hFile; // File handle
  90. HANDLE hThread; // Monitoring thread
  91. WCHAR szDevName[_MAX_PATH];
  92. Port (void) {
  93. memset (this, 0, sizeof(*this));
  94. hFile = INVALID_HANDLE_VALUE;
  95. }
  96. };
  97. struct Security {
  98. Security *pNext;
  99. int fDeletePIN;
  100. int             fDeleteKEY;
  101. BT_ADDR bt;
  102. int cPin;
  103. int cKey;
  104. unsigned char acPin[16];
  105. unsigned char acKey[16];
  106. Security (void) {
  107. memset (this, 0, sizeof(*this));
  108. }
  109. };
  110. struct Config {
  111. Port *pPortList;
  112. Security *pSecurityList;
  113. int fa;
  114. int fe;
  115. unsigned int    uiRasAuth;
  116. Config (void) {
  117. memset (this, 0, sizeof(*this));
  118. }
  119. };
  120. struct PortThreadArgs {
  121. HANDLE hFile;
  122. int    fLan;
  123. };
  124. static inline WCHAR hxd(unsigned char c) {
  125. if (c >= 10)
  126. return c - 10 + 'a';
  127. return c + '0';
  128. }
  129. static int GetDI (WCHAR **pp, unsigned int *pi) {
  130. while (iswspace(**pp))
  131. ++*pp;
  132. int iDig = 0;
  133. *pi = 0;
  134. while (iswdigit (**pp)) {
  135. int c = **pp;
  136. c = c - '0';
  137. if ((c < 0) || (c > 9))
  138. return FALSE;
  139. *pi = *pi * 10 + c;
  140. ++*pp;
  141. ++iDig;
  142. }
  143. if ((iDig <= 0) || (iDig > 10))
  144. return FALSE;
  145. return TRUE;
  146. }
  147. static int GetBA (WCHAR **pp, BT_ADDR *pba) {
  148.     memset (pba, 0, sizeof (BT_ADDR));
  149.     while (iswspace(**pp))
  150. ++*pp;
  151. for (int i = 0 ; i < 12 ; ++i, ++*pp) {
  152. if (! iswxdigit (**pp))
  153. return FALSE;
  154. int c = **pp;
  155. if (c >= 'a')
  156. c = c - 'a' + 0xa;
  157. else if (c >= 'A')
  158. c = c - 'A' + 0xa;
  159. else c = c - '0';
  160. if ((c < 0) || (c > 16))
  161. return FALSE;
  162. *pba = *pba * 16 + c;
  163. }
  164. if ((! iswspace(**pp)) && (**pp != ''))
  165. return FALSE;
  166. return TRUE;
  167. }
  168. static int GetUx (WCHAR **pp, void *pRes, int nDigs, int fPrefix) {
  169. while (iswspace(**pp))
  170. ++*pp;
  171. if (fPrefix) {
  172. if (**pp != '0')
  173. return FALSE;
  174. ++*pp;
  175. if (**pp != 'x')
  176. return FALSE;
  177. ++*pp;
  178. }
  179. int iDig = 0;
  180. int iRes = 0;
  181. while (iswxdigit (**pp)) {
  182. int c = **pp;
  183. if (c >= 'a')
  184. c = c - 'a' + 0xa;
  185. else if (c >= 'A')
  186. c = c - 'A' + 0xa;
  187. else c = c - '0';
  188. if ((c < 0) || (c > 16))
  189. return FALSE;
  190. iRes = iRes * 16 + c;
  191. ++*pp;
  192. ++iDig;
  193. }
  194. if (iDig != nDigs) // ???????????? iDig > nDig
  195. return FALSE;
  196. switch (nDigs) {
  197. case 2:
  198. *(unsigned char *)pRes = (unsigned char)iRes;
  199. break;
  200. case 4:
  201. *(unsigned short *)pRes = (unsigned short)iRes;
  202. break;
  203. case 8:
  204. *(unsigned int *)pRes = (unsigned int)iRes;
  205. break;
  206. }
  207. return TRUE;
  208. }
  209. //
  210. // PPP server configuration and management
  211. //
  212. //
  213. static DWORD GetServerParameters(RASCNTL_SERVERSTATUS *pParameters) {
  214. DWORD cbParameters;
  215. DWORD dwResult = RasIOControl(0, RASCNTL_SERVER_GET_PARAMETERS, 0, 0, (unsigned char *)pParameters, sizeof(*pParameters), &cbParameters);
  216. if (dwResult != 0)
  217. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Unable to get PPP server parameters, error=%d" CRLF, dwResult));
  218. return dwResult;
  219. }
  220. static DWORD SetServerParameters(RASCNTL_SERVERSTATUS *pParameters) {
  221. DWORD dwResult = RasIOControl(0, RASCNTL_SERVER_SET_PARAMETERS, (unsigned char *)pParameters, sizeof(*pParameters), NULL, 0, NULL);
  222. if (dwResult != 0)
  223. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Unable to set PPP server parameters, error=%d" CRLF, dwResult));
  224. return dwResult;
  225. }
  226. static DWORD SetGlobalPPPConfig (void) {
  227. DWORD fDHCP = TRUE;
  228. HKEY hk;
  229. if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"software\microsoft\bluetooth\gateway", 0, KEY_READ, &hk)) {
  230. DWORD dwType = 0;
  231. DWORD dwSize = sizeof(fDHCP);
  232. RegQueryValueEx (hk, L"UseDHCP", NULL, &dwType, (BYTE *)&fDHCP, &dwSize);
  233. if (! fDHCP) {
  234. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: NOT using DHCP for dialup lines" CRLF));
  235. }
  236. RegCloseKey (hk);
  237. }
  238. RASCNTL_SERVERSTATUS Parameters;
  239. DWORD dwResult = RasIOControl(0, RASCNTL_SERVER_ENABLE, 0, 0, NULL, 0, NULL);
  240. if (dwResult != ERROR_SUCCESS)
  241. return dwResult;
  242. dwResult = GetServerParameters(&Parameters);
  243. if (dwResult == ERROR_SUCCESS) {
  244. Parameters.bUseDhcpAddresses = fDHCP;
  245. dwResult = SetServerParameters(&Parameters);
  246. }
  247. if (dwResult == ERROR_SUCCESS) {
  248. RASCNTL_SERVERUSERCREDENTIALS Credentials;
  249. memset(&Credentials, 0, sizeof(Credentials));
  250. wcscpy (Credentials.tszUserName, L"guest");
  251. strcpy ((char *)Credentials.password, "guest");
  252. Credentials.cbPassword = strlen ((char *)Credentials.password) + 1;
  253. dwResult = RasIOControl(0, RASCNTL_SERVER_USER_SET_CREDENTIALS, (PUCHAR)&Credentials, sizeof(Credentials), NULL, 0, NULL);
  254. }
  255. return dwResult;
  256. }
  257. static DWORD GetLineDevices (LPRASDEVINFOW *ppRasDevInfo, PDWORD pcDevices) {
  258. DWORD cbNeeded = 0;
  259. DWORD dwResult = ERROR_SUCCESS;
  260. *pcDevices = 0;
  261.     *ppRasDevInfo = NULL;
  262. RasIOControl(0, RASCNTL_ENUMDEV, NULL, 0, (PUCHAR)&cbNeeded, 0, pcDevices);
  263. if (cbNeeded) {
  264. *ppRasDevInfo = (LPRASDEVINFOW)malloc(cbNeeded);
  265. if (*ppRasDevInfo == NULL) {
  266. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Unable to allocate %d bytes of memory to store device info" CRLF, cbNeeded));
  267. dwResult = ERROR_OUTOFMEMORY;
  268. } else {
  269. (*ppRasDevInfo)->dwSize = sizeof(RASDEVINFOW);
  270. dwResult = RasIOControl(0, RASCNTL_ENUMDEV, (PUCHAR)*ppRasDevInfo, 0, (PUCHAR)&cbNeeded, 0, pcDevices);
  271. }
  272. }
  273. return dwResult;
  274. }
  275. static void DisplayPPP (void) {
  276. RASCNTL_SERVERSTATUS *pStatus = NULL;
  277. DWORD  cbStatus = 0;
  278. //
  279. // First pass is to get the size
  280. //
  281. RasIOControl(0, RASCNTL_SERVER_GET_STATUS, 0, 0, NULL, 0, &cbStatus);
  282. if (cbStatus)
  283. pStatus = (RASCNTL_SERVERSTATUS *)malloc (cbStatus);
  284. if (pStatus) {
  285. DWORD dwResult = RasIOControl(0, RASCNTL_SERVER_GET_STATUS, 0, 0, (PUCHAR)pStatus, cbStatus, &cbStatus);
  286. if (dwResult == ERROR_SUCCESS) {
  287. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Ras Server Status:" CRLF));
  288. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: tEnabled               = %x" CRLF, pStatus->bEnable));
  289. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: tFlags                 = %x" CRLF, pStatus->bmFlags));
  290. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: tUseDhcpAddresses      = %d" CRLF,  pStatus->bUseDhcpAddresses));
  291. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: tStaticIpAddrStart     = %u.%u.%u.%u" CRLF,  IPADDR(pStatus->dwStaticIpAddrStart)));
  292. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: tStaticIpAddrCount     = %u" CRLF,  pStatus->dwStaticIpAddrCount));
  293. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: tAuthenticationMethods = %x" CRLF,  pStatus->bmAuthenticationMethods));
  294. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: tNumLines              = %u" CRLF, pStatus->dwNumLines));
  295. //
  296. // Per line info is in an array immediately following the global server status struct
  297. //
  298.             RASCNTL_SERVERLINE   *pLine = (RASCNTL_SERVERLINE *)(&pStatus[1]);
  299. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Configured Line Devices:" CRLF));
  300. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Type   Flags IdleTO Name" CRLF));
  301. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: ------ ----- ------ ----" CRLF));
  302. for (int iLine = 0; iLine < (int)pStatus->dwNumLines; iLine++, pLine++)
  303. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: %6s %5x %6d %s" CRLF, pLine->rasDevInfo.szDeviceType, pLine->bmFlags, pLine->DisconnectIdleSeconds, pLine->rasDevInfo.szDeviceName));
  304. } else
  305. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: RasIOControl failed, error = %d" CRLF, dwResult));
  306. free(pStatus);
  307. }
  308. LPRASDEVINFOW pRasDevInfo;
  309. DWORD cDevices;
  310. DWORD dwResult = GetLineDevices(&pRasDevInfo, &cDevices);
  311. if (dwResult == 0) {
  312. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Available RAS Line Devices:" CRLF));
  313. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: ##  Type     Name" CRLF));
  314. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: -- ------   ----" CRLF));
  315. for (int iDevice = 0; iDevice < (int)cDevices; iDevice++)
  316. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: %2d %6s   %s" CRLF, iDevice, pRasDevInfo[iDevice].szDeviceType, pRasDevInfo[iDevice].szDeviceName));
  317. }
  318. if (pRasDevInfo)
  319. free (pRasDevInfo);
  320. }
  321. static DWORD GetDeviceInfo (WCHAR *szDeviceName, RASDEVINFO *DeviceInfo) {
  322. LPRASDEVINFOW pRasDevInfo;
  323. DWORD cDevices;
  324. DWORD dwResult = GetLineDevices(&pRasDevInfo, &cDevices);
  325. if (dwResult == ERROR_SUCCESS) {
  326. dwResult = ERROR_NOT_FOUND;
  327. for (int i = 0; i < (int)cDevices; i++) {
  328. if (_tcscmp(pRasDevInfo[i].szDeviceName, szDeviceName) == 0) {
  329. *DeviceInfo = pRasDevInfo[i];
  330. dwResult = ERROR_SUCCESS;
  331. break;
  332. }
  333. }
  334. }
  335. if (pRasDevInfo)
  336. free (pRasDevInfo);
  337. return dwResult;
  338. }
  339. static DWORD
  340. LineGetParameters(
  341. IN RASCNTL_SERVERLINE *pLine,
  342. OUT RASCNTL_SERVERLINE  **ppOutBuf,
  343. OUT DWORD *pdwOutBufSize)
  344. {
  345. DWORD dwResult = 0;
  346. PRASCNTL_SERVERLINE  pOutBuf = NULL;
  347. DWORD dwOutBufSize = 0,
  348.   dwNeededSize;
  349. do
  350. {
  351. dwResult = RasIOControl(0, RASCNTL_SERVER_LINE_GET_PARAMETERS, (PUCHAR)pLine, sizeof(*pLine), (PUCHAR)pOutBuf, dwOutBufSize, &dwNeededSize);
  352. if (dwResult != ERROR_BUFFER_TOO_SMALL)
  353. break;
  354. // Free old buffer
  355. if (pOutBuf)
  356. LocalFree(pOutBuf);
  357. // Allocate new buffer
  358. pOutBuf = (PRASCNTL_SERVERLINE)LocalAlloc (LPTR, dwNeededSize);
  359. if (pOutBuf == NULL)
  360. {
  361. dwResult = ERROR_OUTOFMEMORY;
  362. break;
  363. }
  364. dwOutBufSize = dwNeededSize;
  365. } while (TRUE);
  366. *ppOutBuf = pOutBuf;
  367. *pdwOutBufSize = dwOutBufSize;
  368. return dwResult;
  369. }
  370. static DWORD LineSetAuthentication(RASCNTL_SERVERLINE *pLine, unsigned int uiRasAuth) {
  371. RASCNTL_SERVERLINE *pLineSettings;
  372. DWORD  cbLineSettings;
  373. DWORD  dwResult;
  374. dwResult = LineGetParameters(pLine, &pLineSettings, &cbLineSettings);
  375. if (dwResult == NO_ERROR)
  376. {
  377. if (uiRasAuth == 0)
  378. pLineSettings->bmFlags |= PPPSRV_FLAG_ALLOW_UNAUTHENTICATED_ACCESS;
  379. else
  380. pLineSettings->bmFlags &= ~PPPSRV_FLAG_ALLOW_UNAUTHENTICATED_ACCESS;
  381. dwResult = RasIOControl(0, RASCNTL_SERVER_LINE_SET_PARAMETERS, (PUCHAR)pLineSettings, cbLineSettings, NULL, 0, NULL);
  382. LocalFree(pLineSettings);
  383. }
  384. return dwResult;
  385. }
  386. static DWORD ServerSetAuthentication (unsigned int uiRasAuth) {
  387. if (! uiRasAuth)
  388. return ERROR_SUCCESS;
  389. DWORD cbStatus = 0;
  390. // Retrieve RAS setting
  391. DWORD dwResult = RasIOControl(0, RASCNTL_SERVER_GET_PARAMETERS, 0, 0, NULL, 0, &cbStatus);
  392. if (dwResult && (cbStatus  == 0)) {
  393. RETAILMSG (1, (L"BLUETOOTH GATEWAY:: Failed to get server parameters. Error code %d" CRLF, dwResult));
  394. return dwResult;
  395. }
  396. RASCNTL_SERVERSTATUS *pStatus = (RASCNTL_SERVERSTATUS *) malloc ( cbStatus );
  397. if (pStatus == NULL) {
  398. RETAILMSG (1, (L"BLUETOOTH GATEWAY:: Failed to get server parameters. Error code %d" CRLF, ERROR_OUTOFMEMORY));
  399. return ERROR_OUTOFMEMORY;
  400. }
  401. dwResult = RasIOControl(0, RASCNTL_SERVER_GET_PARAMETERS, 0, 0, (PUCHAR)pStatus, cbStatus, &cbStatus);
  402. if (dwResult) {
  403. free (pStatus);
  404. RETAILMSG (1, (L"BLUETOOTH GATEWAY:: Failed to get server parameters. Error code %d" CRLF, dwResult));
  405. return dwResult;
  406. }
  407. pStatus->bmAuthenticationMethods &= ~bmProhibitAll;
  408. pStatus->bmAuthenticationMethods |= uiRasAuth;
  409. dwResult = RasIOControl(0, RASCNTL_SERVER_SET_PARAMETERS, (PUCHAR)pStatus, cbStatus, 0, 0, &cbStatus);
  410. free (pStatus);
  411. if (dwResult) {
  412. RETAILMSG (1, (L"BLUETOOTH GATEWAY:: Failed to set server parameters. Error code %d" CRLF, dwResult));
  413. return dwResult;
  414. }
  415. RETAILMSG (1, (L"BLUETOOTH GATEWAY:: Successfully set server authentication." CRLF));
  416. return ERROR_SUCCESS;
  417. }
  418. static int AddAndEnable (WCHAR *szFriendlyName, unsigned int uiRasAuth) {
  419. RASCNTL_SERVERLINE Line;
  420. DWORD dwResult = GetDeviceInfo (szFriendlyName, &Line.rasDevInfo);
  421. if (dwResult == ERROR_SUCCESS) {
  422. if (ERROR_SUCCESS == (dwResult = RasIOControl(0, RASCNTL_SERVER_LINE_ADD, (PUCHAR)&Line, sizeof(Line), NULL, 0, NULL))) {
  423. if (ERROR_SUCCESS == (dwResult = LineSetAuthentication(&Line, uiRasAuth))) {
  424. if (ERROR_SUCCESS == (dwResult = RasIOControl(0, RASCNTL_SERVER_LINE_ENABLE, (PUCHAR)&Line, sizeof(Line), NULL, 0, NULL)))
  425. RETAILMSG (1, (L"BLUETOOTH GATEWAY:: Successfully enabled device %s. Ready to receive calls." CRLF, szFriendlyName));
  426. else
  427. RETAILMSG (1, (L"BLUETOOTH GATEWAY:: Failed to enable device %s. Error code %d" CRLF, szFriendlyName, dwResult));
  428. } else
  429. RETAILMSG (1, (L"BLUETOOTH GATEWAY:: Failed to disable authentication for device %s. Error code %d" CRLF, szFriendlyName, dwResult));
  430. } else
  431. RETAILMSG (1, (L"BLUETOOTH GATEWAY:: Failed to add device %s. Error code %d" CRLF, szFriendlyName, dwResult));
  432. } else
  433. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Device %s is not recognized, code %d" CRLF, szFriendlyName, dwResult));
  434. return dwResult;
  435. }
  436. static int DisableAndRemove (WCHAR *szFriendlyName) {
  437. RASCNTL_SERVERLINE Line;
  438. DWORD dwResult = GetDeviceInfo (szFriendlyName, &Line.rasDevInfo);
  439. if (dwResult == ERROR_SUCCESS) {
  440. RasIOControl(0, RASCNTL_SERVER_LINE_DISABLE, (PUCHAR)&Line, sizeof(Line), NULL, 0, NULL);
  441. RasIOControl(0, RASCNTL_SERVER_LINE_REMOVE, (PUCHAR)&Line, sizeof(Line), NULL, 0, NULL);
  442. } else
  443. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Device %s is not recognized, code %d" CRLF, szFriendlyName, dwResult));
  444. return dwResult;
  445. }
  446. //
  447. // Port management
  448. //
  449. static ULONG RegisterSDP (HANDLE hFile, int fLan) {
  450. ULONG recordHandle = 0;
  451. DWORD port = 0;
  452. DWORD dwSizeOut = 0;
  453. if (! DeviceIoControl (hFile, IOCTL_BLUETOOTH_GET_RFCOMM_CHANNEL, NULL, 0, &port, sizeof(port), &dwSizeOut, NULL)) {
  454. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Failed to retrieve port server channel, error = %d" CRLF, GetLastError ()));
  455. return 0;
  456. }
  457. struct {
  458. BTHNS_SETBLOB b;
  459. unsigned char   uca[SDP_RECORD_SIZE];
  460. } bigBlob;
  461. ULONG ulSdpVersion = BTH_SDP_VERSION;
  462. bigBlob.b.pRecordHandle   = &recordHandle;
  463.     bigBlob.b.pSdpVersion     = &ulSdpVersion;
  464. bigBlob.b.fSecurity       = 0;
  465. bigBlob.b.fOptions        = 0;
  466. bigBlob.b.ulRecordLength  = SDP_RECORD_SIZE;
  467. memcpy (bigBlob.b.pRecord, fLan ? rgbSdpRecordLAN : rgbSdpRecordDUN, SDP_RECORD_SIZE);
  468. bigBlob.b.pRecord[SDP_CHANNEL_OFFSET] = (unsigned char)port;
  469. BLOB blob;
  470. blob.cbSize    = sizeof(BTHNS_SETBLOB) + SDP_RECORD_SIZE - 1;
  471. blob.pBlobData = (PBYTE) &bigBlob;
  472. WSAQUERYSET Service;
  473. memset (&Service, 0, sizeof(Service));
  474. Service.dwSize = sizeof(Service);
  475. Service.lpBlob = &blob;
  476. Service.dwNameSpace = NS_BTH;
  477. int iRet = BthNsSetService (&Service, RNRSERVICE_REGISTER,0);
  478. if (iRet != ERROR_SUCCESS) {
  479. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: BthNsSetService fails with status %d" CRLF, iRet));
  480. return 0;
  481. }
  482. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Created SDP record 0x%08x, channel %d" CRLF, recordHandle, port));
  483. return recordHandle;
  484. }
  485. static void DeRegisterSDP (ULONG recordHandle) {
  486. ULONG ulSdpVersion = BTH_SDP_VERSION;
  487. BTHNS_SETBLOB delBlob;
  488. memset (&delBlob, 0, sizeof(delBlob));
  489. delBlob.pRecordHandle = &recordHandle;
  490.     delBlob.pSdpVersion = &ulSdpVersion;
  491. BLOB blob;
  492. blob.cbSize    = sizeof(BTHNS_SETBLOB);
  493. blob.pBlobData = (PBYTE) &delBlob;
  494. WSAQUERYSET Service;
  495. memset (&Service, 0, sizeof(Service));
  496. Service.dwSize = sizeof(Service);
  497. Service.lpBlob = &blob;
  498. Service.dwNameSpace = NS_BTH;
  499. int iErr = BthNsSetService (&Service, RNRSERVICE_DELETE, 0);
  500. RETAILMSG (1, (L"BLUETOOTH GATEWAY: removed SDP record 0x%08x (%d)" CRLF, recordHandle, iErr));
  501. }
  502. static DWORD WINAPI PortThread (LPVOID lparg) {
  503. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Entered port monitor thread" CRLF));
  504. HANDLE hFile = ((PortThreadArgs *)lparg)->hFile;
  505. int fLan = ((PortThreadArgs *)lparg)->fLan;
  506. LocalFree (lparg);
  507. ULONG recordHandle = 0;
  508. // Register SDP handle, etc.
  509.     SetCommMask(hFile, EV_RLSD);
  510. for ( ; ; ) {
  511.     DWORD Mask;
  512. DWORD ModemStatus;
  513. if (! GetCommModemStatus (hFile, &ModemStatus)) {
  514. break;
  515. }
  516. if (ModemStatus & MS_RLSD_ON) {
  517. BT_ADDR bt;
  518. DWORD dwSizeOut = 0;
  519. if (! DeviceIoControl (hFile, IOCTL_BLUETOOTH_GET_PEER_DEVICE, NULL, 0, &bt, sizeof(bt), &dwSizeOut, NULL))
  520. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Failed to retrieve peer device name, error = %d" CRLF, GetLastError ()));
  521. else
  522. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Connection detected from %04x%08x" CRLF, GET_NAP(bt), GET_SAP(bt)));
  523. if (recordHandle)
  524. DeRegisterSDP (recordHandle);
  525. recordHandle = 0;
  526. } else {
  527. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: No connection detected" CRLF));
  528. if (! recordHandle)
  529. recordHandle = RegisterSDP (hFile, fLan);
  530. }
  531. if (! WaitCommEvent(hFile, &Mask, NULL )) {
  532. break;
  533. }
  534. }
  535. if (recordHandle)
  536. DeRegisterSDP (recordHandle);
  537. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Exiting port monitor thread" CRLF));
  538. return 0;
  539. }
  540. static void ClosePort (Port *pPort) {
  541. if (pPort->hFile != INVALID_HANDLE_VALUE)
  542. CloseHandle (pPort->hFile);
  543. pPort->hFile = INVALID_HANDLE_VALUE;
  544. if (pPort->hThread) {
  545. WaitForSingleObject (pPort->hThread, INFINITE);
  546. CloseHandle (pPort->hThread);
  547. }
  548. pPort->hThread = NULL;
  549. WCHAR szKeyName[_MAX_PATH];
  550. wsprintf (szKeyName, L"software\microsoft\bluetoothgateway\com%d\unimodem", pPort->index);
  551. RegDeleteKey (HKEY_LOCAL_MACHINE, szKeyName);
  552. wsprintf (szKeyName, L"software\microsoft\bluetoothgateway\com%d", pPort->fModem ? pPort->index2 : pPort->index);
  553. RegDeleteKey (HKEY_LOCAL_MACHINE, szKeyName);
  554. if (pPort->fModem) {
  555. wsprintf (szKeyName, L"software\microsoft\bluetoothgateway\com%d", pPort->index2);
  556. RegDeleteKey (HKEY_LOCAL_MACHINE, szKeyName);
  557. }
  558. DisableAndRemove (pPort->szDevName);
  559. if (pPort->hDevice)
  560. DeactivateDevice (pPort->hDevice);
  561. if (pPort->hDevice2)
  562. DeactivateDevice (pPort->hDevice2);
  563. pPort->hDevice = NULL;
  564. pPort->hDevice2 = NULL;
  565. }
  566. static void OpenPort (Port *pPort, int fa, int fe, unsigned int uiRasAuth) {
  567. ASSERT (pPort->hDevice == NULL);
  568. ASSERT (pPort->hDevice2 == NULL);
  569. PORTEMUPortParams pp;
  570. memset (&pp, 0, sizeof(pp));
  571. pp.flocal = TRUE;
  572. pp.channel = pPort->channel;
  573. if (! pp.channel)
  574. pp.channel = 0xfe;
  575. if (fa)
  576. pp.uiportflags |= RFCOMM_PORT_FLAGS_AUTHENTICATE;
  577. if (fe)
  578. pp.uiportflags |= RFCOMM_PORT_FLAGS_ENCRYPT;
  579. WCHAR szKeyName[_MAX_PATH];
  580. wsprintf (szKeyName, L"software\microsoft\bluetoothgateway\com%d", pPort->index);
  581. HKEY hk;
  582. DWORD dwDisp = 0;
  583. if (ERROR_SUCCESS != RegCreateKeyEx (HKEY_LOCAL_MACHINE, szKeyName, 0, NULL, 0, KEY_WRITE, NULL, &hk, &dwDisp)) {
  584. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Failed to create registry key %s, error = %d" CRLF, szKeyName, GetLastError ()));
  585. return;
  586. }
  587. RegSetValueEx (hk, L"dll", 0, REG_SZ, (BYTE *)L"btd.dll", sizeof(L"btd.dll"));
  588. RegSetValueEx (hk, L"prefix", 0, REG_SZ, (BYTE *)L"COM", sizeof(L"COM"));
  589. DWORD dw = pPort->index;
  590. RegSetValueEx (hk, L"index", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw));
  591. dw = (DWORD) &pp;
  592. RegSetValueEx (hk, L"context", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw));
  593. if (! pPort->fModem) {
  594. HKEY hk2;
  595. if (ERROR_SUCCESS != RegCreateKeyEx (hk, L"unimodem", 0, NULL, 0, KEY_WRITE, NULL, &hk2, &dwDisp)) {
  596. RegCloseKey (hk);
  597. RegDeleteKey (HKEY_LOCAL_MACHINE, szKeyName);
  598. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Failed to create unimodem subkey of %s, error = %d" CRLF, szKeyName, GetLastError ()));
  599. return;
  600. }
  601. RegSetValueEx (hk2, L"friendlyname", 0, REG_SZ, (BYTE *)pPort->szDevName, (wcslen (pPort->szDevName) + 1) * sizeof(WCHAR));
  602. RegSetValueEx (hk2, L"tsp", 0, REG_SZ, (BYTE *)L"unimodem.dll", sizeof(L"unimodem.dll"));
  603. dw = 0;
  604. RegSetValueEx (hk2, L"devicetype", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw));
  605. RegCloseKey (hk2);
  606. }
  607. RegCloseKey (hk);
  608. pPort->hDevice = ActivateDevice (szKeyName, 0);
  609. if (! pPort->hDevice) {
  610. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Failed to register port %d, error = %d" CRLF, pPort->index, GetLastError ()));
  611. RegDeleteKey (HKEY_LOCAL_MACHINE, szKeyName);
  612. return;
  613. }
  614. if (pPort->fModem) {
  615. wsprintf (szKeyName, L"software\microsoft\bluetoothgateway\com%d", pPort->index2);
  616. if (ERROR_SUCCESS != RegCreateKeyEx (HKEY_LOCAL_MACHINE, szKeyName, 0, NULL, 0, KEY_WRITE, NULL, &hk, &dwDisp)) {
  617. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Failed to create registry key %s, error = %d" CRLF, szKeyName, GetLastError ()));
  618. ClosePort (pPort);
  619. return;
  620. }
  621. RegSetValueEx (hk, L"dll", 0, REG_SZ, (BYTE *)L"btdun.dll", sizeof(L"btdun.dll"));
  622. RegSetValueEx (hk, L"prefix", 0, REG_SZ, (BYTE *)L"COM", sizeof(L"COM"));
  623. DWORD dw = pPort->index2;
  624. RegSetValueEx (hk, L"index", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw));
  625. dw = (DWORD) pPort->index;
  626. RegSetValueEx (hk, L"context", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw));
  627. HKEY hk2;
  628. if (ERROR_SUCCESS != RegCreateKeyEx (hk, L"unimodem", 0, NULL, 0, KEY_WRITE, NULL, &hk2, &dwDisp)) {
  629. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Failed to create unimodem subkey of %s, error = %d" CRLF, szKeyName, GetLastError ()));
  630. ClosePort (pPort);
  631. return;
  632. }
  633. RegSetValueEx (hk2, L"friendlyname", 0, REG_SZ, (BYTE *)pPort->szDevName, (wcslen (pPort->szDevName) + 1) * sizeof(WCHAR));
  634. RegSetValueEx (hk2, L"tsp", 0, REG_SZ, (BYTE *)L"unimodem.dll", sizeof(L"unimodem.dll"));
  635. dw = 0;
  636. RegSetValueEx (hk2, L"devicetype", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw));
  637. RegCloseKey (hk2);
  638. RegCloseKey (hk);
  639. pPort->hDevice2 = ActivateDevice (szKeyName, 0);
  640. if (! pPort->hDevice) {
  641. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Failed to register port %d, error = %d" CRLF, pPort->index2, GetLastError ()));
  642. ClosePort (pPort);
  643. return;
  644. }
  645. }
  646. Sleep (3000); // Tapi need to process device insertion
  647. if (ERROR_SUCCESS != AddAndEnable (pPort->szDevName, uiRasAuth)) {
  648. ClosePort (pPort);
  649. return;
  650. }
  651. WCHAR szFile[40];
  652. wsprintf (szFile, L"COM%d:", pPort->index);
  653. pPort->hFile = CreateFile (szFile, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
  654. if (pPort->hFile == INVALID_HANDLE_VALUE) {
  655. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Failed to open port %d, error = %d" CRLF, pPort->index, GetLastError ()));
  656. ClosePort (pPort);
  657. return;
  658. }
  659. PortThreadArgs *pArgs = (PortThreadArgs *)LocalAlloc (LMEM_FIXED, sizeof(PortThreadArgs));
  660. if (pArgs) {
  661. pArgs->fLan = ! pPort->fModem;
  662. pArgs->hFile = pPort->hFile;
  663. pPort->hThread = CreateThread (NULL, 0, PortThread, (LPVOID)pArgs, 0, NULL);
  664. }
  665. if (! pPort->hThread) {
  666. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Failed attach thread to port %d, error = %d" CRLF, pPort->index, GetLastError ()));
  667. ClosePort (pPort);
  668. }
  669. }
  670. //
  671. // Configuration management and parsing
  672. //
  673. //
  674. #define DEFAULT_CONFIG_FILE L"AUTH=OFFnENCRYPT=OFFnPORT=btline0,7nPORT=btline1,8,9n"
  675. static void PrintDefaultHeader (FILE *fp, WCHAR *sz) {
  676. fwprintf (fp, L";n; This is Bluetooth Gateway configuration file %s.n;n", sz);
  677. fwprintf (fp, L"; It is automatically regenerated on every update,n");
  678. fwprintf (fp, L"; do not store any information (including comments)n");
  679. fwprintf (fp, L"; aside of information inside defined keywords.n;n");
  680. fwprintf (fp, L"; The keywords legal in this file are:n");
  681. fwprintf (fp, L";   AUTH={ON|OFF} require authentication on connectionn");
  682. fwprintf (fp, L";   ENCRYPT={ON|OFF} require encryption to be on on connectionn");
  683.     fwprintf (fp, L";   RASAUTH={NONE|PAP CHAP MSCHAP MSCHAPv2}n");
  684. fwprintf (fp, L";   PORT=name,number[:channel][,number] use COMx: port, use pre-defined channeln");
  685. fwprintf (fp, L";              if given, otherwise auto-allocaten");
  686. fwprintf (fp, L";              if second index is specified, use modem emulator on itn");
  687. fwprintf (fp, L";   PINaddress=sequence of 1 to 16 double hex charactersn");
  688. fwprintf (fp, L";       e. g. PIN000101020304=30 31 32 32 34n");
  689. fwprintf (fp, L";   KEYaddress=sequence of 16 double hex characters - same as PINn;n");
  690. }
  691. static void MakeDefaultConfig (WCHAR *szName) {
  692. HKEY hk;
  693. int fReg = FALSE;
  694. WCHAR buffer[512];
  695. if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"software\microsoft\bluetooth\gateway", 0, KEY_READ, &hk)) {
  696. DWORD dwType = 0;
  697. DWORD dwSize = sizeof(buffer);
  698. if (ERROR_SUCCESS == RegQueryValueEx (hk, L"config", NULL, &dwType, (BYTE *)buffer, &dwSize)) {
  699. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Found registry definition for default gateway config in %s" CRLF, szName));
  700. fReg = TRUE;
  701. }
  702. RegCloseKey (hk);
  703. }
  704. if (! fReg) {
  705. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Making default gateway config in %s" CRLF, szName));
  706. wcscpy (buffer, DEFAULT_CONFIG_FILE);
  707. }
  708. FILE *fp = _wfopen (szName, L"w");
  709. if (! fp) {
  710. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Could not create configuration: failed to open %s! Error = %d" CRLF, szName, GetLastError ()));
  711. return;
  712. }
  713. PrintDefaultHeader (fp, L"(default configuration)");
  714. fwprintf (fp, L"%s", buffer);
  715. fclose (fp);
  716. }
  717. static void GetPersistentName (WCHAR *szName, int ccName) {
  718. ASSERT (ccName > (CONFIG_NAME_SZ + 2));
  719. WIN32_FIND_DATA wfd;
  720. for (int i = 0 ; i < 2 ; ++i) {
  721. HANDLE hSearch = FindFirstFile (L"\*.*", &wfd);
  722. if (hSearch != INVALID_HANDLE_VALUE) {
  723. do {
  724. if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  725. (wfd.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY)) {
  726. int cSize = wcslen (wfd.cFileName) + 3 + CONFIG_NAME_SZ;
  727. if (cSize <= ccName) {
  728. szName[0] = L'\';
  729. wcscpy (szName + 1, wfd.cFileName);
  730. wcscat (szName, L"\" CONFIG_NAME);
  731. DWORD dwRes = GetFileAttributes (szName);
  732. if (((dwRes != 0xffffffff) && ((dwRes & FILE_ATTRIBUTE_DIRECTORY) == 0)) || // Found!
  733.  ((i == 1) && (dwRes == 0xffffffff))) { // Found place for it!
  734. FindClose (hSearch);
  735. if ((i == 1) && (dwRes == 0xffffffff))
  736. MakeDefaultConfig (szName);
  737. return;
  738. }
  739. }
  740. }
  741. } while (FindNextFile (hSearch, &wfd));
  742. FindClose (hSearch);
  743. }
  744. }
  745. wcscpy (szName, L"\" CONFIG_NAME);
  746. if (GetFileAttributes (szName) == 0xffffffff)
  747. MakeDefaultConfig (szName);
  748. return;
  749. }
  750. static Security *Get (Security *pList, BT_ADDR bt) {
  751. while (pList) {
  752. if (pList->bt == bt)
  753. return pList;
  754. pList = pList->pNext;
  755. }
  756. return NULL;
  757. }
  758. static Port *Get (Port *pList, int index) {
  759. while (pList) {
  760. if (pList->index == index)
  761. return pList;
  762. pList = pList->pNext;
  763. }
  764. return NULL;
  765. }
  766. static void Free (Security *pList) {
  767. while (pList) {
  768. Security *pNext = pList->pNext;
  769. delete pList;
  770. pList = pNext;
  771. }
  772. }
  773. static void Free (Port *pList) {
  774. while (pList) {
  775. Port *pNext = pList->pNext;
  776. delete pList;
  777. pList = pNext;
  778. }
  779. }
  780. static Security *GetRegistrySecurity (void) {
  781. HKEY hKey;
  782. Security *pResult = NULL;
  783. if (ERROR_SUCCESS != RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"software\microsoft\bluetooth\security", 0, KEY_READ, &hKey))
  784. return NULL;
  785. for (DWORD dwIndex = 0 ; ; ++dwIndex) {
  786. unsigned char link_key[16];
  787. DWORD clink_key = sizeof(link_key);
  788. WCHAR szName[32];
  789. DWORD cName = 32;
  790. DWORD dwType = 0;
  791. WCHAR *p = szName + 3;
  792. LONG res = RegEnumValue (hKey, dwIndex, szName, &cName, NULL, &dwType, link_key, &clink_key);
  793. if (res == ERROR_NO_MORE_ITEMS)
  794. break;
  795. BT_ADDR bt;
  796. if ((res == ERROR_SUCCESS) && (dwType == REG_BINARY) && (clink_key > 0) &&
  797. (clink_key < 17) && (cName == 13) &&
  798. (((wcsnicmp (szName, L"KEY", 3) == 0) && (clink_key == 16)) ||
  799. (wcsnicmp (szName, L"PIN", 3) == 0)) && GetBA(&p, &bt)) {
  800. Security *pNew = Get (pResult, bt);
  801. if (! pNew) {
  802. pNew = new Security;
  803. if (! pNew) {
  804. RETAILMSG (1, (L"BLUETOOTH GATEWAY:: OUT OF MEMORY! Data may be lost!n"));
  805. break;
  806. }
  807. pNew->bt = bt;
  808. pNew->pNext = pResult;
  809. pResult = pNew;
  810. }
  811. if ((clink_key == 16) && (wcsnicmp (szName, L"KEY", 3) == 0)) {
  812. pNew->cKey = 16;
  813. memcpy (pNew->acKey, link_key, 16);
  814. RETAILMSG (1, (L"BLUETOOTH GATEWAY:: Found link key for %04x%08xn", GET_NAP(bt), GET_SAP(bt)));
  815. } else {
  816. // Registry is ONLY harvested for LINK keys.
  817. // PINs are exclusively managed by the file.
  818. // pNew->cPin = clink_key;
  819. // memcpy (pNew->acPin, link_key, clink_key);
  820.    RETAILMSG (1, (L"BLUETOOTH GATEWAY:: Found and ignored PIN code for %04x%08x in registryn", GET_NAP(bt), GET_SAP(bt)));
  821. }
  822. }
  823. }
  824. RegCloseKey (hKey);
  825. return pResult;
  826. }
  827. //
  828. // Config file structure
  829. //
  830. // PORT=name,index[:channel][,modem port index]
  831. // PIN<address>=sequence1..16
  832. //  KEY<address>=sequence16
  833. //  ENCRYPT={ON|OFF}
  834. //  AUTHN={ON|OFF}
  835. //  RASAUTH={NONE|PAP CHAP MSCHAP MSCHAPv2}
  836. // sequence={0xXX}+
  837. //
  838. static int Parse (WCHAR *szFileName, Config *pConfig) {
  839. Security *pRegistry = GetRegistrySecurity ();
  840. Security *pFileS = NULL;
  841. Port *pFileP = NULL;
  842. int fSyntaxError = FALSE;
  843. int fa_old = pConfig->fa;
  844. int fe_old = pConfig->fe;
  845. unsigned int rasauth_old = pConfig->uiRasAuth;
  846. pConfig->uiRasAuth = 0;
  847. FILE *fp = _wfopen (szFileName, L"r");
  848. if (fp) {
  849. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Using config file %s" CRLF, szFileName));
  850. WCHAR szBuffer[256];
  851. int line = 0;
  852. while (! feof (fp)) {
  853. ++line;
  854. if (! fgetws (szBuffer, sizeof(szBuffer)/sizeof(szBuffer[0]), fp))
  855. break;
  856. WCHAR *p = szBuffer;
  857. while (iswspace(*p))
  858. ++p;
  859. if ((*p == '') || (*p == ';'))
  860. continue;
  861. WCHAR *pKey=p;
  862. while ((*p != '') && (*p != '=') && (! iswspace(*p)))
  863. ++p;
  864. WCHAR *pKeyEnd = p;
  865. while (iswspace(*p))
  866. ++p;
  867. if (*p != '=') {
  868. fSyntaxError = TRUE;
  869. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, expected '='" CRLF, line));
  870. break;
  871. }
  872. ++p;
  873. while (iswspace(*p))
  874. ++p;
  875. WCHAR *pVal = p;
  876. *pKeyEnd = L'';
  877. if (wcsicmp (pKey, L"PORT") == 0) {
  878. WCHAR *pName=pVal;
  879. while (*pVal && (! iswspace(*pVal)) && (*pVal != ','))
  880. ++pVal;
  881. while (iswspace(*pVal)) {
  882. *pVal = '';
  883. ++pVal;
  884. }
  885. if (*pVal != ',') {
  886. fSyntaxError = TRUE;
  887. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, expected PORT=name,0..9[:1-31][,0..9]" CRLF, line));
  888. break;
  889. }
  890. *pVal = '';
  891. if (wcslen (pName) >= _MAX_PATH) {
  892. fSyntaxError = TRUE;
  893. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, expected PORT=name,0..9[:1-31][,0..9]" CRLF, line));
  894. break;
  895. }
  896. ++pVal;
  897. while (iswspace(*pVal))
  898. ++pVal;
  899. unsigned int index = 0;
  900. unsigned int channel = 0;
  901. if ((! GetDI (&pVal, &index)) || (index > 9)) {
  902. fSyntaxError = TRUE;
  903. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, expected PORT=name,0..9[:1-31][,0..9]" CRLF, line));
  904. break;
  905. }
  906. while (iswspace (*pVal))
  907. ++pVal;
  908. if (*pVal == ':') {
  909. ++pVal;
  910. while (iswspace (*pVal))
  911. ++pVal;
  912. if ((! GetDI (&pVal, &channel)) || (channel == 0) || (channel > 31)) {
  913. fSyntaxError = TRUE;
  914. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, expected PORT=name,0..9[:1-31][,0..9]" CRLF, line));
  915. break;
  916. }
  917. }
  918. while (iswspace (*pVal))
  919. ++pVal;
  920. unsigned int index2 = 0;
  921. int fHaveIndex2 = FALSE;
  922. if (*pVal == ',') { // Emulator port
  923. ++pVal;
  924. while (iswspace (*pVal))
  925. ++pVal;
  926. if ((! GetDI (&pVal, &index2)) || (index2 > 9)) {
  927. fSyntaxError = TRUE;
  928. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, expected PORT=name,0..9[:1-31][,0..9]" CRLF, line));
  929. break;
  930. }
  931. fHaveIndex2 = TRUE;
  932. }
  933. while (iswspace (*pVal))
  934. ++pVal;
  935. if ((*pVal != '') && (*pVal != ';')) {
  936. fSyntaxError = TRUE;
  937. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, expected PORT=name,0..9[:1-31][,0..9]" CRLF, line));
  938. break;
  939. }
  940. Port *pNewPort = new Port;
  941. pNewPort->pNext = pFileP;
  942. pFileP = pNewPort;
  943. pNewPort->index = index;
  944. pNewPort->channel = channel;
  945. wcscpy (pNewPort->szDevName, pName);
  946. if (fHaveIndex2) {
  947. pNewPort->fModem = TRUE;
  948. pNewPort->index2 = index2;
  949. }
  950. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: <%s> Port %d channel %d" CRLF, szFileName, pNewPort->index, pNewPort->channel));
  951. if (pNewPort->fModem)
  952.     RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Modem emulation port %d" CRLF, pNewPort->index2));
  953. } else if ((wcsnicmp (pKey, L"PIN", 3) == 0) || (wcsnicmp (pKey, L"KEY", 3) == 0)) {
  954. BT_ADDR bt;
  955. p = pKey + 3;
  956. if (! GetBA(&p, &bt)) {
  957. fSyntaxError = TRUE;
  958. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, expected PIN/KEY<bt_addr>=xx xx xx..." CRLF, line));
  959. break;
  960. }
  961. unsigned char value[16];
  962. for (int i = 0 ; i < 16 ; ++i) {
  963. if (! GetUx (&pVal, value+i, 2, FALSE))
  964. break;
  965. }
  966. if (((*pVal != L'') && (*pVal != L';')) || (((pKey[0] == 'K') || (pKey[0] == 'k')) && (i != 16))) {
  967. fSyntaxError = TRUE;
  968. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, expected sequence of hex digits" CRLF, line));
  969. break;
  970. }
  971. Security *pNewS = Get (pFileS, bt);
  972. if (! pNewS) {
  973. pNewS = new Security;
  974. pNewS->pNext = pFileS;
  975. pFileS = pNewS;
  976. pNewS->bt = bt;
  977. }
  978. if (pKey[0] == L'K') {
  979. pNewS->cKey = 16;
  980. memcpy (pNewS->acKey, value, 16);
  981. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: <%s> KEY %04x%08x" CRLF, szFileName, GET_NAP(pFileS->bt), GET_SAP(pFileS->bt)));
  982. } else {
  983. pNewS->cPin = i;
  984. memcpy (pNewS->acPin, value, i);
  985. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: <%s> PIN %04x%08x" CRLF, szFileName, GET_NAP(pFileS->bt), GET_SAP(pFileS->bt)));
  986. }
  987. } else if (wcsicmp (pKey, L"AUTH") == 0) {
  988. if (wcsnicmp (pVal, L"ON", 2) == 0) {
  989. pConfig->fa = TRUE;
  990. pVal += 2;
  991. } else if (wcsnicmp (pVal, L"OFF", 3) == 0) {
  992. pConfig->fa = FALSE;
  993. pVal += 3;
  994. } else {
  995. fSyntaxError = TRUE;
  996. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, expected AUTH={ON|OFF}" CRLF, line));
  997. break;
  998. }
  999. while (iswspace (*pVal))
  1000. ++pVal;
  1001. if ((*pVal != '') && (*pVal != ';')) {
  1002. fSyntaxError = TRUE;
  1003. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, expected AUTH={ON|OFF}" CRLF, line));
  1004. break;
  1005. }
  1006. } else if (wcsicmp (pKey, L"RASAUTH") == 0) {
  1007. if (wcsnicmp (pVal, L"NONE", 4) == 0) {
  1008. pConfig->uiRasAuth = 0;
  1009. pVal += 4;
  1010. } else {
  1011.   pConfig->uiRasAuth = bmProhibitAll;
  1012. for ( ; ; ) {
  1013. if (wcsnicmp (pVal, L"MSCHAPv2", 8) == 0) {
  1014. pConfig->uiRasAuth &= ~RASEO_ProhibitMsCHAP2;
  1015. pVal += 8;
  1016. } else if (wcsnicmp (pVal, L"MSCHAP", 6) == 0) {
  1017. pConfig->uiRasAuth &= ~RASEO_ProhibitMsCHAP;
  1018. pVal += 6;
  1019. } else if (wcsnicmp (pVal, L"CHAP", 4) == 0) {
  1020. pConfig->uiRasAuth &= ~RASEO_ProhibitCHAP;
  1021. pVal += 4;
  1022. } else if (wcsnicmp (pVal, L"PAP", 3) == 0) {
  1023. pConfig->uiRasAuth &= ~RASEO_ProhibitPAP;
  1024. pVal += 3;
  1025. } else {
  1026. fSyntaxError = TRUE;
  1027. DEBUGMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, unknown RAS auth type" CRLF, line));
  1028. break;
  1029. }
  1030. while (iswspace (*pVal))
  1031. ++pVal;
  1032. if ((*pVal == '') || (*pVal == ';'))
  1033. break;
  1034. }
  1035. if ((pConfig->uiRasAuth == bmProhibitAll) && (! fSyntaxError)) {
  1036. fSyntaxError = TRUE;
  1037. DEBUGMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, expected RAS auth type" CRLF, line));
  1038. break;
  1039. }
  1040. if (fSyntaxError)
  1041. break;
  1042. }
  1043. while (iswspace (*pVal))
  1044. ++pVal;
  1045. if ((*pVal != '') && (*pVal != ';')) {
  1046. fSyntaxError = TRUE;
  1047. DEBUGMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, expected RASAUTH={NONE|PAP CHAP MSCHAP MSCHAPv2}" CRLF, line));
  1048. break;
  1049. }
  1050. } else if (wcsicmp (pKey, L"ENCRYPT") == 0) {
  1051. if (wcsnicmp (pVal, L"ON", 2) == 0) {
  1052. pConfig->fe = TRUE;
  1053. pVal += 2;
  1054. } else if (wcsnicmp (pVal, L"OFF", 3) == 0) {
  1055. pConfig->fe = FALSE;
  1056. pVal += 3;
  1057. } else {
  1058. fSyntaxError = TRUE;
  1059. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, expected ENCRYPT={ON|OFF}" CRLF, line));
  1060. break;
  1061. }
  1062. while (iswspace (*pVal))
  1063. ++pVal;
  1064. if ((*pVal != '') && (*pVal != ';')) {
  1065. fSyntaxError = TRUE;
  1066. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, expected ENCRYPT={ON|OFF}" CRLF, line));
  1067. break;
  1068. }
  1069. } else {
  1070. fSyntaxError = TRUE;
  1071. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Syntax error near line %d, unrecognized token %s" CRLF, line, pKey));
  1072. break;
  1073. }
  1074. }
  1075. fclose (fp);
  1076. } else
  1077. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: config file %s not found" CRLF, szFileName));
  1078. if (fSyntaxError) {
  1079. Free (pFileS);
  1080. Free (pFileP);
  1081. Free (pRegistry);
  1082. return FALSE;
  1083. }
  1084. ServerSetAuthentication (pConfig->uiRasAuth);
  1085. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Merging configuration : ports" CRLF));
  1086. Port *pP = pConfig->pPortList;
  1087. while (pP) {
  1088. pP->fOld = TRUE;
  1089. pP = pP->pNext;
  1090. }
  1091. while (pFileP) {
  1092. Port *pNext = pFileP->pNext;
  1093. Port *pExist = Get (pConfig->pPortList, pFileP->index);
  1094. if (pExist && (fa_old == pConfig->fa) && (fe_old == pConfig->fe) && (rasauth_old == pConfig->uiRasAuth) &&
  1095. ((pExist->channel == pFileP->channel) || (pFileP->channel == 0))) {
  1096. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Port %d on channel %d already exists" CRLF, pFileP->index, pFileP->channel));
  1097. pExist->fOld = FALSE;
  1098. delete pFileP;
  1099. pFileP = pNext;
  1100. continue;
  1101. }
  1102. if (pExist) {
  1103. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Port %d on channel %d => channel %d %s %s" CRLF, pFileP->index, pExist->channel, pFileP->channel, pConfig->fa ? L"AUTH" : L"", pConfig->fe ? L"ENCRYPT" : L""));
  1104. ClosePort (pExist);
  1105. pExist->channel = pFileP->channel;
  1106. pExist->fOld = FALSE;
  1107. delete pFileP;
  1108. pFileP = pNext;
  1109. OpenPort (pExist, pConfig->fa, pConfig->fe, pConfig->uiRasAuth);
  1110. continue;
  1111. }
  1112. pFileP->pNext = pConfig->pPortList;
  1113. pConfig->pPortList = pFileP;
  1114. OpenPort (pFileP, pConfig->fa, pConfig->fe, pConfig->uiRasAuth);
  1115. pFileP = pNext;
  1116. }
  1117. Port *pParentP = NULL;
  1118. pP = pConfig->pPortList;
  1119. while (pP) {
  1120. if (pP->fOld) {
  1121. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Port %d on channel %d is closed" CRLF, pP->index, pP->channel));
  1122. if (! pParentP)
  1123. pConfig->pPortList = pP->pNext;
  1124. else
  1125. pParentP->pNext = pP->pNext;
  1126. ClosePort (pP);
  1127. delete pP;
  1128. pP = pParentP ? pParentP->pNext : pConfig->pPortList;
  1129. continue;
  1130. }
  1131. pParentP = pP;
  1132. pP = pP->pNext;
  1133. }
  1134. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Merging configuration : security" CRLF));
  1135. Security *pS = pConfig->pSecurityList;
  1136. while (pS) {
  1137. pS->fDeleteKEY = TRUE;
  1138. pS->fDeletePIN = TRUE;
  1139. pS = pS->pNext;
  1140. }
  1141. // New = file + registry - old...
  1142. while (pRegistry) {
  1143. Security *pNext = pRegistry->pNext;
  1144. Security *pExist = Get (pConfig->pSecurityList, pRegistry->bt);
  1145. Security *pFileSec = Get (pFileS, pRegistry->bt);
  1146. if (pFileSec) // Registry ALWAYS superceedes file for link keys
  1147. pFileSec->cKey = 0;
  1148. if (pExist && (pRegistry->cKey == 16)) {
  1149. if ((pExist->acKey == 0) || memcmp (pExist->acKey, pRegistry->acKey, 16))
  1150. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: KEY for %04x%08x is updated" CRLF, GET_NAP(pRegistry->bt), GET_SAP(pRegistry->bt)));
  1151. pExist->cKey = 16;
  1152. memcpy (pExist->acKey, pRegistry->acKey, 16);
  1153. delete pRegistry;
  1154. pRegistry = pNext;
  1155. continue;
  1156. }
  1157. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: New KEY for %04x%08x" CRLF, GET_NAP(pRegistry->bt), GET_SAP(pRegistry->bt)));
  1158. pRegistry->pNext = pConfig->pSecurityList;
  1159. pConfig->pSecurityList = pRegistry;
  1160. pRegistry = pNext;
  1161. }
  1162. while (pFileS) {
  1163. Security *pNext = pFileS->pNext;
  1164. Security *pExist = Get (pConfig->pSecurityList, pFileS->bt);
  1165. if (pExist) {
  1166. if (pFileS->cKey) {
  1167. pExist->fDeleteKEY = FALSE;
  1168. if (memcmp (pFileS->acKey, pExist->acKey, 16)) {
  1169. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: KEY for %04x%08x is updated" CRLF, GET_NAP(pFileS->bt), GET_SAP(pFileS->bt)));
  1170. pExist->cKey = 16;
  1171. memcpy (pExist->acKey, pFileS->acKey, 16);
  1172. BthSetLinkKey (&pExist->bt, pExist->acKey);
  1173. }
  1174. }
  1175. if (pFileS->cPin) {
  1176. pExist->fDeletePIN = FALSE;
  1177. if ((pFileS->cPin != pExist->cPin) || memcmp (pFileS->acPin, pExist->acPin, 16)) {
  1178. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: PIN for %04x%08x is updated" CRLF, GET_NAP(pFileS->bt), GET_SAP(pFileS->bt)));
  1179. pExist->cPin = pFileS->cPin;
  1180. memcpy (pExist->acPin, pFileS->acPin, pFileS->cPin);
  1181. BthSetPIN (&pExist->bt, pExist->cPin, pExist->acPin);
  1182. }
  1183. }
  1184. delete pFileS;
  1185. pFileS = pNext;
  1186. continue;
  1187. }
  1188. if (pFileS->cKey) {
  1189. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: New KEY for %04x%08x" CRLF, GET_NAP(pFileS->bt), GET_SAP(pFileS->bt)));
  1190. BthSetLinkKey (&pFileS->bt, pFileS->acKey);
  1191. }
  1192. if (pFileS->cPin) {
  1193. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: New PIN for %04x%08x" CRLF, GET_NAP(pFileS->bt), GET_SAP(pFileS->bt)));
  1194. BthSetPIN (&pFileS->bt, pFileS->cPin, pFileS->acPin);
  1195. }
  1196. pFileS->pNext = pConfig->pSecurityList;
  1197. pConfig->pSecurityList = pFileS;
  1198. pFileS = pNext;
  1199. }
  1200. Security *pParentS = NULL;
  1201. pS = pConfig->pSecurityList;
  1202. while (pS) {
  1203. if (pS->fDeletePIN) {
  1204. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: PIN for %04x%08x is retired" CRLF, GET_NAP(pS->bt), GET_SAP(pS->bt)));
  1205. if (pS->cPin)
  1206. BthRevokePIN (&pS->bt);
  1207. pS->cPin = 0;
  1208. pS->fDeletePIN = FALSE;
  1209. }
  1210. if (pS->fDeleteKEY) {
  1211. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: KEY for %04x%08x is retired" CRLF, GET_NAP(pS->bt), GET_SAP(pS->bt)));
  1212. if (pS->cKey)
  1213. BthRevokeLinkKey (&pS->bt);
  1214. pS->cKey = 0;
  1215. pS->fDeleteKEY = FALSE;
  1216. }
  1217. if ((pS->cKey == 0) && (pS->cPin == 0)) {
  1218. if (! pParentS)
  1219. pConfig->pSecurityList = pS->pNext;
  1220. else
  1221. pParentS->pNext = pS->pNext;
  1222. delete pS;
  1223. pS = pParentS ? pParentS->pNext : pConfig->pSecurityList;
  1224. continue;
  1225. }
  1226. pParentS = pS;
  1227. pS = pS->pNext;
  1228. }
  1229. return TRUE;
  1230. }
  1231. static Config *ReadConfig (void) {
  1232. Config *pConfig = new Config;
  1233. WCHAR szFileName[_MAX_PATH];
  1234. GetPersistentName (szFileName, _MAX_PATH);
  1235. Parse (szFileName, pConfig);
  1236. return pConfig;
  1237. }
  1238. static void WriteByteSequence (FILE *fp, int c, unsigned char *p) {
  1239. while (c > 0) {
  1240. fputc (hxd((*p) >> 4), fp);
  1241. fputc (hxd((*p) & 0xf), fp);
  1242. fputwc (L' ', fp);
  1243. ++p;
  1244. --c;
  1245. }
  1246.     fputc ('n', fp);
  1247. }
  1248. static void Write (Config *pConfig) {
  1249. WCHAR szFileName[_MAX_PATH];
  1250. GetPersistentName (szFileName, _MAX_PATH);
  1251. FILE *fp = _wfopen (szFileName, L"w");
  1252. if (! fp) {
  1253. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Could not save configuration: failed to open %s! Error = %d" CRLF, szFileName, GetLastError ()));
  1254. return;
  1255. }
  1256. PrintDefaultHeader (fp, L"");
  1257. fwprintf (fp, L"AUTH=%stt; Legal values are ON or OFFn", pConfig->fa ? L"ON":L"OFF");
  1258. fwprintf (fp, L"ENCRYPT=%stt; Legal values are ON or OFFn", pConfig->fe ? L"ON":L"OFF");
  1259. if (pConfig->uiRasAuth) {
  1260. fwprintf (fp, L"RASAUTH=");
  1261. if ((pConfig->uiRasAuth & RASEO_ProhibitPAP) == 0)
  1262. fwprintf (fp, L"PAP ");
  1263. if ((pConfig->uiRasAuth & RASEO_ProhibitCHAP) == 0)
  1264. fwprintf (fp, L"CHAP ");
  1265. if ((pConfig->uiRasAuth & RASEO_ProhibitMsCHAP) == 0)
  1266. fwprintf (fp, L"MSCHAP ");
  1267. if ((pConfig->uiRasAuth & RASEO_ProhibitMsCHAP2) == 0)
  1268. fwprintf (fp, L"MSCHAPv2 ");
  1269. fwprintf (fp, L"tt; Legal values are NONE or a list of any of PAP CHAP MSCHAP MSCHAPv2n");
  1270. }
  1271. Port *pP = pConfig->pPortList;
  1272. while (pP) {
  1273. fwprintf (fp, L"; configure COM%d:n", pP->index);
  1274. WCHAR szChan[20];
  1275. WCHAR szNdx2[20];
  1276. szChan[0] = '';
  1277. szNdx2[0] = '';
  1278. if (pP->channel)
  1279. wsprintf (szChan, L":%d", pP->channel);
  1280. if (pP->fModem)
  1281. wsprintf (szNdx2, L",%d", pP->index2);
  1282. fwprintf (fp, L"PORT=%s,%d%s%sn", pP->szDevName, pP->index, szChan, szNdx2);
  1283. pP = pP->pNext;
  1284. }
  1285. Security *pS = pConfig->pSecurityList;
  1286. while (pS) {
  1287. if (pS->cPin) {
  1288. fwprintf (fp, L"; set PIN code for device %04x%08xn", GET_NAP(pS->bt), GET_SAP(pS->bt));
  1289. fwprintf (fp, L"PIN%04x%08x=", GET_NAP(pS->bt), GET_SAP(pS->bt));
  1290. WriteByteSequence (fp, pS->cPin, pS->acPin);
  1291. }
  1292. if (pS->cKey) {
  1293. fwprintf (fp, L"; set link key for device %04x%08xn", GET_NAP(pS->bt), GET_SAP(pS->bt));
  1294. fwprintf (fp, L"KEY%04x%08x=", GET_NAP(pS->bt), GET_SAP(pS->bt));
  1295. WriteByteSequence (fp, pS->cKey, pS->acKey);
  1296. }
  1297. pS = pS->pNext;
  1298. }
  1299. fclose (fp);
  1300. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: configuration saved to file %s" CRLF, szFileName));
  1301. }
  1302. static void UpdateConfig (Config *pConfig) {
  1303. WCHAR szFileName[_MAX_PATH];
  1304. GetPersistentName (szFileName, _MAX_PATH);
  1305. if (Parse (szFileName, pConfig))
  1306. Write (pConfig);
  1307. }
  1308. //
  1309. // main
  1310. //
  1311. //
  1312. int wmain (int argc, WCHAR **argv) {
  1313. RETAILMSG(1, (CRLF CRLF CRLF CRLF L"Welcome to Windows CE Bluetooth gateway" CRLF CRLF CRLF CRLF));
  1314. int fSleep = TRUE;
  1315. HANDLE hExit     = CreateEvent (NULL, FALSE, FALSE, L"system/events/bluetooth/gateway/exit");
  1316. if (! hExit) {
  1317. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Could not create event! Error = %d" CRLF, GetLastError ()));
  1318. return 0;
  1319. }
  1320. for (int i = 1 ; i < argc ; ++i) {
  1321. if (wcsicmp (argv[i], L"-nosleep") == 0)
  1322. fSleep = FALSE;
  1323. else
  1324. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: unknown parameter %s" CRLF, argv[i]));
  1325. }
  1326. if (fSleep) {
  1327. for (i = 0 ; i < GW_SLEEP ; ++i) {
  1328. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Sleeping for 1000 ms (%d)" CRLF, GW_SLEEP - i));
  1329. Sleep (1000);
  1330. }
  1331. }
  1332. if (SetGlobalPPPConfig() != 0) {
  1333. CloseHandle (hExit);
  1334. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Initialization of PPP server failed!" CRLF));
  1335. return 0;
  1336. }
  1337. WSADATA wsd;
  1338. if (WSAStartup (MAKEWORD(1,0), &wsd)) {
  1339. CloseHandle (hExit);
  1340. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Initialization of socket subsystem failed! Error = %d" CRLF, WSAGetLastError ()));
  1341. return 0;
  1342. }
  1343. HANDLE hEvent = CreateEvent (NULL, FALSE, FALSE, L"system/events/bluetooth/gateway/refresh");
  1344. if (! hEvent) {
  1345. CloseHandle (hExit);
  1346. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: Could not create event! Error = %d" CRLF, GetLastError ()));
  1347. return 0;
  1348. }
  1349. HANDLE hSecurity = CreateEvent (NULL, TRUE, FALSE, BTH_NAMEDEVENT_PAIRING_CHANGED);
  1350. HANDLE hWaitArray[3];
  1351. hWaitArray[0] = hEvent;
  1352. hWaitArray[1] = hExit;
  1353. hWaitArray[2] = hSecurity;
  1354. DWORD cWaitEvents = hSecurity ? 3 : 2;
  1355. Config *pConfig = ReadConfig ();
  1356. DisplayPPP ();
  1357. for ( ; ; ) {
  1358. DWORD dwRes = WaitForMultipleObjects (cWaitEvents, hWaitArray, FALSE, INFINITE);
  1359. if ((dwRes == WAIT_OBJECT_0) || (dwRes == (WAIT_OBJECT_0 + 2))) { // Refresh config
  1360. UpdateConfig (pConfig);
  1361. DisplayPPP ();
  1362. continue;
  1363. }
  1364. if (dwRes != (WAIT_OBJECT_0 + 1))
  1365. RETAILMSG(1, (L"BLUETOOTH GATEWAY:: fatal error %d" CRLF, GetLastError ()));
  1366. break;
  1367. }
  1368. RETAILMSG(1, (CRLF CRLF CRLF CRLF L"BLUETOOTH GATEWAY:: cleaning up and exiting..." CRLF CRLF CRLF CRLF));
  1369. while (pConfig->pPortList) {
  1370. Port *pThis = pConfig->pPortList;
  1371. pConfig->pPortList = pConfig->pPortList->pNext;
  1372. ClosePort (pThis);
  1373. delete pThis;
  1374. }
  1375. while (pConfig->pSecurityList) {
  1376. Security *pThis = pConfig->pSecurityList;
  1377. pConfig->pSecurityList = pConfig->pSecurityList->pNext;
  1378. if (pThis->cPin)
  1379. BthRevokePIN (&pThis->bt);
  1380. delete pThis;
  1381. }
  1382. delete pConfig;
  1383. return 0;
  1384. }