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.

1612 lines
46 KiB

  1. #include "privcpp.h"
  2. #define CPP_FUNCTIONS
  3. // #include <crtfree.h>
  4. UINT g_cfFileContents;
  5. UINT g_cfFileDescriptor;
  6. UINT g_cfObjectDescriptor;
  7. UINT g_cfEmbedSource;
  8. UINT g_cfFileNameW;
  9. INT g_cxIcon;
  10. INT g_cyIcon;
  11. INT g_cxArrange;
  12. INT g_cyArrange;
  13. HFONT g_hfontTitle;
  14. BOOL gCmdLineOK = FALSE; // this global flag will (eventually) be set by security policy in packager constructor
  15. static TCHAR szUserType[] = TEXT("Package");
  16. static TCHAR szDefTempFile[] = TEXT("PKG");
  17. DEFINE_GUID(SID_targetGUID, 0xc7b318a8, 0xfc2c, 0x47e6, 0x8b, 0x2, 0x46, 0xa9, 0xc, 0xc9, 0x1b, 0x43);
  18. CPackage::CPackage() :
  19. _cRef(1)
  20. {
  21. DebugMsg(DM_TRACE, "pack - CPackage() called.");
  22. g_cRefThisDll++;
  23. // Excel v.5 - v2000 has a hosting bug when they host an object as a link.
  24. // They always remove their hpmbed->hpobj object, yet all their methods
  25. // on the IOleClientSite interface they give us dereference this and fault.
  26. //
  27. _fNoIOleClientSiteCalls = FALSE;
  28. TCHAR szProcess[MAX_PATH];
  29. if (GetModuleFileName(NULL, szProcess, ARRAYSIZE(szProcess)) &&
  30. !lstrcmp(TEXT("EXCEL.EXE"), PathFindFileName(szProcess)))
  31. {
  32. DWORD dwVersionSize = GetFileVersionInfoSize(szProcess, 0);
  33. char * pVersionBuffer = new char[dwVersionSize];
  34. GetFileVersionInfo(szProcess, 0, ARRAYSIZE(szProcess), pVersionBuffer);
  35. VS_FIXEDFILEINFO * pVersionInfo;
  36. UINT dwVerLen;
  37. BOOL result = VerQueryValue(pVersionBuffer, L"\\", (LPVOID *) &pVersionInfo, &dwVerLen);
  38. if(result)
  39. {
  40. if(pVersionInfo->dwFileVersionLS < 0x0a0000)
  41. _fNoIOleClientSiteCalls = TRUE;
  42. else
  43. _fNoIOleClientSiteCalls = FALSE; // Except that they fixed it in version 10.
  44. }
  45. else
  46. {
  47. _fNoIOleClientSiteCalls = TRUE;
  48. }
  49. delete [] pVersionBuffer;
  50. }
  51. ASSERT(_cf == 0);
  52. ASSERT(_panetype == NOTHING);
  53. }
  54. CPackage::~CPackage()
  55. {
  56. DebugMsg(DM_TRACE, "pack - ~CPackage() called.");
  57. // We should never be destroyed unless our ref count is zero.
  58. ASSERT(_cRef == 0);
  59. g_cRefThisDll--;
  60. // Destroy the packaged file structure...
  61. //
  62. _DestroyIC();
  63. // we destroy depending on which type of object we had packaged
  64. switch(_panetype)
  65. {
  66. case PEMBED:
  67. if (_pEmbed->pszTempName)
  68. {
  69. DeleteFile(_pEmbed->pszTempName);
  70. delete [] _pEmbed->pszTempName;
  71. }
  72. delete _pEmbed;
  73. break;
  74. case CMDLINK:
  75. delete _pCml;
  76. break;
  77. }
  78. // Release Advise pointers...
  79. //
  80. if (_pIDataAdviseHolder)
  81. _pIDataAdviseHolder->Release();
  82. if (_pIOleAdviseHolder)
  83. _pIOleAdviseHolder->Release();
  84. if (_pIOleClientSite)
  85. _pIOleClientSite->Release();
  86. delete [] _lpszContainerApp;
  87. delete [] _lpszContainerObj;
  88. ReleaseContextMenu();
  89. if (NULL != _pVerbs)
  90. {
  91. for (ULONG i = 0; i < _cVerbs; i++)
  92. {
  93. delete _pVerbs[i].lpszVerbName;
  94. }
  95. delete _pVerbs;
  96. }
  97. DebugMsg(DM_TRACE,"CPackage being destroyed. _cRef == %d",_cRef);
  98. }
  99. HRESULT CPackage::Init()
  100. {
  101. //
  102. // initializes parts of a package object that have a potential to fail
  103. // return: S_OK -- everything initialized
  104. // E_FAIL -- error in initialzation
  105. // E_OUTOFMEMORY -- out of memory
  106. //
  107. DebugMsg(DM_TRACE, "pack - Init() called.");
  108. // Get some system metrics that we'll need later...
  109. //
  110. LOGFONT lf;
  111. SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, FALSE);
  112. SystemParametersInfo(SPI_ICONHORIZONTALSPACING, 0, &g_cxArrange, FALSE);
  113. SystemParametersInfo(SPI_ICONVERTICALSPACING, 0, &g_cyArrange, FALSE);
  114. g_cxIcon = GetSystemMetrics(SM_CXICON);
  115. g_cyIcon = GetSystemMetrics(SM_CYICON);
  116. g_hfontTitle = CreateFontIndirect(&lf);
  117. // register some clipboard formats that we support...
  118. //
  119. g_cfFileContents = RegisterClipboardFormat(CFSTR_FILECONTENTS);
  120. g_cfFileDescriptor = RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);
  121. g_cfObjectDescriptor= RegisterClipboardFormat(CFSTR_OBJECTDESCRIPTOR);
  122. g_cfEmbedSource = RegisterClipboardFormat(CFSTR_EMBEDSOURCE);
  123. g_cfFileNameW = RegisterClipboardFormat(TEXT("FileNameW"));
  124. // Get the value of the group policy (if it exists) for the "Software\Policies\Microsoft\Packager -- AllowCommandLinePackages key
  125. DWORD dwAllowCL = 0;
  126. DWORD dwDataType;
  127. DWORD dwcb = sizeof(DWORD);
  128. if(ERROR_SUCCESS == SHGetValue(
  129. HKEY_CURRENT_USER,
  130. L"Software\\Policies\\Microsoft\\Packager",
  131. L"AllowCommandLinePackages",
  132. &dwDataType,
  133. &dwAllowCL,
  134. &dwcb))
  135. {
  136. if(REG_DWORD == dwDataType && dwAllowCL)
  137. {
  138. gCmdLineOK = TRUE;
  139. }
  140. }
  141. // Initialize a generic icon
  142. _lpic = IconCreate();
  143. _IconRefresh();
  144. return S_OK;
  145. }
  146. ////////////////////////////////////////////////////////////////////////
  147. //
  148. // IUnknown Methods...
  149. //
  150. ////////////////////////////////////////////////////////////////////////
  151. HRESULT CPackage::QueryInterface(REFIID riid, void ** ppv)
  152. {
  153. DebugMsg(DM_TRACE, "pack - QueryInterface() called.");
  154. static const QITAB qit[] =
  155. {
  156. QITABENT(CPackage, IOleObject),
  157. QITABENT(CPackage, IViewObject),
  158. QITABENT(CPackage, IViewObject2),
  159. QITABENT(CPackage, IDataObject),
  160. QITABENT(CPackage, IPersistStorage),
  161. QITABENT(CPackage, IPersistFile),
  162. QITABENT(CPackage, IAdviseSink),
  163. QITABENT(CPackage, IRunnableObject),
  164. QITABENT(CPackage, IEnumOLEVERB),
  165. QITABENT(CPackage, IOleCommandTarget),
  166. QITABENT(CPackage, IOleCache),
  167. QITABENT(CPackage, IExternalConnection),
  168. { 0 },
  169. };
  170. HRESULT hr = QISearch(this, qit, riid, ppv);
  171. if(FAILED(hr))
  172. {
  173. DebugMsg(DM_TRACE, "pack - QueryInterface() failed! .");
  174. }
  175. return hr;
  176. }
  177. ULONG CPackage::AddRef()
  178. {
  179. _cRef++;
  180. return _cRef;
  181. }
  182. ULONG CPackage::Release()
  183. {
  184. DebugMsg(DM_TRACE, "pack - Release() called.");
  185. ULONG cRef = InterlockedDecrement( &_cRef );
  186. if ( 0 == cRef )
  187. {
  188. delete this;
  189. }
  190. return cRef;
  191. }
  192. HRESULT CPackage_CreateInstance(LPUNKNOWN * ppunk)
  193. {
  194. HRESULT hr = S_OK;
  195. DebugMsg(DM_TRACE, "pack - CreateInstance called");
  196. *ppunk = NULL; // null the out param
  197. CPackage* pPack = new CPackage;
  198. if (!pPack)
  199. hr = E_OUTOFMEMORY;
  200. else
  201. {
  202. if (FAILED(pPack->Init())) {
  203. delete pPack;
  204. hr = E_OUTOFMEMORY;
  205. }
  206. }
  207. if(SUCCEEDED(hr))
  208. {
  209. hr = pPack->QueryInterface(IID_IUnknown, (void **) ppunk);
  210. pPack->Release();
  211. }
  212. return hr;
  213. }
  214. STDMETHODIMP CPackage::Next(ULONG celt, OLEVERB* rgVerbs, ULONG* pceltFetched)
  215. {
  216. DebugMsg(DM_TRACE, "Next called");
  217. HRESULT hr;
  218. if (NULL != rgVerbs)
  219. {
  220. if (1 == celt)
  221. {
  222. if (_nCurVerb < _cVerbs)
  223. {
  224. ASSERT(NULL != _pVerbs);
  225. *rgVerbs = _pVerbs[_nCurVerb];
  226. if ((NULL != _pVerbs[_nCurVerb].lpszVerbName))
  227. {
  228. DWORD cch = lstrlenW(_pVerbs[_nCurVerb].lpszVerbName) + 1;
  229. if(NULL != (rgVerbs->lpszVerbName = (LPWSTR) CoTaskMemAlloc(cch * SIZEOF(WCHAR))))
  230. {
  231. StringCchCopy(rgVerbs->lpszVerbName, cch, _pVerbs[_nCurVerb].lpszVerbName);
  232. }
  233. }
  234. _nCurVerb++;
  235. hr = S_OK;
  236. }
  237. else
  238. {
  239. hr = S_FALSE;
  240. }
  241. if (NULL != pceltFetched)
  242. {
  243. *pceltFetched = (S_OK == hr) ? 1 : 0;
  244. }
  245. }
  246. else if (NULL != pceltFetched)
  247. {
  248. int cVerbsToCopy = min(celt, _cVerbs - _nCurVerb);
  249. if (cVerbsToCopy > 0)
  250. {
  251. ASSERT(NULL != _pVerbs);
  252. CopyMemory(rgVerbs, &(_pVerbs[_nCurVerb]), cVerbsToCopy * sizeof(OLEVERB));
  253. for (int i = 0; i < cVerbsToCopy; i++)
  254. {
  255. if ((NULL != _pVerbs[_nCurVerb + i].lpszVerbName))
  256. {
  257. DWORD cch = lstrlenW(_pVerbs[_nCurVerb + i].lpszVerbName) + 1;
  258. if(NULL != (rgVerbs[i].lpszVerbName = (LPWSTR) CoTaskMemAlloc(cch * SIZEOF(WCHAR))))
  259. {
  260. StringCchCopy(rgVerbs[i].lpszVerbName, cch, _pVerbs[_nCurVerb + i].lpszVerbName);
  261. }
  262. else
  263. return E_OUTOFMEMORY;
  264. }
  265. }
  266. _nCurVerb += cVerbsToCopy;
  267. }
  268. *pceltFetched = (ULONG) cVerbsToCopy;
  269. hr = (celt == (ULONG) cVerbsToCopy) ? S_OK : S_FALSE;
  270. }
  271. else
  272. {
  273. hr = E_INVALIDARG;
  274. }
  275. }
  276. else
  277. {
  278. hr = E_INVALIDARG;
  279. }
  280. return hr;
  281. }
  282. STDMETHODIMP CPackage::Skip(ULONG celt)
  283. {
  284. DebugMsg(DM_TRACE, "Skip called");
  285. HRESULT hr = S_OK;
  286. if (_nCurVerb + celt > _cVerbs)
  287. {
  288. // there aren't enough elements, go to the end and return S_FALSE
  289. _nCurVerb = _cVerbs;
  290. hr = S_FALSE;
  291. }
  292. else
  293. {
  294. _nCurVerb += celt;
  295. }
  296. return hr;
  297. }
  298. STDMETHODIMP CPackage::Reset()
  299. {
  300. DebugMsg(DM_TRACE, "pack - Reset() called.");
  301. _nCurVerb = 0;
  302. return S_OK;
  303. }
  304. STDMETHODIMP CPackage::Clone(IEnumOLEVERB** ppEnum)
  305. {
  306. DebugMsg(DM_TRACE, "pack - Clone() called.");
  307. if (NULL != ppEnum)
  308. {
  309. *ppEnum = NULL;
  310. }
  311. return E_NOTIMPL;
  312. }
  313. ///////////////////////////////////////////////////////////////////
  314. //
  315. // Package helper functions
  316. //
  317. ///////////////////////////////////////////////////////////////////
  318. HRESULT CPackage::EmbedInitFromFile(LPCTSTR lpFileName, BOOL fInitFile)
  319. {
  320. DebugMsg(DM_TRACE, "pack - EmbedInitFromFile() called.");
  321. //
  322. // get's the file size of the packaged file and set's the name
  323. // of the packaged file if fInitFile == TRUE.
  324. // return: S_OK -- initialized ok
  325. // E_FAIL -- error initializing file
  326. //
  327. DWORD dwSize;
  328. // if this is the first time we've been called, then we need to allocate
  329. // memory for the _pEmbed structure
  330. if (_pEmbed == NULL)
  331. {
  332. _pEmbed = new EMBED;
  333. if (_pEmbed)
  334. {
  335. _pEmbed->pszTempName = NULL;
  336. _pEmbed->hTask = NULL;
  337. _pEmbed->poo = NULL;
  338. _pEmbed->fIsOleFile = TRUE;
  339. }
  340. }
  341. if (_pEmbed == NULL)
  342. return E_OUTOFMEMORY;
  343. // open the file to package...
  344. //
  345. HANDLE fh = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READWRITE,
  346. NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  347. if (fh == INVALID_HANDLE_VALUE)
  348. {
  349. DWORD dwError = GetLastError();
  350. return E_FAIL;
  351. }
  352. _panetype = PEMBED;
  353. // Get the size of the file
  354. _pEmbed->fd.nFileSizeLow = GetFileSize(fh, &dwSize);
  355. if (_pEmbed->fd.nFileSizeLow == 0xFFFFFFFF)
  356. {
  357. DWORD dwError = GetLastError();
  358. return E_FAIL;
  359. }
  360. ASSERT(dwSize == 0);
  361. _pEmbed->fd.nFileSizeHigh = 0L;
  362. _pEmbed->fd.dwFlags = FD_FILESIZE;
  363. // We only want to set the filename if this is the file to be packaged.
  364. // If it's only a temp file that we're reloading (fInitFile == FALSE) then
  365. // don't bother setting the filename.
  366. //
  367. if (fInitFile)
  368. {
  369. StringCchCopy(_pEmbed->fd.cFileName, ARRAYSIZE(_pEmbed->fd.cFileName), lpFileName);
  370. _DestroyIC();
  371. _lpic = _IconCreateFromFile(lpFileName);
  372. if (_pIDataAdviseHolder)
  373. _pIDataAdviseHolder->SendOnDataChange(this,0, NULL);
  374. if (_pViewSink)
  375. _pViewSink->OnViewChange(_dwViewAspects,_dwViewAdvf);
  376. }
  377. _fIsDirty = TRUE;
  378. CloseHandle(fh);
  379. return S_OK;
  380. }
  381. HRESULT CPackage::CmlInitFromFile(LPTSTR lpFileName, BOOL fUpdateIcon, PANETYPE paneType)
  382. {
  383. DebugMsg(DM_TRACE, "pack - CmlINitFromFile() called.");
  384. // if this is the first time we've been called, then we need to allocate
  385. // memory for the _pCml structure
  386. if (_pCml == NULL)
  387. {
  388. _pCml = new CML;
  389. if (_pCml)
  390. {
  391. // we don't use this, but an old packager accessing us might.
  392. _pCml->fCmdIsLink = FALSE;
  393. }
  394. }
  395. if (_pCml == NULL)
  396. return E_OUTOFMEMORY;
  397. _panetype = paneType;
  398. StringCchCopy(_pCml->szCommandLine, ARRAYSIZE(_pCml->szCommandLine), lpFileName);
  399. _fIsDirty = TRUE;
  400. if (fUpdateIcon)
  401. {
  402. _DestroyIC();
  403. _lpic = _IconCreateFromFile(lpFileName);
  404. if (_pIDataAdviseHolder)
  405. _pIDataAdviseHolder->SendOnDataChange(this, 0, NULL);
  406. if (_pViewSink)
  407. _pViewSink->OnViewChange(_dwViewAspects, _dwViewAdvf);
  408. }
  409. return S_OK;
  410. }
  411. HRESULT CPackage::InitFromPackInfo(LPPACKAGER_INFO lppi)
  412. {
  413. DebugMsg(DM_TRACE, "pack - InitFromPackInfo() called.");
  414. HRESULT hr = E_FAIL;
  415. // Ok, we need to test whether the user tried to package a folder
  416. // instead of a file. If s/he did, then we'll just create a link
  417. // to that folder instead of an embedded file.
  418. //
  419. if (lppi->bUseCommandLine)
  420. {
  421. hr = CmlInitFromFile(lppi->szFilename, FALSE, CMDLINK);
  422. }
  423. else
  424. {
  425. // we pass FALSE here, because we don't want to write the icon
  426. hr = EmbedInitFromFile(lppi->szFilename, FALSE);
  427. StringCchCopy(_pEmbed->fd.cFileName, ARRAYSIZE(_pEmbed->fd.cFileName), lppi->szFilename);
  428. _panetype = PEMBED;
  429. }
  430. if(!SUCCEEDED(hr))
  431. return hr;
  432. // set the icon information
  433. if (PathFileExists(lppi->szFilename))
  434. {
  435. StringCchCopy(_lpic->szIconPath, ARRAYSIZE(_lpic->szIconPath), *lppi->szIconPath? lppi->szIconPath : lppi->szFilename);
  436. }
  437. _lpic->iDlgIcon = lppi->iIcon;
  438. StringCchCopy(_lpic->szIconText, ARRAYSIZE(_lpic->szIconText), lppi->szLabel);
  439. _IconRefresh();
  440. // we need to tell the client we want to be saved...it should be smart
  441. // enough to do it anyway, but we can't take any chances.
  442. if (_pIOleClientSite)
  443. _pIOleClientSite->SaveObject();
  444. return hr;
  445. }
  446. HRESULT CPackage::CreateTempFileName()
  447. {
  448. ASSERT(NULL != _pEmbed);
  449. TCHAR szDefPath[MAX_PATH];
  450. if (_pEmbed->pszTempName)
  451. {
  452. return S_OK;
  453. }
  454. else if (GetTempPath(ARRAYSIZE(szDefPath), szDefPath))
  455. {
  456. LPTSTR pszFile;
  457. pszFile = PathFindFileName(_pEmbed->fd.cFileName);
  458. if(!PathAppend(szDefPath, pszFile))
  459. return E_FAIL;
  460. HRESULT hr;
  461. if (PathFileExists(szDefPath))
  462. {
  463. TCHAR szOriginal[MAX_PATH];
  464. StringCchCopy(szOriginal, ARRAYSIZE(szOriginal), szDefPath);
  465. hr = PathYetAnotherMakeUniqueName(szDefPath, szOriginal, NULL, NULL)
  466. ? S_OK
  467. : E_FAIL;
  468. }
  469. else
  470. {
  471. hr = S_OK;
  472. }
  473. if (SUCCEEDED(hr))
  474. {
  475. DWORD cch = lstrlen(szDefPath) + 1;
  476. _pEmbed->pszTempName = new TCHAR[cch];
  477. if (!_pEmbed->pszTempName)
  478. {
  479. DebugMsg(DM_TRACE," couldn't alloc memory for pszTempName!!");
  480. return E_OUTOFMEMORY;
  481. }
  482. StringCchCopy(_pEmbed->pszTempName, cch, szDefPath);
  483. }
  484. return hr;
  485. }
  486. else
  487. {
  488. DebugMsg(DM_TRACE," couldn't get temp path!!");
  489. return E_FAIL;
  490. }
  491. }
  492. HRESULT CPackage::CreateTempFile(bool deleteExisting)
  493. {
  494. //
  495. // used to create a temporary file that holds the file contents of the
  496. // packaged file. the old packager used to keep the packaged file in
  497. // memory which is just a total waste. so, being as we're much more
  498. // efficient, we create a temp file whenever someone wants to do something
  499. // with our contents. we initialze the temp file from the original file
  500. // to package or our persistent storage depending on whether we are a new
  501. // package or a loaded package
  502. // return: S_OK -- temp file created
  503. // E_FAIL -- error creating temp file
  504. //
  505. DebugMsg(DM_TRACE," CreateTempFile() called.");
  506. HRESULT hr = CreateTempFileName();
  507. if (FAILED(hr))
  508. {
  509. return hr;
  510. }
  511. if (_pEmbed->pszTempName && PathFileExists(_pEmbed->pszTempName))
  512. {
  513. DebugMsg(DM_TRACE," already have a temp file!!");
  514. if(!deleteExisting)
  515. return S_OK;
  516. else
  517. {
  518. DeleteFile(_pEmbed->pszTempName);
  519. }
  520. }
  521. // if we weren't loaded from a storage then we're in the process of
  522. // creating a package, and should be able to copy the packaged file
  523. // to create a temp file
  524. //
  525. if (!_fLoaded)
  526. {
  527. if (!(CopyFile(_pEmbed->fd.cFileName, _pEmbed->pszTempName, FALSE)))
  528. {
  529. DebugMsg(DM_TRACE," couldn't copy file!!");
  530. return E_FAIL;
  531. }
  532. }
  533. else
  534. {
  535. // nothing to do, we've already loaded it. temp file must exist
  536. ASSERT(_pEmbed);
  537. ASSERT(_pEmbed->pszTempName);
  538. }
  539. // whenever we create a tempfile we are activating the contents which
  540. // means we are dirty until we get a save message
  541. return S_OK;
  542. }
  543. ///////////////////////////////////////////////////////////////////////
  544. //
  545. // Data Transfer Functions
  546. //
  547. ///////////////////////////////////////////////////////////////////////
  548. HRESULT CPackage::GetFileDescriptor(LPFORMATETC pFE, LPSTGMEDIUM pSTM)
  549. {
  550. DebugMsg(DM_TRACE, "pack - GetFileDescriptor called");
  551. FILEGROUPDESCRIPTOR *pfgd;
  552. HRESULT hr = S_OK;
  553. DebugMsg(DM_TRACE," Getting File Descriptor");
  554. // we only support HGLOBAL at this time
  555. //
  556. if (!(pFE->tymed & TYMED_HGLOBAL)) {
  557. DebugMsg(DM_TRACE," does not support HGLOBAL!");
  558. return DATA_E_FORMATETC;
  559. }
  560. //// Copy file descriptor to HGLOBAL ///////////////////////////
  561. //
  562. pSTM->tymed = TYMED_HGLOBAL;
  563. // render the file descriptor
  564. if (!(pfgd = (FILEGROUPDESCRIPTOR *)GlobalAlloc(GPTR,
  565. sizeof(FILEGROUPDESCRIPTOR))))
  566. return E_OUTOFMEMORY;
  567. pSTM->hGlobal = pfgd;
  568. pfgd->cItems = 1;
  569. switch(_panetype)
  570. {
  571. case PEMBED:
  572. pfgd->fgd[0] = _pEmbed->fd;
  573. GetDisplayName(pfgd->fgd[0].cFileName, _pEmbed->fd.cFileName); // This is packagers, not the shell (for now)
  574. break;
  575. case CMDLINK:
  576. // the label for the package will serve as the filename for the
  577. // shortcut we're going to create.
  578. hr = StringCchCopy(pfgd->fgd[0].cFileName, ARRAYSIZE(pfgd->fgd[0].cFileName), _lpic->szIconText);
  579. // harcoded use of .lnk extension!!
  580. if(SUCCEEDED(hr))
  581. {
  582. hr = StringCchCat(pfgd->fgd[0].cFileName, ARRAYSIZE(pfgd->fgd[0].cFileName), TEXT(".lnk"));
  583. }
  584. // we want to add the little arrow to the shortcut.
  585. pfgd->fgd[0].dwFlags = FD_LINKUI;
  586. break;
  587. }
  588. return hr;
  589. }
  590. HRESULT CPackage::GetFileContents(LPFORMATETC pFE, LPSTGMEDIUM pSTM)
  591. {
  592. void * lpvDest = NULL;
  593. DWORD dwSize;
  594. HANDLE hFile = NULL;
  595. HRESULT hr = E_FAIL;
  596. DebugMsg(DM_TRACE," Getting File Contents");
  597. //// Copy file contents to ISTREAM ///////////////////////////
  598. //
  599. // NOTE: Hopefully, everyone using our object supports TYMED_ISTREAM,
  600. // otherwise we could get some really slow behavior. We might later
  601. // want to implement TYMED_ISTORAGE as well and shove our file contents
  602. // into a single stream named CONTENTS.
  603. //
  604. if (pFE->tymed & TYMED_ISTREAM)
  605. {
  606. DWORD dwFileLength;
  607. DebugMsg(DM_TRACE," using TYMED_ISTREAM");
  608. pSTM->tymed = TYMED_ISTREAM;
  609. hr = CreateStreamOnHGlobal(NULL, TRUE, &pSTM->pstm);
  610. if (SUCCEEDED(hr))
  611. {
  612. switch (_panetype)
  613. {
  614. case PEMBED:
  615. hr = CopyFileToStream(_pEmbed->pszTempName, pSTM->pstm, &dwFileLength);
  616. break;
  617. case CMDLINK:
  618. hr = CreateShortcutOnStream(pSTM->pstm);
  619. break;
  620. }
  621. }
  622. if (FAILED(hr))
  623. {
  624. pSTM->pstm->Release();
  625. pSTM->pstm = NULL;
  626. }
  627. return hr;
  628. }
  629. //// Copy file contents to HGLOBAL ///////////////////////////
  630. //
  631. // NOTE: This is really icky and could potentially be very slow if
  632. // somebody decides to package really large files. Hopefully,
  633. // everyone should be able to get the info it wants through TYMED_ISTREAM,
  634. // but this is here as a common denominator
  635. //
  636. if (pFE->tymed & TYMED_HGLOBAL)
  637. {
  638. DebugMsg(DM_TRACE," using TYMED_HGLOBAL");
  639. pSTM->tymed = TYMED_HGLOBAL;
  640. if (_panetype == CMDLINK)
  641. {
  642. DebugMsg(DM_TRACE, " H_GLOBAL not supported for CMDLINK");
  643. return DATA_E_FORMATETC;
  644. }
  645. dwSize = _pEmbed->fd.nFileSizeLow;
  646. // caller is responsible for freeing this memory, even if we fail.
  647. if (!(lpvDest = GlobalAlloc(GPTR, dwSize)))
  648. {
  649. DebugMsg(DM_TRACE," out o memory!!");
  650. return E_OUTOFMEMORY;
  651. }
  652. pSTM->hGlobal = lpvDest;
  653. // open file to copy to stream
  654. hFile = CreateFile(_pEmbed->pszTempName, GENERIC_READ,
  655. FILE_SHARE_READWRITE, NULL,
  656. OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  657. if (hFile == INVALID_HANDLE_VALUE)
  658. {
  659. DebugMsg(DM_TRACE, " couldn't open file!!");
  660. hr = HRESULT_FROM_WIN32(GetLastError());
  661. goto ErrRet;
  662. }
  663. DWORD dwSizeLow;
  664. DWORD dwSizeHigh;
  665. // Figure out how much to copy...
  666. dwSizeLow = GetFileSize(hFile, &dwSizeHigh);
  667. ASSERT(dwSizeHigh == 0);
  668. SetFilePointer(hFile, 0L, NULL, FILE_BEGIN);
  669. // read in the file
  670. DWORD cbRead;
  671. if (ReadFile(hFile, lpvDest, dwSize, &cbRead, NULL))
  672. {
  673. return S_OK;
  674. }
  675. else
  676. {
  677. hr = E_FAIL;
  678. }
  679. ErrRet:
  680. CloseHandle(hFile);
  681. GlobalFree(pSTM->hGlobal);
  682. pSTM->hGlobal = NULL;
  683. return hr;
  684. }
  685. return DATA_E_FORMATETC;
  686. }
  687. void CPackage::_DrawIconToDC(HDC hdcMF, LPIC lpic, bool stripAlpha, LPCTSTR pszActualFileName)
  688. {
  689. RECT rcTemp;
  690. HFONT hfont = NULL;
  691. // Initializae the metafile
  692. _IconCalcSize(lpic);
  693. SetWindowOrgEx(hdcMF, 0, 0, NULL);
  694. SetWindowExtEx(hdcMF, lpic->rc.right - 1, lpic->rc.bottom - 1, NULL);
  695. SetRect(&rcTemp, 0, 0, lpic->rc.right,lpic->rc.bottom);
  696. hfont = SelectFont(hdcMF, g_hfontTitle);
  697. // Center the icon
  698. if(stripAlpha)
  699. AlphaStripRenderIcon(hdcMF, (rcTemp.right - g_cxIcon) / 2, 0, lpic->hDlgIcon, NULL);
  700. else
  701. DrawIcon(hdcMF, (rcTemp.right - g_cxIcon) / 2, 0, lpic->hDlgIcon);
  702. // Center the text below the icon
  703. SetBkMode(hdcMF, TRANSPARENT);
  704. SetTextAlign(hdcMF, TA_CENTER);
  705. // Set's the icon text for MF ie Word display's it from here.
  706. WCHAR szLabel[MAX_PATH];
  707. _CreateSaferIconTitle(szLabel, lpic->szIconText);
  708. TextOut(hdcMF, rcTemp.right / 2, g_cxIcon + 1, szLabel, lstrlen(szLabel));
  709. if (hfont)
  710. SelectObject(hdcMF, hfont);
  711. }
  712. HRESULT CPackage::GetEnhMetafile(LPFORMATETC pFE, LPSTGMEDIUM pSTM)
  713. {
  714. DebugMsg(DM_TRACE," Getting EnhancedMetafile");
  715. if (!(pFE->tymed & TYMED_ENHMF))
  716. {
  717. DebugMsg(DM_TRACE," does not support ENHMF!");
  718. return DATA_E_FORMATETC;
  719. }
  720. // Map to device independent coordinates
  721. RECT rcTemp;
  722. SetRect(&rcTemp, 0, 0, _lpic->rc.right,_lpic->rc.bottom);
  723. rcTemp.right = MulDiv((rcTemp.right - rcTemp.left), HIMETRIC_PER_INCH, DEF_LOGPIXELSX);
  724. rcTemp.bottom = MulDiv((rcTemp.bottom - rcTemp.top), HIMETRIC_PER_INCH, DEF_LOGPIXELSY);
  725. HDC hdc = CreateEnhMetaFile(NULL, NULL, &rcTemp, NULL);
  726. if (hdc)
  727. {
  728. _DrawIconToDC(hdc, _lpic, false, _pEmbed->fd.cFileName);
  729. pSTM->tymed = TYMED_ENHMF;
  730. pSTM->hEnhMetaFile = CloseEnhMetaFile(hdc);
  731. return S_OK;
  732. }
  733. else
  734. {
  735. pSTM->tymed = TYMED_NULL;
  736. return E_OUTOFMEMORY;
  737. }
  738. }
  739. HRESULT CPackage::GetMetafilePict(LPFORMATETC pFE, LPSTGMEDIUM pSTM)
  740. {
  741. LPMETAFILEPICT lpmfpict;
  742. RECT rcTemp;
  743. LPIC lpic = _lpic;
  744. HDC hdcMF = NULL;
  745. DebugMsg(DM_TRACE," Getting MetafilePict");
  746. if (!(pFE->tymed & TYMED_MFPICT))
  747. {
  748. DebugMsg(DM_TRACE," does not support MFPICT!");
  749. return DATA_E_FORMATETC;
  750. }
  751. pSTM->tymed = TYMED_MFPICT;
  752. // Allocate memory for the metafilepict and get a pointer to it
  753. // NOTE: the caller is responsible for freeing this memory, even on fail
  754. //
  755. if (!(pSTM->hMetaFilePict = GlobalAlloc(GPTR, sizeof(METAFILEPICT))))
  756. return E_OUTOFMEMORY;
  757. lpmfpict = (LPMETAFILEPICT)pSTM->hMetaFilePict;
  758. // Create the metafile
  759. if (!(hdcMF = CreateMetaFile(NULL)))
  760. return E_OUTOFMEMORY;
  761. _DrawIconToDC(hdcMF, _lpic, true, _pEmbed->fd.cFileName);
  762. // Map to device independent coordinates
  763. SetRect(&rcTemp, 0, 0, lpic->rc.right,lpic->rc.bottom);
  764. rcTemp.right =
  765. MulDiv((rcTemp.right - rcTemp.left), HIMETRIC_PER_INCH, DEF_LOGPIXELSX);
  766. rcTemp.bottom =
  767. MulDiv((rcTemp.bottom - rcTemp.top), HIMETRIC_PER_INCH, DEF_LOGPIXELSY);
  768. // Finish filling in the metafile header
  769. lpmfpict->mm = MM_ANISOTROPIC;
  770. lpmfpict->xExt = rcTemp.right;
  771. lpmfpict->yExt = rcTemp.bottom;
  772. lpmfpict->hMF = CloseMetaFile(hdcMF);
  773. return S_OK;
  774. }
  775. HRESULT CPackage::GetObjectDescriptor(LPFORMATETC pFE, LPSTGMEDIUM pSTM)
  776. {
  777. LPOBJECTDESCRIPTOR lpobj;
  778. DWORD dwFullUserTypeNameLen;
  779. DebugMsg(DM_TRACE," Getting Object Descriptor");
  780. // we only support HGLOBAL at this time
  781. //
  782. if (!(pFE->tymed & TYMED_HGLOBAL))
  783. {
  784. DebugMsg(DM_TRACE," does not support HGLOBAL!");
  785. return DATA_E_FORMATETC;
  786. }
  787. //// Copy file descriptor to HGLOBAL ///////////////////////////
  788. dwFullUserTypeNameLen = 0; //lstrlen(szUserType) + 1;
  789. pSTM->tymed = TYMED_HGLOBAL;
  790. if (!(lpobj = (OBJECTDESCRIPTOR *)GlobalAlloc(GPTR,
  791. sizeof(OBJECTDESCRIPTOR)+dwFullUserTypeNameLen)))
  792. return E_OUTOFMEMORY;
  793. pSTM->hGlobal = lpobj;
  794. lpobj->cbSize = sizeof(OBJECTDESCRIPTOR) + dwFullUserTypeNameLen;
  795. lpobj->clsid = CLSID_CPackage;
  796. lpobj->dwDrawAspect = DVASPECT_CONTENT|DVASPECT_ICON;
  797. GetMiscStatus(DVASPECT_CONTENT|DVASPECT_ICON,&(lpobj->dwStatus));
  798. lpobj->dwFullUserTypeName = 0L; //sizeof(OBJECTDESCRIPTOR);
  799. lpobj->dwSrcOfCopy = 0L;
  800. return S_OK;
  801. }
  802. /////////////////////////////////////////////////////////////////////////
  803. //
  804. // Stream I/O Functions
  805. //
  806. /////////////////////////////////////////////////////////////////////////
  807. HRESULT CPackage::PackageReadFromStream(IStream* pstm)
  808. {
  809. //
  810. // initialize the package object from a stream
  811. // return: s_OK - package properly initialized
  812. // E_FAIL - error initializing package
  813. //
  814. WORD w;
  815. DWORD dw;
  816. DebugMsg(DM_TRACE, "pack - PackageReadFromStream called.");
  817. // read in the package size, which we don't really need, but the old
  818. // packager puts it there.
  819. if (FAILED(pstm->Read(&dw, sizeof(dw), NULL)))
  820. return E_FAIL;
  821. // NOTE: Ok, this is really dumb. The old packager allowed the user
  822. // to create packages without giving them icons or labels, which
  823. // in my opinion is just dumb, it should have at least created a default
  824. // icon and shoved it in the persistent storage...oh well...
  825. // So if the appearance type comes back as NOTHING ( == 0)
  826. // then we just won't read any icon information.
  827. // read in the appearance type
  828. pstm->Read(&w, sizeof(w), NULL);
  829. // read in the icon information
  830. if (w == (WORD)ICON)
  831. {
  832. if (FAILED(IconReadFromStream(pstm)))
  833. {
  834. DebugMsg(DM_TRACE," error reading icon info!!");
  835. return E_FAIL;
  836. }
  837. }
  838. else if (w == (WORD)PICTURE)
  839. {
  840. DebugMsg(DM_TRACE, " old Packager Appearance, not supported!!");
  841. // NOTE: Ideally, we could just ignore the appearance and continue, but to
  842. // do so, we'll need to know how much information to skip over before continuing
  843. // to read from the stream
  844. #ifdef USE_RESOURCE_DLL
  845. HINSTANCE hInstRes = LoadLibraryEx(L"sp1res.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
  846. if(!hInstRes)
  847. return E_FAIL;
  848. #endif
  849. ShellMessageBox(hInstRes,
  850. NULL,
  851. MAKEINTRESOURCE(IDS_OLD_FORMAT_ERROR),
  852. MAKEINTRESOURCE(IDS_APP_TITLE),
  853. MB_OK | MB_ICONERROR | MB_TASKMODAL);
  854. #ifdef USE_RESOURCE_DLL
  855. FreeLibrary(hInstRes);
  856. #endif
  857. return E_FAIL;
  858. }
  859. // read in the contents type
  860. pstm->Read(&w, sizeof(w), NULL);
  861. _panetype = (PANETYPE)w;
  862. switch((PANETYPE)w)
  863. {
  864. case PEMBED:
  865. // read in the contents information
  866. return EmbedReadFromStream(pstm);
  867. case CMDLINK:
  868. // read in the contents information
  869. return CmlReadFromStream(pstm);
  870. default:
  871. return E_FAIL;
  872. }
  873. }
  874. //
  875. // read the icon info from a stream
  876. // return: S_OK -- icon read correctly
  877. // E_FAIL -- error reading icon
  878. //
  879. HRESULT CPackage::IconReadFromStream(IStream* pstm)
  880. {
  881. UINT cb;
  882. DebugMsg(DM_TRACE, "pack - IconReadFromStream() called.");
  883. LPIC lpic = IconCreate();
  884. if (lpic)
  885. {
  886. CHAR szTemp[MAX_PATH];
  887. cb = (UINT) StringReadFromStream(pstm, szTemp, ARRAYSIZE(szTemp));
  888. SHAnsiToTChar(szTemp, lpic->szIconText, ARRAYSIZE(lpic->szIconText));
  889. cb = (UINT) StringReadFromStream(pstm, szTemp, ARRAYSIZE(szTemp));
  890. SHAnsiToTChar(szTemp, lpic->szIconPath, ARRAYSIZE(lpic->szIconPath));
  891. WORD wDlgIcon;
  892. pstm->Read(&wDlgIcon, sizeof(wDlgIcon), NULL);
  893. lpic->iDlgIcon = (INT) wDlgIcon;
  894. _GetCurrentIcon(lpic);
  895. _IconCalcSize(lpic);
  896. }
  897. _DestroyIC();
  898. _lpic = lpic;
  899. return lpic ? S_OK : E_FAIL;
  900. }
  901. HRESULT CPackage::EmbedReadFromStream(IStream* pstm)
  902. {
  903. //
  904. // reads embedded file contents from a stream
  905. // return: S_OK - contents read succesfully
  906. // E_FAIL - error reading contents
  907. //
  908. DWORD dwSize;
  909. DWORD cb;
  910. CHAR szFileName[MAX_PATH];
  911. DebugMsg(DM_TRACE, "pack - EmbedReadFromStream called.");
  912. pstm->Read(&dwSize, sizeof(dwSize), &cb); // get string size
  913. if(dwSize < MAX_PATH)
  914. {
  915. pstm->Read(szFileName, dwSize, &cb); // get string
  916. }
  917. else
  918. return E_FAIL;
  919. pstm->Read(&dwSize, sizeof(dwSize), &cb); // get file size
  920. if (_pEmbed)
  921. {
  922. if (_pEmbed->pszTempName)
  923. {
  924. DeleteFile(_pEmbed->pszTempName);
  925. delete [] _pEmbed->pszTempName;
  926. }
  927. delete _pEmbed;
  928. }
  929. _pEmbed = new EMBED;
  930. if (NULL != _pEmbed)
  931. {
  932. _pEmbed->fd.dwFlags = FD_FILESIZE;
  933. _pEmbed->fd.nFileSizeLow = dwSize;
  934. _pEmbed->fd.nFileSizeHigh = 0;
  935. _pEmbed->fIsOleFile = TRUE; // Give it a chance to do ole style launch
  936. SHAnsiToTChar(szFileName, _pEmbed->fd.cFileName, ARRAYSIZE(_pEmbed->fd.cFileName));
  937. DebugMsg(DM_TRACE," %s\n\r %d",_pEmbed->fd.cFileName,_pEmbed->fd.nFileSizeLow);
  938. HRESULT hr = CreateTempFileName();
  939. if (FAILED(hr))
  940. {
  941. return hr;
  942. }
  943. if (FAILED(CopyStreamToFile(pstm, _pEmbed->pszTempName, _pEmbed->fd.nFileSizeLow)))
  944. {
  945. DebugMsg(DM_TRACE," couldn't copy from stream!!");
  946. return E_FAIL;
  947. }
  948. return S_OK;
  949. }
  950. else
  951. {
  952. return E_OUTOFMEMORY;
  953. }
  954. }
  955. HRESULT CPackage::CmlReadFromStream(IStream* pstm)
  956. {
  957. //
  958. // reads command line contents from a stream
  959. // return: S_OK - contents read succesfully
  960. // E_FAIL - error reading contents
  961. //
  962. DebugMsg(DM_TRACE, "pack - CmlReadFromStream() called.");
  963. WORD w;
  964. CHAR szCmdLink[CBCMDLINKMAX];
  965. DebugMsg(DM_TRACE, "pack - CmlReadFromStream called.");
  966. // read in the fCmdIsLink and the command line string
  967. if (FAILED(pstm->Read(&w, sizeof(w), NULL)))
  968. return E_FAIL;
  969. StringReadFromStream(pstm, szCmdLink, ARRAYSIZE(szCmdLink));
  970. if (_pCml != NULL)
  971. delete _pCml;
  972. _pCml = new CML;
  973. SHAnsiToTChar(szCmdLink, _pCml->szCommandLine, ARRAYSIZE(_pCml->szCommandLine));
  974. return S_OK;
  975. }
  976. HRESULT CPackage::PackageWriteToStream(IStream* pstm)
  977. {
  978. //
  979. // write the package object to a stream
  980. // return: s_OK - package properly written
  981. // E_FAIL - error writing package
  982. //
  983. WORD w;
  984. DWORD cb = 0L;
  985. DWORD dwSize;
  986. DebugMsg(DM_TRACE, "pack - PackageWriteToStream called.");
  987. // write out a DWORD where the package size will go
  988. if (FAILED(pstm->Write(&cb, sizeof(DWORD), NULL)))
  989. return E_FAIL;
  990. cb = 0;
  991. // write out the appearance type
  992. w = (WORD)ICON;
  993. if (FAILED(pstm->Write(&w, sizeof(WORD), NULL)))
  994. return E_FAIL;
  995. cb += sizeof(WORD);
  996. // write out the icon information
  997. if (FAILED(IconWriteToStream(pstm,&dwSize)))
  998. {
  999. DebugMsg(DM_TRACE," error writing icon info!!");
  1000. return E_FAIL;
  1001. }
  1002. cb += dwSize;
  1003. // write out the contents type
  1004. w = (WORD)_panetype;
  1005. if (FAILED(pstm->Write(&_panetype, sizeof(WORD), NULL)))
  1006. return E_FAIL;
  1007. cb += sizeof(WORD);
  1008. switch(_panetype)
  1009. {
  1010. case PEMBED:
  1011. // write out the contents information
  1012. if (FAILED(EmbedWriteToStream(pstm,&dwSize)))
  1013. {
  1014. DebugMsg(DM_TRACE," error writing embed info!!");
  1015. return E_FAIL;
  1016. }
  1017. cb += dwSize;
  1018. break;
  1019. case CMDLINK:
  1020. // write out the contents information
  1021. if (FAILED(CmlWriteToStream(pstm,&dwSize)))
  1022. {
  1023. DebugMsg(DM_TRACE," error writing cml info!!");
  1024. return E_FAIL;
  1025. }
  1026. cb += dwSize;
  1027. break;
  1028. }
  1029. LARGE_INTEGER li = {0, 0};
  1030. if (FAILED(pstm->Seek(li, STREAM_SEEK_SET, NULL)))
  1031. return E_FAIL;
  1032. if (FAILED(pstm->Write(&cb, sizeof(DWORD), NULL)))
  1033. return E_FAIL;
  1034. return S_OK;
  1035. }
  1036. //
  1037. // write the icon to a stream
  1038. // return: s_OK - icon properly written
  1039. // E_FAIL - error writing icon
  1040. //
  1041. HRESULT CPackage::IconWriteToStream(IStream* pstm, DWORD *pdw)
  1042. {
  1043. ASSERT(pdw);
  1044. DebugMsg(DM_TRACE, "pack - IconWriteToStream() called.");
  1045. CHAR szTemp[MAX_PATH];
  1046. SHTCharToAnsi(_lpic->szIconText, szTemp, ARRAYSIZE(szTemp));
  1047. *pdw = 0;
  1048. HRESULT hr = StringWriteToStream(pstm, szTemp, pdw);
  1049. if (SUCCEEDED(hr))
  1050. {
  1051. SHTCharToAnsi(_lpic->szIconPath, szTemp, ARRAYSIZE(szTemp));
  1052. hr = StringWriteToStream(pstm, szTemp, pdw);
  1053. if (SUCCEEDED(hr))
  1054. {
  1055. DWORD dwWrite;
  1056. WORD wDlgIcon = (WORD) _lpic->iDlgIcon;
  1057. hr = pstm->Write(&wDlgIcon, sizeof(wDlgIcon), &dwWrite);
  1058. if (SUCCEEDED(hr))
  1059. {
  1060. *pdw += dwWrite;
  1061. }
  1062. }
  1063. }
  1064. return hr;
  1065. }
  1066. //
  1067. // write embedded file contents to a stream
  1068. // return: S_OK - contents written succesfully
  1069. // E_FAIL - error writing contents
  1070. //
  1071. HRESULT CPackage::EmbedWriteToStream(IStream* pstm, DWORD *pdw)
  1072. {
  1073. DebugMsg(DM_TRACE, "pack - EmbedWriteToStream() called.");
  1074. DWORD cb = 0;
  1075. CHAR szTemp[MAX_PATH];
  1076. SHTCharToAnsi(_pEmbed->fd.cFileName, szTemp, ARRAYSIZE(szTemp));
  1077. DWORD dwSize = lstrlenA(szTemp) + 1;
  1078. HRESULT hr = pstm->Write(&dwSize, sizeof(dwSize), &cb);
  1079. if (SUCCEEDED(hr))
  1080. {
  1081. DWORD dwWrite = 0;
  1082. hr = StringWriteToStream(pstm, szTemp, &dwWrite);
  1083. if (SUCCEEDED(hr))
  1084. {
  1085. cb += dwWrite;
  1086. hr = pstm->Write(&_pEmbed->fd.nFileSizeLow, sizeof(_pEmbed->fd.nFileSizeLow), &dwWrite);
  1087. if (SUCCEEDED(hr))
  1088. {
  1089. cb += dwWrite;
  1090. // This is for screwy apps, like MSWorks that ask us to save ourselves
  1091. // before they've even told us to initialize ourselves.
  1092. //
  1093. if (_pEmbed->pszTempName && _pEmbed->pszTempName[0])
  1094. {
  1095. DWORD dwFileSize;
  1096. hr = CopyFileToStream(_pEmbed->pszTempName, pstm, &dwFileSize);
  1097. if (SUCCEEDED(hr))
  1098. {
  1099. cb += dwFileSize;
  1100. }
  1101. }
  1102. else
  1103. {
  1104. ASSERT(0);
  1105. hr = E_FAIL;
  1106. }
  1107. if (pdw)
  1108. *pdw = cb;
  1109. }
  1110. }
  1111. }
  1112. return hr;
  1113. }
  1114. //
  1115. // write embedded file contents to a stream
  1116. // return: S_OK - contents written succesfully
  1117. // E_FAIL - error writing contents
  1118. //
  1119. HRESULT CPackage::CmlWriteToStream(IStream* pstm, DWORD *pdw)
  1120. {
  1121. DWORD cb = 0;
  1122. WORD w = (WORD)_pCml->fCmdIsLink;
  1123. DebugMsg(DM_TRACE, "pack - CmlWriteToStream called.");
  1124. if (FAILED(pstm->Write(&w, sizeof(w), NULL)))
  1125. return E_FAIL; // write fCmdIsLink
  1126. cb += sizeof(w); // for fCmdIsLink
  1127. CHAR szTemp[MAX_PATH];
  1128. SHTCharToAnsi(_pCml->szCommandLine, szTemp, ARRAYSIZE(szTemp));
  1129. HRESULT hres = StringWriteToStream(pstm, szTemp, &cb);
  1130. if (FAILED(hres))
  1131. return hres; // write command link
  1132. // return the number of bytes written in the outparam
  1133. if (pdw)
  1134. *pdw = cb;
  1135. return S_OK;
  1136. }
  1137. HRESULT CPackage::CreateShortcutOnStream(IStream* pstm)
  1138. {
  1139. DebugMsg(DM_TRACE, "pack - CreateShortcutOnStream() called.");
  1140. HRESULT hr;
  1141. IShellLink *psl;
  1142. TCHAR szArgs[CBCMDLINKMAX];
  1143. TCHAR szPath[CBCMDLINKMAX];
  1144. hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
  1145. IID_IShellLink, (void **)&psl);
  1146. if (SUCCEEDED(hr))
  1147. {
  1148. IPersistStream *pps;
  1149. StringCchCopy(szPath, ARRAYSIZE(szPath), _pCml->szCommandLine);
  1150. PathSeparateArgs(szPath, szArgs, ARRAYSIZE(szPath));
  1151. psl->SetPath(szPath);
  1152. psl->SetIconLocation(_lpic->szIconPath, _lpic->iDlgIcon);
  1153. psl->SetShowCmd(SW_SHOW);
  1154. psl->SetArguments(szArgs);
  1155. hr = psl->QueryInterface(IID_IPersistStream, (void **)&pps);
  1156. if (SUCCEEDED(hr))
  1157. {
  1158. hr = pps->Save(pstm,TRUE);
  1159. pps->Release();
  1160. }
  1161. psl->Release();
  1162. }
  1163. LARGE_INTEGER li = {0,0};
  1164. pstm->Seek(li,STREAM_SEEK_SET,NULL);
  1165. return hr;
  1166. }
  1167. HRESULT CPackage::InitVerbEnum(OLEVERB* pVerbs, ULONG cVerbs)
  1168. {
  1169. DebugMsg(DM_TRACE, "pack - InitVerbEnum called");
  1170. if (NULL != _pVerbs)
  1171. {
  1172. for (ULONG i = 0; i < _cVerbs; i++)
  1173. {
  1174. delete _pVerbs[i].lpszVerbName;
  1175. }
  1176. delete [] _pVerbs;
  1177. }
  1178. _pVerbs = pVerbs;
  1179. _cVerbs = cVerbs;
  1180. _nCurVerb = 0;
  1181. return (NULL != pVerbs) ? S_OK : E_FAIL;
  1182. }
  1183. VOID CPackage::ReleaseContextMenu()
  1184. {
  1185. if (NULL != _pcm)
  1186. {
  1187. _pcm->Release();
  1188. _pcm = NULL;
  1189. }
  1190. }
  1191. HRESULT CPackage::GetContextMenu(IContextMenu** ppcm)
  1192. {
  1193. DebugMsg(DM_TRACE, "pack - GetContextMenu called");
  1194. HRESULT hr = E_FAIL;
  1195. ASSERT(NULL != ppcm);
  1196. if (NULL != _pcm)
  1197. {
  1198. _pcm->AddRef();
  1199. *ppcm = _pcm;
  1200. hr = S_OK;
  1201. }
  1202. else if ((PEMBED == _panetype) || (CMDLINK == _panetype))
  1203. {
  1204. if (PEMBED == _panetype)
  1205. {
  1206. hr = CreateTempFileName();
  1207. }
  1208. else
  1209. {
  1210. hr = S_OK;
  1211. }
  1212. if (SUCCEEDED(hr))
  1213. {
  1214. LPITEMIDLIST pidl = SHSimpleIDListFromPath((PEMBED == _panetype) ?
  1215. _pEmbed->pszTempName :
  1216. _pCml->szCommandLine);
  1217. if (NULL != pidl)
  1218. {
  1219. IShellFolder* psf;
  1220. LPCITEMIDLIST pidlChild;
  1221. if (SUCCEEDED(hr = SHBindToIDListParent(pidl, IID_IShellFolder, (void **)&psf, &pidlChild)))
  1222. {
  1223. hr = psf->GetUIObjectOf(NULL, 1, &pidlChild, IID_IContextMenu, NULL, (void**) &_pcm);
  1224. if (SUCCEEDED(hr))
  1225. {
  1226. _pcm->AddRef();
  1227. *ppcm = _pcm;
  1228. }
  1229. psf->Release();
  1230. }
  1231. ILFree(pidl);
  1232. }
  1233. else
  1234. {
  1235. hr = E_OUTOFMEMORY;
  1236. }
  1237. }
  1238. }
  1239. return hr;
  1240. }
  1241. HRESULT CPackage::_IconRefresh()
  1242. {
  1243. DebugMsg(DM_TRACE, "pack - IconRefresh() called.");
  1244. // we refresh the icon. typically, this will be called the first time
  1245. // the package is created to load the new icon and calculate how big
  1246. // it should be. this will also be called after we edit the package,
  1247. // since the user might have changed the icon.
  1248. // First, load the appropriate icon. We'll load the icon specified by
  1249. // lpic->szIconPath and lpic->iDlgIcon if possible, otherwise we'll just
  1250. // use the generic packager icon.
  1251. //
  1252. _GetCurrentIcon(_lpic);
  1253. // Next, we need to have the icon recalculate its size, since it's text
  1254. // might have changed, causing it to get bigger or smaller.
  1255. //
  1256. _IconCalcSize(_lpic);
  1257. // Next, notify our containers that our view has changed.
  1258. if (_pIDataAdviseHolder)
  1259. _pIDataAdviseHolder->SendOnDataChange(this,0, NULL);
  1260. if (_pViewSink)
  1261. _pViewSink->OnViewChange(_dwViewAspects,_dwViewAdvf);
  1262. // Set our dirty flag
  1263. _fIsDirty = TRUE;
  1264. return S_OK;
  1265. }
  1266. void CPackage::_DestroyIC()
  1267. {
  1268. if (_lpic)
  1269. {
  1270. if (_lpic->hDlgIcon)
  1271. DestroyIcon(_lpic->hDlgIcon);
  1272. GlobalFree(_lpic);
  1273. }
  1274. }
  1275. // This is an IOleCommandTarget method that we use because we cannot marshal the pIOleAdviseHolder.
  1276. // While we're at it, we use the _pIOleClientSite methods too.
  1277. HRESULT CPackage::Exec(const GUID* pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG* pvaIn, VARIANTARG* pvaOut)
  1278. {
  1279. DebugMsg(DM_TRACE, "pack Exec called");
  1280. HRESULT hr = OLECMDERR_E_UNKNOWNGROUP;
  1281. if (*pguidCmdGroup != SID_targetGUID)
  1282. {
  1283. return hr;
  1284. }
  1285. if(nCmdID == 0) // for future expansion
  1286. {
  1287. // this will set our dirty flag...
  1288. if (FAILED(EmbedInitFromFile(_pEmbed->pszTempName,FALSE)))
  1289. {
  1290. #ifdef USE_RESOURCE_DLL
  1291. HINSTANCE hInstRes = LoadLibraryEx(L"sp1res.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
  1292. if(!hInstRes)
  1293. return E_FAIL;
  1294. #endif
  1295. ShellMessageBox(hInstRes,
  1296. NULL,
  1297. MAKEINTRESOURCE(IDS_UPDATE_ERROR),
  1298. MAKEINTRESOURCE(IDS_APP_TITLE),
  1299. MB_ICONERROR | MB_TASKMODAL | MB_OK);
  1300. #ifdef USE_RESOURCE_DLL
  1301. FreeLibrary(hInstRes);
  1302. #endif
  1303. }
  1304. // The SendOnDataChange is necessary for Word to save any changes
  1305. if(_pIDataAdviseHolder)
  1306. {
  1307. // if it fails, no harm, no foul?
  1308. _pIDataAdviseHolder->SendOnDataChange(this, 0, 0);
  1309. }
  1310. if(_pIOleClientSite)
  1311. _pIOleClientSite->SaveObject();
  1312. hr = _pIOleAdviseHolder->SendOnSave();
  1313. if(FAILED(hr))
  1314. return hr;
  1315. hr = _pIOleAdviseHolder->SendOnClose();
  1316. _pEmbed->hTask = NULL;
  1317. if(FAILED(hr))
  1318. return hr;
  1319. if (_pIOleClientSite && !_fNoIOleClientSiteCalls)
  1320. hr = _pIOleClientSite->OnShowWindow(FALSE);
  1321. _pEmbed->hTask = NULL;
  1322. }
  1323. return hr;
  1324. }
  1325. // This is a required IOleCommandTarget method that should never be called
  1326. HRESULT CPackage::QueryStatus(const GUID* pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT* pCmdText)
  1327. {
  1328. DebugMsg(DM_TRACE, "pack - QueryStatus called");
  1329. return OLECMDERR_E_UNKNOWNGROUP;
  1330. }