846 lines
22 KiB
C++
846 lines
22 KiB
C++
|
/*
|
||
|
* ispersis.cpp - IPersist, IPersistFile, and IPersistStream implementations for
|
||
|
* URL class.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include "priv.h"
|
||
|
#include "ishcut.h"
|
||
|
|
||
|
#include "resource.h"
|
||
|
|
||
|
// Need to flush the file to prevent win95 from barfing after stuff is written in
|
||
|
VOID FlushFile(LPCTSTR pszFile)
|
||
|
{
|
||
|
if (!g_fRunningOnNT)
|
||
|
{
|
||
|
WritePrivateProfileString(NULL, NULL, NULL, pszFile);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// save object to file
|
||
|
|
||
|
STDMETHODIMP Intshcut::SaveToFile(LPCTSTR pszFile, BOOL bRemember)
|
||
|
{
|
||
|
HRESULT hres = InitProp();
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
m_pprop->SetFileName(pszFile);
|
||
|
|
||
|
hres = m_pprop->Commit(STGC_DEFAULT);
|
||
|
|
||
|
// Remember file if requested
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
if (bRemember)
|
||
|
{
|
||
|
Dirty(FALSE);
|
||
|
|
||
|
if ( !Str_SetPtr(&m_pszFile, pszFile) )
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
Dump();
|
||
|
#endif
|
||
|
}
|
||
|
SHChangeNotify(SHCNE_UPDATEITEM, (SHCNF_PATH | SHCNF_FLUSH), pszFile, NULL);
|
||
|
}
|
||
|
|
||
|
if (!bRemember)
|
||
|
m_pprop->SetFileName(m_pszFile);
|
||
|
}
|
||
|
|
||
|
if(pszFile && (S_OK == hres))
|
||
|
FlushFile(pszFile);
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP Intshcut::LoadFromFile(LPCTSTR pszFile)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
|
||
|
if (Str_SetPtr(&m_pszFile, pszFile))
|
||
|
{
|
||
|
hres = InitProp();
|
||
|
#ifdef DEBUG
|
||
|
Dump();
|
||
|
#endif
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP Intshcut::LoadFromAsyncFileNow()
|
||
|
{
|
||
|
HRESULT hres = S_OK;
|
||
|
if (m_pszFileToLoad)
|
||
|
{
|
||
|
hres = LoadFromFile(m_pszFileToLoad);
|
||
|
Str_SetPtr(&m_pszFileToLoad, NULL);
|
||
|
}
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP Intshcut::GetCurFile(LPTSTR pszFile, UINT cchLen)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
if (m_pszFile)
|
||
|
{
|
||
|
StrCpyN(pszFile, m_pszFile, cchLen);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
hr = S_FALSE;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP Intshcut::Dirty(BOOL bDirty)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
|
||
|
|
||
|
if (bDirty)
|
||
|
{
|
||
|
if (IsFlagClear(m_dwFlags, ISF_DIRTY))
|
||
|
TraceMsg(TF_INTSHCUT, "Intshcut now dirty.");
|
||
|
|
||
|
SetFlag(m_dwFlags, ISF_DIRTY);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (IsFlagSet(m_dwFlags, ISF_DIRTY))
|
||
|
TraceMsg(TF_INTSHCUT, "Intshcut now clean.");
|
||
|
|
||
|
ClearFlag(m_dwFlags, ISF_DIRTY);
|
||
|
}
|
||
|
|
||
|
hres = S_OK;
|
||
|
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
// IPersist::GetClassID method for Intshcut
|
||
|
|
||
|
STDMETHODIMP Intshcut::GetClassID(CLSID *pclsid)
|
||
|
{
|
||
|
ASSERT(IS_VALID_WRITE_PTR(pclsid, CLSID));
|
||
|
|
||
|
*pclsid = CLSID_InternetShortcut;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
// IPersistFile::IsDirty handler for Intshcut
|
||
|
|
||
|
STDMETHODIMP Intshcut::IsDirty(void)
|
||
|
{
|
||
|
HRESULT hres = LoadFromAsyncFileNow();
|
||
|
|
||
|
if(SUCCEEDED(hres))
|
||
|
{
|
||
|
hres = InitProp();
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
if (IsFlagSet(m_dwFlags, ISF_DIRTY) || S_OK == m_pprop->IsDirty())
|
||
|
hres = S_OK;
|
||
|
else
|
||
|
hres = S_FALSE;
|
||
|
}
|
||
|
}
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
// Helper function to save off Trident specific stuff
|
||
|
|
||
|
STDMETHODIMP Intshcut::_SaveOffPersistentDataFromSite()
|
||
|
{
|
||
|
IOleCommandTarget *pcmdt = NULL;
|
||
|
HRESULT hr = S_OK;
|
||
|
if (_punkSite)
|
||
|
{
|
||
|
if(S_OK == _CreateTemporaryBackingFile())
|
||
|
{
|
||
|
ASSERT(m_pszTempFileName);
|
||
|
hr = _punkSite->QueryInterface(IID_IOleCommandTarget, (LPVOID *)&pcmdt);
|
||
|
if((S_OK == hr))
|
||
|
{
|
||
|
ASSERT(pcmdt);
|
||
|
VARIANT varIn = {0};
|
||
|
varIn.vt = VT_UNKNOWN;
|
||
|
varIn.punkVal = (LPUNKNOWN)(SAFECAST(this, IUniformResourceLocator *));
|
||
|
|
||
|
// Tell the site to save off it's persistent stuff
|
||
|
hr = pcmdt->Exec(&CGID_ShortCut, CMDID_INTSHORTCUTCREATE, 0, &varIn, NULL);
|
||
|
|
||
|
pcmdt->Release();
|
||
|
}
|
||
|
FlushFile(m_pszTempFileName);
|
||
|
}
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// IPersistFile::Save handler for Intshcut
|
||
|
|
||
|
STDMETHODIMP Intshcut::Save(LPCOLESTR pwszFile, BOOL bRemember)
|
||
|
{
|
||
|
HRESULT hres = LoadFromAsyncFileNow();
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
TCHAR szFile[MAX_PATH];
|
||
|
|
||
|
if (pwszFile)
|
||
|
SHUnicodeToTChar(pwszFile, szFile, SIZECHARS(szFile));
|
||
|
else if (m_pszFile)
|
||
|
StrCpyN(szFile, m_pszFile, ARRAYSIZE(szFile));
|
||
|
else
|
||
|
return E_FAIL;
|
||
|
|
||
|
// Perhaps there is a site which wants to save off stuff ?
|
||
|
// However, the site may end up calling via intefaces
|
||
|
hres = _SaveOffPersistentDataFromSite();
|
||
|
|
||
|
if ((S_OK == hres) && (m_pszTempFileName) && (StrCmp(m_pszTempFileName, szFile) != 0))
|
||
|
{
|
||
|
// Copy contents of the temp file to the destination
|
||
|
// if they are different files
|
||
|
EVAL(CopyFile(m_pszTempFileName, szFile, FALSE));
|
||
|
}
|
||
|
|
||
|
// Then save off in memory stuff to this file
|
||
|
hres = SaveToFile(szFile, bRemember);
|
||
|
}
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP Intshcut::SaveCompleted(LPCOLESTR pwszFile)
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// IPersistFile::Load()
|
||
|
|
||
|
STDMETHODIMP Intshcut::Load(LPCOLESTR pwszFile, DWORD dwMode)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
|
||
|
if (m_pszFile || m_pszFileToLoad)
|
||
|
{
|
||
|
hres = E_FAIL; // can't ::Load twice
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (m_fMustLoadSync)
|
||
|
hres = LoadFromFile(pwszFile);
|
||
|
else
|
||
|
{
|
||
|
if (Str_SetPtr(&m_pszFileToLoad, pwszFile))
|
||
|
hres = S_OK;
|
||
|
else
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
// IPersistFile::GetCurFile method for Intshcut
|
||
|
|
||
|
STDMETHODIMP Intshcut::GetCurFile(WCHAR **ppwszFile)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
TCHAR szTempFile[MAX_PATH];
|
||
|
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
|
||
|
ASSERT(IS_VALID_WRITE_PTR(ppwszFile, LPOLESTR));
|
||
|
|
||
|
hr = LoadFromAsyncFileNow();
|
||
|
if (FAILED(hr))
|
||
|
return hr;
|
||
|
|
||
|
if (m_pszFile)
|
||
|
{
|
||
|
StrCpyN(szTempFile, m_pszFile, SIZECHARS(szTempFile));
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
StrCpyN(szTempFile, TEXT("*.url"), ARRAYSIZE(szTempFile));
|
||
|
hr = S_FALSE;
|
||
|
}
|
||
|
|
||
|
HRESULT hrTemp = SHStrDup(szTempFile, ppwszFile);
|
||
|
if (FAILED(hrTemp))
|
||
|
hr = hrTemp;
|
||
|
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
|
||
|
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
// IPersistStream::Load method for Intshcut
|
||
|
|
||
|
STDMETHODIMP Intshcut::Load(IStream *pstm)
|
||
|
{
|
||
|
// to implement this:
|
||
|
// save stream to temp.ini
|
||
|
// IPersistFile::Load() from that
|
||
|
// delete temp file
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
// IPersistStream::Save method for Intshcut
|
||
|
STDMETHODIMP Intshcut::Save(IStream *pstm, BOOL bClearDirty)
|
||
|
{
|
||
|
HRESULT hr = InitProp();
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
TCHAR szURL[INTERNET_MAX_URL_LENGTH];
|
||
|
hr = m_pprop->GetProp(PID_IS_URL, szURL, SIZECHARS(szURL));
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
LPSTR pszContents;
|
||
|
hr = CreateURLFileContents(szURL, &pszContents);
|
||
|
if (SUCCEEDED(hr)) {
|
||
|
ASSERT(hr == lstrlenA(pszContents));
|
||
|
hr = pstm->Write(pszContents, hr + 1, NULL);
|
||
|
GlobalFree(pszContents);
|
||
|
pszContents = NULL;
|
||
|
} else {
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// IPersistStream::GetSizeMax method for Intshcut
|
||
|
|
||
|
STDMETHODIMP Intshcut::GetSizeMax(PULARGE_INTEGER puliSize)
|
||
|
{
|
||
|
puliSize->LowPart = 0;
|
||
|
puliSize->HighPart = 0;
|
||
|
|
||
|
HRESULT hr = InitProp();
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
puliSize->LowPart = GetFileContentsAndSize(NULL);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP Intshcut::_SetTempFileName(TCHAR *pszTempFileName)
|
||
|
{
|
||
|
ASSERT(NULL == m_pszTempFileName);
|
||
|
if (m_pszTempFileName)
|
||
|
DeleteFile(m_pszTempFileName);
|
||
|
|
||
|
Str_SetPtr(&m_pszTempFileName, pszTempFileName);
|
||
|
return (m_pszTempFileName ? S_OK : E_OUTOFMEMORY);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP Intshcut::_CreateTemporaryBackingFile()
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
if (m_pszTempFileName)
|
||
|
return S_OK;
|
||
|
|
||
|
TCHAR szTempFileName[MAX_PATH];
|
||
|
TCHAR szDirectory[MAX_PATH];
|
||
|
|
||
|
DWORD dwRet = GetTempPath(ARRAYSIZE(szDirectory), szDirectory);
|
||
|
|
||
|
if ((FALSE == dwRet) || (FALSE == PathFileExists(szDirectory)))
|
||
|
{
|
||
|
szDirectory[0] = TEXT('\\');
|
||
|
szDirectory[1] = TEXT('\0');
|
||
|
dwRet = TRUE;
|
||
|
}
|
||
|
|
||
|
dwRet = GetTempFileName(szDirectory, TEXT("www"), 0, szTempFileName);
|
||
|
if (dwRet)
|
||
|
{
|
||
|
hres = _SetTempFileName(szTempFileName);
|
||
|
// Now copy over the current file from which this was loaded and then save off
|
||
|
// any changes
|
||
|
if (S_OK == hres)
|
||
|
{
|
||
|
if (m_pszFile)
|
||
|
{
|
||
|
EVAL(CopyFile(m_pszFile, m_pszTempFileName, FALSE));
|
||
|
SaveToFile(m_pszTempFileName, FALSE); // this flushes the file
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
// Calculate the size of the contents to be transferred in a block.
|
||
|
STDMETHODIMP_(DWORD) Intshcut::GetFileContentsAndSize(LPSTR *ppszBuf)
|
||
|
{
|
||
|
DWORD cbSize = 0; // this is in bytes, not characters
|
||
|
TCHAR szURL[INTERNET_MAX_URL_LENGTH];
|
||
|
BOOL fSuccess = FALSE;
|
||
|
HRESULT hres;
|
||
|
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
|
||
|
ASSERT(m_pprop);
|
||
|
|
||
|
if (ppszBuf)
|
||
|
*ppszBuf = NULL;
|
||
|
|
||
|
// Create a temporary backing File here and save off everything that needs to be
|
||
|
// saved off there and use that to satisfy this request
|
||
|
if (S_OK == _CreateTemporaryBackingFile())
|
||
|
{
|
||
|
ASSERT(m_pszTempFileName);
|
||
|
|
||
|
WCHAR wszTemp[MAX_PATH];
|
||
|
SHTCharToUnicode(m_pszTempFileName, wszTemp, ARRAYSIZE(wszTemp));
|
||
|
|
||
|
hres = Save(wszTemp, FALSE); // So our temp file is now up to date
|
||
|
|
||
|
// Just copy the file
|
||
|
HANDLE hFile = CreateFile(m_pszTempFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||
|
if (hFile != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
DWORD dwTemp = 0;
|
||
|
cbSize = GetFileSize(hFile, &dwTemp);
|
||
|
if (ppszBuf)
|
||
|
{
|
||
|
if (0xFFFFFFFF != cbSize)
|
||
|
{
|
||
|
ASSERT(0 == dwTemp);
|
||
|
*ppszBuf = (LPSTR)LocalAlloc(LPTR, cbSize);
|
||
|
if (*ppszBuf)
|
||
|
{
|
||
|
dwTemp = 0;
|
||
|
if(ReadFile(hFile, *ppszBuf, cbSize, &dwTemp, NULL))
|
||
|
{
|
||
|
ASSERT(cbSize >= dwTemp);
|
||
|
fSuccess = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fSuccess = TRUE; // Just want the size - not contents
|
||
|
}
|
||
|
CloseHandle(hFile);
|
||
|
}
|
||
|
|
||
|
if (FALSE == fSuccess)
|
||
|
{
|
||
|
cbSize = 0;
|
||
|
if(ppszBuf && (*ppszBuf))
|
||
|
{
|
||
|
LocalFree(*ppszBuf);
|
||
|
*ppszBuf = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (FALSE == fSuccess)
|
||
|
{
|
||
|
// if you couldn't read the file, then perhaps atleast this will work ?
|
||
|
HRESULT hr = InitProp();
|
||
|
if (SUCCEEDED(hr) && SUCCEEDED(m_pprop->GetProp(PID_IS_URL, szURL, SIZECHARS(szURL))))
|
||
|
{
|
||
|
hr = CreateURLFileContents(szURL, ppszBuf);
|
||
|
|
||
|
// IEUNIX-This function should return the strlen not including the
|
||
|
// null characters as this causes the shortcut file having a null
|
||
|
// character causing a crash in the execution of the link.
|
||
|
// Fortunately, that's what CreateURLFileContents returns
|
||
|
|
||
|
cbSize = SUCCEEDED(hr) ? hr : 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
|
||
|
|
||
|
return cbSize;
|
||
|
}
|
||
|
|
||
|
#ifndef WC_NO_BEST_FIT_CHARS
|
||
|
#define WC_NO_BEST_FIT_CHARS 0x00000400
|
||
|
#endif
|
||
|
|
||
|
// transfer the URL data in URL clipboard
|
||
|
STDMETHODIMP Intshcut::TransferUniformResourceLocator(FORMATETC *pfmtetc, STGMEDIUM *pstgmed)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
ASSERT(pfmtetc->dwAspect == DVASPECT_CONTENT);
|
||
|
ASSERT(pfmtetc->lindex == -1);
|
||
|
|
||
|
if (pfmtetc->tymed & TYMED_HGLOBAL)
|
||
|
{
|
||
|
TCHAR szURL[INTERNET_MAX_URL_LENGTH];
|
||
|
ASSERT(m_pprop);
|
||
|
hr = InitProp();
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = m_pprop->GetProp(PID_IS_URL, szURL, SIZECHARS(szURL));
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
int cch = lstrlen(szURL) + 1;
|
||
|
int cb = (cch-1) * 9 + 1; // the biggest result is an utf8 escaped version of the string
|
||
|
// utf8 encoding can blow the size up to 3 times
|
||
|
// escaping can blow each byte up to 3 times
|
||
|
LPSTR pszURL = (LPSTR)GlobalAlloc(GPTR, cb);
|
||
|
if (pszURL)
|
||
|
{
|
||
|
if (pfmtetc->cfFormat == CF_UNICODETEXT || pfmtetc->cfFormat == g_cfURLW)
|
||
|
{
|
||
|
StrCpyN((LPWSTR)pszURL, szURL, cch);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BOOL bUsedDefaultChar = FALSE;
|
||
|
DWORD dwFlags = 0;
|
||
|
if (IsOS(OS_WIN2000ORGREATER) || IsOS(OS_WIN98ORGREATER))
|
||
|
{
|
||
|
dwFlags |= WC_NO_BEST_FIT_CHARS;
|
||
|
}
|
||
|
int wcResult = WideCharToMultiByte(CP_ACP,
|
||
|
dwFlags,
|
||
|
szURL,
|
||
|
cch,
|
||
|
pszURL,
|
||
|
cb,
|
||
|
NULL,
|
||
|
&bUsedDefaultChar);
|
||
|
if ((0 == wcResult) || bUsedDefaultChar)
|
||
|
{
|
||
|
// the string is weird and can't be converted back to unicode
|
||
|
// we're going to utf8-escaped encode it
|
||
|
ConvertToUtf8Escaped(szURL, ARRAYSIZE(szURL));
|
||
|
SHUnicodeToAnsi(szURL, pszURL, cb);
|
||
|
}
|
||
|
}
|
||
|
pstgmed->tymed = TYMED_HGLOBAL;
|
||
|
pstgmed->hGlobal = pszURL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hr = DV_E_TYMED;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// transfer the URL data in text
|
||
|
STDMETHODIMP Intshcut::TransferText(FORMATETC *pfmtetc, STGMEDIUM *pstgmed)
|
||
|
{
|
||
|
return TransferUniformResourceLocator(pfmtetc, pstgmed);
|
||
|
}
|
||
|
|
||
|
// assumes the current seek pos in the stream is at the start
|
||
|
|
||
|
BOOL GetStreamMimeAndExt(LPCWSTR pszURL, IStream *pstm,
|
||
|
LPTSTR pszMime, UINT cchMime, LPTSTR pszExt, UINT cchExt)
|
||
|
{
|
||
|
BYTE buf[256];
|
||
|
ULONG cbRead;
|
||
|
pstm->Read(buf, SIZEOF(buf), &cbRead);
|
||
|
|
||
|
WCHAR *pwszMimeOut;
|
||
|
if (SUCCEEDED(FindMimeFromData(NULL, pszURL, buf, cbRead, NULL, 0, &pwszMimeOut, 0)))
|
||
|
{
|
||
|
TCHAR szMimeTemp[MAX_PATH];
|
||
|
|
||
|
if (pszMime == NULL)
|
||
|
{
|
||
|
pszMime = szMimeTemp;
|
||
|
cchMime = ARRAYSIZE(szMimeTemp);
|
||
|
}
|
||
|
|
||
|
SHUnicodeToTChar(pwszMimeOut, pszMime, cchMime);
|
||
|
CoTaskMemFree(pwszMimeOut);
|
||
|
|
||
|
if (pszExt)
|
||
|
MIME_GetExtension(pszMime, pszExt, cchExt);
|
||
|
}
|
||
|
|
||
|
// const LARGE_INTEGER c_li0 = {0, 0};
|
||
|
pstm->Seek(c_li0, STREAM_SEEK_SET, NULL);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// pszName is assumed to be MAX_PATH
|
||
|
|
||
|
STDMETHODIMP Intshcut::GetDocumentName(LPTSTR pszName)
|
||
|
{
|
||
|
GetDescription(pszName, MAX_PATH);
|
||
|
|
||
|
WCHAR *pszURL;
|
||
|
if (S_OK == GetURLW(&pszURL))
|
||
|
{
|
||
|
IStream *pstm;
|
||
|
if (SUCCEEDED(URLOpenBlockingStreamW(NULL, pszURL, &pstm, 0, NULL)))
|
||
|
{
|
||
|
TCHAR szExt[MAX_PATH];
|
||
|
GetStreamMimeAndExt(pszURL, pstm, NULL, 0, szExt, ARRAYSIZE(szExt));
|
||
|
|
||
|
PathRenameExtension(pszName, szExt);
|
||
|
|
||
|
pstm->Release();
|
||
|
}
|
||
|
SHFree(pszURL);
|
||
|
}
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// transfer URL data in file-group-descriptor clipboard format.
|
||
|
STDMETHODIMP Intshcut::TransferFileGroupDescriptorA(FORMATETC *pfmtetc, STGMEDIUM *pstgmed)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
if (pfmtetc->dwAspect != DVASPECT_COPY &&
|
||
|
pfmtetc->dwAspect != DVASPECT_LINK &&
|
||
|
pfmtetc->dwAspect != DVASPECT_CONTENT)
|
||
|
{
|
||
|
hr = DV_E_DVASPECT;
|
||
|
}
|
||
|
else if (pfmtetc->tymed & TYMED_HGLOBAL)
|
||
|
{
|
||
|
FILEGROUPDESCRIPTORA * pfgd = (FILEGROUPDESCRIPTORA *)GlobalAlloc(GPTR, SIZEOF(FILEGROUPDESCRIPTORA));
|
||
|
if (pfgd)
|
||
|
{
|
||
|
FILEDESCRIPTORA * pfd = &(pfgd->fgd[0]);
|
||
|
TCHAR szTemp[MAX_PATH];
|
||
|
|
||
|
if (pfmtetc->dwAspect == DVASPECT_COPY)
|
||
|
{
|
||
|
pfd->dwFlags = FD_FILESIZE;
|
||
|
GetDocumentName(szTemp);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pfd->dwFlags = FD_FILESIZE | FD_LINKUI;
|
||
|
GetDescription(szTemp, ARRAYSIZE(szTemp));
|
||
|
}
|
||
|
SHTCharToAnsi(PathFindFileName(szTemp), pfd->cFileName, SIZECHARS(pfd->cFileName));
|
||
|
|
||
|
pfd->nFileSizeHigh = 0;
|
||
|
pfd->nFileSizeLow = GetFileContentsAndSize(NULL);
|
||
|
|
||
|
pfgd->cItems = 1;
|
||
|
|
||
|
pstgmed->tymed = TYMED_HGLOBAL;
|
||
|
pstgmed->hGlobal = pfgd;
|
||
|
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
else
|
||
|
hr = DV_E_TYMED;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// transfer URL data in file-group-descriptor clipboard format.
|
||
|
STDMETHODIMP Intshcut::TransferFileGroupDescriptorW(FORMATETC *pfmtetc, STGMEDIUM *pstgmed)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
if (pfmtetc->dwAspect != DVASPECT_COPY &&
|
||
|
pfmtetc->dwAspect != DVASPECT_LINK &&
|
||
|
pfmtetc->dwAspect != DVASPECT_CONTENT)
|
||
|
{
|
||
|
hr = DV_E_DVASPECT;
|
||
|
}
|
||
|
else if (pfmtetc->tymed & TYMED_HGLOBAL)
|
||
|
{
|
||
|
FILEGROUPDESCRIPTORW * pfgd = (FILEGROUPDESCRIPTORW *)GlobalAlloc(GPTR, SIZEOF(FILEGROUPDESCRIPTORW));
|
||
|
if (pfgd)
|
||
|
{
|
||
|
FILEDESCRIPTORW * pfd = &(pfgd->fgd[0]);
|
||
|
TCHAR szTemp[MAX_PATH];
|
||
|
|
||
|
if (pfmtetc->dwAspect == DVASPECT_COPY)
|
||
|
{
|
||
|
pfd->dwFlags = FD_FILESIZE;
|
||
|
GetDocumentName(szTemp);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pfd->dwFlags = FD_FILESIZE | FD_LINKUI;
|
||
|
GetDescription(szTemp, ARRAYSIZE(szTemp));
|
||
|
}
|
||
|
|
||
|
SHTCharToUnicode(PathFindFileName(szTemp), pfd->cFileName, SIZECHARS(pfd->cFileName));
|
||
|
|
||
|
pfd->nFileSizeHigh = 0;
|
||
|
pfd->nFileSizeLow = GetFileContentsAndSize(NULL);
|
||
|
|
||
|
pfgd->cItems = 1;
|
||
|
|
||
|
pstgmed->tymed = TYMED_HGLOBAL;
|
||
|
pstgmed->hGlobal = pfgd;
|
||
|
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
else
|
||
|
hr = DV_E_TYMED;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
#if defined(BIG_ENDIAN) && defined(BYTE_ORDER)
|
||
|
#if BYTE_ORDER != BIG_ENDIAN
|
||
|
#undef BIG_ENDIAN
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#ifdef BIG_ENDIAN
|
||
|
#define BOM 0xfffe
|
||
|
#else
|
||
|
#define BOM 0xfeff
|
||
|
#endif
|
||
|
|
||
|
STDMETHODIMP Intshcut::GetDocumentStream(IStream **ppstm)
|
||
|
{
|
||
|
*ppstm = NULL;
|
||
|
|
||
|
WCHAR *pszURL;
|
||
|
HRESULT hres = GetURLW(&pszURL);
|
||
|
if (S_OK == hres)
|
||
|
{
|
||
|
IStream *pstm;
|
||
|
hres = URLOpenBlockingStreamW(NULL, pszURL, &pstm, 0, NULL);
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
TCHAR szMime[80];
|
||
|
|
||
|
if (GetStreamMimeAndExt(pszURL, pstm, szMime, ARRAYSIZE(szMime), NULL, 0) &&
|
||
|
StrCmpI(szMime, TEXT("text/html")) == 0)
|
||
|
{
|
||
|
IStream *aStreams[2];
|
||
|
|
||
|
if(m_uiCodePage == 1200) // Unicode
|
||
|
{
|
||
|
WCHAR wzBaseTag[INTERNET_MAX_URL_LENGTH + 20];
|
||
|
|
||
|
wnsprintfW(wzBaseTag, ARRAYSIZE(wzBaseTag), TEXT("%wc<BASE HREF=\"%ws\">\n"), (WCHAR)BOM, pszURL);
|
||
|
aStreams[0] = SHCreateMemStream((BYTE *)wzBaseTag, lstrlenW(wzBaseTag) * SIZEOF(wzBaseTag[0]));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CHAR szURL[INTERNET_MAX_URL_LENGTH], szBaseTag[INTERNET_MAX_URL_LENGTH + 20];
|
||
|
|
||
|
SHUnicodeToAnsi(pszURL, szURL, ARRAYSIZE(szURL));
|
||
|
wnsprintfA(szBaseTag, ARRAYSIZE(szBaseTag), "<BASE HREF=\"%s\">\n", szURL);
|
||
|
|
||
|
// NOTE: this is an ANSI stream
|
||
|
|
||
|
aStreams[0] = SHCreateMemStream((BYTE *)szBaseTag, lstrlenA(szBaseTag) * SIZEOF(szBaseTag[0]));
|
||
|
}
|
||
|
if (aStreams[0])
|
||
|
{
|
||
|
aStreams[1] = pstm;
|
||
|
hres = SHCreateStreamWrapperCP(aStreams, ARRAYSIZE(aStreams), STGM_READ, m_uiCodePage, ppstm);
|
||
|
aStreams[0]->Release();
|
||
|
}
|
||
|
else
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
pstm->Release();
|
||
|
}
|
||
|
else
|
||
|
*ppstm = pstm;
|
||
|
}
|
||
|
SHFree(pszURL);
|
||
|
}
|
||
|
else
|
||
|
hres = E_FAIL;
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
// transfer URL data in file-contents clipboard format.
|
||
|
STDMETHODIMP Intshcut::TransferFileContents(FORMATETC *pfmtetc, STGMEDIUM *pstgmed)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
if (pfmtetc->lindex != 0)
|
||
|
return DV_E_LINDEX;
|
||
|
|
||
|
if ((pfmtetc->dwAspect == DVASPECT_CONTENT ||
|
||
|
pfmtetc->dwAspect == DVASPECT_LINK) &&
|
||
|
(pfmtetc->tymed & TYMED_HGLOBAL))
|
||
|
{
|
||
|
LPSTR pszFileContents;
|
||
|
DWORD cbSize = GetFileContentsAndSize(&pszFileContents);
|
||
|
if (pszFileContents)
|
||
|
{
|
||
|
pstgmed->tymed = TYMED_HGLOBAL;
|
||
|
pstgmed->hGlobal = pszFileContents;
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
else if ((pfmtetc->dwAspect == DVASPECT_COPY) && (pfmtetc->tymed & TYMED_ISTREAM))
|
||
|
{
|
||
|
hr = GetDocumentStream(&pstgmed->pstm);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
pstgmed->tymed = TYMED_ISTREAM;
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hr = DV_E_TYMED;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
|
||
|
STDMETHODIMP_(void) Intshcut::Dump(void)
|
||
|
{
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
|
||
|
|
||
|
#define INDENT_STRING " "
|
||
|
|
||
|
if (IsFlagSet(g_dwDumpFlags, DF_INTSHCUT))
|
||
|
{
|
||
|
TraceMsg(TF_ALWAYS, "%sm_dwFlags = %#08lx",
|
||
|
INDENT_STRING,
|
||
|
m_dwFlags);
|
||
|
TraceMsg(TF_ALWAYS, "%sm_pszFile = \"%s\"",
|
||
|
INDENT_STRING,
|
||
|
Dbg_SafeStr(m_pszFile));
|
||
|
|
||
|
if (m_pprop)
|
||
|
m_pprop->Dump();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif // DEBUG
|