obexstream.cpp
来自「Windows CE 6.0 Server 源码」· C++ 代码 · 共 1,418 行 · 第 1/4 页
CPP
1,418 行
if(cLen)
{
memcpy(pcBodyChunk + uiBodyLen, pBuf, cLen);
uiBodyLen += cLen;
}
if (p.IsA (OBEX_HID_BODY_END) || p.Op() == (OBEX_STAT_OK | OBEX_OP_ISFINAL))
{
DEBUGMSG(OBEX_NETWORK_ZONE, (L"OBEX_HID_BODY_END reached...\n"));
fReadFinished = TRUE;
}
}
p.Next ();
}
//at this point we dont need the packet anymore so delete it
if(ucIncomingPacket)
delete [] ucIncomingPacket;
}
else
{
if(ucIncomingPacket)
delete [] ucIncomingPacket;
return E_FAIL;
}
}
else
return E_FAIL;
CallReadAgain:
*pcbRead = cbRead;
return S_OK;
}
//CObexStream::Write -- just do a sanity check for OBEX_PUT
// and setup the opCode to be OBEX_OP_PUT (this is done because
// the WriteAll function is used by Get's where the opcode
// is different
HRESULT STDMETHODCALLTYPE
CObexStream::Write(const void *pv, ULONG cb, ULONG *pcbWritten)
{
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::Write() -- %d bytes\n", cb));
HRESULT hr = E_FAIL;
if(uiStreamType != OBEX_PUT || StreamDisabled())
{
return E_FAIL;
}
hr = WriteAll(OBEX_OP_PUT, pv, cb, pcbWritten);
if(FAILED(hr))
{
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::Write() -- failed. cutting off stream!\n"));
uiStreamType = OBEX_ERR;
}
else
{
ASSERT(*pcbWritten == cb);
}
return hr;
}
//WriteAllHeaders is a utility used by WriteAll for transmitting a set of
// user passed in headers that are bigger than one packet. It returns when the
// headers in myHeaderCollection are smaller in size than one OBEX packet
HRESULT
CObexStream::WriteAllHeaders(char cOpCode, UINT uiMINPackSize)
{
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() -- cant fit all headers into one packet -- breaking into multiple parts!"));
//
// While the packet is too large to contain
// BODY's send off as many of the headers
// as will fit in a packet
//
HRESULT hr = E_FAIL;
BYTE cOp;
CHeaderCollection *pNewHeaderCollection = new CHeaderCollection();
if( !pNewHeaderCollection )
return E_OUTOFMEMORY;
IHeaderEnum *pHeaderEnum = NULL;
OBEX_HEADER *myHeader = NULL;
ULONG ulFetched;
UINT uiHeaderCount = 0;
myHeaderCollection->EnumHeaders(&pHeaderEnum);
while(SUCCEEDED((hr = pHeaderEnum->Next(1, &myHeader, &ulFetched))) && ulFetched)
{
SVSUTIL_ASSERT(pHeaderEnum && pNewHeaderCollection);
cOp = myHeader->bId;
//copy the header and insert it into the new list (note: the collection
// takes ownership
OBEX_HEADER *pNewHeader = new OBEX_HEADER();
if( !pNewHeader )
{
hr = E_OUTOFMEMORY;
goto Done;
}
CHeaderCollection::CopyHeader(myHeader,pNewHeader);
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() -- Adding 0x%x to temp pNewHeaderCollectoin!", pNewHeader->bId));
if(FAILED(hr = pNewHeaderCollection->InsertHeader(pNewHeader)))
{
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() -- Error inserting new header into list!"));
goto Done;
}
uiHeaderCount ++;
//
// If this header throws us over the edge in size, remove it
// and send off the header, otherwise, move (ie transfer) it from
// 'myHeaderCollection' to 'pNewHeaderCollection'
//
if(uiMINPackSize + SizeOfHeader(pNewHeaderCollection) >= uiMaxPacket)
{
//remove the older header (note: this just removes it from the
// newheader collection and *NOT* the old one!)
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() -- Removing 0x%x from temp pNewHeaderCollectoin!", cOp));
pNewHeaderCollection->Remove(cOp);
uiHeaderCount --;
//if there are NO headers, that means the one we just added is too
// big for one packet, so we are forced to quit... :(
if(!uiHeaderCount)
{
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() -- one of our headers is too large -- cant send packet!"));
hr = E_FAIL;
goto Done;
}
//add a connectionID (if required)
if(uiConnectionId != OBEX_INVALID_CONNECTION)
pNewHeaderCollection->AddConnectionId(uiConnectionId);
//send out the packet, and grab the response
unsigned char *pNewPacket;
ULONG uiIPackSize;
if(SUCCEEDED(hr = ObexSendRecvWithAuthSaveHeaders(pConnection, uiMaxPacket, wcPassword, cOpCode, 0,0, pNewHeaderCollection, &pNewPacket, &uiIPackSize)))
{
//parse out all interesting fields
ObexParser p (pNewPacket, uiIPackSize);
//get the command data
if (p.Op() != 0x90)
{
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() -- recieved an invalid return code! : op -- %d\n", p.Op()));
hr = E_FAIL;
}
else
hr = S_OK;
//cleanup & init everything to be ready for a new packet
delete [] pNewPacket;
pNewHeaderCollection->Release();
pNewHeaderCollection = new CHeaderCollection();
if( !pNewHeaderCollection )
{
hr = E_OUTOFMEMORY;
goto Done;
}
uiHeaderCount = 0;
//reset the enumerator (so we can start where we left off)
pHeaderEnum->Release();
pHeaderEnum = 0;
myHeaderCollection->EnumHeaders(&pHeaderEnum);
if(FAILED(hr))
goto Done;
}
else
{
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() --- ObexSendRecvWithAuth() failed!\n"));
goto Done;
}
}
else
{
//
//we have moved the header to our new location... so remove it from
// the origin (thereby transfering the bag)
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() -- Removing 0x%x from temp pHeaderCollection!", cOp));
myHeaderCollection->Remove(cOp);
}
//
// Recompute size of main header collection, if its too big loop again
// if it fits in one packet, break out of the loop
UINT uiPacketSize = uiMINPackSize + SizeOfHeader(myHeaderCollection);
if(!uiHeaderCount && 3 + uiPacketSize <= uiMaxPacket)
break;
//
// Flush the buffer
//
else if(uiHeaderCount && 3 + uiPacketSize <= uiMaxPacket)
{
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() -- down to a managable header size, flushing temp buffer and going on as usual\n"));
//add a connectionID (if required)
if(uiConnectionId != OBEX_INVALID_CONNECTION)
pNewHeaderCollection->AddConnectionId(uiConnectionId);
//send out the packet, and grab the response
unsigned char *pNewPacket;
ULONG uiIPackSize;
if(SUCCEEDED(hr = ObexSendRecvWithAuthSaveHeaders(pConnection, uiMaxPacket, wcPassword, cOpCode, 0,0, pNewHeaderCollection, &pNewPacket, &uiIPackSize)))
{
//parse out all interesting fields
ObexParser p (pNewPacket, uiIPackSize);
//get the command data
if (p.Op() != 0x90)
{
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() -- recieved an invalid return code! : op -- %d\n", p.Op()));
hr = E_FAIL;
}
else
hr = S_OK;
//cleanup & init everything to be ready for a new packet
delete [] pNewPacket;
pNewHeaderCollection->Release();
pNewHeaderCollection = NULL;
uiHeaderCount = 0;
if(FAILED(hr))
goto Done;
}
else
{
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() --- ObexSendRecvWithAuth() failed!\n"));
hr = E_FAIL;
goto Done;
}
break;
}
}
Done:
if(pHeaderEnum)
pHeaderEnum->Release();
if(pNewHeaderCollection)
pNewHeaderCollection->Release();
return hr;
}
HRESULT STDMETHODCALLTYPE
CObexStream::WriteAll(char cOpCode, const void *pv, ULONG cb, ULONG *pcbWritten)
{
HRESULT hr = S_OK;
UINT cbTotalWritten = 0;
if(!cb) {
ULONG cbJustWritten = 0;
if(FAILED(hr = WriteAllHelper(cOpCode, pv, cb, &cbJustWritten)))
goto Done;
ASSERT(0 == cbJustWritten);
}
else {
while(cb)
{
ULONG cbJustWritten = 0;
if(FAILED(hr = WriteAllHelper(cOpCode, pv, cb, &cbJustWritten)))
goto Done;
cbTotalWritten += cbJustWritten;
pv = (char *)pv + (UINT) cbJustWritten;
cb -= cbJustWritten;
}
}
Done:
if(SUCCEEDED(hr))
{
*pcbWritten = cbTotalWritten;
}
return hr;
}
HRESULT
CObexStream::WriteAllHelper(char cOpCode, const void *pv, ULONG cb, ULONG *pcbWritten)
{
PREFAST_ASSERT(myHeaderCollection);
PREFAST_ASSERT(pcbWritten);
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() -- %d bytes\n", cb));
UINT uiPacketSize = 0;
UINT toWrite = cb; // <-- make the first attempt the entire buffer
UINT uiMINPackSize = MIN_PUT_PACKET_SIZE;
UINT uiTemp; //holder for temp comparisons
HRESULT hr = S_OK;
*pcbWritten = 0;
//determine the minimum packet we can transmit
// (5 bytes to transfer a connection ID)
// also remove a previous connection ID (if one exists)
if(OBEX_INVALID_CONNECTION != uiConnectionId)
uiMINPackSize += 5;
myHeaderCollection->Remove(OBEX_HID_CONNECTIONID);
//figure out the size of the packet (as it currently is...)
if(FAILED(UIntAdd(uiMINPackSize, SizeOfHeader(myHeaderCollection), &uiPacketSize))||
FAILED(UIntAdd(uiPacketSize, 3, &uiTemp))) {
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() -- WriteAllHeaders overflow of uiPacketSize!"));
goto Done;
}
//if the packet is too large without any BODY send off a few packets
// before attaching a body
if(uiTemp >= uiMaxPacket)
{
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() -- cant fit all headers into one packet -- breaking into multiple parts!"));
if(FAILED(hr = WriteAllHeaders(cOpCode, uiMINPackSize)))
{
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() -- WriteAllHeaders failed!"));
goto Done;
}
SVSUTIL_ASSERT(uiMaxPacket >= uiMINPackSize + SizeOfHeader(myHeaderCollection));
//recompute the packet size after sending as many headers as possible
if(FAILED(UIntAdd(uiMINPackSize, SizeOfHeader(myHeaderCollection), &uiPacketSize))) {
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() -- WriteAllHeaders overflow of uiPacketSize!"));
goto Done;
}
}
//
// figure out how much non header data we can put into one packet
//
DEBUGMSG(OBEX_OBEXSTREAM_ZONE,(L"CObexStream::WriteAll() -- toWrite(%d) uiBodyLen(%d) uiPacketSize(%d) maxPacket(%d)\n", toWrite, uiBodyLen, uiPacketSize, uiMaxPacket));
UINT uiTotalSize = 0;
if(FAILED(UIntAdd(3, toWrite, &uiTotalSize)) ||
FAILED(UIntAdd(uiBodyLen, uiTotalSize, &uiTotalSize)) ||
FAILED(UIntAdd(uiPacketSize, uiTotalSize, &uiTotalSize))) {
ASSERT(FALSE);
hr = E_INVALIDARG;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?