📄 obexirdatransport.cpp
字号:
//
// 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.
//
#include "common.h"
#include "ObexIRDATransport.h"
#include "IRDATransportSocket.h"
#include "CObex.h"
#include "PropertyBag.h"
#include "PropertyBagEnum.h"
#include "ObexStrings.h"
/*----------globals---------------*/
LPSOCKET CObexIRDATransport::pSocket = 0;
CObexIRDATransport::CObexIRDATransport() : _refCount(1), dwTimeOfLastEnum(0), fIsAborting(FALSE)
{
DEBUGMSG(OBEX_IRDATRANSPORT_ZONE,(L"CObexIRDATransport::CObexIRDATransport()\n"));
//initilize the socket libs
WSADATA wsd;
WSAStartup (MAKEWORD(2,2), &wsd);
}
CObexIRDATransport::~CObexIRDATransport()
{
DEBUGMSG(OBEX_IRDATRANSPORT_ZONE,(L"CObexIRDATransport::~CObexIRDATransport()\n"));
//clean up winsock
WSACleanup();
}
HRESULT STDMETHODCALLTYPE
CObexIRDATransport::Init(void)
{
DEBUGMSG(OBEX_IRDATRANSPORT_ZONE,(L"CObexIRDATransport::Init()\n"));
return S_OK;
}
HRESULT STDMETHODCALLTYPE
CObexIRDATransport::Shutdown(void)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE
//singleton that holds a socket object
CObexIRDATransport::CreateSocket(LPPROPERTYBAG2 pPropertyBag,
LPSOCKET *ppSocket)
{
DEBUGMSG(OBEX_IRDATRANSPORT_ZONE,(L"CObexIRDATransport::CreateSocket()\n"));
*ppSocket = new CIRDATransportSocket();
if( !(*ppSocket) )
{
return E_OUTOFMEMORY;
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE
CObexIRDATransport::CreateSocketBlob(unsigned long ulSize,
byte __RPC_FAR *pbData,
LPSOCKET __RPC_FAR *ppSocket)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE
CObexIRDATransport::EnumDevices(LPPROPERTYBAGENUM *ppDevices)
{
DEBUGMSG(OBEX_IRDATRANSPORT_ZONE,(L"CObexIRDATransport::EnumDevices()\n"));
//
// Because IRDA is very quick on enum we can end up spin locking
// during query. this limits the frequency of call to 500 ms
//
if(GetTickCount() - dwTimeOfLastEnum < 500)
{
DEBUGMSG(OBEX_IRDATRANSPORT_ZONE, (L"[OBEX] ObexIRDATransport::UpdateDeviceProperties() -- sleeping for a bit to avoid spinlock\n"));
Sleep(500);
}
dwTimeOfLastEnum = GetTickCount();
//start by setting the enumeration to be 0 (error)
*ppDevices = 0;
//create a socket
SOCKET s = socket(AF_IRDA, SOCK_STREAM, 0);
if(s == INVALID_SOCKET) {
DEBUGMSG(OBEX_IRDATRANSPORT_ZONE,(L"CObexIRDATransport::EnumDevices() -- got an invalid socket\n"));
SetLastError (ERROR_DEVICE_NOT_CONNECTED);
return E_FAIL;
}
//memory to hold possible servers
unsigned char DevListBuff[sizeof(DEVICELIST) -
sizeof(IRDA_DEVICE_INFO) +
(sizeof(IRDA_DEVICE_INFO) * DEVICE_LIST_LEN)];
int DevListLen = sizeof(DevListBuff);
PDEVICELIST pDevList = (PDEVICELIST)DevListBuff;
pDevList->numDevice = 0;
//search to see what IrDA devices are visible
for(UINT uiTries=0; uiTries <= g_uiIRDAMaxRetries; uiTries ++) {
int optReturn = getsockopt(s,
SOL_IRLMP,
IRLMP_ENUMDEVICES,
(char *) pDevList,
&DevListLen);
if (optReturn == SOCKET_ERROR)
{
int errorCode = WSAGetLastError();
//if a blocking call is being made, just sleep and
// try again, otherwise bail out
if(WSAEINPROGRESS == errorCode)
{
DEBUGMSG(OBEX_IRDATRANSPORT_ZONE,(L"CObexIRDATransport::EnumDevices() -- error in progress.. trying again in 500 ms\n"));
//clean out the structure so there is no
// confusion later (since it hasnt been inited
// by getsockopt)
pDevList->numDevice = 0;
//sleep for half a second to give the other
// function time to finish up (note: this stinks
// but there isnt anything we can do but wait it
// out)
Sleep(500);
}
else
{
closesocket(s);
int err = WSAGetLastError();
DEBUGMSG(OBEX_IRDATRANSPORT_ZONE, (L"Error code: %d\n", err));
return E_FAIL;
}
}
if(pDevList->numDevice != 0)
break;
}
CPropertyBagEnum *pPropEnum = new CPropertyBagEnum();
if(!pPropEnum)
{
closesocket(s);
return E_OUTOFMEMORY;
}
CPropertyBag *pPropBag;
HRESULT hr = S_OK;
VARIANT var;
VariantInit(&var);
for(UINT i=0; i<pDevList->numDevice; i++)
{
DEBUGMSG(OBEX_IRDATRANSPORT_ZONE,(L"CObexIRDATransport::EnumDevices() -- found %d devices\n", pDevList->numDevice));
hr = S_OK;
pPropBag = new CPropertyBag();
if(NULL == pPropBag)
{
closesocket(s);
pPropBag->Release();
return E_OUTOFMEMORY;
}
// set the device ID
var.vt = VT_I4;
memcpy((char *)&var.lVal, pDevList->Device[i].irdaDeviceID, 4);
hr = pPropBag->Write(c_szDevicePropAddress, &var);
SVSUTIL_ASSERT(SUCCEEDED(hr));
DEBUGMSG(OBEX_IRDATRANSPORT_ZONE,(L"CObexIRDATransport::EnumDevices() -- filling in props for device\n"));
// now the name
WCHAR pszName[MAX_PATH];
int nRet = MultiByteToWideChar(CP_ACP, 0, pDevList->Device[i].irdaDeviceName, -1, pszName, MAX_PATH);
if ((nRet > 0) && (nRet < MAX_PATH))
{
VariantClear(&var);
var.vt = VT_BSTR;
var.bstrVal = SysAllocString(pszName);
if(NULL == var.bstrVal)
{
closesocket(s);
pPropBag->Release();
return E_OUTOFMEMORY;
}
hr = pPropBag->Write(c_szDevicePropName, &var);
SVSUTIL_ASSERT(SUCCEEDED(hr));
}
// finally the transport ID
LPOLESTR pszClsid = NULL;
hr = StringFromCLSID((REFCLSID) CLSID_IrdaTransport, &pszClsid);
SVSUTIL_ASSERT(SUCCEEDED(hr));
VariantClear(&var);
var.vt = VT_BSTR;
var.bstrVal = SysAllocString(pszClsid);
CoTaskMemFree(pszClsid);
hr = pPropBag->Write(c_szDevicePropTransport, &var);
SVSUTIL_ASSERT(SUCCEEDED(hr));
// add to the list
pPropEnum->Insert(pPropBag);
pPropBag->Release();
VariantClear(&var);
}
*ppDevices = pPropEnum;
closesocket(s);
return hr;
}
HRESULT STDMETHODCALLTYPE
CObexIRDATransport::UpdateDeviceProperties(LPPROPERTYBAG2 __RPC_FAR pDevice,
IPropertyBagEnum **_ppNewBagEnum,
BOOL fGetJustEnoughToConnect,
UINT *uiUpdateStatus)
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE,(L"ObexIRDATransport::UpdateDeviceProperties()\n"));
PREFAST_ASSERT(pDevice && uiUpdateStatus);
//set the default error to return
HRESULT hRet = E_FAIL;
//variables
SOCKET sMySock = INVALID_SOCKET;
BOOL fHaveIrXFer = FALSE;
BOOL fHaveObex = FALSE;
//fetch the device ID from the property bag
VARIANT pDeviceVar;
VARIANT pNameVar;
VARIANT varMarkTest;
VariantInit(&pDeviceVar);
VariantInit(&pNameVar);
VariantInit(&varMarkTest);
char pDeviceName[25];
BOOL fAbort;
//
// Do a test to see if we already have enough info (if we have been here)
//
if(SUCCEEDED(pDevice->Read(L"BeenVisited", &varMarkTest, 0)) &&
1 == varMarkTest.lVal)
{
DEBUGMSG(OBEX_IRDATRANSPORT_ZONE, (L"[OBEX] ObexIRDATransport::UpdateDeviceProperties() -- already visited!\n"));
*uiUpdateStatus = 0xFFFFFFFF;
VariantClear(&varMarkTest);
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -