2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Clipboard routines
5 * FILE: subsys/win32k/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 PWINSTATION_OBJECT
static FASTCALL
21 IntGetWinStaForCbAccess()
24 PWINSTATION_OBJECT pWinStaObj
;
27 hWinSta
= UserGetProcessWindowStation();
28 Status
= IntValidateWindowStationHandle(hWinSta
, KernelMode
, WINSTA_ACCESSCLIPBOARD
, &pWinStaObj
);
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
, otClipBoardData
);
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 exisiting 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())
138 IntSynthesizeDib(PWINSTATION_OBJECT pWinStaObj
, HBITMAP hBm
)
144 PCLIPBOARDDATA pMemObj
;
147 hdc
= UserGetDCEx(NULL
, NULL
, DCX_USESTYLE
);
151 psurf
= SURFACE_ShareLockSurface(hBm
);
154 BITMAP_GetObject(psurf
, sizeof(BITMAP
), (PVOID
)&bm
);
155 SURFACE_ShareUnlockSurface(psurf
);
157 bi
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
158 bi
.bmiHeader
.biWidth
= bm
.bmWidth
;
159 bi
.bmiHeader
.biHeight
= bm
.bmHeight
;
160 bi
.bmiHeader
.biPlanes
= bm
.bmPlanes
;
161 bi
.bmiHeader
.biBitCount
= bm
.bmBitsPixel
;
162 bi
.bmiHeader
.biCompression
= BI_RGB
;
163 bi
.bmiHeader
.biSizeImage
= 0;
164 bi
.bmiHeader
.biXPelsPerMeter
= 0;
165 bi
.bmiHeader
.biYPelsPerMeter
= 0;
166 bi
.bmiHeader
.biClrUsed
= 0;
168 NtGdiGetDIBitsInternal(hdc
, hBm
, 0, bm
.bmHeight
, NULL
, &bi
, DIB_RGB_COLORS
, 0, 0);
170 pMemObj
= (PCLIPBOARDDATA
)UserCreateObject(gHandleTable
, NULL
, &hMem
, otClipBoardData
,
171 sizeof(BITMAPINFOHEADER
) + bi
.bmiHeader
.biSizeImage
);
174 pMemObj
->cbData
= sizeof(BITMAPINFOHEADER
) + bi
.bmiHeader
.biSizeImage
;
175 memcpy(pMemObj
->Data
, &bi
, sizeof(BITMAPINFOHEADER
));
176 NtGdiGetDIBitsInternal(hdc
, pMemObj
->Data
, 0, bm
.bmHeight
, (LPBYTE
)pMemObj
->Data
+ sizeof(BITMAPINFOHEADER
), &bi
, DIB_RGB_COLORS
, 0, 0);
177 IntAddFormatedData(pWinStaObj
, CF_DIB
, hMem
, TRUE
, TRUE
);
181 UserReleaseDC(NULL
, hdc
, FALSE
);
185 IntSynthesizeBitmap(PWINSTATION_OBJECT pWinStaObj
, PCLIP pBmEl
)
188 PBITMAPINFO pBmi
, pConvertedBmi
= NULL
;
190 PCLIPBOARDDATA pMemObj
;
194 TRACE("IntSynthesizeBitmap(%p, %p)\n", pWinStaObj
, pBmEl
);
196 pDibEl
= IntIsFormatAvailable(pWinStaObj
, CF_DIB
);
197 ASSERT(pDibEl
&& !IS_DATA_SYNTHESIZED(pDibEl
));
198 if(!pDibEl
->fGlobalHandle
)
201 pMemObj
= (PCLIPBOARDDATA
)UserGetObject(gHandleTable
, pDibEl
->hData
, otClipBoardData
);
205 pBmi
= (BITMAPINFO
*)pMemObj
->Data
;
207 if (pMemObj
->cbData
< sizeof(DWORD
) && pMemObj
->cbData
< pBmi
->bmiHeader
.biSize
)
210 pConvertedBmi
= DIB_ConvertBitmapInfo(pBmi
, DIB_RGB_COLORS
);
214 Offset
= DIB_BitmapInfoSize(pBmi
, DIB_RGB_COLORS
);
216 hdc
= UserGetDCEx(NULL
, NULL
, DCX_USESTYLE
);
220 hBm
= GreCreateDIBitmapInternal(hdc
,
221 pConvertedBmi
->bmiHeader
.biWidth
,
222 pConvertedBmi
->bmiHeader
.biHeight
,
224 pMemObj
->Data
+ Offset
,
232 GreSetObjectOwner(hBm
, GDI_OBJ_HMGR_PUBLIC
);
238 UserReleaseDC(NULL
, hdc
, FALSE
);
241 DIB_FreeConvertedBitmapInfo(pConvertedBmi
, pBmi
);
245 IntAddSynthesizedFormats(PWINSTATION_OBJECT pWinStaObj
)
247 PCLIP pTextEl
, pUniTextEl
, pOemTextEl
, pLocaleEl
, pBmEl
, pDibEl
;
249 pTextEl
= IntIsFormatAvailable(pWinStaObj
, CF_TEXT
);
250 pOemTextEl
= IntIsFormatAvailable(pWinStaObj
, CF_OEMTEXT
);
251 pUniTextEl
= IntIsFormatAvailable(pWinStaObj
, CF_UNICODETEXT
);
252 pLocaleEl
= IntIsFormatAvailable(pWinStaObj
, CF_LOCALE
);
253 pBmEl
= IntIsFormatAvailable(pWinStaObj
, CF_BITMAP
);
254 pDibEl
= IntIsFormatAvailable(pWinStaObj
, CF_DIB
);
256 /* Add CF_LOCALE format if we have CF_TEXT */
257 if (!pLocaleEl
&& pTextEl
)
259 PCLIPBOARDDATA pMemObj
;
262 pMemObj
= (PCLIPBOARDDATA
)UserCreateObject(gHandleTable
, NULL
, &hMem
, otClipBoardData
,
263 sizeof(CLIPBOARDDATA
) + sizeof(LCID
));
266 pMemObj
->cbData
= sizeof(LCID
);
267 *((LCID
*)pMemObj
->Data
) = NtCurrentTeb()->CurrentLocale
;
268 IntAddFormatedData(pWinStaObj
, CF_LOCALE
, hMem
, TRUE
, TRUE
);
272 /* Add CF_TEXT. Note: it is synthesized in user32.dll */
273 if (!pTextEl
&& (pUniTextEl
|| pOemTextEl
))
274 IntAddFormatedData(pWinStaObj
, CF_TEXT
, DATA_SYNTH_USER
, FALSE
, TRUE
);
276 /* Add CF_OEMTEXT. Note: it is synthesized in user32.dll */
277 if (!pOemTextEl
&& (pUniTextEl
|| pTextEl
))
278 IntAddFormatedData(pWinStaObj
, CF_OEMTEXT
, DATA_SYNTH_USER
, FALSE
, TRUE
);
280 /* Add CF_UNICODETEXT. Note: it is synthesized in user32.dll */
281 if (!pUniTextEl
&& (pTextEl
|| pOemTextEl
))
282 IntAddFormatedData(pWinStaObj
, CF_UNICODETEXT
, DATA_SYNTH_USER
, FALSE
, TRUE
);
284 /* Add CF_BITMAP. Note: it is synthesized on demand */
285 if (!pBmEl
&& pDibEl
)
286 IntAddFormatedData(pWinStaObj
, CF_BITMAP
, DATA_SYNTH_KRNL
, FALSE
, TRUE
);
288 /* Note: We need to render the DIB or DIBV5 format as soon as possible
289 because pallette information may change */
290 if (!pDibEl
&& pBmEl
)
291 IntSynthesizeDib(pWinStaObj
, pBmEl
->hData
);
295 UserEmptyClipboardData(PWINSTATION_OBJECT pWinSta
)
300 for (i
= 0; i
< pWinSta
->cNumClipFormats
; ++i
)
302 pElement
= &pWinSta
->pClipBase
[i
];
303 IntFreeElementData(pElement
);
306 if(pWinSta
->pClipBase
)
307 ExFreePoolWithTag(pWinSta
->pClipBase
, USERTAG_CLIPBOARD
);
308 pWinSta
->pClipBase
= NULL
;
309 pWinSta
->cNumClipFormats
= 0;
312 /* UserClipboardFreeWindow is called from co_UserFreeWindow in window.c */
314 UserClipboardFreeWindow(PWND pWindow
)
316 PWINSTATION_OBJECT pWinStaObj
;
318 pWinStaObj
= IntGetWinStaForCbAccess();
322 /* Check if clipboard is not locked by this window, if yes, unlock it */
323 if (pWindow
== pWinStaObj
->spwndClipOpen
)
325 /* The window that opens the clipboard was destroyed */
326 pWinStaObj
->spwndClipOpen
= NULL
;
327 pWinStaObj
->ptiClipLock
= NULL
;
329 if (pWindow
== pWinStaObj
->spwndClipOwner
)
331 /* The owner window was destroyed */
332 pWinStaObj
->spwndClipOwner
= NULL
;
334 /* Remove window from window chain */
335 if (pWindow
== pWinStaObj
->spwndClipViewer
)
336 pWinStaObj
->spwndClipViewer
= NULL
;
338 ObDereferenceObject(pWinStaObj
);
342 UserEnumClipboardFormats(UINT fmt
)
346 PWINSTATION_OBJECT pWinStaObj
= NULL
;
348 pWinStaObj
= IntGetWinStaForCbAccess();
352 /* Check if clipboard has been opened */
353 if (!IntIsClipboardOpenByMe(pWinStaObj
))
355 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
361 /* Return first format */
362 if (pWinStaObj
->pClipBase
)
363 Ret
= pWinStaObj
->pClipBase
[0].fmt
;
367 /* Return next format */
368 pElement
= IntIsFormatAvailable(pWinStaObj
, fmt
);
370 if (pElement
< &pWinStaObj
->pClipBase
[pWinStaObj
->cNumClipFormats
])
376 ObDereferenceObject(pWinStaObj
);
382 UserOpenClipboard(HWND hWnd
)
386 PWINSTATION_OBJECT pWinStaObj
= NULL
;
390 pWindow
= UserGetWindowObject(hWnd
);
395 pWinStaObj
= IntGetWinStaForCbAccess();
399 if (pWinStaObj
->ptiClipLock
)
401 /* Clipboard is already open */
402 if (pWinStaObj
->spwndClipOpen
!= pWindow
)
404 EngSetLastError(ERROR_ACCESS_DENIED
);
405 ERR("Access denied!\n");
411 pWinStaObj
->spwndClipOpen
= pWindow
;
412 pWinStaObj
->ptiClipLock
= PsGetCurrentThreadWin32Thread();
417 ObDereferenceObject(pWinStaObj
);
423 NtUserOpenClipboard(HWND hWnd
, DWORD Unknown1
)
427 UserEnterExclusive();
428 bRet
= UserOpenClipboard(hWnd
);
435 UserCloseClipboard(VOID
)
438 PWINSTATION_OBJECT pWinStaObj
= NULL
;
440 pWinStaObj
= IntGetWinStaForCbAccess();
444 if (!IntIsClipboardOpenByMe(pWinStaObj
))
446 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
450 /* Clipboard is no longer open */
451 pWinStaObj
->spwndClipOpen
= NULL
;
452 pWinStaObj
->ptiClipLock
= NULL
;
455 if (pWinStaObj
->fClipboardChanged
)
457 /* Add synthesized formats - they are rendered later */
458 IntAddSynthesizedFormats(pWinStaObj
);
460 /* Notify viewer windows in chain */
461 if (pWinStaObj
->spwndClipViewer
)
463 TRACE("Clipboard: sending WM_DRAWCLIPBOARD to %p\n", pWinStaObj
->spwndClipViewer
->head
.h
);
464 co_IntSendMessage(pWinStaObj
->spwndClipViewer
->head
.h
, WM_DRAWCLIPBOARD
, 0, 0);
467 pWinStaObj
->fClipboardChanged
= FALSE
;
472 ObDereferenceObject(pWinStaObj
);
478 NtUserCloseClipboard(VOID
)
482 UserEnterExclusive();
483 bRet
= UserCloseClipboard();
490 NtUserGetOpenClipboardWindow(VOID
)
493 PWINSTATION_OBJECT pWinStaObj
;
497 pWinStaObj
= IntGetWinStaForCbAccess();
501 if (pWinStaObj
->spwndClipOpen
)
502 hWnd
= pWinStaObj
->spwndClipOpen
->head
.h
;
504 ObDereferenceObject(pWinStaObj
);
513 NtUserChangeClipboardChain(HWND hWndRemove
, HWND hWndNewNext
)
517 PWINSTATION_OBJECT pWinStaObj
;
519 TRACE("NtUserChangeClipboardChain(%p, %p)\n", hWndRemove
, hWndNewNext
);
521 UserEnterExclusive();
523 pWinStaObj
= IntGetWinStaForCbAccess();
527 pWindowRemove
= UserGetWindowObject(hWndRemove
);
529 if (pWindowRemove
&& pWinStaObj
->spwndClipViewer
)
531 if(pWindowRemove
== pWinStaObj
->spwndClipViewer
)
532 pWinStaObj
->spwndClipViewer
= UserGetWindowObject(hWndNewNext
);
534 if(pWinStaObj
->spwndClipViewer
)
535 bRet
= (BOOL
)co_IntSendMessage(pWinStaObj
->spwndClipViewer
->head
.h
, WM_CHANGECBCHAIN
, (WPARAM
)hWndRemove
, (LPARAM
)hWndNewNext
);
538 ObDereferenceObject(pWinStaObj
);
547 NtUserCountClipboardFormats(VOID
)
550 PWINSTATION_OBJECT pWinStaObj
= NULL
;
554 pWinStaObj
= IntGetWinStaForCbAccess();
558 cFormats
= pWinStaObj
->cNumClipFormats
;
560 ObDereferenceObject(pWinStaObj
);
569 UserEmptyClipboard(VOID
)
572 PWINSTATION_OBJECT pWinStaObj
;
574 pWinStaObj
= IntGetWinStaForCbAccess();
578 if (IntIsClipboardOpenByMe(pWinStaObj
))
580 UserEmptyClipboardData(pWinStaObj
);
582 if (pWinStaObj
->spwndClipOwner
)
584 TRACE("Clipboard: WM_DESTROYCLIPBOARD to %p", pWinStaObj
->spwndClipOwner
->head
.h
);
585 co_IntSendMessageNoWait(pWinStaObj
->spwndClipOwner
->head
.h
, WM_DESTROYCLIPBOARD
, 0, 0);
588 pWinStaObj
->spwndClipOwner
= pWinStaObj
->spwndClipOpen
;
590 pWinStaObj
->iClipSequenceNumber
++;
596 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
597 ERR("Access denied!\n");
600 ObDereferenceObject(pWinStaObj
);
606 NtUserEmptyClipboard(VOID
)
610 TRACE("NtUserEmptyClipboard()\n");
612 UserEnterExclusive();
613 bRet
= UserEmptyClipboard();
620 NtUserGetClipboardFormatName(UINT fmt
, LPWSTR lpszFormatName
, INT cchMaxCount
)
626 /* If the format is built-in we fail */
629 /* Registetrated formats are >= 0xc000 */
633 if (cchMaxCount
< 1 || !lpszFormatName
)
635 EngSetLastError(ERROR_INVALID_PARAMETER
);
641 ProbeForWrite(lpszFormatName
, cchMaxCount
* sizeof(WCHAR
), 1);
643 iRet
= IntGetAtomName((RTL_ATOM
)fmt
,
645 cchMaxCount
* sizeof(WCHAR
));
646 iRet
/= sizeof(WCHAR
);
648 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
650 SetLastNtError(_SEH2_GetExceptionCode());
661 NtUserGetClipboardOwner(VOID
)
664 PWINSTATION_OBJECT pWinStaObj
;
668 pWinStaObj
= IntGetWinStaForCbAccess();
672 if (pWinStaObj
->spwndClipOwner
)
673 hWnd
= pWinStaObj
->spwndClipOwner
->head
.h
;
675 ObDereferenceObject(pWinStaObj
);
684 NtUserGetClipboardViewer(VOID
)
687 PWINSTATION_OBJECT pWinStaObj
;
691 pWinStaObj
= IntGetWinStaForCbAccess();
695 if (pWinStaObj
->spwndClipViewer
)
696 hWnd
= pWinStaObj
->spwndClipViewer
->head
.h
;
698 ObDereferenceObject(pWinStaObj
);
707 NtUserGetPriorityClipboardFormat(UINT
*paFormatPriorityList
, INT cFormats
)
710 PWINSTATION_OBJECT pWinStaObj
;
714 pWinStaObj
= IntGetWinStaForCbAccess();
718 if (pWinStaObj
->pClipBase
== NULL
)
726 ProbeForRead(paFormatPriorityList
, cFormats
* sizeof(UINT
), sizeof(UINT
));
730 for (i
= 0; i
< cFormats
; ++i
)
732 if (IntIsFormatAvailable(pWinStaObj
, paFormatPriorityList
[i
]))
734 iRet
= paFormatPriorityList
[i
];
739 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
741 SetLastNtError(_SEH2_GetExceptionCode());
746 ObDereferenceObject(pWinStaObj
);
756 NtUserIsClipboardFormatAvailable(UINT fmt
)
759 PWINSTATION_OBJECT pWinStaObj
;
761 TRACE("NtUserIsClipboardFormatAvailable(%x)\n", fmt
);
765 pWinStaObj
= IntGetWinStaForCbAccess();
769 if (IntIsFormatAvailable(pWinStaObj
, fmt
))
772 ObDereferenceObject(pWinStaObj
);
781 NtUserGetClipboardData(UINT fmt
, PGETCLIPBDATA pgcd
)
785 PWINSTATION_OBJECT pWinStaObj
= NULL
;
787 TRACE("NtUserGetClipboardData(%x, %p)\n", fmt
, pgcd
);
791 pWinStaObj
= IntGetWinStaForCbAccess();
795 if (!IntIsClipboardOpenByMe(pWinStaObj
))
797 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
801 pElement
= IntIsFormatAvailable(pWinStaObj
, fmt
);
802 if (pElement
&& IS_DATA_DELAYED(pElement
) && pWinStaObj
->spwndClipOwner
)
804 /* Send WM_RENDERFORMAT message */
805 pWinStaObj
->fInDelayedRendering
= TRUE
;
806 co_IntSendMessage(pWinStaObj
->spwndClipOwner
->head
.h
, WM_RENDERFORMAT
, (WPARAM
)fmt
, 0);
807 pWinStaObj
->fInDelayedRendering
= FALSE
;
809 /* Data should be in clipboard now */
810 pElement
= IntIsFormatAvailable(pWinStaObj
, fmt
);
813 if (!pElement
|| IS_DATA_DELAYED(pElement
))
817 if (IS_DATA_SYNTHESIZED(pElement
))
819 /* Note: Data is synthesized in usermode */
820 /* TODO: Add more formats */
826 pElement
= IntIsFormatAvailable(pWinStaObj
, CF_UNICODETEXT
);
827 if (IS_DATA_SYNTHESIZED(pElement
))
828 pElement
= IntIsFormatAvailable(pWinStaObj
, CF_TEXT
);
829 if (IS_DATA_SYNTHESIZED(pElement
))
830 pElement
= IntIsFormatAvailable(pWinStaObj
, CF_OEMTEXT
);
833 IntSynthesizeBitmap(pWinStaObj
, pElement
);
842 ProbeForWrite(pgcd
, sizeof(*pgcd
), 1);
843 pgcd
->uFmtRet
= pElement
->fmt
;
844 pgcd
->fGlobalHandle
= pElement
->fGlobalHandle
;
846 /* Text and bitmap needs more data */
851 pLocaleEl
= IntIsFormatAvailable(pWinStaObj
, CF_LOCALE
);
852 if (pLocaleEl
&& !IS_DATA_DELAYED(pLocaleEl
))
853 pgcd
->hLocale
= pLocaleEl
->hData
;
855 else if (fmt
== CF_BITMAP
)
859 pPaletteEl
= IntIsFormatAvailable(pWinStaObj
, CF_PALETTE
);
860 if (pPaletteEl
&& !IS_DATA_DELAYED(pPaletteEl
))
861 pgcd
->hPalette
= pPaletteEl
->hData
;
864 hRet
= pElement
->hData
;
866 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
868 SetLastNtError(_SEH2_GetExceptionCode());
874 ObDereferenceObject(pWinStaObj
);
878 TRACE("NtUserGetClipboardData returns %p\n", hRet
);
884 UserSetClipboardData(UINT fmt
, HANDLE hData
, PSETCLIPBDATA scd
)
887 PWINSTATION_OBJECT pWinStaObj
= NULL
;
889 pWinStaObj
= IntGetWinStaForCbAccess();
893 /* If it's delayed rendering we don't have to open clipboard */
894 if ((pWinStaObj
->fInDelayedRendering
&&
895 pWinStaObj
->spwndClipOwner
->head
.pti
!= PsGetCurrentThreadWin32Thread()) ||
896 !IntIsClipboardOpenByMe(pWinStaObj
))
898 ERR("Access denied!\n");
899 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
903 if (scd
->fIncSerialNumber
)
904 pWinStaObj
->iClipSerialNumber
++;
906 /* Is it a delayed render? */
909 /* Is it a bitmap? */
910 if (fmt
== CF_BITMAP
)
912 /* Make bitmap public */
913 GreSetObjectOwner(hData
, GDI_OBJ_HMGR_PUBLIC
);
916 /* Save data in the clipboard */
917 IntAddFormatedData(pWinStaObj
, fmt
, hData
, scd
->fGlobalHandle
, FALSE
);
918 TRACE("hData stored\n");
920 pWinStaObj
->iClipSequenceNumber
++;
921 pWinStaObj
->fClipboardChanged
= TRUE
;
923 /* Note: Synthesized formats are added in NtUserCloseClipboard */
927 /* This is a delayed render */
928 IntAddFormatedData(pWinStaObj
, fmt
, DATA_DELAYED
, FALSE
, FALSE
);
929 TRACE("SetClipboardData delayed format: %u\n", fmt
);
932 /* Return hData on success */
936 TRACE("NtUserSetClipboardData returns: %p\n", hRet
);
939 ObDereferenceObject(pWinStaObj
);
945 NtUserSetClipboardData(UINT fmt
, HANDLE hData
, PSETCLIPBDATA pUnsafeScd
)
950 TRACE("NtUserSetClipboardData(%x %p %p)\n", fmt
, hData
, pUnsafeScd
);
954 ProbeForRead(pUnsafeScd
, sizeof(*pUnsafeScd
), 1);
955 RtlCopyMemory(&scd
, pUnsafeScd
, sizeof(scd
));
957 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
959 SetLastNtError(_SEH2_GetExceptionCode());
960 _SEH2_YIELD(return NULL
;)
964 UserEnterExclusive();
966 /* Call internal function */
967 hRet
= UserSetClipboardData(fmt
, hData
, &scd
);
975 NtUserSetClipboardViewer(HWND hWndNewViewer
)
977 HWND hWndNext
= NULL
;
978 PWINSTATION_OBJECT pWinStaObj
= NULL
;
981 UserEnterExclusive();
983 pWinStaObj
= IntGetWinStaForCbAccess();
987 pWindow
= UserGetWindowObject(hWndNewViewer
);
990 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
994 /* Return previous viewer. New viever window should
995 send messages to rest of the chain */
996 if (pWinStaObj
->spwndClipViewer
)
997 hWndNext
= pWinStaObj
->spwndClipViewer
->head
.h
;
999 /* Set new viewer window */
1000 pWinStaObj
->spwndClipViewer
= pWindow
;
1004 ObDereferenceObject(pWinStaObj
);
1011 // Sequence number is incremented whenever the contents of the clipboard change
1012 // or the clipboard is emptied. If clipboard rendering is delayed,
1013 // the sequence number is not incremented until the changes are rendered.
1016 NtUserGetClipboardSequenceNumber(VOID
)
1019 PWINSTATION_OBJECT pWinStaObj
;
1023 pWinStaObj
= IntGetWinStaForCbAccess();
1027 /* Get windowstation sequence number */
1028 dwRet
= (DWORD
)pWinStaObj
->iClipSequenceNumber
;
1030 ObDereferenceObject(pWinStaObj
);
1039 NtUserConvertMemHandle(
1044 PCLIPBOARDDATA pMemObj
;
1046 UserEnterExclusive();
1048 /* Create Clipboard data object */
1049 pMemObj
= UserCreateObject(gHandleTable
, NULL
, &hMem
, otClipBoardData
, sizeof(CLIPBOARDDATA
) + cbData
);
1053 pMemObj
->cbData
= cbData
;
1058 ProbeForRead(pData
, cbData
, 1);
1059 memcpy(pMemObj
->Data
, pData
, cbData
);
1061 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1067 /* If we failed to copy data, remove handle */
1070 UserDeleteObject(hMem
, otClipBoardData
);
1081 NtUserCreateLocalMemHandle(
1087 PCLIPBOARDDATA pMemObj
;
1088 NTSTATUS Status
= STATUS_SUCCESS
;
1092 /* Get Clipboard data object */
1093 pMemObj
= (PCLIPBOARDDATA
)UserGetObject(gHandleTable
, hMem
, otClipBoardData
);
1096 Status
= STATUS_INVALID_HANDLE
;
1101 if (cbData
> pMemObj
->cbData
)
1102 cbData
= pMemObj
->cbData
;
1104 /* Copy data to usermode */
1109 ProbeForWrite(pcbData
, sizeof(*pcbData
), 1);
1110 *pcbData
= pMemObj
->cbData
;
1113 ProbeForWrite(pData
, cbData
, 1);
1114 memcpy(pData
, pMemObj
->Data
, cbData
);
1116 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1118 Status
= _SEH2_GetExceptionCode();