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 GreDeleteObject(pElement
->hData
);
70 /* adds a new format and data to the clipboard */
72 IntAddFormatedData(PWINSTATION_OBJECT pWinStaObj
, UINT fmt
, HANDLE hData
, BOOLEAN fGlobalHandle
, BOOL bEnd
)
74 PCLIP pElement
= NULL
;
76 /* Use exisiting entry with specified format */
78 pElement
= IntIsFormatAvailable(pWinStaObj
, fmt
);
80 /* Put new entry at the end if nothing was found */
83 /* Allocate bigger clipboard if needed. We could use lists but Windows uses array */
84 if (pWinStaObj
->cNumClipFormats
% 4 == 0)
88 /* Allocate new clipboard */
89 pNewClip
= ExAllocatePoolWithTag(PagedPool
,
90 (pWinStaObj
->cNumClipFormats
+ 4) * sizeof(CLIP
),
94 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
99 memcpy(pNewClip
, pWinStaObj
->pClipBase
, pWinStaObj
->cNumClipFormats
* sizeof(CLIP
));
101 /* Free old clipboard */
102 if (pWinStaObj
->pClipBase
)
103 ExFreePoolWithTag(pWinStaObj
->pClipBase
, USERTAG_CLIPBOARD
);
106 pWinStaObj
->pClipBase
= pNewClip
;
109 /* New element is at the end */
110 pElement
= &pWinStaObj
->pClipBase
[pWinStaObj
->cNumClipFormats
];
112 pWinStaObj
->cNumClipFormats
++;
115 IntFreeElementData(pElement
);
117 pElement
->hData
= hData
;
118 pElement
->fGlobalHandle
= fGlobalHandle
;
124 IntIsClipboardOpenByMe(PWINSTATION_OBJECT pWinSta
)
126 /* check if current thread has opened the clipboard */
127 if (pWinSta
->ptiClipLock
&&
128 pWinSta
->ptiClipLock
== PsGetCurrentThreadWin32Thread())
137 IntSynthesizeDib(PWINSTATION_OBJECT pWinStaObj
, HBITMAP hBm
)
143 PCLIPBOARDDATA pMemObj
;
146 hdc
= UserGetDCEx(NULL
, NULL
, DCX_USESTYLE
);
150 psurf
= SURFACE_ShareLockSurface(hBm
);
153 BITMAP_GetObject(psurf
, sizeof(BITMAP
), (PVOID
)&bm
);
154 SURFACE_ShareUnlockSurface(psurf
);
156 bi
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
157 bi
.bmiHeader
.biWidth
= bm
.bmWidth
;
158 bi
.bmiHeader
.biHeight
= bm
.bmHeight
;
159 bi
.bmiHeader
.biPlanes
= bm
.bmPlanes
;
160 bi
.bmiHeader
.biBitCount
= bm
.bmBitsPixel
;
161 bi
.bmiHeader
.biCompression
= BI_RGB
;
162 bi
.bmiHeader
.biSizeImage
= 0;
163 bi
.bmiHeader
.biXPelsPerMeter
= 0;
164 bi
.bmiHeader
.biYPelsPerMeter
= 0;
165 bi
.bmiHeader
.biClrUsed
= 0;
167 NtGdiGetDIBitsInternal(hdc
, hBm
, 0, bm
.bmHeight
, NULL
, &bi
, DIB_RGB_COLORS
, 0, 0);
169 pMemObj
= (PCLIPBOARDDATA
)UserCreateObject(gHandleTable
, NULL
, &hMem
, otClipBoardData
,
170 sizeof(BITMAPINFOHEADER
) + bi
.bmiHeader
.biSizeImage
);
173 pMemObj
->cbData
= sizeof(BITMAPINFOHEADER
) + bi
.bmiHeader
.biSizeImage
;
174 memcpy(pMemObj
->Data
, &bi
, sizeof(BITMAPINFOHEADER
));
175 NtGdiGetDIBitsInternal(hdc
, pMemObj
->Data
, 0, bm
.bmHeight
, (LPBYTE
)pMemObj
->Data
+ sizeof(BITMAPINFOHEADER
), &bi
, DIB_RGB_COLORS
, 0, 0);
176 IntAddFormatedData(pWinStaObj
, CF_DIB
, hMem
, TRUE
, TRUE
);
180 UserReleaseDC(NULL
, hdc
, FALSE
);
184 IntSynthesizeBitmap(PWINSTATION_OBJECT pWinStaObj
, PCLIP pBmEl
)
187 PBITMAPINFO pBmi
, pConvertedBmi
= NULL
;
189 PCLIPBOARDDATA pMemObj
;
193 TRACE("IntSynthesizeBitmap(%p, %p)\n", pWinStaObj
, pBmEl
);
195 pDibEl
= IntIsFormatAvailable(pWinStaObj
, CF_DIB
);
196 ASSERT(pDibEl
&& !IS_DATA_SYNTHESIZED(pDibEl
));
197 if(!pDibEl
->fGlobalHandle
)
200 pMemObj
= (PCLIPBOARDDATA
)UserGetObject(gHandleTable
, pDibEl
->hData
, otClipBoardData
);
204 pBmi
= (BITMAPINFO
*)pMemObj
->Data
;
206 if (pMemObj
->cbData
< sizeof(DWORD
) && pMemObj
->cbData
< pBmi
->bmiHeader
.biSize
)
209 pConvertedBmi
= DIB_ConvertBitmapInfo(pBmi
, DIB_RGB_COLORS
);
213 Offset
= DIB_BitmapInfoSize(pBmi
, DIB_RGB_COLORS
);
215 hdc
= UserGetDCEx(NULL
, NULL
, DCX_USESTYLE
);
219 hBm
= GreCreateDIBitmapInternal(hdc
,
220 pConvertedBmi
->bmiHeader
.biWidth
,
221 pConvertedBmi
->bmiHeader
.biHeight
,
223 pMemObj
->Data
+ Offset
,
231 GreSetObjectOwner(hBm
, GDI_OBJ_HMGR_PUBLIC
);
237 UserReleaseDC(NULL
, hdc
, FALSE
);
240 DIB_FreeConvertedBitmapInfo(pConvertedBmi
, pBmi
);
244 IntAddSynthesizedFormats(PWINSTATION_OBJECT pWinStaObj
)
246 PCLIP pTextEl
, pUniTextEl
, pOemTextEl
, pLocaleEl
, pBmEl
, pDibEl
;
248 pTextEl
= IntIsFormatAvailable(pWinStaObj
, CF_TEXT
);
249 pOemTextEl
= IntIsFormatAvailable(pWinStaObj
, CF_OEMTEXT
);
250 pUniTextEl
= IntIsFormatAvailable(pWinStaObj
, CF_UNICODETEXT
);
251 pLocaleEl
= IntIsFormatAvailable(pWinStaObj
, CF_LOCALE
);
252 pBmEl
= IntIsFormatAvailable(pWinStaObj
, CF_BITMAP
);
253 pDibEl
= IntIsFormatAvailable(pWinStaObj
, CF_DIB
);
255 /* Add CF_LOCALE format if we have CF_TEXT */
256 if (!pLocaleEl
&& pTextEl
)
258 PCLIPBOARDDATA pMemObj
;
261 pMemObj
= (PCLIPBOARDDATA
)UserCreateObject(gHandleTable
, NULL
, &hMem
, otClipBoardData
,
262 sizeof(CLIPBOARDDATA
) + sizeof(LCID
));
265 pMemObj
->cbData
= sizeof(LCID
);
266 *((LCID
*)pMemObj
->Data
) = NtCurrentTeb()->CurrentLocale
;
267 IntAddFormatedData(pWinStaObj
, CF_LOCALE
, hMem
, TRUE
, TRUE
);
271 /* Add CF_TEXT. Note: it is synthesized in user32.dll */
272 if (!pTextEl
&& (pUniTextEl
|| pOemTextEl
))
273 IntAddFormatedData(pWinStaObj
, CF_TEXT
, DATA_SYNTH_USER
, FALSE
, TRUE
);
275 /* Add CF_OEMTEXT. Note: it is synthesized in user32.dll */
276 if (!pOemTextEl
&& (pUniTextEl
|| pTextEl
))
277 IntAddFormatedData(pWinStaObj
, CF_OEMTEXT
, DATA_SYNTH_USER
, FALSE
, TRUE
);
279 /* Add CF_UNICODETEXT. Note: it is synthesized in user32.dll */
280 if (!pUniTextEl
&& (pTextEl
|| pOemTextEl
))
281 IntAddFormatedData(pWinStaObj
, CF_UNICODETEXT
, DATA_SYNTH_USER
, FALSE
, TRUE
);
283 /* Add CF_BITMAP. Note: it is synthesized on demand */
284 if (!pBmEl
&& pDibEl
)
285 IntAddFormatedData(pWinStaObj
, CF_BITMAP
, DATA_SYNTH_KRNL
, FALSE
, TRUE
);
287 /* Note: we need to render the DIB or DIBV5 format as soon as possible
288 because pallette information may change */
289 if (!pDibEl
&& pBmEl
)
290 IntSynthesizeDib(pWinStaObj
, pBmEl
->hData
);
294 UserEmptyClipboardData(PWINSTATION_OBJECT pWinSta
)
299 for (i
= 0; i
< pWinSta
->cNumClipFormats
; ++i
)
301 pElement
= &pWinSta
->pClipBase
[i
];
302 IntFreeElementData(pElement
);
305 if(pWinSta
->pClipBase
)
306 ExFreePoolWithTag(pWinSta
->pClipBase
, USERTAG_CLIPBOARD
);
307 pWinSta
->pClipBase
= NULL
;
308 pWinSta
->cNumClipFormats
= 0;
311 /* UserClipboardFreeWindow is called from co_UserFreeWindow in window.c */
313 UserClipboardFreeWindow(PWND pWindow
)
315 PWINSTATION_OBJECT pWinStaObj
;
317 pWinStaObj
= IntGetWinStaForCbAccess();
321 /* check if clipboard is not locked by this window, if yes, unlock it */
322 if (pWindow
== pWinStaObj
->spwndClipOpen
)
324 /* the window that opens the clipboard was destroyed */
325 pWinStaObj
->spwndClipOpen
= NULL
;
326 pWinStaObj
->ptiClipLock
= NULL
;
328 if (pWindow
== pWinStaObj
->spwndClipOwner
)
330 /* the owner window was destroyed */
331 pWinStaObj
->spwndClipOwner
= NULL
;
333 /* remove window from window chain */
334 if (pWindow
== pWinStaObj
->spwndClipViewer
)
335 pWinStaObj
->spwndClipViewer
= NULL
;
337 ObDereferenceObject(pWinStaObj
);
341 UserEnumClipboardFormats(UINT fmt
)
345 PWINSTATION_OBJECT pWinStaObj
= NULL
;
347 pWinStaObj
= IntGetWinStaForCbAccess();
351 /* Check if clipboard has been opened */
352 if (!IntIsClipboardOpenByMe(pWinStaObj
))
354 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
360 /* Return first format */
361 if (pWinStaObj
->pClipBase
)
362 Ret
= pWinStaObj
->pClipBase
[0].fmt
;
366 /* Return next format */
367 pElement
= IntIsFormatAvailable(pWinStaObj
, fmt
);
369 if (pElement
< &pWinStaObj
->pClipBase
[pWinStaObj
->cNumClipFormats
])
375 ObDereferenceObject(pWinStaObj
);
381 NtUserOpenClipboard(HWND hWnd
, DWORD Unknown1
)
385 PWINSTATION_OBJECT pWinStaObj
= NULL
;
387 UserEnterExclusive();
391 pWindow
= UserGetWindowObject(hWnd
);
394 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
399 pWinStaObj
= IntGetWinStaForCbAccess();
403 if (pWinStaObj
->ptiClipLock
)
405 /* Clipboard is already open */
406 if (pWinStaObj
->spwndClipOpen
!= pWindow
)
408 EngSetLastError(ERROR_ACCESS_DENIED
);
414 pWinStaObj
->spwndClipOpen
= pWindow
;
415 pWinStaObj
->ptiClipLock
= PsGetCurrentThreadWin32Thread();
420 ObDereferenceObject(pWinStaObj
);
428 NtUserCloseClipboard(VOID
)
431 PWINSTATION_OBJECT pWinStaObj
= NULL
;
433 UserEnterExclusive();
435 pWinStaObj
= IntGetWinStaForCbAccess();
439 if (!IntIsClipboardOpenByMe(pWinStaObj
))
441 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
445 /* Clipboard is no longer open */
446 pWinStaObj
->spwndClipOpen
= NULL
;
447 pWinStaObj
->ptiClipLock
= NULL
;
450 if (pWinStaObj
->fClipboardChanged
)
452 /* Add synthesized formats - they are rendered later */
453 IntAddSynthesizedFormats(pWinStaObj
);
455 /* Notify viewer windows in chain */
456 if (pWinStaObj
->spwndClipViewer
)
458 TRACE("Clipboard: sending WM_DRAWCLIPBOARD to %p\n", pWinStaObj
->spwndClipViewer
->head
.h
);
459 co_IntSendMessage(pWinStaObj
->spwndClipViewer
->head
.h
, WM_DRAWCLIPBOARD
, 0, 0);
462 pWinStaObj
->fClipboardChanged
= FALSE
;
467 ObDereferenceObject(pWinStaObj
);
475 NtUserGetOpenClipboardWindow(VOID
)
478 PWINSTATION_OBJECT pWinStaObj
;
482 pWinStaObj
= IntGetWinStaForCbAccess();
486 if (pWinStaObj
->spwndClipOpen
)
487 hWnd
= pWinStaObj
->spwndClipOpen
->head
.h
;
489 ObDereferenceObject(pWinStaObj
);
498 NtUserChangeClipboardChain(HWND hWndRemove
, HWND hWndNewNext
)
502 PWINSTATION_OBJECT pWinStaObj
;
504 TRACE("NtUserChangeClipboardChain(%p, %p)\n", hWndRemove
, hWndNewNext
);
506 UserEnterExclusive();
508 pWinStaObj
= IntGetWinStaForCbAccess();
512 pWindowRemove
= UserGetWindowObject(hWndRemove
);
514 if (pWindowRemove
&& pWinStaObj
->spwndClipViewer
)
516 if(pWindowRemove
== pWinStaObj
->spwndClipViewer
)
517 pWinStaObj
->spwndClipViewer
= UserGetWindowObject(hWndNewNext
);
519 if(pWinStaObj
->spwndClipViewer
)
520 bRet
= (BOOL
)co_IntSendMessage(pWinStaObj
->spwndClipViewer
->head
.h
, WM_CHANGECBCHAIN
, (WPARAM
)hWndRemove
, (LPARAM
)hWndNewNext
);
523 ObDereferenceObject(pWinStaObj
);
532 NtUserCountClipboardFormats(VOID
)
535 PWINSTATION_OBJECT pWinStaObj
= NULL
;
539 pWinStaObj
= IntGetWinStaForCbAccess();
543 cFormats
= pWinStaObj
->cNumClipFormats
;
545 ObDereferenceObject(pWinStaObj
);
554 NtUserEmptyClipboard(VOID
)
557 PWINSTATION_OBJECT pWinStaObj
;
559 TRACE("NtUserEmptyClipboard()\n");
561 UserEnterExclusive();
563 pWinStaObj
= IntGetWinStaForCbAccess();
567 if (IntIsClipboardOpenByMe(pWinStaObj
))
569 UserEmptyClipboardData(pWinStaObj
);
571 if (pWinStaObj
->spwndClipOwner
)
573 TRACE("Clipboard: WM_DESTROYCLIPBOARD to %p", pWinStaObj
->spwndClipOwner
->head
.h
);
574 co_IntSendMessageNoWait(pWinStaObj
->spwndClipOwner
->head
.h
, WM_DESTROYCLIPBOARD
, 0, 0);
577 pWinStaObj
->spwndClipOwner
= pWinStaObj
->spwndClipOpen
;
579 pWinStaObj
->iClipSequenceNumber
++;
585 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
586 ERR("Access denied!\n");
589 ObDereferenceObject(pWinStaObj
);
598 NtUserGetClipboardFormatName(UINT fmt
, LPWSTR lpszFormatName
, INT cchMaxCount
)
604 /* if the format is built-in we fail */
607 /* registetrated formats are >= 0xc000 */
611 if (cchMaxCount
< 1 || !lpszFormatName
)
613 EngSetLastError(ERROR_INVALID_PARAMETER
);
619 ProbeForWrite(lpszFormatName
, cchMaxCount
* sizeof(WCHAR
), 1);
621 iRet
= IntGetAtomName((RTL_ATOM
)fmt
,
623 cchMaxCount
* sizeof(WCHAR
));
624 iRet
/= sizeof(WCHAR
);
626 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
628 SetLastNtError(_SEH2_GetExceptionCode());
639 NtUserGetClipboardOwner(VOID
)
642 PWINSTATION_OBJECT pWinStaObj
;
646 pWinStaObj
= IntGetWinStaForCbAccess();
650 if (pWinStaObj
->spwndClipOwner
)
651 hWnd
= pWinStaObj
->spwndClipOwner
->head
.h
;
653 ObDereferenceObject(pWinStaObj
);
662 NtUserGetClipboardViewer(VOID
)
665 PWINSTATION_OBJECT pWinStaObj
;
669 pWinStaObj
= IntGetWinStaForCbAccess();
673 if (pWinStaObj
->spwndClipViewer
)
674 hWnd
= pWinStaObj
->spwndClipViewer
->head
.h
;
676 ObDereferenceObject(pWinStaObj
);
685 NtUserGetPriorityClipboardFormat(UINT
*paFormatPriorityList
, INT cFormats
)
688 PWINSTATION_OBJECT pWinStaObj
;
692 pWinStaObj
= IntGetWinStaForCbAccess();
696 if (pWinStaObj
->pClipBase
== NULL
)
704 ProbeForRead(paFormatPriorityList
, cFormats
* sizeof(UINT
), sizeof(UINT
));
708 for (i
= 0; i
< cFormats
; ++i
)
710 if (IntIsFormatAvailable(pWinStaObj
, paFormatPriorityList
[i
]))
712 iRet
= paFormatPriorityList
[i
];
717 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
719 SetLastNtError(_SEH2_GetExceptionCode());
724 ObDereferenceObject(pWinStaObj
);
734 NtUserIsClipboardFormatAvailable(UINT fmt
)
737 PWINSTATION_OBJECT pWinStaObj
;
739 TRACE("NtUserIsClipboardFormatAvailable(%x)\n", fmt
);
743 pWinStaObj
= IntGetWinStaForCbAccess();
747 if (IntIsFormatAvailable(pWinStaObj
, fmt
))
750 ObDereferenceObject(pWinStaObj
);
759 NtUserGetClipboardData(UINT fmt
, PGETCLIPBDATA pgcd
)
761 NTSTATUS Status
= STATUS_SUCCESS
;
764 PWINSTATION_OBJECT pWinStaObj
= NULL
;
766 TRACE("NtUserGetClipboardData(%x, %p)\n", fmt
, pgcd
);
770 pWinStaObj
= IntGetWinStaForCbAccess();
774 if (!IntIsClipboardOpenByMe(pWinStaObj
))
776 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
780 pElement
= IntIsFormatAvailable(pWinStaObj
, fmt
);
781 if (pElement
&& IS_DATA_DELAYED(pElement
) && pWinStaObj
->spwndClipOwner
)
783 /* send WM_RENDERFORMAT message */
784 pWinStaObj
->fInDelayedRendering
= TRUE
;
785 co_IntSendMessage(pWinStaObj
->spwndClipOwner
->head
.h
, WM_RENDERFORMAT
, (WPARAM
)fmt
, 0);
786 pWinStaObj
->fInDelayedRendering
= FALSE
;
788 /* data should be in clipboard now */
789 pElement
= IntIsFormatAvailable(pWinStaObj
, fmt
);
792 if (!pElement
|| IS_DATA_DELAYED(pElement
))
796 if (IS_DATA_SYNTHESIZED(pElement
))
798 /* Note: data is synthesized in usermode */
799 /* TODO: Add more formats */
805 pElement
= IntIsFormatAvailable(pWinStaObj
, CF_UNICODETEXT
);
806 if (IS_DATA_SYNTHESIZED(pElement
))
807 pElement
= IntIsFormatAvailable(pWinStaObj
, CF_TEXT
);
808 if (IS_DATA_SYNTHESIZED(pElement
))
809 pElement
= IntIsFormatAvailable(pWinStaObj
, CF_OEMTEXT
);
812 IntSynthesizeBitmap(pWinStaObj
, pElement
);
821 ProbeForWrite(pgcd
, sizeof(*pgcd
), 1);
822 pgcd
->uFmtRet
= pElement
->fmt
;
823 pgcd
->fGlobalHandle
= pElement
->fGlobalHandle
;
825 /* Text and bitmap needs more data */
830 pLocaleEl
= IntIsFormatAvailable(pWinStaObj
, CF_LOCALE
);
831 if (pLocaleEl
&& !IS_DATA_DELAYED(pLocaleEl
))
832 pgcd
->hLocale
= pLocaleEl
->hData
;
834 else if (fmt
== CF_BITMAP
)
838 pPaletteEl
= IntIsFormatAvailable(pWinStaObj
, CF_PALETTE
);
839 if (pPaletteEl
&& !IS_DATA_DELAYED(pPaletteEl
))
840 pgcd
->hPalette
= pPaletteEl
->hData
;
843 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
845 Status
= _SEH2_GetExceptionCode();
849 if (!NT_SUCCESS(Status
))
851 SetLastNtError(Status
);
855 hRet
= pElement
->hData
;
859 ObDereferenceObject(pWinStaObj
);
863 TRACE("Ret: %p\n", hRet
);
869 NtUserSetClipboardData(UINT fmt
, HANDLE hData
, PSETCLIPBDATA scd
)
872 NTSTATUS Status
= STATUS_SUCCESS
;
873 PWINSTATION_OBJECT pWinStaObj
= NULL
;
874 BOOLEAN fGlobalHandle
= FALSE
;
876 TRACE("NtUserSetClipboardData(%x %p %p)\n", fmt
, hData
, scd
);
878 UserEnterExclusive();
880 pWinStaObj
= IntGetWinStaForCbAccess();
884 /* If it's delayed rendering we don't have to open clipboard */
885 if ((pWinStaObj
->fInDelayedRendering
&&
886 pWinStaObj
->spwndClipOwner
->head
.pti
!= PsGetCurrentThreadWin32Thread()) ||
887 !IntIsClipboardOpenByMe(pWinStaObj
))
889 ERR("Access denied!\n");
890 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
896 ProbeForRead(scd
, sizeof(*scd
), 1);
897 fGlobalHandle
= scd
->fGlobalHandle
;
898 if (scd
->fIncSerialNumber
)
899 pWinStaObj
->iClipSerialNumber
++;
901 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
903 Status
= _SEH2_GetExceptionCode();
907 if (!NT_SUCCESS(Status
))
909 SetLastNtError(Status
);
913 /* Is it a delayed render? */
916 /* Is it a bitmap? */
917 if (fmt
== CF_BITMAP
)
919 /* Make bitmap public */
920 GreSetObjectOwner(hData
, GDI_OBJ_HMGR_PUBLIC
);
923 /* Save data in the clipboard */
924 IntAddFormatedData(pWinStaObj
, fmt
, hData
, fGlobalHandle
, FALSE
);
925 TRACE("hData stored\n");
927 pWinStaObj
->iClipSequenceNumber
++;
928 pWinStaObj
->fClipboardChanged
= TRUE
;
930 /* Note: synthesized formats are added in NtUserCloseClipboard */
934 /* This is a delayed render */
935 IntAddFormatedData(pWinStaObj
, fmt
, DATA_DELAYED
, FALSE
, FALSE
);
936 TRACE("SetClipboardData delayed format: %u\n", fmt
);
939 /* Return hData on success */
943 TRACE("NtUserSetClipboardData returns: %p\n", hRet
);
946 ObDereferenceObject(pWinStaObj
);
954 NtUserSetClipboardViewer(HWND hWndNewViewer
)
956 HWND hWndNext
= NULL
;
957 PWINSTATION_OBJECT pWinStaObj
= NULL
;
960 UserEnterExclusive();
962 pWinStaObj
= IntGetWinStaForCbAccess();
966 pWindow
= UserGetWindowObject(hWndNewViewer
);
969 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
973 /* Return previous viewer. New viever window should
974 send messages to rest of the chain */
975 if (pWinStaObj
->spwndClipViewer
)
976 hWndNext
= pWinStaObj
->spwndClipViewer
->head
.h
;
978 /* Set new viewer window */
979 pWinStaObj
->spwndClipViewer
= pWindow
;
983 ObDereferenceObject(pWinStaObj
);
990 // Sequence number is incremented whenever the contents of the clipboard change
991 // or the clipboard is emptied. If clipboard rendering is delayed,
992 // the sequence number is not incremented until the changes are rendered.
995 NtUserGetClipboardSequenceNumber(VOID
)
998 PWINSTATION_OBJECT pWinStaObj
;
1002 pWinStaObj
= IntGetWinStaForCbAccess();
1006 /* Get windowstation sequence number */
1007 dwRet
= (DWORD
)pWinStaObj
->iClipSequenceNumber
;
1009 ObDereferenceObject(pWinStaObj
);
1018 NtUserConvertMemHandle(
1023 PCLIPBOARDDATA pMemObj
;
1025 UserEnterExclusive();
1027 /* Create Clipboard data object */
1028 pMemObj
= UserCreateObject(gHandleTable
, NULL
, &hMem
, otClipBoardData
, sizeof(CLIPBOARDDATA
) + cbData
);
1032 pMemObj
->cbData
= cbData
;
1037 ProbeForRead(pData
, cbData
, 1);
1038 memcpy(pMemObj
->Data
, pData
, cbData
);
1040 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1046 /* If we failed to copy data, remove handle */
1049 UserDeleteObject(hMem
, otClipBoardData
);
1060 NtUserCreateLocalMemHandle(
1066 PCLIPBOARDDATA pMemObj
;
1067 NTSTATUS Status
= STATUS_SUCCESS
;
1071 /* Get Clipboard data object */
1072 pMemObj
= (PCLIPBOARDDATA
)UserGetObject(gHandleTable
, hMem
, otClipBoardData
);
1075 Status
= STATUS_INVALID_HANDLE
;
1080 if (cbData
> pMemObj
->cbData
)
1081 cbData
= pMemObj
->cbData
;
1083 /* Copy data to usermode */
1088 ProbeForWrite(pcbData
, sizeof(*pcbData
), 1);
1089 *pcbData
= pMemObj
->cbData
;
1092 ProbeForWrite(pData
, cbData
, 1);
1093 memcpy(pData
, pMemObj
->Data
, cbData
);
1095 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1097 Status
= _SEH2_GetExceptionCode();