Corrected some segvs that occur with ownerdata listviews.
[wine] / dlls / shell32 / clipboard.c
1 /*
2  *      clipboard helper functions
3  *
4  *      Copyright 2000  Juergen Schmied <juergen.schmied@debitel.de>
5  *
6  * For copy & paste functions within contextmenus does the shell use
7  * the OLE clipboard functions in combination with dataobjects.
8  * The OLE32.DLL gets loaded with LoadLibrary
9  *
10  * - a right mousebutton-copy sets the following formats:
11  *  classic:
12  *      Shell IDList Array
13  *      Prefered Drop Effect
14  *      Shell Object Offsets
15  *      HDROP
16  *      FileName
17  *  ole:
18  *      OlePrivateData (ClipboardDataObjectInterface)
19  *
20  */
21
22 #include <string.h>
23
24 #include "debugtools.h"
25
26 #include "pidl.h"
27 #include "wine/undocshell.h"
28 #include "shell32_main.h"
29
30 DEFAULT_DEBUG_CHANNEL(shell)
31
32 static int refClipCount = 0;
33 static HINSTANCE hShellOle32 = 0;
34
35 /**************************************************************************
36  * InitShellOle
37  *
38  * 
39  */
40 void InitShellOle(void)
41 {
42 }
43
44 /**************************************************************************
45  * FreeShellOle
46  *
47  * unload OLE32.DLL
48  */
49 void FreeShellOle(void)
50 {
51         if (!--refClipCount)
52         {
53           pOleUninitialize();
54           FreeLibrary(hShellOle32);
55         }
56 }
57
58 /**************************************************************************
59  * LoadShellOle
60  *
61  * make sure OLE32.DLL is loaded
62  */
63 BOOL GetShellOle(void)
64 {
65         if(!refClipCount)
66         {
67           hShellOle32 = LoadLibraryA("ole32.dll");
68           if(hShellOle32)
69           {
70             pOleInitialize=(void*)GetProcAddress(hShellOle32,"OleInitialize");
71             pOleUninitialize=(void*)GetProcAddress(hShellOle32,"OleUninitialize");
72             pRegisterDragDrop=(void*)GetProcAddress(hShellOle32,"RegisterDragDrop");
73             pRevokeDragDrop=(void*)GetProcAddress(hShellOle32,"RevokeDragDrop");
74             pDoDragDrop=(void*)GetProcAddress(hShellOle32,"DoDragDrop");
75             pReleaseStgMedium=(void*)GetProcAddress(hShellOle32,"ReleaseStgMedium");
76             pOleSetClipboard=(void*)GetProcAddress(hShellOle32,"OleSetClipboard");
77             pOleGetClipboard=(void*)GetProcAddress(hShellOle32,"OleGetClipboard");
78
79             pOleInitialize(NULL);
80             refClipCount++;
81           }
82         }
83         return TRUE;
84 }
85
86 /**************************************************************************
87  * RenderHDROP
88  *
89  * creates a CF_HDROP structure
90  */
91 HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
92 {
93         int i;
94         int rootsize = 0,size = 0;
95         char szRootPath[MAX_PATH];
96         char szFileName[MAX_PATH];
97         HGLOBAL hGlobal;
98         DROPFILES *pDropFiles;
99         int offset;
100         
101         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
102
103         /* get the size needed */
104         size = sizeof(DROPFILES);
105
106         SHGetPathFromIDListA(pidlRoot, szRootPath);
107         PathAddBackslashA(szRootPath);
108         rootsize = strlen(szRootPath);
109         
110         for (i=0; i<cidl;i++)
111         {
112           _ILSimpleGetText(apidl[i], szFileName, MAX_PATH);
113           size += rootsize + strlen(szFileName) + 1;
114         }
115
116         size++;
117
118         /* Fill the structure */
119         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
120         if(!hGlobal) return hGlobal;
121
122         pDropFiles = (DROPFILES *)GlobalLock(hGlobal);
123         pDropFiles->pFiles = sizeof(DROPFILES);
124         pDropFiles->fWide = FALSE;
125
126         offset = pDropFiles->pFiles;
127         strcpy(szFileName, szRootPath);
128         
129         for (i=0; i<cidl;i++)
130         {
131           
132           _ILSimpleGetText(apidl[i], szFileName + rootsize, MAX_PATH - rootsize);
133           size = strlen(szFileName) + 1;
134           strcpy(((char*)pDropFiles)+offset, szFileName);
135           offset += size;
136         }
137
138         ((char*)pDropFiles)[offset] = 0;
139         GlobalUnlock(hGlobal);
140
141         return hGlobal;
142 }
143
144 HGLOBAL RenderSHELLIDLIST (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
145 {
146         int i,offset = 0, sizePidl, size;
147         HGLOBAL hGlobal;
148         LPCIDA  pcida;
149
150         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
151
152         /* get the size needed */
153         size = sizeof(CIDA) + sizeof (UINT)*(cidl);     /* header */
154         size += ILGetSize (pidlRoot);                   /* root pidl */
155         for(i=0; i<cidl; i++)
156         {
157           size += ILGetSize(apidl[i]);                  /* child pidls */
158         }
159
160         /* fill the structure */
161         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);           
162         if(!hGlobal) return hGlobal;
163         pcida = GlobalLock (hGlobal);
164         pcida->cidl = cidl;
165
166         /* root pidl */
167         offset = sizeof(CIDA) + sizeof (UINT)*(cidl);
168         pcida->aoffset[0] = offset;                     /* first element */
169         sizePidl = ILGetSize (pidlRoot);
170         memcpy(((LPBYTE)pcida)+offset, pidlRoot, sizePidl);
171         offset += sizePidl;
172
173         for(i=0; i<cidl; i++)                           /* child pidls */
174         {
175           pcida->aoffset[i+1] = offset;
176           sizePidl = ILGetSize(apidl[i]);
177           memcpy(((LPBYTE)pcida)+offset, apidl[i], sizePidl);
178           offset += sizePidl;
179         }
180
181         GlobalUnlock(hGlobal);
182         return hGlobal;
183 }
184
185 HGLOBAL RenderSHELLIDLISTOFFSET (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
186 {
187         FIXME("\n");
188         return 0;
189 }
190
191 HGLOBAL RenderFILECONTENTS (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
192 {
193         FIXME("\n");
194         return 0;
195 }
196
197 HGLOBAL RenderFILEDESCRIPTOR (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
198 {
199         FIXME("\n");
200         return 0;
201 }
202
203 HGLOBAL RenderFILENAME (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
204 {
205         int len, size = 0;
206         char szTemp[MAX_PATH], *szFileName;
207         HGLOBAL hGlobal;
208         
209         TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
210
211         /* build name of first file */
212         SHGetPathFromIDListA(pidlRoot, szTemp);
213         PathAddBackslashA(szTemp);
214         len = strlen(szTemp);
215         _ILSimpleGetText(apidl[0], szTemp+len, MAX_PATH - len);
216         size = strlen(szTemp) + 1;
217
218         /* fill the structure */
219         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
220         if(!hGlobal) return hGlobal;
221         szFileName = (char *)GlobalLock(hGlobal);
222         GlobalUnlock(hGlobal);
223         return hGlobal;
224 }
225
226 HGLOBAL RenderPREFEREDDROPEFFECT (DWORD dwFlags)
227 {
228         DWORD * pdwFlag;
229         HGLOBAL hGlobal;
230         
231         TRACE("(0x%08lx)\n", dwFlags);
232
233         hGlobal = GlobalAlloc(GHND|GMEM_SHARE, sizeof(DWORD));
234         if(!hGlobal) return hGlobal;
235         pdwFlag = (DWORD*)GlobalLock(hGlobal);
236         *pdwFlag = dwFlags;
237         GlobalUnlock(hGlobal);
238         return hGlobal;
239 }
240
241 /**************************************************************************
242  * IsDataInClipboard
243  *
244  * checks if there is something in the clipboard we can use
245  */
246 BOOL IsDataInClipboard (HWND hwnd)
247 {
248         BOOL ret = FALSE;
249         
250         if (OpenClipboard(hwnd))
251         {
252           if (GetOpenClipboardWindow())
253           {
254             ret = IsClipboardFormatAvailable(CF_TEXT);
255           }
256           CloseClipboard();
257         }
258         return ret;
259 }