📄 obexdevice.cpp
字号:
if (*szRemotePath == L'\\')
{
//fill in cPacket independent fields
fields.flags = (char)dwFlags;
fields.constants = 0;
if(uiConnectionId != OBEX_INVALID_CONNECTION)
pHeaders->AddConnectionId(uiConnectionId);
pHeaders->AddName(L"");
//move beyond the '\'
++szRemotePath;
ASSERT(*szRemotePath != '\\');
UCHAR *pNewPacket = NULL;
ULONG uiNewPackSize;
//send off the packet
hResult = ObexSendRecvWithAuth(pConnection, uiMaxPacket, wcPassword, cOpCode, (char *)&fields, sizeof(PUTFields), pHeaders, &pNewPacket, &uiNewPackSize);
if (FAILED(hResult) || pNewPacket[0] != (OBEX_STAT_OK | OBEX_OP_ISFINAL))
{
pHeaders->Release();
return E_FAIL;
}
pHeaders->Release();
pHeaders = new CHeaderCollection();
delete [] pNewPacket;
if(!pHeaders)
return E_OUTOFMEMORY;
}
char fError = FALSE;
while ((! fError) && (*szRemotePath != '\0'))
{
pHeaders->Release();
pHeaders = new CHeaderCollection();
if(!pHeaders)
return E_OUTOFMEMORY;
WCHAR *p = (WCHAR*)wcschr (szRemotePath, L'\\');
//clear fields
memset(&fields, 0, sizeof(PUTFields));
if (p) {
*p = '\0';
ASSERT(*(p+1) != '\\');
}
if (wcscmp (szRemotePath, L"..") == 0)
{
fields.flags = 3;
fields.constants = 0;
if(uiConnectionId != OBEX_INVALID_CONNECTION)
pHeaders->AddConnectionId(uiConnectionId);
}
else if (wcscmp (szRemotePath, L".") == 0)
{
if (p)
{
*p = '\\';
szRemotePath = p + 1;
continue;
}
else
break;
}
else
{
//fill in cPacket independent fields
fields.flags = (char)dwFlags;
fields.constants = 0;
if(uiConnectionId != OBEX_INVALID_CONNECTION)
pHeaders->AddConnectionId(uiConnectionId);
pHeaders->AddName(szRemotePath);
}
//send off the packet
UCHAR *pNewPacket;
ULONG uiNewPackSize;
hResult = ObexSendRecvWithAuth(pConnection, uiMaxPacket, wcPassword, cOpCode, (char *)&fields, sizeof(PUTFields), pHeaders, &pNewPacket, &uiNewPackSize);
if(FAILED(hResult))
return E_FAIL;
if (pNewPacket[0] != (OBEX_STAT_OK | OBEX_OP_ISFINAL))
{
SetLastError (ERROR_INVALID_NAME);
fError = TRUE;
}
delete [] pNewPacket;
if (p)
{
*p = '\\';
szRemotePath = p + 1;
}
else
break;
}
pHeaders->Release();
if(fError)
return E_FAIL;
return S_OK;
}
HRESULT STDMETHODCALLTYPE
CObexDevice::EnumProperties(REFIID riid, void **ppv)
{
SVSUTIL_ASSERT(pPropBag);
if (!ppv)
return E_INVALIDARG;
return pPropBag->QueryInterface(riid, ppv);
}
HRESULT STDMETHODCALLTYPE
CObexDevice::SetPassword(LPCWSTR _pszPassToUse)
{
if(wcslen(_pszPassToUse) >= MAX_PASS_SIZE)
{
return E_FAIL;
}
//
// Set the password
//
wcscpy(wcPassword, _pszPassToUse);
//
// return...
//
return S_OK;
}
HRESULT STDMETHODCALLTYPE
CObexDevice::BindToStorage(DWORD dwCapability, IStorage **ppStorage)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE
CObexDevice::QueryInterface(REFIID riid, void** ppv)
{
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::QueryInterface()\n"));
if(!ppv)
return E_POINTER;
if(riid == IID_IObexDevice)
*ppv = this;
else if(riid == IID_IObexDevice)
*ppv = static_cast<IObexDevice*>(this);
else
return *ppv = 0, E_NOINTERFACE;
return AddRef(), S_OK;
}
ULONG STDMETHODCALLTYPE
CObexDevice::AddRef()
{
ULONG ret = InterlockedIncrement((LONG *)&_refCount);
DEBUGMSG(OBEX_ADDREFREL_ZONE,(L"CObexDevice::AddRef(%d) -- 0x%x\n",ret, (int)this));
return ret;
}
ULONG STDMETHODCALLTYPE
CObexDevice::Release()
{
SVSUTIL_ASSERT(_refCount != 0xFFFFFFFF);
ULONG ret = InterlockedDecrement((LONG *)&_refCount);
DEBUGMSG(OBEX_ADDREFREL_ZONE,(L"CObexDevice::Release(%d) -- 0x%x\n",ret, (int)this));
if(!ret)
delete this;
return ret;
}
HRESULT
CObexDevice::CompleteDiscovery()
{
//first make sure that we have figured out all fields required for connection
// (the user might have clicked on a BT device before the discovery had
// completed)
if(GetUpdateStatus() != 0xFFFFFFFF)
{
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::CompleteDiscovery() -- dont have full device property list... querying for it now\n"));
IObexTransport *pTransport = NULL;
HRESULT hr = CoCreateInstance(clsidTransport, NULL, CLSCTX_INPROC_SERVER, IID_IObexTransport,
(void **)&pTransport);
if(SUCCEEDED(hr) && pTransport)
{
IObexAbortTransportEnumeration *pAbortEnum = NULL;
if(SUCCEEDED(pTransport->QueryInterface(IID_IObexAbortTransportEnumeration, (LPVOID *)&pAbortEnum))) {
pAbortEnum->Resume();
pAbortEnum->Release();
}
UINT uiUpdateStatus;
hr = pTransport->UpdateDeviceProperties(pPropBag, NULL, TRUE, &uiUpdateStatus);
if (FAILED(hr) || 0 == (uiUpdateStatus & CAN_CONNECT))
{
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::CompleteDiscovery() -- updated device to level 0x%x -- NOT GOOD ENOUGH TO CONNECT\n", uiUpdateStatus));
hr = E_FAIL;
}
else
{
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::CompleteDiscovery() -- updated device to level 0x%x -- ready to GO!\n", uiUpdateStatus));
}
pTransport->Release();
pTransport = NULL;
return hr;
}
else
{
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::CompleteDiscovery() -- ERROR couldnt get a transport!\n"));
return E_FAIL;
}
}
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::CompleteDiscovery() -- SUCCESS -- no need to query, its already been done\n"));
return S_OK;
}
HRESULT
CObexDevice::ConnectSocket()
{
HRESULT hRes = S_OK;
//
// complete the discovery phase... if it fails we have to quit
//
if(FAILED((hRes=CompleteDiscovery())))
{
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::ConnectSocket() --- Failure completing discovery!\n"));
return hRes;
}
else
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::ConnectSocket() --- SUCCEEDED completing discovery!\n"));
//
// if we are not connected, get connected
//
if(!pConnection)
{
if(FAILED((hRes = ConnectToTransportSocket())))
{
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::ConnectSocket() -- cannot ConnectToTransportSocket\n"));
return hRes;
}
else
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::ConnectSocket() --- SUCCEEDED with ConnectToTransportSocket!\n"));
}
else
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::ConnectSocket() --- already have connection!\n"));
return hRes;
}
HRESULT
CObexDevice::Connect(LPCWSTR _pszPassToUse, DWORD dwCapability, LPHEADERCOLLECTION pHeaderCollection)
{
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::Connect()\n"));
HRESULT hRes;
BYTE bMyNonce[16];
BOOL fOkayToContinueWithoutAuthentication = TRUE;
BOOL fHaveAuthentication = FALSE;
//verify password size
if(_pszPassToUse && wcslen(_pszPassToUse) >= MAX_PASS_SIZE)
return E_FAIL;
//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;
//
// if there is no global password, set the one passed in as global
//
if(wcPassword[0] == '\0' && _pszPassToUse)
{
wcscpy(wcPassword , _pszPassToUse);
}
//
// As per spec: use the Connect() password first, if it does not
// exist, use the cached one from SetPassword
//
else if(!_pszPassToUse)
{
_pszPassToUse = wcPassword;
}
//
// if a password was sent down, its not okay to continue without authentication
// so build up a nonce and put it in along with the headers
//
if(_pszPassToUse && wcPassword[0] != '\0')
{
fOkayToContinueWithoutAuthentication = FALSE;
hRes = MakeNonce (_pszPassToUse, bMyNonce);
if (hRes != ERROR_SUCCESS)
return hRes;
BYTE bChallenge[18];
memcpy(bChallenge+2, bMyNonce, 16);
bChallenge[0] = 0x00;
bChallenge[1] = 0x10;
pHeaderCollection->AddByteArray(OBEX_HID_AUTH_CHALLENGE, 18, bChallenge);
}
//
// Build the CONNECT headers
//
char packet[4];
WORD wMaxSizeNBO = htons(g_uiMaxFileChunk);
packet[0] = OBEX_VERSION; //version
packet[1] = 0x00; //flags
packet[2] = ((char *)(&wMaxSizeNBO))[0]; //max PACKET size (in nbo)
packet[3] = ((char *)(&wMaxSizeNBO))[1];
//
// Send out the CONNECT packet, and recieve a response
//
UCHAR *pPacket = 0;
ULONG uiPackSize;
hRes = ObexSendRecv(
pConnection,
uiMaxPacket,
(char)OBEX_OP_CONNECT,
packet,
4,
pHeaderCollection,
&pPacket,
&uiPackSize);
if(FAILED(hRes))
{
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::Connect() -- error with ObexSendRecv!\n"));
return hRes;
}
//
// Parse the return packet for its fields
//
ObexParser *p = new ObexParser(pPacket, uiPackSize);
if(!p) {
return E_OUTOFMEMORY;
}
//
// if the opcode on the return packet is 0xA0 (OK, Success)
// fill out the max packet size and prepare the data
// for parsing below. If it was UNAUTHORIZED (0xC1) then
// we need to complete the authorization part
//
if (p->Op() == (OBEX_STAT_OK | OBEX_OP_ISFINAL))
{
WORD wMaxLen;
((char *)(&wMaxLen))[0] = pPacket[5];
((char *)(&wMaxLen))[1] = pPacket[6];
uiMaxPacket = htons(wMaxLen) - OBEX_AUTH_HEADER_SIZE;
if(uiMaxPacket > g_uiMaxFileChunk - OBEX_AUTH_HEADER_SIZE)
uiMaxPacket = g_uiMaxFileChunk - OBEX_AUTH_HEADER_SIZE;
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::ObexConnect() -- setting max packet size to : %d\n",uiMaxPacket));
//
// Fix up the ObexPacketData by pointing at the start of headers
// huh you ask? :) the CONNECT response is like this
// byte0: response code
// byte1: connect response packet length
// byte2: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// byte3: OBEX version #
// byte4: flags
// byte5: max OBEX packet length
// byte6: ^^^^^^^^^^^^^^^^^^^^^^
// so we advance the packet by 7 bytes to account for this header stuff
p->ppkt = pPacket;
p->start = p->current = (pPacket + 7);
p->length = uiPackSize - 7;
}
else if(p->Op() == (OBEX_STAT_UNAUTHORIZED | OBEX_OP_ISFINAL))
{
BYTE bServerChallenge[16];
BOOL fChallengeFound = FALSE;
WORD wMaxLen;
((char *)(&wMaxLen))[0] = pPacket[5];
((char *)(&wMaxLen))[1] = pPacket[6];
uiMaxPacket = htons(wMaxLen) - OBEX_AUTH_HEADER_SIZE;
if(uiMaxPacket > g_uiMaxFileChunk - OBEX_AUTH_HEADER_SIZE)
uiMaxPacket = g_uiMaxFileChunk - OBEX_AUTH_HEADER_SIZE;
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::ObexConnect() -- DENIED access, but setting max packet size to : %d -- retrying connection with password\n",uiMaxPacket));
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -