⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 obex.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:

        pTemp = pTemp->pNext;
    }

    VariantClear(&varDev1Address);
    *isCorpse = bHasBeenCorpsed;
    return S_OK;
}



HRESULT 
CObex::UpdateDevices(IObexTransport *pTransport, CLSID *pclsid, DEVICE_LIST *pMatchedDeviceList)
{
    CObexDevice *pObexDevice = NULL;
    HRESULT hRes = S_OK;
    
    while(pMatchedDeviceList)
    {                            
        SVSUTIL_ASSERT(gpSynch->IsLocked());                        
        
        DEVICE_LIST *pDel = pMatchedDeviceList;
        pObexDevice = pMatchedDeviceList->pDevice;
        pMatchedDeviceList = pMatchedDeviceList->pNext;
        delete pDel;
        
        PREFAST_ASSERT(pObexDevice);

        //because we are here, this device still exists
        pObexDevice->SetPresent(TRUE);

        IPropertyBag *pDeviceBag = pObexDevice->GetPropertyBag();
            
        VARIANT varCorpse;
        VariantInit(&varCorpse);
        BOOL fIsCorpse = FALSE;
        
        if(SUCCEEDED(pDeviceBag->Read(L"Corpse", &varCorpse, NULL)))
        {
            if(varCorpse.lVal == 1)
                fIsCorpse = TRUE;
            VariantClear(&varCorpse);
        }
        
        // finish updating the device 
        //  (but only if it needs updating...)
        if(!fIsCorpse && 0xFFFFFFFF != pObexDevice->GetUpdateStatus())
        {        
            DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumIndividualDevicesThread - finishing update \n"));

            HRESULT hr;            
            SVSUTIL_ASSERT(pDeviceBag);
        
            //go update the devices properties.. this will go out
            //  and preform the (possible) time consuming chore
            //  of figuring out if OBEX is supported on the device
            //  as well as build the human name
                        

            IPropertyBagEnum *pNewBagEnum = NULL;                
             
            UINT uiUpdateStatus;
            UINT uiPrevStatus = pObexDevice->GetUpdateStatus();
            BOOL fAborted = FALSE;
            
            ReleaseLock();
            hr = pTransport->UpdateDeviceProperties(pDeviceBag, &pNewBagEnum, FALSE, &uiUpdateStatus);

            if (! GetLock ())
            {    
                hRes = E_FAIL;
                pObexDevice->Release();
                goto done;
            }            
                          
            //if we succeeded, progress has been made (or could have been)
            //  so notify the client and possibly SetModified
            if(SUCCEEDED(hr))
            {
                if(S_OK != hr)
                    pObexDevice->SetUpdateStatus(uiUpdateStatus);
                else
                    pObexDevice->SetUpdateStatus(0xFFFFFFFF);
				
                //special case this to maintain bkwrds compat with ppc2002
                if(!(g_dwObexCaps & SEND_DEVICE_UPDATES))
				{
					if(uiUpdateStatus != uiPrevStatus && (S_OK == hr))
					{    
						DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumIndividualDevicesThread - sending update message - status (before/after) = (0x%x/0x%x)\n", uiUpdateStatus, uiPrevStatus));
						
						pObexDevice->SetModified(TRUE);    
						
						if (!g_pObex->_bStopEnum)        
							g_pObex->_pConnPt->Notify(OE_DEVICE_ARRIVAL, pDeviceBag, NULL);
					}
					else if(uiUpdateStatus != uiPrevStatus && S_OK == hr)
					{
						pObexDevice->SetModified(TRUE);    
					}   
					else
					{
						pObexDevice->SetModified(FALSE);
					}
				}	
				else 
				{
					if(uiUpdateStatus != uiPrevStatus)
					{    
						DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumIndividualDevicesThread - sending update message - status (before/after) = (0x%x/0x%x)\n", uiUpdateStatus, uiPrevStatus));
						
						pObexDevice->SetModified(TRUE);    
						
						if (!g_pObex->_bStopEnum)        
							g_pObex->_pConnPt->Notify(OE_DEVICE_UPDATE, pDeviceBag, NULL);
					}
					else
					{
						pObexDevice->SetModified(FALSE);
					}
				}                
                
            }


            //if we have failed, or if we havent been modified in a while
            //  corpse the device
            if(E_ABORT != hr && (FAILED(hr) || (!(uiUpdateStatus & CAN_CONNECT) && !pObexDevice->GetModified())))
            {
                DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumIndividualDevicesThread - device doesnt support OBEX -- making it a corpse\n"));
                
                //if an error occured, mark the device as a corpse in its bag
                VARIANT varCorpseWrite;
                VariantInit(&varCorpseWrite);                                
                varCorpseWrite.vt = VT_I4;
                varCorpseWrite.lVal = 1;

                hr = pDeviceBag->Write(L"Corpse", &varCorpseWrite);
                   SVSUTIL_ASSERT(SUCCEEDED(hr));
                VariantClear(&varCorpseWrite);

                pObexDevice->Release();
                pObexDevice=NULL;
                break;
            }
            
            
                
            //
            //  If devices were discovered while updating a previous device
            //      they will be cloned and will have information. 
            //        so place them into the list of devices and send
            //        a NOTIFY to any Sink
            //
            if(pNewBagEnum)
            {
                pNewBagEnum->Reset();

                ULONG ulFetched = 0;
                LPPROPERTYBAG2 pNewDeviceBag = NULL;
                
                while(SUCCEEDED(pNewBagEnum->Next(1, &pNewDeviceBag, &ulFetched)) && ulFetched)
                {
                    DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumIndividualDevicesThread - New device found during Update of prev found device!!\n"));
                
                    //create a new device with our clsid and propertybag (this marks it
                    //  updated and present)        
                    CObexDevice *pNewDevice = new CObexDevice(pNewDeviceBag, *pclsid);
                    if (!pNewDevice)
                    {
                        pNewBagEnum->Release();        
                        pObexDevice->Release();    
                        hRes = E_FAIL;
                        goto done;
                    }

                    //insert it into the device list 
                    hr = g_pObex->_pDevices->Insert(pNewDevice);                    
                    SVSUTIL_ASSERT(SUCCEEDED(hr));
					
                    //if all went okay, notify any connection points
					//  <-- dont send arrival here on PPC2002                    
                    if ((g_dwObexCaps & SEND_DEVICE_UPDATES) && SUCCEEDED(hr))
                    {    
                        if (!g_pObex->_bStopEnum)    
                            g_pObex->_pConnPt->Notify(OE_DEVICE_ARRIVAL, pNewDeviceBag, NULL);
                    }
					
                    pNewDeviceBag->Release();
                    pNewDevice->Release();    
                    pNewDevice = NULL;     
                }
                
                pNewBagEnum->Release();
                pNewBagEnum = NULL;
            }
        }
        else if(!fIsCorpse)
        {
            SVSUTIL_ASSERT(pObexDevice);
            pObexDevice->SetModified(TRUE);    
        }
        
        pObexDevice->Release();
        pObexDevice=NULL;
    }


done:

    // safety net -- clean up memory (only will happen on bad error)
    while(pMatchedDeviceList)
    {
        DEVICE_LIST *pDel = pMatchedDeviceList;
        pMatchedDeviceList->pDevice->Release();
        pMatchedDeviceList = pMatchedDeviceList->pNext;
        delete pDel;
    }

    return hRes;
}

HRESULT
CObex::PauseEnumIfRequired()
{
        HRESULT hr = E_FAIL;
        SVSUTIL_ASSERT(!gpSynch->IsLocked());  
        //
        // Handle pausing 
        //    this is done by first getting the lock, then if we were
        //    told to pause, we decrement the pause thread count (the number
        //    of instances of EnumIndividualDeviceThread running) and then
        //    if 0 we wake up the initiating Pause() function -- then
        //    we wait for a pauseEvent 
        if (!GetLock())
            goto Done;   
            
            if(TRUE == g_pObex->_fPause) {
                g_pObex->_uiRunningENumThreadCnt --; 
                if(0==g_pObex->_uiRunningENumThreadCnt) 
                    SetEvent(g_pObex->_hEnumPauseEvent_UnlockPauseFunction);                
            }   
        ReleaseLock();
        
        //note: this is a manual reset event!!
        if(WAIT_FAILED == WaitForSingleObject(g_pObex->_hEnumPauseEvent, INFINITE)) {
            ASSERT(FALSE);
            goto Done;
        }  
        
        hr = S_OK;
        Done:        
            return hr;
}


//
//  Note: because we monitor the number of instances of this 
//     thread that are running (via _uiRunningEnumThreadCnt)
//     on *EVERY* exit (return) we have to first decrement 
//     the _uiRunninEnumThreadCnt (while under the main lock -- this is important)
//     THEN once we have left that lock we MUST call PauseEnumIfRequired
//     so that we wont race
//
DWORD WINAPI
CObex::EnumIndividualDeviceThread(LPVOID lpvParam)
{        
    PREFAST_ASSERT(g_pObex);
    
    IObexTransport *pTransport = NULL;
    
    ULONG ulFetched = 0;
    
    HRESULT hr = E_FAIL;
    CLSID clsid;
    VARIANT var;
    BOOL bOK;

    LPPROPERTYBAG2 pBag = NULL;
    DEVICE_PROPBAG_LIST *pDeviceCorpses = NULL;
    IObexAbortTransportEnumeration *pAbortEnum = NULL;
        
    //we are GIVEN the propery bag for the device, DO NOT ref count it!
    LPPROPERTYBAG2 pPropBag = (LPPROPERTYBAG2) lpvParam;
    PREFAST_ASSERT(pPropBag);

    //init the COM library
    if (FAILED(CoInitializeEx(NULL,COINIT_MULTITHREADED)))
    {
        DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumDevicesThread - CANT CoInitializeEx\n"));
        g_pObex->Release();
        
        //
        //  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
        if (!GetLock())
                goto done;
            //decrement the # of threads running    
            g_pObex->_uiRunningENumThreadCnt --;    
        ReleaseLock();  
        g_pObex->PauseEnumIfRequired();   
        return E_FAIL;
    }

    
     //fetch the GUID from the prop bag, if it doesnt exist, quit
    VariantInit(&var);
    
    bOK = ( (SUCCEEDED(pPropBag->Read(L"GUID", &var, 0))) && (SUCCEEDED(CLSIDFromString(var.bstrVal, &clsid))) );
    if (!bOK)
        goto done;    
      
    VariantClear(&var);    

    //get a  transport (for seeing what devices are up)
    hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IObexTransport,  
        (void **)&pTransport);
             
    if ( (FAILED(hr)) || (!pTransport) )
    {
        pTransport = NULL;
        goto done;
    }
    
    // make sure the transport is not in the abort state
    if(SUCCEEDED(pTransport->QueryInterface(IID_IObexAbortTransportEnumeration, (LPVOID *)&pAbortEnum))) {
         pAbortEnum->Resume();
         pAbortEnum->Release();    
    }  
    
              
    if(FAILED(g_pObex->AddActiveTransport(pTransport))) {
        DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumIndividualDevicesThread - Cant add active transport to list! -- can continue w/o this but enumeration stopping may be slow\n"));
    }
    
    for(;;)
    {   
        SVSUTIL_ASSERT(pTransport && g_pObex && g_pObex->_pDevices);
                
        // pause enumeration if required
        if(FAILED(g_pObex->PauseEnumIfRequired())) 
            goto done;
         
        //if we are told to stop... do so
        if (!GetLock())
            goto done;   
        if (g_pObex->_bStopEnum)
        {
            ReleaseLock();
            goto done;
        }

        //start an enumeration run for all devices that are of the 
        //  transport from 'clsid'... this mean the SetPresent flag is
        //  set false -- thus the credits go down by 1.  if they go to
        //  0 the device is deleted (well, marked as a corpse)
        g_pObex->_pDevices->StartEnumRun(clsid);

        ReleaseLock();

        //
        //get all the devices on a particular transport (pTransport)
        //
        LPPROPERTYBAGENUM pPropBagEnum = NULL;
        if( (SUCCEEDED(pTransport->EnumDevices(&pPropBagEnum))) && (pPropBagEnum))
        {    
            //
            //  quick check to see if we've been stopped.
            //
            if (g_pObex->_bStopEnum)
            {
                pPropBagEnum->Release();
                goto done;    
            }

            //look through each discoverd device, creating devices and inserting them into the 
            //  device enumerator
            ulFetched = 0;
            pPropBagEnum->Reset();

            //
            //  Loop through all devices discovered, find devices that might match
            //    (-- if they share addresses) and then figure out if multiple 'devices'
            //      live under that one device (1 BT device + multiple SDP records)            
            while(SUCCEEDED(pPropBagEnum->Next(1, &pBag, &ulFetched) ) && ulFetched == 1)
            {            
                if (! GetLock ())
                {            
                    pBag->Release();
                    pBag = NULL;
                    pPropBagEnum->Release();
                    goto done;
                }

                //quick check to see if we've been stopped.
                if (g_pObex->_bStopEnum)
                {
                    pBag->Release();
                    pBag = NULL;
                    pPropBagEnum->Release();
                    ReleaseLock();
                    goto done;
                }


                //
                //  Check to see if this device has been found to be a corpse
                //     if it has,  skip it
                //                
                BOOL fIsCorpse = FALSE;
                if(FAILED(g_pObex->IsCorpse(pDeviceCorpses,pBag,&fIsCorpse)))
                {
                    ReleaseLock();    
                    pBag->Release();                    
                    pBag = NULL;
                    pPropBagEnum->Release();
                    goto done;
                }
                else if(fIsCorpse)
                {
                    SVSUTIL_ASSERT(gpSynch->IsLocked());                
                    ulFetched = 0;
                    ReleaseLock();                        
                    pBag->Release();
                    pBag = NULL;
                    continue;
                }

                //
                //   Hunt out the obex device with the passed in property bag
                //      if it exists, set its present flag
                DEVICE_LIST *pMatchedDeviceList = NULL;    
                

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -