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.

353 lines
10 KiB

  1. #include "general.h"
  2. #include "folder.h"
  3. #include "utils.h"
  4. #include <mluisupp.h>
  5. #define CPP_FUNCTIONS
  6. #include <crtfree.h>
  7. // string displayed to represent missing data
  8. TCHAR g_szUnknownData[64];
  9. int CompareVersion(LPCTSTR lpszVersion1, LPCTSTR lpszVersion2);
  10. ///////////////////////////////////////////////////////////////////////////////
  11. // IShellFolder methods
  12. CControlFolder::CControlFolder()
  13. {
  14. DebugMsg(DM_TRACE,TEXT("cf - CControlFolder() called."));
  15. m_cRef = 1;
  16. DllAddRef();
  17. // initialize g_szUnknownData, a string used to represent missing data
  18. if (g_szUnknownData[0] == 0)
  19. MLLoadString(IDS_UNKNOWNDATA, g_szUnknownData, ARRAYSIZE(g_szUnknownData));
  20. }
  21. CControlFolder::~CControlFolder()
  22. {
  23. Assert(m_cRef == 0); // should always have zero
  24. DebugMsg(DM_TRACE, TEXT("cf - ~CControlFolder() called."));
  25. if (m_pidl)
  26. ILFree(m_pidl);
  27. DllRelease();
  28. }
  29. STDAPI ControlFolder_CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppvOut)
  30. {
  31. *ppvOut = NULL; // null the out param
  32. if (punkOuter)
  33. return CLASS_E_NOAGGREGATION;
  34. CControlFolder *pCFolder = new CControlFolder;
  35. if (!pCFolder)
  36. return E_OUTOFMEMORY;
  37. HRESULT hr = pCFolder->QueryInterface(riid, ppvOut);
  38. pCFolder->Release();
  39. return hr;
  40. }
  41. HRESULT CControlFolder::QueryInterface(REFIID iid, void **ppv)
  42. {
  43. DebugMsg(DM_TRACE, TEXT("cf - QueryInterface() called."));
  44. if ((iid == IID_IUnknown) || (iid == IID_IShellFolder))
  45. {
  46. *ppv = (void *)(IShellFolder*)this;
  47. }
  48. else if ((iid == IID_IPersistFolder) || (iid == IID_IPersist))
  49. {
  50. *ppv = (void *)(IPersistFolder*)this;
  51. }
  52. else if (iid == IID_IPersistFolder2)
  53. {
  54. *ppv = (void *)(IPersistFolder2*)this;
  55. }
  56. else if (iid == IID_IContextMenu)
  57. {
  58. *ppv = (void *)(IContextMenu*)this;
  59. }
  60. else if (iid == IID_IShellView)
  61. {
  62. // this is a total hack... return our view object from this folder
  63. //
  64. // the desktop.ini file for "Temporary Internet Files" has UICLSID={guid of this object}
  65. // this lets us implment only ths IShellView for this folder, leaving the IShellFolder
  66. // to the default file system. this enables operations on the pidls that are stored in
  67. // this folder that would otherwise faile since our IShellFolder is not as complete
  68. // as the default (this is the same thing the font folder does).
  69. //
  70. // to support this with defview we would either have to do a complete wrapper object
  71. // for the view implemenation, or add this hack that hands out the view object, this
  72. // assumes we know the order of calls that the shell makes to create this object
  73. // and get the IShellView implementation
  74. //
  75. return ControlFolderView_CreateInstance(this, m_pidl, ppv);
  76. }
  77. else
  78. {
  79. *ppv = NULL; // null the out param
  80. return E_NOINTERFACE;
  81. }
  82. AddRef();
  83. return S_OK;
  84. }
  85. ULONG CControlFolder::AddRef()
  86. {
  87. return ++m_cRef;
  88. }
  89. ULONG CControlFolder::Release()
  90. {
  91. if (--m_cRef)
  92. return m_cRef;
  93. delete this;
  94. return 0;
  95. }
  96. HRESULT CControlFolder::ParseDisplayName(
  97. HWND hwndOwner,
  98. LPBC pbcReserved,
  99. LPOLESTR lpszDisplayName,
  100. ULONG *pchEaten,
  101. LPITEMIDLIST *ppidl,
  102. ULONG *pdwAttributes)
  103. {
  104. DebugMsg(DM_TRACE, TEXT("cf - sf - ParseDisplayName() called."));
  105. *ppidl = NULL; // null the out param
  106. return E_FAIL;
  107. }
  108. HRESULT CControlFolder::EnumObjects(
  109. HWND hwndOwner,
  110. DWORD grfFlags,
  111. LPENUMIDLIST *ppenumIDList)
  112. {
  113. DebugMsg(DM_TRACE, TEXT("cf - sf - EnumObjects() called."));
  114. // Cannot filter on grfFlags yet - Corel Gallery expects to receive
  115. // an empty enumerator.
  116. return CControlFolderEnum_CreateInstance(m_pidl, grfFlags, ppenumIDList);
  117. }
  118. HRESULT CControlFolder::BindToObject(
  119. LPCITEMIDLIST pidl,
  120. LPBC pbcReserved,
  121. REFIID riid,
  122. void **ppvOut)
  123. {
  124. DebugMsg(DM_TRACE, TEXT("cf - sf - BindToObject() called."));
  125. *ppvOut = NULL; // null the out param
  126. return E_FAIL;
  127. }
  128. HRESULT CControlFolder::BindToStorage(
  129. LPCITEMIDLIST pidl,
  130. LPBC pbcReserved,
  131. REFIID riid,
  132. void **ppv)
  133. {
  134. DebugMsg(DM_TRACE, TEXT("cf - sf - BindToStorage() called."));
  135. *ppv = NULL; // null the out param
  136. return E_NOTIMPL;
  137. }
  138. HRESULT CControlFolder::CompareIDs(
  139. LPARAM lParam,
  140. LPCITEMIDLIST pidl1,
  141. LPCITEMIDLIST pidl2)
  142. {
  143. DebugMsg(DM_TRACE, TEXT("cf - sf - CompareIDs() called."));
  144. int iRet;
  145. LPCONTROLPIDL pcpidl1 = (LPCONTROLPIDL)pidl1;
  146. LPCONTROLPIDL pcpidl2 = (LPCONTROLPIDL)pidl2;
  147. LPCSTR lpszStr[2] = {NULL, NULL};
  148. if (pcpidl1 == NULL || pcpidl2 == NULL)
  149. return E_INVALIDARG;
  150. switch (lParam) {
  151. case SI_CONTROL:
  152. iRet = lstrcmpi(
  153. GetStringInfo(pcpidl1, SI_CONTROL),
  154. GetStringInfo(pcpidl2, SI_CONTROL));
  155. break;
  156. case SI_VERSION:
  157. lpszStr[0] = GetStringInfo(pcpidl1, SI_VERSION);
  158. lpszStr[1] = GetStringInfo(pcpidl2, SI_VERSION);
  159. if (lstrcmp(lpszStr[0], g_szUnknownData) == 0)
  160. iRet = -1;
  161. else if (lstrcmp(lpszStr[1], g_szUnknownData) == 0)
  162. iRet = 1;
  163. else
  164. iRet = CompareVersion(lpszStr[0], lpszStr[1]);
  165. break;
  166. case SI_CREATION:
  167. case SI_LASTACCESS:
  168. {
  169. FILETIME time[2];
  170. GetTimeInfo(pcpidl1, (int)lParam, &(time[0]));
  171. GetTimeInfo(pcpidl2, (int)lParam, &(time[1]));
  172. iRet = CompareFileTime(&(time[0]), &(time[1]));
  173. }
  174. break;
  175. case SI_STATUS:
  176. iRet = GetStatus(pcpidl1) - GetStatus(pcpidl2);
  177. break;
  178. case SI_TOTALSIZE:
  179. {
  180. DWORD dwSize1 = GetSizeSaved((LPCONTROLPIDL)pidl1);
  181. DWORD dwSize2 = GetSizeSaved((LPCONTROLPIDL)pidl2);
  182. iRet = (dwSize1 == dwSize2 ? 0 : (dwSize1 > dwSize2 ? 1 : -1));
  183. }
  184. break;
  185. default:
  186. iRet = -1;
  187. }
  188. return ResultFromShort((SHORT)iRet);
  189. }
  190. HRESULT CControlFolder::CreateViewObject(
  191. HWND hwndOwner,
  192. REFIID riid,
  193. void **ppvOut)
  194. {
  195. HRESULT hres;
  196. DebugMsg(DM_TRACE, TEXT("cf - sf - CreateViewObject() called."));
  197. if (riid == IID_IShellView)
  198. {
  199. hres = ControlFolderView_CreateInstance(this, m_pidl, ppvOut);
  200. }
  201. else if (riid == IID_IContextMenu)
  202. {
  203. hres = ControlFolder_CreateInstance(NULL, riid, ppvOut);
  204. }
  205. else
  206. {
  207. *ppvOut = NULL; // null the out param
  208. hres = E_NOINTERFACE;
  209. }
  210. return hres;
  211. }
  212. HRESULT CControlFolder::GetAttributesOf(UINT cidl, LPCITEMIDLIST *apidl, ULONG *prgfInOut)
  213. {
  214. // Should we initialize this for each item in here? In other words,
  215. // if cidl > 1, then we should initialize each entry in the prgInOut array
  216. Assert(cidl == 1);
  217. *prgfInOut = SFGAO_CANCOPY | SFGAO_HASPROPSHEET | SFGAO_CANMOVE | SFGAO_CANDELETE;
  218. return NOERROR;
  219. }
  220. HRESULT CControlFolder::GetUIObjectOf(
  221. HWND hwndOwner,
  222. UINT cidl,
  223. LPCITEMIDLIST *apidl,
  224. REFIID riid,
  225. UINT *prgfInOut,
  226. void **ppvOut)
  227. {
  228. HRESULT hres;
  229. if ((riid == IID_IDataObject) ||
  230. (riid == IID_IExtractIcon) ||
  231. (riid == IID_IContextMenu))
  232. {
  233. hres = CControlItem_CreateInstance(this, cidl, apidl, riid, ppvOut);
  234. }
  235. else
  236. {
  237. *ppvOut = NULL; // null the out param
  238. hres = E_FAIL;
  239. }
  240. return hres;
  241. }
  242. HRESULT CControlFolder::GetDisplayNameOf(
  243. LPCITEMIDLIST pidl,
  244. DWORD uFlags,
  245. LPSTRRET lpName)
  246. {
  247. DebugMsg(DM_TRACE, TEXT("cf - sf - GetDisplayNameOf() called."));
  248. if (pidl)
  249. {
  250. lpName->uType = STRRET_CSTR;
  251. // for the history, we'll use the title if we have one, otherwise we'll use
  252. // the url filename.
  253. if (uFlags & SHGDN_FORPARSING)
  254. lstrcpyn(
  255. lpName->cStr,
  256. GetStringInfo((LPCONTROLPIDL)pidl, SI_LOCATION),
  257. ARRAYSIZE(lpName->cStr));
  258. else
  259. lstrcpyn(
  260. lpName->cStr,
  261. GetStringInfo((LPCONTROLPIDL)pidl, SI_CONTROL),
  262. ARRAYSIZE(lpName->cStr));
  263. return NOERROR;
  264. }
  265. else
  266. {
  267. return E_INVALIDARG;
  268. }
  269. }
  270. HRESULT CControlFolder::SetNameOf(
  271. HWND hwndOwner,
  272. LPCITEMIDLIST pidl,
  273. LPCOLESTR lpszName,
  274. DWORD uFlags,
  275. LPITEMIDLIST *ppidlOut)
  276. {
  277. DebugMsg(DM_TRACE, TEXT("cf - sf - SetNameOf() called."));
  278. *ppidlOut = NULL; // null the out param
  279. return E_FAIL;
  280. }
  281. ///////////////////////////////////////////////////////////////////////////////
  282. // Helper functions
  283. int CompareVersion(LPCTSTR lpszVersion1, LPCTSTR lpszVersion2)
  284. {
  285. LPCTSTR pszVerNum[2] = {lpszVersion1, lpszVersion2};
  286. int nVerNum[2];
  287. int nResult = 0;
  288. while (nResult == 0 && *(pszVerNum[0]) != '\0' && *(pszVerNum[1]) != '\0')
  289. {
  290. nVerNum[0] = StrToInt(pszVerNum[0]++);
  291. nVerNum[1] = StrToInt(pszVerNum[1]++);
  292. nResult = ((nVerNum[0] < nVerNum[1]) ?
  293. (-1) :
  294. (nVerNum[0] > nVerNum[1] ? 1 : 0));
  295. }
  296. return nResult;
  297. }