/***************************************************************************** * * (C) COPYRIGHT MICROSOFT CORPORATION, 2000 * * TITLE: drop.cpp * * VERSION: 1.0, stolen from netplwiz * * AUTHOR: RickTu * * DATE: 10/12/00 * * DESCRIPTION: IDropTarget implementation * *****************************************************************************/ #include "precomp.h" #pragma hdrstop /***************************************************************************** CPrintDropTarget class definition *****************************************************************************/ class CPrintDropTarget : public IDropTarget, IPersistFile { public: CPrintDropTarget(CLSID clsidWizard); ~CPrintDropTarget(); // IUnknown STDMETHOD(QueryInterface)(REFIID riid, void **ppvObj); STDMETHOD_(ULONG,AddRef)(void); STDMETHOD_(ULONG,Release)(void); // IPersist STDMETHODIMP GetClassID(CLSID *pClassID) { *pClassID = _clsidWizard; return S_OK; }; // IPersistFile STDMETHODIMP IsDirty(void) { return S_FALSE; }; STDMETHODIMP Load(LPCOLESTR pszFileName, DWORD dwMode) { return S_OK; }; STDMETHODIMP Save(LPCOLESTR pszFileName, BOOL fRemember) { return S_OK; }; STDMETHODIMP SaveCompleted(LPCOLESTR pszFileName) { return S_OK; }; STDMETHODIMP GetCurFile(LPOLESTR *ppszFileName) { *ppszFileName = NULL; return S_OK; }; // IDropTarget STDMETHODIMP DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { *pdwEffect = DROPEFFECT_COPY; return S_OK; }; STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { *pdwEffect = DROPEFFECT_COPY; return S_OK; }; STDMETHODIMP DragLeave(void) { return S_OK; }; STDMETHODIMP Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); private: static DWORD s_PrintPhotosThreadProc(void *pv); void _PrintPhotos(IDataObject *pdo); CLSID _clsidWizard; // instance of the wizard being invoked (publish vs. ipp) LONG _cRef; CComPtr _ppwsi; // print photos set wizard info object }; #define WIZDLG(dlg_id, name_id, title_id, dlgproc, dwFlags) \ { MAKEINTRESOURCE(##dlg_id##), dlgproc, MAKEINTRESOURCE(##name_id##), MAKEINTRESOURCE(##title_id##), dwFlags } /***************************************************************************** CPrintDropTarget Constructor/Destructor *****************************************************************************/ CPrintDropTarget::CPrintDropTarget(CLSID clsidWizard) : _clsidWizard(clsidWizard), _cRef(1) { WIA_PUSH_FUNCTION_MASK((TRACE_DROP,TEXT("CPrintDropTarget::CPrintDropTarget( this == 0x%x )"),this)); DllAddRef(); } CPrintDropTarget::~CPrintDropTarget() { WIA_PUSH_FUNCTION_MASK((TRACE_DROP,TEXT("CPrintDropTarget::~CPrintDropTarget( this == 0x%x )"),this)); DllRelease(); } /***************************************************************************** CPrintDropTarget IUnknown methods *****************************************************************************/ ULONG CPrintDropTarget::AddRef() { ULONG ul = InterlockedIncrement(&_cRef); WIA_PUSH_FUNCTION_MASK((TRACE_REF_COUNTS,TEXT("CPrintDropTarget::AddRef( new count is %d )"), ul)); return ul; } ULONG CPrintDropTarget::Release() { ULONG ul = InterlockedDecrement(&_cRef); WIA_PUSH_FUNCTION_MASK((TRACE_REF_COUNTS,TEXT("CPrintDropTarget::Release( new count is %d )"), ul)); if (ul) return ul; WIA_TRACE((TEXT("deleting CPrintDropTarget( this == 0x%x ) object"),this)); delete this; return 0; } HRESULT CPrintDropTarget::QueryInterface(REFIID riid, void **ppv) { WIA_PUSH_FUNCTION_MASK((TRACE_DROP,TEXT("CPrintDropTarget::QueryInterface()"))); static const QITAB qit[] = { QITABENT(CPrintDropTarget, IDropTarget), // IID_IDropTarget QITABENT(CPrintDropTarget, IPersistFile), // IID_IPersistFile {0, 0 }, }; HRESULT hr = QISearch(this, qit, riid, ppv); WIA_RETURN_HR(hr); } /***************************************************************************** CPrintDropTarget::_PrintPhotos Creates the wizard. *****************************************************************************/ void CPrintDropTarget::_PrintPhotos(IDataObject *pdo) { WIA_PUSH_FUNCTION_MASK((TRACE_DROP, TEXT("CPrintDropTarget::_PrintPhotos"))); CComPtr pUnk; HRESULT hr = CPrintPhotosWizard_CreateInstance(NULL, (IUnknown **)&pUnk, NULL); WIA_CHECK_HR(hr,"CPrintPhotosWizard_CreateInstance()"); if (SUCCEEDED(hr) && pUnk) { hr = pUnk->QueryInterface( IID_IPrintPhotosWizardSetInfo, (LPVOID *)&_ppwsi ); WIA_CHECK_HR(hr, "pUnk->QI( IID_IPrintPhotosWizardSetInfo )"); } // initialize the wizard with the DataObject that expressess the // files that we are going to copy to. if (SUCCEEDED(hr) && _ppwsi) { hr = _ppwsi->SetFileListDataObject( pdo ); WIA_CHECK_HR(hr,"_ppwsi->SetFileListDataObject()"); if (SUCCEEDED(hr)) { hr = _ppwsi->RunWizard(); WIA_CHECK_HR(hr,"_ppwsi->RunWizard()") } } else { WIA_ERROR((TEXT("not calling into wizard, hr = 0x%x, _ppwsi = 0x%x"),hr,_ppwsi)); } } typedef struct { CLSID clsidWizard; // which wizard is being invoked IStream *pStream; // stream for doing marshalling CPrintDropTarget *that; // copy of object pointer } PRINTWIZDROPINFO; /***************************************************************************** CPrintDropTarget::s_PrintPhotosThreadProc Thread to handle creating & running the wizard (in order to free up caller to ::Drop). *****************************************************************************/ DWORD CPrintDropTarget::s_PrintPhotosThreadProc(void *pv) { WIA_PUSH_FUNCTION_MASK((TRACE_DROP, TEXT("CPrintDropTarget::s_PrintPhotosThreadProc"))); PRINTWIZDROPINFO *ppwdi = (PRINTWIZDROPINFO*)pv; CPrintDropTarget * that = (ppwdi) ? (ppwdi->that):NULL; if (ppwdi) { WIA_PRINTGUID((ppwdi->clsidWizard,TEXT("ppwdi->_clsid ="))); CComPtr pdo; HRESULT hr = CoGetInterfaceAndReleaseStream(ppwdi->pStream, IID_PPV_ARG(IDataObject, &pdo)); WIA_CHECK_HR(hr,"CoGetInterfaceAndReleaseStream()"); if (SUCCEEDED(hr) && pdo) { that->_PrintPhotos(pdo); } delete [] ppwdi; } if (that) { that->Release(); } return 0; } /***************************************************************************** CPrintDropTarget::Drop Handle the drop operation, as the printing wizard can take a long time we marshall the IDataObject and then create a worker thread which can handle showing the wizard. *****************************************************************************/ STDMETHODIMP CPrintDropTarget::Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { WIA_PUSH_FUNCTION_MASK((TRACE_DROP, TEXT("CPrintDropTarget::Drop"))); HRESULT hr = E_OUTOFMEMORY; // create an instance of the wizard on another thread, package up any parameters // into a structure for the thread to handle (eg. the drop target) PRINTWIZDROPINFO *ppwdi = (PRINTWIZDROPINFO*) new BYTE[sizeof(PRINTWIZDROPINFO)]; if (ppwdi) { ppwdi->clsidWizard = _clsidWizard; ppwdi->that = this; hr = CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pdtobj, &ppwdi->pStream); WIA_CHECK_HR(hr,"CoMarshalInterThreadInterfaceInStream()"); if (SUCCEEDED(hr)) { // // AddRef this object so it stays around for the length of the // thread. The thread will Release() the object, unless there // is an error creating it in which case we need to release it // here... AddRef(); if (!SHCreateThread(s_PrintPhotosThreadProc, ppwdi, CTF_COINIT | CTF_FREELIBANDEXIT, NULL)) { WIA_ERROR((TEXT("SHCreateThread failed! Cleaning up."))); hr = E_FAIL; ppwdi->pStream->Release(); Release(); } } if (FAILED(hr)) delete [] ppwdi; } WIA_RETURN_HR(hr); } /***************************************************************************** CPrintPhotosDropTarget_CreateInstance Create an instance of the CPrintDropTarget specifically configured as the photo printing wizard. *****************************************************************************/ STDAPI CPrintPhotosDropTarget_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi) { WIA_PUSH_FUNCTION_MASK((TRACE_DROP, TEXT("CPrintPhotosDropTarget_CreateInstance"))); HRESULT hr = E_OUTOFMEMORY; CPrintDropTarget *pDrop = new CPrintDropTarget(*poi->pclsid); if (!pDrop) { *ppunk = NULL; // incase of failure WIA_RETURN_HR(hr); } hr = pDrop->QueryInterface(IID_PPV_ARG(IUnknown, ppunk)); pDrop->Release(); // we do this release because the new of CPrintPhotosDropTarget // set the ref count to 1, doing the QI bumps it up to 2, // and we want to leave this function with the ref count // at zero... WIA_RETURN_HR(hr); }