|
|
#include "stdafx.h"
#include "pubwiz.h"
#pragma hdrstop
typedef struct { CLSID clsidWizard; // which wizard is being invoked
IStream *pstrmDataObj; // IDataObject marshall object
IStream *pstrmView; // IFolderView marshall object
} PUBWIZDROPINFO;
// This is the drop target object which exposes the publishing wizard
class CPubDropTarget : public IDropTarget, IPersistFile, IWizardSite, IServiceProvider, CObjectWithSite { public: CPubDropTarget(CLSID clsidWizard, IFolderView *pfv); ~CPubDropTarget();
// 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);
// IWizardSite
STDMETHODIMP GetPreviousPage(HPROPSHEETPAGE *phPage); STDMETHODIMP GetNextPage(HPROPSHEETPAGE *phPage); STDMETHODIMP GetCancelledPage(HPROPSHEETPAGE *phPage) { return GetNextPage(phPage); }
// IServiceProvider
STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void **ppv);
private: CLSID _clsidWizard; LONG _cRef;
HWND _hwndFrame;
IPublishingWizard *_ppw; IResourceMap *_prm; IUnknown *_punkFTM; IFolderView *_pfv;
TCHAR _szSiteName[MAX_PATH]; TCHAR _szSiteURL[INTERNET_MAX_URL_LENGTH];
// helpers
static void s_FreePubWizDropInfo(PUBWIZDROPINFO *ppwdi); static DWORD s_PublishThreadProc(void *pv); void _Publish(IDataObject *pdo); INT_PTR _InitDonePage(HWND hwnd); void _OpenSiteURL(); // dialog handlers
static INT_PTR s_WelcomeDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CPubDropTarget *ppdt = s_GetPDT(hwnd, uMsg, lParam); return ppdt->_WelcomeDlgProc(hwnd, uMsg, wParam, lParam); } static INT_PTR s_DoneDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CPubDropTarget *ppdt = s_GetPDT(hwnd, uMsg, lParam); return ppdt->_DoneDlgProc(hwnd, uMsg, wParam, lParam); }
static CPubDropTarget* s_GetPDT(HWND hwnd, UINT uMsg, LPARAM lParam); INT_PTR _WelcomeDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR _DoneDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
friend void PublishRunDll(HWND hwndStub, HINSTANCE hAppInstance, LPSTR pszCmdLine, int nCmdShow); };
// Construction/destruction
CPubDropTarget::CPubDropTarget(CLSID clsidWizard, IFolderView *pfv) : _clsidWizard(clsidWizard), _cRef(1) { // use the FTM to make the call back interface calls unmarshalled
CoCreateFreeThreadedMarshaler(SAFECAST(this, IDropTarget *), &_punkFTM);
// addref the IFolderView object we might be given
IUnknown_Set((IUnknown**)&_pfv, pfv);
DllAddRef(); }
CPubDropTarget::~CPubDropTarget() { ATOMICRELEASE(_punkFTM); ATOMICRELEASE(_pfv); DllRelease(); }
// Reference counting of the object
ULONG CPubDropTarget::AddRef() { return InterlockedIncrement(&_cRef); }
ULONG CPubDropTarget::Release() { if (InterlockedDecrement(&_cRef)) return _cRef;
delete this; return 0; }
HRESULT CPubDropTarget::QueryInterface(REFIID riid, void **ppv) { static const QITAB qit[] = { QITABENT(CPubDropTarget, IObjectWithSite), // IID_IObjectWithSite
QITABENT(CPubDropTarget, IWizardSite), // IID_IWizardSite
QITABENT(CPubDropTarget, IDropTarget), // IID_IDropTarget
QITABENT(CPubDropTarget, IPersistFile), // IID_IPersistFile
QITABENT(CPubDropTarget, IServiceProvider), // IID_IServiceProvider
{0, 0}, }; HRESULT hr = QISearch(this, qit, riid, ppv); if (FAILED(hr) && _punkFTM) { hr = _punkFTM->QueryInterface(riid, ppv); } return hr;
}
// retrieve the 'this' ptr for the dialog
CPubDropTarget* CPubDropTarget::s_GetPDT(HWND hwnd, UINT uMsg, LPARAM lParam) { if (uMsg == WM_INITDIALOG) { PROPSHEETPAGE *ppsp = (PROPSHEETPAGE*)lParam; SetWindowLongPtr(hwnd, GWLP_USERDATA, ppsp->lParam); return (CPubDropTarget*)ppsp->lParam; } return (CPubDropTarget*)GetWindowLongPtr(hwnd, GWLP_USERDATA); }
// Welcome dialog.
INT_PTR CPubDropTarget::_WelcomeDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: { _hwndFrame = GetParent(hwnd); SendDlgItemMessage(hwnd, IDC_PUB_WELCOME, WM_SETFONT, (WPARAM)GetIntroFont(hwnd), 0);
IXMLDOMNode *pdn; HRESULT hr = _prm->SelectResourceScope(TEXT("dialog"), TEXT("welcome"), &pdn); if (SUCCEEDED(hr)) { TCHAR szBuffer[512];
_prm->LoadString(pdn, TEXT("caption"), szBuffer, ARRAYSIZE(szBuffer)); SetDlgItemText(hwnd, IDC_PUB_WELCOME, szBuffer);
_prm->LoadString(pdn, TEXT("description"), szBuffer, ARRAYSIZE(szBuffer)); SetDlgItemText(hwnd, IDC_PUB_WELCOMEPROMPT, szBuffer);
pdn->Release(); } return TRUE; }
case WM_NOTIFY: { LPNMHDR pnmh = (LPNMHDR)lParam; switch (pnmh->code) { case PSN_SETACTIVE: { #if 0
if (_fSkipWelcome) { _fSkipWelcome = FALSE; HPROPSHEETPAGE hpage; if (SUCCEEDED(_ppw->GetFirstPage(&hpage))) { int i = PropSheet_PageToIndex(GetParent(hwnd), hpage); if (i > 0) //cannot be zero because that's our index
{ UINT_PTR id = PropSheet_IndexToId(GetParent(hwnd), i); SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LPARAM)id); } } } #endif
PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_NEXT); return TRUE; }
case PSN_WIZNEXT: { HPROPSHEETPAGE hpage; if (SUCCEEDED(_ppw->GetFirstPage(&hpage))) { PropSheet_SetCurSel(GetParent(hwnd), hpage, -1); } SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LPARAM)-1); return TRUE; } } break; } }
return FALSE; }
// layout the controls on the done page
INT_PTR CPubDropTarget::_InitDonePage(HWND hwnd) { HRESULT hrFromTransfer = E_FAIL; // default to that based on not getting any state back!
// these are the states we can read back from the manifest
BOOL fHasSiteName = FALSE; BOOL fHasNetPlace = FALSE; BOOL fHasFavorite = FALSE; BOOL fHasURL = FALSE;
// lets crack the manifest and work out whats what with the publish that
// we just performed.
IXMLDOMDocument *pdocManifest; HRESULT hr = _ppw->GetTransferManifest(&hrFromTransfer, &pdocManifest); if (SUCCEEDED(hr)) { IXMLDOMNode *pdnUploadInfo; hr = pdocManifest->selectSingleNode(XPATH_UPLOADINFO, &pdnUploadInfo); if (hr == S_OK) { IXMLDOMElement *pdel; VARIANT var;
// lets pick up the site name from the manifest, this will be an attribute on the
// upload info element.
hr = pdnUploadInfo->QueryInterface(IID_PPV_ARG(IXMLDOMElement, &pdel)); if (SUCCEEDED(hr)) { hr = pdel->getAttribute(ATTRIBUTE_FRIENDLYNAME, &var); if (hr == S_OK) { StrCpyN(_szSiteName, var.bstrVal, ARRAYSIZE(_szSiteName)); VariantClear(&var);
fHasSiteName = TRUE; }
pdel->Release(); }
// lets now try and pick up the site URL node, this is going to either
// be the file target, or HTML UI element.
IXMLDOMNode *pdnURL; hr = pdnUploadInfo->selectSingleNode(ELEMENT_HTMLUI, &pdnURL); if (hr == S_FALSE) hr = pdnUploadInfo->selectSingleNode(ELEMENT_NETPLACE, &pdnURL);
if (hr== S_FALSE) hr = pdnUploadInfo->selectSingleNode(ELEMENT_TARGET, &pdnURL);
if (hr == S_OK) { hr = pdnURL->QueryInterface(IID_PPV_ARG(IXMLDOMElement, &pdel)); if (SUCCEEDED(hr)) { // attempt to read the HREF attribute, if that is defined
// the we use it, otherwise (for compatibility with B2, we need
// to get the node text and use that instead).
hr = pdel->getAttribute(ATTRIBUTE_HREF, &var); if (hr != S_OK) hr = pdel->get_nodeTypedValue(&var);
if (hr == S_OK) { StrCpyN(_szSiteURL, var.bstrVal, ARRAYSIZE(_szSiteURL)); VariantClear(&var);
fHasURL = TRUE; // we now have the URL
}
pdel->Release(); } pdnURL->Release(); }
// lets check for the favorite - if the element is present then we assume that
// it was created.
IXMLDOMNode *pdnFavorite; hr = pdnUploadInfo->selectSingleNode(ELEMENT_FAVORITE, &pdnFavorite); if (hr == S_OK) { pdnFavorite->Release(); fHasFavorite = TRUE; }
// lets check for the net place element - if the element is present then we
// will assume it was created.
IXMLDOMNode *pdnNetPlace; hr = pdnUploadInfo->selectSingleNode(ELEMENT_NETPLACE, &pdnNetPlace); if (hr == S_OK) { pdnNetPlace->Release(); fHasNetPlace = TRUE; }
pdnUploadInfo->Release(); } pdocManifest->Release(); }
// adjust the resources on the done page to reflect the wizard that was invoked
// and more importantly the success / failure that ocurred.
IXMLDOMNode *pdn; hr = _prm->SelectResourceScope(TEXT("dialog"), TEXT("done"), &pdn); if (SUCCEEDED(hr)) { TCHAR szBuffer[384 + INTERNET_MAX_URL_LENGTH]; // enough for URL + text
_prm->LoadString(pdn, TEXT("caption"), szBuffer, ARRAYSIZE(szBuffer)); SetDlgItemText(hwnd, IDC_PUB_DONE, szBuffer);
if (hrFromTransfer == HRESULT_FROM_WIN32(ERROR_CANCELLED)) { _prm->LoadString(pdn, TEXT("cancel"), szBuffer, ARRAYSIZE(szBuffer)); } else if (FAILED(hrFromTransfer)) { _prm->LoadString(pdn, TEXT("failure"), szBuffer, ARRAYSIZE(szBuffer)); } else { TCHAR szIntro[128] = {0}; TCHAR szLink[128 +INTERNET_MAX_URL_LENGTH] = {0}; TCHAR szConclusion[128] = {0};
// get the intro text - this is common for all success pages
_prm->LoadString(pdn, TEXT("success"), szIntro, ARRAYSIZE(szIntro));
// if we have a link then we sometimes have a intro for that also
if (fHasURL) { TCHAR szFmt[MAX_PATH]; if (SUCCEEDED(_prm->LoadString(pdn, TEXT("haslink"), szFmt, ARRAYSIZE(szFmt)))) { wnsprintf(szLink, ARRAYSIZE(szLink), szFmt, fHasSiteName ? _szSiteName:_szSiteURL); } }
// then for some scenarios we have a postscript about creating favorites/netplaces
if (fHasFavorite && fHasNetPlace) { _prm->LoadString(pdn, TEXT("hasfavoriteandplace"), szConclusion, ARRAYSIZE(szConclusion)); } else if (fHasNetPlace) { _prm->LoadString(pdn, TEXT("hasplace"), szConclusion, ARRAYSIZE(szConclusion)); } else if (fHasFavorite) { _prm->LoadString(pdn, TEXT("hasfavorite"), szConclusion, ARRAYSIZE(szConclusion)); }
// format it all into one string that we can set into the control
wnsprintf(szBuffer, ARRAYSIZE(szBuffer), TEXT("%s%s%s"), szIntro, szLink, szConclusion); }
// update the message based on the strings we loaded. lets move the controls accordingly
SetDlgItemText(hwnd, IDC_PUB_COMPLETEMSG, szBuffer);
UINT ctls[] = { IDC_PUB_OPENFILES }; int dy = SizeControlFromText(hwnd, IDC_PUB_COMPLETEMSG, szBuffer); MoveControls(hwnd, ctls, ARRAYSIZE(ctls), 0, dy);
// show/hide the "open these files check" based on the URL that we might have
BOOL fShowOpen = fHasURL && SUCCEEDED(hrFromTransfer) && (_clsidWizard == CLSID_PublishDropTarget); ShowWindow(GetDlgItem(hwnd, IDC_PUB_OPENFILES), fShowOpen ? SW_SHOW:SW_HIDE); CheckDlgButton(hwnd, IDC_PUB_OPENFILES, fShowOpen);
pdn->Release(); }
// set the buttons to reflect what we can do in the wizard
PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_FINISH|PSWIZB_BACK); return TRUE; }
void CPubDropTarget::_OpenSiteURL() { SHELLEXECUTEINFO shexinfo = {0}; shexinfo.cbSize = sizeof(shexinfo); shexinfo.fMask = SEE_MASK_FLAG_NO_UI; shexinfo.nShow = SW_SHOWNORMAL; shexinfo.lpVerb = TEXT("open"); shexinfo.lpFile =_szSiteURL; ShellExecuteEx(&shexinfo); }
INT_PTR CPubDropTarget::_DoneDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch ( uMsg ) { case WM_INITDIALOG: SendDlgItemMessage(hwnd, IDC_PUB_DONE, WM_SETFONT, (WPARAM)GetIntroFont(hwnd), 0); return TRUE;
case WM_NOTIFY: { LPNMHDR pnmh = (LPNMHDR)lParam; switch (pnmh->code) { case NM_CLICK: case NM_RETURN: if (pnmh->idFrom == IDC_PUB_COMPLETEMSG) { _OpenSiteURL(); return TRUE; } break;
case PSN_SETACTIVE: return _InitDonePage(hwnd);
case PSN_WIZBACK: { HPROPSHEETPAGE hpage; if (SUCCEEDED(_ppw->GetLastPage(&hpage))) { PropSheet_SetCurSel(GetParent(hwnd), hpage, -1); } SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LPARAM)-1); return TRUE; }
case PSN_WIZFINISH: { if (IsDlgButtonChecked(hwnd, IDC_PUB_OPENFILES) == BST_CHECKED) { _OpenSiteURL(); } SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LPARAM)FALSE); return TRUE; } } break; } }
return FALSE; }
// IServiceProvider
STDMETHODIMP CPubDropTarget::QueryService(REFGUID guidService, REFIID riid, void **ppv) { if (guidService == SID_ResourceMap) { return _prm->QueryInterface(riid, ppv); } else if ((guidService == SID_SFolderView) && _pfv) { return _pfv->QueryInterface(riid, ppv); }
*ppv = NULL; return E_NOINTERFACE; }
// site object helpers, these allow nagivation back and forward in the wizard
HRESULT CPubDropTarget::GetPreviousPage(HPROPSHEETPAGE *phPage) { int i = PropSheet_IdToIndex(_hwndFrame, IDD_PUB_WELCOME); *phPage = PropSheet_IndexToPage(_hwndFrame, i); return S_OK; }
HRESULT CPubDropTarget::GetNextPage(HPROPSHEETPAGE *phPage) { int i = PropSheet_IdToIndex(_hwndFrame, IDD_PUB_DONE); *phPage = PropSheet_IndexToPage(_hwndFrame, i); return S_OK; }
// our publishing object
void CPubDropTarget::_Publish(IDataObject *pdo) { // wizard implementation
struct { LPCTSTR idPage; LPCTSTR pszPage; DWORD dwFlags; DLGPROC dlgproc; } _wizardpages[] = { {MAKEINTRESOURCE(IDD_PUB_WELCOME), TEXT("welcome"), PSP_HIDEHEADER, CPubDropTarget::s_WelcomeDlgProc}, {MAKEINTRESOURCE(IDD_PUB_DONE), TEXT("done"), PSP_HIDEHEADER, CPubDropTarget::s_DoneDlgProc}, };
// load the resource map for this instance of the wizard
HRESULT hr = CResourceMap_Initialize(L"res://netplwiz.dll/xml/resourcemap.xml", &_prm); if (SUCCEEDED(hr)) { // if this is the printing wizard then configure accordingly
// (eg. remove ADVANCED, FOLDERCREATEION and NETPLACES).
DWORD dwFlags = 0x0; LPTSTR pszWizardDefn = TEXT("PublishingWizard");
if (_clsidWizard == CLSID_InternetPrintOrdering) { dwFlags |= SHPWHF_NONETPLACECREATE|SHPWHF_NORECOMPRESS; pszWizardDefn = TEXT("InternetPhotoPrinting"); }
hr = _prm->LoadResourceMap(TEXT("wizard"), pszWizardDefn); if (SUCCEEDED(hr)) { // create the page array, we add the welcome page and the finished page
// the rest is loaded as an extension to the wizard.
HPROPSHEETPAGE hpages[10] = { 0 }; for (int cPages = 0; SUCCEEDED(hr) && (cPages < ARRAYSIZE(_wizardpages)); cPages++) { // find resource map for this page of the wizard
IXMLDOMNode *pdn; hr = _prm->SelectResourceScope(TEXT("dialog"), _wizardpages[cPages].pszPage, &pdn); if (SUCCEEDED(hr)) { TCHAR szTitle[MAX_PATH], szHeading[MAX_PATH], szSubHeading[MAX_PATH];
_prm->LoadString(pdn, TEXT("title"), szTitle, ARRAYSIZE(szTitle)); _prm->LoadString(pdn, TEXT("heading"), szHeading, ARRAYSIZE(szHeading)); _prm->LoadString(pdn, TEXT("subheading"), szSubHeading, ARRAYSIZE(szSubHeading));
PROPSHEETPAGE psp = { 0 }; psp.dwSize = sizeof(PROPSHEETPAGE); psp.hInstance = g_hinst; psp.lParam = (LPARAM)this; psp.dwFlags = PSP_USETITLE | PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE | _wizardpages[cPages].dwFlags; psp.pszTemplate = _wizardpages[cPages].idPage; psp.pfnDlgProc = _wizardpages[cPages].dlgproc; psp.pszTitle = szTitle; psp.pszHeaderTitle = szHeading; psp.pszHeaderSubTitle = szSubHeading; hpages[cPages] = CreatePropertySheetPage(&psp); hr = ((hpages[cPages]) != NULL) ? S_OK:E_FAIL;
pdn->Release(); } }
// lets create the web publishing wizard, this will handle the transfer
// and destination selection for the upload.
hr = CoCreateInstance(CLSID_PublishingWizard, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IPublishingWizard, &_ppw)); if (SUCCEEDED(hr)) { IUnknown_SetSite(_ppw, SAFECAST(this, IWizardSite*)); hr = _ppw->Initialize(pdo, dwFlags, pszWizardDefn); if (SUCCEEDED(hr)) { UINT cExtnPages; hr = _ppw->AddPages(&hpages[cPages], ARRAYSIZE(hpages)-cPages, &cExtnPages); if (SUCCEEDED(hr)) { cPages += cExtnPages; } } }
// ... that all worked so lets show the wizard. on our way our remember
// to clear up the objects
if (SUCCEEDED(hr)) { PROPSHEETHEADER psh = { 0 }; psh.dwSize = sizeof(PROPSHEETHEADER); psh.hInstance = g_hinst; psh.dwFlags = PSH_WIZARD | PSH_WIZARD97 | (PSH_WATERMARK|PSH_USEHBMWATERMARK) | (PSH_HEADER|PSH_USEHBMHEADER); psh.phpage = hpages; psh.nPages = cPages;
_prm->LoadBitmap(NULL, TEXT("header"), &psh.hbmHeader); _prm->LoadBitmap(NULL, TEXT("watermark"), &psh.hbmWatermark);
if (psh.hbmHeader && psh.hbmWatermark) PropertySheet(&psh);
if (psh.hbmHeader) DeleteObject(psh.hbmHeader); if (psh.hbmWatermark) DeleteObject(psh.hbmWatermark); }
IUnknown_SetSite(_ppw, NULL); // discard the publishing wizard
IUnknown_Set((IUnknown**)&_ppw, NULL); }
IUnknown_Set((IUnknown**)&_prm, NULL); // no more resource map
} }
// handle the drop operation, as the publishing wizard can take a long time we
// marshall the IDataObject and then create a worker thread which can
// handle showing the wizard.
void CPubDropTarget::s_FreePubWizDropInfo(PUBWIZDROPINFO *ppwdi) { if (ppwdi->pstrmDataObj) ppwdi->pstrmDataObj->Release(); if (ppwdi->pstrmView) ppwdi->pstrmView->Release();
LocalFree(ppwdi); }
DWORD CPubDropTarget::s_PublishThreadProc(void *pv) { PUBWIZDROPINFO *ppwdi = (PUBWIZDROPINFO*)pv; if (ppwdi) { // ICW must have run before we go too far down this path
LaunchICW(); // get the IDataObject, we need this to handle th drop
IDataObject *pdo; HRESULT hr = CoGetInterfaceAndReleaseStream(ppwdi->pstrmDataObj, IID_PPV_ARG(IDataObject, &pdo)); ppwdi->pstrmDataObj = NULL; // CoGetInterfaceAndReleaseStream always releases; NULL out.
if (SUCCEEDED(hr)) { // try to unmarshall the IFolderView object we will use.
IFolderView *pfv = NULL; if (ppwdi->pstrmView) { CoGetInterfaceAndReleaseStream(ppwdi->pstrmView, IID_PPV_ARG(IFolderView, &pfv)); ppwdi->pstrmView = NULL; // CoGetInterfaceAndReleaseStream always releases; NULL out.
}
CPubDropTarget *ppw = new CPubDropTarget(ppwdi->clsidWizard, pfv); if (ppw) { ppw->_Publish(pdo); ppw->Release(); } if (pfv) pfv->Release();
pdo->Release(); } s_FreePubWizDropInfo(ppwdi); } return 0; }
STDMETHODIMP CPubDropTarget::Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { 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)
PUBWIZDROPINFO *ppwdi = (PUBWIZDROPINFO*)LocalAlloc(LPTR, sizeof(PUBWIZDROPINFO)); if (ppwdi) { ppwdi->clsidWizard = _clsidWizard;
// lets get the IFolderView object and marshall it for the bg thread
IFolderView *pfv; if (SUCCEEDED(IUnknown_QueryService(_punkSite, SID_SFolderView, IID_PPV_ARG(IFolderView, &pfv)))) { CoMarshalInterThreadInterfaceInStream(IID_IFolderView, pfv, &ppwdi->pstrmView); pfv->Release(); } hr = CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pdtobj, &ppwdi->pstrmDataObj); if (SUCCEEDED(hr)) { hr = SHCreateThread(s_PublishThreadProc, ppwdi, CTF_THREAD_REF|CTF_COINIT, NULL) ? S_OK:E_FAIL; }
if (FAILED(hr)) { s_FreePubWizDropInfo(ppwdi); } } return hr; }
// create instance
STDAPI CPublishDropTarget_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi) { CPubDropTarget *pwiz = new CPubDropTarget(*poi->pclsid, NULL); if (!pwiz) { *ppunk = NULL; // incase of failure
return E_OUTOFMEMORY; }
HRESULT hr = pwiz->QueryInterface(IID_PPV_ARG(IUnknown, ppunk)); pwiz->Release(); return hr; }
// invoke the publishing wizard to point at a particular directory
void APIENTRY PublishRunDll(HWND hwndStub, HINSTANCE hAppInstance, LPSTR pszCmdLine, int nCmdShow) { HRESULT hr = CoInitialize(NULL); if (SUCCEEDED(hr)) { CLSID clsid = CLSID_PublishDropTarget; UINT csidl = CSIDL_PERSONAL;
if (0 == StrCmpIA(pszCmdLine, "/print")) { clsid = CLSID_InternetPrintOrdering; csidl = CSIDL_MYPICTURES; }
LPITEMIDLIST pidl; hr = SHGetSpecialFolderLocation(NULL, csidl, &pidl); if (SUCCEEDED(hr)) { LPCITEMIDLIST pidlChild; IShellFolder *psf; hr = SHBindToIDListParent(pidl, IID_PPV_ARG(IShellFolder, &psf), &pidlChild); if (SUCCEEDED(hr)) { IDataObject *pdo; hr = psf->GetUIObjectOf(NULL, 1, &pidlChild, IID_X_PPV_ARG(IDataObject, NULL, &pdo)); if (SUCCEEDED(hr)) { CPubDropTarget *pdt = new CPubDropTarget(clsid, NULL); if (pdt) { pdt->_Publish(pdo); pdt->Release(); } pdo->Release(); } psf->Release(); } ILFree(pidl); } CoUninitialize(); } }
|