Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

806 lines
26 KiB

  1. #include "stdafx.h"
  2. #include "pubwiz.h"
  3. #pragma hdrstop
  4. typedef struct
  5. {
  6. CLSID clsidWizard; // which wizard is being invoked
  7. IStream *pstrmDataObj; // IDataObject marshall object
  8. IStream *pstrmView; // IFolderView marshall object
  9. } PUBWIZDROPINFO;
  10. // This is the drop target object which exposes the publishing wizard
  11. class CPubDropTarget : public IDropTarget, IPersistFile, IWizardSite, IServiceProvider, CObjectWithSite
  12. {
  13. public:
  14. CPubDropTarget(CLSID clsidWizard, IFolderView *pfv);
  15. ~CPubDropTarget();
  16. // IUnknown
  17. STDMETHOD(QueryInterface)(REFIID riid, void **ppvObj);
  18. STDMETHOD_(ULONG,AddRef)(void);
  19. STDMETHOD_(ULONG,Release)(void);
  20. // IPersist
  21. STDMETHODIMP GetClassID(CLSID *pClassID)
  22. { *pClassID = _clsidWizard; return S_OK; };
  23. // IPersistFile
  24. STDMETHODIMP IsDirty(void)
  25. { return S_FALSE; };
  26. STDMETHODIMP Load(LPCOLESTR pszFileName, DWORD dwMode)
  27. { return S_OK; };
  28. STDMETHODIMP Save(LPCOLESTR pszFileName, BOOL fRemember)
  29. { return S_OK; };
  30. STDMETHODIMP SaveCompleted(LPCOLESTR pszFileName)
  31. { return S_OK; };
  32. STDMETHODIMP GetCurFile(LPOLESTR *ppszFileName)
  33. { *ppszFileName = NULL; return S_OK; };
  34. // IDropTarget
  35. STDMETHODIMP DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  36. { *pdwEffect = DROPEFFECT_COPY; return S_OK; };
  37. STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  38. { *pdwEffect = DROPEFFECT_COPY; return S_OK; };
  39. STDMETHODIMP DragLeave(void)
  40. { return S_OK; };
  41. STDMETHODIMP Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  42. // IWizardSite
  43. STDMETHODIMP GetPreviousPage(HPROPSHEETPAGE *phPage);
  44. STDMETHODIMP GetNextPage(HPROPSHEETPAGE *phPage);
  45. STDMETHODIMP GetCancelledPage(HPROPSHEETPAGE *phPage)
  46. { return GetNextPage(phPage); }
  47. // IServiceProvider
  48. STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void **ppv);
  49. private:
  50. CLSID _clsidWizard;
  51. LONG _cRef;
  52. HWND _hwndFrame;
  53. IPublishingWizard *_ppw;
  54. IResourceMap *_prm;
  55. IUnknown *_punkFTM;
  56. IFolderView *_pfv;
  57. TCHAR _szSiteName[MAX_PATH];
  58. TCHAR _szSiteURL[INTERNET_MAX_URL_LENGTH];
  59. // helpers
  60. static void s_FreePubWizDropInfo(PUBWIZDROPINFO *ppwdi);
  61. static DWORD s_PublishThreadProc(void *pv);
  62. void _Publish(IDataObject *pdo);
  63. INT_PTR _InitDonePage(HWND hwnd);
  64. void _OpenSiteURL();
  65. // dialog handlers
  66. static INT_PTR s_WelcomeDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  67. { CPubDropTarget *ppdt = s_GetPDT(hwnd, uMsg, lParam); return ppdt->_WelcomeDlgProc(hwnd, uMsg, wParam, lParam); }
  68. static INT_PTR s_DoneDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  69. { CPubDropTarget *ppdt = s_GetPDT(hwnd, uMsg, lParam); return ppdt->_DoneDlgProc(hwnd, uMsg, wParam, lParam); }
  70. static CPubDropTarget* s_GetPDT(HWND hwnd, UINT uMsg, LPARAM lParam);
  71. INT_PTR _WelcomeDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  72. INT_PTR _DoneDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  73. friend void PublishRunDll(HWND hwndStub, HINSTANCE hAppInstance, LPSTR pszCmdLine, int nCmdShow);
  74. };
  75. // Construction/destruction
  76. CPubDropTarget::CPubDropTarget(CLSID clsidWizard, IFolderView *pfv) :
  77. _clsidWizard(clsidWizard), _cRef(1)
  78. {
  79. // use the FTM to make the call back interface calls unmarshalled
  80. CoCreateFreeThreadedMarshaler(SAFECAST(this, IDropTarget *), &_punkFTM);
  81. // addref the IFolderView object we might be given
  82. IUnknown_Set((IUnknown**)&_pfv, pfv);
  83. DllAddRef();
  84. }
  85. CPubDropTarget::~CPubDropTarget()
  86. {
  87. ATOMICRELEASE(_punkFTM);
  88. ATOMICRELEASE(_pfv);
  89. DllRelease();
  90. }
  91. // Reference counting of the object
  92. ULONG CPubDropTarget::AddRef()
  93. {
  94. return InterlockedIncrement(&_cRef);
  95. }
  96. ULONG CPubDropTarget::Release()
  97. {
  98. if (InterlockedDecrement(&_cRef))
  99. return _cRef;
  100. delete this;
  101. return 0;
  102. }
  103. HRESULT CPubDropTarget::QueryInterface(REFIID riid, void **ppv)
  104. {
  105. static const QITAB qit[] =
  106. {
  107. QITABENT(CPubDropTarget, IObjectWithSite), // IID_IObjectWithSite
  108. QITABENT(CPubDropTarget, IWizardSite), // IID_IWizardSite
  109. QITABENT(CPubDropTarget, IDropTarget), // IID_IDropTarget
  110. QITABENT(CPubDropTarget, IPersistFile), // IID_IPersistFile
  111. QITABENT(CPubDropTarget, IServiceProvider), // IID_IServiceProvider
  112. {0, 0},
  113. };
  114. HRESULT hr = QISearch(this, qit, riid, ppv);
  115. if (FAILED(hr) && _punkFTM)
  116. {
  117. hr = _punkFTM->QueryInterface(riid, ppv);
  118. }
  119. return hr;
  120. }
  121. // retrieve the 'this' ptr for the dialog
  122. CPubDropTarget* CPubDropTarget::s_GetPDT(HWND hwnd, UINT uMsg, LPARAM lParam)
  123. {
  124. if (uMsg == WM_INITDIALOG)
  125. {
  126. PROPSHEETPAGE *ppsp = (PROPSHEETPAGE*)lParam;
  127. SetWindowLongPtr(hwnd, GWLP_USERDATA, ppsp->lParam);
  128. return (CPubDropTarget*)ppsp->lParam;
  129. }
  130. return (CPubDropTarget*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  131. }
  132. // Welcome dialog.
  133. INT_PTR CPubDropTarget::_WelcomeDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  134. {
  135. switch (uMsg)
  136. {
  137. case WM_INITDIALOG:
  138. {
  139. _hwndFrame = GetParent(hwnd);
  140. SendDlgItemMessage(hwnd, IDC_PUB_WELCOME, WM_SETFONT, (WPARAM)GetIntroFont(hwnd), 0);
  141. IXMLDOMNode *pdn;
  142. HRESULT hr = _prm->SelectResourceScope(TEXT("dialog"), TEXT("welcome"), &pdn);
  143. if (SUCCEEDED(hr))
  144. {
  145. TCHAR szBuffer[512];
  146. _prm->LoadString(pdn, TEXT("caption"), szBuffer, ARRAYSIZE(szBuffer));
  147. SetDlgItemText(hwnd, IDC_PUB_WELCOME, szBuffer);
  148. _prm->LoadString(pdn, TEXT("description"), szBuffer, ARRAYSIZE(szBuffer));
  149. SetDlgItemText(hwnd, IDC_PUB_WELCOMEPROMPT, szBuffer);
  150. pdn->Release();
  151. }
  152. return TRUE;
  153. }
  154. case WM_NOTIFY:
  155. {
  156. LPNMHDR pnmh = (LPNMHDR)lParam;
  157. switch (pnmh->code)
  158. {
  159. case PSN_SETACTIVE:
  160. {
  161. #if 0
  162. if (_fSkipWelcome)
  163. {
  164. _fSkipWelcome = FALSE;
  165. HPROPSHEETPAGE hpage;
  166. if (SUCCEEDED(_ppw->GetFirstPage(&hpage)))
  167. {
  168. int i = PropSheet_PageToIndex(GetParent(hwnd), hpage);
  169. if (i > 0) //cannot be zero because that's our index
  170. {
  171. UINT_PTR id = PropSheet_IndexToId(GetParent(hwnd), i);
  172. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LPARAM)id);
  173. }
  174. }
  175. }
  176. #endif
  177. PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_NEXT);
  178. return TRUE;
  179. }
  180. case PSN_WIZNEXT:
  181. {
  182. HPROPSHEETPAGE hpage;
  183. if (SUCCEEDED(_ppw->GetFirstPage(&hpage)))
  184. {
  185. PropSheet_SetCurSel(GetParent(hwnd), hpage, -1);
  186. }
  187. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LPARAM)-1);
  188. return TRUE;
  189. }
  190. }
  191. break;
  192. }
  193. }
  194. return FALSE;
  195. }
  196. // layout the controls on the done page
  197. INT_PTR CPubDropTarget::_InitDonePage(HWND hwnd)
  198. {
  199. HRESULT hrFromTransfer = E_FAIL; // default to that based on not getting any state back!
  200. // these are the states we can read back from the manifest
  201. BOOL fHasSiteName = FALSE;
  202. BOOL fHasNetPlace = FALSE;
  203. BOOL fHasFavorite = FALSE;
  204. BOOL fHasURL = FALSE;
  205. // lets crack the manifest and work out whats what with the publish that
  206. // we just performed.
  207. IXMLDOMDocument *pdocManifest;
  208. HRESULT hr = _ppw->GetTransferManifest(&hrFromTransfer, &pdocManifest);
  209. if (SUCCEEDED(hr))
  210. {
  211. IXMLDOMNode *pdnUploadInfo;
  212. hr = pdocManifest->selectSingleNode(XPATH_UPLOADINFO, &pdnUploadInfo);
  213. if (hr == S_OK)
  214. {
  215. IXMLDOMElement *pdel;
  216. VARIANT var;
  217. // lets pick up the site name from the manifest, this will be an attribute on the
  218. // upload info element.
  219. hr = pdnUploadInfo->QueryInterface(IID_PPV_ARG(IXMLDOMElement, &pdel));
  220. if (SUCCEEDED(hr))
  221. {
  222. hr = pdel->getAttribute(ATTRIBUTE_FRIENDLYNAME, &var);
  223. if (hr == S_OK)
  224. {
  225. StrCpyN(_szSiteName, var.bstrVal, ARRAYSIZE(_szSiteName));
  226. VariantClear(&var);
  227. fHasSiteName = TRUE;
  228. }
  229. pdel->Release();
  230. }
  231. // lets now try and pick up the site URL node, this is going to either
  232. // be the file target, or HTML UI element.
  233. IXMLDOMNode *pdnURL;
  234. hr = pdnUploadInfo->selectSingleNode(ELEMENT_HTMLUI, &pdnURL);
  235. if (hr == S_FALSE)
  236. hr = pdnUploadInfo->selectSingleNode(ELEMENT_NETPLACE, &pdnURL);
  237. if (hr== S_FALSE)
  238. hr = pdnUploadInfo->selectSingleNode(ELEMENT_TARGET, &pdnURL);
  239. if (hr == S_OK)
  240. {
  241. hr = pdnURL->QueryInterface(IID_PPV_ARG(IXMLDOMElement, &pdel));
  242. if (SUCCEEDED(hr))
  243. {
  244. // attempt to read the HREF attribute, if that is defined
  245. // the we use it, otherwise (for compatibility with B2, we need
  246. // to get the node text and use that instead).
  247. hr = pdel->getAttribute(ATTRIBUTE_HREF, &var);
  248. if (hr != S_OK)
  249. hr = pdel->get_nodeTypedValue(&var);
  250. if (hr == S_OK)
  251. {
  252. StrCpyN(_szSiteURL, var.bstrVal, ARRAYSIZE(_szSiteURL));
  253. VariantClear(&var);
  254. fHasURL = TRUE; // we now have the URL
  255. }
  256. pdel->Release();
  257. }
  258. pdnURL->Release();
  259. }
  260. // lets check for the favorite - if the element is present then we assume that
  261. // it was created.
  262. IXMLDOMNode *pdnFavorite;
  263. hr = pdnUploadInfo->selectSingleNode(ELEMENT_FAVORITE, &pdnFavorite);
  264. if (hr == S_OK)
  265. {
  266. pdnFavorite->Release();
  267. fHasFavorite = TRUE;
  268. }
  269. // lets check for the net place element - if the element is present then we
  270. // will assume it was created.
  271. IXMLDOMNode *pdnNetPlace;
  272. hr = pdnUploadInfo->selectSingleNode(ELEMENT_NETPLACE, &pdnNetPlace);
  273. if (hr == S_OK)
  274. {
  275. pdnNetPlace->Release();
  276. fHasNetPlace = TRUE;
  277. }
  278. pdnUploadInfo->Release();
  279. }
  280. pdocManifest->Release();
  281. }
  282. // adjust the resources on the done page to reflect the wizard that was invoked
  283. // and more importantly the success / failure that ocurred.
  284. IXMLDOMNode *pdn;
  285. hr = _prm->SelectResourceScope(TEXT("dialog"), TEXT("done"), &pdn);
  286. if (SUCCEEDED(hr))
  287. {
  288. TCHAR szBuffer[384 + INTERNET_MAX_URL_LENGTH]; // enough for URL + text
  289. _prm->LoadString(pdn, TEXT("caption"), szBuffer, ARRAYSIZE(szBuffer));
  290. SetDlgItemText(hwnd, IDC_PUB_DONE, szBuffer);
  291. if (hrFromTransfer == HRESULT_FROM_WIN32(ERROR_CANCELLED))
  292. {
  293. _prm->LoadString(pdn, TEXT("cancel"), szBuffer, ARRAYSIZE(szBuffer));
  294. }
  295. else if (FAILED(hrFromTransfer))
  296. {
  297. _prm->LoadString(pdn, TEXT("failure"), szBuffer, ARRAYSIZE(szBuffer));
  298. }
  299. else
  300. {
  301. TCHAR szIntro[128] = {0};
  302. TCHAR szLink[128 +INTERNET_MAX_URL_LENGTH] = {0};
  303. TCHAR szConclusion[128] = {0};
  304. // get the intro text - this is common for all success pages
  305. _prm->LoadString(pdn, TEXT("success"), szIntro, ARRAYSIZE(szIntro));
  306. // if we have a link then we sometimes have a intro for that also
  307. if (fHasURL)
  308. {
  309. TCHAR szFmt[MAX_PATH];
  310. if (SUCCEEDED(_prm->LoadString(pdn, TEXT("haslink"), szFmt, ARRAYSIZE(szFmt))))
  311. {
  312. wnsprintf(szLink, ARRAYSIZE(szLink), szFmt, fHasSiteName ? _szSiteName:_szSiteURL);
  313. }
  314. }
  315. // then for some scenarios we have a postscript about creating favorites/netplaces
  316. if (fHasFavorite && fHasNetPlace)
  317. {
  318. _prm->LoadString(pdn, TEXT("hasfavoriteandplace"), szConclusion, ARRAYSIZE(szConclusion));
  319. }
  320. else if (fHasNetPlace)
  321. {
  322. _prm->LoadString(pdn, TEXT("hasplace"), szConclusion, ARRAYSIZE(szConclusion));
  323. }
  324. else if (fHasFavorite)
  325. {
  326. _prm->LoadString(pdn, TEXT("hasfavorite"), szConclusion, ARRAYSIZE(szConclusion));
  327. }
  328. // format it all into one string that we can set into the control
  329. wnsprintf(szBuffer, ARRAYSIZE(szBuffer), TEXT("%s%s%s"), szIntro, szLink, szConclusion);
  330. }
  331. // update the message based on the strings we loaded. lets move the controls accordingly
  332. SetDlgItemText(hwnd, IDC_PUB_COMPLETEMSG, szBuffer);
  333. UINT ctls[] = { IDC_PUB_OPENFILES };
  334. int dy = SizeControlFromText(hwnd, IDC_PUB_COMPLETEMSG, szBuffer);
  335. MoveControls(hwnd, ctls, ARRAYSIZE(ctls), 0, dy);
  336. // show/hide the "open these files check" based on the URL that we might have
  337. BOOL fShowOpen = fHasURL && SUCCEEDED(hrFromTransfer) && (_clsidWizard == CLSID_PublishDropTarget);
  338. ShowWindow(GetDlgItem(hwnd, IDC_PUB_OPENFILES), fShowOpen ? SW_SHOW:SW_HIDE);
  339. CheckDlgButton(hwnd, IDC_PUB_OPENFILES, fShowOpen);
  340. pdn->Release();
  341. }
  342. // set the buttons to reflect what we can do in the wizard
  343. PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_FINISH|PSWIZB_BACK);
  344. return TRUE;
  345. }
  346. void CPubDropTarget::_OpenSiteURL()
  347. {
  348. SHELLEXECUTEINFO shexinfo = {0};
  349. shexinfo.cbSize = sizeof(shexinfo);
  350. shexinfo.fMask = SEE_MASK_FLAG_NO_UI;
  351. shexinfo.nShow = SW_SHOWNORMAL;
  352. shexinfo.lpVerb = TEXT("open");
  353. shexinfo.lpFile =_szSiteURL;
  354. ShellExecuteEx(&shexinfo);
  355. }
  356. INT_PTR CPubDropTarget::_DoneDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  357. {
  358. switch ( uMsg )
  359. {
  360. case WM_INITDIALOG:
  361. SendDlgItemMessage(hwnd, IDC_PUB_DONE, WM_SETFONT, (WPARAM)GetIntroFont(hwnd), 0);
  362. return TRUE;
  363. case WM_NOTIFY:
  364. {
  365. LPNMHDR pnmh = (LPNMHDR)lParam;
  366. switch (pnmh->code)
  367. {
  368. case NM_CLICK:
  369. case NM_RETURN:
  370. if (pnmh->idFrom == IDC_PUB_COMPLETEMSG)
  371. {
  372. _OpenSiteURL();
  373. return TRUE;
  374. }
  375. break;
  376. case PSN_SETACTIVE:
  377. return _InitDonePage(hwnd);
  378. case PSN_WIZBACK:
  379. {
  380. HPROPSHEETPAGE hpage;
  381. if (SUCCEEDED(_ppw->GetLastPage(&hpage)))
  382. {
  383. PropSheet_SetCurSel(GetParent(hwnd), hpage, -1);
  384. }
  385. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LPARAM)-1);
  386. return TRUE;
  387. }
  388. case PSN_WIZFINISH:
  389. {
  390. if (IsDlgButtonChecked(hwnd, IDC_PUB_OPENFILES) == BST_CHECKED)
  391. {
  392. _OpenSiteURL();
  393. }
  394. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LPARAM)FALSE);
  395. return TRUE;
  396. }
  397. }
  398. break;
  399. }
  400. }
  401. return FALSE;
  402. }
  403. // IServiceProvider
  404. STDMETHODIMP CPubDropTarget::QueryService(REFGUID guidService, REFIID riid, void **ppv)
  405. {
  406. if (guidService == SID_ResourceMap)
  407. {
  408. return _prm->QueryInterface(riid, ppv);
  409. }
  410. else if ((guidService == SID_SFolderView) && _pfv)
  411. {
  412. return _pfv->QueryInterface(riid, ppv);
  413. }
  414. *ppv = NULL;
  415. return E_NOINTERFACE;
  416. }
  417. // site object helpers, these allow nagivation back and forward in the wizard
  418. HRESULT CPubDropTarget::GetPreviousPage(HPROPSHEETPAGE *phPage)
  419. {
  420. int i = PropSheet_IdToIndex(_hwndFrame, IDD_PUB_WELCOME);
  421. *phPage = PropSheet_IndexToPage(_hwndFrame, i);
  422. return S_OK;
  423. }
  424. HRESULT CPubDropTarget::GetNextPage(HPROPSHEETPAGE *phPage)
  425. {
  426. int i = PropSheet_IdToIndex(_hwndFrame, IDD_PUB_DONE);
  427. *phPage = PropSheet_IndexToPage(_hwndFrame, i);
  428. return S_OK;
  429. }
  430. // our publishing object
  431. void CPubDropTarget::_Publish(IDataObject *pdo)
  432. {
  433. // wizard implementation
  434. struct
  435. {
  436. LPCTSTR idPage;
  437. LPCTSTR pszPage;
  438. DWORD dwFlags;
  439. DLGPROC dlgproc;
  440. }
  441. _wizardpages[] =
  442. {
  443. {MAKEINTRESOURCE(IDD_PUB_WELCOME), TEXT("welcome"), PSP_HIDEHEADER, CPubDropTarget::s_WelcomeDlgProc},
  444. {MAKEINTRESOURCE(IDD_PUB_DONE), TEXT("done"), PSP_HIDEHEADER, CPubDropTarget::s_DoneDlgProc},
  445. };
  446. // load the resource map for this instance of the wizard
  447. HRESULT hr = CResourceMap_Initialize(L"res://netplwiz.dll/xml/resourcemap.xml", &_prm);
  448. if (SUCCEEDED(hr))
  449. {
  450. // if this is the printing wizard then configure accordingly
  451. // (eg. remove ADVANCED, FOLDERCREATEION and NETPLACES).
  452. DWORD dwFlags = 0x0;
  453. LPTSTR pszWizardDefn = TEXT("PublishingWizard");
  454. if (_clsidWizard == CLSID_InternetPrintOrdering)
  455. {
  456. dwFlags |= SHPWHF_NONETPLACECREATE|SHPWHF_NORECOMPRESS;
  457. pszWizardDefn = TEXT("InternetPhotoPrinting");
  458. }
  459. hr = _prm->LoadResourceMap(TEXT("wizard"), pszWizardDefn);
  460. if (SUCCEEDED(hr))
  461. {
  462. // create the page array, we add the welcome page and the finished page
  463. // the rest is loaded as an extension to the wizard.
  464. HPROPSHEETPAGE hpages[10] = { 0 };
  465. for (int cPages = 0; SUCCEEDED(hr) && (cPages < ARRAYSIZE(_wizardpages)); cPages++)
  466. {
  467. // find resource map for this page of the wizard
  468. IXMLDOMNode *pdn;
  469. hr = _prm->SelectResourceScope(TEXT("dialog"), _wizardpages[cPages].pszPage, &pdn);
  470. if (SUCCEEDED(hr))
  471. {
  472. TCHAR szTitle[MAX_PATH], szHeading[MAX_PATH], szSubHeading[MAX_PATH];
  473. _prm->LoadString(pdn, TEXT("title"), szTitle, ARRAYSIZE(szTitle));
  474. _prm->LoadString(pdn, TEXT("heading"), szHeading, ARRAYSIZE(szHeading));
  475. _prm->LoadString(pdn, TEXT("subheading"), szSubHeading, ARRAYSIZE(szSubHeading));
  476. PROPSHEETPAGE psp = { 0 };
  477. psp.dwSize = sizeof(PROPSHEETPAGE);
  478. psp.hInstance = g_hinst;
  479. psp.lParam = (LPARAM)this;
  480. psp.dwFlags = PSP_USETITLE | PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE | _wizardpages[cPages].dwFlags;
  481. psp.pszTemplate = _wizardpages[cPages].idPage;
  482. psp.pfnDlgProc = _wizardpages[cPages].dlgproc;
  483. psp.pszTitle = szTitle;
  484. psp.pszHeaderTitle = szHeading;
  485. psp.pszHeaderSubTitle = szSubHeading;
  486. hpages[cPages] = CreatePropertySheetPage(&psp);
  487. hr = ((hpages[cPages]) != NULL) ? S_OK:E_FAIL;
  488. pdn->Release();
  489. }
  490. }
  491. // lets create the web publishing wizard, this will handle the transfer
  492. // and destination selection for the upload.
  493. hr = CoCreateInstance(CLSID_PublishingWizard, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IPublishingWizard, &_ppw));
  494. if (SUCCEEDED(hr))
  495. {
  496. IUnknown_SetSite(_ppw, SAFECAST(this, IWizardSite*));
  497. hr = _ppw->Initialize(pdo, dwFlags, pszWizardDefn);
  498. if (SUCCEEDED(hr))
  499. {
  500. UINT cExtnPages;
  501. hr = _ppw->AddPages(&hpages[cPages], ARRAYSIZE(hpages)-cPages, &cExtnPages);
  502. if (SUCCEEDED(hr))
  503. {
  504. cPages += cExtnPages;
  505. }
  506. }
  507. }
  508. // ... that all worked so lets show the wizard. on our way our remember
  509. // to clear up the objects
  510. if (SUCCEEDED(hr))
  511. {
  512. PROPSHEETHEADER psh = { 0 };
  513. psh.dwSize = sizeof(PROPSHEETHEADER);
  514. psh.hInstance = g_hinst;
  515. psh.dwFlags = PSH_WIZARD | PSH_WIZARD97 | (PSH_WATERMARK|PSH_USEHBMWATERMARK) | (PSH_HEADER|PSH_USEHBMHEADER);
  516. psh.phpage = hpages;
  517. psh.nPages = cPages;
  518. _prm->LoadBitmap(NULL, TEXT("header"), &psh.hbmHeader);
  519. _prm->LoadBitmap(NULL, TEXT("watermark"), &psh.hbmWatermark);
  520. if (psh.hbmHeader && psh.hbmWatermark)
  521. PropertySheet(&psh);
  522. if (psh.hbmHeader)
  523. DeleteObject(psh.hbmHeader);
  524. if (psh.hbmWatermark)
  525. DeleteObject(psh.hbmWatermark);
  526. }
  527. IUnknown_SetSite(_ppw, NULL); // discard the publishing wizard
  528. IUnknown_Set((IUnknown**)&_ppw, NULL);
  529. }
  530. IUnknown_Set((IUnknown**)&_prm, NULL); // no more resource map
  531. }
  532. }
  533. // handle the drop operation, as the publishing wizard can take a long time we
  534. // marshall the IDataObject and then create a worker thread which can
  535. // handle showing the wizard.
  536. void CPubDropTarget::s_FreePubWizDropInfo(PUBWIZDROPINFO *ppwdi)
  537. {
  538. if (ppwdi->pstrmDataObj)
  539. ppwdi->pstrmDataObj->Release();
  540. if (ppwdi->pstrmView)
  541. ppwdi->pstrmView->Release();
  542. LocalFree(ppwdi);
  543. }
  544. DWORD CPubDropTarget::s_PublishThreadProc(void *pv)
  545. {
  546. PUBWIZDROPINFO *ppwdi = (PUBWIZDROPINFO*)pv;
  547. if (ppwdi)
  548. {
  549. // ICW must have run before we go too far down this path
  550. LaunchICW();
  551. // get the IDataObject, we need this to handle th drop
  552. IDataObject *pdo;
  553. HRESULT hr = CoGetInterfaceAndReleaseStream(ppwdi->pstrmDataObj, IID_PPV_ARG(IDataObject, &pdo));
  554. ppwdi->pstrmDataObj = NULL; // CoGetInterfaceAndReleaseStream always releases; NULL out.
  555. if (SUCCEEDED(hr))
  556. {
  557. // try to unmarshall the IFolderView object we will use.
  558. IFolderView *pfv = NULL;
  559. if (ppwdi->pstrmView)
  560. {
  561. CoGetInterfaceAndReleaseStream(ppwdi->pstrmView, IID_PPV_ARG(IFolderView, &pfv));
  562. ppwdi->pstrmView = NULL; // CoGetInterfaceAndReleaseStream always releases; NULL out.
  563. }
  564. CPubDropTarget *ppw = new CPubDropTarget(ppwdi->clsidWizard, pfv);
  565. if (ppw)
  566. {
  567. ppw->_Publish(pdo);
  568. ppw->Release();
  569. }
  570. if (pfv)
  571. pfv->Release();
  572. pdo->Release();
  573. }
  574. s_FreePubWizDropInfo(ppwdi);
  575. }
  576. return 0;
  577. }
  578. STDMETHODIMP CPubDropTarget::Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  579. {
  580. HRESULT hr = E_OUTOFMEMORY;
  581. // create an instance of the wizard on another thread, package up any parameters
  582. // into a structure for the thread to handle (eg. the drop target)
  583. PUBWIZDROPINFO *ppwdi = (PUBWIZDROPINFO*)LocalAlloc(LPTR, sizeof(PUBWIZDROPINFO));
  584. if (ppwdi)
  585. {
  586. ppwdi->clsidWizard = _clsidWizard;
  587. // lets get the IFolderView object and marshall it for the bg thread
  588. IFolderView *pfv;
  589. if (SUCCEEDED(IUnknown_QueryService(_punkSite, SID_SFolderView, IID_PPV_ARG(IFolderView, &pfv))))
  590. {
  591. CoMarshalInterThreadInterfaceInStream(IID_IFolderView, pfv, &ppwdi->pstrmView);
  592. pfv->Release();
  593. }
  594. hr = CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pdtobj, &ppwdi->pstrmDataObj);
  595. if (SUCCEEDED(hr))
  596. {
  597. hr = SHCreateThread(s_PublishThreadProc, ppwdi, CTF_THREAD_REF|CTF_COINIT, NULL) ? S_OK:E_FAIL;
  598. }
  599. if (FAILED(hr))
  600. {
  601. s_FreePubWizDropInfo(ppwdi);
  602. }
  603. }
  604. return hr;
  605. }
  606. // create instance
  607. STDAPI CPublishDropTarget_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  608. {
  609. CPubDropTarget *pwiz = new CPubDropTarget(*poi->pclsid, NULL);
  610. if (!pwiz)
  611. {
  612. *ppunk = NULL; // incase of failure
  613. return E_OUTOFMEMORY;
  614. }
  615. HRESULT hr = pwiz->QueryInterface(IID_PPV_ARG(IUnknown, ppunk));
  616. pwiz->Release();
  617. return hr;
  618. }
  619. // invoke the publishing wizard to point at a particular directory
  620. void APIENTRY PublishRunDll(HWND hwndStub, HINSTANCE hAppInstance, LPSTR pszCmdLine, int nCmdShow)
  621. {
  622. HRESULT hr = CoInitialize(NULL);
  623. if (SUCCEEDED(hr))
  624. {
  625. CLSID clsid = CLSID_PublishDropTarget;
  626. UINT csidl = CSIDL_PERSONAL;
  627. if (0 == StrCmpIA(pszCmdLine, "/print"))
  628. {
  629. clsid = CLSID_InternetPrintOrdering;
  630. csidl = CSIDL_MYPICTURES;
  631. }
  632. LPITEMIDLIST pidl;
  633. hr = SHGetSpecialFolderLocation(NULL, csidl, &pidl);
  634. if (SUCCEEDED(hr))
  635. {
  636. LPCITEMIDLIST pidlChild;
  637. IShellFolder *psf;
  638. hr = SHBindToIDListParent(pidl, IID_PPV_ARG(IShellFolder, &psf), &pidlChild);
  639. if (SUCCEEDED(hr))
  640. {
  641. IDataObject *pdo;
  642. hr = psf->GetUIObjectOf(NULL, 1, &pidlChild, IID_X_PPV_ARG(IDataObject, NULL, &pdo));
  643. if (SUCCEEDED(hr))
  644. {
  645. CPubDropTarget *pdt = new CPubDropTarget(clsid, NULL);
  646. if (pdt)
  647. {
  648. pdt->_Publish(pdo);
  649. pdt->Release();
  650. }
  651. pdo->Release();
  652. }
  653. psf->Release();
  654. }
  655. ILFree(pidl);
  656. }
  657. CoUninitialize();
  658. }
  659. }