2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Clipboard routines
5 * FILE: win32ss/user/ntuser/clipboard.c
6 * PROGRAMER: Filip Navara <xnavara@volny.cz>
7 * Pablo Borobia <pborobia@gmail.com>
8 * Rafal Harabien <rafalh@reactos.org>
12 DBG_DEFAULT_CHANNEL(UserClipbrd
);
14 #define DATA_DELAYED (HANDLE)0
15 #define DATA_SYNTH_USER (HANDLE)1
16 #define DATA_SYNTH_KRNL (HANDLE)2
17 #define IS_DATA_DELAYED(ce) ((ce)->hData == DATA_DELAYED)
18 #define IS_DATA_SYNTHESIZED(ce) ((ce)->hData == DATA_SYNTH_USER || (ce)->hData == DATA_SYNTH_KRNL)
20 static PWINSTATION_OBJECT FASTCALL
21 IntGetWinStaForCbAccess(VOID
)
24 PWINSTATION_OBJECT pWinStaObj
;
27 hWinSta
= UserGetProcessWindowStation();
28 Status
= IntValidateWindowStationHandle(hWinSta
, UserMode
, WINSTA_ACCESSCLIPBOARD
, &pWinStaObj
, 0);
29 if (!NT_SUCCESS(Status
))
31 ERR("Cannot open winsta\n");
32 SetLastNtError(Status
);
39 /* If format exists, returns a non-null value (pointing to formated object) */
41 IntGetFormatElement(PWINSTATION_OBJECT pWinStaObj
, UINT fmt
)
45 for (i
= 0; i
< pWinStaObj
->cNumClipFormats
; ++i
)
47 if (pWinStaObj
->pClipBase
[i
].fmt
== fmt
)
48 return &pWinStaObj
->pClipBase
[i
];
55 IntIsFormatAvailable(PWINSTATION_OBJECT pWinStaObj
, UINT fmt
)
57 return IntGetFormatElement(pWinStaObj
, fmt
) != NULL
;
61 IntFreeElementData(PCLIP pElement
)
63 if (!IS_DATA_DELAYED(pElement
) &&
64 !IS_DATA_SYNTHESIZED(pElement
))
66 if (pElement
->fGlobalHandle
)
67 UserDeleteObject(pElement
->hData
, TYPE_CLIPDATA
);
68 else if (pElement
->fmt
== CF_BITMAP
||
69 pElement
->fmt
== CF_PALETTE
||
70 pElement
->fmt
== CF_DSPBITMAP
||
71 pElement
->fmt
== CF_METAFILEPICT
||
72 pElement
->fmt
== CF_DSPMETAFILEPICT
||
73 pElement
->fmt
== CF_DSPENHMETAFILE
||
74 pElement
->fmt
== CF_ENHMETAFILE
)
76 GreSetObjectOwner(pElement
->hData
, GDI_OBJ_HMGR_POWNED
);
77 GreDeleteObject(pElement
->hData
);
82 /* Adds a new format and data to the clipboard */
84 IntAddFormatedData(PWINSTATION_OBJECT pWinStaObj
, UINT fmt
, HANDLE hData
, BOOLEAN fGlobalHandle
, BOOL bEnd
)
86 PCLIP pElement
= NULL
;
88 /* Use existing entry with specified format */
90 pElement
= IntGetFormatElement(pWinStaObj
, fmt
);
92 /* Put new entry at the end if nothing was found */
95 /* Allocate bigger clipboard if needed. We could use lists but Windows uses array */
96 if (pWinStaObj
->cNumClipFormats
% 4 == 0)
100 /* Allocate new clipboard */
101 pNewClip
= ExAllocatePoolWithTag(PagedPool
,
102 (pWinStaObj
->cNumClipFormats
+ 4) * sizeof(CLIP
),
106 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
111 memcpy(pNewClip
, pWinStaObj
->pClipBase
, pWinStaObj
->cNumClipFormats
* sizeof(CLIP
));
113 /* Free old clipboard */
114 if (pWinStaObj
->pClipBase
)
115 ExFreePoolWithTag(pWinStaObj
->pClipBase
, USERTAG_CLIPBOARD
);
118 pWinStaObj
->pClipBase
= pNewClip
;
121 /* New element is at the end */
122 pElement
= &pWinStaObj
->pClipBase
[pWinStaObj
->cNumClipFormats
];
124 pWinStaObj
->cNumClipFormats
++;
127 IntFreeElementData(pElement
);
129 pElement
->hData
= hData
;
130 pElement
->fGlobalHandle
= fGlobalHandle
;
136 IntIsClipboardOpenByMe(PWINSTATION_OBJECT pWinSta
)
138 /* Check if the current thread has opened the clipboard */
139 return (pWinSta
->ptiClipLock
&&
140 pWinSta
->ptiClipLock
== PsGetCurrentThreadWin32Thread());
145 PWINSTATION_OBJECT pWinStaObj
,
149 ULONG cjInfoSize
, cjDataSize
;
150 PCLIPBOARDDATA pClipboardData
;
155 BITMAPINFOHEADER bmih
;
156 RGBQUAD rgbColors
[256];
158 PBITMAPINFO pbmi
= (PBITMAPINFO
)&bmiBuffer
;
160 /* Get the display DC */
161 hdc
= UserGetDCEx(NULL
, NULL
, DCX_USESTYLE
);
167 /* Get information about the bitmap format */
168 memset(&bmiBuffer
, 0, sizeof(bmiBuffer
));
169 pbmi
->bmiHeader
.biSize
= sizeof(bmiBuffer
.bmih
);
170 iResult
= GreGetDIBitsInternal(hdc
,
184 /* Get the size for a full BITMAPINFO */
185 cjInfoSize
= DIB_BitmapInfoSize(pbmi
, DIB_RGB_COLORS
);
187 /* Calculate the size of the clipboard data, which is a packed DIB */
188 cjDataSize
= cjInfoSize
+ pbmi
->bmiHeader
.biSizeImage
;
190 /* Create the clipboard data */
191 pClipboardData
= (PCLIPBOARDDATA
)UserCreateObject(gHandleTable
,
196 sizeof(CLIPBOARDDATA
) + cjDataSize
);
202 /* Set the data size */
203 pClipboardData
->cbData
= cjDataSize
;
205 /* Copy the BITMAPINFOHEADER */
206 memcpy(pClipboardData
->Data
, pbmi
, sizeof(BITMAPINFOHEADER
));
208 /* Get the bitmap bits and the color table */
209 iResult
= GreGetDIBitsInternal(hdc
,
212 abs(pbmi
->bmiHeader
.biHeight
),
213 (LPBYTE
)pClipboardData
->Data
+ cjInfoSize
,
214 (LPBITMAPINFO
)pClipboardData
->Data
,
216 pbmi
->bmiHeader
.biSizeImage
,
219 /* Add the clipboard data */
220 IntAddFormatedData(pWinStaObj
, CF_DIB
, hMem
, TRUE
, TRUE
);
222 /* Release the extra reference (UserCreateObject added 2 references) */
223 UserDereferenceObject(pClipboardData
);
226 UserReleaseDC(NULL
, hdc
, FALSE
);
230 IntSynthesizeBitmap(PWINSTATION_OBJECT pWinStaObj
, PCLIP pBmEl
)
233 PBITMAPINFO pBmi
, pConvertedBmi
= NULL
;
235 PCLIPBOARDDATA pMemObj
;
239 TRACE("IntSynthesizeBitmap(%p, %p)\n", pWinStaObj
, pBmEl
);
241 pDibEl
= IntGetFormatElement(pWinStaObj
, CF_DIB
);
242 ASSERT(pDibEl
&& !IS_DATA_SYNTHESIZED(pDibEl
));
243 if (!pDibEl
->fGlobalHandle
)
246 pMemObj
= (PCLIPBOARDDATA
)UserGetObject(gHandleTable
, pDibEl
->hData
, TYPE_CLIPDATA
);
250 pBmi
= (BITMAPINFO
*)pMemObj
->Data
;
252 if (pMemObj
->cbData
< sizeof(DWORD
) && pMemObj
->cbData
< pBmi
->bmiHeader
.biSize
)
255 pConvertedBmi
= DIB_ConvertBitmapInfo(pBmi
, DIB_RGB_COLORS
);
259 Offset
= DIB_BitmapInfoSize(pBmi
, DIB_RGB_COLORS
);
261 hdc
= UserGetDCEx(NULL
, NULL
, DCX_USESTYLE
);
265 hBm
= GreCreateDIBitmapInternal(hdc
,
266 pConvertedBmi
->bmiHeader
.biWidth
,
267 pConvertedBmi
->bmiHeader
.biHeight
,
269 pMemObj
->Data
+ Offset
,
273 pMemObj
->cbData
- Offset
,
278 GreSetObjectOwner(hBm
, GDI_OBJ_HMGR_PUBLIC
);
284 UserReleaseDC(NULL
, hdc
, FALSE
);
287 DIB_FreeConvertedBitmapInfo(pConvertedBmi
, pBmi
, -1);
291 IntAddSynthesizedFormats(PWINSTATION_OBJECT pWinStaObj
)
293 BOOL bHaveText
, bHaveUniText
, bHaveOemText
, bHaveLocale
, bHaveBm
, bHaveDib
, bHaveMFP
, bHaveEMF
;
295 bHaveText
= IntIsFormatAvailable(pWinStaObj
, CF_TEXT
);
296 bHaveOemText
= IntIsFormatAvailable(pWinStaObj
, CF_OEMTEXT
);
297 bHaveUniText
= IntIsFormatAvailable(pWinStaObj
, CF_UNICODETEXT
);
298 bHaveLocale
= IntIsFormatAvailable(pWinStaObj
, CF_LOCALE
);
299 bHaveBm
= IntIsFormatAvailable(pWinStaObj
, CF_BITMAP
);
300 bHaveDib
= IntIsFormatAvailable(pWinStaObj
, CF_DIB
);
301 bHaveMFP
= IntIsFormatAvailable(pWinStaObj
, CF_METAFILEPICT
);
302 bHaveEMF
= IntIsFormatAvailable(pWinStaObj
, CF_ENHMETAFILE
);
304 /* Add CF_LOCALE format if we have CF_TEXT, CF_OEMTEXT or CF_UNICODETEXT */
305 if (!bHaveLocale
&& (bHaveText
|| bHaveOemText
|| bHaveUniText
))
307 PCLIPBOARDDATA pMemObj
;
310 pMemObj
= (PCLIPBOARDDATA
)UserCreateObject(gHandleTable
, NULL
, NULL
, &hMem
, TYPE_CLIPDATA
,
311 sizeof(CLIPBOARDDATA
) + sizeof(LCID
));
314 pMemObj
->cbData
= sizeof(LCID
);
315 *((LCID
*)pMemObj
->Data
) = NtCurrentTeb()->CurrentLocale
;
316 IntAddFormatedData(pWinStaObj
, CF_LOCALE
, hMem
, TRUE
, TRUE
);
318 /* Release the extra reference (UserCreateObject added 2 references) */
319 UserDereferenceObject(pMemObj
);
323 /* Add CF_TEXT. Note: it is synthesized in user32.dll */
324 if (!bHaveText
&& (bHaveUniText
|| bHaveOemText
))
325 IntAddFormatedData(pWinStaObj
, CF_TEXT
, DATA_SYNTH_USER
, FALSE
, TRUE
);
327 /* Add CF_OEMTEXT. Note: it is synthesized in user32.dll */
328 if (!bHaveOemText
&& (bHaveUniText
|| bHaveText
))
329 IntAddFormatedData(pWinStaObj
, CF_OEMTEXT
, DATA_SYNTH_USER
, FALSE
, TRUE
);
331 /* Add CF_UNICODETEXT. Note: it is synthesized in user32.dll */
332 if (!bHaveUniText
&& (bHaveText
|| bHaveOemText
))
333 IntAddFormatedData(pWinStaObj
, CF_UNICODETEXT
, DATA_SYNTH_USER
, FALSE
, TRUE
);
335 /* Add CF_BITMAP. Note: it is synthesized on demand */
336 if (!bHaveBm
&& bHaveDib
)
337 IntAddFormatedData(pWinStaObj
, CF_BITMAP
, DATA_SYNTH_KRNL
, FALSE
, TRUE
);
339 /* Add CF_ENHMETAFILE. Note: it is synthesized in gdi32.dll */
340 if (bHaveMFP
&& !bHaveEMF
)
341 IntAddFormatedData(pWinStaObj
, CF_ENHMETAFILE
, DATA_SYNTH_USER
, FALSE
, TRUE
);
343 /* Add CF_METAFILEPICT. Note: it is synthesized in gdi32.dll */
344 if (bHaveEMF
&& !bHaveMFP
)
345 IntAddFormatedData(pWinStaObj
, CF_METAFILEPICT
, DATA_SYNTH_USER
, FALSE
, TRUE
);
347 /* Note: We need to render the DIB or DIBV5 format as soon as possible
348 because palette information may change */
349 if (!bHaveDib
&& bHaveBm
)
350 IntSynthesizeDib(pWinStaObj
, IntGetFormatElement(pWinStaObj
, CF_BITMAP
)->hData
);
354 UserEmptyClipboardData(PWINSTATION_OBJECT pWinSta
)
359 for (i
= 0; i
< pWinSta
->cNumClipFormats
; ++i
)
361 pElement
= &pWinSta
->pClipBase
[i
];
362 IntFreeElementData(pElement
);
365 if (pWinSta
->pClipBase
)
366 ExFreePoolWithTag(pWinSta
->pClipBase
, USERTAG_CLIPBOARD
);
368 pWinSta
->pClipBase
= NULL
;
369 pWinSta
->cNumClipFormats
= 0;
372 /* UserClipboardRelease is called from IntSendDestroyMsg in window.c */
374 UserClipboardRelease(PWND pWindow
)
376 PWINSTATION_OBJECT pWinStaObj
;
381 pWinStaObj
= IntGetWinStaForCbAccess();
385 co_IntSendMessage(UserHMGetHandle(pWinStaObj
->spwndClipOwner
), WM_RENDERALLFORMATS
, 0, 0);
387 /* If the window being destroyed is the current clipboard owner... */
388 if (pWindow
== pWinStaObj
->spwndClipOwner
)
390 /* ... make it release the clipboard */
391 pWinStaObj
->spwndClipOwner
= NULL
;
394 if (pWinStaObj
->fClipboardChanged
)
396 /* Add synthesized formats - they are rendered later */
397 IntAddSynthesizedFormats(pWinStaObj
);
399 /* Notify viewer windows in chain */
400 pWinStaObj
->fClipboardChanged
= FALSE
;
401 if (pWinStaObj
->spwndClipViewer
)
403 TRACE("Clipboard: sending WM_DRAWCLIPBOARD to %p\n", UserHMGetHandle(pWinStaObj
->spwndClipViewer
));
404 // For 32-bit applications this message is sent as a notification
405 co_IntSendMessageNoWait(UserHMGetHandle(pWinStaObj
->spwndClipViewer
), WM_DRAWCLIPBOARD
, 0, 0);
409 ObDereferenceObject(pWinStaObj
);
412 /* UserClipboardFreeWindow is called from co_UserFreeWindow in window.c */
414 UserClipboardFreeWindow(PWND pWindow
)
416 PWINSTATION_OBJECT pWinStaObj
;
418 pWinStaObj
= IntGetWinStaForCbAccess();
422 if (pWindow
== pWinStaObj
->spwndClipOwner
)
424 /* The owner window was destroyed */
425 pWinStaObj
->spwndClipOwner
= NULL
;
428 /* Check if clipboard is not locked by this window, if yes, unlock it */
429 if (pWindow
== pWinStaObj
->spwndClipOpen
)
431 /* The window that opens the clipboard was destroyed */
432 pWinStaObj
->spwndClipOpen
= NULL
;
433 pWinStaObj
->ptiClipLock
= NULL
;
435 /* Remove window from window chain */
436 if (pWindow
== pWinStaObj
->spwndClipViewer
)
437 pWinStaObj
->spwndClipViewer
= NULL
;
439 ObDereferenceObject(pWinStaObj
);
443 UserEnumClipboardFormats(UINT fmt
)
447 PWINSTATION_OBJECT pWinStaObj
;
449 pWinStaObj
= IntGetWinStaForCbAccess();
453 /* Check if the clipboard has been opened */
454 if (!IntIsClipboardOpenByMe(pWinStaObj
))
456 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
462 /* Return first format */
463 if (pWinStaObj
->pClipBase
)
464 Ret
= pWinStaObj
->pClipBase
[0].fmt
;
468 /* Return next format */
469 pElement
= IntGetFormatElement(pWinStaObj
, fmt
);
470 if (pElement
!= NULL
)
473 if (pElement
< &pWinStaObj
->pClipBase
[pWinStaObj
->cNumClipFormats
])
482 ObDereferenceObject(pWinStaObj
);
488 UserOpenClipboard(HWND hWnd
)
492 PWINSTATION_OBJECT pWinStaObj
= NULL
;
496 pWindow
= UserGetWindowObject(hWnd
);
501 pWinStaObj
= IntGetWinStaForCbAccess();
505 /* Check if we already opened the clipboard */
506 if ((pWindow
== pWinStaObj
->spwndClipOpen
) && IntIsClipboardOpenByMe(pWinStaObj
))
512 /* If the clipboard was already opened by somebody else, bail out */
513 if ((pWindow
!= pWinStaObj
->spwndClipOpen
) && pWinStaObj
->ptiClipLock
)
515 ERR("Access denied!\n");
516 EngSetLastError(ERROR_ACCESS_DENIED
);
520 /* Open the clipboard */
521 pWinStaObj
->spwndClipOpen
= pWindow
;
522 pWinStaObj
->ptiClipLock
= PsGetCurrentThreadWin32Thread();
527 ObDereferenceObject(pWinStaObj
);
533 NtUserOpenClipboard(HWND hWnd
, DWORD Unknown1
)
537 UserEnterExclusive();
538 bRet
= UserOpenClipboard(hWnd
);
545 UserCloseClipboard(VOID
)
548 PWINSTATION_OBJECT pWinStaObj
;
550 pWinStaObj
= IntGetWinStaForCbAccess();
554 /* Check if the clipboard has been opened */
555 if (!IntIsClipboardOpenByMe(pWinStaObj
))
557 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
561 /* Clipboard is no longer open */
562 pWinStaObj
->spwndClipOpen
= NULL
;
563 pWinStaObj
->ptiClipLock
= NULL
;
566 if (pWinStaObj
->fClipboardChanged
)
568 /* Add synthesized formats - they are rendered later */
569 IntAddSynthesizedFormats(pWinStaObj
);
571 /* Notify viewer windows in chain */
572 pWinStaObj
->fClipboardChanged
= FALSE
;
573 if (pWinStaObj
->spwndClipViewer
)
575 TRACE("Clipboard: sending WM_DRAWCLIPBOARD to %p\n", UserHMGetHandle(pWinStaObj
->spwndClipViewer
));
576 // For 32-bit applications this message is sent as a notification
577 co_IntSendMessageNoWait(UserHMGetHandle(pWinStaObj
->spwndClipViewer
), WM_DRAWCLIPBOARD
, 0, 0);
583 ObDereferenceObject(pWinStaObj
);
589 NtUserCloseClipboard(VOID
)
593 UserEnterExclusive();
594 bRet
= UserCloseClipboard();
601 NtUserGetOpenClipboardWindow(VOID
)
604 PWINSTATION_OBJECT pWinStaObj
;
608 pWinStaObj
= IntGetWinStaForCbAccess();
612 if (pWinStaObj
->spwndClipOpen
)
613 hWnd
= UserHMGetHandle(pWinStaObj
->spwndClipOpen
);
615 ObDereferenceObject(pWinStaObj
);
624 NtUserChangeClipboardChain(HWND hWndRemove
, HWND hWndNewNext
)
628 PWINSTATION_OBJECT pWinStaObj
;
630 TRACE("NtUserChangeClipboardChain(%p, %p)\n", hWndRemove
, hWndNewNext
);
632 UserEnterExclusive();
634 pWinStaObj
= IntGetWinStaForCbAccess();
638 pWindowRemove
= UserGetWindowObject(hWndRemove
);
640 if (pWindowRemove
&& pWinStaObj
->spwndClipViewer
)
642 if (pWindowRemove
== pWinStaObj
->spwndClipViewer
)
643 pWinStaObj
->spwndClipViewer
= UserGetWindowObject(hWndNewNext
);
645 if (pWinStaObj
->spwndClipViewer
)
646 bRet
= (BOOL
)co_IntSendMessage(UserHMGetHandle(pWinStaObj
->spwndClipViewer
), WM_CHANGECBCHAIN
, (WPARAM
)hWndRemove
, (LPARAM
)hWndNewNext
);
649 ObDereferenceObject(pWinStaObj
);
658 NtUserCountClipboardFormats(VOID
)
661 PWINSTATION_OBJECT pWinStaObj
;
665 pWinStaObj
= IntGetWinStaForCbAccess();
669 cFormats
= pWinStaObj
->cNumClipFormats
;
671 ObDereferenceObject(pWinStaObj
);
680 UserEmptyClipboard(VOID
)
683 PWINSTATION_OBJECT pWinStaObj
;
685 pWinStaObj
= IntGetWinStaForCbAccess();
689 /* Check if the clipboard has been opened */
690 if (!IntIsClipboardOpenByMe(pWinStaObj
))
692 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
696 UserEmptyClipboardData(pWinStaObj
);
698 if (pWinStaObj
->spwndClipOwner
)
700 TRACE("Clipboard: WM_DESTROYCLIPBOARD to %p\n", UserHMGetHandle(pWinStaObj
->spwndClipOwner
));
701 // For 32-bit applications this message is sent as a notification
702 co_IntSendMessage(UserHMGetHandle(pWinStaObj
->spwndClipOwner
), WM_DESTROYCLIPBOARD
, 0, 0);
705 pWinStaObj
->spwndClipOwner
= pWinStaObj
->spwndClipOpen
;
707 pWinStaObj
->iClipSerialNumber
++;
708 pWinStaObj
->iClipSequenceNumber
++;
709 pWinStaObj
->fClipboardChanged
= TRUE
;
710 pWinStaObj
->fInDelayedRendering
= FALSE
;
716 ObDereferenceObject(pWinStaObj
);
722 NtUserEmptyClipboard(VOID
)
726 TRACE("NtUserEmptyClipboard()\n");
728 UserEnterExclusive();
729 bRet
= UserEmptyClipboard();
736 NtUserGetClipboardFormatName(UINT fmt
, LPWSTR lpszFormatName
, INT cchMaxCount
)
742 /* If the format is built-in we fail */
743 if (fmt
< 0xc000 || fmt
> 0xffff)
745 /* Registetrated formats are >= 0xc000 */
749 if (cchMaxCount
< 1 || !lpszFormatName
)
751 EngSetLastError(ERROR_INVALID_PARAMETER
);
757 ProbeForWrite(lpszFormatName
, cchMaxCount
* sizeof(WCHAR
), 1);
759 iRet
= IntGetAtomName((RTL_ATOM
)fmt
,
761 cchMaxCount
* sizeof(WCHAR
));
762 iRet
/= sizeof(WCHAR
);
764 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
766 SetLastNtError(_SEH2_GetExceptionCode());
777 NtUserGetClipboardOwner(VOID
)
780 PWINSTATION_OBJECT pWinStaObj
;
784 pWinStaObj
= IntGetWinStaForCbAccess();
788 if (pWinStaObj
->spwndClipOwner
)
789 hWnd
= UserHMGetHandle(pWinStaObj
->spwndClipOwner
);
791 ObDereferenceObject(pWinStaObj
);
800 NtUserGetClipboardViewer(VOID
)
803 PWINSTATION_OBJECT pWinStaObj
;
807 pWinStaObj
= IntGetWinStaForCbAccess();
811 if (pWinStaObj
->spwndClipViewer
)
812 hWnd
= UserHMGetHandle(pWinStaObj
->spwndClipViewer
);
814 ObDereferenceObject(pWinStaObj
);
823 NtUserGetPriorityClipboardFormat(UINT
*paFormatPriorityList
, INT cFormats
)
826 PWINSTATION_OBJECT pWinStaObj
;
830 pWinStaObj
= IntGetWinStaForCbAccess();
834 if (pWinStaObj
->pClipBase
== NULL
)
842 ProbeForRead(paFormatPriorityList
, cFormats
* sizeof(UINT
), sizeof(UINT
));
846 for (i
= 0; i
< cFormats
; ++i
)
848 if (IntIsFormatAvailable(pWinStaObj
, paFormatPriorityList
[i
]))
850 iRet
= paFormatPriorityList
[i
];
855 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
857 SetLastNtError(_SEH2_GetExceptionCode());
862 ObDereferenceObject(pWinStaObj
);
872 NtUserIsClipboardFormatAvailable(UINT fmt
)
875 PWINSTATION_OBJECT pWinStaObj
;
877 TRACE("NtUserIsClipboardFormatAvailable(%x)\n", fmt
);
881 pWinStaObj
= IntGetWinStaForCbAccess();
885 if (IntIsFormatAvailable(pWinStaObj
, fmt
))
888 ObDereferenceObject(pWinStaObj
);
897 NtUserGetClipboardData(UINT fmt
, PGETCLIPBDATA pgcd
)
901 PWINSTATION_OBJECT pWinStaObj
;
902 UINT uSourceFmt
= fmt
;
904 TRACE("NtUserGetClipboardData(%x, %p)\n", fmt
, pgcd
);
908 pWinStaObj
= IntGetWinStaForCbAccess();
912 /* Check if the clipboard has been opened */
913 if (!IntIsClipboardOpenByMe(pWinStaObj
))
915 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
919 pElement
= IntGetFormatElement(pWinStaObj
, fmt
);
923 if (IS_DATA_SYNTHESIZED(pElement
))
925 /* Note: Data is synthesized in usermode */
926 /* TODO: Add more formats */
932 uSourceFmt
= CF_UNICODETEXT
;
933 pElement
= IntGetFormatElement(pWinStaObj
, uSourceFmt
);
934 if (IS_DATA_SYNTHESIZED(pElement
))
936 uSourceFmt
= CF_TEXT
;
937 pElement
= IntGetFormatElement(pWinStaObj
, uSourceFmt
);
939 if (IS_DATA_SYNTHESIZED(pElement
))
941 uSourceFmt
= CF_OEMTEXT
;
942 pElement
= IntGetFormatElement(pWinStaObj
, uSourceFmt
);
947 IntSynthesizeBitmap(pWinStaObj
, pElement
);
950 case CF_METAFILEPICT
:
951 uSourceFmt
= CF_ENHMETAFILE
;
952 pElement
= IntGetFormatElement(pWinStaObj
, uSourceFmt
);
956 uSourceFmt
= CF_METAFILEPICT
;
957 pElement
= IntGetFormatElement(pWinStaObj
, uSourceFmt
);
965 if (pElement
&& IS_DATA_DELAYED(pElement
) && pWinStaObj
->spwndClipOwner
)
967 /* Send WM_RENDERFORMAT message */
968 pWinStaObj
->fInDelayedRendering
= TRUE
;
969 co_IntSendMessage(UserHMGetHandle(pWinStaObj
->spwndClipOwner
), WM_RENDERFORMAT
, (WPARAM
)uSourceFmt
, 0);
970 pWinStaObj
->fInDelayedRendering
= FALSE
;
972 /* Data should be in clipboard now */
973 pElement
= IntGetFormatElement(pWinStaObj
, uSourceFmt
);
976 if (!pElement
|| IS_DATA_DELAYED(pElement
))
981 ProbeForWrite(pgcd
, sizeof(*pgcd
), 1);
982 pgcd
->uFmtRet
= pElement
->fmt
;
983 pgcd
->fGlobalHandle
= pElement
->fGlobalHandle
;
985 /* Text and bitmap needs more data */
990 pLocaleEl
= IntGetFormatElement(pWinStaObj
, CF_LOCALE
);
991 if (pLocaleEl
&& !IS_DATA_DELAYED(pLocaleEl
))
992 pgcd
->hLocale
= pLocaleEl
->hData
;
994 else if (fmt
== CF_BITMAP
)
998 pPaletteEl
= IntGetFormatElement(pWinStaObj
, CF_PALETTE
);
999 if (pPaletteEl
&& !IS_DATA_DELAYED(pPaletteEl
))
1000 pgcd
->hPalette
= pPaletteEl
->hData
;
1003 hRet
= pElement
->hData
;
1005 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1007 SetLastNtError(_SEH2_GetExceptionCode());
1013 ObDereferenceObject(pWinStaObj
);
1017 TRACE("NtUserGetClipboardData returns %p\n", hRet
);
1023 UserSetClipboardData(UINT fmt
, HANDLE hData
, PSETCLIPBDATA scd
)
1026 PWINSTATION_OBJECT pWinStaObj
;
1028 pWinStaObj
= IntGetWinStaForCbAccess();
1032 if (!fmt
|| !pWinStaObj
->ptiClipLock
)
1034 ERR("Access denied!\n");
1035 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
1039 if (scd
->fIncSerialNumber
)
1040 pWinStaObj
->iClipSerialNumber
++;
1042 /* Is it a delayed rendering? */
1045 /* Is it a bitmap? */
1046 if (fmt
== CF_BITMAP
)
1048 /* Make bitmap public */
1049 GreSetObjectOwner(hData
, GDI_OBJ_HMGR_PUBLIC
);
1052 /* Save data in the clipboard */
1053 IntAddFormatedData(pWinStaObj
, fmt
, hData
, scd
->fGlobalHandle
, FALSE
);
1054 TRACE("hData stored\n");
1056 /* If the serial number was increased, increase also the sequence number */
1057 if (scd
->fIncSerialNumber
)
1058 pWinStaObj
->iClipSequenceNumber
++;
1060 pWinStaObj
->fClipboardChanged
= TRUE
;
1062 /* Note: Synthesized formats are added in NtUserCloseClipboard */
1066 /* This is a delayed rendering */
1067 IntAddFormatedData(pWinStaObj
, fmt
, DATA_DELAYED
, FALSE
, FALSE
);
1068 TRACE("SetClipboardData delayed format: %u\n", fmt
);
1071 /* Return hData on success */
1075 TRACE("NtUserSetClipboardData returns: %p\n", hRet
);
1078 ObDereferenceObject(pWinStaObj
);
1084 NtUserSetClipboardData(UINT fmt
, HANDLE hData
, PSETCLIPBDATA pUnsafeScd
)
1089 TRACE("NtUserSetClipboardData(%x %p %p)\n", fmt
, hData
, pUnsafeScd
);
1093 ProbeForRead(pUnsafeScd
, sizeof(*pUnsafeScd
), 1);
1094 RtlCopyMemory(&scd
, pUnsafeScd
, sizeof(scd
));
1096 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1098 SetLastNtError(_SEH2_GetExceptionCode());
1099 _SEH2_YIELD(return NULL
;)
1103 UserEnterExclusive();
1105 /* Call internal function */
1106 hRet
= UserSetClipboardData(fmt
, hData
, &scd
);
1114 NtUserSetClipboardViewer(HWND hWndNewViewer
)
1116 HWND hWndNext
= NULL
;
1117 PWINSTATION_OBJECT pWinStaObj
;
1120 UserEnterExclusive();
1122 pWinStaObj
= IntGetWinStaForCbAccess();
1126 pWindow
= UserGetWindowObject(hWndNewViewer
);
1129 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1133 /* Return previous viewer. New viever window should
1134 send messages to rest of the chain */
1135 if (pWinStaObj
->spwndClipViewer
)
1136 hWndNext
= UserHMGetHandle(pWinStaObj
->spwndClipViewer
);
1138 /* Set new viewer window */
1139 pWinStaObj
->spwndClipViewer
= pWindow
;
1141 /* Notify viewer windows in chain */
1142 pWinStaObj
->fClipboardChanged
= FALSE
;
1143 if (pWinStaObj
->spwndClipViewer
)
1145 TRACE("Clipboard: sending WM_DRAWCLIPBOARD to %p\n", UserHMGetHandle(pWinStaObj
->spwndClipViewer
));
1146 // For 32-bit applications this message is sent as a notification
1147 co_IntSendMessageNoWait(UserHMGetHandle(pWinStaObj
->spwndClipViewer
), WM_DRAWCLIPBOARD
, 0, 0);
1152 ObDereferenceObject(pWinStaObj
);
1159 // Sequence number is incremented whenever the contents of the clipboard change
1160 // or the clipboard is emptied. If clipboard rendering is delayed,
1161 // the sequence number is not incremented until the changes are rendered.
1164 NtUserGetClipboardSequenceNumber(VOID
)
1167 PWINSTATION_OBJECT pWinStaObj
;
1171 pWinStaObj
= IntGetWinStaForCbAccess();
1175 /* Get windowstation sequence number */
1176 dwRet
= (DWORD
)pWinStaObj
->iClipSequenceNumber
;
1178 ObDereferenceObject(pWinStaObj
);
1187 NtUserConvertMemHandle(
1192 PCLIPBOARDDATA pMemObj
;
1194 UserEnterExclusive();
1196 /* Create Clipboard data object */
1197 pMemObj
= UserCreateObject(gHandleTable
, NULL
, NULL
, &hMem
, TYPE_CLIPDATA
, sizeof(CLIPBOARDDATA
) + cbData
);
1201 pMemObj
->cbData
= cbData
;
1206 ProbeForRead(pData
, cbData
, 1);
1207 memcpy(pMemObj
->Data
, pData
, cbData
);
1209 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1215 /* Release the extra reference (UserCreateObject added 2 references) */
1216 UserDereferenceObject(pMemObj
);
1218 /* If we failed to copy data, remove handle */
1221 UserDeleteObject(hMem
, TYPE_CLIPDATA
);
1232 NtUserCreateLocalMemHandle(
1238 PCLIPBOARDDATA pMemObj
;
1239 NTSTATUS Status
= STATUS_SUCCESS
;
1243 /* Get Clipboard data object */
1244 pMemObj
= (PCLIPBOARDDATA
)UserGetObject(gHandleTable
, hMem
, TYPE_CLIPDATA
);
1247 Status
= STATUS_INVALID_HANDLE
;
1252 if (cbData
> pMemObj
->cbData
)
1253 cbData
= pMemObj
->cbData
;
1255 /* Copy data to usermode */
1260 ProbeForWrite(pcbData
, sizeof(*pcbData
), 1);
1261 *pcbData
= pMemObj
->cbData
;
1264 ProbeForWrite(pData
, cbData
, 1);
1265 memcpy(pData
, pMemObj
->Data
, cbData
);
1267 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1269 Status
= _SEH2_GetExceptionCode();