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.

294 lines
7.7 KiB

  1. #include "shellprv.h"
  2. #pragma hdrstop
  3. #include "fstreex.h"
  4. #include "bookmk.h"
  5. // *** WARNING ***
  6. //
  7. // Scrap_CreateFromDataObject is a TCHAR export from SHSCRAP.DLL, if you change its calling convention, you
  8. // must modify PFNSCRAPCREATEFROMDATAOBJECT and the wrapper fn. below
  9. //
  10. // *** WARNING ***
  11. typedef HRESULT (CALLBACK *PFNSCRAPCREATEFROMDATAOBJECT)(LPCTSTR pszPath, IDataObject *pDataObj, BOOL fLink, LPTSTR pszNewFile);
  12. STDAPI Scrap_CreateFromDataObject(LPCTSTR pszPath, IDataObject *pDataObj, BOOL fLink, LPTSTR pszNewFile)
  13. {
  14. static PFNSCRAPCREATEFROMDATAOBJECT pfn = (PFNSCRAPCREATEFROMDATAOBJECT)-1;
  15. if (pfn == (PFNSCRAPCREATEFROMDATAOBJECT)-1)
  16. {
  17. HINSTANCE hinst = LoadLibrary(TEXT("shscrap.dll"));
  18. if (hinst)
  19. {
  20. pfn = (PFNSCRAPCREATEFROMDATAOBJECT)GetProcAddress(hinst, "Scrap_CreateFromDataObject");
  21. }
  22. else
  23. {
  24. pfn = NULL;
  25. }
  26. }
  27. if (pfn)
  28. {
  29. return pfn(pszPath, pDataObj, fLink, pszNewFile);
  30. }
  31. // for failure cases just return E_UNEXPECTED;
  32. return E_UNEXPECTED;
  33. }
  34. //
  35. // Parameters:
  36. // pDataObj -- The data object passed from the drag source.
  37. // pt -- Dropped position (in screen coordinate).
  38. // pdwEffect -- Pointer to dwEffect variable to be returned to the drag source.
  39. //
  40. STDAPI SHCreateBookMark(HWND hwnd, LPCTSTR pszPath, IDataObject *pDataObj, POINTL pt, DWORD *pdwEffect)
  41. {
  42. HRESULT hres;
  43. TCHAR szNewFile[MAX_PATH];
  44. DECLAREWAITCURSOR;
  45. // We should have only one bit set.
  46. ASSERT(*pdwEffect==DROPEFFECT_COPY || *pdwEffect==DROPEFFECT_LINK || *pdwEffect==DROPEFFECT_MOVE);
  47. SetWaitCursor();
  48. hres = Scrap_CreateFromDataObject(pszPath, pDataObj, *pdwEffect == DROPEFFECT_LINK, szNewFile);
  49. ResetWaitCursor();
  50. if (SUCCEEDED(hres))
  51. {
  52. SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, szNewFile, NULL);
  53. SHChangeNotify(SHCNE_FREESPACE, SHCNF_PATH, szNewFile, NULL);
  54. PositionFileFromDrop(hwnd, szNewFile, NULL);
  55. }
  56. else
  57. {
  58. *pdwEffect = 0;
  59. }
  60. return hres;
  61. }
  62. #define MAX_FORMATS 20
  63. typedef struct
  64. {
  65. IEnumFORMATETC efmt;
  66. LONG cRef;
  67. UINT ifmt;
  68. UINT cfmt;
  69. FORMATETC afmt[1];
  70. } CStdEnumFmt;
  71. // forward
  72. extern const IEnumFORMATETCVtbl c_CStdEnumFmtVtbl;
  73. //===========================================================================
  74. // CStdEnumFmt : Constructor
  75. //===========================================================================
  76. STDAPI SHCreateStdEnumFmtEtc(UINT cfmt, const FORMATETC afmt[], IEnumFORMATETC **ppenumFormatEtc)
  77. {
  78. CStdEnumFmt * this = (CStdEnumFmt*)LocalAlloc( LPTR, SIZEOF(CStdEnumFmt) + (cfmt-1)*SIZEOF(FORMATETC));
  79. if (this)
  80. {
  81. this->efmt.lpVtbl = &c_CStdEnumFmtVtbl;
  82. this->cRef = 1;
  83. this->cfmt = cfmt;
  84. memcpy(this->afmt, afmt, cfmt * SIZEOF(FORMATETC));
  85. *ppenumFormatEtc = &this->efmt;
  86. return S_OK;
  87. }
  88. *ppenumFormatEtc = NULL;
  89. return E_OUTOFMEMORY;
  90. }
  91. STDAPI SHCreateStdEnumFmtEtcEx(UINT cfmt, const FORMATETC afmt[],
  92. IDataObject *pdtInner, IEnumFORMATETC **ppenumFormatEtc)
  93. {
  94. HRESULT hres;
  95. FORMATETC *pfmt;
  96. UINT cfmtTotal;
  97. if (pdtInner)
  98. {
  99. IEnumFORMATETC *penum;
  100. hres = pdtInner->lpVtbl->EnumFormatEtc(pdtInner, DATADIR_GET, &penum);
  101. if (SUCCEEDED(hres))
  102. {
  103. UINT cfmt2, cGot;
  104. FORMATETC fmte;
  105. for (cfmt2 = 0; penum->lpVtbl->Next(penum, 1, &fmte, &cGot) == S_OK; cfmt2++)
  106. {
  107. // count up the number of FormatEnum in cfmt2
  108. SHFree(fmte.ptd);
  109. }
  110. penum->lpVtbl->Reset(penum);
  111. cfmtTotal = cfmt + cfmt2;
  112. // Allocate the buffer for total
  113. pfmt = (FORMATETC *)LocalAlloc(LPTR, SIZEOF(FORMATETC) * cfmtTotal);
  114. if (pfmt)
  115. {
  116. UINT i;
  117. // Get formatetcs from the inner object
  118. for (i = 0; i < cfmt2; i++)
  119. {
  120. penum->lpVtbl->Next(penum, 1, &pfmt[i], &cGot);
  121. // NOTE! We do not support inner objects with non-NULL ptd
  122. ASSERT(pfmt[i].ptd == NULL);
  123. SHFree(pfmt[i].ptd);
  124. pfmt[i].ptd = NULL;
  125. }
  126. // Copy the rest
  127. if (cfmt)
  128. {
  129. #ifdef DEBUG
  130. UINT ifmt;
  131. for (ifmt = 0; ifmt < cfmt; ifmt++) {
  132. // NOTE! We do not support non-NULL ptd
  133. ASSERT(afmt[ifmt].ptd == NULL);
  134. }
  135. #endif
  136. memcpy(&pfmt[cfmt2], afmt, SIZEOF(FORMATETC) * cfmt);
  137. }
  138. }
  139. else
  140. {
  141. hres = E_OUTOFMEMORY;
  142. }
  143. penum->lpVtbl->Release(penum);
  144. }
  145. }
  146. else
  147. {
  148. hres = E_FAIL; // ptInner == NULL
  149. }
  150. if (FAILED(hres) && hres != E_OUTOFMEMORY)
  151. {
  152. //
  153. // Ignore none fatal error from pdtInner::EnumFormatEtc
  154. // We'll come here if
  155. // 1. pdtInner == NULL or
  156. // 2. pdtInner->EnumFormatEtc failed (except E_OUTOFMEMORY)
  157. //
  158. hres = NOERROR;
  159. pfmt = (FORMATETC *)afmt; // safe const -> non const cast
  160. cfmtTotal = cfmt;
  161. }
  162. if (SUCCEEDED(hres))
  163. {
  164. hres = SHCreateStdEnumFmtEtc(cfmtTotal, pfmt, ppenumFormatEtc);
  165. if (pfmt != afmt)
  166. LocalFree((HLOCAL)pfmt);
  167. }
  168. return hres;
  169. }
  170. STDMETHODIMP CStdEnumFmt_QueryInterface(IEnumFORMATETC *pefmt, REFIID riid, void **ppvObj)
  171. {
  172. CStdEnumFmt *this = IToClass(CStdEnumFmt, efmt, pefmt);
  173. if (IsEqualIID(riid, &IID_IEnumFORMATETC) || IsEqualIID(riid, &IID_IUnknown))
  174. {
  175. *ppvObj = &this->efmt;
  176. }
  177. else
  178. {
  179. *ppvObj = NULL;
  180. return E_NOINTERFACE;
  181. }
  182. this->cRef++;
  183. return NOERROR;
  184. }
  185. STDMETHODIMP_(ULONG) CStdEnumFmt_AddRef(IEnumFORMATETC *pefmt)
  186. {
  187. CStdEnumFmt *this = IToClass(CStdEnumFmt, efmt, pefmt);
  188. return ++this->cRef;
  189. }
  190. STDMETHODIMP_(ULONG) CStdEnumFmt_Release(IEnumFORMATETC *pefmt)
  191. {
  192. CStdEnumFmt *this = IToClass(CStdEnumFmt, efmt, pefmt);
  193. this->cRef--;
  194. if (this->cRef > 0)
  195. return this->cRef;
  196. LocalFree((HLOCAL)this);
  197. return 0;
  198. }
  199. STDMETHODIMP CStdEnumFmt_Next(IEnumFORMATETC *pefmt, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
  200. {
  201. CStdEnumFmt *this = IToClass(CStdEnumFmt, efmt, pefmt);
  202. UINT cfetch;
  203. HRESULT hres = S_FALSE; // assume less numbers
  204. if (this->ifmt < this->cfmt)
  205. {
  206. cfetch = this->cfmt - this->ifmt;
  207. if (cfetch>=celt)
  208. {
  209. cfetch = celt;
  210. hres = S_OK;
  211. }
  212. memcpy(rgelt, &this->afmt[this->ifmt], cfetch*SIZEOF(FORMATETC));
  213. this->ifmt += cfetch;
  214. }
  215. else
  216. {
  217. cfetch = 0;
  218. }
  219. if (pceltFethed)
  220. *pceltFethed = cfetch;
  221. return hres;
  222. }
  223. STDMETHODIMP CStdEnumFmt_Skip(IEnumFORMATETC *pefmt, ULONG celt)
  224. {
  225. CStdEnumFmt *this = IToClass(CStdEnumFmt, efmt, pefmt);
  226. this->ifmt += celt;
  227. if (this->ifmt > this->cfmt) {
  228. this->ifmt = this->cfmt;
  229. return S_FALSE;
  230. }
  231. return S_OK;
  232. }
  233. STDMETHODIMP CStdEnumFmt_Reset(IEnumFORMATETC *pefmt)
  234. {
  235. CStdEnumFmt *this = IToClass(CStdEnumFmt, efmt, pefmt);
  236. this->ifmt = 0;
  237. return S_OK;
  238. }
  239. STDMETHODIMP CStdEnumFmt_Clone(IEnumFORMATETC *pefmt, IEnumFORMATETC ** ppenum)
  240. {
  241. CStdEnumFmt *this = IToClass(CStdEnumFmt, efmt, pefmt);
  242. return SHCreateStdEnumFmtEtc(this->cfmt, this->afmt, ppenum);
  243. }
  244. const IEnumFORMATETCVtbl c_CStdEnumFmtVtbl = {
  245. CStdEnumFmt_QueryInterface, CStdEnumFmt_AddRef, CStdEnumFmt_Release,
  246. CStdEnumFmt_Next,
  247. CStdEnumFmt_Skip,
  248. CStdEnumFmt_Reset,
  249. CStdEnumFmt_Clone,
  250. };