|
|
/*
* urlprop.cpp - Implementation for URLProp class. */
#include "priv.h"
#include "ishcut.h"
STDAPI_(LPITEMIDLIST) IEILCreate(UINT cbSize);
#define MAX_BUF_INT (1 + 10 + 1) // -2147483647
const TCHAR c_szIntshcut[] = ISHCUT_INISTRING_SECTION;
#ifdef DEBUG
BOOL IsValidPCURLProp(PCURLProp pcurlprop) { return (IS_VALID_READ_PTR(pcurlprop, CURLProp) && (NULL == pcurlprop->m_hstg || IS_VALID_HANDLE(pcurlprop->m_hstg, PROPSTG))); }
BOOL IsValidPCIntshcutProp(PCIntshcutProp pcisprop) { return (IS_VALID_READ_PTR(pcisprop, CIntshcutProp) && IS_VALID_STRUCT_PTR(pcisprop, CURLProp)); }
BOOL IsValidPCIntsiteProp(PCIntsiteProp pcisprop) { return (IS_VALID_READ_PTR(pcisprop, CIntsiteProp) && IS_VALID_STRUCT_PTR(pcisprop, CURLProp)); }
#endif
BOOL AnyMeatW(LPCWSTR pcsz) { ASSERT(! pcsz || IS_VALID_STRING_PTRW(pcsz, -1)); return(pcsz ? StrSpnW(pcsz, L" \t") < lstrlenW(pcsz) : FALSE); }
BOOL AnyMeatA(LPCSTR pcsz) { ASSERT(! pcsz || IS_VALID_STRING_PTRA(pcsz, -1)); return(pcsz ? StrSpnA(pcsz, " \t") < lstrlenA(pcsz) : FALSE); }
/*----------------------------------------------------------
Purpose: Read an arbitrary named string from the .ini file.
Returns: S_OK if the name exists S_FALSE if it doesn't
E_OUTOFMEMORY */ HRESULT ReadStringFromFile(IN LPCTSTR pszFile, IN LPCTSTR pszSectionName, IN LPCTSTR pszName, OUT LPWSTR * ppwsz, IN CHAR * pszBuf) { HRESULT hres = E_OUTOFMEMORY; ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); ASSERT(IS_VALID_STRING_PTR(pszName, -1)); ASSERT(IS_VALID_WRITE_PTR(ppwsz, PWSTR)); *ppwsz = (LPWSTR)LocalAlloc(LPTR, SIZEOF(WCHAR) * INTERNET_MAX_URL_LENGTH); if (*ppwsz) { DWORD cch; hres = S_OK;
cch = SHGetIniString(pszSectionName, pszName, *ppwsz, INTERNET_MAX_URL_LENGTH, pszFile); if (0 == cch) { hres = S_FALSE; LocalFree(*ppwsz); *ppwsz = NULL; } } return hres; }
/*----------------------------------------------------------
Purpose: Read an arbitrary named string from the .ini file. Return a BSTR
Returns: S_OK if the name exists S_FALSE if it doesn't
E_OUTOFMEMORY */ HRESULT ReadBStrFromFile(IN LPCTSTR pszFile, IN LPCTSTR pszSectionName, IN LPCTSTR pszName, OUT BSTR * pBStr) { CHAR szTempBuf[INTERNET_MAX_URL_LENGTH]; WCHAR *pwsz; HRESULT hres = E_OUTOFMEMORY; *pBStr = NULL; ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); ASSERT(IS_VALID_STRING_PTR(pszName, -1)); ASSERT(IS_VALID_WRITE_PTR(pBStr, PWSTR));
// (Pass in an empty string so we can determine from the return
// value whether there is any text associated with this name.)
hres = ReadStringFromFile(pszFile, pszSectionName, pszName, &pwsz, szTempBuf); if (S_OK == hres) { *pBStr = SysAllocString(pwsz); LocalFree(pwsz); pwsz = NULL; }
return hres; }
/*----------------------------------------------------------
Purpose: read an arbitrary named unsigend int from the .ini file. note in order to implement ReadSignedFromFile one'll need to use ReadStringFromFile and then StrToIntEx. this is because GetPrivateProfileInt can't return a negative.
Returns: S_OK if the name exists S_FALSE if it doesn't
E_OUTOFMEMORY */ HRESULT ReadUnsignedFromFile( IN LPCTSTR pszFile, IN LPCTSTR pszSectionName, IN LPCTSTR pszName, IN LPDWORD pdwVal) { HRESULT hr; int iValue;
ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); ASSERT(IS_VALID_STRING_PTR(pszSectionName, -1)); ASSERT(IS_VALID_STRING_PTR(pszName, -1));
if (NULL == pdwVal) return E_INVALIDARG; *pdwVal = 0;
hr = S_OK; iValue = GetPrivateProfileInt(pszSectionName, pszName, 1, pszFile); if (1 == iValue) { iValue = GetPrivateProfileInt(pszSectionName, pszName, 2, pszFile); hr = (2 != iValue) ? S_OK : S_FALSE; ASSERT(S_FALSE == hr || 1 == iValue); }
if (S_OK == hr) *pdwVal = (DWORD)iValue;
return hr; }
/*----------------------------------------------------------
Purpose: Write number to URL (ini) file
*/ HRESULT WriteSignedToFile(IN LPCTSTR pszFile, IN LPCTSTR pszSectionName, IN LPCTSTR pszName, IN int nVal) { HRESULT hres; TCHAR szVal[MAX_BUF_INT]; int cch; ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); ASSERT(IS_VALID_STRING_PTR(pszName, -1)); cch = wnsprintf(szVal, ARRAYSIZE(szVal), TEXT("%d"), nVal); ASSERT(cch > 0); ASSERT(cch < SIZECHARS(szVal)); ASSERT(cch == lstrlen(szVal)); hres = WritePrivateProfileString(pszSectionName, pszName, szVal, pszFile) ? S_OK : E_FAIL; return hres; }
/*----------------------------------------------------------
Purpose: Write number to URL (ini) file
*/ HRESULT WriteUnsignedToFile(IN LPCTSTR pszFile, IN LPCTSTR pszSectionName, IN LPCTSTR pszName, IN DWORD nVal) { HRESULT hres; TCHAR szVal[MAX_BUF_INT]; int cch; ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); ASSERT(IS_VALID_STRING_PTR(pszName, -1)); cch = wnsprintf(szVal, ARRAYSIZE(szVal), TEXT("%u"), nVal); ASSERT(cch > 0); ASSERT(cch < SIZECHARS(szVal)); ASSERT(cch == lstrlen(szVal)); hres = WritePrivateProfileString(pszSectionName, pszName, szVal, pszFile) ? S_OK : E_FAIL; return hres; }
/*----------------------------------------------------------
Purpose: Write binary data to URL (ini) file
*/ HRESULT WriteBinaryToFile(IN LPCTSTR pszFile, IN LPCTSTR pszSectionName, IN LPCTSTR pszName, IN LPVOID pvData, IN DWORD cbSize) { HRESULT hres; ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); ASSERT(IS_VALID_STRING_PTR(pszName, -1));
hres = (WritePrivateProfileStruct(pszSectionName, pszName, pvData, cbSize, pszFile)) ? S_OK : E_FAIL; return hres; }
/*----------------------------------------------------------
Purpose: Read the hotkey from the URL (ini) file
*/ HRESULT ReadBinaryFromFile(IN LPCTSTR pszFile, IN LPCTSTR pszSectionName, IN LPCTSTR pszName, IN LPVOID pvData, IN DWORD cbData) { HRESULT hres = S_FALSE; ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); memset(pvData, 0, cbData); if (GetPrivateProfileStruct(pszSectionName, pszName, pvData, cbData, pszFile)) hres = S_OK; return hres; }
/*----------------------------------------------------------
Purpose: Real the URL from the URL (ini) file
*/ HRESULT ReadURLFromFile( IN LPCTSTR pszFile, IN LPCTSTR pszSectionName, OUT LPTSTR * ppsz) { HRESULT hres = E_OUTOFMEMORY; *ppsz = (LPTSTR)LocalAlloc(LPTR, SIZEOF(TCHAR) * INTERNET_MAX_URL_LENGTH); if (*ppsz) { DWORD cch;
cch = SHGetIniString(pszSectionName, ISHCUT_INISTRING_URL, *ppsz, INTERNET_MAX_URL_LENGTH, pszFile); if (0 != cch) { PathRemoveBlanks(*ppsz); hres = S_OK; } else { LocalFree(*ppsz); *ppsz = NULL; hres = S_FALSE; } } return hres; }
/*----------------------------------------------------------
Purpose: Read the icon location from the URL (ini) file
Returns: S_OK value was obtained from file S_FALSE value wasn't in file
E_OUTOFMEMORY */ HRESULT ReadIconLocation( IN LPCTSTR pszFile, OUT LPWSTR * ppwsz, OUT int * pniIcon, IN CHAR * pszBuf) { HRESULT hres = E_OUTOFMEMORY; DWORD cch; ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); ASSERT(IS_VALID_WRITE_PTR(ppwsz, PTSTR)); ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT)); *ppwsz = NULL; *pniIcon = 0; *ppwsz = (LPWSTR)LocalAlloc(LPTR, SIZEOF(WCHAR) * MAX_PATH); if (*ppwsz) { hres = S_FALSE; // assume no value exists in the file
cch = SHGetIniString(c_szIntshcut, ISHCUT_INISTRING_ICONFILE, *ppwsz, MAX_PATH, pszFile); if (0 != cch) { TCHAR szIndex[MAX_BUF_INT]; // The icon index is all ASCII so don't need SHGetIniString
cch = GetPrivateProfileString(c_szIntshcut, ISHCUT_INISTRING_ICONINDEX, c_szNULL, szIndex, SIZECHARS(szIndex), pszFile); if (0 != cch) { if (StrToIntEx(szIndex, 0, pniIcon)) hres = S_OK; } } if (S_OK != hres) { LocalFree(*ppwsz); *ppwsz = NULL; } } return hres; }
/*----------------------------------------------------------
Purpose: Write icon location to URL (ini) file
*/ HRESULT WriteIconFile( IN LPCTSTR pszFile, IN LPCWSTR pszIconFile) { HRESULT hres = S_OK; ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); ASSERT(! pszIconFile || IS_VALID_STRING_PTRW(pszIconFile, -1)); if (*pszFile) { if (AnyMeatW(pszIconFile)) { hres = SHSetIniString(c_szIntshcut, ISHCUT_INISTRING_ICONFILE, pszIconFile, pszFile) ? S_OK : E_FAIL; } else { // NOTE: since this function removes both the file and the index
// values, then this function must be called *after* any call
// to WriteIconIndex. One way to do this is make sure
// PID_IS_ICONINDEX < PID_IS_ICONFILE, since the index will
// be enumerated first.
hres = (SHDeleteIniString(c_szIntshcut, ISHCUT_INISTRING_ICONFILE, pszFile) && DeletePrivateProfileString(c_szIntshcut, ISHCUT_INISTRING_ICONINDEX, pszFile)) ? S_OK : E_FAIL; } } return hres; }
/*----------------------------------------------------------
Purpose: Write icon index to URL (ini) file
*/ HRESULT WriteIconIndex( IN LPCTSTR pszFile, IN int niIcon) { HRESULT hres; if (*pszFile) hres = WriteSignedToFile(pszFile, c_szIntshcut, ISHCUT_INISTRING_ICONINDEX, niIcon); else hres = S_FALSE; return hres; }
/*----------------------------------------------------------
Purpose: Read the hotkey from the URL (ini) file
*/ HRESULT ReadHotkey( IN LPCTSTR pszFile, IN WORD * pwHotkey) { HRESULT hres = S_FALSE; TCHAR szHotkey[MAX_BUF_INT]; DWORD cch; ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); ASSERT(IS_VALID_WRITE_PTR(pwHotkey, WORD)); *pwHotkey = 0; cch = GetPrivateProfileString(c_szIntshcut, TEXT("Hotkey"), c_szNULL, szHotkey, SIZECHARS(szHotkey), pszFile); if (0 != cch) { int nVal; if (StrToIntEx(szHotkey, 0, &nVal)) { *pwHotkey = nVal; hres = S_OK; } } return hres; }
/*----------------------------------------------------------
Purpose: Write hotkey to URL (ini) file
*/ HRESULT WriteHotkey( IN LPCTSTR pszFile, IN WORD wHotkey) { HRESULT hres = S_FALSE; ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); if (*pszFile) { if (wHotkey) { hres = WriteUnsignedToFile(pszFile, c_szIntshcut, TEXT("Hotkey"), wHotkey); } else { hres = DeletePrivateProfileString(c_szIntshcut, TEXT("Hotkey"), pszFile) ? S_OK : E_FAIL; } } return hres; }
/*----------------------------------------------------------
Purpose: Read the working directory from the URL (ini) file
*/ HRESULT ReadWorkingDirectory( IN LPCTSTR pszFile, OUT LPWSTR * ppwsz) { HRESULT hres = E_OUTOFMEMORY; TCHAR szPath[MAX_PATH]; DWORD cch; ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); ASSERT(IS_VALID_WRITE_PTR(ppwsz, PWSTR)); *ppwsz = NULL; *ppwsz = (LPWSTR)LocalAlloc(LPTR, SIZEOF(WCHAR) * MAX_PATH); if (*ppwsz) { hres = S_FALSE; cch = SHGetIniString(c_szIntshcut, ISHCUT_INISTRING_WORKINGDIR, szPath, SIZECHARS(szPath), pszFile); if (0 != cch) { TCHAR szFullPath[MAX_PATH]; PTSTR pszFileName; if (0 < GetFullPathName(szPath, SIZECHARS(szFullPath), szFullPath, &pszFileName)) { SHTCharToUnicode(szFullPath, *ppwsz, MAX_PATH); hres = S_OK; } } if (S_OK != hres) { LocalFree(*ppwsz); *ppwsz = NULL; } } return hres; }
/*----------------------------------------------------------
Purpose: Write the working directory to the URL (ini) file.
*/ HRESULT WriteGenericString( IN LPCTSTR pszFile, IN LPCTSTR pszSectionName, IN LPCTSTR pszName, IN LPCWSTR pwsz) OPTIONAL { HRESULT hres = S_FALSE; ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); ASSERT(IS_VALID_STRING_PTR(pszName, -1)); ASSERT(! pwsz || IS_VALID_STRING_PTRW(pwsz, -1)); if (*pszFile) { if (AnyMeatW(pwsz)) { hres = (SHSetIniString(pszSectionName, pszName, pwsz, pszFile)) ? S_OK : E_FAIL; } else { hres = (SHDeleteIniString(pszSectionName, pszName, pszFile)) ? S_OK : E_FAIL; } } return hres; }
/*----------------------------------------------------------
Purpose: Read the show-command flag from the URL (ini) file
*/ HRESULT ReadShowCmd( IN LPCTSTR pszFile, OUT PINT pnShowCmd) { HRESULT hres = S_FALSE; TCHAR szT[MAX_BUF_INT]; DWORD cch; ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); ASSERT(IS_VALID_WRITE_PTR(pnShowCmd, INT)); *pnShowCmd = SW_NORMAL; cch = GetPrivateProfileString(c_szIntshcut, TEXT("ShowCommand"), c_szNULL, szT, SIZECHARS(szT), pszFile); if (0 != cch) { if (StrToIntEx(szT, 0, pnShowCmd)) { hres = S_OK; } } return hres; }
/*----------------------------------------------------------
Purpose: Write showcmd to URL (ini) file
*/ HRESULT WriteShowCmd( IN LPCTSTR pszFile, IN int nShowCmd) { HRESULT hres = S_FALSE; ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); if (*pszFile) { if (SW_NORMAL != nShowCmd) { hres = WriteSignedToFile(pszFile, c_szIntshcut, TEXT("ShowCommand"), nShowCmd); } else { hres = DeletePrivateProfileString(c_szIntshcut, TEXT("ShowCommand"), pszFile) ? S_OK : E_FAIL; } } return hres; }
/*----------------------------------------------------------
Purpose: Read the IDList from the URL (ini) file
*/ HRESULT ReadIDList( IN LPCTSTR pszFile, OUT LPITEMIDLIST *ppidl) { HRESULT hres = S_FALSE; ULONG cb;
ASSERT(ppidl);
// Delete the old one if any.
if (*ppidl) { ILFree(*ppidl); *ppidl = NULL; }
// Read the size of the IDLIST
cb = GetPrivateProfileInt(c_szIntshcut, TEXT("ILSize"), 0, pszFile); if (cb) { // Create a IDLIST
LPITEMIDLIST pidl = IEILCreate(cb); if (pidl) { // Read its contents
if (GetPrivateProfileStruct(c_szIntshcut, TEXT("IDList"), (LPVOID)pidl, cb, pszFile)) { *ppidl = pidl; hres = S_OK; } else { ILFree(pidl); hres = E_FAIL; } } else { hres = E_OUTOFMEMORY; } } return hres; }
HRESULT WriteStream( IN LPCTSTR pszFile, IN IStream *pStream, IN LPCTSTR pszStreamName, IN LPCTSTR pszSizeName) { HRESULT hr = E_FAIL; ULARGE_INTEGER li = {0}; if(pStream) IStream_Size(pStream, &li);
if (li.LowPart) { ASSERT(!li.HighPart); LPVOID pv = LocalAlloc(LPTR, li.LowPart);
if (pv && SUCCEEDED(hr = IStream_Read(pStream, pv, li.LowPart))) { // we have loaded the data properly, time to write it out
if (SUCCEEDED(hr = WriteUnsignedToFile(pszFile, c_szIntshcut, pszSizeName, li.LowPart))) hr = WriteBinaryToFile(pszFile, c_szIntshcut, pszStreamName, pv, li.LowPart); }
if (pv) { LocalFree(pv); pv = NULL; } } else { // delete the keys if
// 1. pStream is NULL, or
// 2. pStream in empty (cbPidl == 0).
if (DeletePrivateProfileString(c_szIntshcut, pszSizeName, pszFile) && DeletePrivateProfileString(c_szIntshcut, pszStreamName, pszFile)) { hr = S_OK; } }
return hr; }
/*----------------------------------------------------------
Purpose: Write IDList to URL (ini) file
*/ HRESULT WriteIDList( IN LPCTSTR pszFile, IN IStream *pStream) { return WriteStream(pszFile, pStream, TEXT("IDList"), TEXT("ILSize")); }
/********************************** Methods **********************************/
//==========================================================================================
// URLProp class implementation
//==========================================================================================
#ifdef DEBUG
/*----------------------------------------------------------
Purpose: Dump the properties in this object
*/ STDMETHODIMP_(void) URLProp::Dump(void) { if (IsFlagSet(g_dwDumpFlags, DF_URLPROP)) { PropStg_Dump(m_hstg, 0); } }
#endif
/*----------------------------------------------------------
Purpose: Constructor for URLProp
*/ URLProp::URLProp(void) : m_cRef(1) { // Don't validate this until after construction.
m_hstg = NULL; ASSERT(IS_VALID_STRUCT_PTR(this, CURLProp)); return; }
/*----------------------------------------------------------
Purpose: Destructor for URLProp
*/ URLProp::~URLProp(void) { ASSERT(IS_VALID_STRUCT_PTR(this, CURLProp)); if (m_hstg) { PropStg_Destroy(m_hstg); m_hstg = NULL; } ASSERT(IS_VALID_STRUCT_PTR(this, CURLProp)); return; }
STDMETHODIMP_(ULONG) URLProp::AddRef() { return ++m_cRef; }
STDMETHODIMP_(ULONG) URLProp::Release() { m_cRef--; if (m_cRef > 0) return m_cRef; delete this; return 0; }
/*----------------------------------------------------------
Purpose: IUnknown::QueryInterface method for URLProp
*/ STDMETHODIMP URLProp::QueryInterface(REFIID riid, void **ppvObj) { if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IPropertyStorage)) { *ppvObj = SAFECAST(this, IPropertyStorage *); } else { *ppvObj = NULL; return E_NOINTERFACE; } AddRef(); return NOERROR; }
/*----------------------------------------------------------
Purpose: Initialize the object
Returns: S_OK E_OUTOFMEMORY */ STDMETHODIMP URLProp::Init(void) { HRESULT hres = S_OK; // Don't stomp on ourselves if this has already been initialized
if (NULL == m_hstg) { hres = PropStg_Create(&m_hstg, PSTGF_DEFAULT); } return hres; }
/*----------------------------------------------------------
Purpose: Helper function that retrieves the string property
*/ STDMETHODIMP URLProp::GetProp( IN PROPID pid, IN LPTSTR pszBuf, IN int cchBuf) { HRESULT hres; PROPSPEC propspec; PROPVARIANT propvar; ASSERT(pszBuf); propspec.ulKind = PRSPEC_PROPID; propspec.propid = pid; *pszBuf = TEXT('\0'); hres = ReadMultiple(1, &propspec, &propvar); if (SUCCEEDED(hres)) { if (VT_LPWSTR == propvar.vt) { SHUnicodeToTChar(propvar.pwszVal, pszBuf, cchBuf); hres = S_OK; } else { if (VT_EMPTY != propvar.vt && VT_ILLEGAL != propvar.vt) TraceMsg(TF_WARNING, "URLProp::GetProp: expected propid %#lx to be VT_LPWSTR, but is %s", pid, Dbg_GetVTName(propvar.vt)); hres = S_FALSE; } PropVariantClear(&propvar); } return hres; }
/*----------------------------------------------------------
Purpose: Helper function that retrieves the word property
*/ STDMETHODIMP URLProp::GetProp( IN PROPID pid, IN int * piVal) { HRESULT hres; PROPSPEC propspec; PROPVARIANT propvar; ASSERT(piVal); propspec.ulKind = PRSPEC_PROPID; propspec.propid = pid; *piVal = 0; hres = ReadMultiple(1, &propspec, &propvar); if (SUCCEEDED(hres)) { if (VT_I4 == propvar.vt) { *piVal = propvar.lVal; hres = S_OK; } else { if (VT_EMPTY != propvar.vt && VT_ILLEGAL != propvar.vt) TraceMsg(TF_WARNING, "URLProp::GetProp: expected propid %#lx to be VT_I4, but is %s", pid, Dbg_GetVTName(propvar.vt)); hres = S_FALSE; } PropVariantClear(&propvar); } return hres; }
/*----------------------------------------------------------
Purpose: Helper function that retrieves the word property
*/ STDMETHODIMP URLProp::GetProp( IN PROPID pid, IN LPDWORD pdwVal) { HRESULT hres; PROPSPEC propspec; PROPVARIANT propvar; ASSERT(pdwVal); propspec.ulKind = PRSPEC_PROPID; propspec.propid = pid; *pdwVal = 0; hres = ReadMultiple(1, &propspec, &propvar); if (SUCCEEDED(hres)) { if (VT_UI4 == propvar.vt) { *pdwVal = propvar.ulVal; hres = S_OK; } else { if (VT_EMPTY != propvar.vt && VT_ILLEGAL != propvar.vt) TraceMsg(TF_WARNING, "URLProp::GetProp: expected propid %#lx to be VT_UI4, but is %s", pid, Dbg_GetVTName(propvar.vt)); hres = S_FALSE; } PropVariantClear(&propvar); } return hres; }
/*----------------------------------------------------------
Purpose: Helper function that retrieves the word property
*/ STDMETHODIMP URLProp::GetProp( IN PROPID pid, IN WORD * pwVal) { HRESULT hres; PROPSPEC propspec; PROPVARIANT propvar; ASSERT(pwVal); propspec.ulKind = PRSPEC_PROPID; propspec.propid = pid; *pwVal = 0; hres = ReadMultiple(1, &propspec, &propvar); if (SUCCEEDED(hres)) { if (VT_UI2 == propvar.vt) { *pwVal = propvar.uiVal; hres = S_OK; } else { if (VT_EMPTY != propvar.vt && VT_ILLEGAL != propvar.vt) TraceMsg(TF_WARNING, "URLProp::GetProp: expected propid %#lx to be VT_UI2, but is %s", pid, Dbg_GetVTName(propvar.vt)); hres = S_FALSE; } PropVariantClear(&propvar); } return hres; }
/*----------------------------------------------------------
Purpose: Helper function that retrieves the IStream property
*/ STDMETHODIMP URLProp::GetProp( IN PROPID pid, IN IStream **ppStream) { HRESULT hres; PROPSPEC propspec; PROPVARIANT propvar; ASSERT(ppStream); propspec.ulKind = PRSPEC_PROPID; propspec.propid = pid; *ppStream = 0; hres = ReadMultiple(1, &propspec, &propvar); if (SUCCEEDED(hres)) { if (VT_STREAM == propvar.vt) { *ppStream = propvar.pStream; hres = S_OK; } else { if (VT_EMPTY != propvar.vt && VT_ILLEGAL != propvar.vt && propvar.lVal != 0) TraceMsg(TF_WARNING, "URLProp::GetProp: expected propid %#lx to be VT_STREAM, but is %s", pid, Dbg_GetVTName(propvar.vt)); hres = S_FALSE; } // Do not PropVariantClear(&propvar), because it will call pStream->Release().
} return hres; }
/*----------------------------------------------------------
Purpose: Helper function that sets the string property
*/ STDMETHODIMP URLProp::SetProp( IN PROPID pid, IN LPCTSTR psz) OPTIONAL { HRESULT hres; PROPSPEC propspec; PROPVARIANT propvar;
// WARNING:: this function gets called as part of ShellExecute which can be
// called by 16 bit apps so don't put mondo strings on stack...
WCHAR *pwsz = NULL; propspec.ulKind = PRSPEC_PROPID; propspec.propid = pid; if (psz && *psz) { SHStrDup(psz, &pwsz); propvar.vt = VT_LPWSTR; propvar.pwszVal = pwsz; } else propvar.vt = VT_EMPTY; hres = WriteMultiple(1, &propspec, &propvar, 0);
if (pwsz) CoTaskMemFree(pwsz);
return hres; }
/*----------------------------------------------------------
Purpose: Helper function that sets the int property
*/ STDMETHODIMP URLProp::SetProp( IN PROPID pid, IN int iVal) { PROPSPEC propspec; PROPVARIANT propvar; propspec.ulKind = PRSPEC_PROPID; propspec.propid = pid; propvar.vt = VT_I4; propvar.lVal = iVal; return WriteMultiple(1, &propspec, &propvar, 0); }
/*----------------------------------------------------------
Purpose: Helper function that sets the dword property
*/ STDMETHODIMP URLProp::SetProp( IN PROPID pid, IN DWORD dwVal) { HRESULT hres; PROPSPEC propspec; PROPVARIANT propvar; propspec.ulKind = PRSPEC_PROPID; propspec.propid = pid; propvar.vt = VT_UI4; propvar.ulVal = dwVal; hres = WriteMultiple(1, &propspec, &propvar, 0); return hres; }
/*----------------------------------------------------------
Purpose: Helper function that sets the word property
*/ STDMETHODIMP URLProp::SetProp( IN PROPID pid, IN WORD wVal) { HRESULT hres; PROPSPEC propspec; PROPVARIANT propvar; propspec.ulKind = PRSPEC_PROPID; propspec.propid = pid; propvar.vt = VT_UI2; propvar.uiVal = wVal; hres = WriteMultiple(1, &propspec, &propvar, 0); return hres; }
/*----------------------------------------------------------
Purpose: Helper function that sets the IStream* property
*/ STDMETHODIMP URLProp::SetProp( IN PROPID pid, IN IStream *pStream) { HRESULT hres; PROPSPEC propspec; PROPVARIANT propvar; propspec.ulKind = PRSPEC_PROPID; propspec.propid = pid; propvar.vt = VT_STREAM; propvar.pStream = pStream; hres = WriteMultiple(1, &propspec, &propvar, 0); return hres; }
STDMETHODIMP URLProp::IsDirty(void) { return PropStg_IsDirty(m_hstg); }
STDMETHODIMP URLProp::ReadMultiple(IN ULONG cpspec, IN const PROPSPEC rgpropspec[], IN PROPVARIANT rgpropvar[]) { HRESULT hres = PropStg_ReadMultiple(m_hstg, cpspec, rgpropspec, rgpropvar); if (SUCCEEDED(hres)) { // Set the accessed time
SYSTEMTIME st; GetSystemTime(&st); SystemTimeToFileTime(&st, &m_ftAccessed); } return hres; }
STDMETHODIMP URLProp::WriteMultiple(IN ULONG cpspec, IN const PROPSPEC rgpropspec[], IN const PROPVARIANT rgpropvar[], IN PROPID propidFirst) { HRESULT hres = PropStg_WriteMultiple(m_hstg, cpspec, rgpropspec, rgpropvar, propidFirst); if (SUCCEEDED(hres)) { // Set the modified time
SYSTEMTIME st; GetSystemTime(&st); SystemTimeToFileTime(&st, &m_ftModified); } return hres; }
STDMETHODIMP URLProp::DeleteMultiple(ULONG cpspec, const PROPSPEC rgpropspec[]) { return PropStg_DeleteMultiple(m_hstg, cpspec, rgpropspec); }
STDMETHODIMP URLProp::ReadPropertyNames(ULONG cpropid, const PROPID rgpropid[], LPWSTR rgpwszName[]) { return E_NOTIMPL; }
STDMETHODIMP URLProp::WritePropertyNames(ULONG cpropid, const PROPID rgpropid[], const LPWSTR rgpwszName[]) { return E_NOTIMPL; }
/*----------------------------------------------------------
Purpose: IPropertyStorage::DeletePropertyNames method for URLProp
*/ STDMETHODIMP URLProp::DeletePropertyNames( IN ULONG cpropid, IN const PROPID rgpropid[]) { return E_NOTIMPL; }
/*----------------------------------------------------------
Purpose: IPropertyStorage::SetClass method for URLProp
*/ STDMETHODIMP URLProp::SetClass( IN REFCLSID rclsid) { CopyMemory(&m_clsid, &rclsid, SIZEOF(m_clsid)); return S_OK; }
/*----------------------------------------------------------
Purpose: IPropertyStorage::Commit method for URLProp
*/ STDMETHODIMP URLProp::Commit( IN DWORD dwFlags) { return E_NOTIMPL; }
/*----------------------------------------------------------
Purpose: IPropertyStorage::Revert method for URLProp
*/ STDMETHODIMP URLProp::Revert(void) { #ifdef DEBUG
Dump(); #endif
return E_NOTIMPL; }
/*----------------------------------------------------------
Purpose: IPropertyStorage::Enum method for URLProp
*/ STDMETHODIMP URLProp::Enum(IEnumSTATPROPSTG ** ppenum) { *ppenum = NULL; return E_NOTIMPL; }
/*----------------------------------------------------------
Purpose: IPropertyStorage::Stat method for URLProp
*/ STDMETHODIMP URLProp::Stat( IN STATPROPSETSTG * pstat) { HRESULT hres = STG_E_INVALIDPARAMETER;
if (IS_VALID_WRITE_PTR(pstat, STATPROPSETSTG)) { pstat->fmtid = m_fmtid; pstat->clsid = m_clsid; pstat->grfFlags = m_grfFlags; pstat->mtime = m_ftModified; pstat->ctime = m_ftCreated; pstat->atime = m_ftAccessed;
hres = S_OK; } return hres; }
/*----------------------------------------------------------
Purpose: IPropertyStorage::SetTimes method for URLProp
*/ STDMETHODIMP URLProp::SetTimes( IN const FILETIME * pftModified, OPTIONAL IN const FILETIME * pftCreated, OPTIONAL IN const FILETIME * pftAccessed) OPTIONAL { HRESULT hres; if (pftModified && !IS_VALID_READ_PTR(pftModified, FILETIME) || pftCreated && !IS_VALID_READ_PTR(pftCreated, FILETIME) || pftAccessed && !IS_VALID_READ_PTR(pftAccessed, FILETIME)) { hres = STG_E_INVALIDPARAMETER; } else { if (pftModified) m_ftModified = *pftModified; if (pftCreated) m_ftCreated = *pftCreated; if (pftAccessed) m_ftAccessed = *pftAccessed; hres = S_OK; } return hres; }
#ifdef DEBUG
STDMETHODIMP_(void) IntshcutProp::Dump(void) { if (IsFlagSet(g_dwDumpFlags, DF_URLPROP)) { TraceMsg(TF_ALWAYS, " IntshcutProp obj: %s", m_szFile); URLProp::Dump(); } }
#endif
IntshcutProp::IntshcutProp(void) { // Don't validate this until after construction.
*m_szFile = 0; ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcutProp)); }
IntshcutProp::~IntshcutProp(void) { ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcutProp));
ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcutProp)); }
// (These are not related to PID_IS_*)
#define IPROP_ICONINDEX 0
#define IPROP_ICONFILE 1
#define IPROP_HOTKEY 2
#define IPROP_WORKINGDIR 3
#define IPROP_SHOWCMD 4
#define IPROP_WHATSNEW 5
#define IPROP_AUTHOR 6
#define IPROP_DESC 7
#define IPROP_COMMENT 8
#define IPROP_URL 9 // these two must be the last
#define IPROP_SCHEME 10 // in this list. See LoadFromFile.
#define CPROP_INTSHCUT 11 // Count of properties
// (we don't write the URL or the scheme in the massive write sweep)
#define CPROP_INTSHCUT_WRITE (CPROP_INTSHCUT - 2)
/*----------------------------------------------------------
Purpose: Load the basic property info like URL.
Returns: Cond: -- */ STDMETHODIMP IntshcutProp::LoadFromFile(LPCTSTR pszFile) { HRESULT hres; LPWSTR pwszBuf; LPTSTR pszBuf; CHAR *pszTempBuf; static const PROPSPEC rgpropspec[CPROP_INTSHCUT] = { // This must be initialized in the same order as how the
// IPROP_* values were defined.
{ PRSPEC_PROPID, PID_IS_ICONINDEX }, { PRSPEC_PROPID, PID_IS_ICONFILE }, { PRSPEC_PROPID, PID_IS_HOTKEY }, { PRSPEC_PROPID, PID_IS_WORKINGDIR }, { PRSPEC_PROPID, PID_IS_SHOWCMD }, { PRSPEC_PROPID, PID_IS_WHATSNEW }, { PRSPEC_PROPID, PID_IS_AUTHOR }, { PRSPEC_PROPID, PID_IS_DESCRIPTION }, { PRSPEC_PROPID, PID_IS_COMMENT }, { PRSPEC_PROPID, PID_IS_URL }, { PRSPEC_PROPID, PID_IS_SCHEME }, }; PROPVARIANT rgpropvar[CPROP_INTSHCUT] = { 0 }; ASSERT(pszFile);
// try to allocate a temporary buffer, don't put on stack as this may be called
// by 16 bit apps through the shellexecute thunk
pszTempBuf = (CHAR*)LocalAlloc(LMEM_FIXED, INTERNET_MAX_URL_LENGTH * sizeof(CHAR)); if (!pszTempBuf) return E_OUTOFMEMORY;
if (!g_fRunningOnNT) { // Flush the cache first to encourage Win95 kernel to zero-out
// its buffer. Kernel GP-faults with hundreds of writes made to
// ini files.
WritePrivateProfileString(NULL, NULL, NULL, pszFile); } // Get the URL
hres = ReadURLFromFile(pszFile, c_szIntshcut, &pszBuf); if (S_OK == hres) { // Call this method because it does more work before
// setting the property
SetURLProp(pszBuf, (IURL_SETURL_FL_GUESS_PROTOCOL | IURL_SETURL_FL_USE_DEFAULT_PROTOCOL)); LocalFree(pszBuf); pszBuf = NULL; } // Get the IDList
LPITEMIDLIST pidl = NULL; hres = ReadIDList(pszFile, &pidl); if (S_OK == hres) { // Call this method because it does more work before
// setting the property
SetIDListProp(pidl); ILFree(pidl); }
#ifndef UNIX
// Get icon location
int nVal; hres = ReadIconLocation(pszFile, &pwszBuf, &nVal, pszTempBuf); if (S_OK == hres) { rgpropvar[IPROP_ICONFILE].vt = VT_LPWSTR; rgpropvar[IPROP_ICONFILE].pwszVal = pwszBuf; rgpropvar[IPROP_ICONINDEX].vt = VT_I4; rgpropvar[IPROP_ICONINDEX].lVal = nVal; } // Get the hotkey
WORD wHotkey; hres = ReadHotkey(pszFile, &wHotkey); if (S_OK == hres) { rgpropvar[IPROP_HOTKEY].vt = VT_UI2; rgpropvar[IPROP_HOTKEY].uiVal = wHotkey; } // Get the working directory
hres = ReadWorkingDirectory(pszFile, &pwszBuf); if (S_OK == hres) { rgpropvar[IPROP_WORKINGDIR].vt = VT_LPWSTR; rgpropvar[IPROP_WORKINGDIR].pwszVal = pwszBuf; } // Get the showcmd flag
hres = ReadShowCmd(pszFile, &nVal); rgpropvar[IPROP_SHOWCMD].vt = VT_I4; if (S_OK == hres) rgpropvar[IPROP_SHOWCMD].lVal = nVal; else rgpropvar[IPROP_SHOWCMD].lVal = SW_NORMAL; // Get the What's New bulletin
hres = ReadStringFromFile(pszFile, c_szIntshcut, ISHCUT_INISTRING_WHATSNEW, &pwszBuf, pszTempBuf); if (S_OK == hres) { rgpropvar[IPROP_WHATSNEW].vt = VT_LPWSTR; rgpropvar[IPROP_WHATSNEW].pwszVal = pwszBuf; } // Get the Author
hres = ReadStringFromFile(pszFile, c_szIntshcut, ISHCUT_INISTRING_AUTHOR, &pwszBuf, pszTempBuf); if (S_OK == hres) { rgpropvar[IPROP_AUTHOR].vt = VT_LPWSTR; rgpropvar[IPROP_AUTHOR].pwszVal = pwszBuf; } // Get the Description
hres = ReadStringFromFile(pszFile, c_szIntshcut, ISHCUT_INISTRING_DESC, &pwszBuf, pszTempBuf); if (S_OK == hres) { rgpropvar[IPROP_DESC].vt = VT_LPWSTR; rgpropvar[IPROP_DESC].pwszVal = pwszBuf; } // Get the Comment
hres = ReadStringFromFile(pszFile, c_szIntshcut, ISHCUT_INISTRING_COMMENT, &pwszBuf, pszTempBuf); if (S_OK == hres) { rgpropvar[IPROP_COMMENT].vt = VT_LPWSTR; rgpropvar[IPROP_COMMENT].pwszVal = pwszBuf; }
#endif /* !UNIX */
// Write it all out to our in-memory storage. Note we're using
// CPROP_INTSHCUT_WRITE, which should be the size of the array minus the
// url and scheme propids, since they were written separately
// above.
hres = WriteMultiple(CPROP_INTSHCUT_WRITE, (PROPSPEC *)rgpropspec, rgpropvar, 0); if (SUCCEEDED(hres)) { // Unmark *all* these properties, since we're initializing from
// the file
PropStg_DirtyMultiple(m_hstg, ARRAYSIZE(rgpropspec), rgpropspec, FALSE); } // Get the times. We don't support the Accessed time for internet
// shortcuts updating this field would cause the shortcut to be
// constantly written to disk to record the Accessed time simply
// when a property is read. A huge perf hit!
ZeroMemory(&m_ftAccessed, sizeof(m_ftAccessed)); DWORD cbData = SIZEOF(m_ftModified); ReadBinaryFromFile(pszFile, c_szIntshcut, ISHCUT_INISTRING_MODIFIED, &m_ftModified, cbData); // Free up the buffers that we allocated
int cprops; PROPVARIANT * ppropvar; for (cprops = ARRAYSIZE(rgpropvar), ppropvar = rgpropvar; 0 < cprops; cprops--) { if (VT_LPWSTR == ppropvar->vt) { ASSERT(ppropvar->pwszVal); LocalFree(ppropvar->pwszVal); ppropvar->pwszVal = NULL; } ppropvar++; }
LocalFree((HLOCAL)pszTempBuf); pszTempBuf = NULL; return hres; }
STDMETHODIMP IntshcutProp::Init(void) { return URLProp::Init(); }
STDMETHODIMP IntshcutProp::InitFromFile(LPCTSTR pszFile) { // Initialize the in-memory property storage from the file
// and database
HRESULT hres = Init(); if (SUCCEEDED(hres) && pszFile) { StrCpyN(m_szFile, pszFile, SIZECHARS(m_szFile)); hres = LoadFromFile(m_szFile); } else m_szFile[0] = 0; return hres; }
typedef struct { LPTSTR pszFile; } COMMITISDATA;
/*----------------------------------------------------------
Purpose: Commit the values for any known properties to the file
Note this callback is called only for dirty values.
Returns: S_OK if alright S_FALSE to skip this value error to stop */ STDAPI CommitISProp( IN PROPID propid, IN PROPVARIANT * ppropvar, IN LPARAM lParam) { HRESULT hres = S_OK; COMMITISDATA * pcd = (COMMITISDATA *)lParam; ASSERT(ppropvar); ASSERT(pcd); LPWSTR pwsz; USHORT uiVal; LONG lVal; IStream *pStream; switch (propid) { case PID_IS_URL: case PID_IS_ICONFILE: case PID_IS_WORKINGDIR: case PID_IS_WHATSNEW: case PID_IS_AUTHOR: case PID_IS_DESCRIPTION: case PID_IS_COMMENT: if (VT_LPWSTR == ppropvar->vt) pwsz = ppropvar->pwszVal; else pwsz = NULL; switch (propid) { case PID_IS_URL: hres = WriteGenericString(pcd->pszFile, c_szIntshcut, ISHCUT_INISTRING_URL, pwsz); break; case PID_IS_ICONFILE: hres = WriteIconFile(pcd->pszFile, pwsz); break; case PID_IS_WORKINGDIR: hres = WriteGenericString(pcd->pszFile, c_szIntshcut, ISHCUT_INISTRING_WORKINGDIR, pwsz); break; case PID_IS_WHATSNEW: hres = WriteGenericString(pcd->pszFile, c_szIntshcut, ISHCUT_INISTRING_WHATSNEW, pwsz); break; case PID_IS_AUTHOR: hres = WriteGenericString(pcd->pszFile, c_szIntshcut, ISHCUT_INISTRING_AUTHOR, pwsz); break; case PID_IS_DESCRIPTION: hres = WriteGenericString(pcd->pszFile, c_szIntshcut, ISHCUT_INISTRING_DESC, pwsz); break; case PID_IS_COMMENT: hres = WriteGenericString(pcd->pszFile, c_szIntshcut, ISHCUT_INISTRING_COMMENT, pwsz); break; default: ASSERT(0); // should never get here
break; } break; case PID_IS_ICONINDEX: if (VT_I4 == ppropvar->vt) hres = WriteIconIndex(pcd->pszFile, ppropvar->lVal); break; case PID_IS_HOTKEY: if (VT_UI2 == ppropvar->vt) uiVal = ppropvar->uiVal; else uiVal = 0; hres = WriteHotkey(pcd->pszFile, uiVal); break; case PID_IS_SHOWCMD: if (VT_I4 == ppropvar->vt) lVal = ppropvar->lVal; else lVal = SW_NORMAL; hres = WriteShowCmd(pcd->pszFile, lVal); break; case PID_IS_SCHEME: // Don't write this one out
break; case PID_IS_IDLIST: if (VT_STREAM == ppropvar->vt) pStream = ppropvar->pStream; else pStream = NULL; hres = WriteIDList(pcd->pszFile, pStream); break; default: TraceMsg(TF_WARNING, "Don't know how to commit url property (%#lx)", propid); ASSERT(0); break; } #ifdef DEBUG
if (FAILED(hres)) TraceMsg(TF_WARNING, "Failed to save url property (%#lx) to file %s", propid, pcd->pszFile); #endif
return hres; }
/*----------------------------------------------------------
Purpose: IPropertyStorage::Commit method for URLProp
*/ STDMETHODIMP IntshcutProp::Commit( IN DWORD dwFlags) { HRESULT hres; COMMITISDATA cd; TraceMsg(TF_INTSHCUT, "Writing properties to \"%s\"", m_szFile);
cd.pszFile = m_szFile; // Enumerate thru the dirty property values that get saved to the
// file
hres = PropStg_Enum(m_hstg, PSTGEF_DIRTY, CommitISProp, (LPARAM)&cd); if (SUCCEEDED(hres)) { // Now mark everything clean
PropStg_DirtyAll(m_hstg, FALSE);
// Save the times. Don't write out the Accessed time for perf.
// See LoadFromFile.
EVAL(SUCCEEDED(WriteBinaryToFile(m_szFile, c_szIntshcut, ISHCUT_INISTRING_MODIFIED, &m_ftModified, SIZEOF(m_ftModified)))); } #ifdef DEBUG
Dump(); #endif
return hres; }
/*----------------------------------------------------------
Purpose: Helper function to set the file name.
*/ STDMETHODIMP IntshcutProp::SetFileName( IN LPCTSTR pszFile) { if(pszFile) { ASSERT(IS_VALID_STRING_PTR(pszFile, -1)); StrCpyN(m_szFile, pszFile, SIZECHARS(m_szFile)); } else { *m_szFile = TEXT('\0');; }
return S_OK; }
/*----------------------------------------------------------
Purpose: Helper function that sets the URL.
*/ STDMETHODIMP IntshcutProp::SetIDListProp( LPCITEMIDLIST pcidl) { HRESULT hres; IStream *pstmPidl; if (pcidl) { // ???
// PERF: This loads OLE. Is this OK?
hres = CreateStreamOnHGlobal(NULL, TRUE, &pstmPidl); if (SUCCEEDED(hres)) { hres = ILSaveToStream(pstmPidl, pcidl); if (SUCCEEDED(hres)) hres = SetProp(PID_IS_IDLIST, pstmPidl);
pstmPidl->Release(); } } else { hres = SetProp(PID_IS_IDLIST, NULL); } return hres; }
/*----------------------------------------------------------
Purpose: Helper function that sets the URL. This function optionally canonicalizes the string as well.
*/ STDMETHODIMP IntshcutProp::SetURLProp( IN LPCTSTR pszURL, OPTIONAL IN DWORD dwFlags) { HRESULT hres;
// Warning this function can be called as part of shellexecute which can be
// thunked up to by a 16 bit app, so be carefull what you put on stack...
BOOL bChanged;
struct tbufs { TCHAR szUrl[INTERNET_MAX_URL_LENGTH]; TCHAR szUrlT[INTERNET_MAX_URL_LENGTH]; };
struct tbufs *ptbufs;
ptbufs = (struct tbufs *)LocalAlloc(LMEM_FIXED, sizeof(struct tbufs)); if (!ptbufs) return E_OUTOFMEMORY; hres = GetProp(PID_IS_URL, ptbufs->szUrl, INTERNET_MAX_URL_LENGTH); bChanged = !(( !pszURL && S_OK != hres) || (pszURL && S_OK == hres && 0 == StrCmp(pszURL, ptbufs->szUrl))); hres = S_OK; if (bChanged) { if (NULL == pszURL) { hres = SetProp(PID_IS_URL, pszURL); if (S_OK == hres) hres = SetProp(PID_IS_SCHEME, URL_SCHEME_UNKNOWN); } else { DWORD dwFlagsT = UQF_CANONICALIZE; // Translate the URL
if (IsFlagSet(dwFlags, IURL_SETURL_FL_GUESS_PROTOCOL)) SetFlag(dwFlagsT, UQF_GUESS_PROTOCOL); if (IsFlagSet(dwFlags, IURL_SETURL_FL_USE_DEFAULT_PROTOCOL)) SetFlag(dwFlagsT, UQF_USE_DEFAULT_PROTOCOL); // Translate the URL
hres = IURLQualify(pszURL, dwFlagsT, ptbufs->szUrlT, NULL, NULL); if (SUCCEEDED(hres)) { // Is the URL different after being translated?
bChanged = (0 != StrCmp(ptbufs->szUrlT, ptbufs->szUrl)); hres = S_OK; if (bChanged) { // Yes; validate and get the scheme
PARSEDURL pu; pu.cbSize = SIZEOF(pu); hres = ParseURL(ptbufs->szUrlT, &pu); if (S_OK == hres) hres = SetProp(PID_IS_URL, ptbufs->szUrlT); if (S_OK == hres) hres = SetProp(PID_IS_SCHEME, (DWORD)pu.nScheme); } } } }
LocalFree((HLOCAL)ptbufs); ptbufs = NULL; return hres; }
/*----------------------------------------------------------
Purpose: Helper function that sets the string property
*/ STDMETHODIMP IntshcutProp::SetProp( IN PROPID pid, IN LPCTSTR psz) OPTIONAL { HRESULT hr;
// WARNING:: this function gets called as part of ShellExecute which can be
// called by 16 bit apps so don't put mondo strings on stack...
LPCWSTR pszUrl = psz; LPWSTR pszTemp = NULL;
// For URLs, we need to check for security spoofs
if (PID_IS_URL == pid && psz && IsSpecialUrl((LPWSTR)psz)) //FEATURE: remove cast
{ SHStrDup(psz, &pszTemp);
if (NULL != pszTemp) { // Unescape the url and look for a security context delimitor
hr = WrapSpecialUrlFlat(pszTemp, lstrlen(pszTemp)+1); if (E_ACCESSDENIED == hr) { // Security delimitor found, so wack it off
SHRemoveURLTurd(pszTemp); pszUrl = pszTemp; } } else { return E_OUTOFMEMORY; } }
hr = super::SetProp(pid, pszUrl);
if (pszTemp) { CoTaskMemFree(pszTemp); } return hr; }
STDAPI CIntshcutProp_CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppvOut) { HRESULT hres; *ppvOut = NULL; if (punkOuter) { // No
hres = CLASS_E_NOAGGREGATION; } else { IUnknown * piunk = (IUnknown *)(IPropertyStorage *)new IntshcutProp; if ( !piunk ) { hres = E_OUTOFMEMORY; } else { hres = piunk->QueryInterface(riid, ppvOut); piunk->Release(); } } return hres; // S_OK or E_NOINTERFACE
}
|