📄 蓝牙虚拟串口.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.
//
#include <windows.h>
#include <ras.h>
#include "ndis.h"
#include "nuiouser.h"
#include <svsutil.hxx>
#include <bt_api.h>
#include <bt_buffer.h>
#include <bt_ddi.h>
#include "btenum.hxx"
#include "bthid.h"
#define HID_CLIENT_REGKEY_SZ _T("Software\\Microsoft\\Bluetooth\\Hid\\Hid_Class")
#define HID_REGKEY_SZ _T("Software\\Microsoft\\Bluetooth\\Hid\\Instance")
// RAS
typedef DWORD (RASAPI * p_RasSetEntryDialParams) (LPWSTR lpszPhoneBook, LPRASDIALPARAMS lpRasDialParams, BOOL fRemovePassword);
typedef DWORD (RASAPI * p_RasGetEntryProperties) (LPWSTR lpszPhoneBook, LPWSTR szEntry, LPRASENTRY lpEntry, LPDWORD lpdwEntrySize, LPBYTE lpb, LPDWORD lpdwSize);
typedef DWORD (RASAPI * p_RasSetEntryProperties) (LPWSTR lpszPhoneBook, LPWSTR szEntry, LPRASENTRY lpEntry, DWORD dwEntrySize, LPBYTE lpb, DWORD dwSize);
typedef DWORD (RASAPI * p_RasDeleteEntry) (LPWSTR lpszPhonebook, LPWSTR lpszEntry);
static LPWSTR gszKeyNames[BTENUM_CLASSES + 1] = {L"modem", L"printer", L"lan_access", L"file_trans", L"OBEX", L"Headset", L"ActiveSync", L"HID", L"PAN", L"Handsfree", L"UNKNOWN"};
static int gimtu[BTENUM_CLASSES + 1] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
static int gauth[BTENUM_CLASSES + 1];
static int gencr[BTENUM_CLASSES + 1];
static int gidefault_mtu = 0;
static int gidefault_auth = 0;
static int gidefault_encr = 0;
static WCHAR gszAdapterName[50];
static p_RasGetEntryProperties g_pfnRasGetEntryProperties;
static p_RasSetEntryProperties g_pfnRasSetEntryProperties;
static p_RasSetEntryDialParams g_pfnRasSetEntryDialParams;
static p_RasDeleteEntry g_pfnRasDeleteEntry;
static int GetBA (WCHAR *pp, BT_ADDR *pba) {
*pba = 0;
while (*pp == ' ')
++pp;
for (int i = 0 ; i < 12 ; ++i, ++pp) {
if (! iswxdigit (*pp))
return FALSE;
int c = *pp;
if (c >= 'a')
c = c - 'a' + 0xa;
else if (c >= 'A')
c = c - 'A' + 0xa;
else c = c - '0';
if ((c < 0) || (c > 16))
return FALSE;
*pba = *pba * 16 + c;
}
if ((*pp != ' ') && (*pp != '\0'))
return FALSE;
return TRUE;
}
static BOOL HexStringToDword(WCHAR *lpsz, DWORD &Value, int cDigits, WCHAR chDelim) {
Value = 0;
for (int Count = 0; Count < cDigits; Count++, lpsz++) {
if (*lpsz >= '0' && *lpsz <= '9')
Value = (Value << 4) + *lpsz - '0';
else if (*lpsz >= 'A' && *lpsz <= 'F')
Value = (Value << 4) + *lpsz - 'A' + 10;
else if (*lpsz >= 'a' && *lpsz <= 'f')
Value = (Value << 4) + *lpsz - 'a' + 10;
else
return(FALSE);
}
if (chDelim != 0)
return *lpsz++ == chDelim;
else
return TRUE;
}
static int StrToGUID (WCHAR *szStr, GUID *pguid) {
WCHAR *lpsz = szStr;
DWORD dw;
if (*lpsz++ != '{')
return FALSE;
if (!HexStringToDword(lpsz, pguid->Data1, sizeof(DWORD)*2, '-'))
return FALSE;
if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
return FALSE;
pguid->Data2 = (WORD)dw;
if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
return FALSE;
pguid->Data3 = (WORD)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
return FALSE;
pguid->Data4[0] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '-'))
return FALSE;
pguid->Data4[1] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
return FALSE;
pguid->Data4[2] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
return FALSE;
pguid->Data4[3] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
return FALSE;
pguid->Data4[4] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
return FALSE;
pguid->Data4[5] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
return FALSE;
pguid->Data4[6] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
return FALSE;
pguid->Data4[7] = (BYTE)dw;
if (*lpsz++ != '}')
return FALSE;
if (*lpsz++ != '\0')
return FALSE;
return TRUE;
}
static int SignalPAN (void) {
HANDLE hEvent = OpenEvent (EVENT_ALL_ACCESS, FALSE, BTH_NAMEDEVENT_PAN_REFRESH);
if (! hEvent)
return FALSE;
SetEvent (hEvent);
CloseHandle (hEvent);
return TRUE;
}
static void DeactivatePanDevice (BTDEV *pbtDevice) {
WCHAR szRegKey[_MAX_PATH];
wsprintf (szRegKey, L"COMM\\%s\\Associations\\%04x%08x", gszAdapterName, GET_NAP(pbtDevice->b), GET_SAP(pbtDevice->b));
RegDeleteKey (HKEY_LOCAL_MACHINE, szRegKey);
HANDLE h = CreateFile(
NDISUIO_DEVICE_NAME, // Object name.
0x00, // Desired access.
0x00, // Share Mode.
NULL, // Security Attr
OPEN_EXISTING, // Creation Disposition.
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // Flag and Attributes..
(HANDLE)INVALID_HANDLE_VALUE);
if (INVALID_HANDLE_VALUE != h) {
DWORD dwWritten = 0;
struct {
NDISUIO_SET_OID SetOid;
unsigned char uca[64];
} NdisUioSetOid;
NdisUioSetOid.SetOid.Oid = OID_PAN_DISCONNECT;
NdisUioSetOid.SetOid.ptcDeviceName = L"BTPAN1";
memcpy(&NdisUioSetOid.SetOid.Data, &pbtDevice->b, sizeof(BD_ADDR));
DeviceIoControl(
h,
IOCTL_NDISUIO_SET_OID_VALUE,
&NdisUioSetOid,
sizeof(NdisUioSetOid),
NULL,
0,
&dwWritten,
NULL);
CloseHandle(h);
}
}
static int ActivatePanDevice (BTDEV *pbtDevice, int fFirstTime) {
WCHAR szRegKey[_MAX_PATH];
wsprintf (szRegKey, L"COMM\\%s\\Associations\\%04x%08x", gszAdapterName, GET_NAP(pbtDevice->b), GET_SAP(pbtDevice->b));
DWORD dwDisp;
HKEY hk;
if (ERROR_SUCCESS == RegCreateKeyEx (HKEY_LOCAL_MACHINE, szRegKey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hk, &dwDisp)) {
WCHAR szAddr[40];
wsprintf (szAddr, L"%04x%08x", GET_NAP(pbtDevice->b), GET_SAP(pbtDevice->b));
RegSetValueEx (hk, L"Address", 0, REG_SZ, (BYTE *)szAddr, sizeof(WCHAR) * (wcslen(szAddr) + 1));
WCHAR szServiceId[60];
wsprintf (szServiceId, L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
pbtDevice->service_id.Data1, pbtDevice->service_id.Data2, pbtDevice->service_id.Data3,
pbtDevice->service_id.Data4[0], pbtDevice->service_id.Data4[1], pbtDevice->service_id.Data4[2], pbtDevice->service_id.Data4[3],
pbtDevice->service_id.Data4[4], pbtDevice->service_id.Data4[5], pbtDevice->service_id.Data4[6], pbtDevice->service_id.Data4[7]);
RegSetValueEx (hk, L"ServiceId", 0, REG_SZ, (BYTE*)szServiceId, (wcslen(szServiceId) + 1) * sizeof(WCHAR));
WCHAR szSSID[50];
wsprintf (szSSID, L"PAN@%04x%08x", GET_NAP(pbtDevice->b), GET_SAP(pbtDevice->b));
RegSetValueEx (hk, L"SSID", 0, REG_SZ, (BYTE*)szSSID, (wcslen(szSSID) + 1) * sizeof(WCHAR));
DWORD dw = 1;
RegSetValueEx (hk, L"Priority", 0, REG_DWORD, (BYTE*)&dw, sizeof(dw));
RegCloseKey (hk);
HANDLE h = CreateFile(
NDISUIO_DEVICE_NAME, // Object name.
0x00, // Desired access.
0x00, // Share Mode.
NULL, // Security Attr
OPEN_EXISTING, // Creation Disposition.
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // Flag and Attributes..
(HANDLE)INVALID_HANDLE_VALUE);
if (INVALID_HANDLE_VALUE != h) {
DWORD dwWritten;
struct {
NDISUIO_SET_OID SetOid;
unsigned char uca[64];
} NdisUioSetOid;
// --- Set Authentication for the connection
NdisUioSetOid.SetOid.Oid = OID_PAN_AUTHENTICATE;
NdisUioSetOid.SetOid.ptcDeviceName = L"BTPAN1";
*(PDWORD)NdisUioSetOid.SetOid.Data = pbtDevice->fAuth;
dwWritten = 0;
if (! DeviceIoControl(
h,
IOCTL_NDISUIO_SET_OID_VALUE,
&NdisUioSetOid,
sizeof(NdisUioSetOid),
NULL,
0,
&dwWritten,
NULL)) {
CloseHandle(h);
return FALSE;
}
// --- Set Encryption for the connection
NdisUioSetOid.SetOid.Oid = OID_PAN_ENCRYPT;
NdisUioSetOid.SetOid.ptcDeviceName = L"BTPAN1";
*(PDWORD)NdisUioSetOid.SetOid.Data = pbtDevice->fEncrypt;
dwWritten = 0;
if (! DeviceIoControl(
h,
IOCTL_NDISUIO_SET_OID_VALUE,
&NdisUioSetOid,
sizeof(NdisUioSetOid),
NULL,
0,
&dwWritten,
NULL)) {
CloseHandle(h);
return FALSE;
}
// --- Connect
NdisUioSetOid.SetOid.Oid = OID_PAN_CONNECT;
NdisUioSetOid.SetOid.ptcDeviceName = L"BTPAN1";
memcpy(&NdisUioSetOid.SetOid.Data, &pbtDevice->b, sizeof(BD_ADDR));
memcpy((PBYTE)NdisUioSetOid.SetOid.Data + sizeof(BD_ADDR), &pbtDevice->service_id, sizeof(GUID));
dwWritten = 0;
if (! DeviceIoControl(
h,
IOCTL_NDISUIO_SET_OID_VALUE,
&NdisUioSetOid,
sizeof(NdisUioSetOid),
NULL,
0,
&dwWritten,
NULL)) {
CloseHandle(h);
return FALSE;
}
CloseHandle(h);
return TRUE;
}
}
return FALSE;
}
static void BthEnumInit (void) {
static int fInited = FALSE;
if (fInited)
return;
fInited = TRUE;
HINSTANCE hCoreDll = LoadLibrary (L"coredll.dll");
if(hCoreDll) {
g_pfnRasGetEntryProperties = (p_RasGetEntryProperties)GetProcAddress (hCoreDll, L"RasGetEntryProperties");
g_pfnRasSetEntryProperties = (p_RasSetEntryProperties)GetProcAddress (hCoreDll, L"RasSetEntryProperties");
g_pfnRasSetEntryDialParams = (p_RasSetEntryDialParams)GetProcAddress (hCoreDll, L"RasSetEntryDialParams");
g_pfnRasDeleteEntry = (p_RasDeleteEntry) GetProcAddress (hCoreDll, L"RasDeleteEntry");
}
if ((! g_pfnRasGetEntryProperties) || (! g_pfnRasSetEntryProperties) || (! g_pfnRasSetEntryDialParams) || (! g_pfnRasDeleteEntry)) {
g_pfnRasGetEntryProperties = NULL;
g_pfnRasSetEntryProperties = NULL;
g_pfnRasSetEntryDialParams = NULL;
g_pfnRasDeleteEntry = NULL;
}
memset (gauth, 0, sizeof(gauth));
memset (gencr, 0, sizeof(gencr));
HKEY hk;
if (ERROR_SUCCESS != RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"software\\microsoft\\bluetooth\\device", 0, KEY_READ, &hk))
return;
int iNumDevices = 0;
DWORD dwSize = sizeof (gidefault_mtu);
DWORD dwType;
if ((ERROR_SUCCESS != RegQueryValueEx (hk, L"DefaultMtu", NULL, &dwType, (BYTE *)&gidefault_mtu, &dwSize)) ||
(dwType != REG_DWORD) || (dwSize != sizeof(gidefault_mtu)))
gidefault_mtu = 0;
dwSize = sizeof (gidefault_auth);
if ((ERROR_SUCCESS != RegQueryValueEx (hk, L"DefaultAuth", NULL, &dwType, (BYTE *)&gidefault_auth, &dwSize)) ||
(dwType != REG_DWORD) || (dwSize != sizeof(gidefault_auth)))
gidefault_auth = 0;
dwSize = sizeof (gidefault_encr);
if ((ERROR_SUCCESS != RegQueryValueEx (hk, L"DefaultEncrypt", NULL, &dwType, (BYTE *)&gidefault_encr, &dwSize)) ||
(dwType != REG_DWORD) || (dwSize != sizeof(gidefault_encr)))
gidefault_encr = 0;
for (int i = 0; i < BTENUM_CLASSES + 1; ++i) {
HKEY hkdetail;
if (ERROR_SUCCESS == RegOpenKeyEx (hk, gszKeyNames[i], 0, KEY_ALL_ACCESS , &hkdetail)) {
dwSize = sizeof (gimtu[i]);
if ((ERROR_SUCCESS != RegQueryValueEx (hkdetail, L"DefaultMtu", NULL, &dwType, (BYTE *)&gimtu[i], &dwSize)) ||
(dwType != REG_DWORD) || (dwSize != sizeof(gimtu[i])))
gimtu[i] = -1;
dwSize = sizeof (gauth[i]);
if ((ERROR_SUCCESS != RegQueryValueEx (hkdetail, L"DefaultAuth", NULL, &dwType, (BYTE *)&gauth[i], &dwSize)) ||
(dwType != REG_DWORD) || (dwSize != sizeof(gauth[i])))
gauth[i] = 0;
if (gauth[i])
gauth[i] = TRUE;
dwSize = sizeof (gencr[i]);
if ((ERROR_SUCCESS != RegQueryValueEx (hkdetail, L"DefaultEncrypt", NULL, &dwType, (BYTE *)&gencr[i], &dwSize)) ||
(dwType != REG_DWORD) || (dwSize != sizeof(gencr[i])))
gencr[i] = 0;
if (gencr[i])
gencr[i] = TRUE;
if (i == BTENUM_DEVICE_PAN) {
dwSize = sizeof (gszAdapterName);
if ((ERROR_SUCCESS != RegQueryValueEx (hkdetail, L"AdapterName", NULL, &dwType, (BYTE *)gszAdapterName, &dwSize)) ||
(dwType != REG_SZ) || (dwSize >= sizeof(gszAdapterName)))
gszAdapterName[0] = '\0';
}
RegCloseKey (hkdetail);
}
}
RegCloseKey (hk);
}
int BthEnumDevices (void *pContext, BthEnumCallback pCallback) {
BthEnumInit ();
HKEY hk;
if (ERROR_SUCCESS != RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"software\\microsoft\\bluetooth\\device", 0, KEY_READ, &hk))
return 0;
int iNumDevices = 0;
for (int i = 0; i < BTENUM_CLASSES + 1; ++i) {
HKEY hkdetail;
if (ERROR_SUCCESS == RegOpenKeyEx (hk, gszKeyNames[i], 0, KEY_ENUMERATE_SUB_KEYS , &hkdetail)) {
WCHAR szTemp1[50];
szTemp1[0] = '\0';
DWORD dwSizeKey = sizeof(szTemp1)/sizeof(WCHAR);
int iContinue = TRUE;
for (int j = 0; iContinue && (ERROR_SUCCESS == RegEnumKeyEx(hkdetail, j, szTemp1, &dwSizeKey, NULL, NULL, 0, NULL)); ++j) {
BT_ADDR b;
HKEY hkdevice;
if (GetBA(szTemp1, &b) && (ERROR_SUCCESS == RegOpenKeyEx (hkdetail, szTemp1, 0, KEY_READ, &hkdevice))) {
BTDEV bdev(b, i < BTENUM_CLASSES ? i : -1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -