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