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
, KernelMode
, 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
);
349 pWinSta
->pClipBase
= NULL
;
350 pWinSta
->cNumClipFormats
= 0;
353 /* UserClipboardFreeWindow is called from co_UserFreeWindow in window.c */
355 UserClipboardFreeWindow(PWND pWindow
)
357 PWINSTATION_OBJECT pWinStaObj
;
359 pWinStaObj
= IntGetWinStaForCbAccess();
363 /* Check if clipboard is not locked by this window, if yes, unlock it */
364 if (pWindow
== pWinStaObj
->spwndClipOpen
)
366 /* The window that opens the clipboard was destroyed */
367 pWinStaObj
->spwndClipOpen
= NULL
;
368 pWinStaObj
->ptiClipLock
= NULL
;
370 if (pWindow
== pWinStaObj
->spwndClipOwner
)
372 /* The owner window was destroyed */
373 pWinStaObj
->spwndClipOwner
= NULL
;
375 /* Remove window from window chain */
376 if (pWindow
== pWinStaObj
->spwndClipViewer
)
377 pWinStaObj
->spwndClipViewer
= NULL
;
379 ObDereferenceObject(pWinStaObj
);
383 UserEnumClipboardFormats(UINT fmt
)
387 PWINSTATION_OBJECT pWinStaObj
= NULL
;
389 pWinStaObj
= IntGetWinStaForCbAccess();
393 /* Check if clipboard has been opened */
394 if (!IntIsClipboardOpenByMe(pWinStaObj
))
396 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
402 /* Return first format */
403 if (pWinStaObj
->pClipBase
)
404 Ret
= pWinStaObj
->pClipBase
[0].fmt
;
408 /* Return next format */
409 pElement
= IntIsFormatAvailable(pWinStaObj
, fmt
);
411 if (pElement
< &pWinStaObj
->pClipBase
[pWinStaObj
->cNumClipFormats
])
417 ObDereferenceObject(pWinStaObj
);
423 UserOpenClipboard(HWND hWnd
)
427 PWINSTATION_OBJECT pWinStaObj
= NULL
;
431 pWindow
= UserGetWindowObject(hWnd
);
436 pWinStaObj
= IntGetWinStaForCbAccess();
440 if (pWinStaObj
->ptiClipLock
)
442 /* Clipboard is already open */
443 if (pWinStaObj
->spwndClipOpen
!= pWindow
)
445 EngSetLastError(ERROR_ACCESS_DENIED
);
446 ERR("Access denied!\n");
452 pWinStaObj
->spwndClipOpen
= pWindow
;
453 pWinStaObj
->ptiClipLock
= PsGetCurrentThreadWin32Thread();
458 ObDereferenceObject(pWinStaObj
);
464 NtUserOpenClipboard(HWND hWnd
, DWORD Unknown1
)
468 UserEnterExclusive();
469 bRet
= UserOpenClipboard(hWnd
);
476 UserCloseClipboard(VOID
)
479 PWINSTATION_OBJECT pWinStaObj
= NULL
;
481 pWinStaObj
= IntGetWinStaForCbAccess();
485 if (!IntIsClipboardOpenByMe(pWinStaObj
))
487 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
491 /* Clipboard is no longer open */
492 pWinStaObj
->spwndClipOpen
= NULL
;
493 pWinStaObj
->ptiClipLock
= NULL
;
496 if (pWinStaObj
->fClipboardChanged
)
498 /* Add synthesized formats - they are rendered later */
499 IntAddSynthesizedFormats(pWinStaObj
);
501 /* Notify viewer windows in chain */
502 if (pWinStaObj
->spwndClipViewer
)
504 TRACE("Clipboard: sending WM_DRAWCLIPBOARD to %p\n", pWinStaObj
->spwndClipViewer
->head
.h
);
505 co_IntSendMessage(pWinStaObj
->spwndClipViewer
->head
.h
, WM_DRAWCLIPBOARD
, 0, 0);
508 pWinStaObj
->fClipboardChanged
= FALSE
;
513 ObDereferenceObject(pWinStaObj
);
519 NtUserCloseClipboard(VOID
)
523 UserEnterExclusive();
524 bRet
= UserCloseClipboard();
531 NtUserGetOpenClipboardWindow(VOID
)
534 PWINSTATION_OBJECT pWinStaObj
;
538 pWinStaObj
= IntGetWinStaForCbAccess();
542 if (pWinStaObj
->spwndClipOpen
)
543 hWnd
= pWinStaObj
->spwndClipOpen
->head
.h
;
545 ObDereferenceObject(pWinStaObj
);
554 NtUserChangeClipboardChain(HWND hWndRemove
, HWND hWndNewNext
)
558 PWINSTATION_OBJECT pWinStaObj
;
560 TRACE("NtUserChangeClipboardChain(%p, %p)\n", hWndRemove
, hWndNewNext
);
562 UserEnterExclusive();
564 pWinStaObj
= IntGetWinStaForCbAccess();
568 pWindowRemove
= UserGetWindowObject(hWndRemove
);
570 if (pWindowRemove
&& pWinStaObj
->spwndClipViewer
)
572 if(pWindowRemove
== pWinStaObj
->spwndClipViewer
)
573 pWinStaObj
->spwndClipViewer
= UserGetWindowObject(hWndNewNext
);
575 if(pWinStaObj
->spwndClipViewer
)
576 bRet
= (BOOL
)co_IntSendMessage(pWinStaObj
->spwndClipViewer
->head
.h
, WM_CHANGECBCHAIN
, (WPARAM
)hWndRemove
, (LPARAM
)hWndNewNext
);
579 ObDereferenceObject(pWinStaObj
);
588 NtUserCountClipboardFormats(VOID
)
591 PWINSTATION_OBJECT pWinStaObj
= NULL
;
595 pWinStaObj
= IntGetWinStaForCbAccess();
599 cFormats
= pWinStaObj
->cNumClipFormats
;
601 ObDereferenceObject(pWinStaObj
);
610 UserEmptyClipboard(VOID
)
613 PWINSTATION_OBJECT pWinStaObj
;
615 pWinStaObj
= IntGetWinStaForCbAccess();
619 if (IntIsClipboardOpenByMe(pWinStaObj
))
621 UserEmptyClipboardData(pWinStaObj
);
623 if (pWinStaObj
->spwndClipOwner
)
625 TRACE("Clipboard: WM_DESTROYCLIPBOARD to %p\n", pWinStaObj
->spwndClipOwner
->head
.h
);
626 co_IntSendMessageNoWait(pWinStaObj
->spwndClipOwner
->head
.h
, WM_DESTROYCLIPBOARD
, 0, 0);
629 pWinStaObj
->spwndClipOwner
= pWinStaObj
->spwndClipOpen
;
631 pWinStaObj
->iClipSequenceNumber
++;
637 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
638 ERR("Access denied!\n");
641 ObDereferenceObject(pWinStaObj
);
647 NtUserEmptyClipboard(VOID
)
651 TRACE("NtUserEmptyClipboard()\n");
653 UserEnterExclusive();
654 bRet
= UserEmptyClipboard();
661 NtUserGetClipboardFormatName(UINT fmt
, LPWSTR lpszFormatName
, INT cchMaxCount
)
667 /* If the format is built-in we fail */
670 /* Registetrated formats are >= 0xc000 */
674 if (cchMaxCount
< 1 || !lpszFormatName
)
676 EngSetLastError(ERROR_INVALID_PARAMETER
);
682 ProbeForWrite(lpszFormatName
, cchMaxCount
* sizeof(WCHAR
), 1);
684 iRet
= IntGetAtomName((RTL_ATOM
)fmt
,
686 cchMaxCount
* sizeof(WCHAR
));
687 iRet
/= sizeof(WCHAR
);
689 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
691 SetLastNtError(_SEH2_GetExceptionCode());
702 NtUserGetClipboardOwner(VOID
)
705 PWINSTATION_OBJECT pWinStaObj
;
709 pWinStaObj
= IntGetWinStaForCbAccess();
713 if (pWinStaObj
->spwndClipOwner
)
714 hWnd
= pWinStaObj
->spwndClipOwner
->head
.h
;
716 ObDereferenceObject(pWinStaObj
);
725 NtUserGetClipboardViewer(VOID
)
728 PWINSTATION_OBJECT pWinStaObj
;
732 pWinStaObj
= IntGetWinStaForCbAccess();
736 if (pWinStaObj
->spwndClipViewer
)
737 hWnd
= pWinStaObj
->spwndClipViewer
->head
.h
;
739 ObDereferenceObject(pWinStaObj
);
748 NtUserGetPriorityClipboardFormat(UINT
*paFormatPriorityList
, INT cFormats
)
751 PWINSTATION_OBJECT pWinStaObj
;
755 pWinStaObj
= IntGetWinStaForCbAccess();
759 if (pWinStaObj
->pClipBase
== NULL
)
767 ProbeForRead(paFormatPriorityList
, cFormats
* sizeof(UINT
), sizeof(UINT
));
771 for (i
= 0; i
< cFormats
; ++i
)
773 if (IntIsFormatAvailable(pWinStaObj
, paFormatPriorityList
[i
]))
775 iRet
= paFormatPriorityList
[i
];
780 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
782 SetLastNtError(_SEH2_GetExceptionCode());
787 ObDereferenceObject(pWinStaObj
);
797 NtUserIsClipboardFormatAvailable(UINT fmt
)
800 PWINSTATION_OBJECT pWinStaObj
;
802 TRACE("NtUserIsClipboardFormatAvailable(%x)\n", fmt
);
806 pWinStaObj
= IntGetWinStaForCbAccess();
810 if (IntIsFormatAvailable(pWinStaObj
, fmt
))
813 ObDereferenceObject(pWinStaObj
);
822 NtUserGetClipboardData(UINT fmt
, PGETCLIPBDATA pgcd
)
826 PWINSTATION_OBJECT pWinStaObj
= NULL
;
828 TRACE("NtUserGetClipboardData(%x, %p)\n", fmt
, pgcd
);
832 pWinStaObj
= IntGetWinStaForCbAccess();
836 if (!IntIsClipboardOpenByMe(pWinStaObj
))
838 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
842 pElement
= IntIsFormatAvailable(pWinStaObj
, fmt
);
843 if (pElement
&& IS_DATA_DELAYED(pElement
) && pWinStaObj
->spwndClipOwner
)
845 /* Send WM_RENDERFORMAT message */
846 pWinStaObj
->fInDelayedRendering
= TRUE
;
847 co_IntSendMessage(pWinStaObj
->spwndClipOwner
->head
.h
, WM_RENDERFORMAT
, (WPARAM
)fmt
, 0);
848 pWinStaObj
->fInDelayedRendering
= FALSE
;
850 /* Data should be in clipboard now */
851 pElement
= IntIsFormatAvailable(pWinStaObj
, fmt
);
854 if (!pElement
|| IS_DATA_DELAYED(pElement
))
858 if (IS_DATA_SYNTHESIZED(pElement
))
860 /* Note: Data is synthesized in usermode */
861 /* TODO: Add more formats */
867 pElement
= IntIsFormatAvailable(pWinStaObj
, CF_UNICODETEXT
);
868 if (IS_DATA_SYNTHESIZED(pElement
))
869 pElement
= IntIsFormatAvailable(pWinStaObj
, CF_TEXT
);
870 if (IS_DATA_SYNTHESIZED(pElement
))
871 pElement
= IntIsFormatAvailable(pWinStaObj
, CF_OEMTEXT
);
874 IntSynthesizeBitmap(pWinStaObj
, pElement
);
883 ProbeForWrite(pgcd
, sizeof(*pgcd
), 1);
884 pgcd
->uFmtRet
= pElement
->fmt
;
885 pgcd
->fGlobalHandle
= pElement
->fGlobalHandle
;
887 /* Text and bitmap needs more data */
892 pLocaleEl
= IntIsFormatAvailable(pWinStaObj
, CF_LOCALE
);
893 if (pLocaleEl
&& !IS_DATA_DELAYED(pLocaleEl
))
894 pgcd
->hLocale
= pLocaleEl
->hData
;
896 else if (fmt
== CF_BITMAP
)
900 pPaletteEl
= IntIsFormatAvailable(pWinStaObj
, CF_PALETTE
);
901 if (pPaletteEl
&& !IS_DATA_DELAYED(pPaletteEl
))
902 pgcd
->hPalette
= pPaletteEl
->hData
;
905 hRet
= pElement
->hData
;
907 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
909 SetLastNtError(_SEH2_GetExceptionCode());
915 ObDereferenceObject(pWinStaObj
);
919 TRACE("NtUserGetClipboardData returns %p\n", hRet
);
925 UserSetClipboardData(UINT fmt
, HANDLE hData
, PSETCLIPBDATA scd
)
928 PWINSTATION_OBJECT pWinStaObj
= NULL
;
930 pWinStaObj
= IntGetWinStaForCbAccess();
934 /* If it's delayed rendering we don't have to open clipboard */
935 if ((pWinStaObj
->fInDelayedRendering
&&
936 pWinStaObj
->spwndClipOwner
->head
.pti
!= PsGetCurrentThreadWin32Thread()) ||
937 !IntIsClipboardOpenByMe(pWinStaObj
))
939 ERR("Access denied!\n");
940 EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN
);
944 if (scd
->fIncSerialNumber
)
945 pWinStaObj
->iClipSerialNumber
++;
947 /* Is it a delayed render? */
950 /* Is it a bitmap? */
951 if (fmt
== CF_BITMAP
)
953 /* Make bitmap public */
954 GreSetObjectOwner(hData
, GDI_OBJ_HMGR_PUBLIC
);
957 /* Save data in the clipboard */
958 IntAddFormatedData(pWinStaObj
, fmt
, hData
, scd
->fGlobalHandle
, FALSE
);
959 TRACE("hData stored\n");
961 pWinStaObj
->iClipSequenceNumber
++;
962 pWinStaObj
->fClipboardChanged
= TRUE
;
964 /* Note: Synthesized formats are added in NtUserCloseClipboard */
968 /* This is a delayed render */
969 IntAddFormatedData(pWinStaObj
, fmt
, DATA_DELAYED
, FALSE
, FALSE
);
970 TRACE("SetClipboardData delayed format: %u\n", fmt
);
973 /* Return hData on success */
977 TRACE("NtUserSetClipboardData returns: %p\n", hRet
);
980 ObDereferenceObject(pWinStaObj
);
986 NtUserSetClipboardData(UINT fmt
, HANDLE hData
, PSETCLIPBDATA pUnsafeScd
)
991 TRACE("NtUserSetClipboardData(%x %p %p)\n", fmt
, hData
, pUnsafeScd
);
995 ProbeForRead(pUnsafeScd
, sizeof(*pUnsafeScd
), 1);
996 RtlCopyMemory(&scd
, pUnsafeScd
, sizeof(scd
));
998 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1000 SetLastNtError(_SEH2_GetExceptionCode());
1001 _SEH2_YIELD(return NULL
;)
1005 UserEnterExclusive();
1007 /* Call internal function */
1008 hRet
= UserSetClipboardData(fmt
, hData
, &scd
);
1016 NtUserSetClipboardViewer(HWND hWndNewViewer
)
1018 HWND hWndNext
= NULL
;
1019 PWINSTATION_OBJECT pWinStaObj
= NULL
;
1022 UserEnterExclusive();
1024 pWinStaObj
= IntGetWinStaForCbAccess();
1028 pWindow
= UserGetWindowObject(hWndNewViewer
);
1031 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1035 /* Return previous viewer. New viever window should
1036 send messages to rest of the chain */
1037 if (pWinStaObj
->spwndClipViewer
)
1038 hWndNext
= pWinStaObj
->spwndClipViewer
->head
.h
;
1040 /* Set new viewer window */
1041 pWinStaObj
->spwndClipViewer
= pWindow
;
1045 ObDereferenceObject(pWinStaObj
);
1052 // Sequence number is incremented whenever the contents of the clipboard change
1053 // or the clipboard is emptied. If clipboard rendering is delayed,
1054 // the sequence number is not incremented until the changes are rendered.
1057 NtUserGetClipboardSequenceNumber(VOID
)
1060 PWINSTATION_OBJECT pWinStaObj
;
1064 pWinStaObj
= IntGetWinStaForCbAccess();
1068 /* Get windowstation sequence number */
1069 dwRet
= (DWORD
)pWinStaObj
->iClipSequenceNumber
;
1071 ObDereferenceObject(pWinStaObj
);
1080 NtUserConvertMemHandle(
1085 PCLIPBOARDDATA pMemObj
;
1087 UserEnterExclusive();
1089 /* Create Clipboard data object */
1090 pMemObj
= UserCreateObject(gHandleTable
, NULL
, NULL
, &hMem
, TYPE_CLIPDATA
, sizeof(CLIPBOARDDATA
) + cbData
);
1094 pMemObj
->cbData
= cbData
;
1099 ProbeForRead(pData
, cbData
, 1);
1100 memcpy(pMemObj
->Data
, pData
, cbData
);
1102 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1108 /* Release the extra reference (UserCreateObject added 2 references) */
1109 UserDereferenceObject(pMemObj
);
1111 /* If we failed to copy data, remove handle */
1114 UserDeleteObject(hMem
, TYPE_CLIPDATA
);
1125 NtUserCreateLocalMemHandle(
1131 PCLIPBOARDDATA pMemObj
;
1132 NTSTATUS Status
= STATUS_SUCCESS
;
1136 /* Get Clipboard data object */
1137 pMemObj
= (PCLIPBOARDDATA
)UserGetObject(gHandleTable
, hMem
, TYPE_CLIPDATA
);
1140 Status
= STATUS_INVALID_HANDLE
;
1145 if (cbData
> pMemObj
->cbData
)
1146 cbData
= pMemObj
->cbData
;
1148 /* Copy data to usermode */
1153 ProbeForWrite(pcbData
, sizeof(*pcbData
), 1);
1154 *pcbData
= pMemObj
->cbData
;
1157 ProbeForWrite(pData
, cbData
, 1);
1158 memcpy(pData
, pMemObj
->Data
, cbData
);
1160 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1162 Status
= _SEH2_GetExceptionCode();