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>
15 #define DATA_DELAYED_RENDER 0
16 #define DATA_SYNTHESIZED_RENDER -1
19 PWINSTATION_OBJECT WinStaObj; \
20 WinStaObj = PsGetCurrentThreadWin32Thread()->Desktop->WindowStation;
22 #define WINSTA_ClipboardThread WinStaObj->Clipboard->ClipboardThread
23 #define WINSTA_ClipboardOwnerThread WinStaObj->Clipboard->ClipboardOwnerThread
24 #define WINSTA_ClipboardWindow WinStaObj->Clipboard->ClipboardWindow
25 #define WINSTA_ClipboardViewerWindow WinStaObj->Clipboard->ClipboardViewerWindow
26 #define WINSTA_ClipboardOwnerWindow WinStaObj->Clipboard->ClipboardOwnerWindow
27 #define WINSTA_sendDrawClipboardMsg WinStaObj->Clipboard->sendDrawClipboardMsg
28 #define WINSTA_recentlySetClipboard WinStaObj->Clipboard->recentlySetClipboard
29 #define WINSTA_delayedRender WinStaObj->Clipboard->delayedRender
30 #define WINSTA_lastEnumClipboardFormats WinStaObj->Clipboard->lastEnumClipboardFormats
31 #define WINSTA_ClipboardSequenceNumber WinStaObj->Clipboard->ClipboardSequenceNumber
32 #define WINSTA_WindowsChain WinStaObj->Clipboard->WindowsChain
33 #define WINSTA_ClipboardData WinStaObj->Clipboard->ClipboardData
34 #define WINSTA_synthesizedData WinStaObj->Clipboard->synthesizedData
35 #define WINSTA_synthesizedDataSize WinStaObj->Clipboard->synthesizedDataSize
37 PW32THREAD ClipboardThread
;
38 PW32THREAD ClipboardOwnerThread
;
39 PWINDOW_OBJECT ClipboardWindow
;
40 PWINDOW_OBJECT ClipboardViewerWindow
;
41 PWINDOW_OBJECT ClipboardOwnerWindow
;
42 BOOL sendDrawClipboardMsg
;
43 BOOL recentlySetClipboard
;
45 UINT lastEnumClipboardFormats
;
46 DWORD ClipboardSequenceNumber
= 0;
48 PCLIPBOARDCHAINELEMENT WindowsChain
= NULL
;
49 PCLIPBOARDELEMENT ClipboardData
= NULL
;
51 PCHAR synthesizedData
;
52 DWORD synthesizedDataSize
;
55 /*==============================================================*/
57 /* return the pointer to the prev window of the finded window,
58 if NULL does not exists in the chain */
59 PCLIPBOARDCHAINELEMENT FASTCALL
60 IntIsWindowInChain(PWINDOW_OBJECT window
)
62 PCLIPBOARDCHAINELEMENT wce
= WindowsChain
;
66 if (wce
->window
== window
)
76 VOID FASTCALL
printChain()
79 PCLIPBOARDCHAINELEMENT wce2
= WindowsChain
;
82 DPRINT1("chain: %p\n", wce2
->window
->hSelf
);
87 /* the new window always have to be the first in the chain */
88 PCLIPBOARDCHAINELEMENT FASTCALL
89 IntAddWindowToChain(PWINDOW_OBJECT window
)
91 PCLIPBOARDCHAINELEMENT wce
= NULL
;
93 if (!IntIsWindowInChain(window
))
97 wce
= ExAllocatePool(PagedPool
, sizeof(CLIPBOARDCHAINELEMENT
));
100 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
104 wce
->window
= window
;
105 wce
->next
= WindowsChain
;
113 /* return the next window to beremoved later */
117 PCLIPBOARDCHAINELEMENT FASTCALL
118 IntRemoveWindowFromChain(PWINDOW_OBJECT window
)
120 PCLIPBOARDCHAINELEMENT wce
= WindowsChain
;
121 PCLIPBOARDCHAINELEMENT
*link
= &WindowsChain
;
123 if (IntIsWindowInChain(window
))
127 if (wce
->window
== window
)
148 /*==============================================================*/
149 /* if format exists, returns a non zero value (pointing to format object) */
150 PCLIPBOARDELEMENT FASTCALL
151 intIsFormatAvailable(format
)
153 PCLIPBOARDELEMENT ret
= NULL
;
154 PCLIPBOARDELEMENT ce
= ClipboardData
;
158 if (ce
->format
== format
)
168 /* counts how many distinct format were are in the clipboard */
170 IntCountClipboardFormats()
173 PCLIPBOARDELEMENT ce
= ClipboardData
;
183 /* adds a new format and data to the clipboard */
184 PCLIPBOARDELEMENT FASTCALL
185 intAddFormatedData(UINT format
, HANDLE hData
, DWORD size
)
187 PCLIPBOARDELEMENT ce
= NULL
;
189 ce
= ExAllocatePool(PagedPool
, sizeof(CLIPBOARDELEMENT
));
192 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
199 ce
->next
= ClipboardData
;
203 IntIncrementSequenceNumber();
209 /* removes a format and its data from the clipboard */
211 intRemoveFormatedData(UINT format
)
214 PCLIPBOARDELEMENT ce
= ClipboardData
;
215 PCLIPBOARDELEMENT
*link
= &ClipboardData
;
217 if (intIsFormatAvailable(format
))
221 if (ce
->format
== format
)
233 ExFreePool(ce
->hData
);
243 IntEmptyClipboardData()
245 PCLIPBOARDELEMENT ce
= ClipboardData
;
246 PCLIPBOARDELEMENT tmp
;
251 ExFreePool(ce
->hData
);
256 ClipboardData
= NULL
;
259 /*==============================================================*/
262 renderBITMAPfromDIB(LPBYTE hDIB
)
267 BITMAPINFOHEADER
*ih
;
269 //hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE);
270 hdc
= UserGetDCEx(ClipboardWindow
, NULL
, DCX_USESTYLE
);
272 ih
= (BITMAPINFOHEADER
*)hDIB
;
274 offset
= sizeof(BITMAPINFOHEADER
) + ((ih
->biBitCount
<= 8) ? (sizeof(RGBQUAD
) * (1 << ih
->biBitCount
)) : 0);
276 hbitmap
= NtGdiCreateDIBitmapInternal(hdc
,
287 //UserReleaseDC(NULL, hdc, FALSE);
288 UserReleaseDC(ClipboardWindow
, hdc
, FALSE
);
294 canSinthesize(UINT format
)
301 case CF_METAFILEPICT
:
308 /* returns the size of the sinthesized data */
310 synthesizeData(UINT format
)
314 synthesizedData
= NULL
;
315 synthesizedDataSize
= 0;
317 if (!canSinthesize(format
))
329 case CF_METAFILEPICT
:
341 freeSynthesizedData()
343 ExFreePool(synthesizedData
);
346 /*==============================================================*/
349 intIsClipboardOpenByMe()
351 /* check if we open the clipboard */
352 if (ClipboardThread
&& ClipboardThread
== PsGetCurrentThreadWin32Thread())
354 /* yes, we got a thread and its the same that opens the clipboard */
358 /* will fail if not thread (closed) or not open by me*/
362 /* IntClipboardFreeWindow it's called when a window was destroyed */
364 IntClipboardFreeWindow(PWINDOW_OBJECT window
)
366 /* called from co_UserFreeWindow in window.c */
367 /* check if clipboard is not locked by this window, if yes, unlock it */
368 if (ClipboardThread
== PsGetCurrentThreadWin32Thread())
370 /* the window that opens the clipboard was destroyed */
371 ClipboardThread
= NULL
;
372 ClipboardWindow
= NULL
;
373 //TODO: free clipboard
375 if (window
== ClipboardOwnerWindow
)
377 /* the owner window was destroyed */
378 ClipboardOwnerWindow
= NULL
;
379 ClipboardOwnerThread
= NULL
;
381 /* remove window from window chain */
382 if (IntIsWindowInChain(window
))
384 PCLIPBOARDCHAINELEMENT w
= IntRemoveWindowFromChain(window
);
393 NtUserOpenClipboard(HWND hWnd
, DWORD Unknown1
)
396 PWINDOW_OBJECT Window
;
399 UserEnterExclusive();
401 sendDrawClipboardMsg
= FALSE
;
402 recentlySetClipboard
= FALSE
;
406 /* clipboard is already open */
407 if (ClipboardThread
== PsGetCurrentThreadWin32Thread())
409 if (ClipboardOwnerWindow
)
411 if (ClipboardOwnerWindow
->hSelf
== hWnd
)
430 Window
= UserGetWindowObject(hWnd
);
434 ClipboardWindow
= Window
;
435 ClipboardThread
= PsGetCurrentThreadWin32Thread();
440 ClipboardWindow
= NULL
;
441 ClipboardThread
= NULL
;
442 ClipboardOwnerWindow
= NULL
;
443 ClipboardOwnerThread
= NULL
;
448 ClipboardWindow
= NULL
;
449 ClipboardThread
= PsGetCurrentThreadWin32Thread();
460 NtUserCloseClipboard(VOID
)
464 UserEnterExclusive();
466 if (intIsClipboardOpenByMe())
468 ClipboardWindow
= NULL
;
469 ClipboardThread
= NULL
;
474 SetLastWin32Error(ERROR_CLIPBOARD_NOT_OPEN
);
477 recentlySetClipboard
= FALSE
;
481 if (sendDrawClipboardMsg
&& WindowsChain
)
483 /* only send message to the first window in the chain, then they'll do the chain */
484 /* commented because it makes a crash in co_MsqSendMessage
485 ASSERT(WindowsChain->window);
486 ASSERT(WindowsChain->window->hSelf);
487 DPRINT1("Clipboard: sending WM_DRAWCLIPBOARD to %p\n", WindowsChain->window->hSelf);
488 co_IntSendMessage(WindowsChain->window->hSelf, WM_DRAWCLIPBOARD, 0, 0);
496 NtUserGetOpenClipboardWindow(VOID
)
504 ret
= ClipboardWindow
->hSelf
;
513 NtUserChangeClipboardChain(HWND hWndRemove
, HWND hWndNewNext
)
516 PCLIPBOARDCHAINELEMENT w
= NULL
;
517 PWINDOW_OBJECT removeWindow
;
518 UserEnterExclusive();
520 removeWindow
= UserGetWindowObject(hWndRemove
);
524 if ((ret
= !!IntIsWindowInChain(removeWindow
)))
526 w
= IntRemoveWindowFromChain(removeWindow
);
534 if (ret
&& WindowsChain
)
536 // only send message to the first window in the chain,
537 // then they do the chain
539 /* WindowsChain->window may be NULL */
540 LPARAM lparam
= WindowsChain
->window
== NULL
? 0 : (LPARAM
)WindowsChain
->window
->hSelf
;
541 DPRINT1("Message: WM_CHANGECBCHAIN to %p", WindowsChain
->window
->hSelf
);
542 co_IntSendMessage(WindowsChain
->window
->hSelf
, WM_CHANGECBCHAIN
, (WPARAM
)hWndRemove
, lparam
);
551 NtUserCountClipboardFormats(VOID
)
557 ret
= IntCountClipboardFormats();
564 NtUserEmptyClipboard(VOID
)
568 UserEnterExclusive();
570 if (intIsClipboardOpenByMe())
574 IntEmptyClipboardData();
577 ClipboardOwnerWindow
= ClipboardWindow
;
578 ClipboardOwnerThread
= ClipboardThread
;
580 IntIncrementSequenceNumber();
586 SetLastWin32Error(ERROR_CLIPBOARD_NOT_OPEN
);
589 if (ret
&& ClipboardOwnerWindow
)
591 DPRINT("Clipboard: WM_DESTROYCLIPBOARD to %p", ClipboardOwnerWindow
->hSelf
);
592 co_IntSendMessage( ClipboardOwnerWindow
->hSelf
, WM_DESTROYCLIPBOARD
, 0, 0);
601 NtUserGetClipboardData(UINT uFormat
, DWORD Unknown1
)
608 if (intIsClipboardOpenByMe())
610 /* when Unknown1 is zero, we returns to user32 the data size */
613 PCLIPBOARDELEMENT data
= intIsFormatAvailable(uFormat
);
617 /* format exists in clipboard */
618 if (data
->size
== DATA_DELAYED_RENDER
)
620 /* tell owner what data needs to be rendered */
621 if (ClipboardOwnerWindow
)
623 ASSERT(ClipboardOwnerWindow
->hSelf
);
624 co_IntSendMessage(ClipboardOwnerWindow
->hSelf
, WM_RENDERFORMAT
, (WPARAM
)uFormat
, 0);
625 data
= intIsFormatAvailable(uFormat
);
627 ret
= (HANDLE
)data
->size
;
632 if (data
->size
== DATA_SYNTHESIZED_RENDER
)
634 data
->size
= synthesizeData(uFormat
);
638 ret
= (HANDLE
)data
->size
;
642 /* there is no data in this format */
643 //ret = (HANDLE)FALSE;
648 PCLIPBOARDELEMENT data
= intIsFormatAvailable(uFormat
);
652 if (data
->size
== DATA_DELAYED_RENDER
)
654 // we rendered it in 1st call of getclipboard data
658 if (data
->size
== DATA_SYNTHESIZED_RENDER
)
660 if (uFormat
== CF_BITMAP
)
662 /* BITMAP & METAFILEs returns a GDI handle */
663 PCLIPBOARDELEMENT data
= intIsFormatAvailable(CF_DIB
);
666 ret
= renderBITMAPfromDIB(data
->hData
);
671 buffer
= (PCHAR
)Unknown1
;
672 memcpy(buffer
, (PCHAR
)synthesizedData
, synthesizedDataSize
);
674 freeSynthesizedData();
676 ret
= (HANDLE
)Unknown1
;
681 buffer
= (PCHAR
)Unknown1
;
682 memcpy(buffer
, (PCHAR
)data
->hData
, data
->size
);
684 ret
= (HANDLE
)Unknown1
;
694 SetLastWin32Error(ERROR_CLIPBOARD_NOT_OPEN
);
703 NtUserGetClipboardFormatName(UINT format
, PUNICODE_STRING FormatName
,
706 UNICODE_STRING sFormatName
;
709 /* if the format is built-in we fail */
712 /* registetrated formats are >= 0xc000 */
716 if((cchMaxCount
< 1) || !FormatName
)
718 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
724 ProbeForWriteUnicodeString(FormatName
);
725 sFormatName
= *(volatile UNICODE_STRING
*)FormatName
;
726 ProbeForWrite(sFormatName
.Buffer
, sFormatName
.MaximumLength
, 1);
728 ret
= IntGetAtomName((RTL_ATOM
)format
, sFormatName
.Buffer
, cchMaxCount
* sizeof(WCHAR
));
732 ret
= ret
/ sizeof(WCHAR
);
733 sFormatName
.Length
= ret
;
742 SetLastNtError(_SEH_GetExceptionCode());
750 NtUserRegisterClipboardFormat(PUNICODE_STRING FormatName
)
753 UNICODE_STRING cFormatName
= {0};
755 if (FormatName
== NULL
)
757 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
761 UserEnterExclusive();
765 cFormatName
= ProbeForReadUnicodeString(FormatName
);
767 if (cFormatName
.Length
> 0)
769 ret
= (UINT
)IntAddAtom(cFormatName
.Buffer
);
770 //RtlFreeUnicodeString(&cFormatName);
774 SetLastWin32Error(ERROR_INVALID_NAME
);
781 SetLastNtError(_SEH_GetExceptionCode());
792 NtUserGetClipboardOwner(VOID
)
798 if (ClipboardOwnerWindow
)
800 ret
= ClipboardOwnerWindow
->hSelf
;
809 NtUserGetClipboardViewer(VOID
)
817 ret
= WindowsChain
->window
->hSelf
;
826 NtUserGetPriorityClipboardFormat(UINT
*paFormatPriorityList
, INT cFormats
)
832 UserEnterExclusive();
836 if (IntCountClipboardFormats() == 0)
842 ProbeForRead(paFormatPriorityList
, cFormats
, sizeof(UINT
));
844 priorityList
= paFormatPriorityList
;
848 for (i
= 0; i
< cFormats
; i
++)
850 if (intIsFormatAvailable(priorityList
[i
]))
852 ret
= priorityList
[i
];
861 SetLastNtError(_SEH_GetExceptionCode());
872 NtUserIsClipboardFormatAvailable(UINT format
)
878 ret
= (intIsFormatAvailable(format
) != NULL
);
888 NtUserSetClipboardData(UINT uFormat
, HANDLE hMem
, DWORD size
)
890 HANDLE hCBData
= NULL
;
891 UNICODE_STRING unicodeString
;
892 OEM_STRING oemString
;
893 ANSI_STRING ansiString
;
895 UserEnterExclusive();
897 /* to place data here the we need to be the owner */
898 if (ClipboardOwnerThread
== PsGetCurrentThreadWin32Thread())
900 PCLIPBOARDELEMENT data
= intIsFormatAvailable(uFormat
);
904 if (data
->size
== DATA_DELAYED_RENDER
)
906 intRemoveFormatedData(uFormat
);
910 // we already have this format on clipboard
919 ProbeForRead(hMem
, size
, 1);
923 SetLastNtError(_SEH_GetExceptionCode());
924 _SEH_YIELD(goto exit_setCB
);
928 if (intIsClipboardOpenByMe())
930 delayedRender
= FALSE
;
933 if (!canSinthesize(uFormat
))
935 hCBData
= ExAllocatePool(PagedPool
, size
);
936 memcpy(hCBData
, hMem
, size
);
937 intAddFormatedData(uFormat
, hCBData
, size
);
938 DPRINT1("Data stored\n");
941 sendDrawClipboardMsg
= TRUE
;
942 recentlySetClipboard
= TRUE
;
943 lastEnumClipboardFormats
= uFormat
;
950 //TODO : sinthesize CF_UNICODETEXT & CF_OEMTEXT
951 // CF_TEXT -> CF_UNICODETEXT
952 RtlAnsiStringToUnicodeString(&unicodeString
, hCBData
, TRUE
);
953 intAddFormatedData(CF_UNICODETEXT
, unicodeString
.Buffer
, unicodeString
.Length
* sizeof(WCHAR
));
954 // CF_TEXT -> CF_OEMTEXT
955 RtlUnicodeStringToOemString(&oemString
, &unicodeString
, TRUE
);
956 intAddFormatedData(CF_OEMTEXT
, oemString
.Buffer
, oemString
.Length
);
957 //HKCU\Control Panel\International\Locale
958 //intAddFormatedData(CF_LOCALE, oemString.Buffer, oemString.Length);
963 //TODO : sinthesize CF_TEXT & CF_OEMTEXT
964 //CF_UNICODETEXT -> CF_TEXT
965 unicodeString
.Buffer
= hCBData
;
966 unicodeString
.Length
= size
;
967 RtlUnicodeStringToAnsiString(&ansiString
, &unicodeString
, TRUE
);
968 intAddFormatedData(CF_TEXT
, ansiString
.Buffer
, ansiString
.Length
);
969 //CF_UNICODETEXT -> CF_OEMTEXT
970 RtlUnicodeStringToOemString(&oemString
, &unicodeString
, TRUE
);
971 intAddFormatedData(CF_OEMTEXT
, oemString
.Buffer
, oemString
.Length
);
976 //TODO : sinthesize CF_TEXT & CF_UNICODETEXT
977 //CF_OEMTEXT -> CF_UNICODETEXT
978 oemString
.Buffer
= hCBData
;
979 oemString
.Length
= size
;
980 RtlOemStringToUnicodeString(&unicodeString
, &oemString
, TRUE
);
981 intAddFormatedData(CF_UNICODETEXT
, unicodeString
.Buffer
, unicodeString
.Length
* sizeof(WCHAR
));
982 //CF_OEMTEXT -> CF_TEXT
983 RtlUnicodeStringToAnsiString(&ansiString
, &unicodeString
, TRUE
);
984 intAddFormatedData(CF_TEXT
, ansiString
.Buffer
, ansiString
.Length
);
989 // we need to render the DIB or DIBV5 format as soon as possible
990 // because pallette information may change
996 BITMAPOBJ
*BitmapObj
;
998 hdc
= UserGetDCEx(NULL
, NULL
, DCX_USESTYLE
);
1001 BitmapObj
= BITMAPOBJ_LockBitmap(hMem
);
1002 BITMAP_GetObject(BitmapObj
, sizeof(BITMAP
), (LPSTR
)&bm
);
1005 BITMAPOBJ_UnlockBitmap(BitmapObj
);
1008 bi
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1009 bi
.bmiHeader
.biWidth
= bm
.bmWidth
;
1010 bi
.bmiHeader
.biHeight
= bm
.bmHeight
;
1011 bi
.bmiHeader
.biPlanes
= 1;
1012 bi
.bmiHeader
.biBitCount
= bm
.bmPlanes
* bm
.bmBitsPixel
;
1013 bi
.bmiHeader
.biCompression
= BI_RGB
;
1014 bi
.bmiHeader
.biSizeImage
= 0;
1015 bi
.bmiHeader
.biXPelsPerMeter
= 0;
1016 bi
.bmiHeader
.biYPelsPerMeter
= 0;
1017 bi
.bmiHeader
.biClrUsed
= 0;
1019 ret
= NtGdiGetDIBitsInternal(hdc
, hMem
, 0, bm
.bmHeight
, NULL
, &bi
, DIB_RGB_COLORS
, 0, 0);
1021 size
= bi
.bmiHeader
.biSizeImage
+ sizeof(BITMAPINFOHEADER
);
1023 hCBData
= ExAllocatePool(PagedPool
, size
);
1024 memcpy(hCBData
, &bi
, sizeof(BITMAPINFOHEADER
));
1026 ret
= NtGdiGetDIBitsInternal(hdc
, hMem
, 0, bm
.bmHeight
, (LPBYTE
)hCBData
+ sizeof(BITMAPINFOHEADER
), &bi
, DIB_RGB_COLORS
, 0, 0);
1028 UserReleaseDC(NULL
, hdc
, FALSE
);
1030 intAddFormatedData(CF_DIB
, hCBData
, size
);
1031 intAddFormatedData(CF_BITMAP
, 0, DATA_SYNTHESIZED_RENDER
);
1032 // intAddFormatedData(CF_DIBV5, hCBData, size);
1038 intAddFormatedData(CF_BITMAP
, 0, DATA_SYNTHESIZED_RENDER
);
1039 // intAddFormatedData(CF_DIBV5, hCBData, size);
1041 // intAddFormatedData(CF_PALETTE, hCBData, size);
1045 // intAddFormatedData(CF_BITMAP, hCBData, size);
1046 // intAddFormatedData(CF_PALETTE, hCBData, size);
1047 // intAddFormatedData(CF_DIB, hCBData, size);
1049 case CF_ENHMETAFILE
:
1050 // intAddFormatedData(CF_METAFILEPICT, hCBData, size);
1052 case CF_METAFILEPICT
:
1053 // intAddFormatedData(CF_ENHMETAFILE, hCBData, size);
1060 // the window provides data in the specified format
1061 delayedRender
= TRUE
;
1062 sendDrawClipboardMsg
= TRUE
;
1063 intAddFormatedData(uFormat
, NULL
, 0);
1064 DPRINT1("SetClipboardData delayed format: %d\n", uFormat
);
1078 NtUserSetClipboardViewer(HWND hWndNewViewer
)
1081 PCLIPBOARDCHAINELEMENT newWC
= NULL
;
1082 PWINDOW_OBJECT window
;
1084 UserEnterExclusive();
1086 window
= UserGetWindowObject(hWndNewViewer
);
1090 if ((newWC
= IntAddWindowToChain(window
)))
1094 // newWC->next may be NULL if we are the first window in the chain
1097 // return the next HWND available window in the chain
1098 ret
= newWC
->next
->window
->hSelf
;
1110 NtUserEnumClipboardFormats(UINT uFormat
)
1116 if (intIsClipboardOpenByMe())
1120 if (recentlySetClipboard
)
1122 ret
= lastEnumClipboardFormats
;
1126 /* return the first available format */
1129 ret
= ClipboardData
->format
;
1135 if (recentlySetClipboard
)
1141 /* querying nextt available format */
1142 PCLIPBOARDELEMENT data
= intIsFormatAvailable(uFormat
);
1148 ret
= data
->next
->format
;
1152 /* reached the end */
1162 SetLastWin32Error(ERROR_CLIPBOARD_NOT_OPEN
);
1170 // This number is incremented whenever the contents of the clipboard change
1171 // or the clipboard is emptied.
1172 // If clipboard rendering is delayed,
1173 // the sequence number is not incremented until the changes are rendered.
1175 IntIncrementSequenceNumber(VOID
)
1180 WINSTA_ClipboardSequenceNumber
++;
1185 NtUserGetClipboardSequenceNumber(VOID
)
1187 //windowstation sequence number
1188 //if no WINSTA_ACCESSCLIPBOARD access to the window station,
1189 //the function returns zero.
1193 PWINSTATION_OBJECT WinStaObj
;
1196 WinSta
= UserGetProcessWindowStation();
1198 Status
= IntValidateWindowStationHandle(WinSta
, UserMode
, WINSTA_ACCESSCLIPBOARD
, &WinStaObj
);
1200 if (!NT_SUCCESS(Status
))
1202 DPRINT1("No WINSTA_ACCESSCLIPBOARD access\n");
1203 SetLastNtError(Status
);
1207 sn
= WinStaObj
->ClipboardSequenceNumber
;
1209 ObDereferenceObject(WinStaObj
);
1212 //sn = ClipboardSequenceNumber;
1218 /**************** VISTA FUNCTIONS******************/
1220 BOOL STDCALL
NtUserAddClipboardFormatListener(
1228 BOOL STDCALL
NtUserRemoveClipboardFormatListener(
1236 BOOL STDCALL
NtUserGetUpdatedClipboardFormats(