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.

1601 lines
41 KiB

  1. /*
  2. * persist.cpp - IPersist, IPersistFile, and IPersistStream implementations for
  3. * URL class.
  4. */
  5. /* Headers
  6. **********/
  7. #include "project.hpp"
  8. #pragma hdrstop
  9. #include "resource.h"
  10. #include <mluisupp.h>
  11. /* Global Constants
  12. *******************/
  13. #pragma data_seg(DATA_SEG_READ_ONLY)
  14. extern const UINT g_ucMaxURLLen = 1024;
  15. extern const char g_cszURLPrefix[] = "url:";
  16. extern const UINT g_ucbURLPrefixLen = sizeof(g_cszURLPrefix) - 1;
  17. extern const char g_cszURLExt[] = ".url";
  18. extern const char g_cszURLDefaultFileNamePrompt[] = "*.url";
  19. extern const char g_cszCRLF[] = "\r\n";
  20. #pragma data_seg()
  21. /* Module Constants
  22. *******************/
  23. #pragma data_seg(DATA_SEG_READ_ONLY)
  24. // case-insensitive
  25. PRIVATE_DATA const char s_cszInternetShortcutSection[] = "InternetShortcut";
  26. PRIVATE_DATA const char s_cszURLKey[] = "URL";
  27. PRIVATE_DATA const char s_cszIconFileKey[] = "IconFile";
  28. PRIVATE_DATA const char s_cszIconIndexKey[] = "IconIndex";
  29. PRIVATE_DATA const char s_cszHotkeyKey[] = "Hotkey";
  30. PRIVATE_DATA const char s_cszWorkingDirectoryKey[] = "WorkingDirectory";
  31. PRIVATE_DATA const char s_cszShowCmdKey[] = "ShowCommand";
  32. PRIVATE_DATA const UINT s_ucMaxIconIndexLen = 1 + 10 + 1; // -2147483647
  33. PRIVATE_DATA const UINT s_ucMaxHotkeyLen = s_ucMaxIconIndexLen;
  34. PRIVATE_DATA const UINT s_ucMaxShowCmdLen = s_ucMaxIconIndexLen;
  35. #pragma data_seg()
  36. /***************************** Private Functions *****************************/
  37. PRIVATE_CODE BOOL DeletePrivateProfileString(PCSTR pcszSection, PCSTR pcszKey,
  38. PCSTR pcszFile)
  39. {
  40. ASSERT(IS_VALID_STRING_PTR(pcszSection, CSTR));
  41. ASSERT(IS_VALID_STRING_PTR(pcszKey, CSTR));
  42. ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
  43. return(WritePrivateProfileString(pcszSection, pcszKey, NULL, pcszFile));
  44. }
  45. #define SHDeleteIniString(pcszSection, pcszKey, pcszFile) \
  46. SHSetIniString(pcszSection, pcszKey, NULL, pcszFile)
  47. PRIVATE_CODE HRESULT MassageURL(PSTR pszURL)
  48. {
  49. HRESULT hr = E_FAIL;
  50. ASSERT(IS_VALID_STRING_PTR(pszURL, STR));
  51. TrimWhiteSpace(pszURL);
  52. PSTR pszBase = pszURL;
  53. PSTR psz;
  54. // Skip over any "url:" prefix.
  55. if (! lstrnicmp(pszBase, g_cszURLPrefix, g_ucbURLPrefixLen))
  56. pszBase += g_ucbURLPrefixLen;
  57. lstrcpy(pszURL, pszBase);
  58. hr = S_OK;
  59. TRACE_OUT(("MassageURL(): Massaged URL to %s.",
  60. pszURL));
  61. ASSERT(FAILED(hr) ||
  62. IS_VALID_STRING_PTR(pszURL, STR));
  63. return(hr);
  64. }
  65. PRIVATE_CODE HRESULT ReadURLFromFile(PCSTR pcszFile, PSTR *ppszURL)
  66. {
  67. HRESULT hr;
  68. PSTR pszNewURL;
  69. ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
  70. ASSERT(IS_VALID_WRITE_PTR(ppszURL, PSTR));
  71. *ppszURL = NULL;
  72. pszNewURL = new(char[g_ucMaxURLLen]);
  73. if (pszNewURL)
  74. {
  75. DWORD dwcValueLen;
  76. dwcValueLen = SHGetIniString(s_cszInternetShortcutSection,
  77. s_cszURLKey,
  78. pszNewURL, g_ucMaxURLLen, pcszFile);
  79. if (dwcValueLen > 0)
  80. {
  81. hr = MassageURL(pszNewURL);
  82. if (hr == S_OK)
  83. {
  84. PSTR pszShorterURL;
  85. // (+ 1) for null terminator.
  86. if (ReallocateMemory(pszNewURL, lstrlen(pszNewURL) + 1,
  87. (PVOID *)&pszShorterURL))
  88. {
  89. *ppszURL = pszShorterURL;
  90. hr = S_OK;
  91. }
  92. else
  93. hr = E_OUTOFMEMORY;
  94. }
  95. }
  96. else
  97. {
  98. hr = S_FALSE;
  99. WARNING_OUT(("ReadURLFromFile: No URL found in file %s.",
  100. pcszFile));
  101. }
  102. }
  103. else
  104. hr = E_OUTOFMEMORY;
  105. if (FAILED(hr) ||
  106. hr == S_FALSE)
  107. {
  108. if (pszNewURL)
  109. {
  110. delete pszNewURL;
  111. pszNewURL = NULL;
  112. }
  113. }
  114. ASSERT((hr == S_OK &&
  115. IS_VALID_STRING_PTR(*ppszURL, STR)) ||
  116. (hr != S_OK &&
  117. ! *ppszURL));
  118. return(hr);
  119. }
  120. PRIVATE_CODE HRESULT WriteURLToFile(PCSTR pcszFile, PCSTR pcszURL)
  121. {
  122. HRESULT hr;
  123. ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
  124. ASSERT(! pcszURL ||
  125. IS_VALID_STRING_PTR(pcszURL, CSTR));
  126. if (AnyMeat(pcszURL))
  127. {
  128. int ncbLen;
  129. ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
  130. ASSERT(IS_VALID_STRING_PTR(pcszURL, PSTR));
  131. hr = (SHSetIniString(s_cszInternetShortcutSection, s_cszURLKey, pcszURL, pcszFile))
  132. ? S_OK
  133. : E_FAIL;
  134. }
  135. else
  136. hr = (SHDeleteIniString(s_cszInternetShortcutSection, s_cszURLKey, pcszFile))
  137. ? S_OK
  138. : E_FAIL;
  139. return(hr);
  140. }
  141. PRIVATE_CODE HRESULT ReadIconLocationFromFile(PCSTR pcszFile,
  142. PSTR *ppszIconFile, PINT pniIcon)
  143. {
  144. HRESULT hr;
  145. char rgchNewIconFile[MAX_PATH_LEN];
  146. DWORD dwcValueLen;
  147. ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
  148. ASSERT(IS_VALID_WRITE_PTR(ppszIconFile, PSTR));
  149. ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT));
  150. *ppszIconFile = NULL;
  151. *pniIcon = 0;
  152. dwcValueLen = SHGetIniString(s_cszInternetShortcutSection,
  153. s_cszIconFileKey,
  154. rgchNewIconFile,
  155. sizeof(rgchNewIconFile), pcszFile);
  156. if (dwcValueLen > 0)
  157. {
  158. char rgchNewIconIndex[s_ucMaxIconIndexLen];
  159. dwcValueLen = GetPrivateProfileString(s_cszInternetShortcutSection,
  160. s_cszIconIndexKey,
  161. EMPTY_STRING, rgchNewIconIndex,
  162. sizeof(rgchNewIconIndex),
  163. pcszFile);
  164. if (dwcValueLen > 0)
  165. {
  166. int niIcon;
  167. if (StrToIntEx(rgchNewIconIndex, 0, &niIcon))
  168. {
  169. // (+ 1) for null terminator.
  170. *ppszIconFile = new(char[lstrlen(rgchNewIconFile) + 1]);
  171. if (*ppszIconFile)
  172. {
  173. lstrcpy(*ppszIconFile, rgchNewIconFile);
  174. *pniIcon = niIcon;
  175. hr = S_OK;
  176. }
  177. else
  178. hr = E_OUTOFMEMORY;
  179. }
  180. else
  181. {
  182. hr = S_FALSE;
  183. WARNING_OUT(("ReadIconLocationFromFile(): Bad icon index \"%s\" found in file %s.",
  184. rgchNewIconIndex,
  185. pcszFile));
  186. }
  187. }
  188. else
  189. {
  190. hr = S_FALSE;
  191. WARNING_OUT(("ReadIconLocationFromFile(): No icon index found in file %s.",
  192. pcszFile));
  193. }
  194. }
  195. else
  196. {
  197. hr = S_FALSE;
  198. TRACE_OUT(("ReadIconLocationFromFile(): No icon file found in file %s.",
  199. pcszFile));
  200. }
  201. ASSERT(IsValidIconIndex(hr, *ppszIconFile, MAX_PATH_LEN, *pniIcon));
  202. return(hr);
  203. }
  204. PRIVATE_CODE HRESULT WriteIconLocationToFile(PCSTR pcszFile,
  205. PCSTR pcszIconFile,
  206. int niIcon)
  207. {
  208. HRESULT hr;
  209. ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
  210. ASSERT(! pcszIconFile ||
  211. IS_VALID_STRING_PTR(pcszIconFile, CSTR));
  212. ASSERT(IsValidIconIndex((pcszIconFile ? S_OK : S_FALSE), pcszIconFile, MAX_PATH_LEN, niIcon));
  213. if (AnyMeat(pcszIconFile))
  214. {
  215. char rgchIconIndexRHS[s_ucMaxIconIndexLen];
  216. int ncLen;
  217. ncLen = wsprintf(rgchIconIndexRHS, "%d", niIcon);
  218. ASSERT(ncLen > 0);
  219. ASSERT(ncLen < sizeof(rgchIconIndexRHS));
  220. ASSERT(ncLen == lstrlen(rgchIconIndexRHS));
  221. hr = (SHSetIniString(s_cszInternetShortcutSection,
  222. s_cszIconFileKey, pcszIconFile,
  223. pcszFile) &&
  224. WritePrivateProfileString(s_cszInternetShortcutSection,
  225. s_cszIconIndexKey, rgchIconIndexRHS,
  226. pcszFile))
  227. ? S_OK
  228. : E_FAIL;
  229. }
  230. else
  231. hr = (SHDeleteIniString(s_cszInternetShortcutSection,
  232. s_cszIconFileKey, pcszFile) &&
  233. DeletePrivateProfileString(s_cszInternetShortcutSection,
  234. s_cszIconIndexKey, pcszFile))
  235. ? S_OK
  236. : E_FAIL;
  237. return(hr);
  238. }
  239. PRIVATE_CODE HRESULT ReadHotkeyFromFile(PCSTR pcszFile, PWORD pwHotkey)
  240. {
  241. HRESULT hr = S_FALSE;
  242. char rgchHotkey[s_ucMaxHotkeyLen];
  243. DWORD dwcValueLen;
  244. ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
  245. ASSERT(IS_VALID_WRITE_PTR(pwHotkey, WORD));
  246. *pwHotkey = 0;
  247. dwcValueLen = GetPrivateProfileString(s_cszInternetShortcutSection,
  248. s_cszHotkeyKey, EMPTY_STRING,
  249. rgchHotkey, sizeof(rgchHotkey),
  250. pcszFile);
  251. if (dwcValueLen > 0)
  252. {
  253. UINT uHotkey;
  254. if (StrToIntEx(rgchHotkey, 0, (int *)&uHotkey))
  255. {
  256. *pwHotkey = (WORD)uHotkey;
  257. hr = S_OK;
  258. }
  259. else
  260. WARNING_OUT(("ReadHotkeyFromFile(): Bad hotkey \"%s\" found in file %s.",
  261. rgchHotkey,
  262. pcszFile));
  263. }
  264. else
  265. WARNING_OUT(("ReadHotkeyFromFile(): No hotkey found in file %s.",
  266. pcszFile));
  267. ASSERT((hr == S_OK &&
  268. IsValidHotkey(*pwHotkey)) ||
  269. (hr == S_FALSE &&
  270. ! *pwHotkey));
  271. return(hr);
  272. }
  273. PRIVATE_CODE HRESULT WriteHotkeyToFile(PCSTR pcszFile, WORD wHotkey)
  274. {
  275. HRESULT hr;
  276. ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
  277. ASSERT(! wHotkey ||
  278. IsValidHotkey(wHotkey));
  279. if (wHotkey)
  280. {
  281. char rgchHotkeyRHS[s_ucMaxHotkeyLen];
  282. int ncLen;
  283. ncLen = wsprintf(rgchHotkeyRHS, "%u", (UINT)wHotkey);
  284. ASSERT(ncLen > 0);
  285. ASSERT(ncLen < sizeof(rgchHotkeyRHS));
  286. ASSERT(ncLen == lstrlen(rgchHotkeyRHS));
  287. hr = WritePrivateProfileString(s_cszInternetShortcutSection,
  288. s_cszHotkeyKey, rgchHotkeyRHS,
  289. pcszFile)
  290. ? S_OK
  291. : E_FAIL;
  292. }
  293. else
  294. hr = DeletePrivateProfileString(s_cszInternetShortcutSection,
  295. s_cszHotkeyKey, pcszFile)
  296. ? S_OK
  297. : E_FAIL;
  298. return(hr);
  299. }
  300. PRIVATE_CODE HRESULT ReadWorkingDirectoryFromFile(PCSTR pcszFile,
  301. PSTR *ppszWorkingDirectory)
  302. {
  303. HRESULT hr;
  304. char rgchDirValue[MAX_PATH_LEN];
  305. DWORD dwcValueLen;
  306. ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
  307. ASSERT(IS_VALID_WRITE_PTR(ppszWorkingDirectory, PSTR));
  308. *ppszWorkingDirectory = NULL;
  309. dwcValueLen = SHGetIniString(s_cszInternetShortcutSection,
  310. s_cszWorkingDirectoryKey,
  311. rgchDirValue,
  312. sizeof(rgchDirValue), pcszFile);
  313. if (dwcValueLen > 0)
  314. {
  315. char rgchFullPath[MAX_PATH_LEN];
  316. PSTR pszFileName;
  317. if (GetFullPathName(rgchDirValue, sizeof(rgchFullPath), rgchFullPath,
  318. &pszFileName) > 0)
  319. {
  320. // (+ 1) for null terminator.
  321. *ppszWorkingDirectory = new(char[lstrlen(rgchFullPath) + 1]);
  322. if (*ppszWorkingDirectory)
  323. {
  324. lstrcpy(*ppszWorkingDirectory, rgchFullPath);
  325. hr = S_OK;
  326. }
  327. else
  328. hr = E_OUTOFMEMORY;
  329. }
  330. else
  331. hr = E_FAIL;
  332. }
  333. else
  334. {
  335. hr = S_FALSE;
  336. TRACE_OUT(("ReadWorkingDirectoryFromFile: No working directory found in file %s.",
  337. pcszFile));
  338. }
  339. ASSERT(IsValidPathResult(hr, *ppszWorkingDirectory, MAX_PATH_LEN));
  340. return(hr);
  341. }
  342. PRIVATE_CODE HRESULT WriteWorkingDirectoryToFile(PCSTR pcszFile,
  343. PCSTR pcszWorkingDirectory)
  344. {
  345. HRESULT hr;
  346. ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
  347. ASSERT(! pcszWorkingDirectory ||
  348. IS_VALID_STRING_PTR(pcszWorkingDirectory, CSTR));
  349. if (AnyMeat(pcszWorkingDirectory))
  350. hr = (SHSetIniString(s_cszInternetShortcutSection,
  351. s_cszWorkingDirectoryKey,
  352. pcszWorkingDirectory, pcszFile))
  353. ? S_OK
  354. : E_FAIL;
  355. else
  356. hr = (SHDeleteIniString(s_cszInternetShortcutSection,
  357. s_cszWorkingDirectoryKey, pcszFile))
  358. ? S_OK
  359. : E_FAIL;
  360. return(hr);
  361. }
  362. PRIVATE_CODE HRESULT ReadShowCmdFromFile(PCSTR pcszFile, PINT pnShowCmd)
  363. {
  364. HRESULT hr;
  365. char rgchNewShowCmd[s_ucMaxShowCmdLen];
  366. DWORD dwcValueLen;
  367. ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
  368. ASSERT(IS_VALID_WRITE_PTR(pnShowCmd, INT));
  369. *pnShowCmd = g_nDefaultShowCmd;
  370. dwcValueLen = GetPrivateProfileString(s_cszInternetShortcutSection,
  371. s_cszShowCmdKey, EMPTY_STRING,
  372. rgchNewShowCmd,
  373. sizeof(rgchNewShowCmd), pcszFile);
  374. if (dwcValueLen > 0)
  375. {
  376. int nShowCmd;
  377. if (StrToIntEx(rgchNewShowCmd, 0, &nShowCmd))
  378. {
  379. *pnShowCmd = nShowCmd;
  380. hr = S_OK;
  381. }
  382. else
  383. {
  384. hr = S_FALSE;
  385. WARNING_OUT(("ReadShowCmdFromFile: Invalid show command \"%s\" found in file %s.",
  386. rgchNewShowCmd,
  387. pcszFile));
  388. }
  389. }
  390. else
  391. {
  392. hr = S_FALSE;
  393. TRACE_OUT(("ReadShowCmdFromFile: No show command found in file %s.",
  394. pcszFile));
  395. }
  396. ASSERT((hr == S_OK &&
  397. EVAL(IsValidShowCmd(*pnShowCmd))) ||
  398. (hr == S_FALSE &&
  399. EVAL(*pnShowCmd == g_nDefaultShowCmd)));
  400. return(hr);
  401. }
  402. PRIVATE_CODE HRESULT WriteShowCmdToFile(PCSTR pcszFile, int nShowCmd)
  403. {
  404. HRESULT hr;
  405. ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
  406. ASSERT(IsValidShowCmd(nShowCmd));
  407. if (nShowCmd != g_nDefaultShowCmd)
  408. {
  409. char rgchShowCmdRHS[s_ucMaxShowCmdLen];
  410. int ncLen;
  411. ncLen = wsprintf(rgchShowCmdRHS, "%d", nShowCmd);
  412. ASSERT(ncLen > 0);
  413. ASSERT(ncLen < sizeof(rgchShowCmdRHS));
  414. ASSERT(ncLen == lstrlen(rgchShowCmdRHS));
  415. hr = (WritePrivateProfileString(s_cszInternetShortcutSection,
  416. s_cszShowCmdKey, rgchShowCmdRHS,
  417. pcszFile))
  418. ? S_OK
  419. : E_FAIL;
  420. }
  421. else
  422. hr = (DeletePrivateProfileString(s_cszInternetShortcutSection,
  423. s_cszShowCmdKey, pcszFile))
  424. ? S_OK
  425. : E_FAIL;
  426. return(hr);
  427. }
  428. /****************************** Public Functions *****************************/
  429. PUBLIC_CODE HRESULT UnicodeToANSI(LPCOLESTR pcwszUnicode, PSTR *ppszANSI)
  430. {
  431. HRESULT hr;
  432. int ncbLen;
  433. // FEATURE: Need OLESTR validation function to validate pcwszUnicode here.
  434. ASSERT(IS_VALID_WRITE_PTR(ppszANSI, PSTR));
  435. *ppszANSI = NULL;
  436. // Get length of translated string.
  437. ncbLen = WideCharToMultiByte(CP_ACP, 0, pcwszUnicode, -1, NULL, 0, NULL,
  438. NULL);
  439. if (ncbLen > 0)
  440. {
  441. PSTR pszNewANSI;
  442. // (+ 1) for null terminator.
  443. pszNewANSI = new(char[ncbLen]);
  444. if (pszNewANSI)
  445. {
  446. // Translate string.
  447. if (WideCharToMultiByte(CP_ACP, 0, pcwszUnicode, -1, pszNewANSI,
  448. ncbLen, NULL, NULL) > 0)
  449. {
  450. *ppszANSI = pszNewANSI;
  451. hr = S_OK;
  452. }
  453. else
  454. {
  455. delete pszNewANSI;
  456. pszNewANSI = NULL;
  457. hr = E_UNEXPECTED;
  458. WARNING_OUT(("UnicodeToANSI(): Failed to translate Unicode string to ANSI."));
  459. }
  460. }
  461. else
  462. hr = E_OUTOFMEMORY;
  463. }
  464. else
  465. {
  466. hr = E_UNEXPECTED;
  467. WARNING_OUT(("UnicodeToANSI(): Failed to get length of translated ANSI string."));
  468. }
  469. ASSERT(FAILED(hr) ||
  470. IS_VALID_STRING_PTR(*ppszANSI, STR));
  471. return(hr);
  472. }
  473. PUBLIC_CODE HRESULT ANSIToUnicode(PCSTR pcszANSI, LPOLESTR *ppwszUnicode)
  474. {
  475. HRESULT hr;
  476. int ncbWideLen;
  477. ASSERT(IS_VALID_STRING_PTR(pcszANSI, CSTR));
  478. ASSERT(IS_VALID_WRITE_PTR(ppwszUnicode, LPOLESTR));
  479. *ppwszUnicode = NULL;
  480. // Get length of translated string.
  481. ncbWideLen = MultiByteToWideChar(CP_ACP, 0, pcszANSI, -1, NULL, 0);
  482. if (ncbWideLen > 0)
  483. {
  484. PWSTR pwszNewUnicode;
  485. // (+ 1) for null terminator.
  486. pwszNewUnicode = new(WCHAR[ncbWideLen]);
  487. if (pwszNewUnicode)
  488. {
  489. // Translate string.
  490. if (MultiByteToWideChar(CP_ACP, 0, pcszANSI, -1, pwszNewUnicode,
  491. ncbWideLen) > 0)
  492. {
  493. *ppwszUnicode = pwszNewUnicode;
  494. hr = S_OK;
  495. }
  496. else
  497. {
  498. delete pwszNewUnicode;
  499. pwszNewUnicode = NULL;
  500. hr = E_UNEXPECTED;
  501. WARNING_OUT(("ANSIToUnicode(): Failed to translate ANSI path string to Unicode."));
  502. }
  503. }
  504. else
  505. hr = E_OUTOFMEMORY;
  506. }
  507. else
  508. {
  509. hr = E_UNEXPECTED;
  510. WARNING_OUT(("ANSIToUnicode(): Failed to get length of translated Unicode string."));
  511. }
  512. // FEATURE: Need OLESTR validation function to validate *ppwszUnicode here.
  513. return(hr);
  514. }
  515. /********************************** Methods **********************************/
  516. HRESULT STDMETHODCALLTYPE InternetShortcut::SaveToFile(PCSTR pcszFile,
  517. BOOL bRemember)
  518. {
  519. HRESULT hr;
  520. PSTR pszURL;
  521. DebugEntry(InternetShortcut::SaveToFile);
  522. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  523. ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
  524. hr = GetURL(&pszURL);
  525. if (SUCCEEDED(hr))
  526. {
  527. hr = WriteURLToFile(pcszFile, pszURL);
  528. if (pszURL)
  529. {
  530. SHFree(pszURL);
  531. pszURL = NULL;
  532. }
  533. if (hr == S_OK)
  534. {
  535. char rgchBuf[MAX_PATH_LEN];
  536. int niIcon;
  537. hr = GetIconLocation(rgchBuf, sizeof(rgchBuf), &niIcon);
  538. if (SUCCEEDED(hr))
  539. {
  540. hr = WriteIconLocationToFile(pcszFile, rgchBuf, niIcon);
  541. if (hr == S_OK)
  542. {
  543. WORD wHotkey;
  544. hr = GetHotkey(&wHotkey);
  545. if (SUCCEEDED(hr))
  546. {
  547. hr = WriteHotkeyToFile(pcszFile, wHotkey);
  548. if (hr == S_OK)
  549. {
  550. hr = GetWorkingDirectory(rgchBuf, sizeof(rgchBuf));
  551. if (SUCCEEDED(hr))
  552. {
  553. hr = WriteWorkingDirectoryToFile(pcszFile, rgchBuf);
  554. if (hr == S_OK)
  555. {
  556. int nShowCmd;
  557. GetShowCmd(&nShowCmd);
  558. hr = WriteShowCmdToFile(pcszFile, nShowCmd);
  559. if (hr == S_OK)
  560. {
  561. /* Remember file if requested. */
  562. if (bRemember)
  563. {
  564. PSTR pszFileCopy;
  565. if (StringCopy(pcszFile, &pszFileCopy))
  566. {
  567. if (m_pszFile)
  568. delete m_pszFile;
  569. m_pszFile = pszFileCopy;
  570. TRACE_OUT(("InternetShortcut::SaveToFile(): Remembering file %s, as requested.",
  571. m_pszFile));
  572. }
  573. else
  574. hr = E_OUTOFMEMORY;
  575. }
  576. if (hr == S_OK)
  577. {
  578. Dirty(FALSE);
  579. SHChangeNotify(SHCNE_UPDATEITEM,
  580. (SHCNF_PATH | SHCNF_FLUSH), pcszFile,
  581. NULL);
  582. #ifdef DEBUG
  583. TRACE_OUT(("InternetShortcut::SaveToFile(): Internet Shortcut saved to file %s:",
  584. pcszFile));
  585. Dump();
  586. #endif
  587. }
  588. }
  589. }
  590. }
  591. }
  592. }
  593. }
  594. }
  595. }
  596. }
  597. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  598. DebugExitHRESULT(InternetShortcut::SaveToFile, hr);
  599. return(hr);
  600. }
  601. HRESULT STDMETHODCALLTYPE InternetShortcut::LoadFromFile(PCSTR pcszFile,
  602. BOOL bRemember)
  603. {
  604. HRESULT hr;
  605. PSTR pszURL;
  606. DebugEntry(InternetShortcut::LoadFromFile);
  607. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  608. ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
  609. hr = ReadURLFromFile(pcszFile, &pszURL);
  610. if (SUCCEEDED(hr))
  611. {
  612. hr = SetURL(pszURL, (IURL_SETURL_FL_GUESS_PROTOCOL |
  613. IURL_SETURL_FL_USE_DEFAULT_PROTOCOL));
  614. if (pszURL)
  615. {
  616. delete pszURL;
  617. pszURL = NULL;
  618. }
  619. if (hr == S_OK)
  620. {
  621. PSTR pszIconFile;
  622. int niIcon;
  623. hr = ReadIconLocationFromFile(pcszFile, &pszIconFile, &niIcon);
  624. if (SUCCEEDED(hr))
  625. {
  626. hr = SetIconLocation(pszIconFile, niIcon);
  627. if (pszIconFile)
  628. {
  629. delete pszIconFile;
  630. pszIconFile = NULL;
  631. }
  632. if (hr == S_OK)
  633. {
  634. WORD wHotkey;
  635. hr = ReadHotkeyFromFile(pcszFile, &wHotkey);
  636. if (SUCCEEDED(hr))
  637. {
  638. hr = SetHotkey(wHotkey);
  639. if (hr == S_OK)
  640. {
  641. PSTR pszWorkingDirectory;
  642. hr = ReadWorkingDirectoryFromFile(pcszFile,
  643. &pszWorkingDirectory);
  644. if (SUCCEEDED(hr))
  645. {
  646. hr = SetWorkingDirectory(pszWorkingDirectory);
  647. if (pszWorkingDirectory)
  648. {
  649. delete pszWorkingDirectory;
  650. pszWorkingDirectory = NULL;
  651. }
  652. if (hr == S_OK)
  653. {
  654. int nShowCmd;
  655. hr = ReadShowCmdFromFile(pcszFile, &nShowCmd);
  656. if (SUCCEEDED(hr))
  657. {
  658. /* Remember file if requested. */
  659. if (bRemember)
  660. {
  661. PSTR pszFileCopy;
  662. if (StringCopy(pcszFile, &pszFileCopy))
  663. {
  664. if (m_pszFile)
  665. delete m_pszFile;
  666. m_pszFile = pszFileCopy;
  667. TRACE_OUT(("InternetShortcut::LoadFromFile(): Remembering file %s, as requested.",
  668. m_pszFile));
  669. }
  670. else
  671. hr = E_OUTOFMEMORY;
  672. }
  673. if (SUCCEEDED(hr))
  674. {
  675. SetShowCmd(nShowCmd);
  676. Dirty(FALSE);
  677. hr = S_OK;
  678. #ifdef DEBUG
  679. TRACE_OUT(("InternetShortcut::LoadFromFile(): Internet Shortcut loaded from file %s:",
  680. pcszFile));
  681. Dump();
  682. #endif
  683. }
  684. }
  685. }
  686. }
  687. }
  688. }
  689. }
  690. }
  691. }
  692. }
  693. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  694. DebugExitHRESULT(InternetShortcut::LoadFromFile, hr);
  695. return(hr);
  696. }
  697. HRESULT STDMETHODCALLTYPE InternetShortcut::GetCurFile(PSTR pszFile,
  698. UINT ucbLen)
  699. {
  700. HRESULT hr;
  701. DebugEntry(InternetShortcut::GetCurFile);
  702. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  703. ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszFile, STR, ucbLen));
  704. if (m_pszFile)
  705. {
  706. lstrcpyn(pszFile, m_pszFile, ucbLen);
  707. TRACE_OUT(("InternetShortcut::GetCurFile(): Current file name is %s.",
  708. pszFile));
  709. hr = S_OK;
  710. }
  711. else
  712. hr = S_FALSE;
  713. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  714. ASSERT(IS_VALID_STRING_PTR(pszFile, STR) &&
  715. EVAL((UINT)lstrlen(pszFile) < ucbLen));
  716. ASSERT(hr == S_OK ||
  717. hr == S_FALSE);
  718. DebugExitHRESULT(InternetShortcut::GetCurFile, hr);
  719. return(hr);
  720. }
  721. HRESULT STDMETHODCALLTYPE InternetShortcut::Dirty(BOOL bDirty)
  722. {
  723. HRESULT hr;
  724. DebugEntry(InternetShortcut::Dirty);
  725. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  726. if (bDirty)
  727. {
  728. if (IS_FLAG_CLEAR(m_dwFlags, INTSHCUT_FL_DIRTY)) {
  729. TRACE_OUT(("InternetShortcut::Dirty(): Now dirty."));
  730. }
  731. SET_FLAG(m_dwFlags, INTSHCUT_FL_DIRTY);
  732. }
  733. else
  734. {
  735. if (IS_FLAG_SET(m_dwFlags, INTSHCUT_FL_DIRTY)) {
  736. TRACE_OUT(("InternetShortcut::Dirty(): Now clean."));
  737. }
  738. CLEAR_FLAG(m_dwFlags, INTSHCUT_FL_DIRTY);
  739. }
  740. hr = S_OK;
  741. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  742. ASSERT(hr == S_OK);
  743. DebugExitVOID(InternetShortcut::Dirty);
  744. return(hr);
  745. }
  746. HRESULT STDMETHODCALLTYPE InternetShortcut::GetClassID(PCLSID pclsid)
  747. {
  748. HRESULT hr;
  749. DebugEntry(InternetShortcut::GetClassID);
  750. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  751. ASSERT(IS_VALID_STRUCT_PTR(pclsid, CCLSID));
  752. *pclsid = CLSID_InternetShortcut;
  753. hr = S_OK;
  754. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  755. ASSERT(FAILED(hr) ||
  756. IS_VALID_STRUCT_PTR(pclsid, CCLSID));
  757. DebugExitHRESULT(InternetShortcut::GetClassID, hr);
  758. return(hr);
  759. }
  760. HRESULT STDMETHODCALLTYPE InternetShortcut::IsDirty(void)
  761. {
  762. HRESULT hr;
  763. DebugEntry(InternetShortcut::IsDirty);
  764. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  765. if (IS_FLAG_SET(m_dwFlags, INTSHCUT_FL_DIRTY))
  766. hr = S_OK;
  767. else
  768. hr = S_FALSE;
  769. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  770. DebugExitHRESULT(InternetShortcut::IsDirty, hr);
  771. return(hr);
  772. }
  773. HRESULT STDMETHODCALLTYPE InternetShortcut::Save(LPCOLESTR pcwszFile,
  774. BOOL bRemember)
  775. {
  776. HRESULT hr;
  777. PSTR pszFile;
  778. DebugEntry(InternetShortcut::Save);
  779. // bRemember may be any value.
  780. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  781. // FEATURE: Need OLESTR validation function to validate pcwszFile here.
  782. if (pcwszFile)
  783. {
  784. hr = UnicodeToANSI(pcwszFile, &pszFile);
  785. if (hr == S_OK)
  786. {
  787. hr = SaveToFile(pszFile, bRemember);
  788. delete pszFile;
  789. pszFile = NULL;
  790. }
  791. }
  792. else if (m_pszFile)
  793. // Ignore bRemember.
  794. hr = SaveToFile(m_pszFile, FALSE);
  795. else
  796. hr = E_FAIL;
  797. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  798. DebugExitHRESULT(InternetShortcut::Save, hr);
  799. return(hr);
  800. }
  801. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  802. HRESULT STDMETHODCALLTYPE InternetShortcut::SaveCompleted(LPCOLESTR pcwszFile)
  803. {
  804. HRESULT hr;
  805. DebugEntry(InternetShortcut::SaveCompleted);
  806. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  807. // FEATURE: Need OLESTR validation function to validate pcwszFile here.
  808. hr = S_OK;
  809. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  810. DebugExitHRESULT(InternetShortcut::SaveCompleted, hr);
  811. return(hr);
  812. }
  813. HRESULT STDMETHODCALLTYPE InternetShortcut::Load(LPCOLESTR pcwszFile,
  814. DWORD dwMode)
  815. {
  816. HRESULT hr;
  817. PSTR pszFile;
  818. DebugEntry(InternetShortcut::Load);
  819. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  820. // FEATURE: Need OLESTR validation function to validate pcwszFile here.
  821. // FEATURE: Validate dwMode here.
  822. // FEAUTRE: Implement dwMode flag support.
  823. hr = UnicodeToANSI(pcwszFile, &pszFile);
  824. if (hr == S_OK)
  825. {
  826. hr = LoadFromFile(pszFile, TRUE);
  827. delete pszFile;
  828. pszFile = NULL;
  829. }
  830. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  831. DebugExitHRESULT(InternetShortcut::Load, hr);
  832. return(hr);
  833. }
  834. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */
  835. HRESULT STDMETHODCALLTYPE InternetShortcut::GetCurFile(LPOLESTR *ppwszFile)
  836. {
  837. HRESULT hr;
  838. LPOLESTR pwszTempFile;
  839. DebugEntry(InternetShortcut::GetCurFile);
  840. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  841. ASSERT(IS_VALID_WRITE_PTR(ppwszFile, LPOLESTR));
  842. if (m_pszFile)
  843. {
  844. hr = ANSIToUnicode(m_pszFile, &pwszTempFile);
  845. if (hr == S_OK) {
  846. TRACE_OUT(("InternetShortcut::GetCurFile(): Current file name is %s.",
  847. m_pszFile));
  848. }
  849. }
  850. else
  851. {
  852. hr = ANSIToUnicode(g_cszURLDefaultFileNamePrompt, &pwszTempFile);
  853. if (hr == S_OK)
  854. {
  855. hr = S_FALSE;
  856. TRACE_OUT(("InternetShortcut::GetCurFile(): No current file name. Returning default file name prompt %s.",
  857. g_cszURLDefaultFileNamePrompt));
  858. }
  859. }
  860. if (SUCCEEDED(hr))
  861. {
  862. // We should really call OleGetMalloc() to get the process IMalloc here.
  863. // Use SHAlloc() here instead to avoid loading ole32.dll.
  864. // SHAlloc() / SHFree() turn in to IMalloc::Alloc() and IMalloc::Free()
  865. // once ole32.dll is loaded.
  866. // N.b., lstrlenW() returns the length of the given string in characters,
  867. // not bytes.
  868. // (+ 1) for null terminator.
  869. *ppwszFile = (LPOLESTR)SHAlloc((lstrlenW(pwszTempFile) + 1) *
  870. sizeof(*pwszTempFile));
  871. if (*ppwszFile)
  872. lstrcpyW(*ppwszFile, pwszTempFile);
  873. else
  874. hr = E_OUTOFMEMORY;
  875. delete pwszTempFile;
  876. pwszTempFile = NULL;
  877. }
  878. // FEATURE: Need OLESTR validation function to validate *ppwszFile here.
  879. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  880. DebugExitHRESULT(InternetShortcut::GetCurFile, hr);
  881. return(hr);
  882. }
  883. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  884. HRESULT STDMETHODCALLTYPE InternetShortcut::Load(PIStream pistr)
  885. {
  886. HRESULT hr;
  887. DebugEntry(InternetShortcut::Load);
  888. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  889. ASSERT(IS_VALID_INTERFACE_PTR(pistr, IStream));
  890. hr = E_NOTIMPL;
  891. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  892. DebugExitHRESULT(InternetShortcut::Load, hr);
  893. return(hr);
  894. }
  895. HRESULT STDMETHODCALLTYPE InternetShortcut::Save(PIStream pistr,
  896. BOOL bClearDirty)
  897. {
  898. HRESULT hr;
  899. DebugEntry(InternetShortcut::Save);
  900. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  901. ASSERT(IS_VALID_INTERFACE_PTR(pistr, IStream));
  902. // APPCOMPAT: Yes, this is an awful hack, but that's what we get when
  903. // no one implements a needed interface and we need to get a product
  904. // shipped. (Actually, the hack isn't that bad, as it's what happens in
  905. // TransferFileContents, except we're writing to a stream and not memory).
  906. const static TCHAR s_cszNewLine[] = TEXT("\r\n");
  907. const static TCHAR s_cszPrefix[] = TEXT("[InternetShortcut]\r\nURL=");
  908. LPTSTR pszBuf;
  909. DWORD cb;
  910. pszBuf = (LPTSTR)LocalAlloc(LPTR, lstrlen(m_pszURL) + lstrlen(s_cszPrefix) + lstrlen(s_cszNewLine) + 1);
  911. if (pszBuf)
  912. {
  913. wsprintf(pszBuf, TEXT("%s%s%s"), s_cszPrefix, m_pszURL ? m_pszURL : TEXT("") , s_cszNewLine);
  914. hr = pistr->Write(pszBuf, lstrlen(pszBuf), &cb);
  915. LocalFree(pszBuf);
  916. }
  917. else
  918. {
  919. hr = E_OUTOFMEMORY;
  920. }
  921. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  922. DebugExitHRESULT(InternetShortcut::Save, hr);
  923. return(hr);
  924. }
  925. HRESULT STDMETHODCALLTYPE InternetShortcut::GetSizeMax(PULARGE_INTEGER pcbSize)
  926. {
  927. HRESULT hr;
  928. DebugEntry(InternetShortcut::GetSizeMax);
  929. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  930. ASSERT(IS_VALID_WRITE_PTR(pcbSize, ULARGE_INTEGER));
  931. hr = E_NOTIMPL;
  932. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  933. DebugExitHRESULT(InternetShortcut::GetSizeMax, hr);
  934. return(hr);
  935. }
  936. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */
  937. DWORD STDMETHODCALLTYPE InternetShortcut::GetFileContentsSize(void)
  938. {
  939. DWORD dwcbLen;
  940. DebugEntry(InternetShortcut::GetFileContentsSize);
  941. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  942. // Section length.
  943. // (- 1) for each null terminator.
  944. HRESULT hr = CreateURLFileContents(m_pszURL, NULL);
  945. // REARCHITECT: (DavidDi 3/29/95) We need to save more than just the URL string
  946. // here, i.e., icon file and index, working directory, and show command.
  947. dwcbLen = SUCCEEDED(hr) ? hr : 0;
  948. dwcbLen++; // + 1 for final null terminator
  949. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  950. DebugExitDWORD(InternetShortcut::GetFileContentsSize, dwcbLen);
  951. return(dwcbLen);
  952. }
  953. HRESULT STDMETHODCALLTYPE InternetShortcut::TransferUniformResourceLocator(
  954. PFORMATETC pfmtetc,
  955. PSTGMEDIUM pstgmed)
  956. {
  957. HRESULT hr;
  958. DebugEntry(InternetShortcut::TransferUniformResourceLocator);
  959. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  960. ASSERT(IS_VALID_STRUCT_PTR(pfmtetc, CFORMATETC));
  961. ASSERT(IS_VALID_WRITE_PTR(pstgmed, STGMEDIUM));
  962. ASSERT(pfmtetc->dwAspect == DVASPECT_CONTENT);
  963. ASSERT(pfmtetc->lindex == -1);
  964. ZeroMemory(pstgmed, sizeof(*pstgmed));
  965. if (IS_FLAG_SET(pfmtetc->tymed, TYMED_HGLOBAL))
  966. {
  967. if (m_pszURL)
  968. {
  969. HGLOBAL hgURL;
  970. hr = E_OUTOFMEMORY;
  971. // (+ 1) for null terminator.
  972. hgURL = GlobalAlloc(0, lstrlen(m_pszURL) + 1);
  973. if (hgURL)
  974. {
  975. PSTR pszURL;
  976. pszURL = (PSTR)GlobalLock(hgURL);
  977. if (EVAL(pszURL))
  978. {
  979. lstrcpy(pszURL, m_pszURL);
  980. pstgmed->tymed = TYMED_HGLOBAL;
  981. pstgmed->hGlobal = hgURL;
  982. ASSERT(! pstgmed->pUnkForRelease);
  983. hr = S_OK;
  984. GlobalUnlock(hgURL);
  985. pszURL = NULL;
  986. }
  987. if (hr != S_OK)
  988. {
  989. GlobalFree(hgURL);
  990. hgURL = NULL;
  991. }
  992. }
  993. }
  994. else
  995. hr = DV_E_FORMATETC;
  996. }
  997. else
  998. hr = DV_E_TYMED;
  999. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1000. ASSERT((hr == S_OK &&
  1001. IS_VALID_STRUCT_PTR(pstgmed, CSTGMEDIUM)) ||
  1002. (FAILED(hr) &&
  1003. (EVAL(pstgmed->tymed == TYMED_NULL) &&
  1004. EVAL(! pstgmed->hGlobal) &&
  1005. EVAL(! pstgmed->pUnkForRelease))));
  1006. DebugExitHRESULT(InternetShortcut::TransferUniformResourceLocator, hr);
  1007. return(hr);
  1008. }
  1009. HRESULT STDMETHODCALLTYPE InternetShortcut::TransferText(PFORMATETC pfmtetc,
  1010. PSTGMEDIUM pstgmed)
  1011. {
  1012. HRESULT hr;
  1013. DebugEntry(InternetShortcut::TransferText);
  1014. // Assume InternetShortcut::TransferUniformResourceLocator() will perform
  1015. // input and output validation.
  1016. hr = TransferUniformResourceLocator(pfmtetc, pstgmed);
  1017. DebugExitHRESULT(InternetShortcut::TransferText, hr);
  1018. return(hr);
  1019. }
  1020. HRESULT STDMETHODCALLTYPE InternetShortcut::TransferFileGroupDescriptor(
  1021. PFORMATETC pfmtetc,
  1022. PSTGMEDIUM pstgmed)
  1023. {
  1024. HRESULT hr;
  1025. DebugEntry(InternetShortcut::TransferFileGroupDescriptor);
  1026. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1027. ASSERT(IS_VALID_STRUCT_PTR(pfmtetc, CFORMATETC));
  1028. ASSERT(IS_VALID_WRITE_PTR(pstgmed, STGMEDIUM));
  1029. ASSERT(pfmtetc->dwAspect == DVASPECT_CONTENT);
  1030. ASSERT(pfmtetc->lindex == -1);
  1031. pstgmed->tymed = TYMED_NULL;
  1032. pstgmed->hGlobal = NULL;
  1033. pstgmed->pUnkForRelease = NULL;
  1034. if (IS_FLAG_SET(pfmtetc->tymed, TYMED_HGLOBAL))
  1035. {
  1036. HGLOBAL hgFileGroupDesc;
  1037. hr = E_OUTOFMEMORY;
  1038. hgFileGroupDesc = GlobalAlloc(GMEM_ZEROINIT,
  1039. sizeof(FILEGROUPDESCRIPTOR));
  1040. if (hgFileGroupDesc)
  1041. {
  1042. PFILEGROUPDESCRIPTOR pfgd;
  1043. pfgd = (PFILEGROUPDESCRIPTOR)GlobalLock(hgFileGroupDesc);
  1044. if (EVAL(pfgd))
  1045. {
  1046. PFILEDESCRIPTOR pfd = &(pfgd->fgd[0]);
  1047. // Do we already have a file name to use?
  1048. if (m_pszFile)
  1049. {
  1050. lstrcpyn(pfd->cFileName, ExtractFileName(m_pszFile),
  1051. SIZECHARS(pfd->cFileName));
  1052. hr = S_OK;
  1053. }
  1054. else
  1055. {
  1056. if (EVAL(MLLoadStringA(
  1057. IDS_NEW_INTERNET_SHORTCUT, pfd->cFileName,
  1058. sizeof(pfd->cFileName))))
  1059. hr = S_OK;
  1060. }
  1061. if (hr == S_OK)
  1062. {
  1063. pfd->dwFlags = (FD_FILESIZE |
  1064. FD_LINKUI);
  1065. pfd->nFileSizeHigh = 0;
  1066. pfd->nFileSizeLow = GetFileContentsSize();
  1067. pfgd->cItems = 1;
  1068. pstgmed->tymed = TYMED_HGLOBAL;
  1069. pstgmed->hGlobal = hgFileGroupDesc;
  1070. ASSERT(! pstgmed->pUnkForRelease);
  1071. }
  1072. GlobalUnlock(hgFileGroupDesc);
  1073. pfgd = NULL;
  1074. }
  1075. if (hr != S_OK)
  1076. {
  1077. GlobalFree(hgFileGroupDesc);
  1078. hgFileGroupDesc = NULL;
  1079. }
  1080. }
  1081. }
  1082. else
  1083. hr = DV_E_TYMED;
  1084. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1085. ASSERT((hr == S_OK &&
  1086. IS_VALID_STRUCT_PTR(pstgmed, CSTGMEDIUM)) ||
  1087. (FAILED(hr) &&
  1088. (EVAL(pstgmed->tymed == TYMED_NULL) &&
  1089. EVAL(! pstgmed->hGlobal) &&
  1090. EVAL(! pstgmed->pUnkForRelease))));
  1091. DebugExitHRESULT(InternetShortcut::TransferFileGroupDescriptor, hr);
  1092. return(hr);
  1093. }
  1094. HRESULT STDMETHODCALLTYPE InternetShortcut::TransferFileContents(
  1095. PFORMATETC pfmtetc,
  1096. PSTGMEDIUM pstgmed)
  1097. {
  1098. HRESULT hr;
  1099. DebugEntry(InternetShortcut::TransferFileContents);
  1100. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1101. ASSERT(IS_VALID_STRUCT_PTR(pfmtetc, CFORMATETC));
  1102. ASSERT(IS_VALID_WRITE_PTR(pstgmed, STGMEDIUM));
  1103. ASSERT(pfmtetc->dwAspect == DVASPECT_CONTENT);
  1104. ASSERT(! pfmtetc->lindex);
  1105. pstgmed->tymed = TYMED_NULL;
  1106. pstgmed->hGlobal = NULL;
  1107. pstgmed->pUnkForRelease = NULL;
  1108. if (IS_FLAG_SET(pfmtetc->tymed, TYMED_HGLOBAL))
  1109. {
  1110. HGLOBAL hgFileContents;
  1111. hr = CreateURLFileContents(m_pszURL, (LPSTR *)&hgFileContents);
  1112. if (SUCCEEDED(hr))
  1113. {
  1114. // Note some apps don't pay attention to the nFileSizeLow
  1115. // field; fortunately, CreateURLFileContents adds a final
  1116. // null terminator to prevent trailing garbage.
  1117. pstgmed->tymed = TYMED_HGLOBAL;
  1118. pstgmed->hGlobal = hgFileContents;
  1119. ASSERT(! pstgmed->pUnkForRelease);
  1120. hr = S_OK;
  1121. }
  1122. else
  1123. hr = E_OUTOFMEMORY;
  1124. }
  1125. else
  1126. hr = DV_E_TYMED;
  1127. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1128. ASSERT((hr == S_OK &&
  1129. IS_VALID_STRUCT_PTR(pstgmed, CSTGMEDIUM)) ||
  1130. (FAILED(hr) &&
  1131. (EVAL(pstgmed->tymed == TYMED_NULL) &&
  1132. EVAL(! pstgmed->hGlobal) &&
  1133. EVAL(! pstgmed->pUnkForRelease))));
  1134. DebugExitHRESULT(InternetShortcut::TransferFileContents, hr);
  1135. return(hr);
  1136. }
  1137. #ifdef DEBUG
  1138. void STDMETHODCALLTYPE InternetShortcut::Dump(void)
  1139. {
  1140. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1141. PLAIN_TRACE_OUT(("%sm_dwFlags = %#08lx",
  1142. INDENT_STRING,
  1143. m_dwFlags));
  1144. PLAIN_TRACE_OUT(("%sm_pszFile = \"%s\"",
  1145. INDENT_STRING,
  1146. CHECK_STRING(m_pszFile)));
  1147. PLAIN_TRACE_OUT(("%sm_pszURL = \"%s\"",
  1148. INDENT_STRING,
  1149. CHECK_STRING(m_pszURL)));
  1150. PLAIN_TRACE_OUT(("%sm_pszIconFile = \"%s\"",
  1151. INDENT_STRING,
  1152. CHECK_STRING(m_pszIconFile)));
  1153. PLAIN_TRACE_OUT(("%sm_niIcon = %d",
  1154. INDENT_STRING,
  1155. m_niIcon));
  1156. PLAIN_TRACE_OUT(("%sm_wHotkey = %#04x",
  1157. INDENT_STRING,
  1158. (UINT)m_wHotkey));
  1159. PLAIN_TRACE_OUT(("%sm_pszWorkingDirectory = \"%s\"",
  1160. INDENT_STRING,
  1161. CHECK_STRING(m_pszWorkingDirectory)));
  1162. PLAIN_TRACE_OUT(("%sm_nShowCmd = %d",
  1163. INDENT_STRING,
  1164. m_nShowCmd));
  1165. return;
  1166. }
  1167. #endif