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.

852 lines
23 KiB

  1. /*
  2. * ispersis.cpp - IPersist, IPersistFile, and IPersistStream implementations for
  3. * URL class.
  4. */
  5. #include "priv.h"
  6. #include "ishcut.h"
  7. #include "resource.h"
  8. // Need to flush the file to prevent win95 from barfing after stuff is written in
  9. VOID FlushFile(LPCTSTR pszFile)
  10. {
  11. if (!g_fRunningOnNT)
  12. {
  13. WritePrivateProfileString(NULL, NULL, NULL, pszFile);
  14. }
  15. }
  16. // save object to file
  17. STDMETHODIMP Intshcut::SaveToFile(LPCTSTR pszFile, BOOL bRemember)
  18. {
  19. HRESULT hres = InitProp();
  20. if (SUCCEEDED(hres))
  21. {
  22. m_pprop->SetFileName(pszFile);
  23. hres = m_pprop->Commit(STGC_DEFAULT);
  24. // Remember file if requested
  25. if (SUCCEEDED(hres))
  26. {
  27. if (bRemember)
  28. {
  29. Dirty(FALSE);
  30. if ( !Str_SetPtr(&m_pszFile, pszFile) )
  31. hres = E_OUTOFMEMORY;
  32. #ifdef DEBUG
  33. Dump();
  34. #endif
  35. }
  36. SHChangeNotify(SHCNE_UPDATEITEM, (SHCNF_PATH | SHCNF_FLUSHNOWAIT), pszFile, NULL);
  37. }
  38. if (!bRemember)
  39. m_pprop->SetFileName(m_pszFile);
  40. }
  41. if(pszFile && (S_OK == hres))
  42. FlushFile(pszFile);
  43. return hres;
  44. }
  45. STDMETHODIMP Intshcut::LoadFromFile(LPCTSTR pszFile)
  46. {
  47. HRESULT hres;
  48. if (Str_SetPtr(&m_pszFile, pszFile))
  49. {
  50. hres = InitProp();
  51. #ifdef DEBUG
  52. Dump();
  53. #endif
  54. }
  55. else
  56. {
  57. hres = E_OUTOFMEMORY;
  58. }
  59. return hres;
  60. }
  61. STDMETHODIMP Intshcut::LoadFromAsyncFileNow()
  62. {
  63. HRESULT hres = S_OK;
  64. if (m_pszFileToLoad)
  65. {
  66. hres = LoadFromFile(m_pszFileToLoad);
  67. Str_SetPtr(&m_pszFileToLoad, NULL);
  68. }
  69. return hres;
  70. }
  71. STDMETHODIMP Intshcut::GetCurFile(LPTSTR pszFile, UINT cchLen)
  72. {
  73. HRESULT hr;
  74. if (m_pszFile)
  75. {
  76. hr = StringCchCopy(pszFile, cchLen, m_pszFile);
  77. }
  78. else
  79. hr = S_FALSE;
  80. return hr;
  81. }
  82. STDMETHODIMP Intshcut::Dirty(BOOL bDirty)
  83. {
  84. HRESULT hres;
  85. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  86. if (bDirty)
  87. {
  88. if (IsFlagClear(m_dwFlags, ISF_DIRTY))
  89. TraceMsg(TF_INTSHCUT, "Intshcut now dirty.");
  90. SetFlag(m_dwFlags, ISF_DIRTY);
  91. }
  92. else
  93. {
  94. if (IsFlagSet(m_dwFlags, ISF_DIRTY))
  95. TraceMsg(TF_INTSHCUT, "Intshcut now clean.");
  96. ClearFlag(m_dwFlags, ISF_DIRTY);
  97. }
  98. hres = S_OK;
  99. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  100. return hres;
  101. }
  102. // IPersist::GetClassID method for Intshcut
  103. STDMETHODIMP Intshcut::GetClassID(CLSID *pclsid)
  104. {
  105. ASSERT(IS_VALID_WRITE_PTR(pclsid, CLSID));
  106. *pclsid = CLSID_InternetShortcut;
  107. return S_OK;
  108. }
  109. // IPersistFile::IsDirty handler for Intshcut
  110. STDMETHODIMP Intshcut::IsDirty(void)
  111. {
  112. HRESULT hres = LoadFromAsyncFileNow();
  113. if(SUCCEEDED(hres))
  114. {
  115. hres = InitProp();
  116. if (SUCCEEDED(hres))
  117. {
  118. if (IsFlagSet(m_dwFlags, ISF_DIRTY) || S_OK == m_pprop->IsDirty())
  119. hres = S_OK;
  120. else
  121. hres = S_FALSE;
  122. }
  123. }
  124. return hres;
  125. }
  126. // Helper function to save off Trident specific stuff
  127. STDMETHODIMP Intshcut::_SaveOffPersistentDataFromSite()
  128. {
  129. IOleCommandTarget *pcmdt = NULL;
  130. HRESULT hr = S_OK;
  131. if (_punkSite)
  132. {
  133. if(S_OK == _CreateTemporaryBackingFile())
  134. {
  135. ASSERT(m_pszTempFileName);
  136. hr = _punkSite->QueryInterface(IID_IOleCommandTarget, (LPVOID *)&pcmdt);
  137. if((S_OK == hr))
  138. {
  139. ASSERT(pcmdt);
  140. VARIANT varIn = {0};
  141. varIn.vt = VT_UNKNOWN;
  142. varIn.punkVal = (LPUNKNOWN)(SAFECAST(this, IUniformResourceLocator *));
  143. // Tell the site to save off it's persistent stuff
  144. hr = pcmdt->Exec(&CGID_ShortCut, CMDID_INTSHORTCUTCREATE, 0, &varIn, NULL);
  145. pcmdt->Release();
  146. }
  147. FlushFile(m_pszTempFileName);
  148. }
  149. }
  150. return hr;
  151. }
  152. // IPersistFile::Save handler for Intshcut
  153. STDMETHODIMP Intshcut::Save(LPCOLESTR pwszFile, BOOL bRemember)
  154. {
  155. HRESULT hres = LoadFromAsyncFileNow();
  156. if (SUCCEEDED(hres))
  157. {
  158. TCHAR szFile[MAX_PATH];
  159. if (pwszFile)
  160. SHUnicodeToTChar(pwszFile, szFile, SIZECHARS(szFile));
  161. else if (m_pszFile)
  162. hres = StringCchCopy(szFile, ARRAYSIZE(szFile), m_pszFile);
  163. else
  164. hres = E_FAIL;
  165. if (FAILED(hres))
  166. {
  167. return hres;
  168. }
  169. // Perhaps there is a site which wants to save off stuff ?
  170. // However, the site may end up calling via intefaces
  171. hres = _SaveOffPersistentDataFromSite();
  172. if ((S_OK == hres) && (m_pszTempFileName) && (StrCmp(m_pszTempFileName, szFile) != 0))
  173. {
  174. // Copy contents of the temp file to the destination
  175. // if they are different files
  176. EVAL(CopyFile(m_pszTempFileName, szFile, FALSE));
  177. }
  178. // Then save off in memory stuff to this file
  179. hres = SaveToFile(szFile, bRemember);
  180. }
  181. return hres;
  182. }
  183. STDMETHODIMP Intshcut::SaveCompleted(LPCOLESTR pwszFile)
  184. {
  185. return S_OK;
  186. }
  187. // IPersistFile::Load()
  188. STDMETHODIMP Intshcut::Load(LPCOLESTR pwszFile, DWORD dwMode)
  189. {
  190. HRESULT hres;
  191. if (m_pszFile || m_pszFileToLoad)
  192. {
  193. hres = E_FAIL; // can't ::Load twice
  194. }
  195. else
  196. {
  197. if (m_fMustLoadSync)
  198. hres = LoadFromFile(pwszFile);
  199. else
  200. {
  201. if (Str_SetPtr(&m_pszFileToLoad, pwszFile))
  202. hres = S_OK;
  203. else
  204. hres = E_OUTOFMEMORY;
  205. }
  206. }
  207. return hres;
  208. }
  209. // IPersistFile::GetCurFile method for Intshcut
  210. STDMETHODIMP Intshcut::GetCurFile(WCHAR **ppwszFile)
  211. {
  212. HRESULT hr;
  213. TCHAR szTempFile[MAX_PATH];
  214. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  215. ASSERT(IS_VALID_WRITE_PTR(ppwszFile, LPOLESTR));
  216. hr = LoadFromAsyncFileNow();
  217. if (FAILED(hr))
  218. return hr;
  219. if (m_pszFile)
  220. {
  221. hr = StringCchCopy(szTempFile, ARRAYSIZE(szTempFile), m_pszFile);
  222. }
  223. else
  224. {
  225. hr = StringCchCopy(szTempFile, ARRAYSIZE(szTempFile), TEXT("*.url"));
  226. if (SUCCEEDED(hr))
  227. {
  228. // This code path returns S_FALSE on success
  229. hr = S_FALSE;
  230. }
  231. }
  232. HRESULT hrTemp = SHStrDup(szTempFile, ppwszFile);
  233. if (FAILED(hrTemp))
  234. hr = hrTemp;
  235. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  236. return(hr);
  237. }
  238. // IPersistStream::Load method for Intshcut
  239. STDMETHODIMP Intshcut::Load(IStream *pstm)
  240. {
  241. // to implement this:
  242. // save stream to temp.ini
  243. // IPersistFile::Load() from that
  244. // delete temp file
  245. return E_NOTIMPL;
  246. }
  247. // IPersistStream::Save method for Intshcut
  248. STDMETHODIMP Intshcut::Save(IStream *pstm, BOOL bClearDirty)
  249. {
  250. HRESULT hr = InitProp();
  251. if (SUCCEEDED(hr))
  252. {
  253. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  254. hr = m_pprop->GetProp(PID_IS_URL, szURL, SIZECHARS(szURL));
  255. if (SUCCEEDED(hr))
  256. {
  257. LPSTR pszContents;
  258. hr = CreateURLFileContents(szURL, &pszContents);
  259. if (SUCCEEDED(hr)) {
  260. ASSERT(hr == lstrlenA(pszContents));
  261. hr = pstm->Write(pszContents, hr + 1, NULL);
  262. GlobalFree(pszContents);
  263. pszContents = NULL;
  264. } else {
  265. hr = E_OUTOFMEMORY;
  266. }
  267. }
  268. }
  269. return hr;
  270. }
  271. // IPersistStream::GetSizeMax method for Intshcut
  272. STDMETHODIMP Intshcut::GetSizeMax(PULARGE_INTEGER puliSize)
  273. {
  274. puliSize->LowPart = 0;
  275. puliSize->HighPart = 0;
  276. HRESULT hr = InitProp();
  277. if (SUCCEEDED(hr))
  278. {
  279. puliSize->LowPart = GetFileContentsAndSize(NULL);
  280. hr = S_OK;
  281. }
  282. return hr;
  283. }
  284. STDMETHODIMP Intshcut::_SetTempFileName(TCHAR *pszTempFileName)
  285. {
  286. ASSERT(NULL == m_pszTempFileName);
  287. if (m_pszTempFileName)
  288. DeleteFile(m_pszTempFileName);
  289. Str_SetPtr(&m_pszTempFileName, pszTempFileName);
  290. return (m_pszTempFileName ? S_OK : E_OUTOFMEMORY);
  291. }
  292. STDMETHODIMP Intshcut::_CreateTemporaryBackingFile()
  293. {
  294. HRESULT hres = E_FAIL;
  295. if (m_pszTempFileName)
  296. return S_OK;
  297. TCHAR szTempFileName[MAX_PATH];
  298. TCHAR szDirectory[MAX_PATH];
  299. DWORD dwRet = GetTempPath(ARRAYSIZE(szDirectory), szDirectory);
  300. if ((FALSE == dwRet) || (FALSE == PathFileExists(szDirectory)))
  301. {
  302. szDirectory[0] = TEXT('\\');
  303. szDirectory[1] = TEXT('\0');
  304. dwRet = TRUE;
  305. }
  306. dwRet = GetTempFileName(szDirectory, TEXT("www"), 0, szTempFileName);
  307. if (dwRet)
  308. {
  309. hres = _SetTempFileName(szTempFileName);
  310. // Now copy over the current file from which this was loaded and then save off
  311. // any changes
  312. if (S_OK == hres)
  313. {
  314. if (m_pszFile)
  315. {
  316. EVAL(CopyFile(m_pszFile, m_pszTempFileName, FALSE));
  317. SaveToFile(m_pszTempFileName, FALSE); // this flushes the file
  318. }
  319. }
  320. }
  321. return hres;
  322. }
  323. // Calculate the size of the contents to be transferred in a block.
  324. STDMETHODIMP_(DWORD) Intshcut::GetFileContentsAndSize(LPSTR *ppszBuf)
  325. {
  326. DWORD cbSize = 0; // this is in bytes, not characters
  327. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  328. BOOL fSuccess = FALSE;
  329. HRESULT hres;
  330. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  331. ASSERT(m_pprop);
  332. if (ppszBuf)
  333. *ppszBuf = NULL;
  334. // Create a temporary backing File here and save off everything that needs to be
  335. // saved off there and use that to satisfy this request
  336. if (S_OK == _CreateTemporaryBackingFile())
  337. {
  338. ASSERT(m_pszTempFileName);
  339. WCHAR wszTemp[MAX_PATH];
  340. SHTCharToUnicode(m_pszTempFileName, wszTemp, ARRAYSIZE(wszTemp));
  341. hres = Save(wszTemp, FALSE); // So our temp file is now up to date
  342. // Just copy the file
  343. HANDLE hFile = CreateFile(m_pszTempFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  344. if (hFile != INVALID_HANDLE_VALUE)
  345. {
  346. DWORD dwTemp = 0;
  347. cbSize = GetFileSize(hFile, &dwTemp);
  348. if (ppszBuf)
  349. {
  350. if (0xFFFFFFFF != cbSize)
  351. {
  352. ASSERT(0 == dwTemp);
  353. *ppszBuf = (LPSTR)LocalAlloc(LPTR, cbSize);
  354. if (*ppszBuf)
  355. {
  356. dwTemp = 0;
  357. if(ReadFile(hFile, *ppszBuf, cbSize, &dwTemp, NULL))
  358. {
  359. ASSERT(cbSize >= dwTemp);
  360. fSuccess = TRUE;
  361. }
  362. }
  363. }
  364. }
  365. else
  366. {
  367. fSuccess = TRUE; // Just want the size - not contents
  368. }
  369. CloseHandle(hFile);
  370. }
  371. if (FALSE == fSuccess)
  372. {
  373. cbSize = 0;
  374. if(ppszBuf && (*ppszBuf))
  375. {
  376. LocalFree(*ppszBuf);
  377. *ppszBuf = NULL;
  378. }
  379. }
  380. }
  381. if (FALSE == fSuccess)
  382. {
  383. // if you couldn't read the file, then perhaps atleast this will work ?
  384. HRESULT hr = InitProp();
  385. if (SUCCEEDED(hr) && SUCCEEDED(m_pprop->GetProp(PID_IS_URL, szURL, SIZECHARS(szURL))))
  386. {
  387. hr = CreateURLFileContents(szURL, ppszBuf);
  388. // IEUNIX-This function should return the strlen not including the
  389. // null characters as this causes the shortcut file having a null
  390. // character causing a crash in the execution of the link.
  391. // Fortunately, that's what CreateURLFileContents returns
  392. cbSize = SUCCEEDED(hr) ? hr : 0;
  393. }
  394. }
  395. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  396. return cbSize;
  397. }
  398. #ifndef WC_NO_BEST_FIT_CHARS
  399. #define WC_NO_BEST_FIT_CHARS 0x00000400
  400. #endif
  401. // transfer the URL data in URL clipboard
  402. STDMETHODIMP Intshcut::TransferUniformResourceLocator(FORMATETC *pfmtetc, STGMEDIUM *pstgmed)
  403. {
  404. HRESULT hr;
  405. ASSERT(pfmtetc->dwAspect == DVASPECT_CONTENT);
  406. ASSERT(pfmtetc->lindex == -1);
  407. if (pfmtetc->tymed & TYMED_HGLOBAL)
  408. {
  409. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  410. ASSERT(m_pprop);
  411. hr = InitProp();
  412. if (SUCCEEDED(hr))
  413. {
  414. hr = m_pprop->GetProp(PID_IS_URL, szURL, SIZECHARS(szURL));
  415. if (SUCCEEDED(hr))
  416. {
  417. int cch = lstrlen(szURL) + 1;
  418. int cb = (cch-1) * 9 + 1; // the biggest result is an utf8 escaped version of the string
  419. // utf8 encoding can blow the size up to 3 times
  420. // escaping can blow each byte up to 3 times
  421. LPSTR pszURL = (LPSTR)GlobalAlloc(GPTR, cb);
  422. if (pszURL)
  423. {
  424. if (pfmtetc->cfFormat == CF_UNICODETEXT || pfmtetc->cfFormat == g_cfURLW)
  425. {
  426. StrCpyN((LPWSTR)pszURL, szURL, cch);
  427. }
  428. else
  429. {
  430. BOOL bUsedDefaultChar = FALSE;
  431. DWORD dwFlags = 0;
  432. if (IsOS(OS_WIN2000ORGREATER) || IsOS(OS_WIN98ORGREATER))
  433. {
  434. dwFlags |= WC_NO_BEST_FIT_CHARS;
  435. }
  436. int wcResult = WideCharToMultiByte(CP_ACP,
  437. dwFlags,
  438. szURL,
  439. cch,
  440. pszURL,
  441. cb,
  442. NULL,
  443. &bUsedDefaultChar);
  444. if ((0 == wcResult) || bUsedDefaultChar)
  445. {
  446. // the string is weird and can't be converted back to unicode
  447. // we're going to utf8-escaped encode it
  448. ConvertToUtf8Escaped(szURL, ARRAYSIZE(szURL));
  449. SHUnicodeToAnsi(szURL, pszURL, cb);
  450. }
  451. }
  452. pstgmed->tymed = TYMED_HGLOBAL;
  453. pstgmed->hGlobal = pszURL;
  454. }
  455. }
  456. }
  457. }
  458. else
  459. hr = DV_E_TYMED;
  460. return hr;
  461. }
  462. // transfer the URL data in text
  463. STDMETHODIMP Intshcut::TransferText(FORMATETC *pfmtetc, STGMEDIUM *pstgmed)
  464. {
  465. return TransferUniformResourceLocator(pfmtetc, pstgmed);
  466. }
  467. // assumes the current seek pos in the stream is at the start
  468. BOOL GetStreamMimeAndExt(LPCWSTR pszURL, IStream *pstm,
  469. LPTSTR pszMime, UINT cchMime, LPTSTR pszExt, UINT cchExt)
  470. {
  471. BYTE buf[256];
  472. ULONG cbRead;
  473. pstm->Read(buf, SIZEOF(buf), &cbRead);
  474. WCHAR *pwszMimeOut;
  475. if (SUCCEEDED(FindMimeFromData(NULL, pszURL, buf, cbRead, NULL, 0, &pwszMimeOut, 0)))
  476. {
  477. TCHAR szMimeTemp[MAX_PATH];
  478. if (pszMime == NULL)
  479. {
  480. pszMime = szMimeTemp;
  481. cchMime = ARRAYSIZE(szMimeTemp);
  482. }
  483. SHUnicodeToTChar(pwszMimeOut, pszMime, cchMime);
  484. CoTaskMemFree(pwszMimeOut);
  485. if (pszExt)
  486. MIME_GetExtension(pszMime, pszExt, cchExt);
  487. }
  488. // const LARGE_INTEGER c_li0 = {0, 0};
  489. pstm->Seek(c_li0, STREAM_SEEK_SET, NULL);
  490. return TRUE;
  491. }
  492. // pszName is assumed to be MAX_PATH
  493. STDMETHODIMP Intshcut::GetDocumentName(LPTSTR pszName)
  494. {
  495. GetDescription(pszName, MAX_PATH);
  496. WCHAR *pszURL;
  497. if (S_OK == GetURLW(&pszURL))
  498. {
  499. IStream *pstm;
  500. if (SUCCEEDED(URLOpenBlockingStreamW(NULL, pszURL, &pstm, 0, NULL)))
  501. {
  502. TCHAR szExt[MAX_PATH];
  503. GetStreamMimeAndExt(pszURL, pstm, NULL, 0, szExt, ARRAYSIZE(szExt));
  504. PathRenameExtension(pszName, szExt);
  505. pstm->Release();
  506. }
  507. SHFree(pszURL);
  508. }
  509. return S_OK;
  510. }
  511. // transfer URL data in file-group-descriptor clipboard format.
  512. STDMETHODIMP Intshcut::TransferFileGroupDescriptorA(FORMATETC *pfmtetc, STGMEDIUM *pstgmed)
  513. {
  514. HRESULT hr;
  515. if (pfmtetc->dwAspect != DVASPECT_COPY &&
  516. pfmtetc->dwAspect != DVASPECT_LINK &&
  517. pfmtetc->dwAspect != DVASPECT_CONTENT)
  518. {
  519. hr = DV_E_DVASPECT;
  520. }
  521. else if (pfmtetc->tymed & TYMED_HGLOBAL)
  522. {
  523. FILEGROUPDESCRIPTORA * pfgd = (FILEGROUPDESCRIPTORA *)GlobalAlloc(GPTR, SIZEOF(FILEGROUPDESCRIPTORA));
  524. if (pfgd)
  525. {
  526. FILEDESCRIPTORA * pfd = &(pfgd->fgd[0]);
  527. TCHAR szTemp[MAX_PATH];
  528. if (pfmtetc->dwAspect == DVASPECT_COPY)
  529. {
  530. pfd->dwFlags = FD_FILESIZE;
  531. GetDocumentName(szTemp);
  532. }
  533. else
  534. {
  535. pfd->dwFlags = FD_FILESIZE | FD_LINKUI;
  536. GetDescription(szTemp, ARRAYSIZE(szTemp));
  537. }
  538. SHTCharToAnsi(PathFindFileName(szTemp), pfd->cFileName, SIZECHARS(pfd->cFileName));
  539. pfd->nFileSizeHigh = 0;
  540. pfd->nFileSizeLow = GetFileContentsAndSize(NULL);
  541. pfgd->cItems = 1;
  542. pstgmed->tymed = TYMED_HGLOBAL;
  543. pstgmed->hGlobal = pfgd;
  544. hr = S_OK;
  545. }
  546. else
  547. hr = E_OUTOFMEMORY;
  548. }
  549. else
  550. hr = DV_E_TYMED;
  551. return hr;
  552. }
  553. // transfer URL data in file-group-descriptor clipboard format.
  554. STDMETHODIMP Intshcut::TransferFileGroupDescriptorW(FORMATETC *pfmtetc, STGMEDIUM *pstgmed)
  555. {
  556. HRESULT hr;
  557. if (pfmtetc->dwAspect != DVASPECT_COPY &&
  558. pfmtetc->dwAspect != DVASPECT_LINK &&
  559. pfmtetc->dwAspect != DVASPECT_CONTENT)
  560. {
  561. hr = DV_E_DVASPECT;
  562. }
  563. else if (pfmtetc->tymed & TYMED_HGLOBAL)
  564. {
  565. FILEGROUPDESCRIPTORW * pfgd = (FILEGROUPDESCRIPTORW *)GlobalAlloc(GPTR, SIZEOF(FILEGROUPDESCRIPTORW));
  566. if (pfgd)
  567. {
  568. FILEDESCRIPTORW * pfd = &(pfgd->fgd[0]);
  569. TCHAR szTemp[MAX_PATH];
  570. if (pfmtetc->dwAspect == DVASPECT_COPY)
  571. {
  572. pfd->dwFlags = FD_FILESIZE;
  573. GetDocumentName(szTemp);
  574. }
  575. else
  576. {
  577. pfd->dwFlags = FD_FILESIZE | FD_LINKUI;
  578. GetDescription(szTemp, ARRAYSIZE(szTemp));
  579. }
  580. SHTCharToUnicode(PathFindFileName(szTemp), pfd->cFileName, SIZECHARS(pfd->cFileName));
  581. pfd->nFileSizeHigh = 0;
  582. pfd->nFileSizeLow = GetFileContentsAndSize(NULL);
  583. pfgd->cItems = 1;
  584. pstgmed->tymed = TYMED_HGLOBAL;
  585. pstgmed->hGlobal = pfgd;
  586. hr = S_OK;
  587. }
  588. else
  589. hr = E_OUTOFMEMORY;
  590. }
  591. else
  592. hr = DV_E_TYMED;
  593. return hr;
  594. }
  595. #if defined(BIG_ENDIAN) && defined(BYTE_ORDER)
  596. #if BYTE_ORDER != BIG_ENDIAN
  597. #undef BIG_ENDIAN
  598. #endif
  599. #endif
  600. #ifdef BIG_ENDIAN
  601. #define BOM 0xfffe
  602. #else
  603. #define BOM 0xfeff
  604. #endif
  605. STDMETHODIMP Intshcut::GetDocumentStream(IStream **ppstm)
  606. {
  607. *ppstm = NULL;
  608. WCHAR *pszURL;
  609. HRESULT hres = GetURLW(&pszURL);
  610. if (S_OK == hres)
  611. {
  612. IStream *pstm;
  613. hres = URLOpenBlockingStreamW(NULL, pszURL, &pstm, 0, NULL);
  614. if (SUCCEEDED(hres))
  615. {
  616. TCHAR szMime[80];
  617. if (GetStreamMimeAndExt(pszURL, pstm, szMime, ARRAYSIZE(szMime), NULL, 0) &&
  618. StrCmpI(szMime, TEXT("text/html")) == 0)
  619. {
  620. IStream *aStreams[2];
  621. if(m_uiCodePage == 1200) // Unicode
  622. {
  623. WCHAR wzBaseTag[INTERNET_MAX_URL_LENGTH + 20];
  624. wnsprintfW(wzBaseTag, ARRAYSIZE(wzBaseTag), TEXT("%wc<BASE HREF=\"%ws\">\n"), (WCHAR)BOM, pszURL);
  625. aStreams[0] = SHCreateMemStream((BYTE *)wzBaseTag, lstrlenW(wzBaseTag) * SIZEOF(wzBaseTag[0]));
  626. }
  627. else
  628. {
  629. CHAR szURL[INTERNET_MAX_URL_LENGTH], szBaseTag[INTERNET_MAX_URL_LENGTH + 20];
  630. SHUnicodeToAnsi(pszURL, szURL, ARRAYSIZE(szURL));
  631. wnsprintfA(szBaseTag, ARRAYSIZE(szBaseTag), "<BASE HREF=\"%s\">\n", szURL);
  632. // NOTE: this is an ANSI stream
  633. aStreams[0] = SHCreateMemStream((BYTE *)szBaseTag, lstrlenA(szBaseTag) * SIZEOF(szBaseTag[0]));
  634. }
  635. if (aStreams[0])
  636. {
  637. aStreams[1] = pstm;
  638. hres = SHCreateStreamWrapperCP(aStreams, ARRAYSIZE(aStreams), STGM_READ, m_uiCodePage, ppstm);
  639. aStreams[0]->Release();
  640. }
  641. else
  642. hres = E_OUTOFMEMORY;
  643. pstm->Release();
  644. }
  645. else
  646. *ppstm = pstm;
  647. }
  648. SHFree(pszURL);
  649. }
  650. else
  651. hres = E_FAIL;
  652. return hres;
  653. }
  654. // transfer URL data in file-contents clipboard format.
  655. STDMETHODIMP Intshcut::TransferFileContents(FORMATETC *pfmtetc, STGMEDIUM *pstgmed)
  656. {
  657. HRESULT hr;
  658. if (pfmtetc->lindex != 0)
  659. return DV_E_LINDEX;
  660. if ((pfmtetc->dwAspect == DVASPECT_CONTENT ||
  661. pfmtetc->dwAspect == DVASPECT_LINK) &&
  662. (pfmtetc->tymed & TYMED_HGLOBAL))
  663. {
  664. LPSTR pszFileContents;
  665. DWORD cbSize = GetFileContentsAndSize(&pszFileContents);
  666. if (pszFileContents)
  667. {
  668. pstgmed->tymed = TYMED_HGLOBAL;
  669. pstgmed->hGlobal = pszFileContents;
  670. hr = S_OK;
  671. }
  672. else
  673. hr = E_OUTOFMEMORY;
  674. }
  675. else if ((pfmtetc->dwAspect == DVASPECT_COPY) && (pfmtetc->tymed & TYMED_ISTREAM))
  676. {
  677. hr = GetDocumentStream(&pstgmed->pstm);
  678. if (SUCCEEDED(hr))
  679. {
  680. pstgmed->tymed = TYMED_ISTREAM;
  681. hr = S_OK;
  682. }
  683. }
  684. else
  685. hr = DV_E_TYMED;
  686. return hr;
  687. }
  688. #ifdef DEBUG
  689. STDMETHODIMP_(void) Intshcut::Dump(void)
  690. {
  691. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  692. #define INDENT_STRING " "
  693. if (IsFlagSet(g_dwDumpFlags, DF_INTSHCUT))
  694. {
  695. TraceMsg(TF_ALWAYS, "%sm_dwFlags = %#08lx",
  696. INDENT_STRING,
  697. m_dwFlags);
  698. TraceMsg(TF_ALWAYS, "%sm_pszFile = \"%s\"",
  699. INDENT_STRING,
  700. Dbg_SafeStr(m_pszFile));
  701. if (m_pprop)
  702. m_pprop->Dump();
  703. }
  704. }
  705. #endif // DEBUG