obexstream.cpp

来自「Windows CE 6.0 Server 源码」· C++ 代码 · 共 1,418 行 · 第 1/4 页

CPP
1,418
字号
    if (NULL == pResponseHeaders)
        return E_OUTOFMEMORY;

    memcpy(pResponseHeaders,pNewPacket,Size);
    uiResponseHeaderLen = Size;
    return S_OK;
}            


// Wraps underlying ObexSendRecvWithAuth function.  Saves the first header on a GET
// and the last header on a PUT so that client can retrieve this information later
// if needed.
HRESULT CObexStream::ObexSendRecvWithAuthSaveHeaders(
                   IObexTransportConnection *pConnection, UINT uiMaxPacket,
                   WCHAR *wcPassword, char cOpCode, char *additionalDta, 
                   UINT cAddnlDta, IHeaderCollection *pHeaderCollection, 
                   unsigned char **pNewPacket, ULONG *pSize)
{
    fHaveSentData = TRUE;

    HRESULT hr = ObexSendRecvWithAuth(pConnection, uiMaxPacket,
                   wcPassword, cOpCode, additionalDta, 
                   cAddnlDta, pHeaderCollection, pNewPacket, pSize);

    if (FAILED(hr))
        return hr;

    ObexParser p (*pNewPacket, *pSize);

    // allows client to query last response
    bLastResponseCode = (BYTE) p.Op();

    if (uiStreamType == OBEX_GET) {
        // Store headers initially for GET.  Don't parse them out at this stage
        // since the vast majority of obex clients will never need them
        if (NULL == pResponseHeaders) {
            return CopyResponseHeaders(*pNewPacket,*pSize);
        }
    }
    else if (uiStreamType == OBEX_PUT) {
        // We can receive multiple response packets during PUT session.
        // The last one server sends OBEX_STAT_OK rather than OBEX_STAT_CONTINUE.
        // These are the headers we're interested in.
        if ((p.Op () & 0xF0) == (OBEX_STAT_OK | OBEX_OP_ISFINAL)) {
            if (pResponseHeaders) {
                DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"OBEX: Obex client received more than one (OBEX_STAT_OK | OBEX_OP_ISFINAL) PUT response packets\r\n"));
                ASSERT(0); // We should only be able to get to this stage once
                return S_OK;
            }

            return CopyResponseHeaders(*pNewPacket,*pSize);
        }
    }

    return S_OK;
}


ULONG STDMETHODCALLTYPE 
CObexStream::AddRef() 
{
    DEBUGMSG(OBEX_ADDREFREL_ZONE,(L"CObexStream::AddRef()\n"));
    return InterlockedIncrement((LONG *)&_refCount);
}

ULONG STDMETHODCALLTYPE 
CObexStream::Release() 
{
    DEBUGMSG(OBEX_ADDREFREL_ZONE,(L"CObexStream::Release()\n"));
    SVSUTIL_ASSERT(_refCount != 0xFFFFFFFF);
    ULONG ret = InterlockedDecrement((LONG *)&_refCount);    
    if(!ret) 
        delete this; 
    return ret;
}

HRESULT STDMETHODCALLTYPE 
CObexStream::QueryInterface(REFIID riid, void** ppv) 
{
    DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::QueryInterface()\n"));
     if(!ppv) 
        return E_POINTER;
    if(riid == IID_IUnknown) 
        *ppv = this;
    else if(riid == IID_IStream) 
        *ppv = static_cast<IStream*>(this);
    else if(riid == IID_IObexResponse) 
        *ppv = static_cast<IObexResponse*>(this);
    else if(riid == IID_IHeaderEnum) 
        *ppv = static_cast<IHeaderEnum*>(this);
    else 
        return *ppv = 0, E_NOINTERFACE;

    return AddRef(), S_OK;    
}
   
  
HRESULT 
CObexStream::Read(void *pv, ULONG cb, ULONG *pcbRead)
{
    HRESULT hr = S_OK;
    UINT cbTotalRead = 0;
   
    //check to make sure we CAN read on this connection
    if(!pv || uiStreamType != OBEX_GET || StreamDisabled()) 
    {
        DEBUGMSG(OBEX_NETWORK_ZONE, (L"Wrong connection type\n"));
        return E_FAIL;
    }
        
    while(cb)
    {
        ULONG cbJustRead = 0;
        
        if(FAILED(hr = ReadHelper(pv, cb, &cbJustRead)))
        {
            //if we have read SOMETHING, stop looping
            //  and give them S_OK.  if the stream has 
            //  ended their next call will fail
            if(cbTotalRead)
                hr = S_OK;
                
            cbTotalRead += cbJustRead;    
            goto Done;
        }   
              
        cbTotalRead += cbJustRead;
        pv = (char *)pv + (UINT) cbJustRead;
        cb -= cbJustRead;
    }
Done:
    if(SUCCEEDED(hr))
    {        
        *pcbRead = cbTotalRead;
    }  
    return hr;
}


BOOL CObexStream::StreamDisabled()
{
    if(pMyOBEXDevice && GetStreamID()==pMyOBEXDevice->GetStreamID())
        return FALSE;
    else
        return TRUE;
}

HRESULT 
CObexStream::ReadHelper(void *pv, ULONG cb, ULONG *pcbRead)
{ 
    DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::Read()\n"));
    
    char *pDestBuf = (char *)pv;
    ULONG cbRead = 0;
    HRESULT hr = E_FAIL;
      
    //first see if we have enough data cached to complete the 
    //  request, if not, deplete the cache and request a new 
    //  packet
    if(uiBodyLen >= cb && !fFirstPacket)
    {
        memcpy(pDestBuf, pcBodyPtr, cb);
        pcBodyPtr += cb;
        uiBodyLen -= cb;       
        *pcbRead = cb;
        return S_OK;
    }
    else if(uiBodyLen)
    {
        memcpy(pDestBuf, pcBodyPtr, uiBodyLen);
        pDestBuf += uiBodyLen;
        cbRead = uiBodyLen;
        cb -= uiBodyLen;
        uiBodyLen = 0;
        delete [] pcBodyChunk;
        pcBodyPtr = pcBodyChunk = NULL;

        if(fReadFinished)
        {
            *pcbRead = cbRead;
            return S_OK;
        }
    }

    //if there is no data, AND we are finished, quit
    if((! uiBodyLen) && fReadFinished)
    {
        DEBUGMSG(OBEX_NETWORK_ZONE, (L"-->No more data left\n"));
        return E_FAIL;
    }
   
    //account for the header size upfront
    if(!fHeaderAccounted)
    {
        if(uiConnectionId != OBEX_INVALID_CONNECTION)
            myHeaderCollection->AddConnectionId(uiConnectionId);        
      
        fHeaderAccounted = TRUE;
    }

   
    //if we are sending off the first packet, there might be too much data
    //  in the headers (BODY being really large)... so we use the helper function
    //  WriteAll to help us out
    if(fFirstPacket) 
    {  
        fFirstPacket = FALSE;

        //if the data is too big to fit in one packet (this would most likely be
        //  be because the BODY field is really large... remove
        //  the BODY from the packet, and send it off to WriteAll (with
        //  the BODY data as the value to write... WriteAll will send
        //  the data as a BODY...  NOTE: WriteAll will break the request up
        //  if necessary (for example if there are so many headers that 
        //  multiple packets must be sent)
        if(SizeOfHeader(myHeaderCollection) >= uiMaxPacket)
        {            
            OBEX_HEADER *myHeader;
            ULONG ulFetched;
            LPHEADERENUM pHeaderEnum;
            ULONG ulDataSize = 0;
            ULONG ulWritten = 0;
            BYTE *pData = NULL;

            //
            //  get a copy of the BODY portion of the headers 
            //
            myHeaderCollection->EnumHeaders(&pHeaderEnum);            
            while(SUCCEEDED(pHeaderEnum->Next(1, &myHeader, &ulFetched)))
            {
                if(myHeader->bId == OBEX_HID_BODY)
                {
                    pData = new BYTE[myHeader->value.ba.dwSize];
                    ulDataSize = myHeader->value.ba.dwSize;

                    if(!pData)
                        return E_FAIL;
                        
                    memcpy(pData, myHeader->value.ba.pbaData, ulDataSize);
                    break;
                }           
            }
            pHeaderEnum->Release();
            

            //now make a call to WriteAll to packetize the data and send it out
            //  if there is no data, fall through and just run as normal
            if(pData && ulDataSize)    
            {
                myHeaderCollection->Remove(OBEX_HID_BODY);
                hr = WriteAll(OBEX_OP_GET, pData, ulDataSize, &ulWritten);
                if(FAILED(hr))
                {
                    DEBUGMSG(OBEX_NETWORK_ZONE, (L"Write All in first packet of Write FAILED!\n"));
                    return hr;
                }
                    
                hr = FlushSendBuffers(OBEX_OP_GET);
                if(FAILED(hr))
                {
                    DEBUGMSG(OBEX_NETWORK_ZONE, (L"FlushSendBuffer in first packet of Write FAILED!\n"));            
                    return hr;
                }

                //    
                //  because we already have recieved an answer (and have sent a packet)
                //    just skip to calling read again 
                //
                goto CallReadAgain;
            }  
            
            //if there is no body, we know that the headers are greater than one
            //  packet BUT there is no body.  simply call WriteAll passing
            //  in no body with no size
            else
            {
                hr = WriteAll(OBEX_OP_GET, 0, 0, &ulWritten);
                
                if(FAILED(hr))
                {
                    DEBUGMSG(OBEX_NETWORK_ZONE, (L"WriteAll() in first packet of large headers with no body FAILED!\n"));
                    return hr;
                }
                
                hr = FlushSendBuffers(OBEX_OP_GET);
                if(FAILED(hr))
                {
                    DEBUGMSG(OBEX_NETWORK_ZONE, (L"FlushSendBuffer in first packet of large headers with no body FAILED!\n"));            
                    return hr;
                }

                goto CallReadAgain;
            }
         }
    }

    unsigned char *ucIncomingPacket;  
    ULONG iRespSize;        
     
    //send off the packet and get its answer
    hr = ObexSendRecvWithAuthSaveHeaders(pConnection, uiMaxPacket, wcPassword, (char)(OBEX_OP_GET | OBEX_OP_ISFINAL), 0,0, myHeaderCollection, &ucIncomingPacket, &iRespSize);
    if(SUCCEEDED(hr))
    {            
		//clean out the headers we sent
		myHeaderCollection->Release();
              myHeaderCollection=new CHeaderCollection();
              if( !myHeaderCollection )
                  return E_OUTOFMEMORY;
		   
		fHeaderAccounted = FALSE; 

        //parse out all interesting fields
        ObexParser p (ucIncomingPacket, iRespSize);
                
        if (((p.Op () & 0xF0) == (OBEX_STAT_CONTINUE | OBEX_OP_ISFINAL)) || 
            ((p.Op () & 0xF0) == (OBEX_STAT_OK | OBEX_OP_ISFINAL))) 
        {           
            while (! p.__EOF ()) 
            {
                if (p.IsA (OBEX_HID_BODY) || (p.IsA (OBEX_HID_BODY_END))) 
                {                    
                    int cLen = 0;
                    unsigned char *pBuf;
                    if (! p.GetBytes (&pBuf, &cLen))
                    {
                        SVSUTIL_ASSERT(FALSE);
                        break;
                    }  
                    
                    //copy in the data (we cant have more than
                    //  we can hold)
                    if (pcBodyChunk && cLen) {
                        BYTE *pcNewChunk = new BYTE [uiBodyLen + cLen];
                        if( !pcNewChunk )
                        {
                            delete [] pcBodyChunk;
                            pcBodyChunk = pcBodyPtr = NULL;

                            if(ucIncomingPacket)
                                 delete [] ucIncomingPacket;   

                            return E_OUTOFMEMORY;
                        }

                        memcpy (pcNewChunk, pcBodyPtr, uiBodyLen);
                        delete [] pcBodyChunk;
                        pcBodyChunk = pcBodyPtr = pcNewChunk;
                    } else if(cLen){
                        pcBodyChunk = new BYTE[cLen];
                        pcBodyPtr = pcBodyChunk;
                    }

                    if (! pcBodyChunk && cLen)
                        return E_OUTOFMEMORY;

⌨️ 快捷键说明

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