📄 obexftp.cpp
字号:
{
return TRUE;
}
else
{
m_obex=NULL;
ATLTRACE(_T("Cannot Advise!\n"));
}
}
else
{
m_obex=NULL;
ATLTRACE(_T("Cannot IObex::Initialize!\n"));
}
}
#ifdef _DEBUG
else
{
ATLTRACE(_T("Cannot CoCreate IObex!\n"));
}
#endif
}
return FALSE;
}
//-------------------------------------------------------------------
// CObexFTP::StartDeviceEnum - start asynchronous events via IObexSink
//-------------------------------------------------------------------
BOOL CObexFTP::StartDeviceEnumeration()
{
if (!m_bEnumerating)
{
if (m_obex)
{
if (SUCCEEDED(m_obex->StartDeviceEnum()))
m_bEnumerating=true;
}
}
return m_bEnumerating;
}
//-------------------------------------------------------------------
// CObexFTP::StopDeviceEnum - stop asynchronous events via IObexSink
//-------------------------------------------------------------------
void CObexFTP::StopDeviceEnumeration()
{
if (m_bEnumerating)
{
ATLASSERT((IObex *)m_obex);
m_obex->StopDeviceEnum();
m_bEnumerating=false;
}
}
//-------------------------------------------------------------------
// CObexFTP::IObexSink::IUnknown::Addref - std implementation
//-------------------------------------------------------------------
ULONG CObexFTP::AddRef()
{
ULONG cr=InterlockedIncrement(&m_cRef);
return cr;
}
//-------------------------------------------------------------------
// CObexFTP::IObexSink::IUnknown::Release - std implementation
//-------------------------------------------------------------------
ULONG CObexFTP::Release()
{
ULONG cr=InterlockedDecrement(&m_cRef);
ATLASSERT(m_cRef);
return cr;
}
//-------------------------------------------------------------------
// CObexFTP::IObexSink::IUnknown::QueryInterface - std implementation
//-------------------------------------------------------------------
HRESULT CObexFTP::QueryInterface(REFIID iid,void ** ppvObject)
{
if (InlineIsEqualGUID(iid, IID_IObexSink) ||
InlineIsEqualUnknown(iid))
{
if (ppvObject == NULL)
return E_POINTER;
*ppvObject = (void*)(IUnknown*)this;
AddRef();
return S_OK;
}
*ppvObject=NULL;
return E_NOINTERFACE;
}
//-------------------------------------------------------------------
// CObexFTP::IObexSink::IUnknown::QueryInterface - std implementation
//-------------------------------------------------------------------
HRESULT CObexFTP::Notify(OBEX_EVENT Event,IUnknown* pUnk1,IUnknown* /*pUnk2*/)
{
// Create a helper object for property access
CObexDeviceProperties dev(pUnk1);
ATLASSERT((IPropertyBag *)dev);
if (dev)
{
// build a unique key from Address+ServiceUUID
CString Key=dev.GetAddress();
Key+=dev.GetServices();
// and determine if this device supports OBEX-FTP
bool IsFTP=dev.CanFTP();
// if it does - see if its already connected
if (IsFTP)
{
CObexFTPConnection *pConn;
pConn=FindConnection(Key);
if (pConn)
{
// if yes - call the appropriate handler
ATLASSERT(Event!=OE_DEVICE_ARRIVAL);
if (Event==OE_DEVICE_UPDATE)
OnDeviceChange(pConn,dev);
else
OnDeviceRemoval(pConn);
}
else if (Event!=OE_DEVICE_DEPARTURE)
{
// no this a new one
OnDeviceArrived(dev);
}
}
}
return S_OK;
}
//-------------------------------------------------------------------
// CObexFTP::OnDeviceArrived - should be overridden !
//-------------------------------------------------------------------
void CObexFTP::OnDeviceArrived(IPropertyBag *Bag)
{
}
//-------------------------------------------------------------------
// CObexFTP::OnDeviceRemoval - call pConn->OnDeviceRemoval
//-------------------------------------------------------------------
void CObexFTP::OnDeviceRemoval(CObexFTPConnection *pConn)
{
ATLASSERT(pConn);
if (pConn)
pConn->OnDeviceRemoval();
}
//-------------------------------------------------------------------
// CObexFTP::OnDeviceChange - call pConn->OnDeviceChange
//-------------------------------------------------------------------
void CObexFTP::OnDeviceChange(CObexFTPConnection *pConn,IPropertyBag *Prop)
{
ATLASSERT(pConn);
if (pConn)
pConn->OnDeviceChange(Prop);
}
// This is the ServiceUUID of the Obex-FTP in network order
GUID CLSID_FileExchange_NetOrder = // {F9ec7bc4-953c-11d2-984e-525400dc9e09}
{ 0xc47becf9, 0x3c95, 0xd211, {0x98, 0x4e, 0x52, 0x54, 0x00, 0xdc, 0x9e, 0x09}};
//-------------------------------------------------------------------
// CObexFTP::Connect() - called only from friend CObexFTPConnection
//-------------------------------------------------------------------
BOOL CObexFTP::Connect(CObexFTPConnection *pConn,IPropertyBag *Prop,IObexDevice **ppOut)
{
// first we must bind the properties to a device
if (m_obex)
{
CComPtr<IObexDevice> Dev;
if (SUCCEEDED(m_obex->BindToDevice(Prop,&Dev)))
{
// Set the password if required
const CString &Password=pConn->GetPassword();
if (!Password.IsEmpty())
Dev->SetPassword(Password);
// then connect to proper Service
CComPtr<IHeaderCollection> Coll;
if (SUCCEEDED(Coll.CoCreateInstance(__uuidof(HeaderCollection))))
{
if (SUCCEEDED(Coll->AddTarget(sizeof(CLSID_FileExchange_NetOrder),(BYTE *)&CLSID_FileExchange_NetOrder)))
{
// Question: do we need the password here, if it's already set in SetPassword ?
// is the dwCap parameter of any interest for any server ?
if (SUCCEEDED(Dev->Connect(Password,OBEX_DEVICE_CAP_FILE_BROWSE,Coll)))
{
// NOTE: may be SUCCEDED is not enough; WINCE samples re-enumerate the HeaderCollection,
// try to find a CONNECTION_ID-Header and only report success if it is found ?
*ppOut=Dev.Detach();
// build the unique key
CObexDeviceProperties odp(Prop);
CString Key=odp.GetAddress();
Key+=odp.GetServices();
pConn->SetKey(Key);
// and add to our active list
AddConnection(pConn);
return TRUE;
}
}
}
}
}
return FALSE;
}
BOOL CObexFTP::Disconnect(CObexFTPConnection *pConn)
{
// simply unlink from our list of connections
return m_Connections.Unlink(pConn)!=NULL;
}
//-------------------------------------------------------------------
// CObexFTP::ConnectTo
// use this function if you do not want to use derived classes
// for CObexFTPConnection
//-------------------------------------------------------------------
CObexFTPConnection *CObexFTP::ConnectTo(IPropertyBag *Prop,LPCWSTR pszPassw/*=NULL*/)
{
CObexFTPConnection *pConn=new CObexFTPConnection(pszPassw);
if (!pConn->Connect(this,Prop))
{
delete pConn;
pConn=NULL;
}
return pConn;
}
//-------------------------------------------------------------------
// CObexFTP::Connect management: find a connection with unique id
//-------------------------------------------------------------------
CObexFTPConnection *CObexFTP::FindConnection(const CString &Key)
{
return m_Connections.Find(Key);
}
//-------------------------------------------------------------------
// CObexFTP::Connect management: add a connection to the list
//-------------------------------------------------------------------
void CObexFTP::AddConnection(CObexFTPConnection *pConn)
{
m_Connections.Push(pConn);
}
//-------------------------------------------------------------------
// CObexFTPConnection ctor
// the optional password is used during connect if the server
// requires this
//-------------------------------------------------------------------
CObexFTPConnection::CObexFTPConnection(LPCWSTR pszPassw/*=NULL*/)
: m_strPassw(pszPassw),m_pNext(NULL),m_pObj(NULL)
{
}
//-------------------------------------------------------------------
// CObexFTPConnection dtor
//-------------------------------------------------------------------
CObexFTPConnection::~CObexFTPConnection()
{
// if still connected, disconnect
Disconnect();
}
//-------------------------------------------------------------------
// CObexFTPConnection::OnDeviceRemoval
// should be overwritten to cancel operation an close
//-------------------------------------------------------------------
void CObexFTPConnection::OnDeviceRemoval()
{
}
//-------------------------------------------------------------------
// CObexFTPConnection::OnDeviceChange
// could be overwritten to reread saved properties etc.
//-------------------------------------------------------------------
void CObexFTPConnection::OnDeviceChange(IPropertyBag* /*Bag*/)
{
}
//-------------------------------------------------------------------
// CObexFTPConnection::GetDeviceName
// ask the device for its propertybag and the query the name
//-------------------------------------------------------------------
CString CObexFTPConnection::GetDeviceName()
{
CObexDeviceProperties Prop(m_device);
return Prop.GetName();
}
//-------------------------------------------------------------------
// CObexFTPConnection::Connect
// typically called in CObexFTP::OnDeviceArrived
// call CObexFTP::Connect to do the work
//-------------------------------------------------------------------
BOOL CObexFTPConnection::Connect(CObexFTP *pObj,IPropertyBag *Bag)
{
if (pObj->Connect(this,Bag,&m_device))
{
m_pObj=pObj;
return TRUE;
}
return FALSE;
}
//-------------------------------------------------------------------
// CObexFTPConnection::Disconnect
// call this function if you are done with the connection
// only delete a connection after Disconnect!
//-------------------------------------------------------------------
CObexFTPConnection *CObexFTPConnection::Disconnect(bool bAutoDel/*=false*/)
{
if (m_device)
{
CComPtr<IHeaderCollection> Coll;
Coll.CoCreateInstance(__uuidof(HeaderCollection));
m_device->Disconnect(Coll);
m_device=NULL;
}
if (m_pObj)
{
CObexFTP *pParent=m_pObj;
m_pObj=NULL;
pParent->Disconnect(this);
}
if (bAutoDel)
{
delete this;
return NULL;
}
return this;
}
//-------------------------------------------------------------------
// CObexFTPConnection::SetPath - set the Server-Path
// NOTE: the server path is always relative so pszPath cannot contain
// \\ characters! you can use NULL to go back to the root or use
// dwFlags=SETPATH_FLAG_BACKUP to simulate a cd ..
// use dwFlags=SETPATH_FLAG_DONT_CREATE if you only want to read
//-------------------------------------------------------------------
BOOL CObexFTPConnection::SetPath(LPCWSTR pszPath,DWORD dwFlags/*=0*/)
{
if (m_device)
return SUCCEEDED(m_device->SetPath(pszPath,dwFlags,NULL));
else
return FALSE;
}
//-------------------------------------------------------------------
// CObexFTPConnection::GetFile - get a file from the current server
// path and store it in a Memory file
// use SetPath before for nested folders
//-------------------------------------------------------------------
BOOL CObexFTPConnection::GetFile(LPCWSTR pszName,CStreamToMemory &Mem)
{
if (m_device)
{
return GetFileOrDir(pszName,NULL,Mem);
}
else
{
return FALSE;
}
}
//-------------------------------------------------------------------
// CObexFTPConnection::PutFile - send data as a file to the current
// server path
// use SetPath before for nested folders
//-------------------------------------------------------------------
BOOL CObexFTPConnection::PutFile(LPCWSTR pszName,void *Data,UINT Size)
{
if (m_device)
{
CComPtr<IHeaderCollection> Coll;
if (SUCCEEDED(Coll.CoCreateInstance(__uuidof(HeaderCollection))))
{
if (SUCCEEDED(Coll->AddName(pszName)) &&
SUCCEEDED(Coll->AddLength(Size)))
{
CComPtr<IStream> Stream;
if (SUCCEEDED(m_device->Put(Coll,&Stream)))
{
DWORD Written=0;
if (SUCCEEDED(Stream->Write(Data,Size,&Written)) &&
SUCCEEDED(Stream->Commit(0)))
{
return TRUE;
}
}
}
}
}
return FALSE;
}
//-------------------------------------------------------------------
// CObexFTPConnection::GetDirectory - retrieve the content of the
// current server path
// use SetPath before for nested folders
// see member FindFirstFile, FindNextFile of CObexListing
//-------------------------------------------------------------------
BOOL CObexFTPConnection::GetDirectory(CObexListing &Dir)
{
if (m_device)
{
return GetFileOrDir(_T(""),"x-obex/folder-listing",Dir);
}
else
{
return FALSE;
}
}
//-------------------------------------------------------------------
// CObexFTPConnection::GetFileOrDir
// helper function for GetFile and GetDirectory
//-------------------------------------------------------------------
BOOL CObexFTPConnection::GetFileOrDir(LPCWSTR pszName,const char *mime,CStreamToMemory &Mem)
{
ATLASSERT(m_device);
CComPtr<IHeaderCollection> Coll;
if (SUCCEEDED(Coll.CoCreateInstance(__uuidof(HeaderCollection))))
{
if (SUCCEEDED(Coll->AddName(pszName)))
{
int mime_len=mime ? strlen(mime) : 0;
if (mime_len==0 || SUCCEEDED(Coll->AddType(mime_len+1,(BYTE *)mime)))
{
CComPtr<IStream> Stream;
if (SUCCEEDED(m_device->Get(Coll,&Stream)))
{
return Mem.Read(Stream);
}
}
}
}
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -