mshtml: Don't crash in QueryInterface if uri is NULL.
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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  *      Preferred 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 /**************************************************************************
56  * RenderHDROP
57  *
58  * creates a CF_HDROP structure
59  */
60 HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
61 {
62         UINT i;
63         int rootsize = 0,size = 0;
64         char szRootPath[MAX_PATH];
65         char szFileName[MAX_PATH];
66         HGLOBAL hGlobal;
67         DROPFILES *pDropFiles;
68         int offset;
69
70         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
71
72         /* get the size needed */
73         size = sizeof(DROPFILES);
74
75         SHGetPathFromIDListA(pidlRoot, szRootPath);
76         PathAddBackslashA(szRootPath);
77         rootsize = strlen(szRootPath);
78
79         for (i=0; i<cidl;i++)
80         {
81           _ILSimpleGetText(apidl[i], szFileName, MAX_PATH);
82           size += rootsize + strlen(szFileName) + 1;
83         }
84
85         size++;
86
87         /* Fill the structure */
88         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
89         if(!hGlobal) return hGlobal;
90
91         pDropFiles = (DROPFILES *)GlobalLock(hGlobal);
92         pDropFiles->pFiles = sizeof(DROPFILES);
93         pDropFiles->fWide = FALSE;
94
95         offset = pDropFiles->pFiles;
96         strcpy(szFileName, szRootPath);
97
98         for (i=0; i<cidl;i++)
99         {
100
101           _ILSimpleGetText(apidl[i], szFileName + rootsize, MAX_PATH - rootsize);
102           size = strlen(szFileName) + 1;
103           strcpy(((char*)pDropFiles)+offset, szFileName);
104           offset += size;
105         }
106
107         ((char*)pDropFiles)[offset] = 0;
108         GlobalUnlock(hGlobal);
109
110         return hGlobal;
111 }
112
113 HGLOBAL RenderSHELLIDLIST (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
114 {
115         UINT i;
116         int offset = 0, sizePidl, size;
117         HGLOBAL hGlobal;
118         LPIDA   pcida;
119
120         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
121
122         /* get the size needed */
123         size = sizeof(CIDA) + sizeof (UINT)*(cidl);     /* header */
124         size += ILGetSize (pidlRoot);                   /* root pidl */
125         for(i=0; i<cidl; i++)
126         {
127           size += ILGetSize(apidl[i]);                  /* child pidls */
128         }
129
130         /* fill the structure */
131         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
132         if(!hGlobal) return hGlobal;
133         pcida = GlobalLock (hGlobal);
134         pcida->cidl = cidl;
135
136         /* root pidl */
137         offset = sizeof(CIDA) + sizeof (UINT)*(cidl);
138         pcida->aoffset[0] = offset;                     /* first element */
139         sizePidl = ILGetSize (pidlRoot);
140         memcpy(((LPBYTE)pcida)+offset, pidlRoot, sizePidl);
141         offset += sizePidl;
142
143         for(i=0; i<cidl; i++)                           /* child pidls */
144         {
145           pcida->aoffset[i+1] = offset;
146           sizePidl = ILGetSize(apidl[i]);
147           memcpy(((LPBYTE)pcida)+offset, apidl[i], sizePidl);
148           offset += sizePidl;
149         }
150
151         GlobalUnlock(hGlobal);
152         return hGlobal;
153 }
154
155 HGLOBAL RenderSHELLIDLISTOFFSET (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
156 {
157         FIXME("\n");
158         return 0;
159 }
160
161 HGLOBAL RenderFILECONTENTS (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
162 {
163         FIXME("\n");
164         return 0;
165 }
166
167 HGLOBAL RenderFILEDESCRIPTOR (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
168 {
169         FIXME("\n");
170         return 0;
171 }
172
173 HGLOBAL RenderFILENAMEA (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
174 {
175         int size = 0;
176         char szTemp[MAX_PATH], *szFileName;
177         LPITEMIDLIST pidl;
178         HGLOBAL hGlobal;
179         BOOL bSuccess;
180
181         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
182
183         /* get path of combined pidl */
184         pidl = ILCombine(pidlRoot, apidl[0]);
185         if (!pidl)
186                 return 0;
187
188         bSuccess = SHGetPathFromIDListA(pidl, szTemp);
189         SHFree(pidl);
190         if (!bSuccess)
191                 return 0;
192
193         size = strlen(szTemp) + 1;
194
195         /* fill the structure */
196         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
197         if(!hGlobal) return hGlobal;
198         szFileName = (char *)GlobalLock(hGlobal);
199         memcpy(szFileName, szTemp, size);
200         GlobalUnlock(hGlobal);
201
202         return hGlobal;
203 }
204
205 HGLOBAL RenderFILENAMEW (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
206 {
207         int size = 0;
208         WCHAR szTemp[MAX_PATH], *szFileName;
209         LPITEMIDLIST pidl;
210         HGLOBAL hGlobal;
211         BOOL bSuccess;
212
213         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
214
215         /* get path of combined pidl */
216         pidl = ILCombine(pidlRoot, apidl[0]);
217         if (!pidl)
218                 return 0;
219
220         bSuccess = SHGetPathFromIDListW(pidl, szTemp);
221         SHFree(pidl);
222         if (!bSuccess)
223                 return 0;
224
225         size = (strlenW(szTemp)+1) * sizeof(WCHAR);
226
227         /* fill the structure */
228         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
229         if(!hGlobal) return hGlobal;
230         szFileName = (WCHAR *)GlobalLock(hGlobal);
231         memcpy(szFileName, szTemp, size);
232         GlobalUnlock(hGlobal);
233
234         return hGlobal;
235 }
236
237 HGLOBAL RenderPREFEREDDROPEFFECT (DWORD dwFlags)
238 {
239         DWORD * pdwFlag;
240         HGLOBAL hGlobal;
241
242         TRACE("(0x%08lx)\n", dwFlags);
243
244         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, sizeof(DWORD));
245         if(!hGlobal) return hGlobal;
246         pdwFlag = (DWORD*)GlobalLock(hGlobal);
247         *pdwFlag = dwFlags;
248         GlobalUnlock(hGlobal);
249         return hGlobal;
250 }
251
252 /**************************************************************************
253  * IsDataInClipboard
254  *
255  * checks if there is something in the clipboard we can use
256  */
257 BOOL IsDataInClipboard (HWND hwnd)
258 {
259         BOOL ret = FALSE;
260
261         if (OpenClipboard(hwnd))
262         {
263           if (GetOpenClipboardWindow())
264           {
265             ret = IsClipboardFormatAvailable(CF_TEXT);
266           }
267           CloseClipboard();
268         }
269         return ret;
270 }