- Clear bits in structure passed to IOleCommandTarget_QueryStatus to
[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/debug.h"
47
48 WINE_DEFAULT_DEBUG_CHANNEL(shell);
49
50 HRESULT (WINAPI *pOleInitialize)(LPVOID reserved);
51 void    (WINAPI *pOleUninitialize)(void);
52 HRESULT (WINAPI *pRegisterDragDrop)(HWND hwnd, IDropTarget* pDropTarget);
53 HRESULT (WINAPI *pRevokeDragDrop)(HWND hwnd);
54 HRESULT (WINAPI *pDoDragDrop)(LPDATAOBJECT,LPDROPSOURCE,DWORD,DWORD*);
55 void    (WINAPI *pReleaseStgMedium)(STGMEDIUM* pmedium);
56 HRESULT (WINAPI *pOleSetClipboard)(IDataObject* pDataObj);
57 HRESULT (WINAPI *pOleGetClipboard)(IDataObject** ppDataObj);
58
59 /**************************************************************************
60  * GetShellOle
61  *
62  * make sure OLE32.DLL is loaded
63  */
64 BOOL GetShellOle(void)
65 {
66     static HANDLE hOle32 = NULL;
67     if(!hOle32)
68     {
69         hOle32 = LoadLibraryA("ole32.dll");
70         if(hOle32)
71         {
72             pOleInitialize=(void*)GetProcAddress(hOle32,"OleInitialize");
73             pOleUninitialize=(void*)GetProcAddress(hOle32,"OleUninitialize");
74             pRegisterDragDrop=(void*)GetProcAddress(hOle32,"RegisterDragDrop");
75             pRevokeDragDrop=(void*)GetProcAddress(hOle32,"RevokeDragDrop");
76             pDoDragDrop=(void*)GetProcAddress(hOle32,"DoDragDrop");
77             pReleaseStgMedium=(void*)GetProcAddress(hOle32,"ReleaseStgMedium");
78             pOleSetClipboard=(void*)GetProcAddress(hOle32,"OleSetClipboard");
79             pOleGetClipboard=(void*)GetProcAddress(hOle32,"OleGetClipboard");
80
81             pOleInitialize(NULL);
82         }
83     }
84     return TRUE;
85 }
86
87 /**************************************************************************
88  * RenderHDROP
89  *
90  * creates a CF_HDROP structure
91  */
92 HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
93 {
94         UINT i;
95         int rootsize = 0,size = 0;
96         char szRootPath[MAX_PATH];
97         char szFileName[MAX_PATH];
98         HGLOBAL hGlobal;
99         DROPFILES *pDropFiles;
100         int offset;
101
102         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
103
104         /* get the size needed */
105         size = sizeof(DROPFILES);
106
107         SHGetPathFromIDListA(pidlRoot, szRootPath);
108         PathAddBackslashA(szRootPath);
109         rootsize = strlen(szRootPath);
110
111         for (i=0; i<cidl;i++)
112         {
113           _ILSimpleGetText(apidl[i], szFileName, MAX_PATH);
114           size += rootsize + strlen(szFileName) + 1;
115         }
116
117         size++;
118
119         /* Fill the structure */
120         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
121         if(!hGlobal) return hGlobal;
122
123         pDropFiles = (DROPFILES *)GlobalLock(hGlobal);
124         pDropFiles->pFiles = sizeof(DROPFILES);
125         pDropFiles->fWide = FALSE;
126
127         offset = pDropFiles->pFiles;
128         strcpy(szFileName, szRootPath);
129
130         for (i=0; i<cidl;i++)
131         {
132
133           _ILSimpleGetText(apidl[i], szFileName + rootsize, MAX_PATH - rootsize);
134           size = strlen(szFileName) + 1;
135           strcpy(((char*)pDropFiles)+offset, szFileName);
136           offset += size;
137         }
138
139         ((char*)pDropFiles)[offset] = 0;
140         GlobalUnlock(hGlobal);
141
142         return hGlobal;
143 }
144
145 HGLOBAL RenderSHELLIDLIST (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
146 {
147         UINT i;
148         int offset = 0, sizePidl, size;
149         HGLOBAL hGlobal;
150         LPIDA   pcida;
151
152         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
153
154         /* get the size needed */
155         size = sizeof(CIDA) + sizeof (UINT)*(cidl);     /* header */
156         size += ILGetSize (pidlRoot);                   /* root pidl */
157         for(i=0; i<cidl; i++)
158         {
159           size += ILGetSize(apidl[i]);                  /* child pidls */
160         }
161
162         /* fill the structure */
163         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
164         if(!hGlobal) return hGlobal;
165         pcida = GlobalLock (hGlobal);
166         pcida->cidl = cidl;
167
168         /* root pidl */
169         offset = sizeof(CIDA) + sizeof (UINT)*(cidl);
170         pcida->aoffset[0] = offset;                     /* first element */
171         sizePidl = ILGetSize (pidlRoot);
172         memcpy(((LPBYTE)pcida)+offset, pidlRoot, sizePidl);
173         offset += sizePidl;
174
175         for(i=0; i<cidl; i++)                           /* child pidls */
176         {
177           pcida->aoffset[i+1] = offset;
178           sizePidl = ILGetSize(apidl[i]);
179           memcpy(((LPBYTE)pcida)+offset, apidl[i], sizePidl);
180           offset += sizePidl;
181         }
182
183         GlobalUnlock(hGlobal);
184         return hGlobal;
185 }
186
187 HGLOBAL RenderSHELLIDLISTOFFSET (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
188 {
189         FIXME("\n");
190         return 0;
191 }
192
193 HGLOBAL RenderFILECONTENTS (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
194 {
195         FIXME("\n");
196         return 0;
197 }
198
199 HGLOBAL RenderFILEDESCRIPTOR (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
200 {
201         FIXME("\n");
202         return 0;
203 }
204
205 HGLOBAL RenderFILENAME (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
206 {
207         int len, size = 0;
208         char szTemp[MAX_PATH], *szFileName;
209         HGLOBAL hGlobal;
210
211         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
212
213         /* build name of first file */
214         SHGetPathFromIDListA(pidlRoot, szTemp);
215         PathAddBackslashA(szTemp);
216         len = strlen(szTemp);
217         _ILSimpleGetText(apidl[0], szTemp+len, MAX_PATH - len);
218         size = strlen(szTemp) + 1;
219
220         /* fill the structure */
221         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
222         if(!hGlobal) return hGlobal;
223         szFileName = (char *)GlobalLock(hGlobal);
224         GlobalUnlock(hGlobal);
225         return hGlobal;
226 }
227
228 HGLOBAL RenderPREFEREDDROPEFFECT (DWORD dwFlags)
229 {
230         DWORD * pdwFlag;
231         HGLOBAL hGlobal;
232
233         TRACE("(0x%08lx)\n", dwFlags);
234
235         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, sizeof(DWORD));
236         if(!hGlobal) return hGlobal;
237         pdwFlag = (DWORD*)GlobalLock(hGlobal);
238         *pdwFlag = dwFlags;
239         GlobalUnlock(hGlobal);
240         return hGlobal;
241 }
242
243 /**************************************************************************
244  * IsDataInClipboard
245  *
246  * checks if there is something in the clipboard we can use
247  */
248 BOOL IsDataInClipboard (HWND hwnd)
249 {
250         BOOL ret = FALSE;
251
252         if (OpenClipboard(hwnd))
253         {
254           if (GetOpenClipboardWindow())
255           {
256             ret = IsClipboardFormatAvailable(CF_TEXT);
257           }
258           CloseClipboard();
259         }
260         return ret;
261 }