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

📄 obexdevice.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// 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.
//
// ObexDevice.cpp: implementation of the CObexDevice class.
//
//////////////////////////////////////////////////////////////////////


//#ERROR -- use fixed memory 
#include "common.h"
#include "ObexDevice.h"
#include "ObexParser.h"
#include "ObexStream.h"
#include "ObexPacketInfo.h"
#include "HeaderEnum.h"
#include "HeaderCollection.h"

#include "ObexStrings.h"
#include <MD5.h>
#include <intsafe.h>


void MD5(void *dest, void *orig, int len)
{
    MD5_CTX context;
    MD5Init(&context);
    MD5Update(&context, (UCHAR *)orig, len);
    MD5Final(&context);
    memcpy(dest, context.digest, 16);
}


#if defined(DEBUG) || defined(_DEBUG)
#define SVSLOG_BPR 8
void DumpBuff (unsigned char *lpBuffer, unsigned int cBuffer) 
{
    WCHAR szLine[5 + 7 + 2 + 4 * SVSLOG_BPR];

    for (int i = 0 ; i < (int)cBuffer ; i += SVSLOG_BPR) {
        int bpr = cBuffer - i;
        if (bpr > SVSLOG_BPR)
            bpr = SVSLOG_BPR;

        wsprintf (szLine, L"%04x ", i);
        WCHAR *p = szLine + wcslen (szLine);

        for (int j = 0 ; j < bpr ; ++j) {
            WCHAR c = (lpBuffer[i + j] >> 4) & 0xf;
            if (c > 9) c += L'a' - 10; else c += L'0';
            *p++ = c;
            c = lpBuffer[i + j] & 0xf;
            if (c > 9) c += L'a' - 10; else c += L'0';
            *p++ = c;
            *p++ = L' ';
        }

        for ( ; j < SVSLOG_BPR ; ++j) {
            *p++ = L' ';
            *p++ = L' ';
            *p++ = L' ';
        }

        *p++ = L' ';
        *p++ = L' ';
        *p++ = L' ';
        *p++ = L'|';
        *p++ = L' ';
        *p++ = L' ';
        *p++ = L' ';

        for (j = 0 ; j < bpr ; ++j) {
            WCHAR c = lpBuffer[i + j];
            if ((c < L' ') || (c >= 127))
                c = L'.';

            *p++ = c;
        }

        for ( ; j < SVSLOG_BPR ; ++j)
            *p++ = L' ';

        *p++ = L'\n';
        *p++ = L'\0';

        SVSUTIL_ASSERT (p == szLine + sizeof(szLine)/sizeof(szLine[0]));
        DEBUGMSG(OBEX_DUMP_PACKETS_ZONE, (L"%s", szLine));
    }
}
#endif

//////////////////////////////////////////////////////////////////////
// Utility section
//////////////////////////////////////////////////////////////////////

static HRESULT MakeResponse (const WCHAR *_pszPassToUse, BYTE *bChallenge, BYTE *bResponse) {
    INT cp = CP_UTF8;

    UCHAR ucPassLen = WideCharToMultiByte(cp, 0, _pszPassToUse, -1, NULL, 0, NULL, NULL);

    if (! ucPassLen)
    {
        cp = CP_ACP;
        ucPassLen = WideCharToMultiByte(cp, 0, _pszPassToUse, -1, NULL, 0, NULL, NULL);
    }

    if (! ucPassLen)
        return E_FAIL;    

    UINT uiEncodeSize = 16 + 1 + ucPassLen;
    BYTE bEncodeBuffer[512];
    BYTE *bToEncode = (uiEncodeSize > sizeof(bEncodeBuffer)) ? new BYTE[uiEncodeSize] : bEncodeBuffer;

    if (! bToEncode)
        return E_FAIL;    

    memcpy (bToEncode, bChallenge, 16);

    bToEncode[16] = ':';

    HRESULT hr = E_FAIL;

    if (WideCharToMultiByte (cp, 0, _pszPassToUse, -1, (char *)(bToEncode + 17), ucPassLen, NULL, NULL))
    {
        MD5(bResponse, bToEncode, uiEncodeSize - 1);    // -1 because we don't want terminating '\0'
        hr = ERROR_SUCCESS;
    }

    if (bToEncode != bEncodeBuffer)
        delete [] bToEncode;

    return ERROR_SUCCESS;
}

static HRESULT MakeNonce (const WCHAR *_pszPassToUse, BYTE *bMyNonce)
{
    SYSTEMTIME st;
    GetSystemTime(&st); 

    INT cp = CP_UTF8;

    UCHAR ucPassLen = WideCharToMultiByte(cp, 0, _pszPassToUse, -1, NULL, 0, NULL, NULL);

    if (! ucPassLen)
    {
        cp = CP_ACP;
        ucPassLen = WideCharToMultiByte(cp, 0, _pszPassToUse, -1, NULL, 0, NULL, NULL);
    }

    if (! ucPassLen)
        return E_FAIL;    

    UINT uiEncodeSize = 16 + 1 + ucPassLen;
    BYTE bEncodeBuffer[512];
    BYTE *bToEncode = (uiEncodeSize > sizeof(bEncodeBuffer)) ? new BYTE[uiEncodeSize] : bEncodeBuffer;

    if (! bToEncode)
        return E_FAIL;    

    //16 bytes plus NULL ... so its okay to directly write in bToEncode... the NULL will be replaced!
    sprintf((char *)bToEncode, "%4.4d%2.2d%2.2dT%2.2d%2.2d%2.2dZ", st.wYear,st.wMonth,st.wDay, st.wHour,st.wMinute,st.wSecond);
    SVSUTIL_ASSERT(16 == strlen((char *)bToEncode));

    bToEncode[16] = ':';

    HRESULT hr = E_FAIL;

    if (WideCharToMultiByte (cp, 0, _pszPassToUse, -1, (char *)(bToEncode + 17), ucPassLen, NULL, NULL))
    {
        MD5(bMyNonce, bToEncode, uiEncodeSize - 1);    // -1 because we don't want terminating '\0'
        hr = ERROR_SUCCESS;
    }

    if (bToEncode != bEncodeBuffer)
        delete [] bToEncode;

    return hr;
}



//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CObexDevice::CObexDevice(IPropertyBag *_pPropBag, CLSID clsidTrans) : 
    _refCount(1), 
    pConnection(0),  
    pSocket(0),
    uiConnectionId(OBEX_INVALID_CONNECTION),
    uiMaxPacket(255 - OBEX_AUTH_HEADER_SIZE), //the min packet size for OBEX is 255... this value can get
                                                // renegotiated during CONNECT
    pPropBag(_pPropBag),
    iPresent(g_iCredits),
    iModified(g_iCredits),
    uiUpdateStatus(0),
    uiActiveStreamID(0xFFFFFFFF)
{
    wcPassword[0] = '\0';
    DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::CObexDevice() -- propbag: 0x%x -- me: 0x%x\n",(int)_pPropBag, (int)this));
    PREFAST_ASSERT(_pPropBag);  
    _pPropBag->AddRef();
    clsidTransport = clsidTrans;
}

CObexDevice::~CObexDevice()
{
    DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::~CObexDevice() -- me: 0x%x\n", (int)this));
     
    if(pConnection)
        pConnection->Release();
    if(pPropBag)    
        pPropBag->Release();   
    if(pSocket)
        pSocket->Release();   
}


HRESULT STDMETHODCALLTYPE
CObexDevice::Disconnect(LPHEADERCOLLECTION pHeaders)
{   
    DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::Disconnect()\n"));
    PREFAST_ASSERT(pHeaders);
    
    //first if there is an ongoing stream, deactiveate it    
    uiActiveStreamID = 0xFFFFFFFF;
    
    //make sure we have a connection ID
    if(uiConnectionId != OBEX_INVALID_CONNECTION)
        pHeaders->AddConnectionId(uiConnectionId);      
    
    HRESULT hRes = E_FAIL;
    if(pHeaders)
    {
        UCHAR *pNewPacket = NULL;
        ULONG uiNewPackSize;
        
        //send off the packet
        hRes = ObexSendRecv(pConnection, uiMaxPacket, (char)OBEX_OP_DISCONNECT, 0,0, pHeaders, &pNewPacket, &uiNewPackSize);        
        
        if (FAILED(hRes) || pNewPacket[0] != (OBEX_STAT_OK | OBEX_OP_ISFINAL))    
            hRes = E_FAIL;
        else
        {
            DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::Disconnect() -- failed?  socket went down?\n"));
        }
        
        if(pNewPacket)
            delete [] pNewPacket;
    }
    return hRes;
}


HRESULT STDMETHODCALLTYPE
CObexDevice::Get(LPHEADERCOLLECTION pHeaders, IStream **pStream)
{
    DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::Get()\n"));

    //if a get is requested the old stream is marked invalid
    //  note: this will be replaced below once the stream is created
    uiActiveStreamID =0xFFFFFFFF;

    //if we have an obex device but dont have a connection, they have not
    //  used a connection point (and thus have not 'BoundToDevice'...
    //  do the transport connection for them
    if(!pConnection && FAILED(ConnectSocket()))
        return E_FAIL;
      
   
     
    //return an obex stream    
    CObexStream *pOBEXStream = new CObexStream(pConnection, this, uiMaxPacket, uiConnectionId, wcPassword, &pHeaders);
   
    if(pOBEXStream && pOBEXStream->IsInited())
    {
        *pStream = pOBEXStream;
        
        uiActiveStreamID = pOBEXStream->GetStreamID();
        return S_OK;
    }
    else if(pOBEXStream)
    {
         //pOBEXStream fails to initialize
         delete pOBEXStream;
         return E_OUTOFMEMORY; 
    }
    else
        return E_OUTOFMEMORY;
}


HRESULT STDMETHODCALLTYPE
CObexDevice::Put(LPHEADERCOLLECTION pHeaders, IStream **pStream)
{
    DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::Put()\n"));

     //  
     //  Make sure they arent trying to squeeze in a BODY or BODY_END
     //     with our interfaces, this is an error... they are using a 
     //        STREAM and by definition that uses the BODY/BODY_END fields.
     //
     IHeaderEnum *pHeaderEnum;
     OBEX_HEADER *myHeader;
     ULONG ulFetched;
     
     //if a Put is requested the old stream is not used anymore -- so release it
     uiActiveStreamID = 0xFFFFFFFF;
 
     pHeaders->EnumHeaders(&pHeaderEnum);            
     while(SUCCEEDED(pHeaderEnum->Next(1, &myHeader, &ulFetched)))
     {
        if(myHeader->bId == OBEX_HID_BODY || myHeader->bId == OBEX_HID_BODY_END)
        {
            DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::Write() -- failed.  CANT use BODY/BODY_END with a PUT!"));
            pHeaderEnum->Release();
            return E_FAIL;            
        }           
     }
     pHeaderEnum->Release();


    //if we have an obex device but dont have a connection, they have not
    //  used a connection point (and thus have not 'BoundToDevice'...
    //  do the transport connection for them
    if(!pConnection && FAILED(ConnectSocket()))
        return E_FAIL;
    
    
    
    //return an obex stream
    CObexStream *pOBEXStream = new CObexStream(pConnection, this, uiMaxPacket, uiConnectionId, wcPassword, pHeaders);
      
    //if there is an existing stream, release it
    if(pOBEXStream && pOBEXStream->IsInited())
    {
        *pStream = pOBEXStream;
        uiActiveStreamID = pOBEXStream->GetStreamID();
        return S_OK;
    }
    else if(pOBEXStream)
    {
         //pOBEXStream fails to initialize
         delete pOBEXStream;
         return E_OUTOFMEMORY; 
    }
    else
        return E_OUTOFMEMORY;
}


HRESULT STDMETHODCALLTYPE
CObexDevice::Abort(LPHEADERCOLLECTION pHeaders)
{   
    HRESULT hRes = S_OK;
    
    //invalidate our stream
    uiActiveStreamID = 0xFFFFFFFF;     
            
    //if we have an obex device but dont have a connection, they have not
    //  used a connection point (and thus have not 'BoundToDevice'...
    //  do the transport connection for them
    if(!pConnection && FAILED(ConnectSocket()))
        return E_FAIL;
    
    DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::Abort() -- sending OBEX Abort packet\n"));

    if(uiConnectionId != OBEX_INVALID_CONNECTION)
        pHeaders->AddConnectionId(uiConnectionId);

    UCHAR *pNewPacket = NULL;
    ULONG uiNewPackSize;

    //send off the packet
    hRes = ObexSendRecv(pConnection, uiMaxPacket, (char)OBEX_OP_ABORT, 0,0, pHeaders, &pNewPacket, &uiNewPackSize);        
    
    if (FAILED(hRes) || pNewPacket[0] != (OBEX_STAT_OK | OBEX_OP_ISFINAL))    
        hRes = E_FAIL;
   
    delete [] pNewPacket;  
    
    return hRes;
}



HRESULT STDMETHODCALLTYPE
CObexDevice::SetPath(LPCWSTR szRemotePath, DWORD dwFlags, LPHEADERCOLLECTION pHeaders)
{
    DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::SetPath()\n"));
    PREFAST_ASSERT(szRemotePath);
    
    //if a Put is requested the old stream is not used anymore -- so release it
    uiActiveStreamID = 0xFFFFFFFF;

    //if we have an obex device but dont have a connection, they have not
    //  used a connection point (and thus have not 'BoundToDevice'...
    //  do the transport connection for them
    if(!pConnection && FAILED(ConnectSocket()))
        return E_FAIL;

        
    //sanity checks
    SVSUTIL_ASSERT(szRemotePath);

    if(!pHeaders)
        pHeaders = new CHeaderCollection();
    else
        pHeaders->AddRef();

    if(NULL == pHeaders)
        return E_OUTOFMEMORY;

    HRESULT hResult;
    unsigned char cOpCode = OBEX_OP_SETPATH;

    struct PUTFields
    {
        char flags;
        char constants;
    };

    PUTFields fields;
    memset(&fields, 0, sizeof(PUTFields));

⌨️ 快捷键说明

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