📄 clipboard.c
字号:
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Clipboard routines
* FILE: subsys/win32k/ntuser/clipboard.c
* PROGRAMER: Filip Navara <xnavara@volny.cz>
* Pablo Borobia <pborobia@gmail.com>
*/
#include <w32k.h>
#define NDEBUG
#include <debug.h>
#define DATA_DELAYED_RENDER 0
#define DATA_SYNTHESIZED_RENDER -1
#define USE_WINSTA \
PWINSTATION_OBJECT WinStaObj; \
WinStaObj = PsGetCurrentThreadWin32Thread()->Desktop->WindowStation;
#define WINSTA_ClipboardThread WinStaObj->Clipboard->ClipboardThread
#define WINSTA_ClipboardOwnerThread WinStaObj->Clipboard->ClipboardOwnerThread
#define WINSTA_ClipboardWindow WinStaObj->Clipboard->ClipboardWindow
#define WINSTA_ClipboardViewerWindow WinStaObj->Clipboard->ClipboardViewerWindow
#define WINSTA_ClipboardOwnerWindow WinStaObj->Clipboard->ClipboardOwnerWindow
#define WINSTA_sendDrawClipboardMsg WinStaObj->Clipboard->sendDrawClipboardMsg
#define WINSTA_recentlySetClipboard WinStaObj->Clipboard->recentlySetClipboard
#define WINSTA_delayedRender WinStaObj->Clipboard->delayedRender
#define WINSTA_lastEnumClipboardFormats WinStaObj->Clipboard->lastEnumClipboardFormats
#define WINSTA_ClipboardSequenceNumber WinStaObj->Clipboard->ClipboardSequenceNumber
#define WINSTA_WindowsChain WinStaObj->Clipboard->WindowsChain
#define WINSTA_ClipboardData WinStaObj->Clipboard->ClipboardData
#define WINSTA_synthesizedData WinStaObj->Clipboard->synthesizedData
#define WINSTA_synthesizedDataSize WinStaObj->Clipboard->synthesizedDataSize
PW32THREAD ClipboardThread;
PW32THREAD ClipboardOwnerThread;
PWINDOW_OBJECT ClipboardWindow;
PWINDOW_OBJECT ClipboardViewerWindow;
PWINDOW_OBJECT ClipboardOwnerWindow;
BOOL sendDrawClipboardMsg;
BOOL recentlySetClipboard;
BOOL delayedRender;
UINT lastEnumClipboardFormats;
DWORD ClipboardSequenceNumber = 0;
PCLIPBOARDCHAINELEMENT WindowsChain = NULL;
PCLIPBOARDELEMENT ClipboardData = NULL;
PCHAR synthesizedData;
DWORD synthesizedDataSize;
/*==============================================================*/
/* return the pointer to the prev window of the finded window,
if NULL does not exists in the chain */
PCLIPBOARDCHAINELEMENT FASTCALL
IntIsWindowInChain(PWINDOW_OBJECT window)
{
PCLIPBOARDCHAINELEMENT wce = WindowsChain;
while (wce)
{
if (wce->window == window)
{
break;
}
wce = wce->next;
}
return wce;
}
VOID FASTCALL printChain()
{
/*test*/
PCLIPBOARDCHAINELEMENT wce2 = WindowsChain;
while (wce2)
{
DPRINT1("chain: %p\n", wce2->window->hSelf);
wce2 = wce2->next;
}
}
/* the new window always have to be the first in the chain */
PCLIPBOARDCHAINELEMENT FASTCALL
IntAddWindowToChain(PWINDOW_OBJECT window)
{
PCLIPBOARDCHAINELEMENT wce = NULL;
if (!IntIsWindowInChain(window))
{
wce = WindowsChain;
wce = ExAllocatePool(PagedPool, sizeof(CLIPBOARDCHAINELEMENT));
if (wce == NULL)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
goto exit_addChain;
}
wce->window = window;
wce->next = WindowsChain;
WindowsChain = wce;
//printChain();
}
exit_addChain:
/* return the next window to beremoved later */
return wce;
}
PCLIPBOARDCHAINELEMENT FASTCALL
IntRemoveWindowFromChain(PWINDOW_OBJECT window)
{
PCLIPBOARDCHAINELEMENT wce = WindowsChain;
PCLIPBOARDCHAINELEMENT *link = &WindowsChain;
if (IntIsWindowInChain(window))
{
while (wce != NULL)
{
if (wce->window == window)
{
*link = wce->next;
break;
}
link = &wce->next;
wce = wce->next;
}
//printChain();
return wce;
}
else
{
return NULL;
}
}
/*==============================================================*/
/* if format exists, returns a non zero value (pointing to format object) */
PCLIPBOARDELEMENT FASTCALL
intIsFormatAvailable(format)
{
PCLIPBOARDELEMENT ret = NULL;
PCLIPBOARDELEMENT ce = ClipboardData;
while(ce)
{
if (ce->format == format)
{
ret = ce;
break;
}
ce = ce->next;
}
return ret;
}
/* counts how many distinct format were are in the clipboard */
DWORD FASTCALL
IntCountClipboardFormats()
{
DWORD ret = 0;
PCLIPBOARDELEMENT ce = ClipboardData;
while(ce)
{
ret++;
ce = ce->next;
}
return ret;
}
/* adds a new format and data to the clipboard */
PCLIPBOARDELEMENT FASTCALL
intAddFormatedData(UINT format, HANDLE hData, DWORD size)
{
PCLIPBOARDELEMENT ce = NULL;
ce = ExAllocatePool(PagedPool, sizeof(CLIPBOARDELEMENT));
if (ce == NULL)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
}
else
{
ce->format = format;
ce->size = size;
ce->hData = hData;
ce->next = ClipboardData;
ClipboardData = ce;
IntIncrementSequenceNumber();
}
return ce;
}
/* removes a format and its data from the clipboard */
BOOL FASTCALL
intRemoveFormatedData(UINT format)
{
BOOL ret = FALSE;
PCLIPBOARDELEMENT ce = ClipboardData;
PCLIPBOARDELEMENT *link = &ClipboardData;
if (intIsFormatAvailable(format))
{
while (ce != NULL)
{
if (ce->format == format)
{
*link = ce->next;
break;
}
link = &ce->next;
ce = ce->next;
}
if (ce->hData)
{
ExFreePool(ce->hData);
}
ExFreePool(ce);
ret = TRUE;
}
return ret;
}
VOID FASTCALL
IntEmptyClipboardData()
{
PCLIPBOARDELEMENT ce = ClipboardData;
PCLIPBOARDELEMENT tmp;
while(ce)
{
tmp = ce->next;
ExFreePool(ce->hData);
ExFreePool(ce);
ce = tmp;
}
ClipboardData = NULL;
}
/*==============================================================*/
HANDLE FASTCALL
renderBITMAPfromDIB(LPBYTE hDIB)
{
HDC hdc;
HBITMAP hbitmap;
unsigned int offset;
BITMAPINFOHEADER *ih;
//hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE);
hdc = UserGetDCEx(ClipboardWindow, NULL, DCX_USESTYLE);
ih = (BITMAPINFOHEADER *)hDIB;
offset = sizeof(BITMAPINFOHEADER) + ((ih->biBitCount <= 8) ? (sizeof(RGBQUAD) * (1 << ih->biBitCount)) : 0);
hbitmap = NtGdiCreateDIBitmap(hdc, ih, CBM_INIT, (LPBYTE)ih + offset, (LPBITMAPINFO)ih, DIB_RGB_COLORS);
//UserReleaseDC(NULL, hdc, FALSE);
UserReleaseDC(ClipboardWindow, hdc, FALSE);
return hbitmap;
}
BOOL FASTCALL
canSinthesize(UINT format)
{
BOOL ret = FALSE;
switch(format)
{
case CF_BITMAP:
case CF_METAFILEPICT:
ret = TRUE;
}
return ret;
}
/* returns the size of the sinthesized data */
DWORD FASTCALL
synthesizeData(UINT format)
{
DWORD ret = 0;
synthesizedData = NULL;
synthesizedDataSize = 0;
if (!canSinthesize(format))
{
return 0;
}
switch (format)
{
case CF_BITMAP:
{
break;
}
case CF_METAFILEPICT:
{
break;
}
}
ret = 1;
return ret;
}
VOID FASTCALL
freeSynthesizedData()
{
ExFreePool(synthesizedData);
}
/*==============================================================*/
BOOL FASTCALL
intIsClipboardOpenByMe()
{
/* check if we open the clipboard */
if (ClipboardThread && ClipboardThread == PsGetCurrentThreadWin32Thread())
{
/* yes, we got a thread and its the same that opens the clipboard */
return TRUE;
}
/* will fail if not thread (closed) or not open by me*/
return FALSE;
}
/* IntClipboardFreeWindow it's called when a window was destroyed */
VOID FASTCALL
IntClipboardFreeWindow(PWINDOW_OBJECT window)
{
/* called from co_UserFreeWindow in window.c */
/* check if clipboard is not locked by this window, if yes, unlock it */
if (ClipboardThread == PsGetCurrentThreadWin32Thread())
{
/* the window that opens the clipboard was destroyed */
ClipboardThread = NULL;
ClipboardWindow = NULL;
//TODO: free clipboard
}
if (window == ClipboardOwnerWindow)
{
/* the owner window was destroyed */
ClipboardOwnerWindow = NULL;
ClipboardOwnerThread = NULL;
}
/* remove window from window chain */
if (IntIsWindowInChain(window))
{
PCLIPBOARDCHAINELEMENT w = IntRemoveWindowFromChain(window);
if (w)
{
ExFreePool(w);
}
}
}
BOOL STDCALL
NtUserOpenClipboard(HWND hWnd, DWORD Unknown1)
{
PWINDOW_OBJECT Window;
BOOL ret = FALSE;
UserEnterExclusive();
sendDrawClipboardMsg = FALSE;
recentlySetClipboard = FALSE;
if (ClipboardThread)
{
/* clipboard is already open */
if (ClipboardThread == PsGetCurrentThreadWin32Thread())
{
if (ClipboardOwnerWindow)
{
if (ClipboardOwnerWindow->hSelf == hWnd)
{
ret = TRUE;
}
}
else
{
if (hWnd == NULL)
{
ret = TRUE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -