📄 btd.cxx
字号:
int cHciHeaders = 0;
int cHciTrailers = 0;
int cLinkType = 0;
int cControl = BTH_CONTROL_DEVICEONLY | BTH_CONTROL_ROUTE_SECURITY | BTH_CONTROL_ROUTE_HARDWARE;
if (RouteSCOControl()) {
// If SCO audio routing is supported in hardware, we need
// to get ConnectionRequest messages for SCO connections
cControl |= BTH_CONTROL_ROUTE_BY_LINKTYPE;
cLinkType = BTH_LINK_TYPE_SCO;
}
if (ERROR_SUCCESS != HCI_EstablishDeviceContext (this, cControl, NULL, 0, cLinkType, &hei, &hc, &hci_if, &cHciHeaders, &cHciTrailers, &hHCI))
return;
fIsRunning = TRUE;
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: new BTSHELL successful\n"));
}
~BTSHELL (void) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: delete BTSHELL\n"));
if (hL2CAP)
L2CAP_CloseDeviceContext (hL2CAP);
if (hHCI)
HCI_CloseDeviceContext (hHCI);
if (pfmdCalls)
svsutil_ReleaseFixedNonEmpty (pfmdCalls);
if (pfmdSecurity)
svsutil_ReleaseFixedNonEmpty (pfmdSecurity);
if (pfmdLinks)
svsutil_ReleaseFixedNonEmpty (pfmdLinks);
if (hAddrEvent)
CloseHandle(hAddrEvent);
for (int i = 0 ; i < BTD_EVENT_NUMBER ; ++i)
CloseHandle (hNamedEvents[i]);
}
};
typedef void (*PFN_SYSTEM_TIMER_RESET) (void);
static BTSHELL *gpState = NULL;
static HANDLE ghBthApiEvent = NULL;
static PFN_SYSTEM_TIMER_RESET gfnSystemTimerReset = NULL;
//
// Auxiliary code
//
static PINRequest *GetNewPINRequest (void) {
PINRequest *pResult = gpState->pFree;
if (pResult)
gpState->pFree = pResult->pNext;
return pResult;
}
static void FreeRequest (PINRequest *pPinReq) { // This unlocks...
#if defined (DEBUG) || defined (_DEBUG)
for (int i = 0 ; i < MAX_PENDING_PIN_REQUESTS ; ++i) {
if (pPinReq == &gpState->pin_reqs[i])
break;
}
SVSUTIL_ASSERT (i != MAX_PENDING_PIN_REQUESTS);
PINRequest *p = gpState->pFree;
while (p) {
SVSUTIL_ASSERT (p != pPinReq);
p = p->pNext;
}
p = gpState->pRequested;
while (p) {
SVSUTIL_ASSERT (p != pPinReq);
p = p->pNext;
}
p = gpState->pInService;
while (p) {
SVSUTIL_ASSERT (p != pPinReq);
p = p->pNext;
}
#endif
pPinReq->pNext = gpState->pFree;
gpState->pFree = pPinReq;
if (pPinReq->fConnectionLocked)
LockL2CAPConnection (&pPinReq->ba, FALSE); // This unlocks the state
}
static void CleanUpSecurityUIHandler (void) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: security handler does not exist any more - cleaning up!\n"));
gpState->hSecurityUIEvent = NULL;
gpState->hSecurityUIProc = NULL;
gpState->dwSecurityProcPermissions = 0;
gpState->dwPINRequestStoreTimeout = 0;
gpState->dwPINRequestProcessTimeout = 0;
}
static void FinishTimeout (LPVOID pArg, PINRequest **pChain) {
PINRequest *pParent = NULL;
PINRequest *pThis = *pChain;
while (pThis && pThis != pArg)
pThis = pThis->pNext;
if (! pThis) {
gpState->Unlock ();
return;
}
if (pParent)
pParent->pNext = pThis->pNext;
else
*pChain = pThis->pNext;
BD_ADDR ba = pThis->ba;
HANDLE h = gpState->hHCI;
HCI_PINCodeRequestNegativeReply_In pCallbackNo = gpState->hci_if.hci_PINCodeRequestNegativeReply_In;
FreeRequest (pThis);
gpState->Unlock ();
__try {
pCallbackNo (h, NULL, &ba);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[SHELL] Exception in hci_PINCodeRequest[Negative]Reply\n"));
}
}
static DWORD WINAPI StorePINTimeout (LPVOID pArg) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"StorePINTimeout\n"));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
FinishTimeout (pArg, &gpState->pRequested); // This unlocks
return 0;
}
static DWORD WINAPI ServicePINTimeout (LPVOID pArg) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"ServicePINTimeout\n"));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
FinishTimeout (pArg, &gpState->pInService); // This unlocks
return 0;
}
static int AddNewPINRequest (BD_ADDR *pba) {
if (! gpState->hSecurityUIEvent) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell AddNewPINRequest: security handler not installed!\n"));
return FALSE;
}
DWORD dwPerms = SetProcPermissions (gpState->dwSecurityProcPermissions);
BOOL bRes = SetEvent (gpState->hSecurityUIEvent);
SetProcPermissions (dwPerms);
if (! bRes) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell AddNewPINRequest: security handler failed\n"));
CleanUpSecurityUIHandler ();
return FALSE;
}
PINRequest *pPRE = gpState->pRequested;
while (pPRE) {
if (pPRE->ba == *pba)
break;
pPRE = pPRE->pNext;
}
if (! pPRE) {
pPRE = gpState->pInService;
while (pPRE) {
if (pPRE->ba == *pba)
break;
pPRE = pPRE->pNext;
}
}
if (pPRE) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell AddNewPINRequest: %04x%08x already in process\n", pba->NAP, pba->SAP));
return FALSE;
}
pPRE = GetNewPINRequest ();
if (! pPRE) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell AddNewPINRequest: - no free slots for PIN requests!\n"));
return FALSE;
}
memset (pPRE, 0, sizeof(*pPRE));
pPRE->ba = *pba;
pPRE->pNext = gpState->pRequested;
gpState->pRequested = pPRE;
pPRE->dwTimeOutCookie = btutil_ScheduleEvent (StorePINTimeout, pPRE, gpState->dwPINRequestStoreTimeout);
pPRE->fConnectionLocked = LockL2CAPConnection (pba, TRUE);
return TRUE;
}
static void UnscheduleAllPINReqests (void) {
PINRequest *p = gpState->pRequested;
while (p) {
btutil_UnScheduleEvent (p->dwTimeOutCookie);
p->dwTimeOutCookie = 0;
p = p->pNext;
}
p = gpState->pInService;
while (p) {
btutil_UnScheduleEvent (p->dwTimeOutCookie);
p->dwTimeOutCookie = 0;
p = p->pNext;
}
}
static BTSHELL *CreateNewState (void) {
return new BTSHELL;
}
static InquiryBuffer *CreateNewInquiryBuffer (void) {
return new InquiryBuffer;
}
static SCall *AllocCall (int fWhat) {
SCall *pCall = (SCall *)svsutil_GetFixed (gpState->pfmdCalls);
if (! pCall)
return NULL;
memset (pCall, 0, sizeof(*pCall));
pCall->hProcOwner = GetOwnerProcess ();
pCall->fWhat = fWhat;
pCall->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
if (NULL == pCall->hEvent) {
svsutil_FreeFixed (pCall, gpState->pfmdCalls);
return NULL;
}
pCall->pNext = gpState->pCalls;
gpState->pCalls = pCall;
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: Allocated call 0x%08x what = 0x%02x\n", pCall, fWhat));
return pCall;
}
static void DeleteCall (SCall *pCall) {
if (pCall == gpState->pCalls)
gpState->pCalls = pCall->pNext;
else {
SCall *pParent = gpState->pCalls;
while (pParent && (pParent->pNext != pCall))
pParent = pParent->pNext;
if (! pParent) {
IFDBG(DebugOut (DEBUG_ERROR, L"Shell: call not in list in DeleteCall!\n"));
return;
}
pParent->pNext = pCall->pNext;
}
CloseHandle (pCall->hEvent);
svsutil_FreeFixed (pCall, gpState->pfmdCalls);
}
static SCall *VerifyCall (SCall *pCall) {
SCall *p = gpState->pCalls;
while (p && (p != pCall))
p = p->pNext;
#if defined (DEBUG) || defined (_DEBUG) || defined (RETAILLOG)
if (! p)
IFDBG(DebugOut (DEBUG_ERROR, L"Shell: call verify failed!\n"));
#endif
return p;
}
static SCall *FindCall (unsigned int fOp) {
SCall *p = gpState->pCalls;
while (p && (p->fWhat != fOp))
p = p->pNext;
#if defined (DEBUG) || defined (_DEBUG) || defined (RETAILLOG)
if (! p)
IFDBG(DebugOut (DEBUG_ERROR, L"Shell: call find failed!\n"));
#endif
return p;
}
static DWORD WINAPI StackDisconnect (LPVOID lpVoid) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: DisconnectStack\n"));
btshell_CloseDriverInstance ();
return ERROR_SUCCESS;
}
static DWORD WINAPI StackDown (LPVOID lpVoid) {
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if ((! gpState->fIsRunning) || (! gpState->fConnected)) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
gpState->fConnected = FALSE;
memset (&gpState->b, 0, sizeof(gpState->b));
UnscheduleAllPINReqests ();
gpState->ClearPinRequests ();
SCall *pC = gpState->pCalls;
while (pC) {
if (! pC->fComplete) {
pC->fComplete = TRUE;
pC->iResult = ERROR_CONNECTION_UNAVAIL;
SetEvent (pC->hEvent);
} else {
if (pC->iResult == ERROR_SUCCESS)
pC->iResult = ERROR_CONNECTION_UNAVAIL;
}
pC = pC->pNext;
}
while (gpState->pLinks) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"StackDown : Deleting link 0x%04x\n", gpState->pLinks->h));
Link *pNext = gpState->pLinks->pNext;
svsutil_FreeFixed (gpState->pLinks, gpState->pfmdLinks);
gpState->pLinks = pNext;
}
SetEvent (gpState->hNamedEvents[BTD_EVENT_HARDWARE_CHANGED]);
ResetEvent (gpState->hNamedEvents[BTD_EVENT_HARDWARE_CHANGED]);
gpState->Unlock ();
return ERROR_SUCCESS;
}
static DWORD WINAPI StackUp (LPVOID lpVoid) {
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if ((! gpState->fIsRunning) || gpState->fConnected) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
gpState->fConnected = TRUE;
ResetEvent (gpState->hAddrEvent);
SCall *pCall = AllocCall (CALL_HCI_READ_BD_ADDR);
if (! pCall) {
gpState->Unlock ();
return ERROR_OUTOFMEMORY;
}
pCall->hProcOwner = NULL;
HANDLE hEvent = pCall->hEvent;
HCI_ReadBDADDR_In pCallback = gpState->hci_if.hci_ReadBDADDR_In;
HANDLE hHCI = gpState->hHCI;
gpState->AddRef ();
gpState->Unlock ();
int iRes = ERROR_INTERNAL_ERROR;
__try {
iRes = pCallback (hHCI, pCall);
} __except (1) {
}
if (iRes == ERROR_SUCCESS)
WaitForSingleObject (hEvent, 5000);
gpState->Lock ();
gpState->DelRef ();
SetEvent (gpState->hAddrEvent);
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_CANCELLED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -