Return "file not found" error values instead of E_INVALIDARG if
[wine] / dlls / shell32 / clipboard.c
1 /*
2  *      clipboard helper functions
3  *
4  *      Copyright 2000  Juergen Schmied <juergen.schmied@debitel.de>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * NOTES:
21  *
22  * For copy & paste functions within contextmenus does the shell use
23  * the OLE clipboard functions in combination with dataobjects.
24  * The OLE32.DLL gets loaded with LoadLibrary
25  *
26  * - a right mousebutton-copy sets the following formats:
27  *  classic:
28  *      Shell IDList Array
29  *      Prefered Drop Effect
30  *      Shell Object Offsets
31  *      HDROP
32  *      FileName
33  *  ole:
34  *      OlePrivateData (ClipboardDataObjectInterface)
35  *
36  */
37
38 #include <stdarg.h>
39 #include <string.h>
40
41 #include "windef.h"
42 #include "winbase.h"
43 #include "winreg.h"
44 #include "wingdi.h"
45 #include "pidl.h"
46 #include "undocshell.h"
47 #include "shell32_main.h"
48 #include "shlwapi.h"
49
50 #include "wine/unicode.h"
51 #include "wine/debug.h"
52
53 WINE_DEFAULT_DEBUG_CHANNEL(shell);
54
55 HRESULT (WINAPI *pOleInitialize)(LPVOID reserved);
56 void    (WINAPI *pOleUninitialize)(void);
57 HRESULT (WINAPI *pRegisterDragDrop)(HWND hwnd, IDropTarget* pDropTarget);
58 HRESULT (WINAPI *pRevokeDragDrop)(HWND hwnd);
59 HRESULT (WINAPI *pDoDragDrop)(LPDATAOBJECT,LPDROPSOURCE,DWORD,DWORD*);
60 void    (WINAPI *pReleaseStgMedium)(STGMEDIUM* pmedium);
61 HRESULT (WINAPI *pOleSetClipboard)(IDataObject* pDataObj);
62 HRESULT (WINAPI *pOleGetClipboard)(IDataObject** ppDataObj);
63
64 /**************************************************************************
65  * GetShellOle
66  *
67  * make sure OLE32.DLL is loaded
68  */
69 BOOL GetShellOle(void)
70 {
71     static HANDLE hOle32 = NULL;
72     if(!hOle32)
73     {
74         hOle32 = LoadLibraryA("ole32.dll");
75         if(hOle32)
76         {
77             pOleInitialize=(void*)GetProcAddress(hOle32,"OleInitialize");
78             pOleUninitialize=(void*)GetProcAddress(hOle32,"OleUninitialize");
79             pRegisterDragDrop=(void*)GetProcAddress(hOle32,"RegisterDragDrop");
80             pRevokeDragDrop=(void*)GetProcAddress(hOle32,"RevokeDragDrop");
81             pDoDragDrop=(void*)GetProcAddress(hOle32,"DoDragDrop");
82             pReleaseStgMedium=(void*)GetProcAddress(hOle32,"ReleaseStgMedium");
83             pOleSetClipboard=(void*)GetProcAddress(hOle32,"OleSetClipboard");
84             pOleGetClipboard=(void*)GetProcAddress(hOle32,"OleGetClipboard");
85
86             pOleInitialize(NULL);
87         }
88     }
89     return TRUE;
90 }
91
92 /**************************************************************************
93  * RenderHDROP
94  *
95  * creates a CF_HDROP structure
96  */
97 HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
98 {
99         UINT i;
100         int rootsize = 0,size = 0;
101         char szRootPath[MAX_PATH];
102         char szFileName[MAX_PATH];
103         HGLOBAL hGlobal;
104         DROPFILES *pDropFiles;
105         int offset;
106
107         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
108
109         /* get the size needed */
110         size = sizeof(DROPFILES);
111
112         SHGetPathFromIDListA(pidlRoot, szRootPath);
113         PathAddBackslashA(szRootPath);
114         rootsize = strlen(szRootPath);
115
116         for (i=0; i<cidl;i++)
117         {
118           _ILSimpleGetText(apidl[i], szFileName, MAX_PATH);
119           size += rootsize + strlen(szFileName) + 1;
120         }
121
122         size++;
123
124         /* Fill the structure */
125         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
126         if(!hGlobal) return hGlobal;
127
128         pDropFiles = (DROPFILES *)GlobalLock(hGlobal);
129         pDropFiles->pFiles = sizeof(DROPFILES);
130         pDropFiles->fWide = FALSE;
131
132         offset = pDropFiles->pFiles;
133         strcpy(szFileName, szRootPath);
134
135         for (i=0; i<cidl;i++)
136         {
137
138           _ILSimpleGetText(apidl[i], szFileName + rootsize, MAX_PATH - rootsize);
139           size = strlen(szFileName) + 1;
140           strcpy(((char*)pDropFiles)+offset, szFileName);
141           offset += size;
142         }
143
144         ((char*)pDropFiles)[offset] = 0;
145         GlobalUnlock(hGlobal);
146
147         return hGlobal;
148 }
149
150 HGLOBAL RenderSHELLIDLIST (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
151 {
152         UINT i;
153         int offset = 0, sizePidl, size;
154         HGLOBAL hGlobal;
155         LPIDA   pcida;
156
157         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
158
159         /* get the size needed */
160         size = sizeof(CIDA) + sizeof (UINT)*(cidl);     /* header */
161         size += ILGetSize (pidlRoot);                   /* root pidl */
162         for(i=0; i<cidl; i++)
163         {
164           size += ILGetSize(apidl[i]);                  /* child pidls */
165         }
166
167         /* fill the structure */
168         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
169         if(!hGlobal) return hGlobal;
170         pcida = GlobalLock (hGlobal);
171         pcida->cidl = cidl;
172
173         /* root pidl */
174         offset = sizeof(CIDA) + sizeof (UINT)*(cidl);
175         pcida->aoffset[0] = offset;                     /* first element */
176         sizePidl = ILGetSize (pidlRoot);
177         memcpy(((LPBYTE)pcida)+offset, pidlRoot, sizePidl);
178         offset += sizePidl;
179
180         for(i=0; i<cidl; i++)                           /* child pidls */
181         {
182           pcida->aoffset[i+1] = offset;
183           sizePidl = ILGetSize(apidl[i]);
184           memcpy(((LPBYTE)pcida)+offset, apidl[i], sizePidl);
185           offset += sizePidl;
186         }
187
188         GlobalUnlock(hGlobal);
189         return hGlobal;
190 }
191
192 HGLOBAL RenderSHELLIDLISTOFFSET (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
193 {
194         FIXME("\n");
195         return 0;
196 }
197
198 HGLOBAL RenderFILECONTENTS (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
199 {
200         FIXME("\n");
201         return 0;
202 }
203
204 HGLOBAL RenderFILEDESCRIPTOR (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
205 {
206         FIXME("\n");
207         return 0;
208 }
209
210 HGLOBAL RenderFILENAMEA (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
211 {
212         int size = 0;
213         char szTemp[MAX_PATH], *szFileName;
214         LPITEMIDLIST pidl;
215         HGLOBAL hGlobal;
216         HRESULT hr;
217
218         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
219
220         /* get path of combined pidl */
221         pidl = ILCombine(pidlRoot, apidl[0]);
222         if (!pidl)
223                 return 0;
224
225         hr = SHELL_GetPathFromIDListA(pidl, szTemp, MAX_PATH);
226         SHFree(pidl);
227         if (FAILED(hr))
228                 return 0;
229
230         size = strlen(szTemp) + 1;
231
232         /* fill the structure */
233         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
234         if(!hGlobal) return hGlobal;
235         szFileName = (char *)GlobalLock(hGlobal);
236         memcpy(szFileName, szTemp, size);
237         GlobalUnlock(hGlobal);
238
239         return hGlobal;
240 }
241
242 HGLOBAL RenderFILENAMEW (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
243 {
244         int size = 0;
245         WCHAR szTemp[MAX_PATH], *szFileName;
246         LPITEMIDLIST pidl;
247         HGLOBAL hGlobal;
248         HRESULT hr;
249
250         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
251
252         /* get path of combined pidl */
253         pidl = ILCombine(pidlRoot, apidl[0]);
254         if (!pidl)
255                 return 0;
256
257         hr = SHELL_GetPathFromIDListW(pidl, szTemp, MAX_PATH);
258         SHFree(pidl);
259         if (FAILED(hr))
260                 return 0;
261
262         size = (strlenW(szTemp)+1) * sizeof(WCHAR);
263
264         /* fill the structure */
265         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
266         if(!hGlobal) return hGlobal;
267         szFileName = (WCHAR *)GlobalLock(hGlobal);
268         memcpy(szFileName, szTemp, size);
269         GlobalUnlock(hGlobal);
270
271         return hGlobal;
272 }
273
274 HGLOBAL RenderPREFEREDDROPEFFECT (DWORD dwFlags)
275 {
276         DWORD * pdwFlag;
277         HGLOBAL hGlobal;
278
279         TRACE("(0x%08lx)\n", dwFlags);
280
281         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, sizeof(DWORD));
282         if(!hGlobal) return hGlobal;
283         pdwFlag = (DWORD*)GlobalLock(hGlobal);
284         *pdwFlag = dwFlags;
285         GlobalUnlock(hGlobal);
286         return hGlobal;
287 }
288
289 /**************************************************************************
290  * IsDataInClipboard
291  *
292  * checks if there is something in the clipboard we can use
293  */
294 BOOL IsDataInClipboard (HWND hwnd)
295 {
296         BOOL ret = FALSE;
297
298         if (OpenClipboard(hwnd))
299         {
300           if (GetOpenClipboardWindow())
301           {
302             ret = IsClipboardFormatAvailable(CF_TEXT);
303           }
304           CloseClipboard();
305         }
306         return ret;
307 }