📄 btmodem.cxx
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
*/
//
// This code implements boot-time activation of registered Bluetooth peers,
// as well as authentication UI.
//
// It is heavily dependent on registry key structure created by
// public\common\oak\drivers\netui components (btmgmtui).
//
// Please maintain synchronization between the two files.
//
//
#include <windows.h>
//#include <service.h>
#include <stdio.h>
#include <svsutil.hxx>
#include <winsock2.h>
#include <ws2bth.h>
#include <bt_sdp.h>
#include <bthapi.h>
#include <bt_api.h>
//#define DUMPCOMM 1
#define BTH_MODEM_TIMEOUT 15000
#define BTH_MODEM_MTU 256
#define BUF_MAX 1024
#define BTH_MODEM_REGBASE L"software\\microsoft\\bluetooth\\modemgw"
#define BTH_MODEM_BAUD 115200
#define BTH_MODEM_HARDWARE 1
#define BTH_MODEM_SOFTWARE 2
#define BTH_MODEM_NONE 3
#define BTH_BLUETOOTH_READER L"Bluetooth Port Reader"
#define BTH_MODEM_READER L"Modem Port Reader"
#define MAX_WRITE_FAILS 5
#define MAX_READ_FAILS 10
#define CRLF L"\r\n"
static DWORD gfServiceState = SERVICE_STATE_OFF;
static HANDLE ghServiceThread;
static HANDLE ghServiceExitEvent;
#define SDP_RECORD_SIZE 0x0000004d
#define SDP_CHANNEL_OFFSET 26
static const BYTE rgbSdpRecordDUN[] = {
0x35, 0x4b, 0x09, 0x00, 0x01, 0x35, 0x03, 0x19,
0x11, 0x03, 0x09, 0x00, 0x04, 0x35, 0x0c, 0x35,
0x03, 0x19, 0x01, 0x00, 0x35, 0x05, 0x19, 0x00,
0x03, 0x08,
0x01, // server channel goes here (+26)
0x09, 0x00, 0x06, 0x35, 0x09,
0x09, 0x65, 0x6e, 0x09, 0x00, 0x6a, 0x09, 0x01,
0x00, 0x09, 0x00, 0x09, 0x35, 0x08, 0x35, 0x06,
0x19, 0x11, 0x03, 0x09, 0x01, 0x00, 0x09, 0x01,
0x00, 0x25, 0x12, 'D', 'i', 'a', 'l', '-',
'u', 'p', ' ', 'N', 'e', 't', 'w', 'o',
'r', 'k', 'i', 'n', 'g'
};
extern "C" BOOL WINAPI DllMain( HANDLE hInstDll, DWORD fdwReason, LPVOID lpvReserved) {
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
static ULONG RegisterSDP (HANDLE hFile) {
ULONG recordHandle = 0;
DWORD port = 0;
DWORD dwSizeOut = 0;
if (! DeviceIoControl (hFile, IOCTL_BLUETOOTH_GET_RFCOMM_CHANNEL, NULL, 0, &port, sizeof(port), &dwSizeOut, NULL)) {
RETAILMSG(1, (L"Bluetooth modem gateway: Failed to retrieve port server channel, error = %d" CRLF, GetLastError ()));
return 0;
}
struct {
BTHNS_SETBLOB b;
unsigned char uca[SDP_RECORD_SIZE];
} bigBlob;
ULONG ulSdpVersion = BTH_SDP_VERSION;
bigBlob.b.pRecordHandle = &recordHandle;
bigBlob.b.pSdpVersion = &ulSdpVersion;
bigBlob.b.fSecurity = 0;
bigBlob.b.fOptions = 0;
bigBlob.b.ulRecordLength = SDP_RECORD_SIZE;
memcpy (bigBlob.b.pRecord, rgbSdpRecordDUN, SDP_RECORD_SIZE);
bigBlob.b.pRecord[SDP_CHANNEL_OFFSET] = (unsigned char)port;
BLOB blob;
blob.cbSize = sizeof(BTHNS_SETBLOB) + SDP_RECORD_SIZE - 1;
blob.pBlobData = (PBYTE) &bigBlob;
WSAQUERYSET Service;
memset (&Service, 0, sizeof(Service));
Service.dwSize = sizeof(Service);
Service.lpBlob = &blob;
Service.dwNameSpace = NS_BTH;
int iRet = BthNsSetService (&Service, RNRSERVICE_REGISTER,0);
if (iRet != ERROR_SUCCESS) {
RETAILMSG(1, (L"Bluetooth modem gateway: BthNsSetService fails with status %d" CRLF, iRet));
return 0;
}
RETAILMSG(1, (L"Bluetooth modem gateway: Created SDP record 0x%08x, channel %d" CRLF, recordHandle, port));
return recordHandle;
}
static void DeRegisterSDP (ULONG recordHandle) {
ULONG ulSdpVersion = BTH_SDP_VERSION;
BTHNS_SETBLOB delBlob;
memset (&delBlob, 0, sizeof(delBlob));
delBlob.pRecordHandle = &recordHandle;
delBlob.pSdpVersion = &ulSdpVersion;
BLOB blob;
blob.cbSize = sizeof(BTHNS_SETBLOB);
blob.pBlobData = (PBYTE) &delBlob;
WSAQUERYSET Service;
memset (&Service, 0, sizeof(Service));
Service.dwSize = sizeof(Service);
Service.lpBlob = &blob;
Service.dwNameSpace = NS_BTH;
int iErr = BthNsSetService (&Service, RNRSERVICE_DELETE, 0);
RETAILMSG (1, (L"Bluetooth modem gateway: removed SDP record 0x%08x (%d)" CRLF, recordHandle, iErr));
}
static HANDLE CreatePort (int port, int channel, int mtu, int fa, int fe) {
PORTEMUPortParams pp;
memset (&pp, 0, sizeof(pp));
pp.flocal = TRUE;
pp.channel = channel;
pp.imtu = mtu;
if (fa)
pp.uiportflags |= RFCOMM_PORT_FLAGS_AUTHENTICATE;
if (fe)
pp.uiportflags |= RFCOMM_PORT_FLAGS_ENCRYPT;
WCHAR szKeyName[_MAX_PATH];
wsprintf (szKeyName, BTH_MODEM_REGBASE L"\\com%d", port);
HKEY hk;
DWORD dwDisp = 0;
if (ERROR_SUCCESS != RegCreateKeyEx (HKEY_LOCAL_MACHINE, szKeyName, 0, NULL, 0, KEY_WRITE, NULL, &hk, &dwDisp)) {
RETAILMSG(1, (L"Bluetooth modem gateway: Failed to create registry key %s, error = %d" CRLF, szKeyName, GetLastError ()));
return NULL;
}
RegSetValueEx (hk, L"dll", 0, REG_SZ, (BYTE *)L"btd.dll", sizeof(L"btd.dll"));
RegSetValueEx (hk, L"prefix", 0, REG_SZ, (BYTE *)L"COM", sizeof(L"COM"));
DWORD dw = port;
RegSetValueEx (hk, L"index", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw));
dw = (DWORD) &pp;
RegSetValueEx (hk, L"context", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw));
RegCloseKey (hk);
HANDLE hDevice = ActivateDevice (szKeyName, 0);
if (! hDevice) {
RETAILMSG(1, (L"Bluetooth modem gateway: Failed to activate device @ %s (error = %d)" CRLF, szKeyName, GetLastError ()));
}
RegDeleteKey (HKEY_LOCAL_MACHINE, szKeyName);
return hDevice;
}
#if defined (DUMPCOMM)
#define BPR 8
static void DumpBuff (WCHAR *szLineHeader, unsigned char *lpBuffer, unsigned int cBuffer) {
WCHAR szLine[5 + 7 + 2 + 4 * BPR];
for (int i = 0 ; i < (int)cBuffer ; i += BPR) {
int bpr = cBuffer - i;
if (bpr > BPR)
bpr = BPR;
wsprintf (szLine, L"%04x ", i);
WCHAR *p = szLine + wcslen (szLine);
for (int j = 0 ; j < bpr ; ++j) {
WCHAR c = (lpBuffer[i + j] >> 4) & 0xf;
if (c > 9) c += L'a' - 10; else c += L'0';
*p++ = c;
c = lpBuffer[i + j] & 0xf;
if (c > 9) c += L'a' - 10; else c += L'0';
*p++ = c;
*p++ = L' ';
}
for ( ; j < BPR ; ++j) {
*p++ = L' ';
*p++ = L' ';
*p++ = L' ';
}
*p++ = L' ';
*p++ = L' ';
*p++ = L' ';
*p++ = L'|';
*p++ = L' ';
*p++ = L' ';
*p++ = L' ';
for (j = 0 ; j < bpr ; ++j) {
WCHAR c = lpBuffer[i + j];
if ((c < L' ') || (c >= 127))
c = L'.';
*p++ = c;
}
for ( ; j < BPR ; ++j) {
*p++ = L' ';
}
*p++ = L'\0';
RETAILMSG(1, (L"%s %s" CRLF, szLineHeader ? szLineHeader : L"", szLine));
}
}
#endif
static void SendCommand (HANDLE hFile, char *command, int sleeptime) {
#if defined (DUMPCOMM)
WCHAR szCommand[1024];
if (MultiByteToWideChar (CP_ACP, 0, command, -1, szCommand, 1024))
RETAILMSG (1, (L"Bluetooth modem gateway: writing %s" CRLF, szCommand));
#endif
DWORD ch = strlen (command);
PurgeComm (hFile, PURGE_RXCLEAR|PURGE_TXCLEAR);
DWORD dwWritFails = 0;
DWORD dwWrit = 0;
while (ch > 0 && (dwWritFails < MAX_WRITE_FAILS)) {
int fRet = WriteFile (hFile, command, ch, &dwWrit, NULL);
if (! fRet) {
#if defined (DUMPCOMM)
RETAILMSG(1, (L"Bluetooth modem : WRITE FAIL ERROR %d" CRLF, GetLastError ()));
#endif
return;
}
command += dwWrit;
ch -= dwWrit;
if (dwWrit == 0)
dwWritFails++;
else
dwWritFails = 0;
dwWrit = 0;
}
Sleep (sleeptime);
char resp[100];
DWORD dwRead = 0;
DWORD dwReadFails = 0;
do {
int fRet = ReadFile (hFile, resp, sizeof(resp)-1, &dwRead, NULL);
if (! fRet) {
#if defined (DUMPCOMM)
RETAILMSG(1, (L"Bluetooth modem : READ FAIL ERROR %d" CRLF, GetLastError ()));
#endif
break;
}
if (dwRead) {
#if defined (DUMPCOMM)
DumpBuff (L"Bluetooth modem : Send Response >", (unsigned char *)resp, dwRead);
#endif
dwReadFails = 0;
resp[dwRead] = '\0';
if (strchr (resp, '\n') || strchr (resp, '\r'))
break;
} else {
#if defined (DUMPCOMM)
RETAILMSG(1, (L"Bluetooth modem : READ NOTHING" CRLF));
#endif
++dwReadFails;
}
} while (dwReadFails < MAX_READ_FAILS);
}
static int HangUpModem (HANDLE hModem) {
#if defined (DUMPCOMM)
RETAILMSG(1, (L"Bluetooth modem gateway: Hanging up" CRLF));
#endif
DWORD dwModem2 = 0;
Sleep (1000);
GetCommModemStatus (hModem, &dwModem2);
if (dwModem2 & MS_RLSD_ON) { // We're finished with Bluetooth connection, but the other line is still up!
#if defined (DUMPCOMM)
RETAILMSG(1, (L"Bluetooth modem gateway: RLSD ON on modem - terminating connection..." CRLF));
#endif
Sleep (1500);
SendCommand (hModem, "+++", 1500);
SendCommand (hModem, "ATH\r", 0);
SendCommand (hModem, "ATZ\r", 0);
return TRUE;
}
return FALSE;
}
static DWORD WINAPI ComCopyThread (LPVOID lpVoid) {
HANDLE hSource = NULL;
HANDLE hDest = NULL;
WCHAR name[_MAX_PATH];
__try {
void **pah = (HANDLE *)lpVoid;
hSource = (HANDLE)pah[0];
hDest = (HANDLE)pah[1];
if (wcslen ((WCHAR *)pah[2]) >= _MAX_PATH) {
RETAILMSG (1, (L"Bluetooth modem gateway: invalid parameters in reader thread" CRLF));
SetEvent (ghServiceExitEvent);
return 0;
}
wcscpy (name, (WCHAR *)pah[2]);
} __except (1) {
RETAILMSG (1, (L"Bluetooth Modem Gateway: Exception in reader thread" CRLF));
SetEvent (ghServiceExitEvent);
return 0;
}
int fBluetoothThread = (wcscmp (name, BTH_BLUETOOTH_READER) == 0);
RETAILMSG (1, (L"Bluetooth Modem Gateway: %s thread up" CRLF, name));
SetCommMask (hSource, EV_RXCHAR | EV_CTS | EV_DSR | EV_RLSD | EV_ERR | EV_RING | EV_EVENT1);
for ( ; ; ) {
DWORD ModemState = 0;
if (! WaitCommEvent (hSource, &ModemState, NULL))
break;
#if defined (DUMPCOMM)
RETAILMSG(1, (L"Bluetooth modem gateway: %s thread woke up, Event flags: 0x%08x" CRLF, name, ModemState));
#endif
if (ModemState & EV_RXCHAR) {
char buffer[BUF_MAX];
DWORD dwRead = 0;
if (! ReadFile (hSource, buffer, sizeof(buffer), &dwRead, NULL))
break;
#if defined (DUMPCOMM)
DumpBuff (name, (unsigned char *)buffer, dwRead);
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -