/* * shlink.cpp - IShellLink implementation for InternetShortcut class. */ /* Headers **********/ #include "project.hpp" #pragma hdrstop /* Types ********/ typedef enum isl_getpath_flags { // flag combinations ALL_ISL_GETPATH_FLAGS = (SLGP_SHORTPATH | SLGP_UNCPRIORITY) } ISL_GETPATH_FLAGS; typedef enum isl_resolve_flags { // flag combinations ALL_ISL_RESOLVE_FLAGS = (SLR_NO_UI | SLR_ANY_MATCH | SLR_UPDATE) } ISL_RESOLVE_FLAGS; /********************************** Methods **********************************/ HRESULT STDMETHODCALLTYPE InternetShortcut::SetPath(PCSTR pcszPath) { HRESULT hr; DebugEntry(InternetShortcut::SetPath); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_STRING_PTR(pcszPath, CSTR)); // Treat path as literal URL. hr = SetURL(pcszPath, 0); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); DebugExitHRESULT(InternetShortcut::SetPath, hr); return(hr); } #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */ HRESULT STDMETHODCALLTYPE InternetShortcut::GetPath(PSTR pszFile, int ncFileBufLen, PWIN32_FIND_DATA pwfd, DWORD dwFlags) { HRESULT hr; DebugEntry(InternetShortcut::GetPath); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszFile, STR, ncFileBufLen)); ASSERT(NULL == pwfd || IS_VALID_STRUCT_PTR(pwfd, CWIN32_FIND_DATA)); ASSERT(FLAGS_ARE_VALID(dwFlags, ALL_ISL_GETPATH_FLAGS)); // Ignore dwFlags. if (pwfd) ZeroMemory(pwfd, sizeof(*pwfd)); if (m_pszURL) { lstrcpyn(pszFile, m_pszURL, ncFileBufLen); hr = S_OK; } else { // No URL. if (ncFileBufLen > 0) *pszFile = '\0'; hr = S_FALSE; } ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT((hr == S_OK && (ncFileBufLen < 1 || IS_VALID_STRING_PTR(pszFile, STR))) || (hr == S_FALSE && (ncFileBufLen < 1 || ! *pszFile))); DebugExitHRESULT(InternetShortcut::GetPath, hr); return(hr); } HRESULT STDMETHODCALLTYPE InternetShortcut::SetRelativePath( PCSTR pcszRelativePath, DWORD dwReserved) { HRESULT hr; DebugEntry(InternetShortcut::SetRelativePath); // dwReserved may be any value. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_STRING_PTR(pcszRelativePath, CSTR)); hr = E_NOTIMPL; ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); DebugExitHRESULT(InternetShortcut::SetRelativePath, hr); return(hr); } HRESULT STDMETHODCALLTYPE InternetShortcut::SetIDList(LPCITEMIDLIST pcidl) { HRESULT hr; DebugEntry(InternetShortcut::SetIDList); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_STRUCT_PTR(pcidl, CITEMIDLIST)); hr = E_NOTIMPL; ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); DebugExitHRESULT(InternetShortcut::SetIDList, hr); return(hr); } #pragma warning(default:4100) /* "unreferenced formal parameter" warning */ HRESULT STDMETHODCALLTYPE InternetShortcut::GetIDList(LPITEMIDLIST *ppidl) { HRESULT hr; DebugEntry(InternetShortcut::GetIDList); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_WRITE_PTR(ppidl, PITEMIDLIST)); *ppidl = NULL; hr = E_NOTIMPL; ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); DebugExitHRESULT(InternetShortcut::GetIDList, hr); return(hr); } HRESULT STDMETHODCALLTYPE InternetShortcut::SetDescription( PCSTR pcszDescription) { HRESULT hr; BOOL bDifferent; PSTR pszFileCopy; DebugEntry(InternetShortcut::SetDescription); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_STRING_PTR(pcszDescription, CSTR)); // Set m_pszFile to description. bDifferent = (! m_pszFile || lstrcmp(pcszDescription, m_pszFile) != 0); if (StringCopy(pcszDescription, &pszFileCopy)) { if (m_pszFile) { delete m_pszFile; m_pszFile = NULL; } m_pszFile = pszFileCopy; if (bDifferent) Dirty(TRUE); hr = S_OK; } else hr = E_OUTOFMEMORY; ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); DebugExitHRESULT(InternetShortcut::SetDescription, hr); return(hr); } HRESULT STDMETHODCALLTYPE InternetShortcut::GetDescription( PSTR pszDescription, int ncDesciptionBufLen) { HRESULT hr; DebugEntry(InternetShortcut::GetDescription); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszDescription, STR, ncDesciptionBufLen)); // Get description from m_pszFile. if (m_pszFile) lstrcpyn(pszDescription, m_pszFile, ncDesciptionBufLen); else { if (ncDesciptionBufLen > 0) pszDescription = '\0'; } hr = S_OK; ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(hr == S_OK && (ncDesciptionBufLen <= 0 || (IS_VALID_STRING_PTR(pszDescription, STR) && EVAL(lstrlen(pszDescription) < ncDesciptionBufLen)))); DebugExitHRESULT(InternetShortcut::GetDescription, hr); return(hr); } #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */ HRESULT STDMETHODCALLTYPE InternetShortcut::SetArguments(PCSTR pcszArgs) { HRESULT hr; DebugEntry(InternetShortcut::SetArguments); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_STRING_PTR(pcszArgs, CSTR)); hr = E_NOTIMPL; ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); DebugExitHRESULT(InternetShortcut::SetArguments, hr); return(hr); } #pragma warning(default:4100) /* "unreferenced formal parameter" warning */ HRESULT STDMETHODCALLTYPE InternetShortcut::GetArguments(PSTR pszArgs, int ncArgsBufLen) { HRESULT hr; DebugEntry(InternetShortcut::GetArguments); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszArgs, STR, ncArgsBufLen)); if (ncArgsBufLen > 0) *pszArgs = '\0'; hr = E_NOTIMPL; WARNING_OUT(("InternetShortcut::GetArguments(): Arguments not maintained for CLSID_InternetShortcut.")); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); DebugExitHRESULT(InternetShortcut::GetArguments, hr); return(hr); } HRESULT STDMETHODCALLTYPE InternetShortcut::SetWorkingDirectory( PCSTR pcszWorkingDirectory) { HRESULT hr = S_OK; char rgchNewPath[MAX_PATH_LEN]; BOOL bChanged = FALSE; PSTR pszNewWorkingDirectory = NULL; DebugEntry(InternetShortcut::SetWorkingDirectory); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(! pcszWorkingDirectory || IS_VALID_STRING_PTR(pcszWorkingDirectory, CSTR)); if (! AnyMeat(pcszWorkingDirectory)) pcszWorkingDirectory = NULL; if (pcszWorkingDirectory) { PSTR pszFileName; if (GetFullPathName(pcszWorkingDirectory, sizeof(rgchNewPath), rgchNewPath, &pszFileName) > 0) pcszWorkingDirectory = rgchNewPath; else hr = E_PATH_NOT_FOUND; } if (hr == S_OK) { bChanged = ! ((! pcszWorkingDirectory && ! m_pszWorkingDirectory) || (pcszWorkingDirectory && m_pszWorkingDirectory && ! lstrcmp(pcszWorkingDirectory, m_pszWorkingDirectory))); if (bChanged && pcszWorkingDirectory) { // (+ 1) for null terminator. pszNewWorkingDirectory = new(char[lstrlen(pcszWorkingDirectory) + 1]); if (pszNewWorkingDirectory) lstrcpy(pszNewWorkingDirectory, pcszWorkingDirectory); else hr = E_OUTOFMEMORY; } } if (hr == S_OK) { if (bChanged) { if (m_pszWorkingDirectory) delete m_pszWorkingDirectory; m_pszWorkingDirectory = pszNewWorkingDirectory; Dirty(TRUE); TRACE_OUT(("InternetShortcut::SetWorkingDirectory(): Set working directory to %s.", CHECK_STRING(m_pszWorkingDirectory))); } else TRACE_OUT(("InternetShortcut::SetWorkingDirectory(): Working directory already %s.", CHECK_STRING(m_pszWorkingDirectory))); } ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(hr == S_OK || hr == E_OUTOFMEMORY || hr == E_PATH_NOT_FOUND); DebugExitHRESULT(InternetShortcut::SetWorkingDirectory, hr); return(hr); } HRESULT STDMETHODCALLTYPE InternetShortcut::GetWorkingDirectory( PSTR pszWorkingDirectory, int ncbWorkingDirectoryBufLen) { HRESULT hr; DebugEntry(InternetShortcut::GetWorkingDirectory); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszWorkingDirectory, STR, ncbWorkingDirectoryBufLen)); if (m_pszWorkingDirectory) { lstrcpyn(pszWorkingDirectory, m_pszWorkingDirectory, ncbWorkingDirectoryBufLen); hr = S_OK; } else { if (ncbWorkingDirectoryBufLen > 0) *pszWorkingDirectory = '\0'; hr = S_FALSE; } ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IsValidPathResult(hr, pszWorkingDirectory, ncbWorkingDirectoryBufLen)); ASSERT(hr == S_OK || hr == S_FALSE); DebugExitHRESULT(InternetShortcut::GetWorkingDirectory, hr); return(hr); } HRESULT STDMETHODCALLTYPE InternetShortcut::SetHotkey(WORD wHotkey) { HRESULT hr; DebugEntry(InternetShortcut::SetHotkey); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(! wHotkey || EVAL(IsValidHotkey(wHotkey))); if (wHotkey != m_wHotkey) Dirty(TRUE); m_wHotkey = wHotkey; hr = S_OK; ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); DebugExitHRESULT(InternetShortcut::SetHotkey, hr); return(hr); } HRESULT STDMETHODCALLTYPE InternetShortcut::GetHotkey(PWORD pwHotkey) { HRESULT hr; DebugEntry(InternetShortcut::GetHotkey); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_WRITE_PTR(pwHotkey, WORD)); *pwHotkey = m_wHotkey; hr = S_OK; ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(! *pwHotkey || EVAL(IsValidHotkey(*pwHotkey))); DebugExitHRESULT(InternetShortcut::GetHotkey, hr); return(hr); } HRESULT STDMETHODCALLTYPE InternetShortcut::SetShowCmd(int nShowCmd) { HRESULT hr; DebugEntry(InternetShortcut::SetShowCmd); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IsValidShowCmd(nShowCmd)); if (nShowCmd != m_nShowCmd) { m_nShowCmd = nShowCmd; Dirty(TRUE); TRACE_OUT(("InternetShortcut::SetShowCmd(): Set show command to %d.", m_nShowCmd)); } else TRACE_OUT(("InternetShortcut::SetShowCmd(): Show command already %d.", m_nShowCmd)); hr = S_OK; ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(hr == S_OK); DebugExitHRESULT(InternetShortcut::SetShowCmd, hr); return(hr); } HRESULT STDMETHODCALLTYPE InternetShortcut::GetShowCmd(PINT pnShowCmd) { HRESULT hr; DebugEntry(InternetShortcut::GetShowCmd); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_WRITE_PTR(pnShowCmd, INT)); *pnShowCmd = m_nShowCmd; hr = S_OK; ASSERT(IsValidShowCmd(m_nShowCmd)); DebugExitHRESULT(InternetShortcut::GetShowCmd, hr); return(hr); } HRESULT STDMETHODCALLTYPE InternetShortcut::SetIconLocation(PCSTR pcszIconFile, int niIcon) { HRESULT hr = S_OK; BOOL bNewMeat; char rgchNewPath[MAX_PATH_LEN]; DebugEntry(InternetShortcut::SetIconLocation); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IsValidIconIndex(pcszIconFile ? S_OK : S_FALSE, pcszIconFile, MAX_PATH_LEN, niIcon)); bNewMeat = AnyMeat(pcszIconFile); if (bNewMeat) hr = FullyQualifyPath(pcszIconFile, rgchNewPath, sizeof(rgchNewPath)); if (hr == S_OK) { char rgchOldPath[MAX_PATH_LEN]; int niOldIcon; UINT uFlags; hr = GetIconLocation(0, rgchOldPath, sizeof(rgchOldPath), &niOldIcon, &uFlags); if (SUCCEEDED(hr)) { BOOL bOldMeat; BOOL bChanged = FALSE; PSTR pszNewIconFile = NULL; int niNewIcon = 0; bOldMeat = AnyMeat(rgchOldPath); ASSERT(! *rgchOldPath || bOldMeat); bChanged = ((! bOldMeat && bNewMeat) || (bOldMeat && ! bNewMeat) || (bOldMeat && bNewMeat && (lstrcmp(rgchOldPath, rgchNewPath) != 0 || niIcon != niOldIcon))); if (bChanged && bNewMeat) { // (+ 1) for null terminator. pszNewIconFile = new(char[lstrlen(rgchNewPath) + 1]); if (pszNewIconFile) { lstrcpy(pszNewIconFile, rgchNewPath); niNewIcon = niIcon; hr = S_OK; } else hr = E_OUTOFMEMORY; } else hr = S_OK; if (hr == S_OK) { if (bChanged) { if (m_pszIconFile) delete m_pszIconFile; m_pszIconFile = pszNewIconFile; m_niIcon = niNewIcon; Dirty(TRUE); TRACE_OUT(("InternetShortcut::SetIconLocation(): Set icon location to %d in %s.", m_niIcon, CHECK_STRING(m_pszIconFile))); } else TRACE_OUT(("InternetShortcut::SetIconLocation(): Icon location already %d in %s.", m_niIcon, CHECK_STRING(m_pszIconFile))); } } } ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(hr == S_OK || hr == E_OUTOFMEMORY || hr == E_FILE_NOT_FOUND); DebugExitHRESULT(InternetShortcut::SetIconLocation, hr); return(hr); } HRESULT STDMETHODCALLTYPE InternetShortcut::GetIconLocation( PSTR pszIconFile, int ncbIconFileBufLen, PINT pniIcon) { HRESULT hr; DebugEntry(InternetShortcut::GetIconLocation); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszIconFile, STR, ncbIconFileBufLen)); ASSERT(IS_VALID_WRITE_PTR(pniIcon, int)); if (m_pszIconFile) { lstrcpyn(pszIconFile, m_pszIconFile, ncbIconFileBufLen); *pniIcon = m_niIcon; hr = S_OK; } else { if (ncbIconFileBufLen > 0) *pszIconFile = '\0'; *pniIcon = 0; hr = S_FALSE; } ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IsValidIconIndex(hr, pszIconFile, ncbIconFileBufLen, *pniIcon)); DebugExitHRESULT(InternetShortcut::GetIconLocation, hr); return(hr); } #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */ HRESULT STDMETHODCALLTYPE InternetShortcut::Resolve(HWND hwnd, DWORD dwFlags) { HRESULT hr; DebugEntry(InternetShortcut::Resolve); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_HANDLE(hwnd, WND)); ASSERT(FLAGS_ARE_VALID(dwFlags, ALL_ISL_RESOLVE_FLAGS)); hr = S_OK; WARNING_OUT(("InternetShortcut::Resolve(): This method is a NOP for CLSID_InternetShortcut.")); ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); DebugExitHRESULT(InternetShortcut::Resolve, hr); return(hr); } #pragma warning(default:4100) /* "unreferenced formal parameter" warning */