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 zero value (pointing to formated object) */
41 IntIsFormatAvailable(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 IntFreeElementData(PCLIP pElement
)
57 if (!IS_DATA_DELAYED(pElement
) &&
58 !IS_DATA_SYNTHESIZED(pElement
))
60 if (pElement
->fGlobalHandle
)
61 UserDeleteObject(pElement
->hData
, TYPE_CLIPDATA
);
62 else if (pElement
->fmt
== CF_BITMAP
|| pElement
->fmt
== CF_PALETTE
||
63 pElement
->fmt
== CF_DSPBITMAP
)
65 GreSetObjectOwner(pElement
->hData
, GDI_OBJ_HMGR_POWNED
);
66 GreDeleteObject(pElement
->hData
);
71 /* Adds a new format and data to the clipboard */
73 IntAddFormatedData(PWINSTATION_OBJECT pWinStaObj
, UINT fmt
, HANDLE hData
, BOOLEAN fGlobalHandle
, BOOL bEnd
)
75 PCLIP pElement
= NULL
;
77 /* Use existing entry with specified format */
79 pElement
= IntIsFormatAvailable(pWinStaObj
, fmt
);
81 /* Put new entry at the end if nothing was found */
84 /* Allocate bigger clipboard if needed. We could use lists but Windows uses array */
85 if (pWinStaObj
->cNumClipFormats
% 4 == 0)
89 /* Allocate new clipboard */
90 pNewClip
= ExAllocatePoolWithTag(PagedPool
,
91 (pWinStaObj
->cNumClipFormats
+ 4) * sizeof(CLIP
),
95 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
100 memcpy(pNewClip
, pWinStaObj
->pClipBase
, pWinStaObj
->cNumClipFormats
* sizeof(CLIP
));
102 /* Free old clipboard */
103 if (pWinStaObj
->pClipBase
)
104 ExFreePoolWithTag(pWinStaObj
->pClipBase
, USERTAG_CLIPBOARD
);
107 pWinStaObj
->pClipBase
= pNewClip
;
110 /* New element is at the end */
111 pElement
= &pWinStaObj
->pClipBase
[pWinStaObj
->cNumClipFormats
];
113 pWinStaObj
->cNumClipFormats
++;
116 IntFreeElementData(pElement
);
118 pElement
->hData
= hData
;
119 pElement
->fGlobalHandle
= fGlobalHandle
;
125 IntIsClipboardOpenByMe(PWINSTATION_OBJECT pWinSta
)
127 /* Check if current thread has opened the clipboard */
128 if (pWinSta
->ptiClipLock
&&
129 pWinSta
->ptiClipLock
== PsGetCurrentThreadWin32Thread())
139 PWINSTATION_OBJECT pWinStaObj
,
143 ULONG cjInfoSize
, cjDataSize
;
144 PCLIPBOARDDATA pClipboardData
;
149 BITMAPINFOHEADER bmih
;
150 RGBQUAD rgbColors
[256];
152 PBITMAPINFO pbmi
= (PBITMAPINFO
)&bmiBuffer
;
154 /* Get the display DC */
155 hdc
= UserGetDCEx(NULL
, NULL
, DCX_USESTYLE
);
161 /* Get information about the bitmap format */
162 iResult
= GreGetDIBitsInternal(hdc
,
176 /* Get the size for a full BITMAPINFO */
177 cjInfoSize
= DIB_BitmapInfoSize(pbmi
, DIB_RGB_COLORS
);
179 /* Calculate the size of the clipboard data, which is a packed DIB */
180 cjDataSize
= cjInfoSize
+ pbmi
->bmiHeader
.biSizeImage
;
182 /* Create the clipboard data */
183 pClipboardData
= (PCLIPBOARDDATA
)UserCreateObject(gHandleTable
,
194 /* Set the data size */
195 pClipboardData
->cbData
= cjDataSize
;
197 /* Copy the BITMAPINFOHEADER */
198 memcpy(pClipboardData
->Data
, pbmi
, sizeof(BITMAPINFOHEADER
));
200 /* Get the bitmap bits and the color table */
201 iResult
= GreGetDIBitsInternal(hdc
,
204 abs(pbmi
->bmiHeader
.biHeight
),
205 (LPBYTE
)pClipboardData
->Data
+ cjInfoSize
,
206 (LPBITMAPINFO
)pClipboardData
->Data
,
208 pbmi
->bmiHeader
.biSizeImage
,
211 /* Add the clipboard data */
212 IntAddFormatedData(pWinStaObj
, CF_DIB
, hMem
, TRUE
, TRUE
);
214 /* Release the extra reference (UserCreateObject added 2 references) */
215 UserDereferenceObject(pClipboardData
);
218 UserReleaseDC(NULL
, hdc
, FALSE
);
222 IntSynthesizeBitmap(PWINSTATION_OBJECT pWinStaObj
, PCLIP pBmEl
)
225 PBITMAPINFO pBmi
, pConvertedBmi
= NULL
;
227 PCLIPBOARDDATA pMemObj
;
231 TRACE("IntSynthesizeBitmap(%p, %p)\n", pWinStaObj
, pBmEl
);
233 pDibEl
= IntIsFormatAvailable(pWinStaObj
, CF_DIB
);
234 ASSERT(pDibEl
&& !IS_DATA_SYNTHESIZED(pDibEl
));
235 if (!pDibEl
->fGlobalHandle
)
238 pMemObj
= (PCLIPBOARDDATA
)UserGetObject(gHandleTable
, pDibEl
->hData
, TYPE_CLIPDATA
);
242 pBmi
= (BITMAPINFO
*)pMemObj
->Data
;
244 if (pMemObj
->cbData
< sizeof(DWORD
) && pMemObj
->cbData
< pBmi
->bmiHeader
.biSize
)
247 pConvertedBmi
= DIB_ConvertBitmapInfo(pBmi
, DIB_RGB_COLORS
);
251 Offset
= DIB_BitmapInfoSize(pBmi
, DIB_RGB_COLORS
);
253 hdc
= UserGetDCEx(NULL
, NULL
, DCX_USESTYLE
);
257 hBm
= GreCreateDIBitmapInternal(hdc
,
258 pConvertedBmi
->bmiHeader
.biWidth
,
259 pConvertedBmi
->bmiHeader
.biHeight
,
261 pMemObj
->Data
+ Offset
,
265 pMemObj
->cbData
- Offset
,
270 GreSetObjectOwner(hBm
, GDI_OBJ_HMGR_PUBLIC
);
276 UserReleaseDC(NULL
, hdc
, FALSE
);
279 DIB_FreeConvertedBitmapInfo(pConvertedBmi
, pBmi
, -1);
283 IntAddSynthesizedFormats(PWINSTATION_OBJECT pWinStaObj
)
285 PCLIP pTextEl
, pUniTextEl
, pOemTextEl
, pLocaleEl
, pBmEl
, pDibEl
;
287 pTextEl
= IntIsFormatAvailable(pWinStaObj
, CF_TEXT
);
288 pOemTextEl
= IntIsFormatAvailable(pWinStaObj
, CF_OEMTEXT
);
289 pUniTextEl
= IntIsFormatAvailable(pWinStaObj
, CF_UNICODETEXT
);
290 pLocaleEl
= IntIsFormatAvailable(pWinStaObj
, CF_LOCALE
);
291 pBmEl
= IntIsFormatAvailable(pWinStaObj
, CF_BITMAP
);
292 pDibEl
= IntIsFormatAvailable(pWinStaObj
, CF_DIB
);
294 /* Add CF_LOCALE format if we have CF_TEXT */
295 if (!pLocaleEl
&& pTextEl
)
297 PCLIPBOARDDATA pMemObj
;
300 pMemObj
= (PCLIPBOARDDATA
)UserCreateObject(gHandleTable
, NULL
, NULL
, &hMem
, TYPE_CLIPDATA
,
301 sizeof(CLIPBOARDDATA
) + sizeof(LCID
));
304 pMemObj
->cbData
= sizeof(LCID
);
305 *((LCID
*)pMemObj
->Data
) = NtCurrentTeb()->CurrentLocale
;
306 IntAddFormatedData(pWinStaObj
, CF_LOCALE
, hMem
, TRUE
, TRUE
);
308 /* Release the extra reference (UserCreateObject added 2 references) */
309 UserDereferenceObject(pMemObj
);
313 /* Add CF_TEXT. Note: it is synthesized in user32.dll */
314 if (!pTextEl
&& (pUniTextEl
|| pOemTextEl
))
315 IntAddFormatedData(pWinStaObj
, CF_TEXT
, DATA_SYNTH_USER
, FALSE
, TRUE
);
317 /* Add CF_OEMTEXT. Note: it is synthesized in user32.dll */
318 if (!pOemTextEl
&& (pUniTextEl
|| pTextEl
))
319 IntAddFormatedData(pWinStaObj
, CF_OEMTEXT
, DATA_SYNTH_USER
, FALSE
, TRUE
);
321 /* Add CF_UNICODETEXT. Note: it is synthesized in user32.dll */
322 if (!pUniTextEl
&& (pTextEl
|| pOemTextEl
))
323 IntAddFormatedData(pWinStaObj
, CF_UNICODETEXT
, DATA_SYNTH_USER
, FALSE
, TRUE
);
325 /* Add CF_BITMAP. Note: it is synthesized on demand */
326 if (!pBmEl
&& pDibEl
)
327 IntAddFormatedData(pWinStaObj
, CF_BITMAP
, DATA_SYNTH_KRNL
, FALSE
, TRUE
);
329 /* Note: We need to render the DIB or DIBV5 format as soon as possible
330 because pallette information may change */
331 if (!pDibEl
&& pBmEl
)
332 IntSynthesizeDib(pWinStaObj
, pBmEl
->hData
);
336 UserEmptyClipboardData(PWINSTATION_OBJECT pWinSta
)
341 for (i
= 0; i
< pWinSta
->cNumClipFormats
; ++i
)
343 pElement
= &pWinSta
->pClipBase
[i
];
344 IntFreeElementData(pElement
);
347 if (pWinSta
->pClipBase
)
348 ExFreePoolWithTag(pWinSta
->pClipBase
, USERTAG_CLIPBOARD
);
350 pWinSta
->pClipBase
= NULL
;
351 pWinSta
->cNumClipFormats
= 0;
354 /* UserClipboardFreeWindow is called from co_UserFreeWindow in window.c */
356 UserClipboardFreeWindow(PWND pWindow
)
358 PWINSTATION_OBJECT pWinStaObj
;
360 pWinStaObj
= IntGetWinStaForCbAccess();
364 /* Check if clipboard is not locked by this window, if yes, unlock it */
365 if (pWindow
== pWinStaObj
->spwndClipOpen
)
367 /* The window that opens the clipboard was destroyed */
368 pWinStaObj
->spwndClipOpen
= NULL
;
369 pWinStaObj
->ptiClipLock
= NULL
;
371 if (pWindow
== pWinStaObj
->spwndClipOwner
)
373 /* The owner window was destroyed */
374 pWinStaObj
->spwndClipOwner
= NULL
;
376 /* Remove window from window chain */
377 if (pWindow
== pWinStaObj
->spwndClipViewer
)
378 pWinStaObj
->spwndClipViewer
= NULL
;
380 ObDereferenceObject(pWinStaObj
);
384 UserEnumClipboardFormats(UINT fmt
)
388 PWINSTATION_OBJECT pWinStaObj
= NULL
;
390 pWinStaObj
= IntGetWinStaForCbAccess();
394 /* Check if clipboard has been opened */
395 if (!IntIsClipboardOpenByMe(pWinStaObj
))
397 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
403 /* Return first format */
404 if (pWinStaObj
->pClipBase
)
405 Ret
= pWinStaObj
->pClipBase
[0].fmt
;
409 /* Return next format */
410 pElement
= IntIsFormatAvailable(pWinStaObj
, fmt
);
412 if (pElement
< &pWinStaObj
->pClipBase
[pWinStaObj
->cNumClipFormats
])
418 ObDereferenceObject(pWinStaObj
);
424 UserOpenClipboard(HWND hWnd
)
428 PWINSTATION_OBJECT pWinStaObj
= NULL
;
432 pWindow
= UserGetWindowObject(hWnd
);
437 pWinStaObj
= IntGetWinStaForCbAccess();
441 if (pWinStaObj
->ptiClipLock
)
443 /* Clipboard is already open */
444 if (pWinStaObj
->spwndClipOpen
!= pWindow
)
446 EngSetLastError(ERROR_ACCESS_DENIED
);
447 ERR("Access denied!\n");
453 pWinStaObj
->spwndClipOpen
= pWindow
;
454 pWinStaObj
->ptiClipLock
= PsGetCurrentThreadWin32Thread();
459 ObDereferenceObject(pWinStaObj
);
465 NtUserOpenClipboard(HWND hWnd
, DWORD Unknown1
)
469 UserEnterExclusive();
470 bRet
= UserOpenClipboard(hWnd
);
477 UserCloseClipboard(VOID
)
480 PWINSTATION_OBJECT pWinStaObj
= NULL
;
482 pWinStaObj
= IntGetWinStaForCbAccess();
486 if (!IntIsClipboardOpenByMe(pWinStaObj
))
488 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
492 /* Clipboard is no longer open */
493 pWinStaObj
->spwndClipOpen
= NULL
;
494 pWinStaObj
->ptiClipLock
= NULL
;
497 if (pWinStaObj
->fClipboardChanged
)
499 /* Add synthesized formats - they are rendered later */
500 IntAddSynthesizedFormats(pWinStaObj
);
502 /* Notify viewer windows in chain */
503 if (pWinStaObj
->spwndClipViewer
)
505 TRACE("Clipboard: sending WM_DRAWCLIPBOARD to %p\n", pWinStaObj
->spwndClipViewer
->head
.h
);
506 co_IntSendMessage(pWinStaObj
->spwndClipViewer
->head
.h
, WM_DRAWCLIPBOARD
, 0, 0);
509 pWinStaObj
->fClipboardChanged
= FALSE
;
514 ObDereferenceObject(pWinStaObj
);
520 NtUserCloseClipboard(VOID
)
524 UserEnterExclusive();
525 bRet
= UserCloseClipboard();
532 NtUserGetOpenClipboardWindow(VOID
)
535 PWINSTATION_OBJECT pWinStaObj
;
539 pWinStaObj
= IntGetWinStaForCbAccess();
543 if (pWinStaObj
->spwndClipOpen
)
544 hWnd
= pWinStaObj
->spwndClipOpen
->head
.h
;
546 ObDereferenceObject(pWinStaObj
);
555 NtUserChangeClipboardChain(HWND hWndRemove
, HWND hWndNewNext
)
559 PWINSTATION_OBJECT pWinStaObj
;
561 TRACE("NtUserChangeClipboardChain(%p, %p)\n", hWndRemove
, hWndNewNext
);
563 UserEnterExclusive();
565 pWinStaObj
= IntGetWinStaForCbAccess();
569 pWindowRemove
= UserGetWindowObject(hWndRemove
);
571 if (pWindowRemove
&& pWinStaObj
->spwndClipViewer
)
573 if (pWindowRemove
== pWinStaObj
->spwndClipViewer
)
574 pWinStaObj
->spwndClipViewer
= UserGetWindowObject(hWndNewNext
);
576 if (pWinStaObj
->spwndClipViewer
)
577 bRet
= (BOOL
)co_IntSendMessage(pWinStaObj
->spwndClipViewer
->head
.h
, WM_CHANGECBCHAIN
, (WPARAM
)hWndRemove
, (LPARAM
)hWndNewNext
);
580 ObDereferenceObject(pWinStaObj
);
589 NtUserCountClipboardFormats(VOID
)
592 PWINSTATION_OBJECT pWinStaObj
= NULL
;
596 pWinStaObj
= IntGetWinStaForCbAccess();
600 cFormats
= pWinStaObj
->cNumClipFormats
;
602 ObDereferenceObject(pWinStaObj
);
611 UserEmptyClipboard(VOID
)
614 PWINSTATION_OBJECT pWinStaObj
;
616 pWinStaObj
= IntGetWinStaForCbAccess();
620 if (IntIsClipboardOpenByMe(pWinStaObj
))
622 UserEmptyClipboardData(pWinStaObj
);
624 if (pWinStaObj
->spwndClipOwner
)
626 TRACE("Clipboard: WM_DESTROYCLIPBOARD to %p\n", pWinStaObj
->spwndClipOwner
->head
.h
);
627 co_IntSendMessageNoWait(pWinStaObj
->spwndClipOwner
->head
.h
, WM_DESTROYCLIPBOARD
, 0, 0);
630 pWinStaObj
->spwndClipOwner
= pWinStaObj
->spwndClipOpen
;
632 pWinStaObj
->iClipSequenceNumber
++;
638 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
639 ERR("Access denied!\n");
642 ObDereferenceObject(pWinStaObj
);
648 NtUserEmptyClipboard(VOID
)
652 TRACE("NtUserEmptyClipboard()\n");
654 UserEnterExclusive();
655 bRet
= UserEmptyClipboard();
662 NtUserGetClipboardFormatName(UINT fmt
, LPWSTR lpszFormatName
, INT cchMaxCount
)
668 /* If the format is built-in we fail */
671 /* Registetrated formats are >= 0xc000 */
675 if (cchMaxCount
< 1 || !lpszFormatName
)
677 EngSetLastError(ERROR_INVALID_PARAMETER
);
683 ProbeForWrite(lpszFormatName
, cchMaxCount
* sizeof(WCHAR
), 1);
685 iRet
= IntGetAtomName((RTL_ATOM
)fmt
,
687 cchMaxCount
* sizeof(WCHAR
));
688 iRet
/= sizeof(WCHAR
);
690 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
692 SetLastNtError(_SEH2_GetExceptionCode());
703 NtUserGetClipboardOwner(VOID
)
706 PWINSTATION_OBJECT pWinStaObj
;
710 pWinStaObj
= IntGetWinStaForCbAccess();
714 if (pWinStaObj
->spwndClipOwner
)
715 hWnd
= pWinStaObj
->spwndClipOwner
->head
.h
;
717 ObDereferenceObject(pWinStaObj
);
726 NtUserGetClipboardViewer(VOID
)
729 PWINSTATION_OBJECT pWinStaObj
;
733 pWinStaObj
= IntGetWinStaForCbAccess();
737 if (pWinStaObj
->spwndClipViewer
)
738 hWnd
= pWinStaObj
->spwndClipViewer
->head
.h
;
740 ObDereferenceObject(pWinStaObj
);
749 NtUserGetPriorityClipboardFormat(UINT
*paFormatPriorityList
, INT cFormats
)
752 PWINSTATION_OBJECT pWinStaObj
;
756 pWinStaObj
= IntGetWinStaForCbAccess();
760 if (pWinStaObj
->pClipBase
== NULL
)
768 ProbeForRead(paFormatPriorityList
, cFormats
* sizeof(UINT
), sizeof(UINT
));
772 for (i
= 0; i
< cFormats
; ++i
)
774 if (IntIsFormatAvailable(pWinStaObj
, paFormatPriorityList
[i
]))
776 iRet
= paFormatPriorityList
[i
];
781 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
783 SetLastNtError(_SEH2_GetExceptionCode());
788 ObDereferenceObject(pWinStaObj
);
798 NtUserIsClipboardFormatAvailable(UINT fmt
)
801 PWINSTATION_OBJECT pWinStaObj
;
803 TRACE("NtUserIsClipboardFormatAvailable(%x)\n", fmt
);
807 pWinStaObj
= IntGetWinStaForCbAccess();
811 if (IntIsFormatAvailable(pWinStaObj
, fmt
))
814 ObDereferenceObject(pWinStaObj
);
823 NtUserGetClipboardData(UINT fmt
, PGETCLIPBDATA pgcd
)
827 PWINSTATION_OBJECT pWinStaObj
= NULL
;
829 TRACE("NtUserGetClipboardData(%x, %p)\n", fmt
, pgcd
);
833 pWinStaObj
= IntGetWinStaForCbAccess();
837 if (!IntIsClipboardOpenByMe(pWinStaObj
))
839 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
843 pElement
= IntIsFormatAvailable(pWinStaObj
, fmt
);
844 if (pElement
&& IS_DATA_DELAYED(pElement
) && pWinStaObj
->spwndClipOwner
)
846 /* Send WM_RENDERFORMAT message */
847 pWinStaObj
->fInDelayedRendering
= TRUE
;
848 co_IntSendMessage(pWinStaObj
->spwndClipOwner
->head
.h
, WM_RENDERFORMAT
, (WPARAM
)fmt
, 0);
849 pWinStaObj
->fInDelayedRendering
= FALSE
;
851 /* Data should be in clipboard now */
852 pElement
= IntIsFormatAvailable(pWinStaObj
, fmt
);
855 if (!pElement
|| IS_DATA_DELAYED(pElement
))
859 if (IS_DATA_SYNTHESIZED(pElement
))
861 /* Note: Data is synthesized in usermode */
862 /* TODO: Add more formats */
868 pElement
= IntIsFormatAvailable(pWinStaObj
, CF_UNICODETEXT
);
869 if (IS_DATA_SYNTHESIZED(pElement
))
870 pElement
= IntIsFormatAvailable(pWinStaObj
, CF_TEXT
);
871 if (IS_DATA_SYNTHESIZED(pElement
))
872 pElement
= IntIsFormatAvailable(pWinStaObj
, CF_OEMTEXT
);
875 IntSynthesizeBitmap(pWinStaObj
, pElement
);
884 ProbeForWrite(pgcd
, sizeof(*pgcd
), 1);
885 pgcd
->uFmtRet
= pElement
->fmt
;
886 pgcd
->fGlobalHandle
= pElement
->fGlobalHandle
;
888 /* Text and bitmap needs more data */
893 pLocaleEl
= IntIsFormatAvailable(pWinStaObj
, CF_LOCALE
);
894 if (pLocaleEl
&& !IS_DATA_DELAYED(pLocaleEl
))
895 pgcd
->hLocale
= pLocaleEl
->hData
;
897 else if (fmt
== CF_BITMAP
)
901 pPaletteEl
= IntIsFormatAvailable(pWinStaObj
, CF_PALETTE
);
902 if (pPaletteEl
&& !IS_DATA_DELAYED(pPaletteEl
))
903 pgcd
->hPalette
= pPaletteEl
->hData
;
906 hRet
= pElement
->hData
;
908 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
910 SetLastNtError(_SEH2_GetExceptionCode());
916 ObDereferenceObject(pWinStaObj
);
920 TRACE("NtUserGetClipboardData returns %p\n", hRet
);
926 UserSetClipboardData(UINT fmt
, HANDLE hData
, PSETCLIPBDATA scd
)
929 PWINSTATION_OBJECT pWinStaObj
= NULL
;
931 pWinStaObj
= IntGetWinStaForCbAccess();
935 /* If it's delayed rendering we don't have to open clipboard */
936 if ((pWinStaObj
->fInDelayedRendering
&&
937 pWinStaObj
->spwndClipOwner
->head
.pti
!= PsGetCurrentThreadWin32Thread()) ||
938 !IntIsClipboardOpenByMe(pWinStaObj
))
940 ERR("Access denied!\n");
941 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
945 if (scd
->fIncSerialNumber
)
946 pWinStaObj
->iClipSerialNumber
++;
948 /* Is it a delayed render? */
951 /* Is it a bitmap? */
952 if (fmt
== CF_BITMAP
)
954 /* Make bitmap public */
955 GreSetObjectOwner(hData
, GDI_OBJ_HMGR_PUBLIC
);
958 /* Save data in the clipboard */
959 IntAddFormatedData(pWinStaObj
, fmt
, hData
, scd
->fGlobalHandle
, FALSE
);
960 TRACE("hData stored\n");
962 pWinStaObj
->iClipSequenceNumber
++;
963 pWinStaObj
->fClipboardChanged
= TRUE
;
965 /* Note: Synthesized formats are added in NtUserCloseClipboard */
969 /* This is a delayed render */
970 IntAddFormatedData(pWinStaObj
, fmt
, DATA_DELAYED
, FALSE
, FALSE
);
971 TRACE("SetClipboardData delayed format: %u\n", fmt
);
974 /* Return hData on success */
978 TRACE("NtUserSetClipboardData returns: %p\n", hRet
);
981 ObDereferenceObject(pWinStaObj
);
987 NtUserSetClipboardData(UINT fmt
, HANDLE hData
, PSETCLIPBDATA pUnsafeScd
)
992 TRACE("NtUserSetClipboardData(%x %p %p)\n", fmt
, hData
, pUnsafeScd
);
996 ProbeForRead(pUnsafeScd
, sizeof(*pUnsafeScd
), 1);
997 RtlCopyMemory(&scd
, pUnsafeScd
, sizeof(scd
));
999 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1001 SetLastNtError(_SEH2_GetExceptionCode());
1002 _SEH2_YIELD(return NULL
;)
1006 UserEnterExclusive();
1008 /* Call internal function */
1009 hRet
= UserSetClipboardData(fmt
, hData
, &scd
);
1017 NtUserSetClipboardViewer(HWND hWndNewViewer
)
1019 HWND hWndNext
= NULL
;
1020 PWINSTATION_OBJECT pWinStaObj
= NULL
;
1023 UserEnterExclusive();
1025 pWinStaObj
= IntGetWinStaForCbAccess();
1029 pWindow
= UserGetWindowObject(hWndNewViewer
);
1032 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1036 /* Return previous viewer. New viever window should
1037 send messages to rest of the chain */
1038 if (pWinStaObj
->spwndClipViewer
)
1039 hWndNext
= pWinStaObj
->spwndClipViewer
->head
.h
;
1041 /* Set new viewer window */
1042 pWinStaObj
->spwndClipViewer
= pWindow
;
1046 ObDereferenceObject(pWinStaObj
);
1053 // Sequence number is incremented whenever the contents of the clipboard change
1054 // or the clipboard is emptied. If clipboard rendering is delayed,
1055 // the sequence number is not incremented until the changes are rendered.
1058 NtUserGetClipboardSequenceNumber(VOID
)
1061 PWINSTATION_OBJECT pWinStaObj
;
1065 pWinStaObj
= IntGetWinStaForCbAccess();
1069 /* Get windowstation sequence number */
1070 dwRet
= (DWORD
)pWinStaObj
->iClipSequenceNumber
;
1072 ObDereferenceObject(pWinStaObj
);
1081 NtUserConvertMemHandle(
1086 PCLIPBOARDDATA pMemObj
;
1088 UserEnterExclusive();
1090 /* Create Clipboard data object */
1091 pMemObj
= UserCreateObject(gHandleTable
, NULL
, NULL
, &hMem
, TYPE_CLIPDATA
, sizeof(CLIPBOARDDATA
) + cbData
);
1095 pMemObj
->cbData
= cbData
;
1100 ProbeForRead(pData
, cbData
, 1);
1101 memcpy(pMemObj
->Data
, pData
, cbData
);
1103 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1109 /* Release the extra reference (UserCreateObject added 2 references) */
1110 UserDereferenceObject(pMemObj
);
1112 /* If we failed to copy data, remove handle */
1115 UserDeleteObject(hMem
, TYPE_CLIPDATA
);
1126 NtUserCreateLocalMemHandle(
1132 PCLIPBOARDDATA pMemObj
;
1133 NTSTATUS Status
= STATUS_SUCCESS
;
1137 /* Get Clipboard data object */
1138 pMemObj
= (PCLIPBOARDDATA
)UserGetObject(gHandleTable
, hMem
, TYPE_CLIPDATA
);
1141 Status
= STATUS_INVALID_HANDLE
;
1146 if (cbData
> pMemObj
->cbData
)
1147 cbData
= pMemObj
->cbData
;
1149 /* Copy data to usermode */
1154 ProbeForWrite(pcbData
, sizeof(*pcbData
), 1);
1155 *pcbData
= pMemObj
->cbData
;
1158 ProbeForWrite(pData
, cbData
, 1);
1159 memcpy(pData
, pMemObj
->Data
, cbData
);
1161 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1163 Status
= _SEH2_GetExceptionCode();