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 + -
显示快捷键?