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

📄 obex.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//
// Obex.cpp: implementation of the CObex class.
//
//////////////////////////////////////////////////////////////////////
#include "common.h"
#include "ObexDevice.h"
#include "CObex.h"
#include "DeviceEnum.h"
#include "conpoint.h"
#include "ObexIRDATransport.h"
#include "ObexBTHTransport.h"
#include "PropertyBag.h"
#include "PropertyBagEnum.h"
#include "HeaderEnum.h"
#include "HeaderCollection.h"
#include "ObexTCPTransport.h"
#include "ObexTransportConnection.h"
#include "ObexStream.h"
#include <olectl.h>


#include "ObexStrings.h"

extern UINT g_uiIRDAMaxRetries;

#if defined(DEBUG) || defined(_DEBUG)

    DWORD dwData = 'OBEX'; 

    void *operator new(UINT size)
    {
         return g_funcAlloc(size, &dwData);
    }

    void operator delete(void *pVoid)
    {
        if (pVoid)
            g_funcFree(pVoid, &dwData);
    }
#endif


/*----------globals----------------*/

    //g_TransportSocketCS locks the internal structures of the 
    //  transport socket (for example the linked list of 
    //  transport connections)
    CRITICAL_SECTION g_TransportSocketCS;
    CRITICAL_SECTION g_PropBagCS;
    

CSynch             *gpSynch = NULL;
CObex              *g_pObex = NULL;
DWORD		        g_dwObexCaps = 0;
UINT                g_uiMaxFileChunk;

int                 g_iCredits = OBEX_INQUIRY_FAILURES;

const LPCTSTR k_szRegTransportKey         = TEXT("Software\\Microsoft\\Obex\\Transports");
const LPCTSTR k_szRegObex  		    = TEXT("Software\\Microsoft\\Obex");

	
BOOL setKeyAndValue(const WCHAR * pszPath, const WCHAR * szSubkey, const WCHAR * szValue);
BOOL setValueInKey(const WCHAR * szKey, const WCHAR * szNamedValue, const WCHAR * szValue);
HRESULT CLSIDtochar(REFCLSID clsid, WCHAR * szCLSID, unsigned int length);
LONG recursiveDeleteKey(HKEY hKeyParent, const WCHAR * szKeyChild);

HRESULT RegisterServer(const WCHAR * szModuleName,      // DLL module handle
                       REFCLSID clsid,                  // Class ID
                       const WCHAR * szFriendlyName,    // Friendly Name
                       const WCHAR * szVerIndProgID,    // Programmatic
                       const WCHAR * szProgID,          // IDs
                       const WCHAR * szThreadingModel); // ThreadingModel

LONG UnregisterServer(REFCLSID clsid,                  // Class ID
                      const WCHAR * szVerIndProgID,    // Programmatic
                      const WCHAR * szProgID);         // IDs

const int CLSID_STRING_SIZE = 39;


static CObexIRDATransport *g_pIRDATransport = 0;
static CObexBTHTransport  *g_pBTHTransport = 0;

long g_cComponents = 0;
long g_cServerLocks = 0;



BOOL GetLock()
{
    PREFAST_ASSERT(gpSynch);

    SVSUTIL_ASSERT(!gpSynch->IsLocked());
    gpSynch->Lock();
    if ((!g_pObex) || (!g_pObex->IsInitialized()))
    {
        DEBUGMSG(OBEX_COBEX_ZONE,(L"GetLock::No valid IObex interface\n"));
        gpSynch->Unlock();
        return FALSE;
    }

    return TRUE;
}    

void ReleaseLock()
{
    SVSUTIL_ASSERT(gpSynch);
    SVSUTIL_ASSERT(gpSynch->IsLocked());
    gpSynch->Unlock();
}


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CObex::CObex() : _refCount(1)
{
    DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::CObex()\n"));
    InterlockedIncrement (&g_cComponents);
    _bStopEnum = FALSE;
    _pDevices = NULL;    
    _pConnPt = NULL;
    _stage = Stopped;
    _fPause = FALSE;
    _pActiveTransports = NULL;

    //enumeration thead 
    _uiRunningENumThreadCnt = 0; //<-- num of STILL running enum threads
    _uiEnumThreadCnt = 0;        //<--total enum threads (some might have exited)
    _hEnumPauseEvent = NULL;
    _hEnumPauseEvent_UnlockPauseFunction = NULL;

    //number of times enumeration has been requested
    _uiDeviceEnumCnt = 0;

    //number of times we've been inited
    _uiInitCnt = 0;
}

CObex::~CObex()
{
    SVSUTIL_ASSERT(_refCount == 0);
    DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::~CObex()\n"));

    PREFAST_ASSERT(gpSynch);
    SVSUTIL_ASSERT(NULL == _pActiveTransports);
    
    gpSynch->Lock();
    
    if (g_pBTHTransport)
    {
        g_pBTHTransport->Release();
        g_pBTHTransport = NULL;
    }

    if (g_pIRDATransport)
    {
        g_pIRDATransport->Release();
        g_pIRDATransport = NULL;
    }
    
    if (_pDevices)
    {
        _pDevices->Release();
        _pDevices = NULL;
    }    
    
    g_pObex = NULL;
    
       
    gpSynch->Unlock();

    InterlockedDecrement (&g_cComponents);
}


HRESULT STDMETHODCALLTYPE
CObex::SetCaps(DWORD dwCaps)
{
       g_dwObexCaps = dwCaps;
	return S_OK;
}


HRESULT STDMETHODCALLTYPE 
CObex::Initialize()
{
    DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::Initialize()\n"));
    HRESULT hr = E_FAIL;    
    SVSUTIL_ASSERT(!gpSynch->IsLocked());
    gpSynch->Lock();
    
    if (_stage == ShuttingDown)
    {
        DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::Initialize FAILS....ShuttingDown()\n"));
        return E_FAIL; //<--dont goto Done since that will clean up memory!
    }
        
    if (_stage == Initialized)
    {
        DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::Initialize....Already Initialized\n"));

        //inc the initialization ref count 
        _uiInitCnt++; 
        hr = S_OK;
        goto Done;
    }
    
    // load the # of times to retry IRDA from the registry
    g_uiIRDAMaxRetries = 3;

    HKEY hk;
    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"IRDARetries", NULL, &dwType, (LPBYTE)&dw, &dwSize)) {
            if ((dwType == REG_DWORD) && (dwSize == sizeof(dw)) && (dw > 0) && (((int)dw) > 0)) {
                g_uiIRDAMaxRetries = (UINT)dw;
            }           
        }   
        RegCloseKey (hk);
    } 
   
    ASSERT(NULL == _hEnumPauseEvent);
    if(NULL == (_hEnumPauseEvent = CreateEvent(NULL, TRUE, TRUE, NULL))) {
        hr = E_FAIL;
        goto Done;
    }
    
    ASSERT(NULL == _hEnumPauseEvent_UnlockPauseFunction);
    if(NULL == (_hEnumPauseEvent_UnlockPauseFunction = CreateEvent(NULL, FALSE, FALSE, NULL))) {
        hr = E_FAIL;
        goto Done;
    }
       
    SVSUTIL_ASSERT(_pConnPt == NULL);   
    if (NULL == (_pConnPt = new CConnectionPoint((IConnectionPointContainer *)this)))
    {
        hr = E_OUTOFMEMORY;
        goto Done;
    }
    
    SVSUTIL_ASSERT(_uiEnumThreadCnt ==  NULL);
    SVSUTIL_ASSERT(_bStopEnum == FALSE);

    //inc the initialization ref count, set stage
    _stage = Initialized;
    _uiInitCnt++;      
   
    hr = S_OK;
    Done:
        if(FAILED(hr)) {            
            if(_pConnPt)
                _pConnPt->Release();
            if(_hEnumPauseEvent)
                CloseHandle(_hEnumPauseEvent); 
            if(_hEnumPauseEvent_UnlockPauseFunction)
                CloseHandle(_hEnumPauseEvent_UnlockPauseFunction);
            _pConnPt = NULL;
            _hEnumPauseEvent = NULL;
        }  
        //unlock and return
        SVSUTIL_ASSERT(gpSynch->IsLocked());
        gpSynch->Unlock();
        return hr;
}

HRESULT STDMETHODCALLTYPE 
CObex::Shutdown()
{
    DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::Shutdown()\n"));

	//make sure we are not paused
    PauseDeviceEnum(FALSE);

    gpSynch->Lock();
    
    if (_stage != Initialized)
    {
        DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::Shutdown:ERROR_SERVICE_NOT_ACTIVE()\n"));
        gpSynch->Unlock();
        return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WINDOWS, ERROR_SERVICE_NOT_ACTIVE);
    }

    //dec the increment ref count
    _uiInitCnt --;

    //if we are still referenced, dont delete!  just return OK
    if(_uiInitCnt)
    {
        DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::Shutdown: initilization refcount(%d)\n", _uiInitCnt));
        gpSynch->Unlock();
        return S_OK;
    }

    //if we are no longer referenced, start the shutdown process
    _stage = ShuttingDown;

    if (_uiEnumThreadCnt)
    {
        _bStopEnum = 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
            {
                DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::WaitForMultipleObject thread %d down\n", i));
            }
        }

        
        gpSynch->Lock();

        _uiEnumThreadCnt = 0;    
    }

	//kill the pause event (think of a cattle gate)
    ASSERT(_hEnumPauseEvent);
    if(_hEnumPauseEvent) {
        CloseHandle(_hEnumPauseEvent);
        _hEnumPauseEvent = NULL;        
    } 
    ASSERT(_hEnumPauseEvent_UnlockPauseFunction);
    if(_hEnumPauseEvent_UnlockPauseFunction) {
        CloseHandle(_hEnumPauseEvent_UnlockPauseFunction);
        _hEnumPauseEvent_UnlockPauseFunction = NULL;        
    } 

    PREFAST_ASSERT(_pConnPt);
    
    _pConnPt->ContainerReleased();

    ((IConnectionPoint*)_pConnPt)->Release();
    _pConnPt = NULL;

    if (_pDevices)
    {
        _pDevices->Release();
        _pDevices = NULL;
    }

    
    _stage = Stopped;

    gpSynch->Unlock();
    return S_OK;
}


HRESULT 
CObex::IsCorpse(DEVICE_PROPBAG_LIST *pDeviceCorpses, LPPROPERTYBAG2 pBag, BOOL *isCorpse)
{
    //
    //  See if this device has already been found not to have OBEX
    //
    HRESULT hr;
    DEVICE_PROPBAG_LIST *pTemp = pDeviceCorpses;
    VARIANT varDev1Address;
    VARIANT varDev2Address;

    VariantInit(&varDev1Address);
    VariantInit(&varDev2Address);
    
    hr = pBag->Read(c_szDevicePropAddress, &varDev1Address, NULL);

    if(FAILED(hr))
    {
        return hr;
    }

    BOOL bHasBeenCorpsed = FALSE;
    while(pTemp)
    {
        PREFAST_ASSERT(pTemp->pBag);

        if(FAILED((hr = pTemp->pBag->Read(c_szDevicePropAddress, &varDev2Address, NULL))))                    
        {
            VariantClear(&varDev1Address);
            return hr;
        }


        DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumIndividualDevicesThread -- checking for corpse!\n"));
        if(varDev1Address.vt == varDev2Address.vt && varDev1Address.vt == VT_BSTR)
        {                     
           DEBUGMSG(OBEX_COBEX_ZONE,(L"    Checking: %s to %s\n", varDev1Address.bstrVal, varDev2Address.bstrVal));        
        }
        
        bHasBeenCorpsed =
            ( 
              ((varDev1Address.vt == VT_I4) && (varDev1Address.vt == varDev2Address.vt) && (varDev1Address.lVal == varDev2Address.lVal)) || 
              ((varDev1Address.vt == VT_BSTR) && (varDev1Address.vt == varDev2Address.vt) && (0 == wcscmp(varDev1Address.bstrVal, varDev2Address.bstrVal)))
            );    

        DEBUGMSG(OBEX_COBEX_ZONE,(L"    %s\n", bHasBeenCorpsed ? L"CORPSE" : L"NOT CORPSE"));    
        
    
        VariantClear(&varDev2Address);

        //if a corpse has been found, skip this device
        if(bHasBeenCorpsed)
        {
            DEBUGMSG(OBEX_COBEX_ZONE,(L"CObex::EnumIndividualDevicesThread - Corpse found for device -- skipping!\n"));                
             break;
        }

⌨️ 快捷键说明

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