Author: rharabien Date: Thu Sep 8 16:32:54 2011 New Revision: 53644
URL: http://svn.reactos.org/svn/reactos?rev=53644&view=rev Log: [WIN32K] - Rewrite clipboard to match Windows implementation - Clipboard uses window stations instead of global variables - Data is saved in clipboard data user objects - Memory is no longer leaked when winsta is destroyed - Data is synthesized on demand - Make internal functions static - Fix possible memory corruption in IntGetAtomName - More winetests are passed
Modified: trunk/reactos/dll/win32/user32/windows/clipboard.c trunk/reactos/include/reactos/win32k/ntuser.h trunk/reactos/subsystems/win32/win32k/include/clipboard.h trunk/reactos/subsystems/win32/win32k/include/winsta.h trunk/reactos/subsystems/win32/win32k/ntuser/clipboard.c trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c trunk/reactos/subsystems/win32/win32k/ntuser/simplecall.c trunk/reactos/subsystems/win32/win32k/ntuser/useratom.c trunk/reactos/subsystems/win32/win32k/ntuser/window.c trunk/reactos/subsystems/win32/win32k/ntuser/winsta.c
Modified: trunk/reactos/dll/win32/user32/windows/clipboard.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/cl... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/clipboard.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/user32/windows/clipboard.c [iso-8859-1] Thu Sep 8 16:32:54 2011 @@ -46,40 +46,6 @@ /* * @implemented */ -HANDLE -WINAPI -GetClipboardData(UINT uFormat) -{ - HGLOBAL hGlobal = NULL; - PVOID pGlobal = NULL; - DWORD_PTR size = 0; - - /* dealing with bitmap object */ - if (uFormat != CF_BITMAP) - { - size = (DWORD_PTR)NtUserGetClipboardData(uFormat, NULL); - - if (size) - { - hGlobal = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, size); - pGlobal = GlobalLock(hGlobal); - - size = (DWORD_PTR)NtUserGetClipboardData(uFormat, pGlobal); - - GlobalUnlock(hGlobal); - } - } - else - { - hGlobal = NtUserGetClipboardData(CF_BITMAP, NULL); - } - - return hGlobal; -} - -/* - * @implemented - */ INT WINAPI GetClipboardFormatNameA(UINT format, @@ -87,7 +53,6 @@ int cchMaxCount) { LPWSTR lpBuffer; - UNICODE_STRING FormatName; INT Length;
lpBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, cchMaxCount * sizeof(WCHAR)); @@ -97,12 +62,8 @@ return 0; }
- FormatName.Length = 0; - FormatName.MaximumLength = cchMaxCount * sizeof(WCHAR); - FormatName.Buffer = lpBuffer; - /* we need a UNICODE string */ - Length = NtUserGetClipboardFormatName(format, &FormatName, cchMaxCount); + Length = NtUserGetClipboardFormatName(format, lpBuffer, cchMaxCount);
if (Length != 0) { @@ -123,25 +84,16 @@ */ INT WINAPI -GetClipboardFormatNameW(UINT format, +GetClipboardFormatNameW(UINT uFormat, LPWSTR lpszFormatName, INT cchMaxCount) { - UNICODE_STRING FormatName; - ULONG Ret; - - FormatName.Length = 0; - FormatName.MaximumLength = cchMaxCount * sizeof(WCHAR); - FormatName.Buffer = (PWSTR)lpszFormatName; - Ret = NtUserGetClipboardFormatName(format, &FormatName, cchMaxCount); - return Ret; - -} - -/* - * @implemented - */ - + return NtUserGetClipboardFormatName(uFormat, lpszFormatName, cchMaxCount); +} + +/* + * @implemented + */ UINT WINAPI RegisterClipboardFormatA(LPCSTR lpszFormat) @@ -201,26 +153,44 @@ return ret; }
-HGLOBAL -renderLocale(DWORD Locale) -{ - DWORD* pLocale; - HGLOBAL hGlobal; - - hGlobal = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(DWORD)); - - if(!hGlobal) - { - return hGlobal; - } - - pLocale = (DWORD*)GlobalLock(hGlobal); - - *pLocale = Locale; - - GlobalUnlock(hGlobal); - - return hGlobal; +PVOID static WINAPI +IntSynthesizeMultiByte(PVOID pwStr, DWORD cbStr, BOOL bOem) +{ + HANDLE hGlobal; + PVOID pGlobal; + INT cbGlobal; + + cbGlobal = WideCharToMultiByte(bOem ? CP_OEMCP : CP_ACP, + 0, pwStr, cbStr / sizeof(WCHAR), + NULL, 0, NULL, NULL); + hGlobal = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbGlobal); + if (!hGlobal) + return NULL; + + pGlobal = GlobalLock(hGlobal); + WideCharToMultiByte(bOem ? CP_OEMCP : CP_ACP, + 0, pwStr, cbStr / sizeof(WCHAR), + pGlobal, cbGlobal, NULL, NULL); + return pGlobal; +} + +PVOID static WINAPI +IntSynthesizeWideChar(PVOID pwStr, DWORD cbStr, BOOL bOem) +{ + HANDLE hGlobal; + PVOID pGlobal; + INT cbGlobal; + + cbGlobal = MultiByteToWideChar(bOem ? CP_OEMCP : CP_ACP, + 0, pwStr, cbStr, NULL, 0) * sizeof(WCHAR); + hGlobal = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbGlobal); + if (!hGlobal) + return NULL; + + pGlobal = GlobalLock(hGlobal); + MultiByteToWideChar(bOem ? CP_OEMCP : CP_ACP, + 0, pwStr, cbStr, pGlobal, cbGlobal); + return pGlobal; }
/* @@ -228,62 +198,161 @@ */ HANDLE WINAPI +GetClipboardData(UINT uFormat) +{ + HANDLE hData = NULL; + PVOID pData = NULL; + DWORD cbData = 0; + GETCLIPBDATA gcd; + + hData = NtUserGetClipboardData(uFormat, &gcd); + if (gcd.fGlobalHandle) + { + HANDLE hGlobal; + + NtUserCreateLocalMemHandle(hData, NULL, 0, &cbData); + hGlobal = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbData); + pData = GlobalLock(hGlobal); + NtUserCreateLocalMemHandle(hData, pData, cbData, NULL); + hData = hGlobal; + } + + if (gcd.uFmtRet != uFormat) + { + SETCLIPBDATA scd = {FALSE, FALSE}; + HANDLE hNewData = NULL; + PVOID pNewData = NULL; + + /* Synthesize requested format */ + switch (uFormat) + { + case CF_TEXT: + if (gcd.uFmtRet == CF_UNICODETEXT) + pNewData = IntSynthesizeMultiByte(pData, cbData, uFormat == CF_OEMTEXT); + else // CF_OEMTEXT + OemToCharBuffA(pData, pData, cbData); + break; + case CF_OEMTEXT: + if (gcd.uFmtRet == CF_UNICODETEXT) + pNewData = IntSynthesizeMultiByte(pData, cbData, uFormat == CF_OEMTEXT); + else + CharToOemBuffA(pData, pData, cbData); + break; + case CF_UNICODETEXT: + pNewData = IntSynthesizeWideChar(pData, cbData, gcd.uFmtRet == CF_OEMTEXT); + break; + default: + FIXME("Format: %u\n", uFormat); + } + + /* Is it a global handle? */ + if (pNewData) + hNewData = GlobalHandle(pNewData); + + if (hNewData) + { + /* Free old data */ + if (pData) + { + GlobalUnlock(hData); + GlobalFree(hData); + } + hData = hNewData; + pData = pNewData; + } + + /* Save synthesized format in clibboard */ + if (pData) + { + HANDLE hMem; + + scd.fGlobalHandle = TRUE; + hMem = NtUserConvertMemHandle(pData, GlobalSize(hData)); + NtUserSetClipboardData(uFormat, hMem, &scd); + } + else if (hData) + NtUserSetClipboardData(uFormat, hData, &scd); + } + + /* Unlock global handle */ + if (pData) + GlobalUnlock(hData); + + return hData; +} + +/* + * @implemented + */ +HANDLE +WINAPI SetClipboardData(UINT uFormat, HANDLE hMem) { - DWORD size; + DWORD dwSize; + HANDLE hGlobal; LPVOID pMem; - HANDLE ret = NULL; - + HANDLE hRet = NULL; + SETCLIPBDATA scd = {FALSE, FALSE}; + + /* Check if this is delayed render */ if (hMem == NULL) - { - return NtUserSetClipboardData(uFormat, 0, 0); - } - - if (uFormat == CF_BITMAP) - { - /* GlobalLock should return 0 for GDI handles + return NtUserSetClipboardData(uFormat, NULL, &scd); + + if (hMem <= (HANDLE)4) + SetLastError(ERROR_INVALID_PARAMETER); + /* Bitmaps and palette does not use global handles */ + else if (uFormat == CF_BITMAP || uFormat == CF_DSPBITMAP || uFormat == CF_PALETTE) + hRet = NtUserSetClipboardData(uFormat, hMem, &scd); + /* Meta files are probably checked for validity */ + else if (uFormat == CF_DSPMETAFILEPICT || uFormat == CF_METAFILEPICT || + uFormat == CF_DSPENHMETAFILE || uFormat == CF_ENHMETAFILE) + hRet = NULL; // not supported yet + else + { + /* Some formats accept only global handles, other accept global handles or integer values */ pMem = GlobalLock(hMem); - if (pMem) - { - // not a GDI handle - GlobalUnlock(hMem); - return ret; + dwSize = GlobalSize(hMem); + + if (pMem || uFormat == CF_DIB || uFormat == CF_DIBV5 || + uFormat == CF_DSPTEXT || uFormat == CF_LOCALE || + uFormat == CF_OEMTEXT || uFormat == CF_TEXT || + uFormat == CF_UNICODETEXT) + { + if (pMem) + { + /* This is a local memory. Make global memory object */ + hGlobal = NtUserConvertMemHandle(pMem, dwSize); + + /* Unlock memory */ + GlobalUnlock(hMem); + /* FIXME: free hMem when CloseClipboard is called */ + + if (hGlobal) + { + /* Save data */ + scd.fGlobalHandle = TRUE; + hRet = NtUserSetClipboardData(uFormat, hGlobal, &scd); + } + + /* On success NtUserSetClipboardData returns pMem + however caller expects us to return hMem */ + if (hRet == hGlobal) + hRet = hMem; + } + else + SetLastError(ERROR_INVALID_HANDLE); } else { - */ - /* check if this GDI handle is a HBITMAP */ - /* GetObject for HBITMAP not implemented in ReactOS */ - //if (GetObject(hMem, 0, NULL) == sifeof(BITMAP)) - //{ - return NtUserSetClipboardData(CF_BITMAP, hMem, 0); - //} - /*}*/ - } - - size = GlobalSize(hMem); - pMem = GlobalLock(hMem); - - if ((pMem) && (size)) - { - size = GlobalSize(hMem); - ret = NtUserSetClipboardData(uFormat, pMem, size); - - //On success NtUserSetClipboardData returns pMem - //however caller expects us to return hMem - if (ret == pMem) - ret = hMem; - - //should i unlock hMem? - GlobalUnlock(hMem); - } - else - { - ERR("SetClipboardData failed\n"); - } - - return ret; - + /* Save a number */ + hRet = NtUserSetClipboardData(uFormat, hMem, &scd); + } + } + + if (!hRet) + ERR("SetClipboardData(%u, %p) failed\n", uFormat, hMem); + + return hRet; }
/*
Modified: trunk/reactos/include/reactos/win32k/ntuser.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/win32k/ntus... ============================================================================== --- trunk/reactos/include/reactos/win32k/ntuser.h [iso-8859-1] (original) +++ trunk/reactos/include/reactos/win32k/ntuser.h [iso-8859-1] Thu Sep 8 16:32:54 2011 @@ -204,6 +204,13 @@ BOOLEAN Ansi; /* Is it an Ansi hook? */ UNICODE_STRING ModuleName; /* Module name for global hooks */ } HOOK, *PHOOK; + +typedef struct tagCLIPBOARDDATA +{ + HEAD head; + DWORD cbData; + BYTE Data[0]; +} CLIPBOARDDATA, *PCLIPBOARDDATA;
/* THREADINFO Flags */ #define TIF_INCLEANUP 0x00000001 @@ -909,6 +916,23 @@ SHAREDINFO siClient; } USERCONNECT, *PUSERCONNECT;
+typedef struct tagGETCLIPBDATA +{ + UINT uFmtRet; + BOOL fGlobalHandle; + union + { + HANDLE hLocale; + HANDLE hPalette; + }; +} GETCLIPBDATA, *PGETCLIPBDATA; + +typedef struct tagSETCLIPBDATA +{ + BOOL fGlobalHandle; + BOOL fIncSerialNumber; +} SETCLIPBDATA, *PSETCLIPBDATA; + DWORD NTAPI NtUserAssociateInputContext( @@ -1010,8 +1034,8 @@ BOOL NTAPI NtUserHiliteMenuItem( - HWND hwnd, - HMENU hmenu, + HWND hWnd, + HMENU hMenu, UINT uItemHilite, UINT uHilite);
@@ -1464,11 +1488,11 @@ DWORD dwUnknown2, DWORD dwUnknown3);
-DWORD +HANDLE NTAPI NtUserConvertMemHandle( - DWORD Unknown0, - DWORD Unknown1); + PVOID pData, + DWORD cbData);
int NTAPI @@ -1509,13 +1533,13 @@ NtUserCreateInputContext( DWORD dwUnknown1);
-DWORD +NTSTATUS NTAPI NtUserCreateLocalMemHandle( - DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3); + HANDLE hMem, + PVOID pData, + DWORD cbData, + DWORD *pcbData);
HWND NTAPI @@ -1678,7 +1702,7 @@ BOOL bMetaHDC, PVOID pDIXData);
-DWORD +BOOL NTAPI NtUserEmptyClipboard(VOID);
@@ -1828,14 +1852,14 @@ HANDLE NTAPI NtUserGetClipboardData( + UINT fmt, + PGETCLIPBDATA pgcd); + +INT +NTAPI +NtUserGetClipboardFormatName( UINT uFormat, - PVOID pBuffer); - -INT -NTAPI -NtUserGetClipboardFormatName( - UINT format, - PUNICODE_STRING FormatName, + LPWSTR lpszFormatName, INT cchMaxCount);
HWND @@ -2634,9 +2658,9 @@ HANDLE NTAPI NtUserSetClipboardData( - UINT uFormat, + UINT fmt, HANDLE hMem, - DWORD Unknown2); + PSETCLIPBDATA scd);
HWND NTAPI
Modified: trunk/reactos/subsystems/win32/win32k/include/clipboard.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/clipboard.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/clipboard.h [iso-8859-1] Thu Sep 8 16:32:54 2011 @@ -1,40 +1,22 @@ #pragma once
-typedef struct _ClipboardChainElement +#include "window.h" +#include <include/win32.h> + +typedef struct _CLIP { - PWND window; - struct _ClipboardChainElement *next; -} CLIPBOARDCHAINELEMENT, *PCLIPBOARDCHAINELEMENT; + UINT fmt; + HANDLE hData; + BOOL fGlobalHandle; +} CLIP, *PCLIP;
-typedef struct _ClipboardElement -{ - UINT format; - HANDLE hData; - DWORD size; // data may be delayed o synth render - struct _ClipboardElement *next; -} CLIPBOARDELEMENT, *PCLIPBOARDELEMENT; +UINT APIENTRY +UserEnumClipboardFormats(UINT uFormat);
-typedef struct _CLIPBOARDSYSTEM -{ - PTHREADINFO ClipboardThread; - PTHREADINFO ClipboardOwnerThread; - PWND ClipboardWindow; - PWND ClipboardViewerWindow; - PWND ClipboardOwnerWindow; - BOOL sendDrawClipboardMsg; - BOOL recentlySetClipboard; - BOOL delayedRender; - UINT lastEnumClipboardFormats; - DWORD ClipboardSequenceNumber; +VOID FASTCALL +UserClipboardFreeWindow(PWND pWindow);
- PCLIPBOARDCHAINELEMENT WindowsChain; - PCLIPBOARDELEMENT ClipboardData; +struct _WINSTATION_OBJECT;
- PCHAR synthesizedData; - DWORD synthesizedDataSize; - -} CLIPBOARDSYSTEM, *PCLIPBOARDSYSTEM; - -VOID FASTCALL IntClipboardFreeWindow(PWND window); -UINT APIENTRY IntEnumClipboardFormats(UINT format); -VOID FASTCALL IntIncrementSequenceNumber(VOID); +VOID NTAPI +UserEmptyClipboardData(struct _WINSTATION_OBJECT *pWinSta);
Modified: trunk/reactos/subsystems/win32/win32k/include/winsta.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/winsta.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/winsta.h [iso-8859-1] Thu Sep 8 16:32:54 2011 @@ -39,7 +39,7 @@
/* ScreenSaver */ BOOL ScreenSaverRunning; - UINT ScreenSaverTimeOut; + UINT ScreenSaverTimeOut; /* Should this be on each desktop ? */ BOOL ScreenSaverActive;
@@ -51,8 +51,17 @@ ULONG Flags; struct _DESKTOP* ActiveDesktop;
- PCLIPBOARDSYSTEM Clipboard; - DWORD ClipboardSequenceNumber; + PTHREADINFO ptiClipLock; + PTHREADINFO ptiDrawingClipboard; + PWND spwndClipOpen; + PWND spwndClipViewer; + PWND spwndClipOwner; + PCLIP pClipBase; // Not a clip object. + DWORD cNumClipFormats; + INT iClipSerialNumber; + INT iClipSequenceNumber; + INT fClipboardChanged : 1; + INT fInDelayedRendering : 1;
} WINSTATION_OBJECT, *PWINSTATION_OBJECT;
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/clipboard.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/clipboard.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/clipboard.c [iso-8859-1] Thu Sep 8 16:32:54 2011 @@ -5,763 +5,624 @@ * FILE: subsys/win32k/ntuser/clipboard.c * PROGRAMER: Filip Navara xnavara@volny.cz * Pablo Borobia pborobia@gmail.com + * Rafal Harabien rafalh@reactos.org */
#include <win32k.h>
DBG_DEFAULT_CHANNEL(UserClipbrd);
-#define DATA_DELAYED_RENDER 0 -#define DATA_SYNTHESIZED_RENDER -1 - -PTHREADINFO ClipboardThread; -PTHREADINFO ClipboardOwnerThread; -PWND ClipboardWindow; -PWND ClipboardViewerWindow; -PWND 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(PWND window) -{ - PCLIPBOARDCHAINELEMENT wce = WindowsChain; - - while (wce) - { - if (wce->window == window) - { - break; - } - wce = wce->next; - } - - return wce; -} - -VOID FASTCALL printChain(VOID) -{ - /*test*/ - PCLIPBOARDCHAINELEMENT wce2 = WindowsChain; - while (wce2) - { - ERR("chain: %p\n", wce2->window->head.h); - wce2 = wce2->next; - } -} - -/* the new window always have to be the first in the chain */ -PCLIPBOARDCHAINELEMENT FASTCALL -IntAddWindowToChain(PWND window) -{ - PCLIPBOARDCHAINELEMENT wce = NULL; - - if (!IntIsWindowInChain(window)) - { - wce = WindowsChain; - - wce = ExAllocatePoolWithTag(PagedPool, sizeof(CLIPBOARDCHAINELEMENT), USERTAG_CLIPBOARD); - if (wce == NULL) - { - EngSetLastError(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(PWND window) -{ - PCLIPBOARDCHAINELEMENT wce = WindowsChain; - PCLIPBOARDCHAINELEMENT *link = &WindowsChain; - - if (IntIsWindowInChain(window)) - { - while (wce != NULL) - { - if (wce->window == window) +#define DATA_DELAYED (HANDLE)0 +#define DATA_SYNTH_USER (HANDLE)1 +#define DATA_SYNTH_KRNL (HANDLE)2 +#define IS_DATA_DELAYED(ce) ((ce)->hData == DATA_DELAYED) +#define IS_DATA_SYNTHESIZED(ce) ((ce)->hData == DATA_SYNTH_USER || (ce)->hData == DATA_SYNTH_KRNL) + +PWINSTATION_OBJECT static FASTCALL +IntGetWinStaForCbAccess() +{ + HWINSTA hWinSta; + PWINSTATION_OBJECT pWinStaObj; + NTSTATUS Status; + + hWinSta = UserGetProcessWindowStation(); + Status = IntValidateWindowStationHandle(hWinSta, KernelMode, WINSTA_ACCESSCLIPBOARD, &pWinStaObj); + if (!NT_SUCCESS(Status)) + { + ERR("Cannot open winsta\n"); + SetLastNtError(Status); + return NULL; + } + + return pWinStaObj; +} + +/* if format exists, returns a non zero value (pointing to formated object) */ +PCLIP static FASTCALL +IntIsFormatAvailable(PWINSTATION_OBJECT pWinStaObj, UINT fmt) +{ + unsigned i = 0; + + for (i = 0; i < pWinStaObj->cNumClipFormats; ++i) + { + if (pWinStaObj->pClipBase[i].fmt == fmt) + return &pWinStaObj->pClipBase[i]; + } + + return NULL; +} + +VOID static FASTCALL +IntFreeElementData(PCLIP pElement) +{ + if (!IS_DATA_DELAYED(pElement) && + !IS_DATA_SYNTHESIZED(pElement)) + { + if (pElement->fGlobalHandle) + UserDeleteObject(pElement->hData, otClipBoardData); + else if (pElement->fmt == CF_BITMAP || pElement->fmt == CF_PALETTE || + pElement->fmt == CF_DSPBITMAP) + { + GreDeleteObject(pElement->hData); + } + } +} + +/* adds a new format and data to the clipboard */ +PCLIP static NTAPI +IntAddFormatedData(PWINSTATION_OBJECT pWinStaObj, UINT fmt, HANDLE hData, BOOLEAN fGlobalHandle, BOOL bEnd) +{ + PCLIP pElement = NULL; + + /* Use exisiting entry with specified format */ + if (!bEnd) + pElement = IntIsFormatAvailable(pWinStaObj, fmt); + + /* Put new entry at the end if nothing was found */ + if (!pElement) + { + /* Allocate bigger clipboard if needed. We could use lists but Windows uses array */ + if (pWinStaObj->cNumClipFormats % 4 == 0) + { + PCLIP pNewClip; + + /* Allocate new clipboard */ + pNewClip = ExAllocatePoolWithTag(PagedPool, + (pWinStaObj->cNumClipFormats + 4) * sizeof(CLIP), + USERTAG_CLIPBOARD); + if (!pNewClip) { - *link = wce->next; - break; + EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; }
- link = &wce->next; - wce = wce->next; - } - - //printChain(); - - return wce; + /* Copy data */ + memcpy(pNewClip, pWinStaObj->pClipBase, pWinStaObj->cNumClipFormats * sizeof(CLIP)); + + /* Free old clipboard */ + if (pWinStaObj->pClipBase) + ExFreePoolWithTag(pWinStaObj->pClipBase, USERTAG_CLIPBOARD); + + /* Update WinSta */ + pWinStaObj->pClipBase = pNewClip; + } + + /* New element is at the end */ + pElement = &pWinStaObj->pClipBase[pWinStaObj->cNumClipFormats]; + pElement->fmt = fmt; + pWinStaObj->cNumClipFormats++; } else - { - return NULL; - } -} - - -/*==============================================================*/ -/* if format exists, returns a non zero value (pointing to format object) */ -PCLIPBOARDELEMENT FASTCALL -intIsFormatAvailable(UINT 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(VOID) -{ - 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 = ExAllocatePoolWithTag(PagedPool, sizeof(CLIPBOARDELEMENT), USERTAG_CLIPBOARD); - if (ce == NULL) - { - EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); + IntFreeElementData(pElement); + + pElement->hData = hData; + pElement->fGlobalHandle = fGlobalHandle; + + return pElement; +} + +BOOL static FASTCALL +IntIsClipboardOpenByMe(PWINSTATION_OBJECT pWinSta) +{ + /* check if current thread has opened the clipboard */ + if (pWinSta->ptiClipLock && + pWinSta->ptiClipLock == PsGetCurrentThreadWin32Thread()) + { + return TRUE; + } + + return FALSE; +} + +VOID static NTAPI +IntSynthesizeDib(PWINSTATION_OBJECT pWinStaObj, HBITMAP hBm) +{ + HDC hdc; + BITMAP bm; + BITMAPINFO bi; + SURFACE *psurf; + PCLIPBOARDDATA pMemObj; + HANDLE hMem; + + hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE); + if (!hdc) + return; + + psurf = SURFACE_ShareLockSurface(hBm); + if (!psurf) + goto cleanup; + BITMAP_GetObject(psurf, sizeof(BITMAP), (PVOID)&bm); + SURFACE_ShareUnlockSurface(psurf); + + bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth = bm.bmWidth; + bi.bmiHeader.biHeight = bm.bmHeight; + bi.bmiHeader.biPlanes = bm.bmPlanes; + bi.bmiHeader.biBitCount = bm.bmBitsPixel; + bi.bmiHeader.biCompression = BI_RGB; + bi.bmiHeader.biSizeImage = 0; + bi.bmiHeader.biXPelsPerMeter = 0; + bi.bmiHeader.biYPelsPerMeter = 0; + bi.bmiHeader.biClrUsed = 0; + + NtGdiGetDIBitsInternal(hdc, hBm, 0, bm.bmHeight, NULL, &bi, DIB_RGB_COLORS, 0, 0); + + pMemObj = (PCLIPBOARDDATA)UserCreateObject(gHandleTable, NULL, &hMem, otClipBoardData, + sizeof(BITMAPINFOHEADER) + bi.bmiHeader.biSizeImage); + if(pMemObj) + { + pMemObj->cbData = sizeof(BITMAPINFOHEADER) + bi.bmiHeader.biSizeImage; + memcpy(pMemObj->Data, &bi, sizeof(BITMAPINFOHEADER)); + NtGdiGetDIBitsInternal(hdc, pMemObj->Data, 0, bm.bmHeight, (LPBYTE)pMemObj->Data + sizeof(BITMAPINFOHEADER), &bi, DIB_RGB_COLORS, 0, 0); + IntAddFormatedData(pWinStaObj, CF_DIB, hMem, TRUE, TRUE); + } + +cleanup: + UserReleaseDC(NULL, hdc, FALSE); +} + +VOID static WINAPI +IntSynthesizeBitmap(PWINSTATION_OBJECT pWinStaObj, PCLIP pBmEl) +{ + HDC hdc = NULL; + PBITMAPINFO pBmi, pConvertedBmi = NULL; + HBITMAP hBm = NULL; + PCLIPBOARDDATA pMemObj; + PCLIP pDibEl; + ULONG Offset; + + TRACE("IntSynthesizeBitmap(%p, %p)\n", pWinStaObj, pBmEl); + + pDibEl = IntIsFormatAvailable(pWinStaObj, CF_DIB); + ASSERT(pDibEl && !IS_DATA_SYNTHESIZED(pDibEl)); + if(!pDibEl->fGlobalHandle) + return; + + pMemObj = (PCLIPBOARDDATA)UserGetObject(gHandleTable, pDibEl->hData, otClipBoardData); + if (!pMemObj) + return; + + pBmi = (BITMAPINFO*)pMemObj->Data; + + if (pMemObj->cbData < sizeof(DWORD) && pMemObj->cbData < pBmi->bmiHeader.biSize) + goto cleanup; + + pConvertedBmi = DIB_ConvertBitmapInfo(pBmi, DIB_RGB_COLORS); + if (!pConvertedBmi) + goto cleanup; + + Offset = DIB_BitmapInfoSize(pBmi, DIB_RGB_COLORS); + + hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE); + if (!hdc) + goto cleanup; + + hBm = GreCreateDIBitmapInternal(hdc, + pConvertedBmi->bmiHeader.biWidth, + pConvertedBmi->bmiHeader.biHeight, + CBM_INIT, + pMemObj->Data + Offset, + pConvertedBmi, + DIB_RGB_COLORS, + 0, + 0); + + if (hBm) + { + GreSetObjectOwner(hBm, GDI_OBJ_HMGR_PUBLIC); + pBmEl->hData = hBm; + } + +cleanup: + if (hdc) + UserReleaseDC(NULL, hdc, FALSE); + + if (pConvertedBmi) + DIB_FreeConvertedBitmapInfo(pConvertedBmi, pBmi); +} + +VOID static NTAPI +IntAddSynthesizedFormats(PWINSTATION_OBJECT pWinStaObj) +{ + PCLIP pTextEl, pUniTextEl, pOemTextEl, pLocaleEl, pBmEl, pDibEl; + + pTextEl = IntIsFormatAvailable(pWinStaObj, CF_TEXT); + pOemTextEl = IntIsFormatAvailable(pWinStaObj, CF_OEMTEXT); + pUniTextEl = IntIsFormatAvailable(pWinStaObj, CF_UNICODETEXT); + pLocaleEl = IntIsFormatAvailable(pWinStaObj, CF_LOCALE); + pBmEl = IntIsFormatAvailable(pWinStaObj, CF_BITMAP); + pDibEl = IntIsFormatAvailable(pWinStaObj, CF_DIB); + + /* Add CF_LOCALE format if we have CF_TEXT */ + if (!pLocaleEl && pTextEl) + { + PCLIPBOARDDATA pMemObj; + HANDLE hMem; + + pMemObj = (PCLIPBOARDDATA)UserCreateObject(gHandleTable, NULL, &hMem, otClipBoardData, + sizeof(CLIPBOARDDATA) + sizeof(LCID)); + if (pMemObj) + { + pMemObj->cbData = sizeof(LCID); + *((LCID*)pMemObj->Data) = NtCurrentTeb()->CurrentLocale; + IntAddFormatedData(pWinStaObj, CF_LOCALE, hMem, TRUE, TRUE); + } + } + + /* Add CF_TEXT. Note: it is synthesized in user32.dll */ + if (!pTextEl && (pUniTextEl || pOemTextEl)) + IntAddFormatedData(pWinStaObj, CF_TEXT, DATA_SYNTH_USER, FALSE, TRUE); + + /* Add CF_OEMTEXT. Note: it is synthesized in user32.dll */ + if (!pOemTextEl && (pUniTextEl || pTextEl)) + IntAddFormatedData(pWinStaObj, CF_OEMTEXT, DATA_SYNTH_USER, FALSE, TRUE); + + /* Add CF_UNICODETEXT. Note: it is synthesized in user32.dll */ + if (!pUniTextEl && (pTextEl || pOemTextEl)) + IntAddFormatedData(pWinStaObj, CF_UNICODETEXT, DATA_SYNTH_USER, FALSE, TRUE); + + /* Add CF_BITMAP. Note: it is synthesized on demand */ + if (!pBmEl && pDibEl) + IntAddFormatedData(pWinStaObj, CF_BITMAP, DATA_SYNTH_KRNL, FALSE, TRUE); + + /* Note: we need to render the DIB or DIBV5 format as soon as possible + because pallette information may change */ + if (!pDibEl && pBmEl) + IntSynthesizeDib(pWinStaObj, pBmEl->hData); +} + +VOID NTAPI +UserEmptyClipboardData(PWINSTATION_OBJECT pWinSta) +{ + unsigned i; + PCLIP pElement; + + for (i = 0; i < pWinSta->cNumClipFormats; ++i) + { + pElement = &pWinSta->pClipBase[i]; + IntFreeElementData(pElement); + } + + if(pWinSta->pClipBase) + ExFreePoolWithTag(pWinSta->pClipBase, USERTAG_CLIPBOARD); + pWinSta->pClipBase = NULL; + pWinSta->cNumClipFormats = 0; +} + +/* UserClipboardFreeWindow is called from co_UserFreeWindow in window.c */ +VOID FASTCALL +UserClipboardFreeWindow(PWND pWindow) +{ + PWINSTATION_OBJECT pWinStaObj; + + pWinStaObj = IntGetWinStaForCbAccess(); + if (!pWinStaObj) + return; + + /* check if clipboard is not locked by this window, if yes, unlock it */ + if (pWindow == pWinStaObj->spwndClipOpen) + { + /* the window that opens the clipboard was destroyed */ + pWinStaObj->spwndClipOpen = NULL; + pWinStaObj->ptiClipLock = NULL; + } + if (pWindow == pWinStaObj->spwndClipOwner) + { + /* the owner window was destroyed */ + pWinStaObj->spwndClipOwner = NULL; + } + /* remove window from window chain */ + if (pWindow == pWinStaObj->spwndClipViewer) + pWinStaObj->spwndClipViewer = NULL; + + ObDereferenceObject(pWinStaObj); +} + +UINT APIENTRY +UserEnumClipboardFormats(UINT fmt) +{ + UINT Ret = 0; + PCLIP pElement; + PWINSTATION_OBJECT pWinStaObj = NULL; + + pWinStaObj = IntGetWinStaForCbAccess(); + if (!pWinStaObj) + goto cleanup; + + /* Check if clipboard has been opened */ + if (!IntIsClipboardOpenByMe(pWinStaObj)) + { + EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN); + goto cleanup; + } + + if (fmt == 0) + { + /* Return first format */ + if (pWinStaObj->pClipBase) + Ret = pWinStaObj->pClipBase[0].fmt; } 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(VOID) -{ - PCLIPBOARDELEMENT ce = ClipboardData; - PCLIPBOARDELEMENT tmp; - - while(ce) - { - tmp = ce->next; - if (ce->hData) - { - ExFreePool(ce->hData); - } - ExFreePool(ce); - ce = tmp; - } - - ClipboardData = NULL; -} - -/*==============================================================*/ - -HANDLE FASTCALL -renderBITMAPfromDIB(LPBYTE pDIB) -{ - HDC hdc; - HBITMAP hbitmap; - PBITMAPINFO pBmi, pConvertedBmi = NULL; - NTSTATUS Status ; - UINT offset = 0; /* Stupid compiler */ - - pBmi = (BITMAPINFO*)pDIB; - - //hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE); - hdc = UserGetDCEx(ClipboardWindow, NULL, DCX_USESTYLE); - - /* Probe it */ - _SEH2_TRY - { - ProbeForRead(&pBmi->bmiHeader.biSize, sizeof(DWORD), 1); - ProbeForRead(pBmi, pBmi->bmiHeader.biSize, 1); - ProbeForRead(pBmi, DIB_BitmapInfoSize(pBmi, DIB_RGB_COLORS), 1); - pConvertedBmi = DIB_ConvertBitmapInfo(pBmi, DIB_RGB_COLORS); - if(!pConvertedBmi) - { - Status = STATUS_INVALID_PARAMETER; - } - else - { - offset = DIB_BitmapInfoSize((BITMAPINFO*)pBmi, DIB_RGB_COLORS); - ProbeForRead(pDIB + offset, pConvertedBmi->bmiHeader.biSizeImage, 1); - } - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - Status = _SEH2_GetExceptionCode(); - } - _SEH2_END - - if(!NT_SUCCESS(Status)) - { - UserReleaseDC(ClipboardWindow, hdc, FALSE); - return NULL; - } - - hbitmap = GreCreateDIBitmapInternal(hdc, - pConvertedBmi->bmiHeader.biWidth, - pConvertedBmi->bmiHeader.biHeight, - CBM_INIT, - pDIB+offset, - pConvertedBmi, - DIB_RGB_COLORS, - 0, - 0); - //UserReleaseDC(NULL, hdc, FALSE); - UserReleaseDC(ClipboardWindow, hdc, FALSE); - - DIB_FreeConvertedBitmapInfo(pConvertedBmi, pBmi); - - 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(VOID) -{ - ExFreePool(synthesizedData); -} - -/*==============================================================*/ - -BOOL FASTCALL -intIsClipboardOpenByMe(VOID) -{ - /* 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(PWND 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); - } - } + /* Return next format */ + pElement = IntIsFormatAvailable(pWinStaObj, fmt); + ++pElement; + if (pElement < &pWinStaObj->pClipBase[pWinStaObj->cNumClipFormats]) + Ret = pElement->fmt; + } + +cleanup: + if(pWinStaObj) + ObDereferenceObject(pWinStaObj); + + return Ret; }
BOOL APIENTRY NtUserOpenClipboard(HWND hWnd, DWORD Unknown1) { - - PWND Window; - BOOL ret = FALSE; + PWND pWindow = NULL; + BOOL bRet = FALSE; + PWINSTATION_OBJECT pWinStaObj = NULL;
UserEnterExclusive();
- sendDrawClipboardMsg = FALSE; - recentlySetClipboard = FALSE; - - if (ClipboardThread) - { - /* clipboard is already open */ - if (ClipboardThread == PsGetCurrentThreadWin32Thread()) - { - if (ClipboardOwnerWindow) - { - if (ClipboardOwnerWindow->head.h == hWnd) - { - ret = TRUE; - } - } - else - { - if (hWnd == NULL) - { - ret = TRUE; - } - } - } - } - else - { - - if (hWnd != NULL) - { - Window = UserGetWindowObject(hWnd); - - if (Window != NULL) - { - ClipboardWindow = Window; - ClipboardThread = PsGetCurrentThreadWin32Thread(); - ret = TRUE; - } - else - { - ClipboardWindow = NULL; - ClipboardThread = NULL; - ClipboardOwnerWindow = NULL; - ClipboardOwnerThread = NULL; - } - } - else - { - ClipboardWindow = NULL; - ClipboardThread = PsGetCurrentThreadWin32Thread(); - ret = TRUE; - } - } - - UserLeave(); - - return ret; + if (hWnd) + { + pWindow = UserGetWindowObject(hWnd); + if (!pWindow) + { + EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); + goto cleanup; + } + } + + pWinStaObj = IntGetWinStaForCbAccess(); + if (!pWinStaObj) + goto cleanup; + + if (pWinStaObj->ptiClipLock) + { + /* Clipboard is already open */ + if (pWinStaObj->spwndClipOpen != pWindow) + { + EngSetLastError(ERROR_ACCESS_DENIED); + goto cleanup; + } + } + + /* Open clipboard */ + pWinStaObj->spwndClipOpen = pWindow; + pWinStaObj->ptiClipLock = PsGetCurrentThreadWin32Thread(); + bRet = TRUE; + +cleanup: + if (pWinStaObj) + ObDereferenceObject(pWinStaObj); + + UserLeave(); + + return bRet; }
BOOL APIENTRY NtUserCloseClipboard(VOID) { - BOOL ret = FALSE; + BOOL bRet = FALSE; + PWINSTATION_OBJECT pWinStaObj = NULL;
UserEnterExclusive();
- if (intIsClipboardOpenByMe()) - { - ClipboardWindow = NULL; - ClipboardThread = NULL; - ret = TRUE; - } - else + pWinStaObj = IntGetWinStaForCbAccess(); + if (!pWinStaObj) + goto cleanup; + + if (!IntIsClipboardOpenByMe(pWinStaObj)) { EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN); - } - - recentlySetClipboard = FALSE; - - UserLeave(); - - if (sendDrawClipboardMsg && WindowsChain) - { - /* only send message to the first window in the chain, then they'll do the chain */ - /* commented because it makes a crash in co_MsqSendMessage - ASSERT(WindowsChain->window); - ASSERT(WindowsChain->window->hSelf); - ERR("Clipboard: sending WM_DRAWCLIPBOARD to %p\n", WindowsChain->window->hSelf); - co_IntSendMessage(WindowsChain->window->hSelf, WM_DRAWCLIPBOARD, 0, 0); - */ - } - - return ret; + goto cleanup; + } + + /* Clipboard is no longer open */ + pWinStaObj->spwndClipOpen = NULL; + pWinStaObj->ptiClipLock = NULL; + bRet = TRUE; + + if (pWinStaObj->fClipboardChanged) + { + /* Add synthesized formats - they are rendered later */ + IntAddSynthesizedFormats(pWinStaObj); + + /* Notify viewer windows in chain */ + if (pWinStaObj->spwndClipViewer) + { + TRACE("Clipboard: sending WM_DRAWCLIPBOARD to %p\n", pWinStaObj->spwndClipViewer->head.h); + co_IntSendMessage(pWinStaObj->spwndClipViewer->head.h, WM_DRAWCLIPBOARD, 0, 0); + } + + pWinStaObj->fClipboardChanged = FALSE; + } + +cleanup: + if (pWinStaObj) + ObDereferenceObject(pWinStaObj); + + UserLeave(); + + return bRet; }
HWND APIENTRY NtUserGetOpenClipboardWindow(VOID) { - HWND ret = NULL; + HWND hWnd = NULL; + PWINSTATION_OBJECT pWinStaObj;
UserEnterShared();
- if (ClipboardWindow) - { - ret = ClipboardWindow->head.h; - } - - UserLeave(); - - return ret; + pWinStaObj = IntGetWinStaForCbAccess(); + if (!pWinStaObj) + goto cleanup; + + if (pWinStaObj->spwndClipOpen) + hWnd = pWinStaObj->spwndClipOpen->head.h; + + ObDereferenceObject(pWinStaObj); + +cleanup: + UserLeave(); + + return hWnd; }
BOOL APIENTRY NtUserChangeClipboardChain(HWND hWndRemove, HWND hWndNewNext) { - BOOL ret = FALSE; - PCLIPBOARDCHAINELEMENT w = NULL; - PWND removeWindow; + BOOL bRet = FALSE; + PWND pWindowRemove; + PWINSTATION_OBJECT pWinStaObj; + + TRACE("NtUserChangeClipboardChain(%p, %p)\n", hWndRemove, hWndNewNext); + UserEnterExclusive();
- removeWindow = UserGetWindowObject(hWndRemove); - - if (removeWindow) - { - if ((ret = !!IntIsWindowInChain(removeWindow))) - { - w = IntRemoveWindowFromChain(removeWindow); - if (w) - { - ExFreePool(w); - } - } - } - - if (ret && WindowsChain) - { - // only send message to the first window in the chain, - // then they do the chain - - /* WindowsChain->window may be NULL */ - LPARAM lparam = WindowsChain->window == NULL ? 0 : (LPARAM)WindowsChain->window->head.h; - ERR("Message: WM_CHANGECBCHAIN to %p", WindowsChain->window->head.h); - co_IntSendMessage(WindowsChain->window->head.h, WM_CHANGECBCHAIN, (WPARAM)hWndRemove, lparam); - } - - UserLeave(); - - return ret; + pWinStaObj = IntGetWinStaForCbAccess(); + if (!pWinStaObj) + goto cleanup; + + pWindowRemove = UserGetWindowObject(hWndRemove); + + if (pWindowRemove && pWinStaObj->spwndClipViewer) + { + if(pWindowRemove == pWinStaObj->spwndClipViewer) + pWinStaObj->spwndClipViewer = UserGetWindowObject(hWndNewNext); + + if(pWinStaObj->spwndClipViewer) + bRet = (BOOL)co_IntSendMessage(pWinStaObj->spwndClipViewer->head.h, WM_CHANGECBCHAIN, (WPARAM)hWndRemove, (LPARAM)hWndNewNext); + } + + ObDereferenceObject(pWinStaObj); + +cleanup: + UserLeave(); + + return bRet; }
DWORD APIENTRY NtUserCountClipboardFormats(VOID) { - DWORD ret = 0; - - if (ClipboardData) - { - ret = IntCountClipboardFormats(); - } - - return ret; -} - -DWORD APIENTRY + DWORD cFormats = 0; + PWINSTATION_OBJECT pWinStaObj = NULL; + + UserEnterShared(); + + pWinStaObj = IntGetWinStaForCbAccess(); + if (!pWinStaObj) + goto cleanup; + + cFormats = pWinStaObj->cNumClipFormats; + + ObDereferenceObject(pWinStaObj); + +cleanup: + UserLeave(); + + return cFormats; +} + +BOOL APIENTRY NtUserEmptyClipboard(VOID) { - BOOL ret = FALSE; + BOOL bRet = FALSE; + PWINSTATION_OBJECT pWinStaObj; + + TRACE("NtUserEmptyClipboard()\n");
UserEnterExclusive();
- if (intIsClipboardOpenByMe()) - { - if (ClipboardData) - { - IntEmptyClipboardData(); - } - - ClipboardOwnerWindow = ClipboardWindow; - ClipboardOwnerThread = ClipboardThread; - - IntIncrementSequenceNumber(); - - ret = TRUE; + pWinStaObj = IntGetWinStaForCbAccess(); + if (!pWinStaObj) + goto cleanup; + + if (IntIsClipboardOpenByMe(pWinStaObj)) + { + UserEmptyClipboardData(pWinStaObj); + + if (pWinStaObj->spwndClipOwner) + { + TRACE("Clipboard: WM_DESTROYCLIPBOARD to %p", pWinStaObj->spwndClipOwner->head.h); + co_IntSendMessageNoWait(pWinStaObj->spwndClipOwner->head.h, WM_DESTROYCLIPBOARD, 0, 0); + } + + pWinStaObj->spwndClipOwner = pWinStaObj->spwndClipOpen; + + pWinStaObj->iClipSequenceNumber++; + + bRet = TRUE; } else { EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN); - } - - if (ret && ClipboardOwnerWindow) - { - TRACE("Clipboard: WM_DESTROYCLIPBOARD to %p", ClipboardOwnerWindow->head.h); - co_IntSendMessageNoWait( ClipboardOwnerWindow->head.h, WM_DESTROYCLIPBOARD, 0, 0); - } - - UserLeave(); - - return ret; -} - -HANDLE APIENTRY -NtUserGetClipboardData(UINT uFormat, PVOID pBuffer) -{ - HANDLE ret = NULL; + ERR("Access denied!\n"); + } + + ObDereferenceObject(pWinStaObj); + +cleanup: + UserLeave(); + + return bRet; +} + +INT APIENTRY +NtUserGetClipboardFormatName(UINT fmt, LPWSTR lpszFormatName, INT cchMaxCount) +{ + INT iRet = 0;
UserEnterShared();
- if (intIsClipboardOpenByMe()) - { - /* when Unknown1 is zero, we returns to user32 the data size */ - if (!pBuffer) - { - PCLIPBOARDELEMENT data = intIsFormatAvailable(uFormat); - - if (data) - { - /* format exists in clipboard */ - if (data->size == DATA_DELAYED_RENDER) - { - /* tell owner what data needs to be rendered */ - if (ClipboardOwnerWindow) - { - ASSERT(ClipboardOwnerWindow->head.h); - co_IntSendMessage(ClipboardOwnerWindow->head.h, WM_RENDERFORMAT, (WPARAM)uFormat, 0); - data = intIsFormatAvailable(uFormat); - ASSERT(data->size); - ret = (HANDLE)(ULONG_PTR)data->size; - } - } - else - { - if (data->size == DATA_SYNTHESIZED_RENDER) - { - data->size = synthesizeData(uFormat); - } - - } - ret = (HANDLE)(ULONG_PTR)data->size; - } - else - { - /* there is no data in this format */ - //ret = (HANDLE)FALSE; - } - } - else - { - PCLIPBOARDELEMENT data = intIsFormatAvailable(uFormat); - - if (data) - { - if (data->size == DATA_DELAYED_RENDER) - { - // we rendered it in 1st call of getclipboard data - } - else - { - if (data->size == DATA_SYNTHESIZED_RENDER) - { - if (uFormat == CF_BITMAP) - { - /* BITMAP & METAFILEs returns a GDI handle */ - PCLIPBOARDELEMENT data = intIsFormatAvailable(CF_DIB); - if (data) - { - ret = renderBITMAPfromDIB(data->hData); - } - } - else - { - ret = (HANDLE)pBuffer; - - _SEH2_TRY - { - ProbeForWrite(pBuffer, synthesizedDataSize, 1); - memcpy(pBuffer, (PCHAR)synthesizedData, synthesizedDataSize); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - ret = NULL; - } - _SEH2_END - - freeSynthesizedData(); - } - } - else - { - ret = (HANDLE)pBuffer; - - _SEH2_TRY - { - ProbeForWrite(pBuffer, data->size, 1); - memcpy(pBuffer, (PCHAR)data->hData, data->size); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - ret = NULL; - } - _SEH2_END - } - } - - } - - } - } - else - { - EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN); - } - - UserLeave(); - - return ret; -} - -INT APIENTRY -NtUserGetClipboardFormatName(UINT format, PUNICODE_STRING FormatName, - INT cchMaxCount) -{ - UNICODE_STRING sFormatName; - INT ret = 0; - /* if the format is built-in we fail */ - if (format < 0xc000) + if (fmt < 0xc000) { /* registetrated formats are >= 0xc000 */ - return 0; - } - - if((cchMaxCount < 1) || !FormatName) + goto cleanup; + } + + if (cchMaxCount < 1 || !lpszFormatName) { EngSetLastError(ERROR_INVALID_PARAMETER); - return 0; + goto cleanup; }
_SEH2_TRY { - ProbeForWriteUnicodeString(FormatName); - sFormatName = *(volatile UNICODE_STRING *)FormatName; - ProbeForWrite(sFormatName.Buffer, sFormatName.MaximumLength, 1); - - ret = IntGetAtomName((RTL_ATOM)format, sFormatName.Buffer, cchMaxCount * sizeof(WCHAR)); - - if (ret >= 0) - { - ret = ret / sizeof(WCHAR); - sFormatName.Length = ret; - } - else - { - ret = 0; - } + ProbeForWrite(lpszFormatName, cchMaxCount * sizeof(WCHAR), 1); + + iRet = IntGetAtomName((RTL_ATOM)fmt, + lpszFormatName, + cchMaxCount * sizeof(WCHAR)); + iRet /= sizeof(WCHAR); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -769,432 +630,479 @@ } _SEH2_END;
- return ret; +cleanup: + UserLeave(); + + return iRet; }
HWND APIENTRY NtUserGetClipboardOwner(VOID) { - HWND ret = NULL; + HWND hWnd = NULL; + PWINSTATION_OBJECT pWinStaObj;
UserEnterShared();
- if (ClipboardOwnerWindow) - { - ret = ClipboardOwnerWindow->head.h; - } - - UserLeave(); - - return ret; + pWinStaObj = IntGetWinStaForCbAccess(); + if (!pWinStaObj) + goto cleanup; + + if (pWinStaObj->spwndClipOwner) + hWnd = pWinStaObj->spwndClipOwner->head.h; + + ObDereferenceObject(pWinStaObj); + +cleanup: + UserLeave(); + + return hWnd; }
HWND APIENTRY NtUserGetClipboardViewer(VOID) { - HWND ret = NULL; + HWND hWnd = NULL; + PWINSTATION_OBJECT pWinStaObj;
UserEnterShared();
- if (WindowsChain) - { - ret = WindowsChain->window->head.h; - } - - UserLeave(); - - return ret; + pWinStaObj = IntGetWinStaForCbAccess(); + if(!pWinStaObj) + goto cleanup; + + if (pWinStaObj->spwndClipViewer) + hWnd = pWinStaObj->spwndClipViewer->head.h; + + ObDereferenceObject(pWinStaObj); + +cleanup: + UserLeave(); + + return hWnd; }
INT APIENTRY NtUserGetPriorityClipboardFormat(UINT *paFormatPriorityList, INT cFormats) { - INT i; - UINT *priorityList; - INT ret = 0; - - UserEnterExclusive(); - - _SEH2_TRY - { - if (IntCountClipboardFormats() == 0) - { - ret = 0; - } - else - { - ProbeForRead(paFormatPriorityList, cFormats, sizeof(UINT)); - - priorityList = paFormatPriorityList; - - ret = -1; - - for (i = 0; i < cFormats; i++) + INT i, iRet = 0; + PWINSTATION_OBJECT pWinStaObj; + + UserEnterShared(); + + pWinStaObj = IntGetWinStaForCbAccess(); + if (!pWinStaObj) + goto cleanup; + + if (pWinStaObj->pClipBase == NULL) + { + iRet = 0; + } + else + { + _SEH2_TRY + { + ProbeForRead(paFormatPriorityList, cFormats * sizeof(UINT), sizeof(UINT)); + + iRet = -1; + + for (i = 0; i < cFormats; ++i) { - if (intIsFormatAvailable(priorityList[i])) + if (IntIsFormatAvailable(pWinStaObj, paFormatPriorityList[i])) { - ret = priorityList[i]; + iRet = paFormatPriorityList[i]; break; } } - + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastNtError(_SEH2_GetExceptionCode()); + } + _SEH2_END; + } + + ObDereferenceObject(pWinStaObj); + +cleanup: + UserLeave(); + + return iRet; + +} + +BOOL APIENTRY +NtUserIsClipboardFormatAvailable(UINT fmt) +{ + BOOL bRet = FALSE; + PWINSTATION_OBJECT pWinStaObj; + + TRACE("NtUserIsClipboardFormatAvailable(%x)\n", fmt); + + UserEnterShared(); + + pWinStaObj = IntGetWinStaForCbAccess(); + if (!pWinStaObj) + goto cleanup; + + if (IntIsFormatAvailable(pWinStaObj, fmt)) + bRet = TRUE; + + ObDereferenceObject(pWinStaObj); + +cleanup: + UserLeave(); + + return bRet; +} + +HANDLE APIENTRY +NtUserGetClipboardData(UINT fmt, PGETCLIPBDATA pgcd) +{ + NTSTATUS Status = STATUS_SUCCESS; + HANDLE hRet = NULL; + PCLIP pElement; + PWINSTATION_OBJECT pWinStaObj = NULL; + + TRACE("NtUserGetClipboardData(%x, %p)\n", fmt, pgcd); + + UserEnterShared(); + + pWinStaObj = IntGetWinStaForCbAccess(); + if (!pWinStaObj) + goto cleanup; + + if (!IntIsClipboardOpenByMe(pWinStaObj)) + { + EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN); + goto cleanup; + } + + pElement = IntIsFormatAvailable(pWinStaObj, fmt); + if (pElement && IS_DATA_DELAYED(pElement) && pWinStaObj->spwndClipOwner) + { + /* send WM_RENDERFORMAT message */ + pWinStaObj->fInDelayedRendering = TRUE; + co_IntSendMessage(pWinStaObj->spwndClipOwner->head.h, WM_RENDERFORMAT, (WPARAM)fmt, 0); + pWinStaObj->fInDelayedRendering = FALSE; + + /* data should be in clipboard now */ + pElement = IntIsFormatAvailable(pWinStaObj, fmt); + } + + if (!pElement || IS_DATA_DELAYED(pElement)) + goto cleanup; + + + if (IS_DATA_SYNTHESIZED(pElement)) + { + /* Note: data is synthesized in usermode */ + /* TODO: Add more formats */ + switch (fmt) + { + case CF_UNICODETEXT: + case CF_TEXT: + case CF_OEMTEXT: + pElement = IntIsFormatAvailable(pWinStaObj, CF_UNICODETEXT); + if (IS_DATA_SYNTHESIZED(pElement)) + pElement = IntIsFormatAvailable(pWinStaObj, CF_TEXT); + if (IS_DATA_SYNTHESIZED(pElement)) + pElement = IntIsFormatAvailable(pWinStaObj, CF_OEMTEXT); + break; + case CF_BITMAP: + IntSynthesizeBitmap(pWinStaObj, pElement); + break; + default: + ASSERT(FALSE); + } + } + + _SEH2_TRY + { + ProbeForWrite(pgcd, sizeof(*pgcd), 1); + pgcd->uFmtRet = pElement->fmt; + pgcd->fGlobalHandle = pElement->fGlobalHandle; + + /* Text and bitmap needs more data */ + if (fmt == CF_TEXT) + { + PCLIP pLocaleEl; + + pLocaleEl = IntIsFormatAvailable(pWinStaObj, CF_LOCALE); + if (pLocaleEl && !IS_DATA_DELAYED(pLocaleEl)) + pgcd->hLocale = pLocaleEl->hData; + } + else if (fmt == CF_BITMAP) + { + PCLIP pPaletteEl; + + pPaletteEl = IntIsFormatAvailable(pWinStaObj, CF_PALETTE); + if (pPaletteEl && !IS_DATA_DELAYED(pPaletteEl)) + pgcd->hPalette = pPaletteEl->hData; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - SetLastNtError(_SEH2_GetExceptionCode()); - } - _SEH2_END; - - UserLeave(); - - return ret; - -} - -BOOL APIENTRY -NtUserIsClipboardFormatAvailable(UINT format) -{ - BOOL ret = FALSE; - - UserEnterShared(); - - ret = (intIsFormatAvailable(format) != NULL); - - UserLeave(); - - return ret; -} - - + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END + + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + goto cleanup; + } + + hRet = pElement->hData; + +cleanup: + if(pWinStaObj) + ObDereferenceObject(pWinStaObj); + + UserLeave(); + + TRACE("Ret: %p\n", hRet); + + return hRet; +}
HANDLE APIENTRY -NtUserSetClipboardData(UINT uFormat, HANDLE hMem, DWORD size) -{ - HANDLE hCBData = NULL; - UNICODE_STRING unicodeString; - OEM_STRING oemString; - ANSI_STRING ansiString; +NtUserSetClipboardData(UINT fmt, HANDLE hData, PSETCLIPBDATA scd) +{ + HANDLE hRet = NULL; + NTSTATUS Status = STATUS_SUCCESS; + PWINSTATION_OBJECT pWinStaObj = NULL; + BOOLEAN fGlobalHandle = FALSE; + + TRACE("NtUserSetClipboardData(%x %p %p)\n", fmt, hData, scd);
UserEnterExclusive();
- /* to place data here the we need to be the owner */ - if (ClipboardOwnerThread == PsGetCurrentThreadWin32Thread()) - { - PCLIPBOARDELEMENT data = intIsFormatAvailable(uFormat); - if (data) - { - - if (data->size == DATA_DELAYED_RENDER) - { - intRemoveFormatedData(uFormat); - } - else - { - // we already have this format on clipboard - goto exit_setCB; - } - } - - if (hMem) - { - _SEH2_TRY - { - ProbeForRead(hMem, size, 1); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - SetLastNtError(_SEH2_GetExceptionCode()); - _SEH2_YIELD(goto exit_setCB); - } - _SEH2_END; - - if (intIsClipboardOpenByMe()) - { - delayedRender = FALSE; - } - - if (!canSinthesize(uFormat)) - { - hCBData = ExAllocatePoolWithTag(PagedPool, size, USERTAG_CLIPBOARD); - memcpy(hCBData, hMem, size); - intAddFormatedData(uFormat, hCBData, size); - ERR("Data stored\n"); - } - - sendDrawClipboardMsg = TRUE; - recentlySetClipboard = TRUE; - lastEnumClipboardFormats = uFormat; - - /* conversions */ - switch (uFormat) - { - case CF_TEXT: - { - //TODO : sinthesize CF_UNICODETEXT & CF_OEMTEXT - // CF_TEXT -> CF_UNICODETEXT - ansiString.Buffer = hCBData; - ansiString.Length = size; - RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE); - intAddFormatedData(CF_UNICODETEXT, unicodeString.Buffer, unicodeString.Length * sizeof(WCHAR)); - // CF_TEXT -> CF_OEMTEXT - RtlUnicodeStringToOemString(&oemString, &unicodeString, TRUE); - intAddFormatedData(CF_OEMTEXT, oemString.Buffer, oemString.Length); - //HKCU\Control Panel\International\Locale - //intAddFormatedData(CF_LOCALE, oemString.Buffer, oemString.Length); - break; - } - case CF_UNICODETEXT: - { - //TODO : sinthesize CF_TEXT & CF_OEMTEXT - //CF_UNICODETEXT -> CF_TEXT - unicodeString.Buffer = hCBData; - unicodeString.Length = size; - RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE); - intAddFormatedData(CF_TEXT, ansiString.Buffer, ansiString.Length); - //CF_UNICODETEXT -> CF_OEMTEXT - RtlUnicodeStringToOemString(&oemString, &unicodeString, TRUE); - intAddFormatedData(CF_OEMTEXT, oemString.Buffer, oemString.Length); - break; - } - case CF_OEMTEXT: - { - //TODO : sinthesize CF_TEXT & CF_UNICODETEXT - //CF_OEMTEXT -> CF_UNICODETEXT - oemString.Buffer = hCBData; - oemString.Length = size; - RtlOemStringToUnicodeString(&unicodeString, &oemString, TRUE); - intAddFormatedData(CF_UNICODETEXT, unicodeString.Buffer, unicodeString.Length * sizeof(WCHAR)); - //CF_OEMTEXT -> CF_TEXT - RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE); - intAddFormatedData(CF_TEXT, ansiString.Buffer, ansiString.Length); - break; - } - case CF_BITMAP: - { - // we need to render the DIB or DIBV5 format as soon as possible - // because pallette information may change - - HDC hdc; - BITMAP bm; - BITMAPINFO bi; - SURFACE *psurf; - - hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE); - - - psurf = SURFACE_ShareLockSurface(hMem); - BITMAP_GetObject(psurf, sizeof(BITMAP), (PVOID)&bm); - if(psurf) - { - SURFACE_ShareUnlockSurface(psurf); - } - - bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bi.bmiHeader.biWidth = bm.bmWidth; - bi.bmiHeader.biHeight = bm.bmHeight; - bi.bmiHeader.biPlanes = 1; - bi.bmiHeader.biBitCount = bm.bmPlanes * bm.bmBitsPixel; - bi.bmiHeader.biCompression = BI_RGB; - bi.bmiHeader.biSizeImage = 0; - bi.bmiHeader.biXPelsPerMeter = 0; - bi.bmiHeader.biYPelsPerMeter = 0; - bi.bmiHeader.biClrUsed = 0; - - NtGdiGetDIBitsInternal(hdc, hMem, 0, bm.bmHeight, NULL, &bi, DIB_RGB_COLORS, 0, 0); - - size = bi.bmiHeader.biSizeImage + sizeof(BITMAPINFOHEADER); - - hCBData = ExAllocatePoolWithTag(PagedPool, size, USERTAG_CLIPBOARD); - memcpy(hCBData, &bi, sizeof(BITMAPINFOHEADER)); - - NtGdiGetDIBitsInternal(hdc, hMem, 0, bm.bmHeight, (LPBYTE)hCBData + sizeof(BITMAPINFOHEADER), &bi, DIB_RGB_COLORS, 0, 0); - - UserReleaseDC(NULL, hdc, FALSE); - - intAddFormatedData(CF_DIB, hCBData, size); - intAddFormatedData(CF_BITMAP, 0, DATA_SYNTHESIZED_RENDER); - // intAddFormatedData(CF_DIBV5, hCBData, size); - - break; - } - case CF_DIB: - { - intAddFormatedData(CF_BITMAP, 0, DATA_SYNTHESIZED_RENDER); - // intAddFormatedData(CF_DIBV5, hCBData, size); - /* investigate */ - // intAddFormatedData(CF_PALETTE, hCBData, size); - break; - } - case CF_DIBV5: - // intAddFormatedData(CF_BITMAP, hCBData, size); - // intAddFormatedData(CF_PALETTE, hCBData, size); - // intAddFormatedData(CF_DIB, hCBData, size); - break; - case CF_ENHMETAFILE: - // intAddFormatedData(CF_METAFILEPICT, hCBData, size); - break; - case CF_METAFILEPICT: - // intAddFormatedData(CF_ENHMETAFILE, hCBData, size); - break; - } - - } - else - { - // the window provides data in the specified format - delayedRender = TRUE; - sendDrawClipboardMsg = TRUE; - intAddFormatedData(uFormat, NULL, 0); - ERR("SetClipboardData delayed format: %d\n", uFormat); - } - - - } - -exit_setCB: - - UserLeave(); - - return hMem; + pWinStaObj = IntGetWinStaForCbAccess(); + if (!pWinStaObj) + goto cleanup; + + /* If it's delayed rendering we don't have to open clipboard */ + if ((pWinStaObj->fInDelayedRendering && + pWinStaObj->spwndClipOwner->head.pti != PsGetCurrentThreadWin32Thread()) || + !IntIsClipboardOpenByMe(pWinStaObj)) + { + ERR("Access denied!\n"); + EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN); + goto cleanup; + } + + _SEH2_TRY + { + ProbeForRead(scd, sizeof(*scd), 1); + fGlobalHandle = scd->fGlobalHandle; + if (scd->fIncSerialNumber) + pWinStaObj->iClipSerialNumber++; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END + + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + goto cleanup; + } + + /* Is it a delayed render? */ + if (hData) + { + /* Is it a bitmap? */ + if (fmt == CF_BITMAP) + { + /* Make bitmap public */ + GreSetObjectOwner(hData, GDI_OBJ_HMGR_PUBLIC); + } + + /* Save data in the clipboard */ + IntAddFormatedData(pWinStaObj, fmt, hData, fGlobalHandle, FALSE); + TRACE("hData stored\n"); + + pWinStaObj->iClipSequenceNumber++; + pWinStaObj->fClipboardChanged = TRUE; + + /* Note: synthesized formats are added in NtUserCloseClipboard */ + } + else + { + /* This is a delayed render */ + IntAddFormatedData(pWinStaObj, fmt, DATA_DELAYED, FALSE, FALSE); + TRACE("SetClipboardData delayed format: %u\n", fmt); + } + + /* Return hData on success */ + hRet = hData; + +cleanup: + TRACE("NtUserSetClipboardData returns: %p\n", hRet); + + if(pWinStaObj) + ObDereferenceObject(pWinStaObj); + + UserLeave(); + + return hRet; }
HWND APIENTRY NtUserSetClipboardViewer(HWND hWndNewViewer) { - HWND ret = NULL; - PCLIPBOARDCHAINELEMENT newWC = NULL; - PWND window; + HWND hWndNext = NULL; + PWINSTATION_OBJECT pWinStaObj = NULL; + PWND pWindow;
UserEnterExclusive();
- window = UserGetWindowObject(hWndNewViewer); - - if (window) - { - if ((newWC = IntAddWindowToChain(window))) - { - if (newWC) - { - // newWC->next may be NULL if we are the first window in the chain - if (newWC->next) - { - // return the next HWND available window in the chain - ret = newWC->next->window->head.h; - } - } - } - } - - UserLeave(); - - return ret; -} - -UINT APIENTRY -IntEnumClipboardFormats(UINT uFormat) -{ - UINT ret = 0; - - if (intIsClipboardOpenByMe()) - { - if (uFormat == 0) - { - if (recentlySetClipboard) - { - ret = lastEnumClipboardFormats; - } - else - { - /* return the first available format */ - if (ClipboardData) - { - ret = ClipboardData->format; - } - } - } - else - { - if (recentlySetClipboard) - { - ret = 0; - } - else - { - /* querying nextt available format */ - PCLIPBOARDELEMENT data = intIsFormatAvailable(uFormat); - - if (data) - { - if (data->next) - { - ret = data->next->format; - } - else - { - /* reached the end */ - ret = 0; - } - } - } - - } - } - else - { - EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN); - } - - return ret; -} - -// This number is incremented whenever the contents of the clipboard change -// or the clipboard is emptied. -// If clipboard rendering is delayed, + pWinStaObj = IntGetWinStaForCbAccess(); + if (!pWinStaObj) + goto cleanup; + + pWindow = UserGetWindowObject(hWndNewViewer); + if (!pWindow) + { + EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); + goto cleanup; + } + + /* Return previous viewer. New viever window should + send messages to rest of the chain */ + if (pWinStaObj->spwndClipViewer) + hWndNext = pWinStaObj->spwndClipViewer->head.h; + + /* Set new viewer window */ + pWinStaObj->spwndClipViewer = pWindow; + +cleanup: + if(pWinStaObj) + ObDereferenceObject(pWinStaObj); + + UserLeave(); + + return hWndNext; +} + +// Sequence number is incremented whenever the contents of the clipboard change +// or the clipboard is emptied. If clipboard rendering is delayed, // the sequence number is not incremented until the changes are rendered. -VOID FASTCALL -IntIncrementSequenceNumber(VOID) -{ - PTHREADINFO pti; - PWINSTATION_OBJECT WinStaObj; - - pti = PsGetCurrentThreadWin32Thread(); - WinStaObj = pti->rpdesk->rpwinstaParent; - - WinStaObj->Clipboard->ClipboardSequenceNumber++; -}
DWORD APIENTRY NtUserGetClipboardSequenceNumber(VOID) { - //windowstation sequence number - //if no WINSTA_ACCESSCLIPBOARD access to the window station, - //the function returns zero. - DWORD sn; - - HWINSTA WinSta; - PWINSTATION_OBJECT WinStaObj; - NTSTATUS Status; - - WinSta = UserGetProcessWindowStation(); - - Status = IntValidateWindowStationHandle(WinSta, KernelMode, WINSTA_ACCESSCLIPBOARD, &WinStaObj); - - if (!NT_SUCCESS(Status)) - { - ERR("No WINSTA_ACCESSCLIPBOARD access\n"); - SetLastNtError(Status); - return 0; - } - - sn = WinStaObj->ClipboardSequenceNumber; - - ObDereferenceObject(WinStaObj); - - //local copy - //sn = ClipboardSequenceNumber; - - return sn; + DWORD dwRet = 0; + PWINSTATION_OBJECT pWinStaObj; + + UserEnterShared(); + + pWinStaObj = IntGetWinStaForCbAccess(); + if (!pWinStaObj) + goto cleanup; + + /* Get windowstation sequence number */ + dwRet = (DWORD)pWinStaObj->iClipSequenceNumber; + + ObDereferenceObject(pWinStaObj); + +cleanup: + UserLeave(); + + return dwRet; +} + +HANDLE APIENTRY +NtUserConvertMemHandle( + PVOID pData, + DWORD cbData) +{ + HANDLE hMem = NULL; + PCLIPBOARDDATA pMemObj; + + UserEnterExclusive(); + + /* Create Clipboard data object */ + pMemObj = UserCreateObject(gHandleTable, NULL, &hMem, otClipBoardData, sizeof(CLIPBOARDDATA) + cbData); + if (!pMemObj) + goto cleanup; + + pMemObj->cbData = cbData; + + /* Copy data */ + _SEH2_TRY + { + ProbeForRead(pData, cbData, 1); + memcpy(pMemObj->Data, pData, cbData); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + pMemObj = NULL; + } + _SEH2_END; + + /* If we failed to copy data, remove handle */ + if (!pMemObj) + { + UserDeleteObject(hMem, otClipBoardData); + hMem = NULL; + } + +cleanup: + UserLeave(); + + return hMem; +} + +NTSTATUS APIENTRY +NtUserCreateLocalMemHandle( + HANDLE hMem, + PVOID pData, + DWORD cbData, + DWORD *pcbData) +{ + PCLIPBOARDDATA pMemObj; + NTSTATUS Status = STATUS_SUCCESS; + + UserEnterShared(); + + /* Get Clipboard data object */ + pMemObj = (PCLIPBOARDDATA)UserGetObject(gHandleTable, hMem, otClipBoardData); + if (!pMemObj) + { + Status = STATUS_INVALID_HANDLE; + goto cleanup; + } + + /* Don't overrun */ + if (cbData > pMemObj->cbData) + cbData = pMemObj->cbData; + + /* Copy data to usermode */ + _SEH2_TRY + { + if (pcbData) + { + ProbeForWrite(pcbData, sizeof(*pcbData), 1); + *pcbData = pMemObj->cbData; + } + + ProbeForWrite(pData, cbData, 1); + memcpy(pData, pMemObj->Data, cbData); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + +cleanup: + UserLeave(); + + return Status; }
/* EOF */
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c [iso-8859-1] Thu Sep 8 16:32:54 2011 @@ -106,30 +106,6 @@ { STUB; return 0; -} - -DWORD -APIENTRY -NtUserConvertMemHandle( - DWORD Unknown0, - DWORD Unknown1) -{ - STUB - - return 0; -} - -DWORD -APIENTRY -NtUserCreateLocalMemHandle( - DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3) -{ - STUB - - return 0; }
BOOL
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/simplecall.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/simplecall.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/simplecall.c [iso-8859-1] Thu Sep 8 16:32:54 2011 @@ -313,7 +313,7 @@ } case ONEPARAM_ROUTINE_ENUMCLIPBOARDFORMATS: /* FIXME: Should use UserEnterShared */ - RETURN(IntEnumClipboardFormats(Param)); + RETURN(UserEnumClipboardFormats(Param));
case ONEPARAM_ROUTINE_CSRSS_GUICHECK: IntUserManualGuiCheck(Param);
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/useratom.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/useratom.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/useratom.c [iso-8859-1] Thu Sep 8 16:32:54 2011 @@ -69,7 +69,7 @@ Status = RtlQueryAtomInAtomTable(gAtomTable, nAtom, NULL, NULL, lpBuffer, &Size);
if (Size < nSize) - *(lpBuffer + Size) = 0; + *(lpBuffer + Size/sizeof(WCHAR)) = 0; if (!NT_SUCCESS(Status)) { SetLastNtError(Status);
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/window.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/window.c [iso-8859-1] Thu Sep 8 16:32:54 2011 @@ -482,7 +482,7 @@
UserDereferenceObject(Window);
- IntClipboardFreeWindow(Window); + UserClipboardFreeWindow(Window);
return 0; }
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/winsta.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/winsta.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/winsta.c [iso-8859-1] Thu Sep 8 16:32:54 2011 @@ -97,18 +97,6 @@ return STATUS_SUCCESS; }
-BOOL FASTCALL -IntSetupClipboard(PWINSTATION_OBJECT WinStaObj) -{ - WinStaObj->Clipboard = ExAllocatePoolWithTag(PagedPool, sizeof(CLIPBOARDSYSTEM), TAG_WINSTA); - if (WinStaObj->Clipboard) - { - RtlZeroMemory(WinStaObj->Clipboard, sizeof(CLIPBOARDSYSTEM)); - return TRUE; - } - return FALSE; -} - /* OBJECT CALLBACKS **********************************************************/
VOID APIENTRY @@ -117,6 +105,8 @@ PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)Parameters->Object;
TRACE("Deleting window station (0x%X)\n", WinSta); + + UserEmptyClipboardData(WinSta);
RtlDestroyAtomTable(WinSta->AtomTable);
@@ -240,14 +230,14 @@ Buffer += WINSTA_ROOT_NAME_LENGTH; if (WinStaName != NULL) { - memcpy(Buffer, L"\", sizeof(WCHAR)); + *Buffer = L'\'; Buffer ++; memcpy(Buffer, WinStaName->Buffer, WinStaName->Length);
if (DesktopName != NULL) { Buffer += WinStaName->Length / sizeof(WCHAR); - memcpy(Buffer, L"\", sizeof(WCHAR)); + *Buffer = L'\'; Buffer ++; memcpy(Buffer, DesktopName->Buffer, DesktopName->Length); } @@ -503,11 +493,6 @@ WindowStationObject->Name = WindowStationName; WindowStationObject->ScreenSaverRunning = FALSE; WindowStationObject->FlatMenu = FALSE; - - if (!IntSetupClipboard(WindowStationObject)) - { - ERR("WindowStation: Error Setting up the clipboard!!!\n"); - }
if (InputWindowStation == NULL) {