Source code of Windows XP (NT5)
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.

1183 lines
29 KiB

  1. #include "private.h"
  2. #include "offl_cpp.h"
  3. #include <htmlhelp.h>
  4. #include <shdocvw.h>
  5. #include <mluisupp.h>
  6. // {F5175861-2688-11d0-9C5E-00AA00A45957}
  7. const GUID CLSID_OfflineFolder =
  8. { 0xf5175861, 0x2688, 0x11d0, { 0x9c, 0x5e, 0x0, 0xaa, 0x0, 0xa4, 0x59, 0x57 } };
  9. // {F5175860-2688-11d0-9C5E-00AA00A45957}
  10. const GUID IID_IOfflineObject =
  11. { 0xf5175860, 0x2688, 0x11d0, { 0x9c, 0x5e, 0x0, 0xaa, 0x0, 0xa4, 0x59, 0x57 } };
  12. // Column definition for the Cache Folder DefView
  13. ColInfoType s_AllItems_cols[] = {
  14. {ICOLC_SHORTNAME, IDS_NAME_COL, 20, LVCFMT_LEFT},
  15. {ICOLC_LAST, IDS_LAST_COL, 14, LVCFMT_LEFT},
  16. {ICOLC_STATUS, IDS_STATUS_COL, 14, LVCFMT_LEFT},
  17. {ICOLC_URL, IDS_URL_COL, 20, LVCFMT_LEFT},
  18. {ICOLC_ACTUALSIZE, IDS_SIZE_COL, 10, LVCFMT_LEFT}};
  19. ColInfoType * colInfo = s_AllItems_cols;
  20. LPMYPIDL _CreateFolderPidl(IMalloc *pmalloc, DWORD dwSize);
  21. HRESULT OfflineFolderView_InitMenuPopup(HWND hwnd, UINT idCmdFirst, int nIndex, HMENU hMenu)
  22. {
  23. UINT platform = WhichPlatform();
  24. if (platform != PLATFORM_INTEGRATED) {
  25. MENUITEMINFO mInfo = {0};
  26. mInfo.cbSize = sizeof(MENUITEMINFO);
  27. mInfo.fMask = MIIM_STATE;
  28. if (IsGlobalOffline()) {
  29. mInfo.fState = MFS_CHECKED;
  30. } else {
  31. mInfo.fState = MFS_UNCHECKED;
  32. }
  33. SetMenuItemInfo(hMenu, RSVIDM_WORKOFFLINE + idCmdFirst, FALSE, &mInfo);
  34. }
  35. return NOERROR;
  36. }
  37. HRESULT OfflineFolderView_MergeMenu(LPQCMINFO pqcm)
  38. {
  39. HMENU hmenu = NULL;
  40. UINT platform = WhichPlatform();
  41. if (platform == PLATFORM_INTEGRATED) {
  42. hmenu = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(MENU_OFFLINE_TOP));
  43. } else {
  44. hmenu = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(MENU_OFFLINE_BRONLY));
  45. }
  46. if (hmenu)
  47. {
  48. MergeMenuHierarchy(pqcm->hmenu, hmenu, pqcm->idCmdFirst, pqcm->idCmdLast, TRUE);
  49. DestroyMenu(hmenu);
  50. }
  51. return S_OK;
  52. }
  53. extern HRESULT CancelAllDownloads();
  54. HRESULT OfflineFolderView_Command(HWND hwnd, UINT uID)
  55. {
  56. switch (uID) {
  57. case RSVIDM_SORTBYNAME:
  58. ShellFolderView_ReArrange(hwnd, ICOLC_SHORTNAME);
  59. break;
  60. case RSVIDM_UPDATEALL:
  61. SendUpdateRequests(hwnd, NULL, 0);
  62. break;
  63. case RSVIDM_WORKOFFLINE:
  64. SetGlobalOffline(!IsGlobalOffline());
  65. break;
  66. case RSVIDM_HELP:
  67. SHHtmlHelpOnDemandWrap(hwnd, TEXT("iexplore.chm > iedefault"), 0, (DWORD_PTR) TEXT("subs_upd.htm"), ML_CROSSCODEPAGE);
  68. break;
  69. case RSVIDM_UPDATE:
  70. {
  71. LPMYPIDL * pidlsSel = NULL;
  72. UINT count = 0;
  73. count = (UINT) ShellFolderView_GetSelectedObjects
  74. (hwnd, (LPITEMIDLIST*) &pidlsSel);
  75. if ((!pidlsSel) || !count)
  76. break;
  77. CLSID * cookies = (CLSID *)MemAlloc(LPTR, count * sizeof(CLSID));
  78. UINT validCount = 0;
  79. if (cookies)
  80. {
  81. for (UINT i = 0; i < count; i ++) {
  82. if (IS_VALID_MYPIDL(pidlsSel[i]))
  83. cookies[validCount++] = pidlsSel[i]->ooe.m_Cookie;
  84. }
  85. if (validCount)
  86. SendUpdateRequests(hwnd, cookies, validCount);
  87. MemFree(cookies);
  88. cookies = NULL;
  89. }
  90. break;
  91. }
  92. default:
  93. return E_FAIL;
  94. }
  95. return NOERROR;
  96. }
  97. // We should make this a generic function for all types of items, even
  98. // for the third party items they should support these properties.
  99. HRESULT Generic_GetDetails(PDETAILSINFO pdi, UINT iColumn)
  100. {
  101. LPMYPIDL pooi = (LPMYPIDL)pdi->pidl;
  102. POOEntry pooe = NULL;
  103. TCHAR timeSTR[128];
  104. pdi->str.uType = STRRET_CSTR;
  105. pdi->str.cStr[0] = '\0';
  106. pooe = &(pooi->ooe);
  107. switch (iColumn)
  108. {
  109. case ICOLC_SHORTNAME:
  110. SHTCharToAnsi(NAME(pooe), pdi->str.cStr, sizeof(pdi->str.cStr));
  111. break;
  112. case ICOLC_URL:
  113. SHTCharToAnsi(URL(pooe), pdi->str.cStr, sizeof(pdi->str.cStr));
  114. break;
  115. case ICOLC_LAST:
  116. DATE2DateTimeString(pooe->m_LastUpdated, timeSTR);
  117. SHTCharToAnsi(timeSTR, pdi->str.cStr, sizeof(pdi->str.cStr));
  118. break;
  119. case ICOLC_STATUS:
  120. SHTCharToAnsi(STATUS(pooe), pdi->str.cStr, sizeof(pdi->str.cStr));
  121. break;
  122. case ICOLC_ACTUALSIZE:
  123. StrFormatByteSizeA(pooe->m_ActualSize * 1024, pdi->str.cStr, sizeof(pdi->str.cStr));
  124. break;
  125. }
  126. return S_OK;
  127. }
  128. HRESULT OfflineFolderView_OnGetDetailsOf(HWND hwnd, UINT iColumn, PDETAILSINFO pdi)
  129. {
  130. LPMYPIDL pooi = (LPMYPIDL)pdi->pidl;
  131. if (iColumn > ICOLC_ACTUALSIZE)
  132. return E_NOTIMPL;
  133. if (!pooi)
  134. {
  135. pdi->str.uType = STRRET_CSTR;
  136. pdi->str.cStr[0] = '\0';
  137. MLLoadStringA(colInfo[iColumn].ids, pdi->str.cStr, sizeof(pdi->str.cStr));
  138. pdi->fmt = colInfo[iColumn].iFmt;
  139. pdi->cxChar = colInfo[iColumn].cchCol;
  140. return S_OK;
  141. }
  142. UINT colId = colInfo[iColumn].iCol;
  143. return Generic_GetDetails(pdi, colId);
  144. }
  145. HRESULT OfflineFolderView_OnColumnClick(HWND hwnd, UINT iColumn)
  146. {
  147. ShellFolderView_ReArrange(hwnd, colInfo[iColumn].iCol);
  148. return NOERROR;
  149. }
  150. const TBBUTTON c_tbOffline[] = {
  151. { 0, RSVIDM_UPDATE, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0L, -1 },
  152. { 1, RSVIDM_UPDATEALL, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0L, -1 },
  153. { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP , {0,0}, 0L, -1 },
  154. };
  155. HRESULT OfflineFolderView_OnGetButtons(HWND hwnd, UINT idCmdFirst, LPTBBUTTON ptButton)
  156. {
  157. UINT i;
  158. LONG_PTR iBtnOffset;
  159. IShellBrowser * psb = FileCabinet_GetIShellBrowser(hwnd);
  160. TBADDBITMAP ab;
  161. // add the toolbar button bitmap, get it's offset
  162. ab.hInst =g_hInst;
  163. ab.nID = IDB_TB_SMALL; // std bitmaps
  164. psb->SendControlMsg(FCW_TOOLBAR, TB_ADDBITMAP, 2, (LPARAM)&ab, &iBtnOffset);
  165. for (i = 0; i < ARRAYSIZE(c_tbOffline); i++)
  166. {
  167. ptButton[i] = c_tbOffline[i];
  168. if (!(c_tbOffline[i].fsStyle & TBSTYLE_SEP))
  169. {
  170. ptButton[i].idCommand += idCmdFirst;
  171. ptButton[i].iBitmap += (int)iBtnOffset;
  172. }
  173. }
  174. return S_OK;
  175. }
  176. HRESULT OfflineFolderView_OnGetButtonInfo(TBINFO * ptbInfo)
  177. {
  178. ptbInfo->uFlags = TBIF_PREPEND;
  179. ptbInfo->cbuttons = ARRAYSIZE(c_tbOffline);
  180. return S_OK;
  181. }
  182. HRESULT OfflineFolderView_DidDragDrop(HWND hwnd,IDataObject *pdo,DWORD dwEffect)
  183. {
  184. if ((dwEffect & (DROPEFFECT_MOVE |DROPEFFECT_COPY)) == DROPEFFECT_MOVE)
  185. {
  186. COfflineObjectItem *pOOItem;
  187. if (SUCCEEDED(pdo->QueryInterface(IID_IOfflineObject, (void **)&pOOItem)))
  188. {
  189. BOOL fDel = ConfirmDelete(hwnd, pOOItem->_cItems, pOOItem->_ppooi);
  190. if (!fDel) {
  191. pOOItem->Release();
  192. return S_FALSE;
  193. }
  194. for (UINT i = 0; i < pOOItem->_cItems; i++)
  195. {
  196. if (SUCCEEDED(DoDeleteSubscription(&(pOOItem->_ppooi[i]->ooe)))) {
  197. _GenerateEvent(SHCNE_DELETE,
  198. (LPITEMIDLIST)pOOItem->_ppooi[i],
  199. NULL);
  200. }
  201. }
  202. pOOItem->Release();
  203. return S_OK;
  204. }
  205. }
  206. return E_FAIL;
  207. }
  208. HRESULT CALLBACK OfflineFolderView_ViewCallback(
  209. IShellView *psvOuter,
  210. IShellFolder *psf,
  211. HWND hwnd,
  212. UINT uMsg,
  213. WPARAM wParam,
  214. LPARAM lParam)
  215. {
  216. HRESULT hres = NOERROR;
  217. switch (uMsg)
  218. {
  219. case DVM_GETHELPTEXT:
  220. case DVM_GETTOOLTIPTEXT:
  221. {
  222. UINT id = LOWORD(wParam);
  223. UINT cchBuf = HIWORD(wParam);
  224. if (g_fIsWinNT)
  225. {
  226. WCHAR * pszBuf = (WCHAR *)lParam;
  227. MLLoadStringW(id + IDS_SB_FIRST, pszBuf, cchBuf);
  228. }
  229. else
  230. {
  231. CHAR * pszBuf = (CHAR *)lParam;
  232. MLLoadStringA(id + IDS_SB_FIRST, pszBuf, cchBuf);
  233. }
  234. }
  235. break;
  236. case DVM_DIDDRAGDROP:
  237. hres = OfflineFolderView_DidDragDrop(hwnd,(IDataObject *)lParam,(DWORD)wParam);
  238. break;
  239. case DVM_INITMENUPOPUP:
  240. hres = OfflineFolderView_InitMenuPopup(hwnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
  241. break;
  242. case DVM_INVOKECOMMAND:
  243. OfflineFolderView_Command(hwnd, (UINT)wParam);
  244. break;
  245. case DVM_COLUMNCLICK:
  246. hres = OfflineFolderView_OnColumnClick(hwnd, (UINT)wParam);
  247. break;
  248. case DVM_GETDETAILSOF:
  249. hres = OfflineFolderView_OnGetDetailsOf(hwnd, (UINT)wParam, (PDETAILSINFO)lParam);
  250. break;
  251. case DVM_MERGEMENU:
  252. hres = OfflineFolderView_MergeMenu((LPQCMINFO)lParam);
  253. break;
  254. case DVM_DEFVIEWMODE:
  255. *(FOLDERVIEWMODE *)lParam = FVM_DETAILS;
  256. break;
  257. case DVM_GETBUTTONINFO:
  258. hres = OfflineFolderView_OnGetButtonInfo((TBINFO *)lParam);
  259. break;
  260. case DVM_GETBUTTONS:
  261. hres = OfflineFolderView_OnGetButtons(hwnd, LOWORD(wParam), (TBBUTTON *)lParam);
  262. break;
  263. default:
  264. hres = E_FAIL;
  265. }
  266. return hres;
  267. }
  268. HRESULT OfflineFolderView_CreateInstance(COfflineFolder *pOOFolder, LPCITEMIDLIST pidl, void **ppvOut)
  269. {
  270. CSFV csfv;
  271. csfv.cbSize = sizeof(csfv);
  272. csfv.pshf = (IShellFolder *)pOOFolder;
  273. csfv.psvOuter = NULL;
  274. csfv.pidl = pidl;
  275. csfv.lEvents = SHCNE_DELETE | SHCNE_CREATE | SHCNE_RENAMEITEM | SHCNE_UPDATEITEM | SHCNE_UPDATEDIR;
  276. csfv.pfnCallback = OfflineFolderView_ViewCallback;
  277. csfv.fvm = (FOLDERVIEWMODE)0; // Have defview restore the folder view mode
  278. return SHCreateShellFolderViewEx(&csfv, (IShellView**)ppvOut); // &this->psv);
  279. }
  280. //////////////////////////////////////////////////////////////////////////////
  281. //
  282. // COfflineFolderEnum Object
  283. //
  284. //////////////////////////////////////////////////////////////////////////////
  285. COfflineFolderEnum::COfflineFolderEnum(DWORD grfFlags)
  286. {
  287. TraceMsg(TF_SUBSFOLDER, "hcfe - COfflineFolderEnum() called");
  288. m_cRef = 1;
  289. DllAddRef();
  290. m_grfFlags = grfFlags;
  291. }
  292. IMalloc *COfflineFolderEnum::s_pMalloc = NULL;
  293. void COfflineFolderEnum::EnsureMalloc()
  294. {
  295. if (NULL == s_pMalloc)
  296. {
  297. SHGetMalloc(&s_pMalloc);
  298. }
  299. ASSERT(NULL != s_pMalloc);
  300. }
  301. COfflineFolderEnum::~COfflineFolderEnum()
  302. {
  303. ASSERT(m_cRef == 0); // we should always have a zero ref count here
  304. SAFERELEASE(m_pFolder);
  305. SAFEDELETE(m_pCookies);
  306. TraceMsg(TF_SUBSFOLDER, "hcfe - ~COfflineFolderEnum() called.");
  307. DllRelease();
  308. }
  309. HRESULT COfflineFolderEnum::Initialize(COfflineFolder *pFolder)
  310. {
  311. HRESULT hr = S_OK;
  312. ASSERT(pFolder);
  313. if (NULL != pFolder)
  314. {
  315. m_pFolder = pFolder;
  316. m_pFolder->AddRef();
  317. hr = CoInitialize(NULL);
  318. if (SUCCEEDED(hr))
  319. {
  320. ISubscriptionMgr2 *pSubsMgr2;
  321. hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
  322. IID_ISubscriptionMgr2, (void **)&pSubsMgr2);
  323. if (SUCCEEDED(hr))
  324. {
  325. IEnumSubscription *pes;
  326. hr = pSubsMgr2->EnumSubscriptions(0, &pes);
  327. if (SUCCEEDED(hr))
  328. {
  329. pes->GetCount(&m_nCount);
  330. if (m_nCount > 0)
  331. {
  332. m_pCookies = new SUBSCRIPTIONCOOKIE[m_nCount];
  333. if (NULL != m_pCookies)
  334. {
  335. hr = pes->Next(m_nCount, m_pCookies, &m_nCount);
  336. }
  337. else
  338. {
  339. hr = E_OUTOFMEMORY;
  340. }
  341. }
  342. pes->Release();
  343. }
  344. pSubsMgr2->Release();
  345. }
  346. CoUninitialize();
  347. }
  348. }
  349. else
  350. {
  351. hr = E_INVALIDARG;
  352. }
  353. return hr;
  354. }
  355. HRESULT COfflineFolderEnum_CreateInstance(DWORD grfFlags, COfflineFolder *pFolder,
  356. LPENUMIDLIST *ppeidl)
  357. {
  358. HRESULT hr;
  359. *ppeidl = NULL;
  360. COfflineFolderEnum *pOOFE = new COfflineFolderEnum(grfFlags);
  361. if (NULL != pOOFE)
  362. {
  363. hr = pOOFE->Initialize(pFolder);
  364. if (SUCCEEDED(hr))
  365. {
  366. *ppeidl = pOOFE;
  367. }
  368. else
  369. {
  370. pOOFE->Release();
  371. }
  372. }
  373. else
  374. {
  375. hr = E_OUTOFMEMORY;
  376. }
  377. return hr;
  378. }
  379. //////////////////////////////////
  380. //
  381. // IUnknown Methods...
  382. //
  383. HRESULT COfflineFolderEnum::QueryInterface(REFIID iid,void **ppv)
  384. {
  385. // TraceMsg(TF_SUBSFOLDER, "COfflineFolderEnum - QI called.");
  386. if ((iid == IID_IEnumIDList) || (iid == IID_IUnknown))
  387. {
  388. *ppv = (IEnumIDList *)this;
  389. AddRef();
  390. return S_OK;
  391. }
  392. *ppv = NULL;
  393. return E_NOINTERFACE;
  394. }
  395. ULONG COfflineFolderEnum::AddRef(void)
  396. {
  397. return ++m_cRef;
  398. }
  399. ULONG COfflineFolderEnum::Release(void)
  400. {
  401. if (0L != --m_cRef)
  402. return m_cRef;
  403. delete this;
  404. return 0;
  405. }
  406. LPMYPIDL COfflineFolderEnum::NewPidl(DWORD dwSize)
  407. {
  408. LPMYPIDL pidl;
  409. // TraceMsg(TF_MEMORY, "NewPidl called");
  410. EnsureMalloc();
  411. pidl = _CreateFolderPidl(s_pMalloc, dwSize);
  412. // TraceMsg(TF_MEMORY, "\tNewPidl returned with 0x%x", pidl);
  413. return pidl;
  414. }
  415. void COfflineFolderEnum::FreePidl(LPMYPIDL pidl)
  416. {
  417. ASSERT(NULL != pidl);
  418. // TraceMsg(TF_MEMORY, "FreePidl on (0x%x) called", pidl);
  419. EnsureMalloc();
  420. s_pMalloc->Free(pidl);
  421. }
  422. // IEnumIDList Methods
  423. HRESULT COfflineFolderEnum::Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched)
  424. {
  425. HRESULT hr = S_OK;
  426. ULONG nCopied;
  427. DWORD dwBuffSize;
  428. OOEBuf ooeBuf;
  429. if ((0 == celt) ||
  430. ((celt > 1) && (NULL == pceltFetched)) ||
  431. (NULL == rgelt))
  432. {
  433. return E_INVALIDARG;
  434. }
  435. memset(&ooeBuf, 0, sizeof(ooeBuf));
  436. for (nCopied = 0; (S_OK == hr) && (m_nCurrent < m_nCount) && (nCopied < celt);
  437. m_nCurrent++, nCopied++)
  438. {
  439. rgelt[nCopied] = NULL;
  440. hr = LoadOOEntryInfo(&ooeBuf, &m_pCookies[m_nCurrent], &dwBuffSize);
  441. if (SUCCEEDED(hr))
  442. {
  443. if (IsNativeAgent(ooeBuf.clsidDest))
  444. {
  445. CLSID cookie;
  446. HRESULT hrTmp = ReadCookieFromInetDB(ooeBuf.m_URL, &cookie);
  447. if (S_OK != hrTmp)
  448. {
  449. hrTmp = WriteCookieToInetDB(ooeBuf.m_URL,&(ooeBuf.m_Cookie), FALSE);
  450. ASSERT(SUCCEEDED(hrTmp));
  451. }
  452. }
  453. LPMYPIDL pooi = NewPidl(dwBuffSize);
  454. if (pooi)
  455. {
  456. CopyToMyPooe(&ooeBuf, &(pooi->ooe)); // Always succeeds!
  457. rgelt[nCopied] = (LPITEMIDLIST)pooi;
  458. }
  459. else
  460. {
  461. hr = E_OUTOFMEMORY;
  462. }
  463. }
  464. }
  465. if (SUCCEEDED(hr))
  466. {
  467. hr = (celt == nCopied) ? S_OK : S_FALSE;
  468. }
  469. else
  470. {
  471. for (ULONG i = 0; i < nCopied; i++)
  472. {
  473. FreePidl((LPMYPIDL)rgelt[i]);
  474. }
  475. }
  476. if (NULL != pceltFetched)
  477. {
  478. *pceltFetched = SUCCEEDED(hr) ? nCopied : 0;
  479. }
  480. return hr;
  481. }
  482. HRESULT COfflineFolderEnum::Skip(ULONG celt)
  483. {
  484. HRESULT hr;
  485. m_nCurrent += celt;
  486. if (m_nCurrent > (m_nCount - 1))
  487. {
  488. m_nCurrent = m_nCount; // Passed the last one
  489. hr = S_FALSE;
  490. }
  491. else
  492. {
  493. hr = S_OK;
  494. }
  495. return hr;
  496. }
  497. HRESULT COfflineFolderEnum::Reset()
  498. {
  499. m_nCurrent = 0;
  500. return S_OK;
  501. }
  502. HRESULT COfflineFolderEnum::Clone(IEnumIDList **ppenum)
  503. {
  504. return E_NOTIMPL;
  505. }
  506. //////////////////////////////////////////////////////////////////////////////
  507. //
  508. // COfflineFolder Object
  509. //
  510. //////////////////////////////////////////////////////////////////////////////
  511. COfflineFolder::COfflineFolder(void)
  512. {
  513. TraceMsg(TF_SUBSFOLDER, "Folder - COfflineFolder() called.");
  514. _cRef = 1;
  515. viewMode = 0;
  516. colInfo = s_AllItems_cols;
  517. DllAddRef();
  518. }
  519. COfflineFolder::~COfflineFolder()
  520. {
  521. Assert(_cRef == 0); // should always have zero
  522. TraceMsg(TF_SUBSFOLDER, "Folder - ~COfflineFolder() called.");
  523. if (_pidl)
  524. ILFree(_pidl);
  525. DllRelease();
  526. }
  527. //////////////////////////////////
  528. //
  529. // IUnknown Methods...
  530. //
  531. HRESULT COfflineFolder::QueryInterface(REFIID iid, void **ppvObj)
  532. {
  533. *ppvObj = NULL; // null the out param
  534. if (iid == IID_IUnknown) {
  535. *ppvObj = (void *)this;
  536. }
  537. else if (iid == IID_IShellFolder) {
  538. *ppvObj = (void *)(IShellFolder *)this;
  539. }
  540. else if ((iid == IID_IPersistFolder) || (iid == IID_IPersist) || (iid == IID_IPersistFolder2)) {
  541. *ppvObj = (void *)(IPersistFolder *)this;
  542. }
  543. else if (iid == IID_IContextMenu)
  544. {
  545. *ppvObj = (void *)(IContextMenu *)this;
  546. }
  547. else if (iid == IID_IShellView)
  548. {
  549. return OfflineFolderView_CreateInstance(this, _pidl, ppvObj);
  550. }
  551. else if (iid == IID_IOfflineObject)
  552. {
  553. *ppvObj = (void *)this;
  554. }
  555. else if (iid == IID_IDropTarget)
  556. {
  557. // APPCOMPAT: Implementation of IDropTarget didn't follow the COM rules.
  558. // We create following object by aggregattion but QI on it for IUnknown
  559. // won't get us ptr THIS.
  560. COfflineDropTarget * podt = new COfflineDropTarget(GetDesktopWindow());
  561. if (podt)
  562. {
  563. HRESULT hr = podt->QueryInterface(iid, ppvObj);
  564. podt->Release();
  565. }
  566. else
  567. {
  568. return E_OUTOFMEMORY;
  569. }
  570. }
  571. if (*ppvObj)
  572. {
  573. ((IUnknown *)*ppvObj)->AddRef();
  574. return S_OK;
  575. }
  576. return E_NOINTERFACE;
  577. }
  578. ULONG COfflineFolder::AddRef()
  579. {
  580. return ++_cRef;
  581. }
  582. ULONG COfflineFolder::Release()
  583. {
  584. if (0L != --_cRef)
  585. return _cRef;
  586. delete this;
  587. return 0;
  588. }
  589. //////////////////////////////////
  590. //
  591. // IShellFolder methods...
  592. //
  593. HRESULT COfflineFolder::ParseDisplayName(HWND hwndOwner, LPBC pbcReserved,
  594. LPOLESTR lpszDisplayName, ULONG *pchEaten,
  595. LPITEMIDLIST *ppidl, ULONG *pdwAttributes)
  596. {
  597. // TraceMsg(TF_SUBSFOLDER, "Folder:ISF - ParseDisplayName.");
  598. *ppidl = NULL;
  599. return E_FAIL;
  600. }
  601. HRESULT COfflineFolder::EnumObjects(HWND hwndOwner, DWORD grfFlags,
  602. LPENUMIDLIST *ppenumIDList)
  603. {
  604. // TraceMsg(TF_SUBSFOLDER, "Folder:ISF - EnumObjects.");
  605. return COfflineFolderEnum_CreateInstance(grfFlags, this, ppenumIDList);
  606. }
  607. HRESULT COfflineFolder::BindToObject(LPCITEMIDLIST pidl, LPBC pbcReserved,
  608. REFIID riid, void **ppvOut)
  609. {
  610. // TraceMsg(TF_SUBSFOLDER, "Folder:ISF - BindToObject.");
  611. *ppvOut = NULL;
  612. return E_FAIL;
  613. }
  614. HRESULT COfflineFolder::BindToStorage(LPCITEMIDLIST pidl, LPBC pbcReserved,
  615. REFIID riid, void **ppvObj)
  616. {
  617. // TraceMsg(TF_SUBSFOLDER, "Folder:ISF - BindToStorage.");
  618. *ppvObj = NULL;
  619. return E_NOTIMPL;
  620. }
  621. HRESULT COfflineFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
  622. {
  623. int iRet;
  624. // TraceMsg(TF_SUBSFOLDER, "Folder:ISF - CompareIDs(%d).", lParam);
  625. if (!IS_VALID_MYPIDL(pidl1) || !IS_VALID_MYPIDL(pidl2))
  626. return E_FAIL;
  627. switch (lParam) {
  628. case ICOLC_SHORTNAME:
  629. iRet = _CompareShortName((LPMYPIDL)pidl1, (LPMYPIDL)pidl2);
  630. break;
  631. case ICOLC_URL:
  632. iRet = _CompareURL((LPMYPIDL)pidl1, (LPMYPIDL)pidl2);
  633. break;
  634. case ICOLC_STATUS:
  635. iRet = _CompareStatus((LPMYPIDL)pidl1, (LPMYPIDL)pidl2);
  636. break;
  637. case ICOLC_LAST:
  638. iRet = _CompareLastUpdate((LPMYPIDL)pidl1, (LPMYPIDL)pidl2);
  639. break;
  640. case ICOLC_ACTUALSIZE:
  641. iRet = (((LPMYPIDL)pidl1)->ooe.m_ActualSize - ((LPMYPIDL)pidl2)->ooe.m_ActualSize);
  642. break;
  643. default:
  644. iRet = -1;
  645. break;
  646. }
  647. return ResultFromShort((SHORT)iRet);
  648. }
  649. HRESULT COfflineFolder::CreateViewObject(HWND hwndOwner, REFIID riid, void **ppvOut)
  650. {
  651. HRESULT hres;
  652. // TraceMsg(TF_SUBSFOLDER, "Folder:ISF - CreateViewObject() called.");
  653. if (riid == IID_IShellView)
  654. {
  655. hres = OfflineFolderView_CreateInstance(this, _pidl, ppvOut);
  656. }
  657. else if (riid == IID_IContextMenu)
  658. {
  659. COfflineFolder * pof = new COfflineFolder();
  660. if (pof)
  661. {
  662. hres = pof->Initialize(this->_pidl);
  663. if (SUCCEEDED(hres))
  664. hres = pof->QueryInterface(riid, ppvOut);
  665. pof->Release();
  666. }
  667. else
  668. {
  669. return E_OUTOFMEMORY;
  670. }
  671. }
  672. else if (riid == IID_IDropTarget)
  673. {
  674. COfflineDropTarget * podt = new COfflineDropTarget(hwndOwner);
  675. if (podt)
  676. {
  677. hres = podt->QueryInterface(riid, ppvOut);
  678. podt->Release();
  679. }
  680. else
  681. {
  682. return E_OUTOFMEMORY;
  683. }
  684. }
  685. else if (riid == IID_IShellDetails)
  686. {
  687. COfflineDetails *pod = new COfflineDetails(hwndOwner);
  688. if (NULL != pod)
  689. {
  690. hres = pod->QueryInterface(IID_IShellDetails, ppvOut);
  691. pod->Release();
  692. }
  693. else
  694. {
  695. hres = E_OUTOFMEMORY;
  696. }
  697. }
  698. else
  699. {
  700. DBGIID("COfflineFolder::CreateViewObject() failed", riid);
  701. *ppvOut = NULL; // null the out param
  702. hres = E_NOINTERFACE;
  703. }
  704. return hres;
  705. }
  706. HRESULT COfflineFolder::GetAttributesOf(UINT cidl, LPCITEMIDLIST * apidl,
  707. ULONG * prgfInOut)
  708. {
  709. // Should we initialize this for each item in here? In other words,
  710. // if cidl > 1, then we should initialize each entry in the prgInOut array
  711. Assert( cidl == 1 );
  712. UINT attr = SFGAO_CANCOPY | SFGAO_CANDELETE | SFGAO_CANRENAME |
  713. SFGAO_HASPROPSHEET;
  714. *prgfInOut = attr;
  715. return NOERROR;
  716. }
  717. HRESULT COfflineFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl,
  718. REFIID riid, UINT * prgfInOut, void **ppvOut)
  719. {
  720. HRESULT hres;
  721. // TraceMsg(TF_SUBSFOLDER, "Folder:ISF - GetUIObjectOf.");
  722. if ((riid == IID_IContextMenu) || (riid == IID_IDataObject) ||
  723. (riid == IID_IExtractIcon) || (riid == IID_IQueryInfo))
  724. {
  725. hres = COfflineObjectItem_CreateInstance(this, cidl, apidl, riid, ppvOut);
  726. }
  727. else if (riid == IID_IDropTarget)
  728. {
  729. hres = CreateViewObject(hwndOwner, IID_IDropTarget, ppvOut);
  730. }
  731. else
  732. {
  733. *ppvOut = NULL;
  734. hres = E_FAIL;
  735. DBGIID("Unsupported interface in COfflineFolder::GetUIObjectOf()", riid);
  736. }
  737. return hres;
  738. }
  739. HRESULT COfflineFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD uFlags, LPSTRRET lpName)
  740. {
  741. // TraceMsg(TF_SUBSFOLDER, "Folde:ISF - GetDisplayNameOf.");
  742. if (!IS_VALID_MYPIDL(pidl))
  743. {
  744. lpName->uType = 0;
  745. return E_FAIL;
  746. }
  747. lpName->uType = STRRET_CSTR;
  748. lpName->cStr[0] = '\0';
  749. PCTSTR pszNameLocal;
  750. LPTSTR szNameUnaligned = NAME(&(((LPMYPIDL)pidl)->ooe));
  751. TSTR_ALIGNED_STACK_COPY( &pszNameLocal, szNameUnaligned );
  752. SHTCharToAnsi( pszNameLocal, lpName->cStr, ARRAYSIZE(lpName->cStr) );
  753. TraceMsg(TF_ALWAYS, "COfflineFolder::GetDisplayNameOf() - pszNameLocal='%s'", pszNameLocal );
  754. TraceMsg(TF_ALWAYS, "COfflineFolder::GetDisplayNameOf() - lpName->cStr='%S'", lpName->cStr );
  755. return NOERROR;
  756. }
  757. HRESULT COfflineFolder::SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl,
  758. LPCOLESTR lpszName, DWORD uFlags, LPITEMIDLIST * ppidlOut)
  759. {
  760. OOEBuf ooeBuf;
  761. POOEntry pooe = NULL;
  762. // TraceMsg(TF_SUBSFOLDER, "Folde:ISF - SetNameOf.");
  763. if (ppidlOut) {
  764. *ppidlOut = NULL; // null the out param
  765. }
  766. if (!IS_VALID_MYPIDL(pidl))
  767. return E_FAIL;
  768. HRESULT hr;
  769. WCHAR szTempName[MAX_PATH];
  770. ASSERT(lpszName);
  771. StrCpyNW(szTempName, lpszName, ARRAYSIZE(szTempName));
  772. PathRemoveBlanks(szTempName);
  773. if (szTempName[0])
  774. {
  775. memset(&ooeBuf, 0, sizeof(ooeBuf));
  776. pooe = &(((LPMYPIDL)pidl)->ooe);
  777. CopyToOOEBuf(pooe, &ooeBuf);
  778. MyOleStrToStrN(ooeBuf.m_Name, MAX_NAME, szTempName);
  779. ooeBuf.dwFlags = PROP_WEBCRAWL_NAME;
  780. hr = SaveBufferChange(&ooeBuf, FALSE);
  781. if (ppidlOut) {
  782. DWORD dwSize = BufferSize(&ooeBuf);
  783. *ppidlOut = (LPITEMIDLIST)COfflineFolderEnum::NewPidl(dwSize);
  784. if (*ppidlOut) {
  785. pooe = &(((LPMYPIDL)(*ppidlOut))->ooe);
  786. CopyToMyPooe(&ooeBuf, pooe);
  787. }
  788. }
  789. }
  790. else
  791. {
  792. WCMessageBox(hwndOwner, IDS_NONULLNAME, IDS_RENAME, MB_OK | MB_ICONSTOP);
  793. hr = E_FAIL;
  794. }
  795. return hr;
  796. }
  797. //////////////////////////////////
  798. //
  799. // IPersistFolder Methods...
  800. //
  801. HRESULT COfflineFolder::GetClassID(LPCLSID lpClassID)
  802. {
  803. // TraceMsg(TF_SUBSFOLDER, "hcf - pf - GetClassID.");
  804. *lpClassID = CLSID_OfflineFolder;
  805. return S_OK;
  806. }
  807. HRESULT COfflineFolder::Initialize(LPCITEMIDLIST pidlInit)
  808. {
  809. if (_pidl)
  810. ILFree(_pidl);
  811. _pidl = ILClone(pidlInit);
  812. if (!_pidl)
  813. return E_OUTOFMEMORY;
  814. return NOERROR;
  815. }
  816. HRESULT COfflineFolder::GetCurFolder(LPITEMIDLIST *ppidl)
  817. {
  818. if (_pidl)
  819. {
  820. *ppidl = ILClone(_pidl);
  821. return *ppidl ? NOERROR : E_OUTOFMEMORY;
  822. }
  823. *ppidl = NULL;
  824. return S_FALSE; // success but empty
  825. }
  826. //////////////////////////////////
  827. //
  828. // IContextMenu Methods...
  829. //
  830. HRESULT COfflineFolder::QueryContextMenu
  831. (
  832. HMENU hmenu,
  833. UINT indexMenu,
  834. UINT idCmdFirst,
  835. UINT idCmdLast,
  836. UINT uFlags)
  837. {
  838. USHORT cItems = 0;
  839. // TraceMsg(TF_SUBSFOLDER, "Folder:IContextMenu- QueryContextMenu.");
  840. if (uFlags == CMF_NORMAL)
  841. {
  842. HMENU hmenuHist = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(CONTEXT_MENU_OFFLINE));
  843. if (hmenuHist)
  844. {
  845. cItems = (USHORT) MergeMenuHierarchy(hmenu, hmenuHist, idCmdFirst, idCmdLast, TRUE);
  846. DestroyMenu(hmenuHist);
  847. }
  848. }
  849. return ResultFromShort(cItems); // number of menu items
  850. }
  851. STDMETHODIMP COfflineFolder::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
  852. {
  853. // TraceMsg(TF_SUBSFOLDER, "Folder:IContextMenu - InvokeCommand.");
  854. int idCmd = _GetCmdID(pici->lpVerb);
  855. if (idCmd != RSVIDM_PASTE)
  856. return OfflineFolderView_Command(pici->hwnd, idCmd);
  857. IDataObject * dataSrc = NULL;
  858. IDropTarget * pDropTrgt = NULL;
  859. HRESULT hr;
  860. hr = OleGetClipboard(&(dataSrc));
  861. if (SUCCEEDED(hr))
  862. hr = this->QueryInterface(IID_IDropTarget, (void **) &pDropTrgt);
  863. if (SUCCEEDED(hr)) {
  864. DWORD dwPrefEffect = DROPEFFECT_COPY;
  865. POINTL pt = {0, 0};
  866. hr = pDropTrgt->DragEnter(dataSrc, 0/*keystate*/, pt, &dwPrefEffect);
  867. if (SUCCEEDED(hr)) {
  868. hr = pDropTrgt->Drop(dataSrc, 0, pt, &dwPrefEffect);
  869. }
  870. }
  871. if (dataSrc)
  872. SAFERELEASE(dataSrc);
  873. if (pDropTrgt)
  874. SAFERELEASE(pDropTrgt);
  875. return hr;
  876. }
  877. STDMETHODIMP COfflineFolder::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved,
  878. LPSTR pszName, UINT cchMax)
  879. {
  880. HRESULT hres = E_FAIL;
  881. // TraceMsg(TF_SUBSFOLDER, "Folder:IContextMenu - GetCommandString.");
  882. if (uFlags == GCS_HELPTEXTA)
  883. {
  884. MLLoadStringA((UINT)idCmd + IDS_SB_FIRST, pszName, cchMax);
  885. hres = NOERROR;
  886. }
  887. return hres;
  888. }
  889. COfflineDetails::COfflineDetails(HWND hwndOwner)
  890. {
  891. ASSERT(NULL != hwndOwner);
  892. m_hwndOwner = hwndOwner;
  893. m_cRef = 1;
  894. }
  895. STDMETHODIMP COfflineDetails::QueryInterface(REFIID riid, void **ppv)
  896. {
  897. if ((IID_IUnknown == riid) || (IID_IShellDetails == riid))
  898. {
  899. *ppv = (IShellDetails *)this;
  900. }
  901. else
  902. {
  903. *ppv = NULL;
  904. return E_NOINTERFACE;
  905. }
  906. AddRef();
  907. return S_OK;
  908. }
  909. STDMETHODIMP_(ULONG) COfflineDetails::AddRef()
  910. {
  911. return ++m_cRef;
  912. }
  913. STDMETHODIMP_(ULONG) COfflineDetails::Release()
  914. {
  915. if (--m_cRef == 0)
  916. {
  917. delete this;
  918. return 0;
  919. }
  920. return m_cRef;
  921. }
  922. STDMETHODIMP COfflineDetails::GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, LPSHELLDETAILS pDetails)
  923. {
  924. HRESULT hr;
  925. if (iColumn > ICOLC_ACTUALSIZE)
  926. return E_NOTIMPL;
  927. if (NULL == pDetails)
  928. {
  929. return E_INVALIDARG;
  930. }
  931. if (NULL != pidl)
  932. {
  933. DETAILSINFO di = { pidl };
  934. hr = Generic_GetDetails(&di, colInfo[iColumn].iCol);
  935. pDetails->fmt = di.fmt;
  936. pDetails->cxChar = di.cxChar;
  937. memcpy(&pDetails->str, &di.str, sizeof(di.str));
  938. }
  939. else
  940. {
  941. pDetails->str.uType = STRRET_CSTR;
  942. pDetails->str.cStr[0] = '\0';
  943. MLLoadStringA(colInfo[iColumn].ids, pDetails->str.cStr, sizeof(pDetails->str.cStr));
  944. pDetails->fmt = colInfo[iColumn].iFmt;
  945. pDetails->cxChar = colInfo[iColumn].cchCol;
  946. hr = S_OK;
  947. }
  948. return hr;
  949. }
  950. STDMETHODIMP COfflineDetails::ColumnClick(UINT iColumn)
  951. {
  952. ShellFolderView_ReArrange(m_hwndOwner, colInfo[iColumn].iCol);
  953. return S_OK;
  954. }
  955. LPMYPIDL _CreateFolderPidl(IMalloc *pmalloc, DWORD dwSize)
  956. {
  957. LPMYPIDL pooi = (LPMYPIDL)pmalloc->Alloc(sizeof(MYPIDL) + dwSize + sizeof(USHORT));
  958. if (pooi)
  959. {
  960. memset(pooi, 0, sizeof(MYPIDL) + dwSize + sizeof(USHORT));
  961. pooi->cb = (USHORT)(dwSize + sizeof(MYPIDL));
  962. pooi->usSign = (USHORT)MYPIDL_MAGIC;
  963. // TraceMsg(TF_MEMORY, "CreatePidl %d", sizeof(MYPIDL) + dwSize);
  964. }
  965. return pooi;
  966. }