📄 obex.cpp
字号:
hr = g_pObex->_pDevices->FindDevicesThatMatch (pBag, &pMatchedDeviceList);
if(FAILED(hr))
{
ReleaseLock();
pBag->Release();
pBag = NULL;
pPropBagEnum->Release();
goto done;
}
//
// If there are no devices, this is a new one, so insert it
//
if(NULL == pMatchedDeviceList)
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumIndividualDevicesThread - New device found!\n"));
//create a new device with our clsid and propertybag
// NOTE: creating the device effectivly calles SetModified
CObexDevice *pObexDevice = new CObexDevice(pBag, clsid);
if (!pObexDevice)
{
ReleaseLock();
pBag->Release();
pBag = NULL;
pPropBagEnum->Release();
goto done;
}
//insert it into the device list
hr = g_pObex->_pDevices->Insert(pObexDevice);
//if all went okay, notify any connection points
if ((g_dwObexCaps & SEND_DEVICE_UPDATES) && SUCCEEDED(hr))
{
if (!g_pObex->_bStopEnum)
g_pObex->_pConnPt->Notify(OE_DEVICE_ARRIVAL, pBag, NULL);
}
pObexDevice->Release();
pObexDevice = NULL;
}
//
// Otherwise, there are multiple devices, so update them individually
//
else
{
if(FAILED(g_pObex->UpdateDevices(pTransport, &clsid, pMatchedDeviceList)))
{
ReleaseLock();
pBag->Release();
pBag = NULL;
pPropBagEnum->Release();
goto done;
}
}//must leave this if locked!
SVSUTIL_ASSERT(gpSynch->IsLocked());
ulFetched = 0;
ReleaseLock();
pBag->Release();
pBag = NULL;
}
SVSUTIL_ASSERT(!pBag);
//end of while
pPropBagEnum->Release();
pPropBagEnum = NULL;
}
else
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumDevicesThread - EnumDevices failed for transport %s...()\n", var.bstrVal));
goto done;
}
SVSUTIL_ASSERT(!pPropBagEnum);
if (!GetLock())
goto done;
//finish the enumeration run by building a list of all devices
// that have been removed (as determined by the Present flag)
DEVICE_PROPBAG_LIST *pDevicesToRemove = NULL;
hr = g_pObex->_pDevices->FinishEnumRun(&pDevicesToRemove, clsid);
//now, iterate throuh the removed devices notifying the connection
// point of their departure.
if (SUCCEEDED(hr) && pDevicesToRemove)
{
SVSUTIL_ASSERT(gpSynch->IsLocked());
//loop through all devices to be removed and notify the connectionpts
while(pDevicesToRemove)
{
SVSUTIL_ASSERT(pDevicesToRemove->pBag);
g_pObex->_pConnPt->Notify(OE_DEVICE_DEPARTURE, pDevicesToRemove->pBag, NULL);
//if an error occured, mark the device as a corpse in its bag
VARIANT varCorpse;
VariantInit(&varCorpse);
hr = pDevicesToRemove->pBag->Read(L"Corpse", &varCorpse, NULL);
//if the device isnt a corpse, delete it & move on
if(FAILED(hr) || VT_I4 != varCorpse.vt || 1 != varCorpse.lVal)
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumDevicesThread - found device to remove (it walked off)... but not corpse\n"));
DEVICE_PROPBAG_LIST *pDel = pDevicesToRemove;
pDevicesToRemove->pBag->Release();
pDevicesToRemove = pDevicesToRemove->pNext;
delete pDel;
}
else
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumDevicesThread - found device to remove (its a corpse)\n"));
DEVICE_PROPBAG_LIST *pPBTemp = pDevicesToRemove->pNext;
pDevicesToRemove->pNext = pDeviceCorpses;
pDeviceCorpses = pDevicesToRemove;
pDevicesToRemove = pPBTemp;
}
VariantClear(&varCorpse);
}
}
ReleaseLock();
}
done:
SVSUTIL_ASSERT(!gpSynch->IsLocked());
//
// Clean our corpse list (devices that dont support obex but still get discovered
// but the transport enumerator)
//
while(pDeviceCorpses)
{
DEVICE_PROPBAG_LIST *pDel = pDeviceCorpses;
pDeviceCorpses = pDeviceCorpses->pNext;
pDel->pBag->Release();
delete pDel;
}
// remove this transport from the active list (there is no recovery for error)
g_pObex->RemoveActiveTransport(pTransport);
if (pPropBag)
pPropBag->Release();
if (pTransport)
pTransport->Release();
SVSUTIL_ASSERT(g_pObex && !pBag);
//
// Because we are leaving the thread, the # of running threads
// must be decremented--- and because this has to be dec'ed
// we must call PauseEnumIfRequired
gpSynch->Lock();
//decrement the # of threads running
g_pObex->_uiRunningENumThreadCnt --;
gpSynch->Unlock();
g_pObex->PauseEnumIfRequired();
//close up shop
if(g_pObex)
g_pObex->Release();
CoUninitialize();
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumDevicesThread - FINISHED -- going away\n"));
return 0;
}
DWORD
//note: we are already under gpSynch->Lock()!
CObex::StartEnumeratingDevices()
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumDevices()\n"));
LPPROPERTYBAGENUM pTransportEnum = NULL;
LPPROPERTYBAG2 pPropBag = NULL;
HKEY hk;
HRESULT hr = E_FAIL;
ULONG ulFetched;
if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"software\\microsoft\\obex", 0, KEY_READ, &hk))
{
DWORD dw = 0;
DWORD dwType = REG_DWORD;
DWORD dwSize = sizeof(dw);
if (ERROR_SUCCESS == RegQueryValueEx (hk, L"clientcredits", NULL, &dwType, (LPBYTE)&dw, &dwSize))
{
if ((dwType == REG_DWORD) && (dwSize == sizeof(dw)) && (dw > 0) && (((int)dw) > 0))
g_iCredits = (int)dw;
}
RegCloseKey (hk);
}
if ((!g_pObex) || (!g_pObex->IsInitialized()))
goto done;
//get a property bag of transports
hr = g_pObex->EnumTransports(&pTransportEnum);
if((FAILED(hr)) || (0 == pTransportEnum))
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumDevicesThread - EnumTransports failed(err=0x%08x)()\n", hr));
goto done;
}
//build a linked list of thread handles (and then copy them into an array)
pTransportEnum->Reset();
gpSynch->Lock();
_uiEnumThreadCnt = 0;
while((SUCCEEDED(pTransportEnum->Next(1, &pPropBag, &ulFetched)) && ulFetched))
{ //note: we are passing off ownership of the pPropBag!!!!!
SVSUTIL_ASSERT(g_pObex);
g_pObex->AddRef();
_hEnumThreadArray[_uiEnumThreadCnt] = CreateThread(NULL, 0, EnumIndividualDeviceThread, (void *)pPropBag, 0, 0);
_uiEnumThreadCnt++;
_uiRunningENumThreadCnt++;
}
gpSynch->Unlock();
done:
if (pTransportEnum)
pTransportEnum->Release();
SVSUTIL_ASSERT(gpSynch);
return 0;
}
HRESULT STDMETHODCALLTYPE
CObex::PauseDeviceEnum(BOOL fPauseOn)
{
HRESULT hr = S_OK;
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::PauseDeviceEnum()\n"));
if(fPauseOn) {
BOOL fBlock = FALSE;
UINT uiPreviousThreadCnt;
gpSynch->Lock();
uiPreviousThreadCnt = _uiRunningENumThreadCnt;
if(FALSE == this->_fPause) {
ResetEvent(_hEnumPauseEvent);
this->_fPause = TRUE;
AbortActiveTransports(TRUE);
if(0 != _uiRunningENumThreadCnt) //dont block if no threads are running!
fBlock = TRUE;
}
gpSynch->Unlock();
if(fBlock) {
if(WAIT_OBJECT_0 != WaitForSingleObject(_hEnumPauseEvent_UnlockPauseFunction, INFINITE))
{
hr = E_FAIL;
}
gpSynch->Lock();
_uiRunningENumThreadCnt = uiPreviousThreadCnt;
gpSynch->Unlock();
}
}
else {
gpSynch->Lock();
this->_fPause = FALSE;
gpSynch->Unlock();
SetEvent(_hEnumPauseEvent);
}
gpSynch->Lock();
AbortActiveTransports(FALSE);
gpSynch->Unlock();
return hr;
}
HRESULT STDMETHODCALLTYPE
CObex::StartDeviceEnum()
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::StartDeviceEnum()\n"));
gpSynch->Lock();
if (_stage != Initialized)
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::StartDeviceEnum - Not yet initialized...()\n"));
gpSynch->Unlock();
return OBEX_E_NOT_INITIALIZED;
}
while (_bStopEnum)
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::StartDeviceEnum - In the process of stopping previous enumeration...()\n"));
SVSUTIL_ASSERT(_uiEnumThreadCnt);
//wait for all threads to exit
gpSynch->Unlock();
//
//wait for all threads to exit (they get the _bStopEnum flag and quit)
//
for(UINT i=0; i<_uiEnumThreadCnt; i++)
{
DWORD waitRet = WaitForSingleObject(_hEnumThreadArray[i], INFINITE);
CloseHandle(_hEnumThreadArray[i]);
SVSUTIL_ASSERT(WAIT_FAILED != waitRet);
if(WAIT_FAILED == waitRet)
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::WaitForMultipleObject on thread failed: %x\n", GetLastError()));
return E_FAIL;
}
else
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::WaitForMultipleObject thread %d down\n", i));
}
}
gpSynch->Lock();
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::StartDeviceEnum - Previous enumeration stopped()\n"));
if (_stage != Initialized)
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::StartDeviceEnum - Device shutdown in the meanwhile...()\n"));
gpSynch->Unlock();
return E_FAIL;
}
}
if (_uiEnumThreadCnt)
{
//inc the device ref count to the thread (to prevent removing it later)
_uiDeviceEnumCnt ++;
gpSynch->Unlock();
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::StartDeviceEnum - Enum already running...()\n"));
return S_OK;
}
SVSUTIL_ASSERT(_uiEnumThreadCnt == 0);
if (_pDevices)
{
_pDevices->Release();
_pDevices = NULL;
}
_pDevices = new CDeviceEnum();
if (!_pDevices)
{
gpSynch->Unlock();
return E_OUTOFMEMORY;
}
_pDevices->Reset();
//make sure we are not paused
PauseDeviceEnum(FALSE);
//crank up the device enumeration threads
StartEnumeratingDevices();
//inc the ref count to the thread (to prevent removing it later)
_uiDeviceEnumCnt ++;
gpSynch->Unlock();
return S_OK;
}
HRESULT STDMETHODCALLTYPE
CObex::StopDeviceEnum()
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::StopDeviceEnum()\n"));
gpSynch->Lock();
if (_stage != Initialized || !_uiDeviceEnumCnt)
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::StopDeviceEnum - Not yet initialized...()\n"));
gpSynch->Unlock();
return OBEX_E_NOT_INITIALIZED;
}
//dec the ref count
if(_uiDeviceEnumCnt)
_uiDeviceEnumCnt--;
if (_bStopEnum || !_uiEnumThreadCnt || _uiDeviceEnumCnt)
{
gpSynch->Unlock();
return S_OK;
}
//set the stop enum flag
_bStopEnum = TRUE;
gpSynch->Unlock();
//make sure we are not paused
PauseDeviceEnum(FALSE);
//abort any active connections
gpSynch->Lock();
AbortActiveTransports(TRUE);
gpSynch->Unlock();
//
//wait for all threads to exit (they get the _bStopEnum flag and quit)
//
for(UINT i=0; i<_uiEnumThreadCnt; i++)
{
DWORD waitRet = WaitForSingleObject(_hEnumThreadArray[i], INFINITE);
CloseHandle(_hEnumThreadArray[i]);
SVSUTIL_ASSERT(WAIT_FAILED != waitRet);
if(WAIT_FAILED == waitRet)
{
DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::WaitForMultipleObject on thread failed: %x\n", GetLastError()));
return E_FAIL;
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -