|
|
/*
* persist.cpp - IPersist, IPersistFile, and IPersistStream implementations for * URL class. */
/* Headers
**********/
#include "project.hpp"
#pragma hdrstop
#include "resource.h"
#include <mluisupp.h>
/* Global Constants
*******************/
#pragma data_seg(DATA_SEG_READ_ONLY)
extern const UINT g_ucMaxURLLen = 1024;
extern const char g_cszURLPrefix[] = "url:"; extern const UINT g_ucbURLPrefixLen = sizeof(g_cszURLPrefix) - 1;
extern const char g_cszURLExt[] = ".url"; extern const char g_cszURLDefaultFileNamePrompt[] = "*.url";
extern const char g_cszCRLF[] = "\r\n";
#pragma data_seg()
/* Module Constants
*******************/
#pragma data_seg(DATA_SEG_READ_ONLY)
// case-insensitive
PRIVATE_DATA const char s_cszInternetShortcutSection[] = "InternetShortcut";
PRIVATE_DATA const char s_cszURLKey[] = "URL"; PRIVATE_DATA const char s_cszIconFileKey[] = "IconFile"; PRIVATE_DATA const char s_cszIconIndexKey[] = "IconIndex"; PRIVATE_DATA const char s_cszHotkeyKey[] = "Hotkey"; PRIVATE_DATA const char s_cszWorkingDirectoryKey[] = "WorkingDirectory"; PRIVATE_DATA const char s_cszShowCmdKey[] = "ShowCommand";
PRIVATE_DATA const UINT s_ucMaxIconIndexLen = 1 + 10 + 1; // -2147483647
PRIVATE_DATA const UINT s_ucMaxHotkeyLen = s_ucMaxIconIndexLen; PRIVATE_DATA const UINT s_ucMaxShowCmdLen = s_ucMaxIconIndexLen;
#pragma data_seg()
/***************************** Private Functions *****************************/
PRIVATE_CODE BOOL DeletePrivateProfileString(PCSTR pcszSection, PCSTR pcszKey, PCSTR pcszFile) { ASSERT(IS_VALID_STRING_PTR(pcszSection, CSTR)); ASSERT(IS_VALID_STRING_PTR(pcszKey, CSTR)); ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
return(WritePrivateProfileString(pcszSection, pcszKey, NULL, pcszFile)); }
#define SHDeleteIniString(pcszSection, pcszKey, pcszFile) \
SHSetIniString(pcszSection, pcszKey, NULL, pcszFile)
PRIVATE_CODE HRESULT MassageURL(PSTR pszURL) { HRESULT hr = E_FAIL;
ASSERT(IS_VALID_STRING_PTR(pszURL, STR));
TrimWhiteSpace(pszURL);
PSTR pszBase = pszURL; PSTR psz;
// Skip over any "url:" prefix.
if (! lstrnicmp(pszBase, g_cszURLPrefix, g_ucbURLPrefixLen)) pszBase += g_ucbURLPrefixLen;
lstrcpy(pszURL, pszBase); hr = S_OK;
TRACE_OUT(("MassageURL(): Massaged URL to %s.", pszURL));
ASSERT(FAILED(hr) || IS_VALID_STRING_PTR(pszURL, STR));
return(hr); }
PRIVATE_CODE HRESULT ReadURLFromFile(PCSTR pcszFile, PSTR *ppszURL) { HRESULT hr; PSTR pszNewURL;
ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR)); ASSERT(IS_VALID_WRITE_PTR(ppszURL, PSTR));
*ppszURL = NULL;
pszNewURL = new(char[g_ucMaxURLLen]);
if (pszNewURL) { DWORD dwcValueLen;
dwcValueLen = SHGetIniString(s_cszInternetShortcutSection, s_cszURLKey, pszNewURL, g_ucMaxURLLen, pcszFile);
if (dwcValueLen > 0) { hr = MassageURL(pszNewURL);
if (hr == S_OK) { PSTR pszShorterURL;
// (+ 1) for null terminator.
if (ReallocateMemory(pszNewURL, lstrlen(pszNewURL) + 1, (PVOID *)&pszShorterURL)) { *ppszURL = pszShorterURL;
hr = S_OK; } else hr = E_OUTOFMEMORY; } } else { hr = S_FALSE;
WARNING_OUT(("ReadURLFromFile: No URL found in file %s.", pcszFile)); } } else hr = E_OUTOFMEMORY;
if (FAILED(hr) || hr == S_FALSE) { if (pszNewURL) { delete pszNewURL; pszNewURL = NULL; } }
ASSERT((hr == S_OK && IS_VALID_STRING_PTR(*ppszURL, STR)) || (hr != S_OK && ! *ppszURL));
return(hr); }
PRIVATE_CODE HRESULT WriteURLToFile(PCSTR pcszFile, PCSTR pcszURL) { HRESULT hr;
ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR)); ASSERT(! pcszURL || IS_VALID_STRING_PTR(pcszURL, CSTR));
if (AnyMeat(pcszURL)) { int ncbLen;
ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR)); ASSERT(IS_VALID_STRING_PTR(pcszURL, PSTR));
hr = (SHSetIniString(s_cszInternetShortcutSection, s_cszURLKey, pcszURL, pcszFile)) ? S_OK : E_FAIL; } else hr = (SHDeleteIniString(s_cszInternetShortcutSection, s_cszURLKey, pcszFile)) ? S_OK : E_FAIL;
return(hr); }
PRIVATE_CODE HRESULT ReadIconLocationFromFile(PCSTR pcszFile, PSTR *ppszIconFile, PINT pniIcon) { HRESULT hr; char rgchNewIconFile[MAX_PATH_LEN]; DWORD dwcValueLen;
ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR)); ASSERT(IS_VALID_WRITE_PTR(ppszIconFile, PSTR)); ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT));
*ppszIconFile = NULL; *pniIcon = 0;
dwcValueLen = SHGetIniString(s_cszInternetShortcutSection, s_cszIconFileKey, rgchNewIconFile, sizeof(rgchNewIconFile), pcszFile);
if (dwcValueLen > 0) { char rgchNewIconIndex[s_ucMaxIconIndexLen];
dwcValueLen = GetPrivateProfileString(s_cszInternetShortcutSection, s_cszIconIndexKey, EMPTY_STRING, rgchNewIconIndex, sizeof(rgchNewIconIndex), pcszFile);
if (dwcValueLen > 0) { int niIcon;
if (StrToIntEx(rgchNewIconIndex, 0, &niIcon)) { // (+ 1) for null terminator.
*ppszIconFile = new(char[lstrlen(rgchNewIconFile) + 1]);
if (*ppszIconFile) { lstrcpy(*ppszIconFile, rgchNewIconFile); *pniIcon = niIcon;
hr = S_OK; } else hr = E_OUTOFMEMORY; } else { hr = S_FALSE;
WARNING_OUT(("ReadIconLocationFromFile(): Bad icon index \"%s\" found in file %s.", rgchNewIconIndex, pcszFile)); } } else { hr = S_FALSE;
WARNING_OUT(("ReadIconLocationFromFile(): No icon index found in file %s.", pcszFile)); } } else { hr = S_FALSE;
TRACE_OUT(("ReadIconLocationFromFile(): No icon file found in file %s.", pcszFile)); }
ASSERT(IsValidIconIndex(hr, *ppszIconFile, MAX_PATH_LEN, *pniIcon));
return(hr); }
PRIVATE_CODE HRESULT WriteIconLocationToFile(PCSTR pcszFile, PCSTR pcszIconFile, int niIcon) { HRESULT hr;
ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR)); ASSERT(! pcszIconFile || IS_VALID_STRING_PTR(pcszIconFile, CSTR)); ASSERT(IsValidIconIndex((pcszIconFile ? S_OK : S_FALSE), pcszIconFile, MAX_PATH_LEN, niIcon));
if (AnyMeat(pcszIconFile)) { char rgchIconIndexRHS[s_ucMaxIconIndexLen]; int ncLen;
ncLen = wsprintf(rgchIconIndexRHS, "%d", niIcon); ASSERT(ncLen > 0); ASSERT(ncLen < sizeof(rgchIconIndexRHS)); ASSERT(ncLen == lstrlen(rgchIconIndexRHS));
hr = (SHSetIniString(s_cszInternetShortcutSection, s_cszIconFileKey, pcszIconFile, pcszFile) && WritePrivateProfileString(s_cszInternetShortcutSection, s_cszIconIndexKey, rgchIconIndexRHS, pcszFile)) ? S_OK : E_FAIL; } else hr = (SHDeleteIniString(s_cszInternetShortcutSection, s_cszIconFileKey, pcszFile) && DeletePrivateProfileString(s_cszInternetShortcutSection, s_cszIconIndexKey, pcszFile)) ? S_OK : E_FAIL;
return(hr); }
PRIVATE_CODE HRESULT ReadHotkeyFromFile(PCSTR pcszFile, PWORD pwHotkey) { HRESULT hr = S_FALSE; char rgchHotkey[s_ucMaxHotkeyLen]; DWORD dwcValueLen;
ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR)); ASSERT(IS_VALID_WRITE_PTR(pwHotkey, WORD));
*pwHotkey = 0;
dwcValueLen = GetPrivateProfileString(s_cszInternetShortcutSection, s_cszHotkeyKey, EMPTY_STRING, rgchHotkey, sizeof(rgchHotkey), pcszFile);
if (dwcValueLen > 0) { UINT uHotkey;
if (StrToIntEx(rgchHotkey, 0, (int *)&uHotkey)) { *pwHotkey = (WORD)uHotkey;
hr = S_OK; } else WARNING_OUT(("ReadHotkeyFromFile(): Bad hotkey \"%s\" found in file %s.", rgchHotkey, pcszFile)); } else WARNING_OUT(("ReadHotkeyFromFile(): No hotkey found in file %s.", pcszFile));
ASSERT((hr == S_OK && IsValidHotkey(*pwHotkey)) || (hr == S_FALSE && ! *pwHotkey));
return(hr); }
PRIVATE_CODE HRESULT WriteHotkeyToFile(PCSTR pcszFile, WORD wHotkey) { HRESULT hr;
ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR)); ASSERT(! wHotkey || IsValidHotkey(wHotkey));
if (wHotkey) { char rgchHotkeyRHS[s_ucMaxHotkeyLen]; int ncLen;
ncLen = wsprintf(rgchHotkeyRHS, "%u", (UINT)wHotkey); ASSERT(ncLen > 0); ASSERT(ncLen < sizeof(rgchHotkeyRHS)); ASSERT(ncLen == lstrlen(rgchHotkeyRHS));
hr = WritePrivateProfileString(s_cszInternetShortcutSection, s_cszHotkeyKey, rgchHotkeyRHS, pcszFile) ? S_OK : E_FAIL; } else hr = DeletePrivateProfileString(s_cszInternetShortcutSection, s_cszHotkeyKey, pcszFile) ? S_OK : E_FAIL;
return(hr); }
PRIVATE_CODE HRESULT ReadWorkingDirectoryFromFile(PCSTR pcszFile, PSTR *ppszWorkingDirectory) { HRESULT hr; char rgchDirValue[MAX_PATH_LEN]; DWORD dwcValueLen;
ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR)); ASSERT(IS_VALID_WRITE_PTR(ppszWorkingDirectory, PSTR));
*ppszWorkingDirectory = NULL;
dwcValueLen = SHGetIniString(s_cszInternetShortcutSection, s_cszWorkingDirectoryKey, rgchDirValue, sizeof(rgchDirValue), pcszFile);
if (dwcValueLen > 0) { char rgchFullPath[MAX_PATH_LEN]; PSTR pszFileName;
if (GetFullPathName(rgchDirValue, sizeof(rgchFullPath), rgchFullPath, &pszFileName) > 0) { // (+ 1) for null terminator.
*ppszWorkingDirectory = new(char[lstrlen(rgchFullPath) + 1]);
if (*ppszWorkingDirectory) { lstrcpy(*ppszWorkingDirectory, rgchFullPath);
hr = S_OK; } else hr = E_OUTOFMEMORY; } else hr = E_FAIL; } else { hr = S_FALSE;
TRACE_OUT(("ReadWorkingDirectoryFromFile: No working directory found in file %s.", pcszFile)); }
ASSERT(IsValidPathResult(hr, *ppszWorkingDirectory, MAX_PATH_LEN));
return(hr); }
PRIVATE_CODE HRESULT WriteWorkingDirectoryToFile(PCSTR pcszFile, PCSTR pcszWorkingDirectory) { HRESULT hr;
ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR)); ASSERT(! pcszWorkingDirectory || IS_VALID_STRING_PTR(pcszWorkingDirectory, CSTR));
if (AnyMeat(pcszWorkingDirectory)) hr = (SHSetIniString(s_cszInternetShortcutSection, s_cszWorkingDirectoryKey, pcszWorkingDirectory, pcszFile)) ? S_OK : E_FAIL; else hr = (SHDeleteIniString(s_cszInternetShortcutSection, s_cszWorkingDirectoryKey, pcszFile)) ? S_OK : E_FAIL;
return(hr); }
PRIVATE_CODE HRESULT ReadShowCmdFromFile(PCSTR pcszFile, PINT pnShowCmd) { HRESULT hr; char rgchNewShowCmd[s_ucMaxShowCmdLen]; DWORD dwcValueLen;
ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR)); ASSERT(IS_VALID_WRITE_PTR(pnShowCmd, INT));
*pnShowCmd = g_nDefaultShowCmd;
dwcValueLen = GetPrivateProfileString(s_cszInternetShortcutSection, s_cszShowCmdKey, EMPTY_STRING, rgchNewShowCmd, sizeof(rgchNewShowCmd), pcszFile);
if (dwcValueLen > 0) { int nShowCmd;
if (StrToIntEx(rgchNewShowCmd, 0, &nShowCmd)) { *pnShowCmd = nShowCmd;
hr = S_OK; } else { hr = S_FALSE;
WARNING_OUT(("ReadShowCmdFromFile: Invalid show command \"%s\" found in file %s.", rgchNewShowCmd, pcszFile)); } } else { hr = S_FALSE;
TRACE_OUT(("ReadShowCmdFromFile: No show command found in file %s.", pcszFile)); }
ASSERT((hr == S_OK && EVAL(IsValidShowCmd(*pnShowCmd))) || (hr == S_FALSE && EVAL(*pnShowCmd == g_nDefaultShowCmd)));
return(hr); }
PRIVATE_CODE HRESULT WriteShowCmdToFile(PCSTR pcszFile, int nShowCmd) { HRESULT hr;
ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR)); ASSERT(IsValidShowCmd(nShowCmd));
if (nShowCmd != g_nDefaultShowCmd) { char rgchShowCmdRHS[s_ucMaxShowCmdLen]; int ncLen;
ncLen = wsprintf(rgchShowCmdRHS, "%d", nShowCmd); ASSERT(ncLen > 0); ASSERT(ncLen < sizeof(rgchShowCmdRHS)); ASSERT(ncLen == lstrlen(rgchShowCmdRHS));
hr = (WritePrivateProfileString(s_cszInternetShortcutSection, s_cszShowCmdKey, rgchShowCmdRHS, pcszFile)) ? S_OK : E_FAIL; } else hr = (DeletePrivateProfileString(s_cszInternetShortcutSection, s_cszShowCmdKey, pcszFile)) ? S_OK : E_FAIL;
return(hr); }
/****************************** Public Functions *****************************/
PUBLIC_CODE HRESULT UnicodeToANSI(LPCOLESTR pcwszUnicode, PSTR *ppszANSI) { HRESULT hr; int ncbLen;
// FEATURE: Need OLESTR validation function to validate pcwszUnicode here.
ASSERT(IS_VALID_WRITE_PTR(ppszANSI, PSTR));
*ppszANSI = NULL;
// Get length of translated string.
ncbLen = WideCharToMultiByte(CP_ACP, 0, pcwszUnicode, -1, NULL, 0, NULL, NULL);
if (ncbLen > 0) { PSTR pszNewANSI;
// (+ 1) for null terminator.
pszNewANSI = new(char[ncbLen]);
if (pszNewANSI) { // Translate string.
if (WideCharToMultiByte(CP_ACP, 0, pcwszUnicode, -1, pszNewANSI, ncbLen, NULL, NULL) > 0) { *ppszANSI = pszNewANSI; hr = S_OK; } else { delete pszNewANSI; pszNewANSI = NULL;
hr = E_UNEXPECTED;
WARNING_OUT(("UnicodeToANSI(): Failed to translate Unicode string to ANSI.")); } } else hr = E_OUTOFMEMORY; } else { hr = E_UNEXPECTED;
WARNING_OUT(("UnicodeToANSI(): Failed to get length of translated ANSI string.")); }
ASSERT(FAILED(hr) || IS_VALID_STRING_PTR(*ppszANSI, STR));
return(hr); }
PUBLIC_CODE HRESULT ANSIToUnicode(PCSTR pcszANSI, LPOLESTR *ppwszUnicode) { HRESULT hr; int ncbWideLen;
ASSERT(IS_VALID_STRING_PTR(pcszANSI, CSTR)); ASSERT(IS_VALID_WRITE_PTR(ppwszUnicode, LPOLESTR));
*ppwszUnicode = NULL;
// Get length of translated string.
ncbWideLen = MultiByteToWideChar(CP_ACP, 0, pcszANSI, -1, NULL, 0);
if (ncbWideLen > 0) { PWSTR pwszNewUnicode;
// (+ 1) for null terminator.
pwszNewUnicode = new(WCHAR[ncbWideLen]);
if (pwszNewUnicode) { // Translate string.
if (MultiByteToWideChar(CP_ACP, 0, pcszANSI, -1, pwszNewUnicode, ncbWideLen) > 0) { *ppwszUnicode = pwszNewUnicode; hr = S_OK; } else { delete pwszNewUnicode; pwszNewUnicode = NULL;
hr = E_UNEXPECTED;
WARNING_OUT(("ANSIToUnicode(): Failed to translate ANSI path string to Unicode.")); } } else hr = E_OUTOFMEMORY; } else { hr = E_UNEXPECTED;
WARNING_OUT(("ANSIToUnicode(): Failed to get length of translated Unicode string.")); }
// FEATURE: Need OLESTR validation function to validate *ppwszUnicode here.
return(hr); }
/********************************** Methods **********************************/
HRESULT STDMETHODCALLTYPE InternetShortcut::SaveToFile(PCSTR pcszFile, BOOL bRemember) { HRESULT hr; PSTR pszURL;
DebugEntry(InternetShortcut::SaveToFile);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
hr = GetURL(&pszURL);
if (SUCCEEDED(hr)) { hr = WriteURLToFile(pcszFile, pszURL);
if (pszURL) { SHFree(pszURL); pszURL = NULL; }
if (hr == S_OK) { char rgchBuf[MAX_PATH_LEN]; int niIcon;
hr = GetIconLocation(rgchBuf, sizeof(rgchBuf), &niIcon);
if (SUCCEEDED(hr)) { hr = WriteIconLocationToFile(pcszFile, rgchBuf, niIcon);
if (hr == S_OK) { WORD wHotkey;
hr = GetHotkey(&wHotkey);
if (SUCCEEDED(hr)) { hr = WriteHotkeyToFile(pcszFile, wHotkey);
if (hr == S_OK) { hr = GetWorkingDirectory(rgchBuf, sizeof(rgchBuf));
if (SUCCEEDED(hr)) { hr = WriteWorkingDirectoryToFile(pcszFile, rgchBuf);
if (hr == S_OK) { int nShowCmd;
GetShowCmd(&nShowCmd);
hr = WriteShowCmdToFile(pcszFile, nShowCmd);
if (hr == S_OK) { /* Remember file if requested. */
if (bRemember) { PSTR pszFileCopy;
if (StringCopy(pcszFile, &pszFileCopy)) { if (m_pszFile) delete m_pszFile;
m_pszFile = pszFileCopy;
TRACE_OUT(("InternetShortcut::SaveToFile(): Remembering file %s, as requested.", m_pszFile)); } else hr = E_OUTOFMEMORY; }
if (hr == S_OK) { Dirty(FALSE);
SHChangeNotify(SHCNE_UPDATEITEM, (SHCNF_PATH | SHCNF_FLUSH), pcszFile, NULL);
#ifdef DEBUG
TRACE_OUT(("InternetShortcut::SaveToFile(): Internet Shortcut saved to file %s:", pcszFile)); Dump(); #endif
} } } } } } } } } }
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
DebugExitHRESULT(InternetShortcut::SaveToFile, hr);
return(hr); }
HRESULT STDMETHODCALLTYPE InternetShortcut::LoadFromFile(PCSTR pcszFile, BOOL bRemember) { HRESULT hr; PSTR pszURL;
DebugEntry(InternetShortcut::LoadFromFile);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
hr = ReadURLFromFile(pcszFile, &pszURL);
if (SUCCEEDED(hr)) { hr = SetURL(pszURL, (IURL_SETURL_FL_GUESS_PROTOCOL | IURL_SETURL_FL_USE_DEFAULT_PROTOCOL));
if (pszURL) { delete pszURL; pszURL = NULL; }
if (hr == S_OK) { PSTR pszIconFile; int niIcon;
hr = ReadIconLocationFromFile(pcszFile, &pszIconFile, &niIcon);
if (SUCCEEDED(hr)) { hr = SetIconLocation(pszIconFile, niIcon);
if (pszIconFile) { delete pszIconFile; pszIconFile = NULL; }
if (hr == S_OK) { WORD wHotkey;
hr = ReadHotkeyFromFile(pcszFile, &wHotkey);
if (SUCCEEDED(hr)) { hr = SetHotkey(wHotkey);
if (hr == S_OK) { PSTR pszWorkingDirectory;
hr = ReadWorkingDirectoryFromFile(pcszFile, &pszWorkingDirectory);
if (SUCCEEDED(hr)) { hr = SetWorkingDirectory(pszWorkingDirectory);
if (pszWorkingDirectory) { delete pszWorkingDirectory; pszWorkingDirectory = NULL; }
if (hr == S_OK) { int nShowCmd;
hr = ReadShowCmdFromFile(pcszFile, &nShowCmd);
if (SUCCEEDED(hr)) { /* Remember file if requested. */
if (bRemember) { PSTR pszFileCopy;
if (StringCopy(pcszFile, &pszFileCopy)) { if (m_pszFile) delete m_pszFile;
m_pszFile = pszFileCopy;
TRACE_OUT(("InternetShortcut::LoadFromFile(): Remembering file %s, as requested.", m_pszFile)); } else hr = E_OUTOFMEMORY; }
if (SUCCEEDED(hr)) { SetShowCmd(nShowCmd);
Dirty(FALSE);
hr = S_OK;
#ifdef DEBUG
TRACE_OUT(("InternetShortcut::LoadFromFile(): Internet Shortcut loaded from file %s:", pcszFile)); Dump(); #endif
} } } } } } } } } }
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
DebugExitHRESULT(InternetShortcut::LoadFromFile, hr);
return(hr); }
HRESULT STDMETHODCALLTYPE InternetShortcut::GetCurFile(PSTR pszFile, UINT ucbLen) { HRESULT hr;
DebugEntry(InternetShortcut::GetCurFile);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszFile, STR, ucbLen));
if (m_pszFile) { lstrcpyn(pszFile, m_pszFile, ucbLen);
TRACE_OUT(("InternetShortcut::GetCurFile(): Current file name is %s.", pszFile));
hr = S_OK; } else hr = S_FALSE;
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_STRING_PTR(pszFile, STR) && EVAL((UINT)lstrlen(pszFile) < ucbLen)); ASSERT(hr == S_OK || hr == S_FALSE);
DebugExitHRESULT(InternetShortcut::GetCurFile, hr);
return(hr); }
HRESULT STDMETHODCALLTYPE InternetShortcut::Dirty(BOOL bDirty) { HRESULT hr;
DebugEntry(InternetShortcut::Dirty);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
if (bDirty) { if (IS_FLAG_CLEAR(m_dwFlags, INTSHCUT_FL_DIRTY)) { TRACE_OUT(("InternetShortcut::Dirty(): Now dirty.")); }
SET_FLAG(m_dwFlags, INTSHCUT_FL_DIRTY); } else { if (IS_FLAG_SET(m_dwFlags, INTSHCUT_FL_DIRTY)) { TRACE_OUT(("InternetShortcut::Dirty(): Now clean.")); }
CLEAR_FLAG(m_dwFlags, INTSHCUT_FL_DIRTY); }
hr = S_OK;
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(hr == S_OK);
DebugExitVOID(InternetShortcut::Dirty);
return(hr); }
HRESULT STDMETHODCALLTYPE InternetShortcut::GetClassID(PCLSID pclsid) { HRESULT hr;
DebugEntry(InternetShortcut::GetClassID);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_STRUCT_PTR(pclsid, CCLSID));
*pclsid = CLSID_InternetShortcut; hr = S_OK;
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(FAILED(hr) || IS_VALID_STRUCT_PTR(pclsid, CCLSID));
DebugExitHRESULT(InternetShortcut::GetClassID, hr);
return(hr); }
HRESULT STDMETHODCALLTYPE InternetShortcut::IsDirty(void) { HRESULT hr;
DebugEntry(InternetShortcut::IsDirty);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
if (IS_FLAG_SET(m_dwFlags, INTSHCUT_FL_DIRTY)) hr = S_OK; else hr = S_FALSE;
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
DebugExitHRESULT(InternetShortcut::IsDirty, hr);
return(hr); }
HRESULT STDMETHODCALLTYPE InternetShortcut::Save(LPCOLESTR pcwszFile, BOOL bRemember) { HRESULT hr; PSTR pszFile;
DebugEntry(InternetShortcut::Save);
// bRemember may be any value.
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); // FEATURE: Need OLESTR validation function to validate pcwszFile here.
if (pcwszFile) { hr = UnicodeToANSI(pcwszFile, &pszFile);
if (hr == S_OK) { hr = SaveToFile(pszFile, bRemember);
delete pszFile; pszFile = NULL; } } else if (m_pszFile) // Ignore bRemember.
hr = SaveToFile(m_pszFile, FALSE); else hr = E_FAIL;
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
DebugExitHRESULT(InternetShortcut::Save, hr);
return(hr); }
#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
HRESULT STDMETHODCALLTYPE InternetShortcut::SaveCompleted(LPCOLESTR pcwszFile) { HRESULT hr;
DebugEntry(InternetShortcut::SaveCompleted);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
// FEATURE: Need OLESTR validation function to validate pcwszFile here.
hr = S_OK;
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
DebugExitHRESULT(InternetShortcut::SaveCompleted, hr);
return(hr); }
HRESULT STDMETHODCALLTYPE InternetShortcut::Load(LPCOLESTR pcwszFile, DWORD dwMode) { HRESULT hr; PSTR pszFile;
DebugEntry(InternetShortcut::Load);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
// FEATURE: Need OLESTR validation function to validate pcwszFile here.
// FEATURE: Validate dwMode here.
// FEAUTRE: Implement dwMode flag support.
hr = UnicodeToANSI(pcwszFile, &pszFile);
if (hr == S_OK) { hr = LoadFromFile(pszFile, TRUE);
delete pszFile; pszFile = NULL; }
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
DebugExitHRESULT(InternetShortcut::Load, hr);
return(hr); }
#pragma warning(default:4100) /* "unreferenced formal parameter" warning */
HRESULT STDMETHODCALLTYPE InternetShortcut::GetCurFile(LPOLESTR *ppwszFile) { HRESULT hr; LPOLESTR pwszTempFile;
DebugEntry(InternetShortcut::GetCurFile);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_WRITE_PTR(ppwszFile, LPOLESTR));
if (m_pszFile) { hr = ANSIToUnicode(m_pszFile, &pwszTempFile);
if (hr == S_OK) { TRACE_OUT(("InternetShortcut::GetCurFile(): Current file name is %s.", m_pszFile)); } } else { hr = ANSIToUnicode(g_cszURLDefaultFileNamePrompt, &pwszTempFile);
if (hr == S_OK) { hr = S_FALSE;
TRACE_OUT(("InternetShortcut::GetCurFile(): No current file name. Returning default file name prompt %s.", g_cszURLDefaultFileNamePrompt)); } }
if (SUCCEEDED(hr)) { // We should really call OleGetMalloc() to get the process IMalloc here.
// Use SHAlloc() here instead to avoid loading ole32.dll.
// SHAlloc() / SHFree() turn in to IMalloc::Alloc() and IMalloc::Free()
// once ole32.dll is loaded.
// N.b., lstrlenW() returns the length of the given string in characters,
// not bytes.
// (+ 1) for null terminator.
*ppwszFile = (LPOLESTR)SHAlloc((lstrlenW(pwszTempFile) + 1) * sizeof(*pwszTempFile));
if (*ppwszFile) lstrcpyW(*ppwszFile, pwszTempFile); else hr = E_OUTOFMEMORY;
delete pwszTempFile; pwszTempFile = NULL; }
// FEATURE: Need OLESTR validation function to validate *ppwszFile here.
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
DebugExitHRESULT(InternetShortcut::GetCurFile, hr);
return(hr); }
#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
HRESULT STDMETHODCALLTYPE InternetShortcut::Load(PIStream pistr) { HRESULT hr;
DebugEntry(InternetShortcut::Load);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_INTERFACE_PTR(pistr, IStream));
hr = E_NOTIMPL;
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
DebugExitHRESULT(InternetShortcut::Load, hr);
return(hr); }
HRESULT STDMETHODCALLTYPE InternetShortcut::Save(PIStream pistr, BOOL bClearDirty) { HRESULT hr;
DebugEntry(InternetShortcut::Save);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_INTERFACE_PTR(pistr, IStream));
// APPCOMPAT: Yes, this is an awful hack, but that's what we get when
// no one implements a needed interface and we need to get a product
// shipped. (Actually, the hack isn't that bad, as it's what happens in
// TransferFileContents, except we're writing to a stream and not memory).
const static TCHAR s_cszNewLine[] = TEXT("\r\n"); const static TCHAR s_cszPrefix[] = TEXT("[InternetShortcut]\r\nURL="); LPTSTR pszBuf; DWORD cb;
pszBuf = (LPTSTR)LocalAlloc(LPTR, lstrlen(m_pszURL) + lstrlen(s_cszPrefix) + lstrlen(s_cszNewLine) + 1);
if (pszBuf) { wsprintf(pszBuf, TEXT("%s%s%s"), s_cszPrefix, m_pszURL ? m_pszURL : TEXT("") , s_cszNewLine); hr = pistr->Write(pszBuf, lstrlen(pszBuf), &cb);
LocalFree(pszBuf); } else { hr = E_OUTOFMEMORY; } ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
DebugExitHRESULT(InternetShortcut::Save, hr);
return(hr); }
HRESULT STDMETHODCALLTYPE InternetShortcut::GetSizeMax(PULARGE_INTEGER pcbSize) { HRESULT hr;
DebugEntry(InternetShortcut::GetSizeMax);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_WRITE_PTR(pcbSize, ULARGE_INTEGER));
hr = E_NOTIMPL;
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
DebugExitHRESULT(InternetShortcut::GetSizeMax, hr);
return(hr); }
#pragma warning(default:4100) /* "unreferenced formal parameter" warning */
DWORD STDMETHODCALLTYPE InternetShortcut::GetFileContentsSize(void) { DWORD dwcbLen;
DebugEntry(InternetShortcut::GetFileContentsSize);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
// Section length.
// (- 1) for each null terminator.
HRESULT hr = CreateURLFileContents(m_pszURL, NULL);
// REARCHITECT: (DavidDi 3/29/95) We need to save more than just the URL string
// here, i.e., icon file and index, working directory, and show command.
dwcbLen = SUCCEEDED(hr) ? hr : 0;
dwcbLen++; // + 1 for final null terminator
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
DebugExitDWORD(InternetShortcut::GetFileContentsSize, dwcbLen);
return(dwcbLen); }
HRESULT STDMETHODCALLTYPE InternetShortcut::TransferUniformResourceLocator( PFORMATETC pfmtetc, PSTGMEDIUM pstgmed) { HRESULT hr;
DebugEntry(InternetShortcut::TransferUniformResourceLocator);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_STRUCT_PTR(pfmtetc, CFORMATETC)); ASSERT(IS_VALID_WRITE_PTR(pstgmed, STGMEDIUM));
ASSERT(pfmtetc->dwAspect == DVASPECT_CONTENT); ASSERT(pfmtetc->lindex == -1);
ZeroMemory(pstgmed, sizeof(*pstgmed));
if (IS_FLAG_SET(pfmtetc->tymed, TYMED_HGLOBAL)) { if (m_pszURL) { HGLOBAL hgURL;
hr = E_OUTOFMEMORY;
// (+ 1) for null terminator.
hgURL = GlobalAlloc(0, lstrlen(m_pszURL) + 1);
if (hgURL) { PSTR pszURL;
pszURL = (PSTR)GlobalLock(hgURL);
if (EVAL(pszURL)) { lstrcpy(pszURL, m_pszURL);
pstgmed->tymed = TYMED_HGLOBAL; pstgmed->hGlobal = hgURL; ASSERT(! pstgmed->pUnkForRelease);
hr = S_OK;
GlobalUnlock(hgURL); pszURL = NULL; }
if (hr != S_OK) { GlobalFree(hgURL); hgURL = NULL; } } } else hr = DV_E_FORMATETC; } else hr = DV_E_TYMED;
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT((hr == S_OK && IS_VALID_STRUCT_PTR(pstgmed, CSTGMEDIUM)) || (FAILED(hr) && (EVAL(pstgmed->tymed == TYMED_NULL) && EVAL(! pstgmed->hGlobal) && EVAL(! pstgmed->pUnkForRelease))));
DebugExitHRESULT(InternetShortcut::TransferUniformResourceLocator, hr);
return(hr); }
HRESULT STDMETHODCALLTYPE InternetShortcut::TransferText(PFORMATETC pfmtetc, PSTGMEDIUM pstgmed) { HRESULT hr;
DebugEntry(InternetShortcut::TransferText);
// Assume InternetShortcut::TransferUniformResourceLocator() will perform
// input and output validation.
hr = TransferUniformResourceLocator(pfmtetc, pstgmed);
DebugExitHRESULT(InternetShortcut::TransferText, hr);
return(hr); }
HRESULT STDMETHODCALLTYPE InternetShortcut::TransferFileGroupDescriptor( PFORMATETC pfmtetc, PSTGMEDIUM pstgmed) { HRESULT hr;
DebugEntry(InternetShortcut::TransferFileGroupDescriptor);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_STRUCT_PTR(pfmtetc, CFORMATETC)); ASSERT(IS_VALID_WRITE_PTR(pstgmed, STGMEDIUM));
ASSERT(pfmtetc->dwAspect == DVASPECT_CONTENT); ASSERT(pfmtetc->lindex == -1);
pstgmed->tymed = TYMED_NULL; pstgmed->hGlobal = NULL; pstgmed->pUnkForRelease = NULL;
if (IS_FLAG_SET(pfmtetc->tymed, TYMED_HGLOBAL)) { HGLOBAL hgFileGroupDesc;
hr = E_OUTOFMEMORY;
hgFileGroupDesc = GlobalAlloc(GMEM_ZEROINIT, sizeof(FILEGROUPDESCRIPTOR));
if (hgFileGroupDesc) { PFILEGROUPDESCRIPTOR pfgd;
pfgd = (PFILEGROUPDESCRIPTOR)GlobalLock(hgFileGroupDesc);
if (EVAL(pfgd)) { PFILEDESCRIPTOR pfd = &(pfgd->fgd[0]);
// Do we already have a file name to use?
if (m_pszFile) { lstrcpyn(pfd->cFileName, ExtractFileName(m_pszFile), SIZECHARS(pfd->cFileName));
hr = S_OK; } else { if (EVAL(MLLoadStringA( IDS_NEW_INTERNET_SHORTCUT, pfd->cFileName, sizeof(pfd->cFileName)))) hr = S_OK; }
if (hr == S_OK) { pfd->dwFlags = (FD_FILESIZE | FD_LINKUI); pfd->nFileSizeHigh = 0; pfd->nFileSizeLow = GetFileContentsSize();
pfgd->cItems = 1;
pstgmed->tymed = TYMED_HGLOBAL; pstgmed->hGlobal = hgFileGroupDesc; ASSERT(! pstgmed->pUnkForRelease); }
GlobalUnlock(hgFileGroupDesc); pfgd = NULL; }
if (hr != S_OK) { GlobalFree(hgFileGroupDesc); hgFileGroupDesc = NULL; } } } else hr = DV_E_TYMED;
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT((hr == S_OK && IS_VALID_STRUCT_PTR(pstgmed, CSTGMEDIUM)) || (FAILED(hr) && (EVAL(pstgmed->tymed == TYMED_NULL) && EVAL(! pstgmed->hGlobal) && EVAL(! pstgmed->pUnkForRelease))));
DebugExitHRESULT(InternetShortcut::TransferFileGroupDescriptor, hr);
return(hr); }
HRESULT STDMETHODCALLTYPE InternetShortcut::TransferFileContents( PFORMATETC pfmtetc, PSTGMEDIUM pstgmed) { HRESULT hr;
DebugEntry(InternetShortcut::TransferFileContents);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_STRUCT_PTR(pfmtetc, CFORMATETC)); ASSERT(IS_VALID_WRITE_PTR(pstgmed, STGMEDIUM));
ASSERT(pfmtetc->dwAspect == DVASPECT_CONTENT); ASSERT(! pfmtetc->lindex);
pstgmed->tymed = TYMED_NULL; pstgmed->hGlobal = NULL; pstgmed->pUnkForRelease = NULL;
if (IS_FLAG_SET(pfmtetc->tymed, TYMED_HGLOBAL)) { HGLOBAL hgFileContents; hr = CreateURLFileContents(m_pszURL, (LPSTR *)&hgFileContents);
if (SUCCEEDED(hr)) { // Note some apps don't pay attention to the nFileSizeLow
// field; fortunately, CreateURLFileContents adds a final
// null terminator to prevent trailing garbage.
pstgmed->tymed = TYMED_HGLOBAL; pstgmed->hGlobal = hgFileContents; ASSERT(! pstgmed->pUnkForRelease);
hr = S_OK; } else hr = E_OUTOFMEMORY; } else hr = DV_E_TYMED;
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT((hr == S_OK && IS_VALID_STRUCT_PTR(pstgmed, CSTGMEDIUM)) || (FAILED(hr) && (EVAL(pstgmed->tymed == TYMED_NULL) && EVAL(! pstgmed->hGlobal) && EVAL(! pstgmed->pUnkForRelease))));
DebugExitHRESULT(InternetShortcut::TransferFileContents, hr);
return(hr); }
#ifdef DEBUG
void STDMETHODCALLTYPE InternetShortcut::Dump(void) { ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
PLAIN_TRACE_OUT(("%sm_dwFlags = %#08lx", INDENT_STRING, m_dwFlags)); PLAIN_TRACE_OUT(("%sm_pszFile = \"%s\"", INDENT_STRING, CHECK_STRING(m_pszFile))); PLAIN_TRACE_OUT(("%sm_pszURL = \"%s\"", INDENT_STRING, CHECK_STRING(m_pszURL))); PLAIN_TRACE_OUT(("%sm_pszIconFile = \"%s\"", INDENT_STRING, CHECK_STRING(m_pszIconFile))); PLAIN_TRACE_OUT(("%sm_niIcon = %d", INDENT_STRING, m_niIcon)); PLAIN_TRACE_OUT(("%sm_wHotkey = %#04x", INDENT_STRING, (UINT)m_wHotkey)); PLAIN_TRACE_OUT(("%sm_pszWorkingDirectory = \"%s\"", INDENT_STRING, CHECK_STRING(m_pszWorkingDirectory))); PLAIN_TRACE_OUT(("%sm_nShowCmd = %d", INDENT_STRING, m_nShowCmd));
return; }
#endif
|