|
|
/*
* shlink.cpp - IShellLink implementation for CFusionShortcut class. */
// note: BUGBUG?
// from MSDN, it's unclear that for the GetX methods the len arguments
// are counting the terminating NULL or not.
// "size of the buffer pointed by szX"
// so here, and other methods, assume they do -ie. wcslen(s) + L'\0'
/* Headers
**********/
#include "project.hpp"
/* Types
********/
/*typedef enum isl_getpath_flags
{ // flag combinations
ALL_ISL_GETPATH_FLAGS = (SLGP_SHORTPATH | SLGP_UNCPRIORITY) } ISL_GETPATH_FLAGS;*/
/********************************** Methods **********************************/
HRESULT STDMETHODCALLTYPE CFusionShortcut::SetPath(LPCWSTR pcwzPath) { HRESULT hr = S_OK; WCHAR rgchNewPath[MAX_PATH]; BOOL bChanged = FALSE; LPWSTR pwzOriPath = (LPWSTR) pcwzPath; // still, pwzOriPath shouldn't be modified
LPWSTR pwzFixedPath = NULL;
ASSERT(! pwzOriPath)
// ... this checks if all space in string...
if (! AnyNonWhiteSpace(pwzOriPath)) pwzOriPath = NULL;
if (pwzOriPath) { LPWSTR pwzFileName;
// this ignores "If the lpBuffer buffer is too small, the return value is the size
// of the buffer, in WCHARs, required to hold the path"
if (GetFullPathName(pwzOriPath, sizeof(rgchNewPath)/sizeof(WCHAR), rgchNewPath, &pwzFileName) > 0) pwzOriPath = rgchNewPath; else hr = GetLastWin32Error(); }
if (hr == S_OK) { bChanged = ! ((! pwzOriPath && ! m_pwzPath) || (pwzOriPath && m_pwzPath && ! wcscmp(pwzOriPath, m_pwzPath)));
if (bChanged && pwzOriPath) { // (+ 1) for null terminator.
pwzFixedPath = new(WCHAR[wcslen(pwzOriPath) + 1]);
if (pwzFixedPath) wcscpy(pwzFixedPath, pwzOriPath); else hr = E_OUTOFMEMORY; } }
if (hr == S_OK && bChanged) { if (m_pwzPath) delete [] m_pwzPath;
m_pwzPath = pwzFixedPath;
Dirty(TRUE); }
ASSERT(hr == S_OK || FAILED(hr));
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::GetPath(LPWSTR pwzFile, int ncFileBufLen, PWIN32_FIND_DATA pwfd, DWORD dwFlags) { HRESULT hr = S_OK;
ASSERT(NULL == pwfd); // Ignore dwFlags.
if (pwfd) ZeroMemory(pwfd, sizeof(*pwfd));
if (m_pwzPath) { if (pwzFile == NULL || ncFileBufLen <= 0) hr = E_INVALIDARG; else { wcsncpy(pwzFile, m_pwzPath, ncFileBufLen-1); pwzFile[ncFileBufLen-1] = L'\0'; } } else { if (ncFileBufLen > 0 && pwzFile != NULL) *pwzFile = L'\0';
hr = S_FALSE; }
ASSERT((hr == S_OK && ncFileBufLen < 1) || (hr == S_FALSE && (ncFileBufLen < 1 || ! *pwzFile)));
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::SetRelativePath(LPCWSTR pcwzRelativePath, DWORD dwReserved) { HRESULT hr;
// dwReserved may be any value.
hr = E_NOTIMPL;
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::SetIDList(LPCITEMIDLIST pcidl) { HRESULT hr;
hr = E_NOTIMPL;
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::GetIDList(LPITEMIDLIST *ppidl) { HRESULT hr;
if (ppidl != NULL) *ppidl = NULL;
hr = E_NOTIMPL;
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::SetDescription(LPCWSTR pcwzDescription) { HRESULT hr = S_OK; BOOL bDifferent; LPWSTR pwzNewDesc = NULL;
// Set m_pwzDesc to description.
bDifferent = ! ((! pcwzDescription && ! m_pwzDesc) || (pcwzDescription && m_pwzDesc && ! wcscmp(pcwzDescription, m_pwzDesc)));
if (bDifferent && pcwzDescription) { // (+ 1) for null terminator.
pwzNewDesc = new(WCHAR[wcslen(pcwzDescription) + 1]);
if (pwzNewDesc) wcscpy(pwzNewDesc, pcwzDescription); else hr = E_OUTOFMEMORY; }
if (hr == S_OK && bDifferent) { if (m_pwzDesc) delete [] m_pwzDesc;
m_pwzDesc = pwzNewDesc;
Dirty(TRUE); }
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::GetDescription(LPWSTR pwzDescription, int ncDesciptionBufLen) { HRESULT hr = S_OK;
// Get description from m_pwzDesc.
if (m_pwzDesc) { if (pwzDescription == NULL || ncDesciptionBufLen <= 0) hr = E_INVALIDARG; else { wcsncpy(pwzDescription, m_pwzDesc, ncDesciptionBufLen-1); pwzDescription[ncDesciptionBufLen-1] = L'\0'; } } else { if (ncDesciptionBufLen > 0 && pwzDescription != NULL) pwzDescription = L'\0'; }
ASSERT(hr == S_OK && (ncDesciptionBufLen <= 0 || EVAL(wcslen(pwzDescription) < ncDesciptionBufLen)));
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::SetArguments(LPCWSTR pcwzArgs) { HRESULT hr;
hr = E_NOTIMPL;
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::GetArguments(LPWSTR pwzArgs, int ncArgsBufLen) { HRESULT hr;
if (ncArgsBufLen > 0 && pwzArgs != NULL) *pwzArgs = L'\0';
hr = E_NOTIMPL;
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::SetWorkingDirectory(LPCWSTR pcwzWorkingDirectory) { HRESULT hr = S_OK; WCHAR rgchNewPath[MAX_PATH]; BOOL bChanged = FALSE; LPWSTR pwzOriWorkingDirectory = (LPWSTR) pcwzWorkingDirectory; // still, pwzOriWorkingDirectory shouldn't be modified
LPWSTR pwzFixedWorkingDirectory = NULL;
ASSERT(! pwzOriWorkingDirectory)
// ... this checks if all space in string...
if (! AnyNonWhiteSpace(pwzOriWorkingDirectory)) pwzOriWorkingDirectory = NULL;
if (pwzOriWorkingDirectory) { LPWSTR pwzFileName;
// this ignores "If the lpBuffer buffer is too small, the return value is the size
// of the buffer, in WCHARs, required to hold the path"
if (GetFullPathName(pwzOriWorkingDirectory, sizeof(rgchNewPath)/sizeof(WCHAR), rgchNewPath, &pwzFileName) > 0) pwzOriWorkingDirectory = rgchNewPath; else hr = GetLastWin32Error(); }
if (hr == S_OK) { bChanged = ! ((! pwzOriWorkingDirectory && ! m_pwzWorkingDirectory) || (pwzOriWorkingDirectory && m_pwzWorkingDirectory && ! wcscmp(pwzOriWorkingDirectory, m_pwzWorkingDirectory)));
if (bChanged && pwzOriWorkingDirectory) { // (+ 1) for null terminator.
pwzFixedWorkingDirectory = new(WCHAR[wcslen(pwzOriWorkingDirectory) + 1]);
if (pwzFixedWorkingDirectory) wcscpy(pwzFixedWorkingDirectory, pwzOriWorkingDirectory); else hr = E_OUTOFMEMORY; } }
if (hr == S_OK && bChanged) { if (m_pwzWorkingDirectory) delete [] m_pwzWorkingDirectory;
m_pwzWorkingDirectory = pwzFixedWorkingDirectory;
Dirty(TRUE); }
ASSERT(hr == S_OK || FAILED(hr));
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::GetWorkingDirectory(LPWSTR pwzWorkingDirectory, int ncbWorkingDirectoryBufLen) { HRESULT hr = S_OK;
if (m_pwzWorkingDirectory) { if (pwzWorkingDirectory == NULL || ncbWorkingDirectoryBufLen <= 0) hr = E_INVALIDARG; else { wcsncpy(pwzWorkingDirectory, m_pwzWorkingDirectory, ncbWorkingDirectoryBufLen-1); pwzWorkingDirectory[ncbWorkingDirectoryBufLen-1] = L'\0'; } } else { if (ncbWorkingDirectoryBufLen > 0 && pwzWorkingDirectory != NULL) *pwzWorkingDirectory = L'\0';
hr = S_FALSE; }
ASSERT(IsValidPathResult(hr, pwzWorkingDirectory, ncbWorkingDirectoryBufLen)); ASSERT(hr == S_OK || hr == S_FALSE);
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::SetHotkey(WORD wHotkey) { HRESULT hr=S_OK;
ASSERT(! wHotkey)
if (wHotkey != m_wHotkey) { m_wHotkey = wHotkey; Dirty(TRUE); }
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::GetHotkey(PWORD pwHotkey) { HRESULT hr=S_OK;
if (pwHotkey == NULL) hr = E_INVALIDARG; else *pwHotkey = m_wHotkey;
ASSERT(! *pwHotkey)
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::SetShowCmd(int nShowCmd) { HRESULT hr=S_OK;
ASSERT(IsValidShowCmd(nShowCmd));
if (nShowCmd != m_nShowCmd) { m_nShowCmd = nShowCmd;
Dirty(TRUE); }
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::GetShowCmd(PINT pnShowCmd) { HRESULT hr=S_OK;
if (pnShowCmd == NULL) hr = E_INVALIDARG; else *pnShowCmd = m_nShowCmd;
ASSERT(IsValidShowCmd(m_nShowCmd));
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::SetIconLocation(LPCWSTR pcwzIconFile, int niIcon) { HRESULT hr = S_OK; BOOL bNewNonWhiteSpace;
ASSERT(IsValidIconIndex(pcwzIconFile ? S_OK : S_FALSE, pcwzIconFile, MAX_PATH, niIcon));
bNewNonWhiteSpace = AnyNonWhiteSpace(pcwzIconFile);
if (hr == S_OK) { WCHAR rgchOldPath[MAX_PATH]; int niOldIcon; UINT uFlags;
hr = GetIconLocation(0, rgchOldPath, sizeof(rgchOldPath)/sizeof(WCHAR), &niOldIcon, &uFlags);
// should this continue even if there's error getting icon location??
if (SUCCEEDED(hr)) { BOOL bOldNonWhiteSpace; BOOL bChanged = FALSE; LPWSTR pwzNewIconFile = NULL; int niNewIcon = 0;
bOldNonWhiteSpace = AnyNonWhiteSpace(rgchOldPath);
ASSERT(! *rgchOldPath || bOldNonWhiteSpace);
// check
bChanged = ((! bOldNonWhiteSpace && bNewNonWhiteSpace) || (bOldNonWhiteSpace && ! bNewNonWhiteSpace) || (bOldNonWhiteSpace && bNewNonWhiteSpace && (wcscmp(rgchOldPath, pcwzIconFile) != 0 || niIcon != niOldIcon)));
// clear hr
hr = S_OK; if (bChanged && bNewNonWhiteSpace) { // (+ 1) for null terminator.
// BUGBUG: slightly not optimize as it makes a copy even if only the index changes
pwzNewIconFile = new(WCHAR[wcslen(pcwzIconFile) + 1]);
if (pwzNewIconFile) { wcscpy(pwzNewIconFile, pcwzIconFile); niNewIcon = niIcon; } else hr = E_OUTOFMEMORY; } if (hr == S_OK && bChanged) { if (m_pwzIconFile) delete [] m_pwzIconFile;
m_pwzIconFile = pwzNewIconFile; m_niIcon = niNewIcon;
Dirty(TRUE); } } }
ASSERT(hr == S_OK || hr == E_OUTOFMEMORY || hr == E_FILE_NOT_FOUND);
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::GetIconLocation(LPWSTR pwzIconFile, int ncbIconFileBufLen, PINT pniIcon) { HRESULT hr=S_OK;
// this ignores icon index (even if set) if icon file path is not
if (m_pwzIconFile) { if (pwzIconFile == NULL || ncbIconFileBufLen <= 0) hr = E_INVALIDARG; else { wcsncpy(pwzIconFile, m_pwzIconFile, ncbIconFileBufLen-1); pwzIconFile[ncbIconFileBufLen-1] = L'\0';
if (pniIcon == NULL) hr = E_INVALIDARG; else *pniIcon = m_niIcon; } } else { if (ncbIconFileBufLen > 0 && pwzIconFile != NULL) *pwzIconFile = L'\0';
if (pniIcon != NULL) *pniIcon = 0;
hr = S_FALSE; }
ASSERT(IsValidIconIndex(hr, pwzIconFile, ncbIconFileBufLen, *pniIcon));
return(hr); }
HRESULT STDMETHODCALLTYPE CFusionShortcut::Resolve(HWND hwnd, DWORD dwFlags) { HRESULT hr;
ASSERT(IS_VALID_HANDLE(hwnd, WND));
// BUGBUG?: check dwFlags
hr = S_OK;
// BUGBUG?: should this check the shortcut and do the UI/update/save?
return(hr); }
|