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 #define WIN32_NO_STATUS
39 #define _INC_WINDOWS
40
41 #include <windef.h>
42 #include <winbase.h>
43 #include <shlobj.h>
44 #include <wine/debug.h>
45 #include <wine/unicode.h>
46
47 #include "shell32_main.h"
48
49 WINE_DEFAULT_DEBUG_CHANNEL(shell);
50
51 /**************************************************************************
52 * RenderHDROP
53 *
54 * creates a CF_HDROP structure
55 */
RenderHDROP(LPITEMIDLIST pidlRoot,LPITEMIDLIST * apidl,UINT cidl)56 HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
57 {
58 UINT i;
59 #ifdef __REACTOS__
60 int size = 0;
61 #else
62 int rootlen = 0,size = 0;
63 WCHAR wszRootPath[MAX_PATH];
64 #endif
65 WCHAR wszFileName[MAX_PATH];
66 HGLOBAL hGlobal = NULL;
67 DROPFILES *pDropFiles;
68 int offset;
69 #ifdef __REACTOS__
70 LPITEMIDLIST *pidls;
71 #endif
72
73 TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
74
75 #ifdef __REACTOS__
76 pidls = (LPITEMIDLIST *)HeapAlloc(GetProcessHeap(), 0, cidl * sizeof(*pidls));
77 if (!pidls)
78 goto cleanup;
79 #endif
80
81 /* get the size needed */
82 size = sizeof(DROPFILES);
83
84 #ifndef __REACTOS__
85 SHGetPathFromIDListW(pidlRoot, wszRootPath);
86 PathAddBackslashW(wszRootPath);
87 rootlen = strlenW(wszRootPath);
88 #endif
89
90 for (i=0; i<cidl;i++)
91 {
92 #ifdef __REACTOS__
93 pidls[i] = ILCombine(pidlRoot, apidl[i]);
94 SHGetPathFromIDListW(pidls[i], wszFileName);
95 size += (wcslen(wszFileName) + 1) * sizeof(WCHAR);
96 #else
97 _ILSimpleGetTextW(apidl[i], wszFileName, MAX_PATH);
98 size += (rootlen + strlenW(wszFileName) + 1) * sizeof(WCHAR);
99 #endif
100 }
101
102 size += sizeof(WCHAR);
103
104 /* Fill the structure */
105 hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
106 #ifdef __REACTOS__
107 if(!hGlobal) goto cleanup;
108 #else
109 if(!hGlobal) return hGlobal;
110 #endif
111
112 pDropFiles = GlobalLock(hGlobal);
113 offset = (sizeof(DROPFILES) + sizeof(WCHAR) - 1) / sizeof(WCHAR);
114 pDropFiles->pFiles = offset * sizeof(WCHAR);
115 pDropFiles->fWide = TRUE;
116
117 #ifndef __REACTOS__
118 strcpyW(wszFileName, wszRootPath);
119 #endif
120
121 for (i=0; i<cidl;i++)
122 {
123
124 #ifdef __REACTOS__
125 SHGetPathFromIDListW(pidls[i], wszFileName);
126 wcscpy(((WCHAR*)pDropFiles)+offset, wszFileName);
127 offset += wcslen(wszFileName) + 1;
128 ILFree(pidls[i]);
129 #else
130 _ILSimpleGetTextW(apidl[i], wszFileName + rootlen, MAX_PATH - rootlen);
131 strcpyW(((WCHAR*)pDropFiles)+offset, wszFileName);
132 offset += strlenW(wszFileName) + 1;
133 #endif
134 }
135
136 ((WCHAR*)pDropFiles)[offset] = 0;
137 GlobalUnlock(hGlobal);
138
139 #ifdef __REACTOS__
140 cleanup:
141 if(pidls)
142 HeapFree(GetProcessHeap(), 0, pidls);
143 #endif
144
145 return hGlobal;
146 }
147
RenderSHELLIDLIST(LPITEMIDLIST pidlRoot,LPITEMIDLIST * apidl,UINT cidl)148 HGLOBAL RenderSHELLIDLIST (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
149 {
150 UINT i;
151 int offset = 0, sizePidl, size;
152 HGLOBAL hGlobal;
153 LPIDA pcida;
154
155 TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
156
157 /* get the size needed */
158 size = sizeof(CIDA) + sizeof (UINT)*(cidl); /* header */
159 size += ILGetSize (pidlRoot); /* root pidl */
160 for(i=0; i<cidl; i++)
161 {
162 size += ILGetSize(apidl[i]); /* child pidls */
163 }
164
165 /* fill the structure */
166 hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
167 if(!hGlobal) return hGlobal;
168 pcida = GlobalLock (hGlobal);
169 pcida->cidl = cidl;
170
171 /* root pidl */
172 offset = sizeof(CIDA) + sizeof (UINT)*(cidl);
173 pcida->aoffset[0] = offset; /* first element */
174 sizePidl = ILGetSize (pidlRoot);
175 memcpy(((LPBYTE)pcida)+offset, pidlRoot, sizePidl);
176 offset += sizePidl;
177
178 for(i=0; i<cidl; i++) /* child pidls */
179 {
180 pcida->aoffset[i+1] = offset;
181 sizePidl = ILGetSize(apidl[i]);
182 memcpy(((LPBYTE)pcida)+offset, apidl[i], sizePidl);
183 offset += sizePidl;
184 }
185
186 GlobalUnlock(hGlobal);
187 return hGlobal;
188 }
189
RenderFILENAMEA(LPITEMIDLIST pidlRoot,LPITEMIDLIST * apidl,UINT cidl)190 HGLOBAL RenderFILENAMEA (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
191 {
192 int size = 0;
193 char szTemp[MAX_PATH], *szFileName;
194 LPITEMIDLIST pidl;
195 HGLOBAL hGlobal;
196 BOOL bSuccess;
197
198 TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
199
200 /* get path of combined pidl */
201 pidl = ILCombine(pidlRoot, apidl[0]);
202 if (!pidl)
203 return 0;
204
205 bSuccess = SHGetPathFromIDListA(pidl, szTemp);
206 SHFree(pidl);
207 if (!bSuccess)
208 return 0;
209
210 size = strlen(szTemp) + 1;
211
212 /* fill the structure */
213 hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
214 if(!hGlobal) return hGlobal;
215 szFileName = GlobalLock(hGlobal);
216 memcpy(szFileName, szTemp, size);
217 GlobalUnlock(hGlobal);
218
219 return hGlobal;
220 }
221
RenderFILENAMEW(LPITEMIDLIST pidlRoot,LPITEMIDLIST * apidl,UINT cidl)222 HGLOBAL RenderFILENAMEW (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
223 {
224 int size = 0;
225 WCHAR szTemp[MAX_PATH], *szFileName;
226 LPITEMIDLIST pidl;
227 HGLOBAL hGlobal;
228 BOOL bSuccess;
229
230 TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
231
232 /* get path of combined pidl */
233 pidl = ILCombine(pidlRoot, apidl[0]);
234 if (!pidl)
235 return 0;
236
237 bSuccess = SHGetPathFromIDListW(pidl, szTemp);
238 SHFree(pidl);
239 if (!bSuccess)
240 return 0;
241
242 size = (strlenW(szTemp)+1) * sizeof(WCHAR);
243
244 /* fill the structure */
245 hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
246 if(!hGlobal) return hGlobal;
247 szFileName = GlobalLock(hGlobal);
248 memcpy(szFileName, szTemp, size);
249 GlobalUnlock(hGlobal);
250
251 return hGlobal;
252 }
253