Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1593 lines
52 KiB

  1. // wvcoord.cpp : Implementation of CWebViewCoord
  2. #include "priv.h"
  3. #include "wvcoord.h"
  4. #include "shdispid.h"
  5. /////////////////////////////////////////////////////////////////////////////
  6. // String Constants
  7. /////////////////////////////////////////////////////////////////////////////
  8. #define CSC_PLUSCOLD L"<img id=CSCBmp align=middle src=pluscold.gif>"
  9. #define CSC_PLUSHOT L"<img id=CSCBmp align=middle src=plushot.gif>"
  10. #define CSC_MINUSCOLD L"<img id=CSCBmp align=middle src=mincold.gif>"
  11. #define CSC_MINUSHOT L"<img id=CSCBmp align=middle src=minhot.gif>"
  12. #define WV_LINKNAME L"WVLink"
  13. /////////////////////////////////////////////////////////////////////////////
  14. // CFileListWrapper
  15. /////////////////////////////////////////////////////////////////////////////
  16. CFileListWrapper::CFileListWrapper()
  17. {
  18. m_pThumbNailWrapper = NULL;
  19. m_bCSCDisplayed = FALSE;
  20. m_bExpanded = FALSE;
  21. m_bHotTracked = FALSE;
  22. m_dwDateFlags = FDTF_DEFAULT; // default
  23. m_bRTLDocument = FALSE; // default
  24. }
  25. #define MYDOCS_CLSID L"{450d8fba-ad25-11d0-98a8-0800361b1103}" // CLSID_MyDocuments
  26. HRESULT GetFolderIDList(int nFolder, LPITEMIDLIST* ppidlFolder)
  27. {
  28. HRESULT hr = E_FAIL;
  29. if (nFolder == CSIDL_PERSONAL)
  30. {
  31. hr = SHILCreateFromPath(L"::" MYDOCS_CLSID, ppidlFolder, NULL);
  32. }
  33. else
  34. {
  35. hr = SHGetSpecialFolderLocation(NULL, nFolder, ppidlFolder);
  36. }
  37. return hr;
  38. }
  39. HRESULT CFileListWrapper::IsItThisFolder(int nFolder, BOOL& bResult, LPWSTR pwszDisplayName, DWORD cchDisplayName, LPWSTR pwszUrlPath, DWORD cchUrlPath)
  40. {
  41. HRESULT hr = E_FAIL;
  42. LPITEMIDLIST pidlFolder = NULL, pidlLast = NULL;
  43. CComPtr<IShellFolder> psfParent;
  44. STRRET strret;
  45. CComBSTR bstrTemp;
  46. WCHAR wszPath[MAX_PATH];
  47. if (SUCCEEDED(GetFolderIDList(nFolder, &pidlFolder))
  48. && SUCCEEDED(SHBindToIDListParent(pidlFolder, IID_IShellFolder, (void**)&psfParent, (LPCITEMIDLIST*)&pidlLast))
  49. && SUCCEEDED(psfParent->GetDisplayNameOf(pidlLast, SHGDN_NORMAL, &strret))
  50. && SUCCEEDED(StrRetToBufW(&strret, pidlFolder, pwszDisplayName, cchDisplayName))
  51. && SUCCEEDED(psfParent->GetDisplayNameOf(pidlLast, SHGDN_FORPARSING, &strret))
  52. && SUCCEEDED(StrRetToBufW(&strret, pidlFolder, wszPath, ARRAYSIZE(wszPath)))
  53. && SUCCEEDED(m_spFolderItem->get_Path(&bstrTemp)) && (bstrTemp.Length() > 0))
  54. {
  55. hr = S_OK;
  56. bResult = (StrCmpIW(bstrTemp, wszPath) == 0);
  57. if (CSIDL_PERSONAL == nFolder)
  58. {
  59. // Change the URL for mydocs (after comparing with the path) so that it
  60. // is a CLSID URL instead of the file system path
  61. StrCpyNW(wszPath, L"::" MYDOCS_CLSID, ARRAYSIZE(wszPath));
  62. }
  63. UrlCreateFromPathW(wszPath, pwszUrlPath, &cchUrlPath, 0);
  64. }
  65. if (pidlFolder)
  66. {
  67. ILFree(pidlFolder);
  68. }
  69. return hr;
  70. }
  71. HRESULT CFileListWrapper::GetIMediaPlayer(CComPtr<IMediaPlayer>& spIMediaPlayer)
  72. {
  73. // The MediaPlayer objects has too many bugs. So, let's disable it.
  74. #if 0
  75. if (!m_spIMediaPlayer)
  76. {
  77. if (m_spMediaPlayerSpan)
  78. {
  79. 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>"));
  80. }
  81. CComPtr<IHTMLElementCollection> spDocAll;
  82. CComVariant vEmpty;
  83. CComPtr<IDispatch> spdispItem;
  84. if (SUCCEEDED(m_spDocument->get_all(&spDocAll)) && SUCCEEDED(spDocAll->item(CComVariant(OLESTR("MediaPlayer")), vEmpty, &spdispItem)) && spdispItem)
  85. {
  86. if (FAILED(FindObjectStyle(spdispItem, m_spMediaPlayerStyle)))
  87. {
  88. m_spMediaPlayerStyle = NULL;
  89. }
  90. if (FAILED(spdispItem->QueryInterface(IID_IMediaPlayer, (void **)&m_spIMediaPlayer)))
  91. {
  92. m_spIMediaPlayer = NULL;
  93. }
  94. else
  95. {
  96. m_spIMediaPlayer->put_EnableContextMenu(VARIANT_FALSE);
  97. }
  98. spdispItem = NULL;
  99. }
  100. spDocAll = NULL;
  101. }
  102. #endif
  103. spIMediaPlayer = m_spIMediaPlayer;
  104. return spIMediaPlayer ? S_OK : E_FAIL;
  105. }
  106. HRESULT CFileListWrapper::FormatCrossLink(LPCWSTR pwszDisplayName, LPCWSTR pwszUrlPath, UINT uIDToolTip)
  107. {
  108. m_bstrCrossLinksHTML += OLESTR("<p class=Half><a href=\"");
  109. m_bstrCrossLinksHTML += pwszUrlPath;
  110. m_bstrCrossLinksHTML += OLESTR("\"");
  111. WCHAR wszToolTip[MAX_PATH];
  112. wszToolTip[0] = L'\0';
  113. if (LoadStringW(_Module.GetResourceInstance(), uIDToolTip, wszToolTip, ARRAYSIZE(wszToolTip)) > 0)
  114. {
  115. m_bstrCrossLinksHTML += OLESTR(" title=\"");
  116. m_bstrCrossLinksHTML += wszToolTip;
  117. m_bstrCrossLinksHTML += OLESTR("\"");
  118. }
  119. m_bstrCrossLinksHTML += OLESTR(" name=\"");
  120. m_bstrCrossLinksHTML += WV_LINKNAME;
  121. m_bstrCrossLinksHTML += OLESTR("\"");
  122. m_bstrCrossLinksHTML += OLESTR(">");
  123. m_bstrCrossLinksHTML += pwszDisplayName;
  124. m_bstrCrossLinksHTML += OLESTR("</a>");
  125. return S_OK;
  126. }
  127. HRESULT CFileListWrapper::GetCrossLink(int nFolder, UINT uIDToolTip)
  128. {
  129. HRESULT hres = E_FAIL; // Assume error
  130. // Get the links.
  131. WCHAR wszDisplayName[MAX_PATH], wszUrlPath[MAX_PATH];
  132. BOOL bThisFolder;
  133. if (SUCCEEDED(IsItThisFolder(nFolder, bThisFolder, wszDisplayName, ARRAYSIZE(wszDisplayName), wszUrlPath, ARRAYSIZE(wszUrlPath)))
  134. && !bThisFolder)
  135. {
  136. hres = FormatCrossLink(wszDisplayName, wszUrlPath, uIDToolTip);
  137. }
  138. return hres;
  139. }
  140. HRESULT CFileListWrapper::GetCrossLinks()
  141. {
  142. WCHAR wszSeeAlso[MAX_PATH];
  143. m_bstrCrossLinksHTML += OLESTR("<p>");
  144. LoadStringW(_Module.GetResourceInstance(), IDS_SEEALSO, wszSeeAlso, ARRAYSIZE(wszSeeAlso));
  145. m_bstrCrossLinksHTML += wszSeeAlso;
  146. GetCrossLink(CSIDL_PERSONAL, IDS_MYDOCSTEXT);
  147. if (!SHRestricted(REST_NONETHOOD))
  148. {
  149. GetCrossLink(CSIDL_NETWORK, IDS_MYNETPLACESTEXT);
  150. }
  151. if (FAILED(GetCrossLink(CSIDL_DRIVES, IDS_MYCOMPTEXT)) && !SHRestricted(REST_NONETHOOD))
  152. {
  153. // This is the My Computer folder - Add a link to Network and Dial-up Connections folder
  154. WCHAR wszNDC[MAX_PATH];
  155. wszNDC[0] = L'\0';
  156. LoadStringW(_Module.GetResourceInstance(), IDS_NDC, wszNDC, ARRAYSIZE(wszNDC));
  157. FormatCrossLink(wszNDC, L"shell:ConnectionsFolder", IDS_NDCTEXT);
  158. }
  159. return S_OK;
  160. }
  161. // The Media Player folks haven't published the IMediaPlayer interface, so I define it here.
  162. // Should strip it out when their declaration makes it to the public headers.
  163. const IID IID_IMediaPlayer = {0x22D6F311,0xB0F6,0x11D0,{0x94,0xAB,0x00,0x80,0xC7,0x4C,0x7E,0x95}};
  164. HRESULT CFileListWrapper::Init(
  165. CComPtr<IShellFolderViewDual> spFileList,
  166. CComPtr<IHTMLElement> spInfo,
  167. CComPtr<IHTMLElement> spLinks,
  168. CComPtr<IHTMLStyle> spPanelStyle,
  169. CComPtr<IHTMLElement> spMediaPlayerSpan,
  170. CComPtr<IHTMLElement> spCSCPlusMin,
  171. CComPtr<IHTMLElement> spCSCText,
  172. CComPtr<IHTMLElement> spCSCDetail,
  173. CComPtr<IHTMLElement> spCSCButton,
  174. CComPtr<IHTMLStyle> spCSCStyle,
  175. CComPtr<IHTMLStyle> spCSCDetailStyle,
  176. CComPtr<IHTMLStyle> spCSCButtonStyle,
  177. CComPtr<IHTMLDocument2> spDocument,
  178. CComPtr<IHTMLWindow2> spWindow,
  179. CThumbNailWrapper *pThumbNailWrapper)
  180. {
  181. m_spFileList = spFileList;
  182. m_spInfo = spInfo;
  183. m_spLinks = spLinks;
  184. m_spPanelStyle = spPanelStyle;
  185. m_spMediaPlayerSpan = spMediaPlayerSpan;
  186. m_spMediaPlayerStyle = NULL;
  187. m_spIMediaPlayer = NULL;
  188. m_spCSCPlusMin = spCSCPlusMin;
  189. m_spCSCText = spCSCText;
  190. m_spCSCDetail = spCSCDetail;
  191. m_spCSCButton = spCSCButton;
  192. m_spCSCStyle = spCSCStyle;
  193. m_spCSCDetailStyle = spCSCDetailStyle;
  194. m_spCSCButtonStyle = spCSCButtonStyle;
  195. m_spDocument = spDocument;
  196. m_spWindow = spWindow;
  197. m_pThumbNailWrapper = pThumbNailWrapper;
  198. if (m_pThumbNailWrapper)
  199. {
  200. m_pThumbNailWrapper->AddRef();
  201. }
  202. m_bNeverGotPanelInfo = TRUE;
  203. // Find out if the reading order is from right to left
  204. m_dwDateFlags = FDTF_DEFAULT; // default
  205. m_bRTLDocument = IsRTLDocument(m_spDocument); // default
  206. // Get the date format reading order
  207. LCID locale = GetUserDefaultLCID();
  208. if ((PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_ARABIC) ||
  209. (PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_HEBREW))
  210. {
  211. if (m_bRTLDocument)
  212. m_dwDateFlags |= FDTF_RTLDATE;
  213. else
  214. m_dwDateFlags |= FDTF_LTRDATE;
  215. }
  216. m_bPathIsSlow = FALSE; // default
  217. // Make sure that the path is not slow
  218. CComPtr<Folder> spFolder;
  219. CComPtr<Folder2> spFolder2;
  220. CComPtr<FolderItem> spFolderItem;
  221. CComBSTR bstrPath;
  222. if (m_spFileList && SUCCEEDED(m_spFileList->get_Folder(&spFolder))
  223. && SUCCEEDED(spFolder->QueryInterface(IID_Folder2, (void **)&spFolder2))
  224. && SUCCEEDED(spFolder2->get_Self(&spFolderItem))
  225. && SUCCEEDED(spFolderItem->get_Path(&bstrPath)))
  226. {
  227. m_bPathIsSlow = PathIsSlowW(bstrPath, -1);
  228. }
  229. return S_OK;
  230. }
  231. CFileListWrapper::~CFileListWrapper()
  232. {
  233. // Release any objects we are holding references to
  234. m_spFileList = NULL;
  235. m_spInfo = NULL;
  236. m_spLinks = NULL;
  237. m_spPanelStyle = NULL;
  238. m_spIMediaPlayer = NULL;
  239. m_spMediaPlayerSpan = NULL;
  240. m_spMediaPlayerStyle = NULL;
  241. m_spIMediaPlayer = NULL;
  242. m_spCSCPlusMin = NULL;
  243. m_spCSCText = NULL;
  244. m_spCSCDetail = NULL;
  245. m_spCSCButton = NULL;
  246. m_spCSCStyle = NULL;
  247. m_spCSCDetailStyle = NULL;
  248. m_spCSCButtonStyle = NULL;
  249. m_spDocument = NULL;
  250. m_spWindow = NULL;
  251. // Release thumbnail wrapper
  252. if (m_pThumbNailWrapper)
  253. {
  254. m_pThumbNailWrapper->Release();
  255. }
  256. }
  257. STDMETHODIMP CFileListWrapper::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
  258. WORD wFlags, DISPPARAMS *pDispParams,
  259. VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
  260. UINT *puArgErr)
  261. {
  262. HRESULT hr = S_OK;
  263. if (riid != IID_NULL)
  264. {
  265. hr = DISP_E_UNKNOWNINTERFACE;
  266. }
  267. else if (dispIdMember == DISPID_SELECTIONCHANGED)
  268. {
  269. hr = OnSelectionChanged();
  270. }
  271. else if (dispIdMember == DISPID_FILELISTENUMDONE)
  272. {
  273. hr = SetDefaultPanelDisplay();
  274. }
  275. else if (dispIdMember == DISPID_VERBINVOKED ||
  276. dispIdMember == DISPID_BEGINDRAG)
  277. {
  278. hr = StopMediaPlayer();
  279. }
  280. else if (dispIdMember == DISPID_HTMLELEMENTEVENTS_ONMOUSEOVER)
  281. {
  282. hr = OnWebviewLinkEvent( TRUE );
  283. }
  284. else if (dispIdMember == DISPID_HTMLELEMENTEVENTS_ONMOUSEOUT)
  285. {
  286. hr = OnWebviewLinkEvent( FALSE );
  287. }
  288. else if (dispIdMember == DISPID_HTMLELEMENTEVENTS_ONFOCUS)
  289. {
  290. hr = OnWebviewLinkEvent( TRUE );
  291. }
  292. else if (dispIdMember == DISPID_HTMLELEMENTEVENTS_ONBLUR)
  293. {
  294. hr = OnWebviewLinkEvent( FALSE );
  295. }
  296. return hr;
  297. }
  298. HRESULT CFileListWrapper::ClearThumbNail()
  299. {
  300. if (m_pThumbNailWrapper)
  301. {
  302. m_pThumbNailWrapper->ClearThumbNail();
  303. }
  304. return S_OK;
  305. }
  306. HRESULT CFileListWrapper::StopMediaPlayer()
  307. {
  308. if (m_spIMediaPlayer)
  309. {
  310. m_spIMediaPlayer->Stop();
  311. }
  312. return S_OK;
  313. }
  314. HRESULT CFileListWrapper::ClearMediaPlayer()
  315. {
  316. StopMediaPlayer();
  317. if (m_spMediaPlayerStyle)
  318. {
  319. m_spMediaPlayerStyle->put_display(OLESTR("none"));
  320. }
  321. return S_OK;
  322. }
  323. HRESULT CFileListWrapper::OnSelectionChanged()
  324. {
  325. HRESULT hr = S_OK;
  326. if (m_spFileList)
  327. {
  328. // Erase any visible thumbnail since the selection changed
  329. ClearThumbNail();
  330. // Kill any preview
  331. ClearMediaPlayer();
  332. long cSelection = 0;
  333. CComPtr<FolderItems> spFolderItems;
  334. CComPtr<Folder> spFolder;
  335. CComPtr<Folder2> spFolder2;
  336. if (SUCCEEDED(m_spFileList->SelectedItems(&spFolderItems))
  337. && SUCCEEDED(spFolderItems->get_Count(&cSelection))
  338. && SUCCEEDED(m_spFileList->get_Folder(&spFolder))
  339. && SUCCEEDED(spFolder->QueryInterface(IID_Folder2, (void **)&spFolder2)))
  340. {
  341. m_spFolderItems = spFolderItems;
  342. m_spFolder2 = spFolder2;
  343. m_bstrInfoHTML = OLESTR("");
  344. m_bstrCrossLinksHTML = OLESTR("");
  345. if (cSelection == 0)
  346. {
  347. m_spFolderItems = NULL;
  348. if (SUCCEEDED(m_spFolder2->Items(&m_spFolderItems)))
  349. {
  350. // Nothing is selected
  351. hr = NoneSelected();
  352. }
  353. }
  354. else if (cSelection > 1)
  355. {
  356. // More than one item is selected
  357. hr = MultipleSelected(cSelection);
  358. }
  359. else
  360. {
  361. CComPtr<FolderItem> spFolderItem;
  362. if (SUCCEEDED(m_spFolderItems->Item(CComVariant(0), &spFolderItem)))
  363. {
  364. m_spFolderItem = spFolderItem;
  365. m_spFolderItem->QueryInterface(IID_FolderItem2, (void **)&m_spFolderItem2);
  366. // A single item has been selected
  367. hr = OneSelected();
  368. m_spFolderItem2 = NULL;
  369. m_spFolderItem = NULL;
  370. }
  371. }
  372. DisplayInfoHTML();
  373. DisplayCrossLinksHTML();
  374. m_spFolder2 = NULL;
  375. m_spFolderItems = NULL;
  376. }
  377. }
  378. return hr;
  379. }
  380. HRESULT CFileListWrapper::SetDefaultPanelDisplay()
  381. {
  382. CComPtr<Folder> spFolder;
  383. CComPtr<Folder2> spFolder2;
  384. CComPtr<FolderItems> spFolderItems;
  385. if (m_spFileList && SUCCEEDED(m_spFileList->get_Folder(&spFolder))
  386. && SUCCEEDED(spFolder->QueryInterface(IID_Folder2, (void **)&spFolder2))
  387. && SUCCEEDED(spFolder2->Items(&spFolderItems)))
  388. {
  389. m_bstrInfoHTML = OLESTR("");
  390. m_bstrCrossLinksHTML = OLESTR("");
  391. m_spFolderItems = spFolderItems;
  392. m_spFolder2 = spFolder2;
  393. NoneSelected();
  394. DisplayInfoHTML();
  395. DisplayCrossLinksHTML();
  396. m_spFolder2 = NULL;
  397. m_spFolderItems = NULL;
  398. }
  399. return S_OK;
  400. }
  401. HRESULT CFileListWrapper::DisplayInfoHTML()
  402. {
  403. HRESULT hr = S_FALSE;
  404. if (m_spInfo)
  405. {
  406. // Replace Info.innerHTML with the new text
  407. hr = m_spInfo->put_innerHTML(m_bstrInfoHTML);
  408. }
  409. return hr;
  410. }
  411. HRESULT CFileListWrapper::DisplayCrossLinksHTML()
  412. {
  413. HRESULT hr = S_FALSE;
  414. if (m_spLinks)
  415. {
  416. // Break old connections
  417. AdviseWebviewLinks( FALSE );
  418. // Replace Links.innerHTML with the new text
  419. hr = m_spLinks->put_innerHTML(m_bstrCrossLinksHTML);
  420. // Make new connections
  421. AdviseWebviewLinks( TRUE );
  422. }
  423. return hr;
  424. }
  425. BOOL IsExtensionOneOf(LPCWSTR pwszFileName, const LPCWSTR pwszExtList[], int cExtList)
  426. {
  427. BOOL fRet = FALSE;
  428. LPCWSTR pwszExt = PathFindExtensionW(pwszFileName);
  429. if (pwszExt && *pwszExt)
  430. {
  431. for (int i = 0; i < cExtList; i++)
  432. {
  433. if (StrCmpICW(pwszExtList[i], pwszExt + 1) == 0) // Get pwszExt past "."
  434. {
  435. fRet = TRUE;
  436. break;
  437. }
  438. }
  439. }
  440. return fRet;
  441. }
  442. 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"};
  443. BOOL IsMovieFile(LPCWSTR pwszFileName)
  444. {
  445. return IsExtensionOneOf(pwszFileName, c_pwszMovieFileExt, ARRAYSIZE(c_pwszMovieFileExt));
  446. }
  447. 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"};
  448. BOOL IsSoundFile(LPCWSTR pwszFileName)
  449. {
  450. return IsExtensionOneOf(pwszFileName, c_pwszSoundFileExt, ARRAYSIZE(c_pwszSoundFileExt));
  451. }
  452. HRESULT CFileListWrapper::DealWithDriveInfo()
  453. {
  454. CComBSTR bstrPath;
  455. // Update ThumbNail
  456. if (m_pThumbNailWrapper && m_spFolderItem && SUCCEEDED(m_spFolderItem->get_Path(&bstrPath)) && (bstrPath.Length() > 0))
  457. {
  458. BOOL bRootFolder = PathIsRootW(bstrPath);
  459. BOOL bHaveThumbnail = FALSE;
  460. if (!bRootFolder || !PathIsUNCW(bstrPath))
  461. {
  462. bHaveThumbnail = m_pThumbNailWrapper->UpdateThumbNail(m_spFolderItem);
  463. }
  464. if (bHaveThumbnail)
  465. {
  466. if (bRootFolder)
  467. {
  468. WCHAR wszTemp[MAX_PATH];
  469. CComBSTR bstrSpace;
  470. if (SUCCEEDED(m_pThumbNailWrapper->TotalSpace(bstrSpace)))
  471. {
  472. m_bstrInfoHTML += OLESTR("<p><br>");
  473. IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_TOTALSIZE, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
  474. m_bstrInfoHTML += wszTemp;
  475. m_bstrInfoHTML += bstrSpace;
  476. bstrSpace.Empty();
  477. m_bstrInfoHTML += OLESTR("<p>");
  478. }
  479. if (SUCCEEDED(m_pThumbNailWrapper->UsedSpace(bstrSpace)))
  480. {
  481. m_bstrInfoHTML += OLESTR("<p><table class=Legend width=12 height=12 border=1 align=");
  482. if (m_bRTLDocument)
  483. {
  484. m_bstrInfoHTML += OLESTR("right ");
  485. }
  486. else
  487. {
  488. m_bstrInfoHTML += OLESTR("left ");
  489. }
  490. m_bstrInfoHTML += OLESTR("bgcolor=threedface bordercolordark=black bordercolorlight=black>");
  491. m_bstrInfoHTML += OLESTR("<tr><td title=\'");
  492. IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_USEDSPACE_DESC, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
  493. m_bstrInfoHTML += wszTemp;
  494. m_bstrInfoHTML += OLESTR("\'></td></tr></table>&nbsp;");
  495. IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_USEDSPACE, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
  496. m_bstrInfoHTML += wszTemp;
  497. m_bstrInfoHTML += bstrSpace;
  498. bstrSpace.Empty();
  499. }
  500. if (SUCCEEDED(m_pThumbNailWrapper->FreeSpace(bstrSpace)))
  501. {
  502. m_bstrInfoHTML += OLESTR("<p><table class=Legend width=12 height=12 border=1 align=");
  503. if (m_bRTLDocument)
  504. {
  505. m_bstrInfoHTML += OLESTR("right ");
  506. }
  507. else
  508. {
  509. m_bstrInfoHTML += OLESTR("left ");
  510. }
  511. m_bstrInfoHTML += OLESTR("bgcolor=threedhighlight bordercolordark=black bordercolorlight=black>");
  512. m_bstrInfoHTML += OLESTR("<tr><td title=\'");
  513. IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_FREESPACE_DESC, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
  514. m_bstrInfoHTML += wszTemp;
  515. m_bstrInfoHTML += OLESTR("\'></td></tr></table>&nbsp;");
  516. IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_FREESPACE, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
  517. m_bstrInfoHTML += wszTemp;
  518. m_bstrInfoHTML += bstrSpace;
  519. }
  520. m_pThumbNailWrapper->SetDisplay(CComBSTR(""));
  521. }
  522. }
  523. else if (!bRootFolder)
  524. {
  525. BOOL bDisplayFlag = FALSE;
  526. BOOL bMovieFile = IsMovieFile(bstrPath);
  527. if (bMovieFile || IsSoundFile(bstrPath))
  528. {
  529. CComPtr<IMediaPlayer> spIMediaPlayer;
  530. if (SUCCEEDED(GetIMediaPlayer(spIMediaPlayer)))
  531. {
  532. spIMediaPlayer->Open(bstrPath);
  533. bDisplayFlag = TRUE;
  534. }
  535. spIMediaPlayer = NULL;
  536. }
  537. if (m_spMediaPlayerStyle && bDisplayFlag)
  538. {
  539. if (bMovieFile)
  540. {
  541. m_spMediaPlayerStyle->put_height(CComVariant(136));
  542. }
  543. else
  544. {
  545. m_spMediaPlayerStyle->put_height(CComVariant(46));
  546. }
  547. m_spMediaPlayerStyle->put_display(OLESTR(""));
  548. }
  549. }
  550. }
  551. return S_OK;;
  552. }
  553. HRESULT MakeLink(LPCWSTR pwszLink, LPCWSTR pwszText, CComBSTR& bstrText)
  554. {
  555. HRESULT hr = E_FAIL;
  556. if (pwszLink)
  557. {
  558. bstrText += OLESTR("<A HREF=\"");
  559. bstrText += pwszLink;
  560. bstrText += OLESTR("\">");
  561. if (pwszText && pwszText[0])
  562. {
  563. bstrText += pwszText;
  564. }
  565. else // If pwszText is NULL, use pwszLink itself as text.
  566. {
  567. bstrText += pwszLink;
  568. }
  569. bstrText += OLESTR("</A>");
  570. hr = S_OK;
  571. }
  572. return hr;
  573. }
  574. HRESULT CFileListWrapper::GetItemNameForDisplay()
  575. {
  576. HRESULT hr = E_FAIL;
  577. CComBSTR bstrIgnore, bstrName;
  578. // Get the name of the item
  579. if (SUCCEEDED(GetItemInfo(IDS_NAME_COL, L"Name", bstrIgnore, bstrName)) && (bstrName.Length() > 0))
  580. {
  581. m_bstrInfoHTML += OLESTR("<b>"); // Begin bold tag
  582. m_bstrInfoHTML += bstrName; // Add the name
  583. m_bstrInfoHTML += OLESTR("</b>"); // End bold tag
  584. hr = S_OK;
  585. }
  586. return hr;
  587. }
  588. HRESULT CFileListWrapper::GetItemType()
  589. {
  590. CComBSTR bstrIgnore, bstrType;
  591. HRESULT hr = GetItemInfo(IDS_TYPE_COL, L"Type", bstrIgnore, bstrType);
  592. if (SUCCEEDED(hr) && (bstrType.Length() > 0))
  593. {
  594. m_bstrInfoHTML += OLESTR("<br>");
  595. m_bstrInfoHTML += bstrType;
  596. }
  597. return hr;
  598. }
  599. HRESULT CFileListWrapper::GetItemDateTime()
  600. {
  601. CComBSTR bstrDesc, bstrDateTime;
  602. HRESULT hr = GetItemInfo(IDS_MODIFIED_COL, L"Modified", bstrDesc, bstrDateTime);
  603. if (SUCCEEDED(hr) && (bstrDateTime.Length() > 0))
  604. {
  605. m_bstrInfoHTML += OLESTR("<p>");
  606. m_bstrInfoHTML += bstrDesc;
  607. m_bstrInfoHTML += OLESTR(": ");
  608. m_bstrInfoHTML += bstrDateTime;
  609. }
  610. return hr;
  611. }
  612. HRESULT CFileListWrapper::GetItemSize()
  613. {
  614. WCHAR wszTemp[MAX_PATH];
  615. long lSize = 0;
  616. HRESULT hr = m_spFolderItem->get_Size(&lSize);
  617. if (SUCCEEDED(hr))
  618. {
  619. if (lSize > 0L)
  620. {
  621. m_bstrInfoHTML += OLESTR("<p>");
  622. IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_SIZE, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
  623. m_bstrInfoHTML += wszTemp;
  624. StrFormatByteSizeW(lSize, wszTemp, ARRAYSIZE(wszTemp));
  625. m_bstrInfoHTML += wszTemp;
  626. }
  627. }
  628. else
  629. {
  630. CComBSTR bstrDesc, bstrSize;
  631. hr = GetItemInfo(IDS_SIZE_COL, L"Size", bstrDesc, bstrSize);
  632. if (SUCCEEDED(hr) && (bstrSize.Length() > 0))
  633. {
  634. m_bstrInfoHTML += OLESTR("<p>");
  635. m_bstrInfoHTML += bstrDesc;
  636. m_bstrInfoHTML += OLESTR(": ");
  637. m_bstrInfoHTML += bstrSize;
  638. }
  639. }
  640. return hr;
  641. }
  642. const WCHAR c_wszAttributeCodes[] = {L"RHSCE"};
  643. const int c_iaAttribStringIDs[] = {IDS_READONLY, IDS_HIDDEN, IDS_SYSTEM, //IDS_ARCHIVE,
  644. IDS_COMPRESSED, IDS_ENCRYPTED};
  645. HRESULT FormatAttributes(CComBSTR& bstrDetails, CComBSTR& bstrText)
  646. {
  647. HRESULT hr = S_OK;
  648. BOOL bFlag = FALSE;
  649. WCHAR wszDelimiter[10], wszTemp[MAX_PATH];
  650. IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_DELIMITER, wszDelimiter, ARRAYSIZE(wszDelimiter)), E_FAIL);
  651. for (int i = 0; i < (int)bstrDetails.Length(); i++)
  652. {
  653. WCHAR* pwCh;
  654. if ((pwCh = StrChrIW(c_wszAttributeCodes, bstrDetails[i]))) // Is the value, one of "RHSCE"?
  655. {
  656. if (bFlag)
  657. {
  658. bstrText += wszDelimiter;
  659. bstrText += OLESTR(" ");
  660. }
  661. else
  662. {
  663. bFlag = TRUE;
  664. }
  665. int iPos = (int)(pwCh - c_wszAttributeCodes);
  666. ASSERT((iPos >= 0) && (iPos < ARRAYSIZE(c_iaAttribStringIDs)));
  667. IfFalseRet(LoadStringW(_Module.GetResourceInstance(), c_iaAttribStringIDs[iPos], wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
  668. bstrText += wszTemp;
  669. }
  670. }
  671. if (!bFlag)
  672. {
  673. IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_NOATTRIBUTES, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
  674. bstrText += wszTemp;
  675. }
  676. return hr;
  677. }
  678. HRESULT CFileListWrapper::GetItemAttributes()
  679. {
  680. VARIANT_BOOL fIsFolder;
  681. HRESULT hr = m_spFolderItem->get_IsFolder(&fIsFolder);
  682. if (SUCCEEDED(hr) && (fIsFolder == VARIANT_FALSE))
  683. {
  684. VARIANT_BOOL fIsFileSystem;
  685. hr = m_spFolderItem->get_IsFileSystem(&fIsFileSystem);
  686. if (SUCCEEDED(hr) && (fIsFileSystem == VARIANT_TRUE))
  687. {
  688. CComBSTR bstrDesc, bstrAttributes;
  689. hr = GetItemInfo(IDS_ATTRIBUTES_COL, L"Attributes", bstrDesc, bstrAttributes);
  690. if (SUCCEEDED(hr)) // Go ahead evenif (bstrAttributes.Length() > 0)
  691. {
  692. m_bstrInfoHTML += OLESTR("<p>");
  693. m_bstrInfoHTML += bstrDesc;
  694. m_bstrInfoHTML += OLESTR(": ");
  695. FormatAttributes(bstrAttributes, m_bstrInfoHTML);
  696. }
  697. }
  698. }
  699. return hr;
  700. }
  701. HRESULT MakeMailLink(LPCWSTR pwszMailee, CComBSTR& bstrText)
  702. {
  703. HRESULT hr = S_OK;
  704. bstrText += OLESTR("<A HREF=\'mailto:");
  705. bstrText += pwszMailee;
  706. bstrText += OLESTR("\'>");
  707. bstrText += pwszMailee;
  708. bstrText += OLESTR("</a>");
  709. return hr;
  710. }
  711. HRESULT CFileListWrapper::GetItemAuthor()
  712. {
  713. CComBSTR bstrDesc, bstrAuthor;
  714. HRESULT hr = GetItemInfo(IDS_AUTHOR_COL, L"Author", bstrDesc, bstrAuthor);
  715. if (SUCCEEDED(hr) && (bstrAuthor.Length() > 0))
  716. {
  717. m_bstrInfoHTML += OLESTR("<p>");
  718. m_bstrInfoHTML += bstrDesc;
  719. m_bstrInfoHTML += OLESTR(": ");
  720. if (StrChrW(bstrAuthor, L'@')) // This is most likely to be an e-mail address
  721. {
  722. MakeMailLink(bstrAuthor, m_bstrInfoHTML);
  723. }
  724. else
  725. {
  726. m_bstrInfoHTML += bstrAuthor;
  727. }
  728. m_bFoundAuthor = TRUE;
  729. }
  730. return hr;
  731. }
  732. HRESULT MakeLinksHyper(LPCWSTR pwszStr, CComBSTR& bstrText)
  733. {
  734. HRESULT hr = S_OK;
  735. LPWSTR pwszBegin;
  736. if ((pwszBegin = StrStrIW(pwszStr, L"http://"))
  737. || (pwszBegin = StrStrIW(pwszStr, L"file://")))
  738. {
  739. WCHAR wszTemp[INTERNET_MAX_URL_LENGTH];
  740. int i;
  741. for (i = 0; &pwszStr[i] != pwszBegin; i++)
  742. {
  743. wszTemp[i] = pwszStr[i];
  744. }
  745. wszTemp[i] = L'\0';
  746. bstrText += wszTemp;
  747. WCHAR* pwChEnd = StrStrW(pwszBegin, L" ");
  748. if (!pwChEnd)
  749. {
  750. pwChEnd = &pwszBegin[lstrlenW(pwszBegin)];
  751. }
  752. for (i = 0; &pwszBegin[i] != pwChEnd; i++) // Seperate out the http://... or file://... string
  753. {
  754. wszTemp[i] = pwszBegin[i];
  755. }
  756. wszTemp[i] = L'\0';
  757. MakeLink(wszTemp, wszTemp, bstrText);
  758. for (i = 0; pwChEnd[i]; i++) // Copy out the rest, till the end
  759. {
  760. wszTemp[i] = pwChEnd[i];
  761. }
  762. wszTemp[i] = L'\0';
  763. bstrText += wszTemp;
  764. }
  765. else
  766. {
  767. bstrText += pwszStr;
  768. }
  769. return hr;
  770. }
  771. HRESULT FormatDetails(LPCWSTR pwszDesc, LPCWSTR pwszDetails, CComBSTR& bstrText)
  772. {
  773. HRESULT hr = S_OK;
  774. bstrText += OLESTR("<p>");
  775. bstrText += pwszDesc;
  776. bstrText += OLESTR(":");
  777. if ((lstrlenW(pwszDesc) + lstrlenW(pwszDetails)) > 32)
  778. {
  779. bstrText += OLESTR("<br>");
  780. }
  781. else
  782. {
  783. bstrText += OLESTR(" ");
  784. }
  785. MakeLinksHyper(pwszDetails, bstrText);
  786. return hr;
  787. }
  788. HRESULT CFileListWrapper::GetItemComment()
  789. {
  790. CComBSTR bstrDesc, bstrComment;
  791. HRESULT hr = GetItemInfo(IDS_COMMENT_COL, L"Comment", bstrDesc, bstrComment);
  792. if (SUCCEEDED(hr) && (bstrComment.Length() > 0))
  793. {
  794. m_bstrInfoHTML += OLESTR("<p><div class = Message>");
  795. m_bstrInfoHTML += bstrComment;
  796. m_bstrInfoHTML += OLESTR("</div>");
  797. m_bFoundComment = TRUE;
  798. }
  799. return hr;
  800. }
  801. HRESULT CFileListWrapper::GetItemHTMLInfoTip()
  802. {
  803. CComBSTR bstrDesc, bstrHTMLInfoTipFile;
  804. HRESULT hr = GetItemInfo(0, L"HTMLInfoTipFile", bstrDesc, bstrHTMLInfoTipFile);
  805. if (SUCCEEDED(hr) && (bstrHTMLInfoTipFile.Length() > 0))
  806. {
  807. m_bstrInfoHTML += OLESTR("<br><p><iframe FRAMEBORDER=0 class=Message src=\"");
  808. m_bstrInfoHTML += bstrHTMLInfoTipFile;
  809. m_bstrInfoHTML += OLESTR("\"></iframe>");
  810. }
  811. return hr;
  812. }
  813. HRESULT CFileListWrapper::GetItemInfo(long lResId, LPWSTR wszInfoDescCanonical, CComBSTR& bstrInfoDesc, CComBSTR& bstrInfo)
  814. {
  815. HRESULT hr = E_FAIL;
  816. WCHAR wszInfoDesc[MAX_PATH];
  817. LoadStringW(_Module.GetResourceInstance(), lResId, wszInfoDesc, ARRAYSIZE(wszInfoDesc));
  818. bstrInfoDesc = wszInfoDesc;
  819. if (m_spFolderItem2)
  820. {
  821. CComBSTR bstrInfoDescCanonical = wszInfoDescCanonical;
  822. CComVariant var;
  823. hr = m_spFolderItem2->ExtendedProperty(bstrInfoDescCanonical, &var);
  824. if (SUCCEEDED(hr))
  825. {
  826. WCHAR wszTemp[80];
  827. if (var.vt == VT_BSTR)
  828. {
  829. // Of the three types of data we care about one is dangerous. The BSTR data that
  830. // we read from the file could contain HTML code which we would render in WebView.
  831. // This could cause potential security problems. To get around this we sanatize
  832. // the BSTR before we return it. We need to do the following replacements:
  833. //
  834. // original replace with
  835. // < &lt;
  836. // > &gt;
  837. // " &quot; <= this would be paranoid and isn't 100% critical
  838. // ' &lsquo; <= this would be paranoid and isn't 100% critical
  839. LPWSTR psz = var.bstrVal;
  840. LPWSTR pszBad;
  841. if (psz == NULL)
  842. {
  843. // we probably cant depend on hr and the out param matching (since this is
  844. // scriptable and therefore must return success)
  845. psz = L"";
  846. }
  847. while (pszBad = StrPBrkW(psz, L"<>"))
  848. {
  849. // store the bad character
  850. WCHAR chBadChar = *pszBad;
  851. // null the string
  852. *pszBad = NULL;
  853. // add the good part of the string, if there is any
  854. if ( *psz )
  855. bstrInfo += psz;
  856. // based on which bad character we found add the correct HTLM special character code
  857. switch ( chBadChar )
  858. {
  859. case L'<':
  860. bstrInfo += L"&lt;";
  861. break;
  862. case L'>':
  863. bstrInfo += L"&gt;";
  864. break;
  865. }
  866. // Advance the psz pointer. Note it might be an empty string after this.
  867. psz = pszBad+1;
  868. }
  869. // Add the remaining portion of the good string, even if it's an empty string.
  870. // bstrInfo is passed in uninitialized so we need to set it to something even
  871. // if that something is an empty string.
  872. bstrInfo += psz;
  873. }
  874. else if (var.vt == VT_DATE)
  875. {
  876. SYSTEMTIME st;
  877. FILETIME ft;
  878. if (VariantTimeToSystemTime(var.date, &st)
  879. && SystemTimeToFileTime(&st, &ft)
  880. && SHFormatDateTimeW(&ft, &m_dwDateFlags, wszTemp, ARRAYSIZE(wszTemp)))
  881. {
  882. bstrInfo += wszTemp;
  883. }
  884. else
  885. {
  886. hr = E_FAIL;
  887. }
  888. }
  889. else if (var.vt == VT_UI8 && StrCmpIW(wszInfoDescCanonical, L"size") == 0)
  890. {
  891. StrFormatByteSize64(var.ullVal, wszTemp, ARRAYSIZE(wszTemp));
  892. bstrInfo += wszTemp;
  893. }
  894. else
  895. {
  896. hr = E_FAIL;
  897. }
  898. }
  899. }
  900. return hr;
  901. }
  902. HRESULT CFileListWrapper::NoneSelected()
  903. {
  904. WCHAR wszIntro[MAX_PATH];
  905. CComPtr<FolderItem> spFolderItem;
  906. if (!m_bCSCDisplayed)
  907. {
  908. CSCShowStatusInfo();
  909. m_bCSCDisplayed = TRUE;
  910. }
  911. if (m_spFolderItems->Item(CComVariant(0), &spFolderItem) == S_OK)
  912. { // This filelist has atleast one item.
  913. IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_PROMPT, wszIntro, ARRAYSIZE(wszIntro)), E_FAIL);
  914. }
  915. else
  916. {
  917. IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_EMPTY, wszIntro, ARRAYSIZE(wszIntro)), E_FAIL);
  918. }
  919. m_bstrInfoHTML += wszIntro;
  920. spFolderItem = NULL;
  921. if (SUCCEEDED(m_spFolder2->get_Self(&spFolderItem)))
  922. {
  923. m_spFolderItem = spFolderItem;
  924. m_spFolderItem->QueryInterface(IID_FolderItem2, (void **)&m_spFolderItem2);
  925. m_bFoundAuthor = FALSE;
  926. m_bFoundComment = FALSE;
  927. // Get the comment for the item
  928. GetItemComment();
  929. GetItemHTMLInfoTip();
  930. DealWithDriveInfo();
  931. GetCrossLinks();
  932. m_spFolderItem2 = NULL;
  933. m_spFolderItem = NULL;
  934. }
  935. return S_OK;
  936. }
  937. #define MAX_SELECTEDFILES_FOR_COMPUTING_SIZE 100
  938. #define MAX_SELECTEDFILES_FOR_DISPLAYING_NAMES 16
  939. HRESULT CFileListWrapper::MultipleSelected(long cSelection)
  940. {
  941. HRESULT hr = S_FALSE;
  942. if (cSelection > 1)
  943. {
  944. WCHAR wszTemp[MAX_PATH];
  945. wnsprintfW(wszTemp, ARRAYSIZE(wszTemp), L"%ld", cSelection);
  946. m_bstrInfoHTML += wszTemp;
  947. IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_MULTIPLE, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
  948. m_bstrInfoHTML += wszTemp;
  949. if (cSelection <= MAX_SELECTEDFILES_FOR_COMPUTING_SIZE)
  950. {
  951. m_bstrInfoHTML += OLESTR("<p>");
  952. CComPtr<FolderItem> spFolderItem;
  953. long lSize = 0;
  954. for (int i = 0; i < cSelection; i++)
  955. {
  956. long lTempSize;
  957. if (SUCCEEDED(m_spFolderItems->Item(CComVariant(i), &spFolderItem)))
  958. {
  959. if (SUCCEEDED(spFolderItem->get_Size(&lTempSize)))
  960. {
  961. lSize += lTempSize;
  962. }
  963. spFolderItem = NULL;
  964. }
  965. }
  966. if (lSize > 0L)
  967. {
  968. IfFalseRet(LoadStringW(_Module.GetResourceInstance(), IDS_FILESIZE, wszTemp, ARRAYSIZE(wszTemp)), E_FAIL);
  969. m_bstrInfoHTML += wszTemp;
  970. StrFormatByteSizeW(lSize, wszTemp, ARRAYSIZE(wszTemp));
  971. m_bstrInfoHTML += wszTemp;
  972. m_bstrInfoHTML += OLESTR("<p>");
  973. }
  974. if (cSelection <= MAX_SELECTEDFILES_FOR_DISPLAYING_NAMES)
  975. {
  976. CComBSTR bstrTemp;
  977. for (int i = 0; i < cSelection; i++)
  978. {
  979. if (SUCCEEDED(m_spFolderItems->Item(CComVariant(i), &spFolderItem)))
  980. {
  981. if (SUCCEEDED(spFolderItem->get_Name(&bstrTemp)))
  982. {
  983. m_bstrInfoHTML += "<br>";
  984. m_bstrInfoHTML += bstrTemp;
  985. bstrTemp.Empty();
  986. }
  987. spFolderItem = NULL;
  988. }
  989. }
  990. }
  991. }
  992. hr = S_OK;
  993. }
  994. return hr;
  995. }
  996. HRESULT CFileListWrapper::OneSelected()
  997. {
  998. HRESULT hr = E_FAIL;
  999. m_bFoundAuthor = FALSE;
  1000. m_bFoundComment = FALSE;
  1001. // Get the name of the item, making it a hyper-link if appropriate.
  1002. GetItemNameForDisplay();
  1003. // Get the type of the item
  1004. GetItemType();
  1005. if (!m_bPathIsSlow)
  1006. {
  1007. // Get the comment for the item
  1008. GetItemComment();
  1009. // Get the HTMLInfoTip
  1010. GetItemHTMLInfoTip();
  1011. // Get the date/time stamp on the item
  1012. GetItemDateTime();
  1013. // Get the size of the item
  1014. GetItemSize();
  1015. // Get the attributes (hidden, RO etc.) of the item
  1016. GetItemAttributes();
  1017. // Get the author of the document
  1018. GetItemAuthor();
  1019. DealWithDriveInfo();
  1020. }
  1021. hr = S_OK;
  1022. return hr;
  1023. }
  1024. HRESULT CFileListWrapper::OnCSCClick()
  1025. {
  1026. HRESULT hres = E_FAIL;
  1027. CComPtr<Folder> spFolder;
  1028. CComPtr<Folder2> spFolder2;
  1029. if (m_spFileList && SUCCEEDED(m_spFileList->get_Folder(&spFolder))
  1030. && SUCCEEDED(spFolder->QueryInterface(IID_Folder2, (void **)&spFolder2)))
  1031. {
  1032. m_spFolder2 = spFolder2;
  1033. hres = CSCShowStatus_FoldExpand_Toggle();
  1034. m_spFolder2 = NULL;
  1035. }
  1036. return S_OK;
  1037. }
  1038. HRESULT CFileListWrapper::OnCSCMouseOnOff(BOOL fOn)
  1039. {
  1040. CComPtr<IHTMLStyle> psPlusMin;
  1041. CComPtr<IHTMLStyle> psText;
  1042. HRESULT hres = E_FAIL;
  1043. // If we're already in this state don't do anything
  1044. if (m_bHotTracked == fOn)
  1045. return S_OK;
  1046. // If we receive a 'mouse on' but the element is not one we want to track or if we receive a 'mouse off' but
  1047. // the mouse is over one of our other elements that we want to hot track then don't do anything.
  1048. if (m_spWindow)
  1049. {
  1050. CComPtr<IHTMLEventObj> phtmlevent;
  1051. CComPtr<IHTMLElement> phtmlelement;
  1052. CComBSTR bstrId;
  1053. if (SUCCEEDED(m_spWindow->get_event(&phtmlevent)) && phtmlevent)
  1054. {
  1055. HRESULT hres;
  1056. if (!fOn)
  1057. hres = phtmlevent->get_toElement(&phtmlelement);
  1058. else
  1059. hres = phtmlevent->get_srcElement(&phtmlelement);
  1060. if (SUCCEEDED(hres) && phtmlelement && SUCCEEDED(phtmlelement->get_id(&bstrId)) && (bstrId.Length() > 0))
  1061. {
  1062. BOOL bContainsCSC;
  1063. bContainsCSC = (StrStrIW(bstrId, L"CSC") != NULL);
  1064. if (bContainsCSC != fOn)
  1065. return S_OK;
  1066. }
  1067. }
  1068. }
  1069. if (m_spCSCPlusMin && m_spCSCText && SUCCEEDED(hres = m_spCSCPlusMin->get_style(&psPlusMin)) && SUCCEEDED(hres = m_spCSCText->get_style(&psText)))
  1070. {
  1071. CComVariant vcolorBlack (OLESTR("black"));
  1072. CComBSTR bstrCSCPlusMin;
  1073. LPOLESTR pstrCursor = (fOn ? OLESTR("hand") : OLESTR("auto"));
  1074. CComVariant vcolorLink;
  1075. m_bHotTracked = fOn;
  1076. m_spDocument->get_linkColor(&vcolorLink);
  1077. if (m_bExpanded)
  1078. bstrCSCPlusMin = fOn ? CSC_MINUSHOT : CSC_MINUSCOLD;
  1079. else
  1080. bstrCSCPlusMin = fOn ? CSC_PLUSHOT : CSC_PLUSCOLD;
  1081. m_spCSCPlusMin->put_innerHTML(bstrCSCPlusMin);
  1082. psPlusMin->put_cursor(pstrCursor);
  1083. psText->put_color(fOn ? vcolorLink : vcolorBlack);
  1084. psText->put_cursor(pstrCursor);
  1085. }
  1086. return hres;
  1087. }
  1088. HRESULT CFileListWrapper::CSCSynchronize()
  1089. {
  1090. HRESULT hres = E_FAIL;
  1091. CComPtr<Folder> spFolder;
  1092. CComPtr<Folder2> spFolder2;
  1093. if (m_spFileList && SUCCEEDED(m_spFileList->get_Folder(&spFolder))
  1094. && SUCCEEDED(spFolder->QueryInterface(IID_Folder2, (void **)&spFolder2)))
  1095. {
  1096. hres = spFolder2->Synchronize();
  1097. }
  1098. return hres;
  1099. }
  1100. const UINT c_ids_uiCSCText[] =
  1101. {IDS_CSC_ONLINE, IDS_CSC_OFFLINE, IDS_CSC_SERVERAVAILABLE, IDS_CSC_DIRTYCACHE};
  1102. HRESULT CFileListWrapper::CSCGetStatusText(LONG lStatus, CComBSTR& bstrCSCText)
  1103. {
  1104. WCHAR wszTemp[MAX_PATH];
  1105. if ((lStatus >= 0) && (lStatus < ARRAYSIZE(c_ids_uiCSCText))
  1106. && LoadStringW(_Module.GetResourceInstance(), c_ids_uiCSCText[(int)lStatus], wszTemp, ARRAYSIZE(wszTemp)))
  1107. {
  1108. bstrCSCText += wszTemp;
  1109. }
  1110. return S_OK;
  1111. }
  1112. const UINT c_ids_uiCSCDetail[] =
  1113. {IDS_CSC_DETAIL_ONLINE, IDS_CSC_DETAIL_OFFLINE, IDS_CSC_DETAIL_SERVERAVAILABLE, IDS_CSC_DETAIL_DIRTYCACHE};
  1114. HRESULT CFileListWrapper::CSCGetStatusDetail(LONG lStatus, CComBSTR& bstrCSCDetail)
  1115. {
  1116. WCHAR wszTemp[MAX_PATH];
  1117. if ((lStatus >= 0) && (lStatus < ARRAYSIZE(c_ids_uiCSCDetail))
  1118. && LoadStringW(_Module.GetResourceInstance(), c_ids_uiCSCDetail[(int)lStatus], wszTemp, ARRAYSIZE(wszTemp)))
  1119. {
  1120. bstrCSCDetail += wszTemp;
  1121. }
  1122. return S_OK;
  1123. }
  1124. #define CSC_STATUS_ONLINE 0
  1125. #define CSC_STATUS_OFFLINE 1
  1126. #define CSC_STATUS_SERVERAVAILABLE 2
  1127. #define CSC_STATUS_DIRTYCACHE 3
  1128. HRESULT CFileListWrapper::CSCGetStatusButton(LONG lStatus, CComBSTR& bstrCSCButton)
  1129. {
  1130. if ((lStatus == CSC_STATUS_SERVERAVAILABLE) || (lStatus == CSC_STATUS_DIRTYCACHE))
  1131. {
  1132. bstrCSCButton += OLESTR("<p class=Button><button onclick=\'WVCoord.CSCSynchronize()\'>");
  1133. WCHAR wszTemp[MAX_PATH];
  1134. LoadStringW(_Module.GetResourceInstance(), IDS_CSC_SYNCHRONIZE, wszTemp, ARRAYSIZE(wszTemp));
  1135. bstrCSCButton += wszTemp;
  1136. bstrCSCButton += OLESTR("</button>");
  1137. }
  1138. return S_OK;
  1139. }
  1140. HRESULT CFileListWrapper::GetCSCFolderStatus(LONG* plStatus)
  1141. {
  1142. return m_spFolder2 ? m_spFolder2->get_OfflineStatus(plStatus) : E_FAIL;
  1143. }
  1144. HRESULT CFileListWrapper::CSCShowStatusInfo()
  1145. {
  1146. LONG lStatus;
  1147. if (m_spCSCText && m_spCSCPlusMin && m_spCSCDetail && m_spCSCButton && m_spCSCStyle
  1148. && m_spCSCDetailStyle && m_spCSCButtonStyle)
  1149. {
  1150. CComBSTR bstrCSC_Display;
  1151. if (SUCCEEDED(GetCSCFolderStatus(&lStatus)) && (lStatus >= 0))
  1152. {
  1153. CComBSTR bstrCSCText;
  1154. CSCGetStatusText(lStatus, bstrCSCText);
  1155. bstrCSCText += OLESTR("<br>");
  1156. CComBSTR bstrCSCPlusMin;
  1157. CComBSTR bstrCSCDetail;
  1158. CComBSTR bstrCSCDetail_Display;
  1159. if (m_bExpanded)
  1160. {
  1161. bstrCSCPlusMin = m_bHotTracked ? CSC_MINUSHOT : CSC_MINUSCOLD;
  1162. bstrCSCText += OLESTR("<br>");
  1163. CSCGetStatusDetail(lStatus, bstrCSCDetail);
  1164. bstrCSCDetail += OLESTR("<br>");
  1165. bstrCSCDetail_Display = OLESTR("");
  1166. if (m_bRTLDocument)
  1167. {
  1168. // [msadek]; Life would be easier if the object model has exposed
  1169. // right offset through get_offsetRight().
  1170. CComPtr<IHTMLControlElement> spDocBody = NULL;
  1171. long lOffsetLeft, lOffsetWidth, lClientWidth, lOffsetRight = 0;
  1172. if (SUCCEEDED(m_spCSCText->QueryInterface(IID_IHTMLControlElement, (void **)&spDocBody))
  1173. && SUCCEEDED(m_spCSCText->get_offsetLeft(&lOffsetLeft))
  1174. && SUCCEEDED(m_spCSCText->get_offsetWidth(&lOffsetWidth))
  1175. && SUCCEEDED(spDocBody->get_clientWidth(&lClientWidth)))
  1176. {
  1177. lOffsetRight = lClientWidth - (lOffsetLeft + lOffsetWidth);
  1178. }
  1179. m_spCSCDetailStyle->put_marginRight(CComVariant(lOffsetRight - 10L));
  1180. }
  1181. else
  1182. {
  1183. long lOffsetLeft;
  1184. if (FAILED(m_spCSCText->get_offsetLeft(&lOffsetLeft)))
  1185. {
  1186. lOffsetLeft = 0;
  1187. }
  1188. m_spCSCDetailStyle->put_marginLeft(CComVariant(lOffsetLeft - 10L));
  1189. }
  1190. }
  1191. else
  1192. {
  1193. bstrCSCPlusMin = m_bHotTracked ? CSC_PLUSHOT : CSC_PLUSCOLD;
  1194. bstrCSCDetail += OLESTR("");
  1195. bstrCSCDetail_Display = OLESTR("none");
  1196. }
  1197. m_spCSCPlusMin->put_innerHTML(bstrCSCPlusMin);
  1198. m_spCSCText->put_innerHTML(bstrCSCText);
  1199. m_spCSCDetail->put_innerHTML(bstrCSCDetail);
  1200. m_spCSCDetailStyle->put_display(bstrCSCDetail_Display);
  1201. CComBSTR bstrCSCButton_Display;
  1202. CComBSTR bstrCSCButton;
  1203. if (SUCCEEDED(CSCGetStatusButton(lStatus, bstrCSCButton)) && (bstrCSCButton.Length() > 0))
  1204. {
  1205. bstrCSCButton_Display = OLESTR("");
  1206. }
  1207. else
  1208. {
  1209. bstrCSCButton = OLESTR("");
  1210. bstrCSCButton_Display = OLESTR("none");
  1211. }
  1212. m_spCSCButton->put_innerHTML(bstrCSCButton);
  1213. m_spCSCButtonStyle->put_display(bstrCSCButton_Display);
  1214. bstrCSC_Display = OLESTR("");
  1215. }
  1216. else
  1217. {
  1218. bstrCSC_Display = OLESTR("none");
  1219. }
  1220. m_spCSCStyle->put_display(bstrCSC_Display);
  1221. }
  1222. return S_OK;
  1223. }
  1224. HRESULT CFileListWrapper::CSCShowStatus_FoldExpand_Toggle()
  1225. {
  1226. m_bExpanded = !m_bExpanded;
  1227. return (CSCShowStatusInfo());
  1228. }
  1229. // fEnter true for mouseover, focus; false for mouseout, blur
  1230. HRESULT CFileListWrapper::OnWebviewLinkEvent( BOOL fEnter )
  1231. {
  1232. CComPtr<IHTMLEventObj> spEvent;
  1233. CComPtr<IHTMLElement> spAnchor;
  1234. HRESULT hr;
  1235. // NT# 354743, IHTMLEventObj::get_event() can return S_OK and
  1236. // not set the out param, so we need to protect against that.
  1237. spEvent = NULL;
  1238. hr = m_spWindow->get_event(&spEvent);
  1239. // Automation interfaces sometimes return S_FALSE on failures to prevent scripting errors
  1240. if (S_OK == hr)
  1241. {
  1242. // Sometimes Trident will not set the out parameter when it returns S_OK, so
  1243. // we need to make sure it's not NULL.
  1244. if (spEvent)
  1245. {
  1246. hr = GetEventAnchorElement(spEvent, &spAnchor);
  1247. }
  1248. else
  1249. hr = E_FAIL;
  1250. if (S_OK == hr)
  1251. {
  1252. if (fEnter)
  1253. {
  1254. CComBSTR bstrTitle;
  1255. hr = spAnchor->get_title(&bstrTitle);
  1256. if(SUCCEEDED(hr))
  1257. {
  1258. m_spWindow->put_status(bstrTitle);
  1259. }
  1260. spEvent->put_returnValue(CComVariant(true));
  1261. }
  1262. else
  1263. {
  1264. hr = m_spWindow->put_status(OLESTR(""));
  1265. }
  1266. }
  1267. }
  1268. return S_OK;
  1269. }
  1270. // Walks up the component chain from the event source, looking for
  1271. // an anchor element. Returns S_OK if successful, some error otherwise.
  1272. // On failure *ppElt will be set to null. Note that this gives back
  1273. // the IHTMLElement that corresponds to the anchor, not the
  1274. // IHTMLAnchorElement, as only IHTMLElement has get_title
  1275. HRESULT CFileListWrapper::GetEventAnchorElement( IHTMLEventObj *pEvent,
  1276. IHTMLElement **ppElt )
  1277. {
  1278. CComPtr<IHTMLElement> spElement;
  1279. *ppElt = NULL;
  1280. if( SUCCEEDED( pEvent->get_srcElement( &spElement )))
  1281. {
  1282. BOOL fContinue = TRUE;
  1283. while( fContinue && spElement )
  1284. {
  1285. CComPtr<IHTMLAnchorElement> spAnchor;
  1286. if( SUCCEEDED( spElement->QueryInterface( IID_IHTMLAnchorElement,
  1287. reinterpret_cast<void**>( &spAnchor ))))
  1288. {
  1289. fContinue = false;
  1290. *ppElt = spElement;
  1291. reinterpret_cast<IUnknown*>( *ppElt )->AddRef();
  1292. }
  1293. else
  1294. {
  1295. IHTMLElement *pIElt = NULL;
  1296. if( SUCCEEDED( spElement->get_parentElement( &pIElt )))
  1297. {
  1298. spElement = pIElt;
  1299. if (pIElt)
  1300. {
  1301. pIElt->Release();
  1302. }
  1303. }
  1304. else
  1305. {
  1306. spElement.Release();
  1307. }
  1308. }
  1309. }
  1310. }
  1311. return ( *ppElt ? S_OK : E_FAIL );
  1312. }
  1313. // Bind to the connection points for each of the link elements
  1314. // contained within m_spLinks. The advise cookie for each link
  1315. // is stored as an attribute within the link, so we don't need
  1316. // to maintain a mapping between links and elements.
  1317. // fAdvise -- true to make connections, false to break
  1318. HRESULT CFileListWrapper::AdviseWebviewLinks( BOOL fAdvise)
  1319. {
  1320. CComPtr<IDispatch> spDisp;
  1321. CComPtr<IHTMLElement> spElement;
  1322. CComPtr<IHTMLElementCollection> spCollection;
  1323. CComVariant vtEmpty;
  1324. CComBSTR bstrAttr = WV_LINKNAME;
  1325. long cLinks;
  1326. DWORD dwCookie;
  1327. HRESULT hr;
  1328. IfFailRet( GetWVLinksCollection( &spCollection, &cLinks ));
  1329. for( long i = 0; i < cLinks; i++ )
  1330. {
  1331. hr = spCollection->item( CComVariant( i ), vtEmpty, &spDisp );
  1332. if (!spDisp)
  1333. {
  1334. hr = E_FAIL;
  1335. }
  1336. if( SUCCEEDED( hr ))
  1337. {
  1338. hr = spDisp->QueryInterface( IID_IHTMLElement,
  1339. reinterpret_cast<void**>( &spElement ));
  1340. spDisp.Release();
  1341. }
  1342. if( SUCCEEDED( hr ))
  1343. {
  1344. if( fAdvise )
  1345. {
  1346. hr = AtlAdvise( spElement, this, IID_IDispatch, &dwCookie );
  1347. if( SUCCEEDED( hr ))
  1348. {
  1349. hr = spElement->setAttribute( bstrAttr,
  1350. CComVariant( static_cast<long>( dwCookie )),
  1351. VARIANT_FALSE );
  1352. if( FAILED( hr ))
  1353. {
  1354. AtlUnadvise( spElement, IID_IDispatch, dwCookie );
  1355. }
  1356. }
  1357. }
  1358. else
  1359. {
  1360. CComVariant vtCookie;
  1361. hr = spElement->getAttribute( bstrAttr, FALSE, &vtCookie );
  1362. if( SUCCEEDED( hr ))
  1363. {
  1364. dwCookie = static_cast<DWORD>( vtCookie.lVal );
  1365. AtlUnadvise( spElement, IID_IDispatch, dwCookie );
  1366. }
  1367. }
  1368. spElement.Release();
  1369. }
  1370. }
  1371. return S_OK;
  1372. }
  1373. // Get the IHTMLElementCollection that holds the named links
  1374. HRESULT CFileListWrapper::GetWVLinksCollection( IHTMLElementCollection **ppCollection,
  1375. long *pcLinks )
  1376. {
  1377. CComPtr<IDispatch> spDisp;
  1378. CComPtr<IHTMLElementCollection> spCollection;
  1379. CComVariant vtEmpty;
  1380. HRESULT hr;
  1381. ASSERT( ppCollection );
  1382. ASSERT( pcLinks );
  1383. *ppCollection = NULL;
  1384. *pcLinks = 0;
  1385. if (!m_spLinks) return E_FAIL;
  1386. // Get the initial element collection from m_spLinks
  1387. IfFailRet( m_spLinks->get_all( &spDisp ));
  1388. IfFailRet( spDisp->QueryInterface( IID_IHTMLElementCollection,
  1389. reinterpret_cast<void**>( &spCollection )));
  1390. spDisp.Release();
  1391. // Get the collection of elements with our linkname. If nothing exists, spDisp
  1392. // will be null and item returns S_OK.
  1393. IfFailRet( spCollection->item( CComVariant( WV_LINKNAME ), vtEmpty, &spDisp ));
  1394. if( !spDisp ) return E_FAIL;
  1395. IfFailRet( spDisp->QueryInterface( IID_IHTMLElementCollection,
  1396. reinterpret_cast<void**>( ppCollection )));
  1397. return reinterpret_cast<IHTMLElementCollection*>( *ppCollection )->get_length( pcLinks );
  1398. }