Test some more ntdll types.
[wine] / windows / clipboard.c
1 /*
2  * WIN32 clipboard implementation
3  *
4  * Copyright 1994 Martin Ayotte
5  *           1996 Alex Korobka
6  *           1999 Noel Borthwick
7  *           2003 Ulrich Czekalla for CodeWeavers
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  * NOTES:
24  *    This file contains the implementation for the WIN32 Clipboard API
25  * and Wine's internal clipboard cache.
26  * The actual contents of the clipboard are held in the clipboard cache.
27  * The internal implementation talks to a "clipboard driver" to fill or
28  * expose the cache to the native device. (Currently only the X11 and
29  * TTY clipboard  driver are available)
30  */
31
32 #include "config.h"
33 #include "wine/port.h"
34
35 #include <stdarg.h>
36 #include <stdlib.h>
37 #include <sys/types.h>
38 #include <fcntl.h>
39 #ifdef HAVE_UNISTD_H
40 # include <unistd.h>
41 #endif
42 #include <string.h>
43
44 #include "windef.h"
45 #include "winbase.h"
46 #include "wingdi.h"
47 #include "winuser.h"
48 #include "winerror.h"
49 #include "wine/winuser16.h"
50 #include "wine/winbase16.h"
51 #include "heap.h"
52 #include "user.h"
53 #include "win.h"
54
55 #include "wine/debug.h"
56 #include "wine/unicode.h"
57 #include "wine/server.h"
58
59 WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
60
61 #define  CF_REGFORMATBASE       0xC000
62
63 typedef struct
64 {
65     HWND hWndOpen;
66     HWND hWndOwner;
67     HWND hWndViewer;
68     UINT seqno;
69     UINT flags;
70 } CLIPBOARDINFO, *LPCLIPBOARDINFO;
71
72 /*
73  * Indicates if data has changed since open.
74  */
75 static BOOL bCBHasChanged = FALSE;
76
77
78 /**************************************************************************
79  *                      CLIPBOARD_SetClipboardOwner
80  */
81 BOOL CLIPBOARD_SetClipboardOwner(HWND hWnd)
82 {
83     BOOL bRet = FALSE;
84
85     TRACE(" hWnd(%p)\n", hWnd);
86
87     SERVER_START_REQ( set_clipboard_info )
88     {
89         req->flags = SET_CB_OWNER;
90         req->owner = WIN_GetFullHandle( hWnd );
91
92         if (wine_server_call_err( req ))
93         {
94             ERR("Failed to set clipboard owner to %p\n", hWnd);
95         }
96         else
97         {
98             bRet = TRUE;
99         }
100     }
101     SERVER_END_REQ;
102
103     return bRet;
104 }
105
106
107 /**************************************************************************
108  *                      CLIPBOARD_GetClipboardInfo
109  */
110 static BOOL CLIPBOARD_GetClipboardInfo(LPCLIPBOARDINFO cbInfo)
111 {
112     BOOL bRet = FALSE;
113
114     SERVER_START_REQ( set_clipboard_info )
115     {
116         req->flags = 0;
117
118         if (wine_server_call_err( req ))
119         {
120             ERR("Failed to get clipboard info\n");
121         }
122         else
123         {
124             cbInfo->hWndOpen = reply->old_clipboard;
125             cbInfo->hWndOwner = reply->old_owner;
126             cbInfo->hWndViewer = reply->old_viewer;
127             cbInfo->seqno = reply->seqno;
128             cbInfo->flags = reply->flags;
129
130             bRet = TRUE;
131         }
132     }
133     SERVER_END_REQ;
134
135     return bRet;
136 }
137
138
139 /**************************************************************************
140  *      CLIPBOARD_ReleaseOwner
141  */
142 BOOL CLIPBOARD_ReleaseOwner(void)
143 {
144     BOOL bRet = FALSE;
145
146     SERVER_START_REQ( set_clipboard_info )
147     {
148         req->flags = SET_CB_RELOWNER | SET_CB_SEQNO;
149
150         if (wine_server_call_err( req ))
151         {
152             ERR("Failed to set clipboard.\n");
153         }
154         else
155         {
156             bRet = TRUE;
157         }
158     }
159     SERVER_END_REQ;
160
161     return bRet;
162 }
163
164
165 /**************************************************************************
166  *              CLIPBOARD_OpenClipboard
167  */
168 static BOOL CLIPBOARD_OpenClipboard(HWND hWnd)
169 {
170     BOOL bRet = FALSE;
171
172     SERVER_START_REQ( set_clipboard_info )
173     {
174         req->flags = SET_CB_OPEN;
175         req->clipboard = WIN_GetFullHandle( hWnd );
176
177         if (!wine_server_call( req ))
178             bRet = TRUE;
179     }
180     SERVER_END_REQ;
181
182     return bRet;
183 }
184
185
186 /**************************************************************************
187  *              CLIPBOARD_CloseClipboard
188  */
189 static BOOL CLIPBOARD_CloseClipboard(void)
190 {
191     BOOL bRet = FALSE;
192
193     TRACE(" Changed=%d\n", bCBHasChanged);
194
195     SERVER_START_REQ( set_clipboard_info )
196     {
197         req->flags = SET_CB_CLOSE;
198
199         if (bCBHasChanged)
200         {
201             req->flags |= SET_CB_SEQNO;
202             TRACE("Clipboard data changed\n");
203         }
204
205         if (wine_server_call_err( req ))
206         {
207             ERR("Failed to set clipboard.\n");
208         }
209         else
210         {
211             bRet = TRUE;
212         }
213     }
214     SERVER_END_REQ;
215
216     return bRet;
217 }
218
219
220 /**************************************************************************
221  *                WIN32 Clipboard implementation
222  **************************************************************************/
223
224 /**************************************************************************
225  *              RegisterClipboardFormatA (USER32.@)
226  */
227 UINT WINAPI RegisterClipboardFormatA(LPCSTR FormatName)
228 {
229     UINT wFormatID = 0;
230
231     TRACE("%s\n", debugstr_a(FormatName));
232
233     if (USER_Driver.pRegisterClipboardFormat)
234         wFormatID = USER_Driver.pRegisterClipboardFormat(FormatName);
235
236     return wFormatID;
237 }
238
239
240 /**************************************************************************
241  *              RegisterClipboardFormat (USER.145)
242  */
243 UINT16 WINAPI RegisterClipboardFormat16(LPCSTR FormatName)
244 {
245     UINT wFormatID = 0;
246
247     TRACE("%s\n", debugstr_a(FormatName));
248
249     if (USER_Driver.pRegisterClipboardFormat)
250         wFormatID = USER_Driver.pRegisterClipboardFormat(FormatName);
251
252     return wFormatID;
253 }
254
255
256 /**************************************************************************
257  *              RegisterClipboardFormatW (USER32.@)
258  */
259 UINT WINAPI RegisterClipboardFormatW(LPCWSTR formatName)
260 {
261     LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
262     UINT ret = RegisterClipboardFormatA( aFormat );
263     HeapFree( GetProcessHeap(), 0, aFormat );
264     return ret;
265 }
266
267
268 /**************************************************************************
269  *              GetClipboardFormatName (USER.146)
270  */
271 INT16 WINAPI GetClipboardFormatName16(UINT16 wFormat, LPSTR retStr, INT16 maxlen)
272 {
273     TRACE("%04x,%p,%d\n", wFormat, retStr, maxlen);
274
275     return GetClipboardFormatNameA(wFormat, retStr, maxlen);
276 }
277
278
279 /**************************************************************************
280  *              GetClipboardFormatNameA (USER32.@)
281  */
282 INT WINAPI GetClipboardFormatNameA(UINT wFormat, LPSTR retStr, INT maxlen)
283 {
284     INT len = 0;
285
286     TRACE("%04x,%p,%d\n", wFormat, retStr, maxlen);
287
288     if (USER_Driver.pGetClipboardFormatName)
289         len = USER_Driver.pGetClipboardFormatName(wFormat, retStr, maxlen);
290
291     return len;
292 }
293
294
295 /**************************************************************************
296  *              GetClipboardFormatNameW (USER32.@)
297  */
298 INT WINAPI GetClipboardFormatNameW(UINT wFormat, LPWSTR retStr, INT maxlen)
299 {
300     INT ret;
301     LPSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen );
302     if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
303
304     ret = GetClipboardFormatNameA( wFormat, p, maxlen );
305
306     if (maxlen > 0 && !MultiByteToWideChar( CP_ACP, 0, p, -1, retStr, maxlen ))
307         retStr[maxlen-1] = 0;
308     HeapFree( GetProcessHeap(), 0, p );
309     return ret;
310 }
311
312
313 /**************************************************************************
314  *              OpenClipboard (USER32.@)
315  *
316  * Note: Netscape uses NULL hWnd to open the clipboard.
317  */
318 BOOL WINAPI OpenClipboard( HWND hWnd )
319 {
320     BOOL bRet;
321
322     TRACE("(%p)...\n", hWnd);
323
324     bRet = CLIPBOARD_OpenClipboard(hWnd);
325
326     TRACE(" returning %i\n", bRet);
327
328     return bRet;
329 }
330
331
332 /**************************************************************************
333  *              CloseClipboard (USER.138)
334  */
335 BOOL16 WINAPI CloseClipboard16(void)
336 {
337     return CloseClipboard();
338 }
339
340
341 /**************************************************************************
342  *              CloseClipboard (USER32.@)
343  */
344 BOOL WINAPI CloseClipboard(void)
345 {
346     BOOL bRet = FALSE;
347
348     TRACE("(%d)\n", bCBHasChanged);
349
350     if (CLIPBOARD_CloseClipboard())
351     {
352         if (bCBHasChanged)
353         {
354             HWND hWndViewer = GetClipboardViewer();
355
356             if (USER_Driver.pEndClipboardUpdate)
357                 USER_Driver.pEndClipboardUpdate();
358  
359             if (hWndViewer)
360                 SendMessageW(hWndViewer, WM_DRAWCLIPBOARD, 0, 0);
361  
362             bCBHasChanged = FALSE;
363         }
364
365         bRet = TRUE;
366     }
367
368     return bRet;
369 }
370
371
372 /**************************************************************************
373  *              EmptyClipboard (USER.139)
374  */
375 BOOL16 WINAPI EmptyClipboard16(void)
376 {
377     return EmptyClipboard();
378 }
379
380
381 /**************************************************************************
382  *              EmptyClipboard (USER32.@)
383  * Empties and acquires ownership of the clipboard
384  */
385 BOOL WINAPI EmptyClipboard(void)
386 {
387     CLIPBOARDINFO cbinfo;
388  
389     TRACE("()\n");
390
391     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
392         ~cbinfo.flags & CB_OPEN)
393     { 
394         WARN("Clipboard not opened by calling task!\n");
395         SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
396         return FALSE;
397     }
398
399     /* Destroy private objects */
400     if (cbinfo.hWndOwner) 
401         SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
402
403     /* Tell the driver to acquire the selection. The current owner
404      * will be signaled to delete it's own cache. */
405
406     /* Assign ownership of the clipboard to the current client. We do
407      * this before acquiring the selection so that when we do acquire the
408      * selection and the selection loser gets notified, it can check if 
409      * it has lost the Wine clipboard ownership. If it did then it knows
410      * that a WM_DESTORYCLIPBOARD has already been sent. Otherwise it
411      * lost the selection to a X app and it should send the 
412      * WM_DESTROYCLIPBOARD itself. */
413     CLIPBOARD_SetClipboardOwner(cbinfo.hWndOpen);
414
415     /* Acquire the selection. This will notify the previous owner
416      * to clear it's cache. */ 
417     if (USER_Driver.pAcquireClipboard) 
418         USER_Driver.pAcquireClipboard(cbinfo.hWndOpen);
419
420     /* Empty the local cache */
421     if (USER_Driver.pEmptyClipboard) 
422         USER_Driver.pEmptyClipboard(FALSE);
423  
424     bCBHasChanged = TRUE;
425
426     return TRUE;
427 }
428
429
430 /**************************************************************************
431  *              GetClipboardOwner (USER32.@)
432  *  FIXME: Can't return the owner if the clipboard is owned by an external X-app
433  */
434 HWND WINAPI GetClipboardOwner(void)
435 {
436     HWND hWndOwner = 0;
437
438     SERVER_START_REQ( set_clipboard_info )
439     {
440         req->flags = 0;
441         if (!wine_server_call_err( req )) hWndOwner = reply->old_owner;
442     }
443     SERVER_END_REQ;
444
445     TRACE(" hWndOwner(%p)\n", hWndOwner);
446
447     return hWndOwner;
448 }
449
450
451 /**************************************************************************
452  *              GetOpenClipboardWindow (USER32.@)
453  */
454 HWND WINAPI GetOpenClipboardWindow(void)
455 {
456     HWND hWndOpen = 0;
457
458     SERVER_START_REQ( set_clipboard_info )
459     {
460         req->flags = 0;
461         if (!wine_server_call_err( req )) hWndOpen = reply->old_clipboard;
462     }
463     SERVER_END_REQ;
464
465     TRACE(" hWndClipWindow(%p)\n", hWndOpen);
466
467     return hWndOpen;
468 }
469
470
471 /**************************************************************************
472  *              SetClipboardViewer (USER32.@)
473  */
474 HWND WINAPI SetClipboardViewer( HWND hWnd )
475 {
476     HWND hwndPrev = 0;
477  
478     SERVER_START_REQ( set_clipboard_info )
479     {
480         req->flags = SET_CB_VIEWER;
481         req->viewer = WIN_GetFullHandle(hWnd);
482  
483         if (wine_server_call_err( req ))
484         {
485             ERR("Failed to set clipboard.\n");
486         }
487         else
488         {
489             hwndPrev = reply->old_viewer;
490         }
491     }
492     SERVER_END_REQ;
493  
494     TRACE("(%p): returning %p\n", hWnd, hwndPrev);
495   
496     return hwndPrev;
497 }
498
499
500 /**************************************************************************
501  *              GetClipboardViewer (USER32.@)
502  */
503 HWND WINAPI GetClipboardViewer(void)
504 {
505     HWND hWndViewer = 0;
506
507     SERVER_START_REQ( set_clipboard_info )
508     {
509         req->flags = 0;
510         if (!wine_server_call_err( req )) hWndViewer = reply->old_viewer;
511     }
512     SERVER_END_REQ;
513
514     TRACE(" hWndViewer=%p\n", hWndViewer);
515
516     return hWndViewer;
517 }
518
519
520 /**************************************************************************
521  *              ChangeClipboardChain (USER32.@)
522  */
523 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
524 {
525     BOOL bRet = TRUE;
526     HWND hWndViewer = GetClipboardViewer();
527
528     if (hWndViewer)
529     {
530         if (WIN_GetFullHandle(hWnd) == hWndViewer) 
531             SetClipboardViewer(WIN_GetFullHandle(hWndNext));
532         else
533             bRet = !SendMessageW(hWndViewer, WM_CHANGECBCHAIN, (WPARAM)hWnd, (LPARAM)hWndNext);
534     }
535     else
536         ERR("hWndViewer is lost\n");
537
538     return bRet;
539 }
540
541
542 /**************************************************************************
543  *              SetClipboardData (USER.141)
544  */
545 HANDLE16 WINAPI SetClipboardData16(UINT16 wFormat, HANDLE16 hData)
546 {
547     CLIPBOARDINFO cbinfo;
548     HANDLE16 hResult = 0;
549
550     TRACE("(%04X, %04x) !\n", wFormat, hData);
551
552     /* If it's not owned, data can only be set if the format doesn't exists
553        and its rendering is not delayed */
554     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
555         (!(cbinfo.flags & CB_OWNER) && !hData))
556     {
557         WARN("Clipboard not owned by calling task. Operation failed.\n");
558         return 0;
559     }
560
561     if (USER_Driver.pSetClipboardData &&
562         USER_Driver.pSetClipboardData(wFormat, hData, 0, cbinfo.flags & CB_OWNER))
563     {
564         hResult = hData;
565         bCBHasChanged = TRUE;
566     }
567
568     return hResult;
569 }
570
571
572 /**************************************************************************
573  *              SetClipboardData (USER32.@)
574  */
575 HANDLE WINAPI SetClipboardData(UINT wFormat, HANDLE hData)
576 {
577     CLIPBOARDINFO cbinfo;
578     HANDLE hResult = 0;
579
580     TRACE("(%04X, %p) !\n", wFormat, hData);
581
582     /* If it's not owned, data can only be set if the format isn't
583        available and its rendering is not delayed */
584     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
585        (!(cbinfo.flags & CB_OWNER) && !hData))
586     {
587         WARN("Clipboard not owned by calling task. Operation failed.\n");
588         return 0;
589     }
590
591     if (USER_Driver.pSetClipboardData &&
592         USER_Driver.pSetClipboardData(wFormat, 0, hData, cbinfo.flags & CB_OWNER))
593     {
594         hResult = hData;
595         bCBHasChanged = TRUE;
596     }
597
598     return hResult;
599 }
600
601
602 /**************************************************************************
603  *              CountClipboardFormats (USER.143)
604  */
605 INT16 WINAPI CountClipboardFormats16(void)
606 {
607     return CountClipboardFormats();
608 }
609
610
611 /**************************************************************************
612  *              CountClipboardFormats (USER32.@)
613  */
614 INT WINAPI CountClipboardFormats(void)
615 {
616     INT count = 0;
617
618     if (USER_Driver.pCountClipboardFormats)
619         count = USER_Driver.pCountClipboardFormats();
620
621     TRACE("returning %d\n", count);
622     return count;
623 }
624
625
626 /**************************************************************************
627  *              EnumClipboardFormats (USER.144)
628  */
629 UINT16 WINAPI EnumClipboardFormats16(UINT16 wFormat)
630 {
631     return EnumClipboardFormats(wFormat);
632 }
633
634
635 /**************************************************************************
636  *              EnumClipboardFormats (USER32.@)
637  */
638 UINT WINAPI EnumClipboardFormats(UINT wFormat)
639 {
640     UINT wFmt = 0;
641     CLIPBOARDINFO cbinfo;
642
643     TRACE("(%04X)\n", wFormat);
644
645     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
646         (~cbinfo.flags & CB_OPEN))
647     {
648         WARN("Clipboard not opened by calling task.\n");
649         SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
650         return 0;
651     }
652
653     if (USER_Driver.pEnumClipboardFormats)
654         wFmt = USER_Driver.pEnumClipboardFormats(wFormat);
655
656     return wFmt;
657 }
658
659
660 /**************************************************************************
661  *              IsClipboardFormatAvailable (USER.193)
662  */
663 BOOL16 WINAPI IsClipboardFormatAvailable16(UINT16 wFormat)
664 {
665     return IsClipboardFormatAvailable(wFormat);
666 }
667
668
669 /**************************************************************************
670  *              IsClipboardFormatAvailable (USER32.@)
671  */
672 BOOL WINAPI IsClipboardFormatAvailable(UINT wFormat)
673 {
674     BOOL bret = FALSE;
675
676     if (USER_Driver.pIsClipboardFormatAvailable)
677         bret = USER_Driver.pIsClipboardFormatAvailable(wFormat);
678
679     TRACE("%04x, returning %d\n", wFormat, bret);
680     return bret;
681 }
682
683
684 /**************************************************************************
685  *              GetClipboardData (USER.142)
686  */
687 HANDLE16 WINAPI GetClipboardData16(UINT16 wFormat)
688 {
689     HANDLE16 hData = 0;
690     CLIPBOARDINFO cbinfo;
691
692     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
693         (~cbinfo.flags & CB_OPEN))
694     {
695         WARN("Clipboard not opened by calling task.\n");
696         SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
697         return 0;
698     }
699
700     if (USER_Driver.pGetClipboardData)
701         USER_Driver.pGetClipboardData(wFormat, &hData, NULL);
702
703     return hData;
704 }
705
706
707 /**************************************************************************
708  *              GetClipboardData (USER32.@)
709  */
710 HANDLE WINAPI GetClipboardData(UINT wFormat)
711 {
712     HANDLE hData = 0;
713     CLIPBOARDINFO cbinfo;
714
715     TRACE("%04x\n", wFormat);
716
717     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
718         (~cbinfo.flags & CB_OPEN))
719     {
720         WARN("Clipboard not opened by calling task.\n");
721         SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
722         return 0;
723     }
724
725     if (USER_Driver.pGetClipboardData)
726         USER_Driver.pGetClipboardData(wFormat, NULL, &hData);
727
728     TRACE("returning %p\n", hData);
729     return hData;
730 }
731
732
733 /**************************************************************************
734  *              GetPriorityClipboardFormat (USER32.@)
735  */
736 INT WINAPI GetPriorityClipboardFormat(UINT *list, INT nCount)
737 {
738     int i;
739
740     TRACE("()\n");
741
742     if(CountClipboardFormats() == 0)
743         return 0;
744
745     for (i = 0; i < nCount; i++)
746         if (IsClipboardFormatAvailable(list[i]))
747             return list[i];
748
749     return -1;
750 }
751
752
753 /**************************************************************************
754  *              GetClipboardSequenceNumber (USER32.@)
755  * Supported on Win2k/Win98
756  * MSDN: Windows clipboard code keeps a serial number for the clipboard
757  * for each window station.  The number is incremented whenever the
758  * contents change or are emptied.
759  * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
760  */
761 DWORD WINAPI GetClipboardSequenceNumber(VOID)
762 {
763     DWORD seqno = 0;
764
765     SERVER_START_REQ( set_clipboard_info )
766     {
767         req->flags = 0;
768         if (!wine_server_call_err( req )) seqno = reply->seqno;
769     }
770     SERVER_END_REQ;
771
772     TRACE("returning %lx\n", seqno);
773     return seqno;
774 }