persist.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 42k
Category:

Windows Kernel

Development Platform:

Visual C++

  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[]                      = "rn";
  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.    // BUGBUG: 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.    // BUGBUG: 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.    // BUGBUG: 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.    // BUGBUG: 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.    // BUGBUG: Need OLESTR validation function to validate pcwszFile here.
  821.    // BUGBUG: Validate dwMode here.
  822.    // BUGBUG: 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.    // BUGBUG: 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.    // BUGBUG: 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.    
  907.    const static TCHAR s_cszNewLine[] = TEXT("rn");
  908.    const static TCHAR s_cszPrefix[] = TEXT("[InternetShortcut]rnURL=");
  909.    LPTSTR pszBuf;
  910.    DWORD cb;
  911.    pszBuf = (LPTSTR)LocalAlloc(LPTR, lstrlen(m_pszURL) + lstrlen(s_cszPrefix) + lstrlen(s_cszNewLine) + 1);
  912.    
  913.    wsprintf(pszBuf, TEXT("%s%s%s"), s_cszPrefix, m_pszURL ? m_pszURL : TEXT("") , s_cszNewLine);
  914.       
  915.    hr = pistr->Write(pszBuf, lstrlen(pszBuf), &cb);
  916.    LocalFree(pszBuf);
  917.    
  918.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  919.    DebugExitHRESULT(InternetShortcut::Save, hr);
  920.    return(hr);
  921. }
  922. HRESULT STDMETHODCALLTYPE InternetShortcut::GetSizeMax(PULARGE_INTEGER pcbSize)
  923. {
  924.    HRESULT hr;
  925.    DebugEntry(InternetShortcut::GetSizeMax);
  926.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  927.    ASSERT(IS_VALID_WRITE_PTR(pcbSize, ULARGE_INTEGER));
  928.    hr = E_NOTIMPL;
  929.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  930.    DebugExitHRESULT(InternetShortcut::GetSizeMax, hr);
  931.    return(hr);
  932. }
  933. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */
  934. DWORD STDMETHODCALLTYPE InternetShortcut::GetFileContentsSize(void)
  935. {
  936.    DWORD dwcbLen;
  937.    DebugEntry(InternetShortcut::GetFileContentsSize);
  938.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  939.    // Section length.
  940.    // (- 1) for each null terminator.
  941.    HRESULT hr = CreateURLFileContents(m_pszURL, NULL);
  942.    // BUGBUG: (DavidDi 3/29/95) We need to save more than just the URL string
  943.    // here, i.e., icon file and index, working directory, and show command.
  944.    dwcbLen = SUCCEEDED(hr) ? hr : 0;
  945.    dwcbLen++;       // + 1 for final null terminator
  946.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  947.    DebugExitDWORD(InternetShortcut::GetFileContentsSize, dwcbLen);
  948.    return(dwcbLen);
  949. }
  950. HRESULT STDMETHODCALLTYPE InternetShortcut::TransferUniformResourceLocator(
  951.                                                             PFORMATETC pfmtetc,
  952.                                                             PSTGMEDIUM pstgmed)
  953. {
  954.    HRESULT hr;
  955.    DebugEntry(InternetShortcut::TransferUniformResourceLocator);
  956.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  957.    ASSERT(IS_VALID_STRUCT_PTR(pfmtetc, CFORMATETC));
  958.    ASSERT(IS_VALID_WRITE_PTR(pstgmed, STGMEDIUM));
  959.    ASSERT(pfmtetc->dwAspect == DVASPECT_CONTENT);
  960.    ASSERT(pfmtetc->lindex == -1);
  961.    ZeroMemory(pstgmed, sizeof(*pstgmed));
  962.    if (IS_FLAG_SET(pfmtetc->tymed, TYMED_HGLOBAL))
  963.    {
  964.       if (m_pszURL)
  965.       {
  966.          HGLOBAL hgURL;
  967.          hr = E_OUTOFMEMORY;
  968.          // (+ 1) for null terminator.
  969.          hgURL = GlobalAlloc(0, lstrlen(m_pszURL) + 1);
  970.          if (hgURL)
  971.          {
  972.             PSTR pszURL;
  973.             pszURL = (PSTR)GlobalLock(hgURL);
  974.             if (EVAL(pszURL))
  975.             {
  976.                lstrcpy(pszURL, m_pszURL);
  977.                pstgmed->tymed = TYMED_HGLOBAL;
  978.                pstgmed->hGlobal = hgURL;
  979.                ASSERT(! pstgmed->pUnkForRelease);
  980.                hr = S_OK;
  981.                GlobalUnlock(hgURL);
  982.                pszURL = NULL;
  983.             }
  984.             if (hr != S_OK)
  985.             {
  986.                GlobalFree(hgURL);
  987.                hgURL = NULL;
  988.             }
  989.          }
  990.       }
  991.       else
  992.          hr = DV_E_FORMATETC;
  993.    }
  994.    else
  995.       hr = DV_E_TYMED;
  996.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  997.    ASSERT((hr == S_OK &&
  998.            IS_VALID_STRUCT_PTR(pstgmed, CSTGMEDIUM)) ||
  999.           (FAILED(hr) &&
  1000.            (EVAL(pstgmed->tymed == TYMED_NULL) &&
  1001.             EVAL(! pstgmed->hGlobal) &&
  1002.             EVAL(! pstgmed->pUnkForRelease))));
  1003.    DebugExitHRESULT(InternetShortcut::TransferUniformResourceLocator, hr);
  1004.    return(hr);
  1005. }
  1006. HRESULT STDMETHODCALLTYPE InternetShortcut::TransferText(PFORMATETC pfmtetc,
  1007.                                                          PSTGMEDIUM pstgmed)
  1008. {
  1009.    HRESULT hr;
  1010.    DebugEntry(InternetShortcut::TransferText);
  1011.    // Assume InternetShortcut::TransferUniformResourceLocator() will perform
  1012.    // input and output validation.
  1013.    hr = TransferUniformResourceLocator(pfmtetc, pstgmed);
  1014.    DebugExitHRESULT(InternetShortcut::TransferText, hr);
  1015.    return(hr);
  1016. }
  1017. HRESULT STDMETHODCALLTYPE InternetShortcut::TransferFileGroupDescriptor(
  1018.                                                             PFORMATETC pfmtetc,
  1019.                                                             PSTGMEDIUM pstgmed)
  1020. {
  1021.    HRESULT hr;
  1022.    DebugEntry(InternetShortcut::TransferFileGroupDescriptor);
  1023.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1024.    ASSERT(IS_VALID_STRUCT_PTR(pfmtetc, CFORMATETC));
  1025.    ASSERT(IS_VALID_WRITE_PTR(pstgmed, STGMEDIUM));
  1026.    ASSERT(pfmtetc->dwAspect == DVASPECT_CONTENT);
  1027.    ASSERT(pfmtetc->lindex == -1);
  1028.    pstgmed->tymed = TYMED_NULL;
  1029.    pstgmed->hGlobal = NULL;
  1030.    pstgmed->pUnkForRelease = NULL;
  1031.    if (IS_FLAG_SET(pfmtetc->tymed, TYMED_HGLOBAL))
  1032.    {
  1033.       HGLOBAL hgFileGroupDesc;
  1034.       hr = E_OUTOFMEMORY;
  1035.       hgFileGroupDesc = GlobalAlloc(GMEM_ZEROINIT,
  1036.                                     sizeof(FILEGROUPDESCRIPTOR));
  1037.       if (hgFileGroupDesc)
  1038.       {
  1039.          PFILEGROUPDESCRIPTOR pfgd;
  1040.          pfgd = (PFILEGROUPDESCRIPTOR)GlobalLock(hgFileGroupDesc);
  1041.          if (EVAL(pfgd))
  1042.          {
  1043.             PFILEDESCRIPTOR pfd = &(pfgd->fgd[0]);
  1044.             // Do we already have a file name to use?
  1045.             if (m_pszFile)
  1046.             {
  1047.                lstrcpyn(pfd->cFileName, ExtractFileName(m_pszFile),
  1048.                         SIZECHARS(pfd->cFileName));
  1049.                hr = S_OK;
  1050.             }
  1051.             else
  1052.             {
  1053.                if (EVAL(MLLoadStringA(
  1054.                                    IDS_NEW_INTERNET_SHORTCUT, pfd->cFileName,
  1055.                                    sizeof(pfd->cFileName))))
  1056.                   hr = S_OK;
  1057.             }
  1058.             if (hr == S_OK)
  1059.             {
  1060.                pfd->dwFlags = (FD_FILESIZE |
  1061.                                FD_LINKUI);
  1062.                pfd->nFileSizeHigh = 0;
  1063.                pfd->nFileSizeLow = GetFileContentsSize();
  1064.                pfgd->cItems = 1;
  1065.                pstgmed->tymed = TYMED_HGLOBAL;
  1066.                pstgmed->hGlobal = hgFileGroupDesc;
  1067.                ASSERT(! pstgmed->pUnkForRelease);
  1068.             }
  1069.             GlobalUnlock(hgFileGroupDesc);
  1070.             pfgd = NULL;
  1071.          }
  1072.          if (hr != S_OK)
  1073.          {
  1074.             GlobalFree(hgFileGroupDesc);
  1075.             hgFileGroupDesc = NULL;
  1076.          }
  1077.       }
  1078.    }
  1079.    else
  1080.       hr = DV_E_TYMED;
  1081.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1082.    ASSERT((hr == S_OK &&
  1083.            IS_VALID_STRUCT_PTR(pstgmed, CSTGMEDIUM)) ||
  1084.           (FAILED(hr) &&
  1085.            (EVAL(pstgmed->tymed == TYMED_NULL) &&
  1086.             EVAL(! pstgmed->hGlobal) &&
  1087.             EVAL(! pstgmed->pUnkForRelease))));
  1088.    DebugExitHRESULT(InternetShortcut::TransferFileGroupDescriptor, hr);
  1089.    return(hr);
  1090. }
  1091. HRESULT STDMETHODCALLTYPE InternetShortcut::TransferFileContents(
  1092.                                                             PFORMATETC pfmtetc,
  1093.                                                             PSTGMEDIUM pstgmed)
  1094. {
  1095.    HRESULT hr;
  1096.    DebugEntry(InternetShortcut::TransferFileContents);
  1097.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1098.    ASSERT(IS_VALID_STRUCT_PTR(pfmtetc, CFORMATETC));
  1099.    ASSERT(IS_VALID_WRITE_PTR(pstgmed, STGMEDIUM));
  1100.    ASSERT(pfmtetc->dwAspect == DVASPECT_CONTENT);
  1101.    ASSERT(! pfmtetc->lindex);
  1102.    pstgmed->tymed = TYMED_NULL;
  1103.    pstgmed->hGlobal = NULL;
  1104.    pstgmed->pUnkForRelease = NULL;
  1105.    if (IS_FLAG_SET(pfmtetc->tymed, TYMED_HGLOBAL))
  1106.    {
  1107.       HGLOBAL hgFileContents;
  1108.       hr = CreateURLFileContents(m_pszURL, (LPSTR *)&hgFileContents);
  1109.       if (SUCCEEDED(hr))
  1110.       {
  1111.          // Note some apps don't pay attention to the nFileSizeLow
  1112.          // field; fortunately, CreateURLFileContents adds a final
  1113.          // null terminator to prevent trailing garbage.
  1114.          pstgmed->tymed = TYMED_HGLOBAL;
  1115.          pstgmed->hGlobal = hgFileContents;
  1116.          ASSERT(! pstgmed->pUnkForRelease);
  1117.          hr = S_OK;
  1118.       }
  1119.       else
  1120.          hr = E_OUTOFMEMORY;
  1121.    }
  1122.    else
  1123.       hr = DV_E_TYMED;
  1124.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1125.    ASSERT((hr == S_OK &&
  1126.            IS_VALID_STRUCT_PTR(pstgmed, CSTGMEDIUM)) ||
  1127.           (FAILED(hr) &&
  1128.            (EVAL(pstgmed->tymed == TYMED_NULL) &&
  1129.             EVAL(! pstgmed->hGlobal) &&
  1130.             EVAL(! pstgmed->pUnkForRelease))));
  1131.    DebugExitHRESULT(InternetShortcut::TransferFileContents, hr);
  1132.    return(hr);
  1133. }
  1134. #ifdef DEBUG
  1135. void STDMETHODCALLTYPE InternetShortcut::Dump(void)
  1136. {
  1137.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1138.    PLAIN_TRACE_OUT(("%sm_dwFlags = %#08lx",
  1139.                     INDENT_STRING,
  1140.                     m_dwFlags));
  1141.    PLAIN_TRACE_OUT(("%sm_pszFile = "%s"",
  1142.                     INDENT_STRING,
  1143.                     CHECK_STRING(m_pszFile)));
  1144.    PLAIN_TRACE_OUT(("%sm_pszURL = "%s"",
  1145.                     INDENT_STRING,
  1146.                     CHECK_STRING(m_pszURL)));
  1147.    PLAIN_TRACE_OUT(("%sm_pszIconFile = "%s"",
  1148.                     INDENT_STRING,
  1149.                     CHECK_STRING(m_pszIconFile)));
  1150.    PLAIN_TRACE_OUT(("%sm_niIcon = %d",
  1151.                     INDENT_STRING,
  1152.                     m_niIcon));
  1153.    PLAIN_TRACE_OUT(("%sm_wHotkey = %#04x",
  1154.                     INDENT_STRING,
  1155.                     (UINT)m_wHotkey));
  1156.    PLAIN_TRACE_OUT(("%sm_pszWorkingDirectory = "%s"",
  1157.                     INDENT_STRING,
  1158.                     CHECK_STRING(m_pszWorkingDirectory)));
  1159.    PLAIN_TRACE_OUT(("%sm_nShowCmd = %d",
  1160.                     INDENT_STRING,
  1161.                     m_nShowCmd));
  1162.    return;
  1163. }
  1164. #endif