📄 btd.cxx
字号:
}
if (pCall == VerifyCall (pCall)) {
if (iRes == ERROR_SUCCESS) {
if (pCall->fComplete)
iRes = pCall->iResult;
else
iRes = ERROR_INTERNAL_ERROR;
}
if (iRes == ERROR_SUCCESS)
gpState->b = pCall->baResult;
DeleteCall (pCall);
} else if (iRes == ERROR_SUCCESS)
iRes = ERROR_INTERNAL_ERROR;
if (iRes != ERROR_SUCCESS) {
gpState->Unlock ();
return iRes;
}
WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
unsigned char aComputerName[BD_MAXNAME];
memset (aComputerName, 0, sizeof(aComputerName));
if (gpState->fIsRunning && gpState->fConnected && GetComputerName (szComputerName, &dwSize) &&
(WideCharToMultiByte (CP_UTF8, 0, szComputerName, -1, (char *)aComputerName, sizeof(aComputerName), NULL, NULL) ||
WideCharToMultiByte (CP_ACP, 0, szComputerName, -1, (char *)aComputerName, sizeof(aComputerName), NULL, NULL))) {
HCI_ChangeLocalName_In pCallback = gpState->hci_if.hci_ChangeLocalName_In;
pCall = AllocCall (CALL_HCI_CHANGE_LOCAL_NAME);
if (! pCall) {
gpState->Unlock ();
return ERROR_OUTOFMEMORY;
}
pCall->hProcOwner = NULL;
HANDLE hEvent = pCall->hEvent;
gpState->AddRef ();
gpState->Unlock ();
int iRes = ERROR_INTERNAL_ERROR;
__try {
iRes = pCallback (hHCI, pCall, aComputerName);
} __except (1) {
}
if (iRes == ERROR_SUCCESS)
WaitForSingleObject (hEvent, 5000);
gpState->Lock ();
gpState->DelRef ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_CANCELLED;
}
if (pCall == VerifyCall (pCall)) {
if (iRes == ERROR_SUCCESS) {
if (pCall->fComplete)
iRes = pCall->iResult;
else
iRes = ERROR_INTERNAL_ERROR;
}
DeleteCall (pCall);
} else if (iRes == ERROR_SUCCESS)
iRes = ERROR_INTERNAL_ERROR;
if (iRes != ERROR_SUCCESS) {
gpState->Unlock ();
return iRes;
}
}
HANDLE hSignal = gpState->hNamedEvents[BTD_EVENT_HARDWARE_CHANGED];
int fHaveCOD = FALSE;
unsigned int cod = 0;
gpState->fNoSuspend = FALSE;
HKEY hk;
if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_BASE, L"software\\microsoft\\bluetooth\\sys", 0, KEY_READ, &hk)) {
DWORD dwSize = sizeof(cod);
DWORD dwType;
if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"COD", NULL, &dwType, (BYTE *)&cod, &dwSize)) &&
(dwType == REG_DWORD) && (dwSize == sizeof(cod)))
fHaveCOD = TRUE;
DWORD dw = 0;
dwSize = sizeof(dw);
if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"DisableAutoSuspend", NULL, &dwType, (BYTE *)&dw, &dwSize)) &&
(dwType == REG_DWORD) && (dwSize == sizeof(dw)) && dw)
gpState->fNoSuspend = TRUE;
RegCloseKey (hk);
}
gpState->Unlock ();
if (fHaveCOD)
BthWriteCOD (cod);
SetEvent (hSignal);
ResetEvent (hSignal);
return ERROR_SUCCESS;
}
static void ProcessExited (HANDLE hProc) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: ProcessExited 0x%08x\n", hProc));
if (! gpState)
return;
gpState->Lock ();
if (gpState->hSecurityUIProc == hProc)
CleanUpSecurityUIHandler ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return;
}
SCall *pCall = gpState->pCalls;
while (pCall) {
if ((pCall->hProcOwner == hProc) && (! pCall->fComplete)) {
pCall->fComplete = TRUE;
pCall->iResult = ERROR_SHUTDOWN_IN_PROGRESS;
SetEvent (pCall->hEvent);
}
pCall = pCall->pNext;
}
Link *pLink = gpState->pLinks;
Link *pParent = NULL;
while (pLink) {
if (pLink->hProcOwner == hProc) {
if (pParent)
pParent->pNext = pLink->pNext;
else
gpState->pLinks = pLink->pNext;
unsigned short h = pLink->h;
svsutil_FreeFixed (pLink, gpState->pfmdLinks);
HCI_Disconnect_In pCallback = gpState->hci_if.hci_Disconnect_In;
HANDLE hHCI = gpState->hHCI;
gpState->AddRef ();
gpState->Unlock ();
__try {
pCallback (hHCI, NULL, h, 0x13);
} __except (1) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"BTSHELL :: Process exited :: exception in hci_Disconnect_In\n"));
}
gpState->Lock ();
gpState->DelRef ();
pLink = gpState->pLinks;
pParent = NULL;
} else {
pParent = pLink;
pLink = pLink->pNext;
}
}
gpState->Unlock ();
SdpRemoveRecordsOnProcessExit(hProc);
}
static int CleanUpL2CAP (SCall *pCall) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: CleanUpL2CAP : ensuring that skies are clear\n"));
BT_LAYER_IO_CONTROL pCallback = gpState->l2cap_if.l2ca_ioctl;
int iRes = ERROR_INTERNAL_ERROR;
int fWait = FALSE;
int cRet = 0;
HANDLE hL2CAP = gpState->hL2CAP;
HANDLE hEvent = pCall->hEvent;
gpState->AddRef ();
gpState->Unlock ();
__try {
iRes = pCallback (hL2CAP, BTH_L2CAP_IOCTL_DROP_IDLE, sizeof(pCall), (char *)&pCall, sizeof(fWait), (char *)&fWait, &cRet);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"Shell: CleanUpL2CAP : excepted in l2ca_ioctl\n"));
}
if ((iRes == ERROR_SUCCESS) && fWait) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: CleanUpL2CAP : have connection to clean up, waiting...\n"));
WaitForSingleObject (hEvent, 15000);
}
gpState->Lock ();
gpState->DelRef ();
if (iRes != ERROR_SUCCESS) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: CleanUpL2CAP : %d\n", iRes));
return iRes;
}
if (pCall != VerifyCall (pCall)) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: CleanUpL2CAP : ERROR_INTERNAL_ERROR\n"));
return ERROR_INTERNAL_ERROR;
}
iRes = pCall->iResult;
if (iRes != ERROR_SUCCESS) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: CleanUpL2CAP : aborted, %d\n", iRes));
return iRes;
}
pCall->fComplete = FALSE;
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: CleanUpL2CAP : ERROR_SUCCESS\n"));
return ERROR_SUCCESS;
}
static int GetHandleForBA
(
BD_ADDR *pba,
unsigned short *phandle
) {
// First, get the connection handle
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"GetHandleForBA : %04x%08x : getting connection handle\n", pba->NAP, pba->SAP));
union {
BD_ADDR b;
unsigned char data[sizeof(BD_ADDR) + 1];
} in_buff;
memset (&in_buff, 0, sizeof(in_buff));
in_buff.b = *pba;
HANDLE hHCI = gpState->hHCI;
BT_LAYER_IO_CONTROL pCallbackIOCTL = gpState->hci_if.hci_ioctl;
gpState->AddRef ();
gpState->Unlock ();
int iRes = ERROR_INTERNAL_ERROR;
__try {
int dwData = 0;
iRes = pCallbackIOCTL (hHCI, BTH_HCI_IOCTL_GET_HANDLE_FOR_BD, sizeof(in_buff), (char *)&in_buff, sizeof(*phandle), (char *)phandle, &dwData);
if ((iRes == ERROR_SUCCESS) && (dwData != sizeof(*phandle))) {
IFDBG(DebugOut (DEBUG_ERROR, L"[SHELL] GetHandleForBA : %04x%08x : incorrect return buffer in hci_ioctl\n", pba->NAP, pba->SAP));
iRes = ERROR_INTERNAL_ERROR;
}
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[SHELL] GetHandleForBA : %04x%08x : exception in hci_ioctl\n", pba->NAP, pba->SAP));
}
gpState->Lock ();
gpState->DelRef ();
if ((iRes == ERROR_SUCCESS) && (! gpState->fConnected)) {
iRes = ERROR_SERVICE_NOT_ACTIVE;
IFDBG(DebugOut (DEBUG_WARN, L"[SHELL] GetHandleForBA : %04x%08x (rare event!) disconnected while in ioctl\n", pba->NAP, pba->SAP));
}
return iRes;
}
static int LockL2CAPConnection
(
BD_ADDR *pba,
int fLock
) {
// First, get the connection handle
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"LockL2CAPConnection : %04x%08x : %s l2cap connection\n", pba->NAP, pba->SAP, fLock ? L"locking" : L"unlocking"));
HANDLE hL2CAP = gpState->hL2CAP;
BT_LAYER_IO_CONTROL pCallbackIOCTL = gpState->l2cap_if.l2ca_ioctl;
gpState->AddRef ();
gpState->Unlock ();
int iRes = ERROR_INTERNAL_ERROR;
__try {
int dwData = 0;
iRes = pCallbackIOCTL (hL2CAP, fLock ? BTH_L2CAP_IOCTL_LOCK_BASEBAND : BTH_L2CAP_IOCTL_UNLOCK_BASEBAND, sizeof(*pba), (char *)pba, 0, NULL, &dwData);
if ((iRes == ERROR_SUCCESS) && (dwData != 0)) {
IFDBG(DebugOut (DEBUG_ERROR, L"[SHELL] GetHandleForBA : %04x%08x : incorrect return buffer in l2cap_ioctl\n", pba->NAP, pba->SAP));
iRes = ERROR_INTERNAL_ERROR;
}
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[SHELL] GetHandleForBA : %04x%08x : exception in l2cap_ioctl\n", pba->NAP, pba->SAP));
}
gpState->Lock ();
gpState->DelRef ();
if ((iRes == ERROR_SUCCESS) && (! gpState->fConnected)) {
iRes = ERROR_SERVICE_NOT_ACTIVE;
IFDBG(DebugOut (DEBUG_WARN, L"[SHELL] GetHandleForBA : %04x%08x (rare event!) disconnected while in ioctl\n", pba->NAP, pba->SAP));
}
return iRes == ERROR_SUCCESS ? TRUE : FALSE;
}
static int WaitForCommandCompletion (HANDLE hEvent, BD_ADDR *pba, unsigned short h) {
for ( ; ; ) {
int iRes = WaitForSingleObject (hEvent, COMMAND_PERIODIC_TIMEOUT);
if (iRes == WAIT_OBJECT_0)
return ERROR_SUCCESS;
if (iRes == WAIT_TIMEOUT) {
unsigned short h2 = 0;
gpState->Lock ();
iRes = GetHandleForBA (pba, &h2);
gpState->Unlock ();
if (iRes != ERROR_SUCCESS)
return iRes;
if (h2 != h)
return ERROR_CONNECTION_INVALID;
continue;
}
return ERROR_OPERATION_ABORTED;
}
}
static BOOL RouteSCOControl (void) {
BOOL fSCOControl = TRUE;
HKEY hk;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Bluetooth\\AudioGateway", 0, 0, &hk)) {
DWORD dwData;
DWORD cbAudioRoute = sizeof(DWORD);
if ((ERROR_SUCCESS == RegQueryValueEx(hk, _T("MapAudioToPcmMode"), 0, NULL, (PBYTE)&dwData, &cbAudioRoute)) && (0 == dwData)) {
fSCOControl = FALSE;
}
}
return fSCOControl;
}
//
// Callbacks
//
static int btshell_CallAborted (void *pCallContext, int iError) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: SCall aborted for call 0x%08x error %d\n", pCallContext, iError));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
SCall *pCall = VerifyCall ((SCall *)pCallContext);
if (! pCall) {
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
pCall->fComplete = TRUE;
pCall->iResult = iError;
SetEvent (pCall->hEvent);
gpState->Unlock ();
return ERROR_SUCCESS;
}
static int btshell_LocalNameDone (void *pCallContext, unsigned char status) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: local name done status %d\n", pCallContext, status));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
SCall *pCall = VerifyCall ((SCall *)pCallContext);
if (! pCall) {
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
pCall->fComplete = TRUE;
pCall->iResult = StatusToError (status, ERROR_INTERNAL_ERROR);
SetEvent (pCall->hEvent);
gpState->Unlock ();
return ERROR_SUCCESS;
}
static int btshell_Inquiry_Out (void *pCallContext, unsigned char status) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: Inquiry out status %d\n", status));
if (status != 0)
return btshell_CallAborted (pCallContext, StatusToError (status, ERROR_INTERNAL_ERROR));
return ERROR_SUCCESS;
}
static int btshell_BDADDR_Out (void *pCallContext, unsigned char status, BD_ADDR *pba) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: BD READ out status %d, address %04x%08x\n", status, pba->NAP, pba->SAP));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -