Leaked source code of windows server 2003
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.

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