1594 lines
51 KiB
C++
1594 lines
51 KiB
C++
// wvcoord.cpp : Implementation of CWebViewCoord
|
|
|
|
#include "priv.h"
|
|
#include "wvcoord.h"
|
|
#include "shdispid.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// String Constants
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
#define CSC_PLUSCOLD L"<img id=CSCBmp align=middle src=pluscold.gif>"
|
|
#define CSC_PLUSHOT L"<img id=CSCBmp align=middle src=plushot.gif>"
|
|
#define CSC_MINUSCOLD L"<img id=CSCBmp align=middle src=mincold.gif>"
|
|
#define CSC_MINUSHOT L"<img id=CSCBmp align=middle src=minhot.gif>"
|
|
#define WV_LINKNAME L"WVLink"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CFileListWrapper
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
CFileListWrapper::CFileListWrapper()
|
|
{
|
|
m_pThumbNailWrapper = NULL;
|
|
m_bCSCDisplayed = FALSE;
|
|
m_bExpanded = FALSE;
|
|
m_bHotTracked = FALSE;
|
|
m_dwDateFlags = FDTF_DEFAULT; // default
|
|
m_bRTLDocument = FALSE; // default
|
|
}
|
|
|
|
#define MYDOCS_CLSID L"{450d8fba-ad25-11d0-98a8-0800361b1103}" // CLSID_MyDocuments
|
|
|
|
HRESULT GetFolderIDList(int nFolder, LPITEMIDLIST* ppidlFolder)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (nFolder == CSIDL_PERSONAL)
|
|
{
|
|
hr = SHILCreateFromPath(L"::" MYDOCS_CLSID, ppidlFolder, NULL);
|
|
}
|
|
else
|
|
{
|
|
hr = SHGetSpecialFolderLocation(NULL, nFolder, ppidlFolder);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::IsItThisFolder(int nFolder, BOOL& bResult, LPWSTR pwszDisplayName, DWORD cchDisplayName, LPWSTR pwszUrlPath, DWORD cchUrlPath)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
LPITEMIDLIST pidlFolder = NULL, pidlLast = NULL;
|
|
CComPtr<IShellFolder> psfParent;
|
|
STRRET strret;
|
|
CComBSTR bstrTemp;
|
|
WCHAR wszPath[MAX_PATH];
|
|
|
|
if (SUCCEEDED(GetFolderIDList(nFolder, &pidlFolder))
|
|
&& SUCCEEDED(SHBindToIDListParent(pidlFolder, IID_IShellFolder, (void**)&psfParent, (LPCITEMIDLIST*)&pidlLast))
|
|
&& SUCCEEDED(psfParent->GetDisplayNameOf(pidlLast, SHGDN_NORMAL, &strret))
|
|
&& SUCCEEDED(StrRetToBufW(&strret, pidlFolder, pwszDisplayName, cchDisplayName))
|
|
&& SUCCEEDED(psfParent->GetDisplayNameOf(pidlLast, SHGDN_FORPARSING, &strret))
|
|
&& SUCCEEDED(StrRetToBufW(&strret, pidlFolder, wszPath, ARRAYSIZE(wszPath)))
|
|
&& SUCCEEDED(m_spFolderItem->get_Path(&bstrTemp)) && (bstrTemp.Length() > 0))
|
|
{
|
|
hr = S_OK;
|
|
bResult = (StrCmpIW(bstrTemp, wszPath) == 0);
|
|
if (CSIDL_PERSONAL == nFolder)
|
|
{
|
|
// Change the URL for mydocs (after comparing with the path) so that it
|
|
// is a CLSID URL instead of the file system path
|
|
StrCpyNW(wszPath, L"::" MYDOCS_CLSID, ARRAYSIZE(wszPath));
|
|
}
|
|
UrlCreateFromPathW(wszPath, pwszUrlPath, &cchUrlPath, 0);
|
|
}
|
|
if (pidlFolder)
|
|
{
|
|
ILFree(pidlFolder);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::GetIMediaPlayer(CComPtr<IMediaPlayer>& spIMediaPlayer)
|
|
{
|
|
// The MediaPlayer objects has too many bugs. So, let's disable it.
|
|
#if 0
|
|
if (!m_spIMediaPlayer)
|
|
{
|
|
if (m_spMediaPlayerSpan)
|
|
{
|
|
m_spMediaPlayerSpan->put_innerHTML(OLESTR("<object ID=MediaPlayer classid=\"clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95\" style=\"display:none; position:absolute; width:176px\"> <param name=\"ShowDisplay\" value=false> <param name=\"AutoPlay\" value=false> </object><br>"));
|
|
}
|
|
|
|
CComPtr<IHTMLElementCollection> spDocAll;
|
|
CComVariant vEmpty;
|
|
CComPtr<IDispatch> spdispItem;
|
|
if (SUCCEEDED(m_spDocument->get_all(&spDocAll)) && SUCCEEDED(spDocAll->item(CComVariant(OLESTR("MediaPlayer")), vEmpty, &spdispItem)) && spdispItem)
|
|
{
|
|
if (FAILED(FindObjectStyle(spdispItem, m_spMediaPlayerStyle)))
|
|
{
|
|
m_spMediaPlayerStyle = NULL;
|
|
}
|
|
if (FAILED(spdispItem->QueryInterface(IID_IMediaPlayer, (void **)&m_spIMediaPlayer)))
|
|
{
|
|
m_spIMediaPlayer = NULL;
|
|
}
|
|
else
|
|
{
|
|
m_spIMediaPlayer->put_EnableContextMenu(VARIANT_FALSE);
|
|
}
|
|
spdispItem = NULL;
|
|
}
|
|
spDocAll = NULL;
|
|
}
|
|
#endif
|
|
spIMediaPlayer = m_spIMediaPlayer;
|
|
return spIMediaPlayer ? S_OK : E_FAIL;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::FormatCrossLink(LPCWSTR pwszDisplayName, LPCWSTR pwszUrlPath, UINT uIDToolTip)
|
|
{
|
|
m_bstrCrossLinksHTML += OLESTR("<p class=Half><a href=\"");
|
|
m_bstrCrossLinksHTML += pwszUrlPath;
|
|
m_bstrCrossLinksHTML += OLESTR("\"");
|
|
|
|
WCHAR wszToolTip[MAX_PATH];
|
|
wszToolTip[0] = L'\0';
|
|
if (LoadStringW(_Module.GetResourceInstance(), uIDToolTip, wszToolTip, ARRAYSIZE(wszToolTip)) > 0)
|
|
{
|
|
m_bstrCrossLinksHTML += OLESTR(" title=\"");
|
|
m_bstrCrossLinksHTML += wszToolTip;
|
|
m_bstrCrossLinksHTML += OLESTR("\"");
|
|
}
|
|
m_bstrCrossLinksHTML += OLESTR(" name=\"");
|
|
m_bstrCrossLinksHTML += WV_LINKNAME;
|
|
m_bstrCrossLinksHTML += OLESTR("\"");
|
|
m_bstrCrossLinksHTML += OLESTR(">");
|
|
m_bstrCrossLinksHTML += pwszDisplayName;
|
|
m_bstrCrossLinksHTML += OLESTR("</a>");
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::GetCrossLink(int nFolder, UINT uIDToolTip)
|
|
{
|
|
HRESULT hres = E_FAIL; // Assume error
|
|
// Get the links.
|
|
WCHAR wszDisplayName[MAX_PATH], wszUrlPath[MAX_PATH];
|
|
BOOL bThisFolder;
|
|
if (SUCCEEDED(IsItThisFolder(nFolder, bThisFolder, wszDisplayName, ARRAYSIZE(wszDisplayName), wszUrlPath, ARRAYSIZE(wszUrlPath)))
|
|
&& !bThisFolder)
|
|
{
|
|
hres = FormatCrossLink(wszDisplayName, wszUrlPath, uIDToolTip);
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::GetCrossLinks()
|
|
{
|
|
WCHAR wszSeeAlso[MAX_PATH];
|
|
m_bstrCrossLinksHTML += OLESTR("<p>");
|
|
LoadStringW(_Module.GetResourceInstance(), IDS_SEEALSO, wszSeeAlso, ARRAYSIZE(wszSeeAlso));
|
|
m_bstrCrossLinksHTML += wszSeeAlso;
|
|
|
|
GetCrossLink(CSIDL_PERSONAL, IDS_MYDOCSTEXT);
|
|
if (!SHRestricted(REST_NONETHOOD))
|
|
{
|
|
GetCrossLink(CSIDL_NETWORK, IDS_MYNETPLACESTEXT);
|
|
}
|
|
if (FAILED(GetCrossLink(CSIDL_DRIVES, IDS_MYCOMPTEXT)) && !SHRestricted(REST_NONETHOOD))
|
|
{
|
|
// This is the My Computer folder - Add a link to Network and Dial-up Connections folder
|
|
WCHAR wszNDC[MAX_PATH];
|
|
wszNDC[0] = L'\0';
|
|
LoadStringW(_Module.GetResourceInstance(), IDS_NDC, wszNDC, ARRAYSIZE(wszNDC));
|
|
|
|
FormatCrossLink(wszNDC, L"shell:ConnectionsFolder", IDS_NDCTEXT);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// The Media Player folks haven't published the IMediaPlayer interface, so I define it here.
|
|
// Should strip it out when their declaration makes it to the public headers.
|
|
const IID IID_IMediaPlayer = {0x22D6F311,0xB0F6,0x11D0,{0x94,0xAB,0x00,0x80,0xC7,0x4C,0x7E,0x95}};
|
|
|
|
HRESULT CFileListWrapper::Init(
|
|
CComPtr<IShellFolderViewDual> spFileList,
|
|
CComPtr<IHTMLElement> spInfo,
|
|
CComPtr<IHTMLElement> spLinks,
|
|
CComPtr<IHTMLStyle> spPanelStyle,
|
|
CComPtr<IHTMLElement> spMediaPlayerSpan,
|
|
CComPtr<IHTMLElement> spCSCPlusMin,
|
|
CComPtr<IHTMLElement> spCSCText,
|
|
CComPtr<IHTMLElement> spCSCDetail,
|
|
CComPtr<IHTMLElement> spCSCButton,
|
|
CComPtr<IHTMLStyle> spCSCStyle,
|
|
CComPtr<IHTMLStyle> spCSCDetailStyle,
|
|
CComPtr<IHTMLStyle> spCSCButtonStyle,
|
|
CComPtr<IHTMLDocument2> spDocument,
|
|
CComPtr<IHTMLWindow2> spWindow,
|
|
CThumbNailWrapper *pThumbNailWrapper)
|
|
{
|
|
m_spFileList = spFileList;
|
|
m_spInfo = spInfo;
|
|
m_spLinks = spLinks;
|
|
m_spPanelStyle = spPanelStyle;
|
|
m_spMediaPlayerSpan = spMediaPlayerSpan;
|
|
m_spMediaPlayerStyle = NULL;
|
|
m_spIMediaPlayer = NULL;
|
|
m_spCSCPlusMin = spCSCPlusMin;
|
|
m_spCSCText = spCSCText;
|
|
m_spCSCDetail = spCSCDetail;
|
|
m_spCSCButton = spCSCButton;
|
|
m_spCSCStyle = spCSCStyle;
|
|
m_spCSCDetailStyle = spCSCDetailStyle;
|
|
m_spCSCButtonStyle = spCSCButtonStyle;
|
|
m_spDocument = spDocument;
|
|
m_spWindow = spWindow;
|
|
m_pThumbNailWrapper = pThumbNailWrapper;
|
|
if (m_pThumbNailWrapper)
|
|
{
|
|
m_pThumbNailWrapper->AddRef();
|
|
}
|
|
m_bNeverGotPanelInfo = TRUE;
|
|
|
|
// Find out if the reading order is from right to left
|
|
m_dwDateFlags = FDTF_DEFAULT; // default
|
|
|
|
m_bRTLDocument = IsRTLDocument(m_spDocument); // default
|
|
|
|
// Get the date format reading order
|
|
LCID locale = GetUserDefaultLCID();
|
|
if ((PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_ARABIC) ||
|
|
(PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_HEBREW))
|
|
{
|
|
|
|
if (m_bRTLDocument)
|
|
m_dwDateFlags |= FDTF_RTLDATE;
|
|
else
|
|
m_dwDateFlags |= FDTF_LTRDATE;
|
|
}
|
|
|
|
m_bPathIsSlow = FALSE; // default
|
|
|
|
// Make sure that the path is not slow
|
|
CComPtr<Folder> spFolder;
|
|
CComPtr<Folder2> spFolder2;
|
|
CComPtr<FolderItem> spFolderItem;
|
|
CComBSTR bstrPath;
|
|
|
|
if (m_spFileList && SUCCEEDED(m_spFileList->get_Folder(&spFolder))
|
|
&& SUCCEEDED(spFolder->QueryInterface(IID_Folder2, (void **)&spFolder2))
|
|
&& SUCCEEDED(spFolder2->get_Self(&spFolderItem))
|
|
&& SUCCEEDED(spFolderItem->get_Path(&bstrPath)))
|
|
{
|
|
m_bPathIsSlow = PathIsSlowW(bstrPath, -1);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
CFileListWrapper::~CFileListWrapper()
|
|
{
|
|
// Release any objects we are holding references to
|
|
m_spFileList = NULL;
|
|
m_spInfo = NULL;
|
|
m_spLinks = NULL;
|
|
m_spPanelStyle = NULL;
|
|
m_spIMediaPlayer = NULL;
|
|
m_spMediaPlayerSpan = NULL;
|
|
m_spMediaPlayerStyle = NULL;
|
|
m_spIMediaPlayer = NULL;
|
|
m_spCSCPlusMin = NULL;
|
|
m_spCSCText = NULL;
|
|
m_spCSCDetail = NULL;
|
|
m_spCSCButton = NULL;
|
|
m_spCSCStyle = NULL;
|
|
m_spCSCDetailStyle = NULL;
|
|
m_spCSCButtonStyle = NULL;
|
|
m_spDocument = NULL;
|
|
m_spWindow = NULL;
|
|
|
|
// Release thumbnail wrapper
|
|
if (m_pThumbNailWrapper)
|
|
{
|
|
m_pThumbNailWrapper->Release();
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP CFileListWrapper::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
|
|
WORD wFlags, DISPPARAMS *pDispParams,
|
|
VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
|
|
UINT *puArgErr)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (riid != IID_NULL)
|
|
{
|
|
hr = DISP_E_UNKNOWNINTERFACE;
|
|
}
|
|
else if (dispIdMember == DISPID_SELECTIONCHANGED)
|
|
{
|
|
hr = OnSelectionChanged();
|
|
}
|
|
else if (dispIdMember == DISPID_FILELISTENUMDONE)
|
|
{
|
|
hr = SetDefaultPanelDisplay();
|
|
}
|
|
else if (dispIdMember == DISPID_VERBINVOKED ||
|
|
dispIdMember == DISPID_BEGINDRAG)
|
|
{
|
|
hr = StopMediaPlayer();
|
|
}
|
|
else if (dispIdMember == DISPID_HTMLELEMENTEVENTS_ONMOUSEOVER)
|
|
{
|
|
hr = OnWebviewLinkEvent( TRUE );
|
|
}
|
|
else if (dispIdMember == DISPID_HTMLELEMENTEVENTS_ONMOUSEOUT)
|
|
{
|
|
hr = OnWebviewLinkEvent( FALSE );
|
|
}
|
|
else if (dispIdMember == DISPID_HTMLELEMENTEVENTS_ONFOCUS)
|
|
{
|
|
hr = OnWebviewLinkEvent( TRUE );
|
|
}
|
|
else if (dispIdMember == DISPID_HTMLELEMENTEVENTS_ONBLUR)
|
|
{
|
|
hr = OnWebviewLinkEvent( FALSE );
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::ClearThumbNail()
|
|
{
|
|
if (m_pThumbNailWrapper)
|
|
{
|
|
m_pThumbNailWrapper->ClearThumbNail();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::StopMediaPlayer()
|
|
{
|
|
if (m_spIMediaPlayer)
|
|
{
|
|
m_spIMediaPlayer->Stop();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::ClearMediaPlayer()
|
|
{
|
|
StopMediaPlayer();
|
|
if (m_spMediaPlayerStyle)
|
|
{
|
|
m_spMediaPlayerStyle->put_display(OLESTR("none"));
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::OnSelectionChanged()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_spFileList)
|
|
{
|
|
// Erase any visible thumbnail since the selection changed
|
|
ClearThumbNail();
|
|
// Kill any preview
|
|
ClearMediaPlayer();
|
|
|
|
long cSelection = 0;
|
|
CComPtr<FolderItems> spFolderItems;
|
|
CComPtr<Folder> spFolder;
|
|
CComPtr<Folder2> spFolder2;
|
|
|
|
if (SUCCEEDED(m_spFileList->SelectedItems(&spFolderItems))
|
|
&& SUCCEEDED(spFolderItems->get_Count(&cSelection))
|
|
&& SUCCEEDED(m_spFileList->get_Folder(&spFolder))
|
|
&& SUCCEEDED(spFolder->QueryInterface(IID_Folder2, (void **)&spFolder2)))
|
|
{
|
|
m_spFolderItems = spFolderItems;
|
|
m_spFolder2 = spFolder2;
|
|
|
|
m_bstrInfoHTML = OLESTR("");
|
|
m_bstrCrossLinksHTML = OLESTR("");
|
|
|
|
if (cSelection == 0)
|
|
{
|
|
m_spFolderItems = NULL;
|
|
if (SUCCEEDED(m_spFolder2->Items(&m_spFolderItems)))
|
|
{
|
|
// Nothing is selected
|
|
hr = NoneSelected();
|
|
}
|
|
}
|
|
else if (cSelection > 1)
|
|
{
|
|
// More than one item is selected
|
|
hr = MultipleSelected(cSelection);
|
|
}
|
|
else
|
|
{
|
|
CComPtr<FolderItem> spFolderItem;
|
|
if (SUCCEEDED(m_spFolderItems->Item(CComVariant(0), &spFolderItem)))
|
|
{
|
|
m_spFolderItem = spFolderItem;
|
|
m_spFolderItem->QueryInterface(IID_FolderItem2, (void **)&m_spFolderItem2);
|
|
|
|
// A single item has been selected
|
|
hr = OneSelected();
|
|
|
|
m_spFolderItem2 = NULL;
|
|
m_spFolderItem = NULL;
|
|
}
|
|
}
|
|
|
|
DisplayInfoHTML();
|
|
DisplayCrossLinksHTML();
|
|
|
|
m_spFolder2 = NULL;
|
|
m_spFolderItems = NULL;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::SetDefaultPanelDisplay()
|
|
{
|
|
CComPtr<Folder> spFolder;
|
|
CComPtr<Folder2> spFolder2;
|
|
CComPtr<FolderItems> spFolderItems;
|
|
|
|
if (m_spFileList && SUCCEEDED(m_spFileList->get_Folder(&spFolder))
|
|
&& SUCCEEDED(spFolder->QueryInterface(IID_Folder2, (void **)&spFolder2))
|
|
&& SUCCEEDED(spFolder2->Items(&spFolderItems)))
|
|
{
|
|
m_bstrInfoHTML = OLESTR("");
|
|
m_bstrCrossLinksHTML = OLESTR("");
|
|
|
|
m_spFolderItems = spFolderItems;
|
|
m_spFolder2 = spFolder2;
|
|
|
|
NoneSelected();
|
|
DisplayInfoHTML();
|
|
DisplayCrossLinksHTML();
|
|
|
|
m_spFolder2 = NULL;
|
|
m_spFolderItems = NULL;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::DisplayInfoHTML()
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
if (m_spInfo)
|
|
{
|
|
// Replace Info.innerHTML with the new text
|
|
hr = m_spInfo->put_innerHTML(m_bstrInfoHTML);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::DisplayCrossLinksHTML()
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
if (m_spLinks)
|
|
{
|
|
// Break old connections
|
|
AdviseWebviewLinks( FALSE );
|
|
|
|
// Replace Links.innerHTML with the new text
|
|
hr = m_spLinks->put_innerHTML(m_bstrCrossLinksHTML);
|
|
|
|
// Make new connections
|
|
AdviseWebviewLinks( TRUE );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
BOOL IsExtensionOneOf(LPCWSTR pwszFileName, const LPCWSTR pwszExtList[], int cExtList)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
LPCWSTR pwszExt = PathFindExtensionW(pwszFileName);
|
|
|
|
if (pwszExt && *pwszExt)
|
|
{
|
|
for (int i = 0; i < cExtList; i++)
|
|
{
|
|
if (StrCmpICW(pwszExtList[i], pwszExt + 1) == 0) // Get pwszExt past "."
|
|
{
|
|
fRet = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
const LPCWSTR c_pwszMovieFileExt[] = {L"asf",L"avi",L"wmv",L"wvx",L"m1v",L"mov",L"mp2",L"mpa",L"mpe",L"mpeg",L"mpg",L"mpv2",L"qt",L"asx"};
|
|
BOOL IsMovieFile(LPCWSTR pwszFileName)
|
|
{
|
|
return IsExtensionOneOf(pwszFileName, c_pwszMovieFileExt, ARRAYSIZE(c_pwszMovieFileExt));
|
|
}
|
|
|
|
const LPCWSTR c_pwszSoundFileExt[] = {L"aif",L"aiff",L"au",L"mid",L"midi",L"rmi",L"snd",L"wav",L"mp3",L"m3u",L"wma"};
|
|
BOOL IsSoundFile(LPCWSTR pwszFileName)
|
|
{
|
|
return IsExtensionOneOf(pwszFileName, c_pwszSoundFileExt, ARRAYSIZE(c_pwszSoundFileExt));
|
|
}
|
|
|
|
HRESULT CFileListWrapper::DealWithDriveInfo()
|
|
{
|
|
CComBSTR bstrPath;
|
|
// Update ThumbNail
|
|
if (m_pThumbNailWrapper && m_spFolderItem && SUCCEEDED(m_spFolderItem->get_Path(&bstrPath)) && (bstrPath.Length() > 0))
|
|
{
|
|
BOOL bRootFolder = PathIsRootW(bstrPath);
|
|
BOOL bHaveThumbnail = FALSE;
|
|
if (!bRootFolder || !PathIsUNCW(bstrPath))
|
|
{
|
|
bHaveThumbnail = m_pThumbNailWrapper->UpdateThumbNail(m_spFolderItem);
|
|
}
|
|
if (bHaveThumbnail)
|
|
{
|
|
if (bRootFolder)
|
|
{
|
|
WCHAR wszTemp[MAX_PATH];
|
|
CComBSTR bstrSpace;
|
|
|
|
if (SUCCEEDED(m_pThumbNailWrapper->TotalSpace(bstrSpace)))
|
|
{
|
|
m_bstrInfoHTML += OLESTR("<p><br>");
|
|
IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_TOTALSIZE, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
|
|
m_bstrInfoHTML += wszTemp;
|
|
m_bstrInfoHTML += bstrSpace;
|
|
bstrSpace.Empty();
|
|
m_bstrInfoHTML += OLESTR("<p>");
|
|
}
|
|
if (SUCCEEDED(m_pThumbNailWrapper->UsedSpace(bstrSpace)))
|
|
{
|
|
m_bstrInfoHTML += OLESTR("<p><table class=Legend width=12 height=12 border=1 align=");
|
|
if (m_bRTLDocument)
|
|
{
|
|
m_bstrInfoHTML += OLESTR("right ");
|
|
}
|
|
else
|
|
{
|
|
m_bstrInfoHTML += OLESTR("left ");
|
|
}
|
|
m_bstrInfoHTML += OLESTR("bgcolor=threedface bordercolordark=black bordercolorlight=black>");
|
|
m_bstrInfoHTML += OLESTR("<tr><td title=\'");
|
|
IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_USEDSPACE_DESC, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
|
|
m_bstrInfoHTML += wszTemp;
|
|
m_bstrInfoHTML += OLESTR("\'></td></tr></table> ");
|
|
IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_USEDSPACE, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
|
|
m_bstrInfoHTML += wszTemp;
|
|
m_bstrInfoHTML += bstrSpace;
|
|
bstrSpace.Empty();
|
|
}
|
|
if (SUCCEEDED(m_pThumbNailWrapper->FreeSpace(bstrSpace)))
|
|
{
|
|
m_bstrInfoHTML += OLESTR("<p><table class=Legend width=12 height=12 border=1 align=");
|
|
if (m_bRTLDocument)
|
|
{
|
|
m_bstrInfoHTML += OLESTR("right ");
|
|
}
|
|
else
|
|
{
|
|
m_bstrInfoHTML += OLESTR("left ");
|
|
}
|
|
m_bstrInfoHTML += OLESTR("bgcolor=threedhighlight bordercolordark=black bordercolorlight=black>");
|
|
m_bstrInfoHTML += OLESTR("<tr><td title=\'");
|
|
IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_FREESPACE_DESC, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
|
|
m_bstrInfoHTML += wszTemp;
|
|
m_bstrInfoHTML += OLESTR("\'></td></tr></table> ");
|
|
IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_FREESPACE, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
|
|
m_bstrInfoHTML += wszTemp;
|
|
m_bstrInfoHTML += bstrSpace;
|
|
}
|
|
m_pThumbNailWrapper->SetDisplay(CComBSTR(""));
|
|
}
|
|
}
|
|
else if (!bRootFolder)
|
|
{
|
|
BOOL bDisplayFlag = FALSE;
|
|
BOOL bMovieFile = IsMovieFile(bstrPath);
|
|
|
|
if (bMovieFile || IsSoundFile(bstrPath))
|
|
{
|
|
CComPtr<IMediaPlayer> spIMediaPlayer;
|
|
|
|
if (SUCCEEDED(GetIMediaPlayer(spIMediaPlayer)))
|
|
{
|
|
spIMediaPlayer->Open(bstrPath);
|
|
bDisplayFlag = TRUE;
|
|
}
|
|
spIMediaPlayer = NULL;
|
|
}
|
|
|
|
if (m_spMediaPlayerStyle && bDisplayFlag)
|
|
{
|
|
if (bMovieFile)
|
|
{
|
|
m_spMediaPlayerStyle->put_height(CComVariant(136));
|
|
}
|
|
else
|
|
{
|
|
m_spMediaPlayerStyle->put_height(CComVariant(46));
|
|
}
|
|
m_spMediaPlayerStyle->put_display(OLESTR(""));
|
|
}
|
|
}
|
|
}
|
|
return S_OK;;
|
|
}
|
|
|
|
HRESULT MakeLink(LPCWSTR pwszLink, LPCWSTR pwszText, CComBSTR& bstrText)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
if (pwszLink)
|
|
{
|
|
bstrText += OLESTR("<A HREF=\"");
|
|
bstrText += pwszLink;
|
|
bstrText += OLESTR("\">");
|
|
if (pwszText && pwszText[0])
|
|
{
|
|
bstrText += pwszText;
|
|
}
|
|
else // If pwszText is NULL, use pwszLink itself as text.
|
|
{
|
|
bstrText += pwszLink;
|
|
}
|
|
bstrText += OLESTR("</A>");
|
|
hr = S_OK;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::GetItemNameForDisplay()
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
CComBSTR bstrIgnore, bstrName;
|
|
|
|
// Get the name of the item
|
|
if (SUCCEEDED(GetItemInfo(IDS_NAME_COL, L"Name", bstrIgnore, bstrName)) && (bstrName.Length() > 0))
|
|
{
|
|
m_bstrInfoHTML += OLESTR("<b>"); // Begin bold tag
|
|
m_bstrInfoHTML += bstrName; // Add the name
|
|
m_bstrInfoHTML += OLESTR("</b>"); // End bold tag
|
|
hr = S_OK;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::GetItemType()
|
|
{
|
|
CComBSTR bstrIgnore, bstrType;
|
|
HRESULT hr = GetItemInfo(IDS_TYPE_COL, L"Type", bstrIgnore, bstrType);
|
|
|
|
if (SUCCEEDED(hr) && (bstrType.Length() > 0))
|
|
{
|
|
m_bstrInfoHTML += OLESTR("<br>");
|
|
m_bstrInfoHTML += bstrType;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::GetItemDateTime()
|
|
{
|
|
CComBSTR bstrDesc, bstrDateTime;
|
|
HRESULT hr = GetItemInfo(IDS_MODIFIED_COL, L"Modified", bstrDesc, bstrDateTime);
|
|
|
|
if (SUCCEEDED(hr) && (bstrDateTime.Length() > 0))
|
|
{
|
|
m_bstrInfoHTML += OLESTR("<p>");
|
|
m_bstrInfoHTML += bstrDesc;
|
|
m_bstrInfoHTML += OLESTR(": ");
|
|
m_bstrInfoHTML += bstrDateTime;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::GetItemSize()
|
|
{
|
|
WCHAR wszTemp[MAX_PATH];
|
|
long lSize = 0;
|
|
HRESULT hr = m_spFolderItem->get_Size(&lSize);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (lSize > 0L)
|
|
{
|
|
m_bstrInfoHTML += OLESTR("<p>");
|
|
IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_SIZE, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
|
|
m_bstrInfoHTML += wszTemp;
|
|
StrFormatByteSizeW(lSize, wszTemp, ARRAYSIZE(wszTemp));
|
|
m_bstrInfoHTML += wszTemp;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CComBSTR bstrDesc, bstrSize;
|
|
hr = GetItemInfo(IDS_SIZE_COL, L"Size", bstrDesc, bstrSize);
|
|
if (SUCCEEDED(hr) && (bstrSize.Length() > 0))
|
|
{
|
|
m_bstrInfoHTML += OLESTR("<p>");
|
|
m_bstrInfoHTML += bstrDesc;
|
|
m_bstrInfoHTML += OLESTR(": ");
|
|
m_bstrInfoHTML += bstrSize;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
const WCHAR c_wszAttributeCodes[] = {L"RHSCE"};
|
|
const int c_iaAttribStringIDs[] = {IDS_READONLY, IDS_HIDDEN, IDS_SYSTEM, //IDS_ARCHIVE,
|
|
IDS_COMPRESSED, IDS_ENCRYPTED};
|
|
HRESULT FormatAttributes(CComBSTR& bstrDetails, CComBSTR& bstrText)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bFlag = FALSE;
|
|
WCHAR wszDelimiter[10], wszTemp[MAX_PATH];
|
|
|
|
IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_DELIMITER, wszDelimiter, ARRAYSIZE(wszDelimiter)), E_FAIL);
|
|
for (int i = 0; i < (int)bstrDetails.Length(); i++)
|
|
{
|
|
WCHAR* pwCh;
|
|
if ((pwCh = StrChrIW(c_wszAttributeCodes, bstrDetails[i]))) // Is the value, one of "RHSCE"?
|
|
{
|
|
if (bFlag)
|
|
{
|
|
bstrText += wszDelimiter;
|
|
bstrText += OLESTR(" ");
|
|
}
|
|
else
|
|
{
|
|
bFlag = TRUE;
|
|
}
|
|
int iPos = (int)(pwCh - c_wszAttributeCodes);
|
|
ASSERT((iPos >= 0) && (iPos < ARRAYSIZE(c_iaAttribStringIDs)));
|
|
IfFalseRet(LoadStringW(_Module.GetResourceInstance(), c_iaAttribStringIDs[iPos], wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
|
|
bstrText += wszTemp;
|
|
}
|
|
}
|
|
if (!bFlag)
|
|
{
|
|
IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_NOATTRIBUTES, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
|
|
bstrText += wszTemp;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::GetItemAttributes()
|
|
{
|
|
VARIANT_BOOL fIsFolder;
|
|
HRESULT hr = m_spFolderItem->get_IsFolder(&fIsFolder);
|
|
if (SUCCEEDED(hr) && (fIsFolder == VARIANT_FALSE))
|
|
{
|
|
VARIANT_BOOL fIsFileSystem;
|
|
hr = m_spFolderItem->get_IsFileSystem(&fIsFileSystem);
|
|
if (SUCCEEDED(hr) && (fIsFileSystem == VARIANT_TRUE))
|
|
{
|
|
CComBSTR bstrDesc, bstrAttributes;
|
|
hr = GetItemInfo(IDS_ATTRIBUTES_COL, L"Attributes", bstrDesc, bstrAttributes);
|
|
if (SUCCEEDED(hr)) // Go ahead evenif (bstrAttributes.Length() > 0)
|
|
{
|
|
m_bstrInfoHTML += OLESTR("<p>");
|
|
m_bstrInfoHTML += bstrDesc;
|
|
m_bstrInfoHTML += OLESTR(": ");
|
|
FormatAttributes(bstrAttributes, m_bstrInfoHTML);
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT MakeMailLink(LPCWSTR pwszMailee, CComBSTR& bstrText)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
bstrText += OLESTR("<A HREF=\'mailto:");
|
|
bstrText += pwszMailee;
|
|
bstrText += OLESTR("\'>");
|
|
bstrText += pwszMailee;
|
|
bstrText += OLESTR("</a>");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::GetItemAuthor()
|
|
{
|
|
CComBSTR bstrDesc, bstrAuthor;
|
|
HRESULT hr = GetItemInfo(IDS_AUTHOR_COL, L"Author", bstrDesc, bstrAuthor);
|
|
|
|
if (SUCCEEDED(hr) && (bstrAuthor.Length() > 0))
|
|
{
|
|
m_bstrInfoHTML += OLESTR("<p>");
|
|
m_bstrInfoHTML += bstrDesc;
|
|
m_bstrInfoHTML += OLESTR(": ");
|
|
if (StrChrW(bstrAuthor, L'@')) // This is most likely to be an e-mail address
|
|
{
|
|
MakeMailLink(bstrAuthor, m_bstrInfoHTML);
|
|
}
|
|
else
|
|
{
|
|
m_bstrInfoHTML += bstrAuthor;
|
|
}
|
|
m_bFoundAuthor = TRUE;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT MakeLinksHyper(LPCWSTR pwszStr, CComBSTR& bstrText)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPWSTR pwszBegin;
|
|
|
|
if ((pwszBegin = StrStrIW(pwszStr, L"http://"))
|
|
|| (pwszBegin = StrStrIW(pwszStr, L"file://")))
|
|
{
|
|
WCHAR wszTemp[INTERNET_MAX_URL_LENGTH];
|
|
int i;
|
|
|
|
for (i = 0; &pwszStr[i] != pwszBegin; i++)
|
|
{
|
|
wszTemp[i] = pwszStr[i];
|
|
}
|
|
wszTemp[i] = L'\0';
|
|
bstrText += wszTemp;
|
|
WCHAR* pwChEnd = StrStrW(pwszBegin, L" ");
|
|
if (!pwChEnd)
|
|
{
|
|
pwChEnd = &pwszBegin[lstrlenW(pwszBegin)];
|
|
}
|
|
for (i = 0; &pwszBegin[i] != pwChEnd; i++) // Seperate out the http://... or file://... string
|
|
{
|
|
wszTemp[i] = pwszBegin[i];
|
|
}
|
|
wszTemp[i] = L'\0';
|
|
MakeLink(wszTemp, wszTemp, bstrText);
|
|
for (i = 0; pwChEnd[i]; i++) // Copy out the rest, till the end
|
|
{
|
|
wszTemp[i] = pwChEnd[i];
|
|
}
|
|
wszTemp[i] = L'\0';
|
|
bstrText += wszTemp;
|
|
}
|
|
else
|
|
{
|
|
bstrText += pwszStr;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT FormatDetails(LPCWSTR pwszDesc, LPCWSTR pwszDetails, CComBSTR& bstrText)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
bstrText += OLESTR("<p>");
|
|
bstrText += pwszDesc;
|
|
bstrText += OLESTR(":");
|
|
if ((lstrlenW(pwszDesc) + lstrlenW(pwszDetails)) > 32)
|
|
{
|
|
bstrText += OLESTR("<br>");
|
|
}
|
|
else
|
|
{
|
|
bstrText += OLESTR(" ");
|
|
}
|
|
MakeLinksHyper(pwszDetails, bstrText);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::GetItemComment()
|
|
{
|
|
CComBSTR bstrDesc, bstrComment;
|
|
HRESULT hr = GetItemInfo(IDS_COMMENT_COL, L"Comment", bstrDesc, bstrComment);
|
|
|
|
if (SUCCEEDED(hr) && (bstrComment.Length() > 0))
|
|
{
|
|
m_bstrInfoHTML += OLESTR("<p><div class = Message>");
|
|
m_bstrInfoHTML += bstrComment;
|
|
m_bstrInfoHTML += OLESTR("</div>");
|
|
m_bFoundComment = TRUE;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::GetItemHTMLInfoTip()
|
|
{
|
|
CComBSTR bstrDesc, bstrHTMLInfoTipFile;
|
|
HRESULT hr = GetItemInfo(0, L"HTMLInfoTipFile", bstrDesc, bstrHTMLInfoTipFile);
|
|
|
|
if (SUCCEEDED(hr) && (bstrHTMLInfoTipFile.Length() > 0))
|
|
{
|
|
m_bstrInfoHTML += OLESTR("<br><p><iframe FRAMEBORDER=0 class=Message src=\"");
|
|
m_bstrInfoHTML += bstrHTMLInfoTipFile;
|
|
m_bstrInfoHTML += OLESTR("\"></iframe>");
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::GetItemInfo(long lResId, LPWSTR wszInfoDescCanonical, CComBSTR& bstrInfoDesc, CComBSTR& bstrInfo)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
WCHAR wszInfoDesc[MAX_PATH];
|
|
|
|
LoadStringW(_Module.GetResourceInstance(), lResId, wszInfoDesc, ARRAYSIZE(wszInfoDesc));
|
|
bstrInfoDesc = wszInfoDesc;
|
|
|
|
if (m_spFolderItem2)
|
|
{
|
|
CComBSTR bstrInfoDescCanonical = wszInfoDescCanonical;
|
|
CComVariant var;
|
|
hr = m_spFolderItem2->ExtendedProperty(bstrInfoDescCanonical, &var);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
WCHAR wszTemp[80];
|
|
|
|
if (var.vt == VT_BSTR)
|
|
{
|
|
// Of the three types of data we care about one is dangerous. The BSTR data that
|
|
// we read from the file could contain HTML code which we would render in WebView.
|
|
// This could cause potential security problems. To get around this we sanatize
|
|
// the BSTR before we return it. We need to do the following replacements:
|
|
//
|
|
// original replace with
|
|
// < <
|
|
// > >
|
|
// " " <= this would be paranoid and isn't 100% critical
|
|
// ' ‘ <= this would be paranoid and isn't 100% critical
|
|
|
|
LPWSTR psz = var.bstrVal;
|
|
LPWSTR pszBad;
|
|
|
|
if (psz == NULL)
|
|
{
|
|
// we probably cant depend on hr and the out param matching (since this is
|
|
// scriptable and therefore must return success)
|
|
psz = L"";
|
|
}
|
|
|
|
while (pszBad = StrPBrkW(psz, L"<>"))
|
|
{
|
|
// store the bad character
|
|
WCHAR chBadChar = *pszBad;
|
|
|
|
// null the string
|
|
*pszBad = NULL;
|
|
|
|
// add the good part of the string, if there is any
|
|
if ( *psz )
|
|
bstrInfo += psz;
|
|
|
|
// based on which bad character we found add the correct HTLM special character code
|
|
switch ( chBadChar )
|
|
{
|
|
case L'<':
|
|
bstrInfo += L"<";
|
|
break;
|
|
|
|
case L'>':
|
|
bstrInfo += L">";
|
|
break;
|
|
}
|
|
|
|
// Advance the psz pointer. Note it might be an empty string after this.
|
|
psz = pszBad+1;
|
|
}
|
|
|
|
// Add the remaining portion of the good string, even if it's an empty string.
|
|
// bstrInfo is passed in uninitialized so we need to set it to something even
|
|
// if that something is an empty string.
|
|
bstrInfo += psz;
|
|
}
|
|
else if (var.vt == VT_DATE)
|
|
{
|
|
SYSTEMTIME st;
|
|
FILETIME ft;
|
|
|
|
if (VariantTimeToSystemTime(var.date, &st)
|
|
&& SystemTimeToFileTime(&st, &ft)
|
|
&& SHFormatDateTimeW(&ft, &m_dwDateFlags, wszTemp, ARRAYSIZE(wszTemp)))
|
|
{
|
|
bstrInfo += wszTemp;
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
else if (var.vt == VT_UI8 && StrCmpIW(wszInfoDescCanonical, L"size") == 0)
|
|
{
|
|
StrFormatByteSize64(var.ullVal, wszTemp, ARRAYSIZE(wszTemp));
|
|
bstrInfo += wszTemp;
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::NoneSelected()
|
|
{
|
|
WCHAR wszIntro[MAX_PATH];
|
|
CComPtr<FolderItem> spFolderItem;
|
|
|
|
if (!m_bCSCDisplayed)
|
|
{
|
|
CSCShowStatusInfo();
|
|
m_bCSCDisplayed = TRUE;
|
|
}
|
|
if (m_spFolderItems->Item(CComVariant(0), &spFolderItem) == S_OK)
|
|
{ // This filelist has atleast one item.
|
|
IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_PROMPT, wszIntro, ARRAYSIZE(wszIntro)), E_FAIL);
|
|
}
|
|
else
|
|
{
|
|
IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_EMPTY, wszIntro, ARRAYSIZE(wszIntro)), E_FAIL);
|
|
}
|
|
m_bstrInfoHTML += wszIntro;
|
|
spFolderItem = NULL;
|
|
|
|
if (SUCCEEDED(m_spFolder2->get_Self(&spFolderItem)))
|
|
{
|
|
m_spFolderItem = spFolderItem;
|
|
m_spFolderItem->QueryInterface(IID_FolderItem2, (void **)&m_spFolderItem2);
|
|
m_bFoundAuthor = FALSE;
|
|
m_bFoundComment = FALSE;
|
|
|
|
// Get the comment for the item
|
|
GetItemComment();
|
|
GetItemHTMLInfoTip();
|
|
|
|
DealWithDriveInfo();
|
|
|
|
GetCrossLinks();
|
|
|
|
m_spFolderItem2 = NULL;
|
|
m_spFolderItem = NULL;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
#define MAX_SELECTEDFILES_FOR_COMPUTING_SIZE 100
|
|
#define MAX_SELECTEDFILES_FOR_DISPLAYING_NAMES 16
|
|
|
|
HRESULT CFileListWrapper::MultipleSelected(long cSelection)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
if (cSelection > 1)
|
|
{
|
|
WCHAR wszTemp[MAX_PATH];
|
|
|
|
wnsprintfW(wszTemp, ARRAYSIZE(wszTemp), L"%ld", cSelection);
|
|
m_bstrInfoHTML += wszTemp;
|
|
IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_MULTIPLE, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
|
|
m_bstrInfoHTML += wszTemp;
|
|
if (cSelection <= MAX_SELECTEDFILES_FOR_COMPUTING_SIZE)
|
|
{
|
|
m_bstrInfoHTML += OLESTR("<p>");
|
|
|
|
CComPtr<FolderItem> spFolderItem;
|
|
long lSize = 0;
|
|
|
|
for (int i = 0; i < cSelection; i++)
|
|
{
|
|
long lTempSize;
|
|
if (SUCCEEDED(m_spFolderItems->Item(CComVariant(i), &spFolderItem)))
|
|
{
|
|
if (SUCCEEDED(spFolderItem->get_Size(&lTempSize)))
|
|
{
|
|
lSize += lTempSize;
|
|
}
|
|
spFolderItem = NULL;
|
|
}
|
|
}
|
|
if (lSize > 0L)
|
|
{
|
|
IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_FILESIZE, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
|
|
m_bstrInfoHTML += wszTemp;
|
|
StrFormatByteSizeW(lSize, wszTemp, ARRAYSIZE(wszTemp));
|
|
m_bstrInfoHTML += wszTemp;
|
|
m_bstrInfoHTML += OLESTR("<p>");
|
|
}
|
|
if (cSelection <= MAX_SELECTEDFILES_FOR_DISPLAYING_NAMES)
|
|
{
|
|
CComBSTR bstrTemp;
|
|
for (int i = 0; i < cSelection; i++)
|
|
{
|
|
if (SUCCEEDED(m_spFolderItems->Item(CComVariant(i), &spFolderItem)))
|
|
{
|
|
if (SUCCEEDED(spFolderItem->get_Name(&bstrTemp)))
|
|
{
|
|
m_bstrInfoHTML += "<br>";
|
|
m_bstrInfoHTML += bstrTemp;
|
|
bstrTemp.Empty();
|
|
}
|
|
spFolderItem = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::OneSelected()
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
m_bFoundAuthor = FALSE;
|
|
m_bFoundComment = FALSE;
|
|
|
|
// Get the name of the item, making it a hyper-link if appropriate.
|
|
GetItemNameForDisplay();
|
|
|
|
// Get the type of the item
|
|
GetItemType();
|
|
|
|
if (!m_bPathIsSlow)
|
|
{
|
|
// Get the comment for the item
|
|
GetItemComment();
|
|
|
|
// Get the HTMLInfoTip
|
|
GetItemHTMLInfoTip();
|
|
|
|
// Get the date/time stamp on the item
|
|
GetItemDateTime();
|
|
|
|
// Get the size of the item
|
|
GetItemSize();
|
|
|
|
// Get the attributes (hidden, RO etc.) of the item
|
|
GetItemAttributes();
|
|
|
|
// Get the author of the document
|
|
GetItemAuthor();
|
|
|
|
DealWithDriveInfo();
|
|
}
|
|
hr = S_OK;
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::OnCSCClick()
|
|
{
|
|
HRESULT hres = E_FAIL;
|
|
CComPtr<Folder> spFolder;
|
|
CComPtr<Folder2> spFolder2;
|
|
|
|
if (m_spFileList && SUCCEEDED(m_spFileList->get_Folder(&spFolder))
|
|
&& SUCCEEDED(spFolder->QueryInterface(IID_Folder2, (void **)&spFolder2)))
|
|
{
|
|
m_spFolder2 = spFolder2;
|
|
hres = CSCShowStatus_FoldExpand_Toggle();
|
|
m_spFolder2 = NULL;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::OnCSCMouseOnOff(BOOL fOn)
|
|
{
|
|
CComPtr<IHTMLStyle> psPlusMin;
|
|
CComPtr<IHTMLStyle> psText;
|
|
HRESULT hres = E_FAIL;
|
|
|
|
// If we're already in this state don't do anything
|
|
if (m_bHotTracked == fOn)
|
|
return S_OK;
|
|
|
|
// If we receive a 'mouse on' but the element is not one we want to track or if we receive a 'mouse off' but
|
|
// the mouse is over one of our other elements that we want to hot track then don't do anything.
|
|
if (m_spWindow)
|
|
{
|
|
CComPtr<IHTMLEventObj> phtmlevent;
|
|
CComPtr<IHTMLElement> phtmlelement;
|
|
CComBSTR bstrId;
|
|
|
|
if (SUCCEEDED(m_spWindow->get_event(&phtmlevent)) && phtmlevent)
|
|
{
|
|
HRESULT hres;
|
|
|
|
if (!fOn)
|
|
hres = phtmlevent->get_toElement(&phtmlelement);
|
|
else
|
|
hres = phtmlevent->get_srcElement(&phtmlelement);
|
|
|
|
if (SUCCEEDED(hres) && phtmlelement && SUCCEEDED(phtmlelement->get_id(&bstrId)) && (bstrId.Length() > 0))
|
|
{
|
|
BOOL bContainsCSC;
|
|
|
|
bContainsCSC = (StrStrIW(bstrId, L"CSC") != NULL);
|
|
|
|
if (bContainsCSC != fOn)
|
|
return S_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_spCSCPlusMin && m_spCSCText && SUCCEEDED(hres = m_spCSCPlusMin->get_style(&psPlusMin)) && SUCCEEDED(hres = m_spCSCText->get_style(&psText)))
|
|
{
|
|
CComVariant vcolorBlack (OLESTR("black"));
|
|
CComBSTR bstrCSCPlusMin;
|
|
LPOLESTR pstrCursor = (fOn ? OLESTR("hand") : OLESTR("auto"));
|
|
CComVariant vcolorLink;
|
|
|
|
m_bHotTracked = fOn;
|
|
|
|
m_spDocument->get_linkColor(&vcolorLink);
|
|
|
|
if (m_bExpanded)
|
|
bstrCSCPlusMin = fOn ? CSC_MINUSHOT : CSC_MINUSCOLD;
|
|
else
|
|
bstrCSCPlusMin = fOn ? CSC_PLUSHOT : CSC_PLUSCOLD;
|
|
m_spCSCPlusMin->put_innerHTML(bstrCSCPlusMin);
|
|
|
|
psPlusMin->put_cursor(pstrCursor);
|
|
psText->put_color(fOn ? vcolorLink : vcolorBlack);
|
|
psText->put_cursor(pstrCursor);
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::CSCSynchronize()
|
|
{
|
|
HRESULT hres = E_FAIL;
|
|
CComPtr<Folder> spFolder;
|
|
CComPtr<Folder2> spFolder2;
|
|
|
|
if (m_spFileList && SUCCEEDED(m_spFileList->get_Folder(&spFolder))
|
|
&& SUCCEEDED(spFolder->QueryInterface(IID_Folder2, (void **)&spFolder2)))
|
|
{
|
|
hres = spFolder2->Synchronize();
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
const UINT c_ids_uiCSCText[] =
|
|
{IDS_CSC_ONLINE, IDS_CSC_OFFLINE, IDS_CSC_SERVERAVAILABLE, IDS_CSC_DIRTYCACHE};
|
|
|
|
HRESULT CFileListWrapper::CSCGetStatusText(LONG lStatus, CComBSTR& bstrCSCText)
|
|
{
|
|
WCHAR wszTemp[MAX_PATH];
|
|
if ((lStatus >= 0) && (lStatus < ARRAYSIZE(c_ids_uiCSCText))
|
|
&& LoadStringW(_Module.GetResourceInstance(), c_ids_uiCSCText[(int)lStatus], wszTemp, ARRAYSIZE(wszTemp)))
|
|
{
|
|
bstrCSCText += wszTemp;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
const UINT c_ids_uiCSCDetail[] =
|
|
{IDS_CSC_DETAIL_ONLINE, IDS_CSC_DETAIL_OFFLINE, IDS_CSC_DETAIL_SERVERAVAILABLE, IDS_CSC_DETAIL_DIRTYCACHE};
|
|
|
|
HRESULT CFileListWrapper::CSCGetStatusDetail(LONG lStatus, CComBSTR& bstrCSCDetail)
|
|
{
|
|
WCHAR wszTemp[MAX_PATH];
|
|
if ((lStatus >= 0) && (lStatus < ARRAYSIZE(c_ids_uiCSCDetail))
|
|
&& LoadStringW(_Module.GetResourceInstance(), c_ids_uiCSCDetail[(int)lStatus], wszTemp, ARRAYSIZE(wszTemp)))
|
|
{
|
|
bstrCSCDetail += wszTemp;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
#define CSC_STATUS_ONLINE 0
|
|
#define CSC_STATUS_OFFLINE 1
|
|
#define CSC_STATUS_SERVERAVAILABLE 2
|
|
#define CSC_STATUS_DIRTYCACHE 3
|
|
|
|
HRESULT CFileListWrapper::CSCGetStatusButton(LONG lStatus, CComBSTR& bstrCSCButton)
|
|
{
|
|
if ((lStatus == CSC_STATUS_SERVERAVAILABLE) || (lStatus == CSC_STATUS_DIRTYCACHE))
|
|
{
|
|
bstrCSCButton += OLESTR("<p class=Button><button onclick=\'WVCoord.CSCSynchronize()\'>");
|
|
WCHAR wszTemp[MAX_PATH];
|
|
LoadStringW(_Module.GetResourceInstance(), IDS_CSC_SYNCHRONIZE, wszTemp, ARRAYSIZE(wszTemp));
|
|
bstrCSCButton += wszTemp;
|
|
bstrCSCButton += OLESTR("</button>");
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::GetCSCFolderStatus(LONG* plStatus)
|
|
{
|
|
return m_spFolder2 ? m_spFolder2->get_OfflineStatus(plStatus) : E_FAIL;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::CSCShowStatusInfo()
|
|
{
|
|
LONG lStatus;
|
|
|
|
if (m_spCSCText && m_spCSCPlusMin && m_spCSCDetail && m_spCSCButton && m_spCSCStyle
|
|
&& m_spCSCDetailStyle && m_spCSCButtonStyle)
|
|
{
|
|
CComBSTR bstrCSC_Display;
|
|
if (SUCCEEDED(GetCSCFolderStatus(&lStatus)) && (lStatus >= 0))
|
|
{
|
|
CComBSTR bstrCSCText;
|
|
CSCGetStatusText(lStatus, bstrCSCText);
|
|
bstrCSCText += OLESTR("<br>");
|
|
|
|
CComBSTR bstrCSCPlusMin;
|
|
CComBSTR bstrCSCDetail;
|
|
CComBSTR bstrCSCDetail_Display;
|
|
|
|
if (m_bExpanded)
|
|
{
|
|
bstrCSCPlusMin = m_bHotTracked ? CSC_MINUSHOT : CSC_MINUSCOLD;
|
|
bstrCSCText += OLESTR("<br>");
|
|
|
|
CSCGetStatusDetail(lStatus, bstrCSCDetail);
|
|
bstrCSCDetail += OLESTR("<br>");
|
|
|
|
bstrCSCDetail_Display = OLESTR("");
|
|
|
|
if (m_bRTLDocument)
|
|
{
|
|
// [msadek]; Life would be easier if the object model has exposed
|
|
// right offset through get_offsetRight().
|
|
|
|
CComPtr<IHTMLControlElement> spDocBody = NULL;
|
|
long lOffsetLeft, lOffsetWidth, lClientWidth, lOffsetRight = 0;
|
|
|
|
if (SUCCEEDED(m_spCSCText->QueryInterface(IID_IHTMLControlElement, (void **)&spDocBody))
|
|
&& SUCCEEDED(m_spCSCText->get_offsetLeft(&lOffsetLeft))
|
|
&& SUCCEEDED(m_spCSCText->get_offsetWidth(&lOffsetWidth))
|
|
&& SUCCEEDED(spDocBody->get_clientWidth(&lClientWidth)))
|
|
{
|
|
lOffsetRight = lClientWidth - (lOffsetLeft + lOffsetWidth);
|
|
}
|
|
m_spCSCDetailStyle->put_marginRight(CComVariant(lOffsetRight - 10L));
|
|
}
|
|
else
|
|
{
|
|
long lOffsetLeft;
|
|
if (FAILED(m_spCSCText->get_offsetLeft(&lOffsetLeft)))
|
|
{
|
|
lOffsetLeft = 0;
|
|
}
|
|
m_spCSCDetailStyle->put_marginLeft(CComVariant(lOffsetLeft - 10L));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bstrCSCPlusMin = m_bHotTracked ? CSC_PLUSHOT : CSC_PLUSCOLD;
|
|
bstrCSCDetail += OLESTR("");
|
|
bstrCSCDetail_Display = OLESTR("none");
|
|
}
|
|
m_spCSCPlusMin->put_innerHTML(bstrCSCPlusMin);
|
|
m_spCSCText->put_innerHTML(bstrCSCText);
|
|
m_spCSCDetail->put_innerHTML(bstrCSCDetail);
|
|
m_spCSCDetailStyle->put_display(bstrCSCDetail_Display);
|
|
|
|
CComBSTR bstrCSCButton_Display;
|
|
CComBSTR bstrCSCButton;
|
|
if (SUCCEEDED(CSCGetStatusButton(lStatus, bstrCSCButton)) && (bstrCSCButton.Length() > 0))
|
|
{
|
|
bstrCSCButton_Display = OLESTR("");
|
|
}
|
|
else
|
|
{
|
|
bstrCSCButton = OLESTR("");
|
|
bstrCSCButton_Display = OLESTR("none");
|
|
}
|
|
m_spCSCButton->put_innerHTML(bstrCSCButton);
|
|
m_spCSCButtonStyle->put_display(bstrCSCButton_Display);
|
|
bstrCSC_Display = OLESTR("");
|
|
}
|
|
else
|
|
{
|
|
bstrCSC_Display = OLESTR("none");
|
|
}
|
|
m_spCSCStyle->put_display(bstrCSC_Display);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFileListWrapper::CSCShowStatus_FoldExpand_Toggle()
|
|
{
|
|
m_bExpanded = !m_bExpanded;
|
|
return (CSCShowStatusInfo());
|
|
}
|
|
|
|
// fEnter true for mouseover, focus; false for mouseout, blur
|
|
HRESULT CFileListWrapper::OnWebviewLinkEvent( BOOL fEnter )
|
|
{
|
|
CComPtr<IHTMLEventObj> spEvent;
|
|
CComPtr<IHTMLElement> spAnchor;
|
|
HRESULT hr;
|
|
|
|
// NT# 354743, IHTMLEventObj::get_event() can return S_OK and
|
|
// not set the out param, so we need to protect against that.
|
|
spEvent = NULL;
|
|
hr = m_spWindow->get_event(&spEvent);
|
|
|
|
// Automation interfaces sometimes return S_FALSE on failures to prevent scripting errors
|
|
if (S_OK == hr)
|
|
{
|
|
// Sometimes Trident will not set the out parameter when it returns S_OK, so
|
|
// we need to make sure it's not NULL.
|
|
if (spEvent)
|
|
{
|
|
hr = GetEventAnchorElement(spEvent, &spAnchor);
|
|
}
|
|
else
|
|
hr = E_FAIL;
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
if (fEnter)
|
|
{
|
|
CComBSTR bstrTitle;
|
|
|
|
hr = spAnchor->get_title(&bstrTitle);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
m_spWindow->put_status(bstrTitle);
|
|
}
|
|
|
|
spEvent->put_returnValue(CComVariant(true));
|
|
}
|
|
else
|
|
{
|
|
hr = m_spWindow->put_status(OLESTR(""));
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Walks up the component chain from the event source, looking for
|
|
// an anchor element. Returns S_OK if successful, some error otherwise.
|
|
// On failure *ppElt will be set to null. Note that this gives back
|
|
// the IHTMLElement that corresponds to the anchor, not the
|
|
// IHTMLAnchorElement, as only IHTMLElement has get_title
|
|
HRESULT CFileListWrapper::GetEventAnchorElement( IHTMLEventObj *pEvent,
|
|
IHTMLElement **ppElt )
|
|
{
|
|
CComPtr<IHTMLElement> spElement;
|
|
|
|
*ppElt = NULL;
|
|
|
|
if( SUCCEEDED( pEvent->get_srcElement( &spElement )))
|
|
{
|
|
BOOL fContinue = TRUE;
|
|
while( fContinue && spElement )
|
|
{
|
|
CComPtr<IHTMLAnchorElement> spAnchor;
|
|
|
|
if( SUCCEEDED( spElement->QueryInterface( IID_IHTMLAnchorElement,
|
|
reinterpret_cast<void**>( &spAnchor ))))
|
|
{
|
|
fContinue = false;
|
|
*ppElt = spElement;
|
|
reinterpret_cast<IUnknown*>( *ppElt )->AddRef();
|
|
}
|
|
else
|
|
{
|
|
IHTMLElement *pIElt = NULL;
|
|
|
|
if( SUCCEEDED( spElement->get_parentElement( &pIElt )))
|
|
{
|
|
spElement = pIElt;
|
|
if (pIElt)
|
|
{
|
|
pIElt->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
spElement.Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ( *ppElt ? S_OK : E_FAIL );
|
|
}
|
|
|
|
// Bind to the connection points for each of the link elements
|
|
// contained within m_spLinks. The advise cookie for each link
|
|
// is stored as an attribute within the link, so we don't need
|
|
// to maintain a mapping between links and elements.
|
|
// fAdvise -- true to make connections, false to break
|
|
HRESULT CFileListWrapper::AdviseWebviewLinks( BOOL fAdvise)
|
|
{
|
|
CComPtr<IDispatch> spDisp;
|
|
CComPtr<IHTMLElement> spElement;
|
|
CComPtr<IHTMLElementCollection> spCollection;
|
|
CComVariant vtEmpty;
|
|
CComBSTR bstrAttr = WV_LINKNAME;
|
|
long cLinks;
|
|
DWORD dwCookie;
|
|
HRESULT hr;
|
|
|
|
IfFailRet( GetWVLinksCollection( &spCollection, &cLinks ));
|
|
|
|
for( long i = 0; i < cLinks; i++ )
|
|
{
|
|
hr = spCollection->item( CComVariant( i ), vtEmpty, &spDisp );
|
|
if (!spDisp)
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
if( SUCCEEDED( hr ))
|
|
{
|
|
hr = spDisp->QueryInterface( IID_IHTMLElement,
|
|
reinterpret_cast<void**>( &spElement ));
|
|
spDisp.Release();
|
|
}
|
|
|
|
if( SUCCEEDED( hr ))
|
|
{
|
|
if( fAdvise )
|
|
{
|
|
hr = AtlAdvise( spElement, this, IID_IDispatch, &dwCookie );
|
|
if( SUCCEEDED( hr ))
|
|
{
|
|
hr = spElement->setAttribute( bstrAttr,
|
|
CComVariant( static_cast<long>( dwCookie )),
|
|
VARIANT_FALSE );
|
|
|
|
if( FAILED( hr ))
|
|
{
|
|
AtlUnadvise( spElement, IID_IDispatch, dwCookie );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CComVariant vtCookie;
|
|
|
|
hr = spElement->getAttribute( bstrAttr, FALSE, &vtCookie );
|
|
if( SUCCEEDED( hr ))
|
|
{
|
|
dwCookie = static_cast<DWORD>( vtCookie.lVal );
|
|
AtlUnadvise( spElement, IID_IDispatch, dwCookie );
|
|
}
|
|
}
|
|
|
|
spElement.Release();
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// Get the IHTMLElementCollection that holds the named links
|
|
HRESULT CFileListWrapper::GetWVLinksCollection( IHTMLElementCollection **ppCollection,
|
|
long *pcLinks )
|
|
{
|
|
CComPtr<IDispatch> spDisp;
|
|
CComPtr<IHTMLElementCollection> spCollection;
|
|
CComVariant vtEmpty;
|
|
HRESULT hr;
|
|
|
|
ASSERT( ppCollection );
|
|
ASSERT( pcLinks );
|
|
|
|
*ppCollection = NULL;
|
|
*pcLinks = 0;
|
|
|
|
if (!m_spLinks) return E_FAIL;
|
|
|
|
// Get the initial element collection from m_spLinks
|
|
IfFailRet( m_spLinks->get_all( &spDisp ));
|
|
IfFailRet( spDisp->QueryInterface( IID_IHTMLElementCollection,
|
|
reinterpret_cast<void**>( &spCollection )));
|
|
spDisp.Release();
|
|
|
|
// Get the collection of elements with our linkname. If nothing exists, spDisp
|
|
// will be null and item returns S_OK.
|
|
IfFailRet( spCollection->item( CComVariant( WV_LINKNAME ), vtEmpty, &spDisp ));
|
|
if( !spDisp ) return E_FAIL;
|
|
|
|
IfFailRet( spDisp->QueryInterface( IID_IHTMLElementCollection,
|
|
reinterpret_cast<void**>( ppCollection )));
|
|
|
|
return reinterpret_cast<IHTMLElementCollection*>( *ppCollection )->get_length( pcLinks );
|
|
}
|