Free the debug info when making a critical section global.
[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 <string.h>
39
40 #include "winreg.h"
41 #include "pidl.h"
42 #include "undocshell.h"
43 #include "shell32_main.h"
44 #include "shlwapi.h"
45
46 #include "wine/unicode.h"
47 #include "wine/debug.h"
48
49 WINE_DEFAULT_DEBUG_CHANNEL(shell);
50
51 HRESULT (WINAPI *pOleInitialize)(LPVOID reserved);
52 void    (WINAPI *pOleUninitialize)(void);
53 HRESULT (WINAPI *pRegisterDragDrop)(HWND hwnd, IDropTarget* pDropTarget);
54 HRESULT (WINAPI *pRevokeDragDrop)(HWND hwnd);
55 HRESULT (WINAPI *pDoDragDrop)(LPDATAOBJECT,LPDROPSOURCE,DWORD,DWORD*);
56 void    (WINAPI *pReleaseStgMedium)(STGMEDIUM* pmedium);
57 HRESULT (WINAPI *pOleSetClipboard)(IDataObject* pDataObj);
58 HRESULT (WINAPI *pOleGetClipboard)(IDataObject** ppDataObj);
59
60 /**************************************************************************
61  * GetShellOle
62  *
63  * make sure OLE32.DLL is loaded
64  */
65 BOOL GetShellOle(void)
66 {
67     static HANDLE hOle32 = NULL;
68     if(!hOle32)
69     {
70         hOle32 = LoadLibraryA("ole32.dll");
71         if(hOle32)
72         {
73             pOleInitialize=(void*)GetProcAddress(hOle32,"OleInitialize");
74             pOleUninitialize=(void*)GetProcAddress(hOle32,"OleUninitialize");
75             pRegisterDragDrop=(void*)GetProcAddress(hOle32,"RegisterDragDrop");
76             pRevokeDragDrop=(void*)GetProcAddress(hOle32,"RevokeDragDrop");
77             pDoDragDrop=(void*)GetProcAddress(hOle32,"DoDragDrop");
78             pReleaseStgMedium=(void*)GetProcAddress(hOle32,"ReleaseStgMedium");
79             pOleSetClipboard=(void*)GetProcAddress(hOle32,"OleSetClipboard");
80             pOleGetClipboard=(void*)GetProcAddress(hOle32,"OleGetClipboard");
81
82             pOleInitialize(NULL);
83         }
84     }
85     return TRUE;
86 }
87
88 /**************************************************************************
89  * RenderHDROP
90  *
91  * creates a CF_HDROP structure
92  */
93 HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
94 {
95         UINT i;
96         int rootsize = 0,size = 0;
97         char szRootPath[MAX_PATH];
98         char szFileName[MAX_PATH];
99         HGLOBAL hGlobal;
100         DROPFILES *pDropFiles;
101         int offset;
102
103         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
104
105         /* get the size needed */
106         size = sizeof(DROPFILES);
107
108         SHGetPathFromIDListA(pidlRoot, szRootPath);
109         PathAddBackslashA(szRootPath);
110         rootsize = strlen(szRootPath);
111
112         for (i=0; i<cidl;i++)
113         {
114           _ILSimpleGetText(apidl[i], szFileName, MAX_PATH);
115           size += rootsize + strlen(szFileName) + 1;
116         }
117
118         size++;
119
120         /* Fill the structure */
121         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
122         if(!hGlobal) return hGlobal;
123
124         pDropFiles = (DROPFILES *)GlobalLock(hGlobal);
125         pDropFiles->pFiles = sizeof(DROPFILES);
126         pDropFiles->fWide = FALSE;
127
128         offset = pDropFiles->pFiles;
129         strcpy(szFileName, szRootPath);
130
131         for (i=0; i<cidl;i++)
132         {
133
134           _ILSimpleGetText(apidl[i], szFileName + rootsize, MAX_PATH - rootsize);
135           size = strlen(szFileName) + 1;
136           strcpy(((char*)pDropFiles)+offset, szFileName);
137           offset += size;
138         }
139
140         ((char*)pDropFiles)[offset] = 0;
141         GlobalUnlock(hGlobal);
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 RenderSHELLIDLISTOFFSET (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
189 {
190         FIXME("\n");
191         return 0;
192 }
193
194 HGLOBAL RenderFILECONTENTS (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
195 {
196         FIXME("\n");
197         return 0;
198 }
199
200 HGLOBAL RenderFILEDESCRIPTOR (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
201 {
202         FIXME("\n");
203         return 0;
204 }
205
206 HGLOBAL RenderFILENAMEA (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
207 {
208         int len, size = 0;
209         char szTemp[MAX_PATH], *szFileName;
210         HGLOBAL hGlobal;
211
212         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
213
214         /* build name of first file */
215         SHGetPathFromIDListA(pidlRoot, szTemp);
216         PathAddBackslashA(szTemp);
217         len = strlen(szTemp);
218         _ILSimpleGetText(apidl[0], szTemp+len, MAX_PATH - len);
219         size = strlen(szTemp) + 1;
220
221         /* fill the structure */
222         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
223         if(!hGlobal) return hGlobal;
224         szFileName = (char *)GlobalLock(hGlobal);
225         memcpy(szFileName, szTemp, size);
226         GlobalUnlock(hGlobal);
227         return hGlobal;
228 }
229
230 HGLOBAL RenderFILENAMEW (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
231 {
232         int len, size = 0;
233         WCHAR szTemp[MAX_PATH], *szFileName;
234         HGLOBAL hGlobal;
235
236         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
237
238         /* build name of first file */
239         SHGetPathFromIDListW(pidlRoot, szTemp);
240         PathAddBackslashW(szTemp);
241         len = strlenW(szTemp);
242         _ILSimpleGetTextW(apidl[0], szTemp+len, MAX_PATH - len);
243         size = sizeof(WCHAR) * (strlenW(szTemp)+1);
244
245         /* fill the structure */
246         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
247         if(!hGlobal) return hGlobal;
248         szFileName = (WCHAR *)GlobalLock(hGlobal);
249         memcpy(szFileName, szTemp, size);
250         GlobalUnlock(hGlobal);
251         return hGlobal;
252 }
253
254 HGLOBAL RenderPREFEREDDROPEFFECT (DWORD dwFlags)
255 {
256         DWORD * pdwFlag;
257         HGLOBAL hGlobal;
258
259         TRACE("(0x%08lx)\n", dwFlags);
260
261         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, sizeof(DWORD));
262         if(!hGlobal) return hGlobal;
263         pdwFlag = (DWORD*)GlobalLock(hGlobal);
264         *pdwFlag = dwFlags;
265         GlobalUnlock(hGlobal);
266         return hGlobal;
267 }
268
269 /**************************************************************************
270  * IsDataInClipboard
271  *
272  * checks if there is something in the clipboard we can use
273  */
274 BOOL IsDataInClipboard (HWND hwnd)
275 {
276         BOOL ret = FALSE;
277
278         if (OpenClipboard(hwnd))
279         {
280           if (GetOpenClipboardWindow())
281           {
282             ret = IsClipboardFormatAvailable(CF_TEXT);
283           }
284           CloseClipboard();
285         }
286         return ret;
287 }