xref: /reactos/dll/win32/shell32/wine/clipboard.c (revision 52dd07fe)
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