1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS user32.dll
3c2c66affSColin Finck * FILE: win32ss/user/user32/windows/clipboard.c
4c2c66affSColin Finck * PURPOSE: Input
5c2c66affSColin Finck * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
6c2c66affSColin Finck * Pablo Borobia <pborobia@gmail.com>
7c2c66affSColin Finck * UPDATE HISTORY:
8c2c66affSColin Finck * 09-05-2001 CSH Created
9c2c66affSColin Finck *
10c2c66affSColin Finck */
11c2c66affSColin Finck
12c2c66affSColin Finck #include <user32.h>
13c2c66affSColin Finck
14c2c66affSColin Finck #define NDEBUG
15c2c66affSColin Finck
16c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(user32);
17c2c66affSColin Finck
18da264743Sjimtabor HANDLE WINAPI GdiConvertMetaFilePict(HANDLE);
19da264743Sjimtabor HANDLE WINAPI GdiConvertEnhMetaFile(HANDLE);
20da264743Sjimtabor HANDLE WINAPI GdiCreateLocalEnhMetaFile(HANDLE);
21da264743Sjimtabor HANDLE WINAPI GdiCreateLocalMetaFilePict(HANDLE);
22da264743Sjimtabor
23da264743Sjimtabor
24c2c66affSColin Finck /*
25c2c66affSColin Finck * @implemented
26c2c66affSColin Finck */
27c2c66affSColin Finck BOOL
28c2c66affSColin Finck WINAPI
OpenClipboard(HWND hWndNewOwner)29c2c66affSColin Finck OpenClipboard(HWND hWndNewOwner)
30c2c66affSColin Finck {
31c2c66affSColin Finck return NtUserOpenClipboard(hWndNewOwner, 0);
32c2c66affSColin Finck }
33c2c66affSColin Finck
34c2c66affSColin Finck /*
35c2c66affSColin Finck * @implemented
36c2c66affSColin Finck */
37c2c66affSColin Finck UINT
38c2c66affSColin Finck WINAPI
EnumClipboardFormats(UINT format)39c2c66affSColin Finck EnumClipboardFormats(UINT format)
40c2c66affSColin Finck {
41c2c66affSColin Finck SetLastError(NO_ERROR);
42c2c66affSColin Finck return NtUserxEnumClipboardFormats(format);
43c2c66affSColin Finck }
44c2c66affSColin Finck
45c2c66affSColin Finck /*
46c2c66affSColin Finck * @implemented
47c2c66affSColin Finck */
48c2c66affSColin Finck INT
49c2c66affSColin Finck WINAPI
GetClipboardFormatNameA(UINT format,LPSTR lpszFormatName,int cchMaxCount)50c2c66affSColin Finck GetClipboardFormatNameA(UINT format,
51c2c66affSColin Finck LPSTR lpszFormatName,
52c2c66affSColin Finck int cchMaxCount)
53c2c66affSColin Finck {
54c2c66affSColin Finck LPWSTR lpBuffer;
55c2c66affSColin Finck INT Length;
56c2c66affSColin Finck
57c2c66affSColin Finck lpBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, cchMaxCount * sizeof(WCHAR));
58c2c66affSColin Finck if (!lpBuffer)
59c2c66affSColin Finck {
60c2c66affSColin Finck SetLastError(ERROR_OUTOFMEMORY);
61c2c66affSColin Finck return 0;
62c2c66affSColin Finck }
63c2c66affSColin Finck
64c2c66affSColin Finck /* we need a UNICODE string */
65c2c66affSColin Finck Length = NtUserGetClipboardFormatName(format, lpBuffer, cchMaxCount);
66c2c66affSColin Finck
67c2c66affSColin Finck if (Length != 0)
68c2c66affSColin Finck {
69c2c66affSColin Finck if (!WideCharToMultiByte(CP_ACP, 0, lpBuffer, Length, lpszFormatName, cchMaxCount, NULL, NULL))
70c2c66affSColin Finck {
71c2c66affSColin Finck /* clear result string */
72c2c66affSColin Finck Length = 0;
73c2c66affSColin Finck }
7438db0744SSerge Gautherie lpszFormatName[Length] = ANSI_NULL;
75c2c66affSColin Finck }
76c2c66affSColin Finck
77c2c66affSColin Finck RtlFreeHeap(RtlGetProcessHeap(), 0, lpBuffer);
78c2c66affSColin Finck return Length;
79c2c66affSColin Finck }
80c2c66affSColin Finck
81c2c66affSColin Finck /*
82c2c66affSColin Finck * @implemented
83c2c66affSColin Finck */
84c2c66affSColin Finck INT
85c2c66affSColin Finck WINAPI
GetClipboardFormatNameW(UINT uFormat,LPWSTR lpszFormatName,INT cchMaxCount)86c2c66affSColin Finck GetClipboardFormatNameW(UINT uFormat,
87c2c66affSColin Finck LPWSTR lpszFormatName,
88c2c66affSColin Finck INT cchMaxCount)
89c2c66affSColin Finck {
90c2c66affSColin Finck return NtUserGetClipboardFormatName(uFormat, lpszFormatName, cchMaxCount);
91c2c66affSColin Finck }
92c2c66affSColin Finck
93c2c66affSColin Finck /*
94c2c66affSColin Finck * @implemented
95c2c66affSColin Finck */
96c2c66affSColin Finck UINT
97c2c66affSColin Finck WINAPI
RegisterClipboardFormatA(LPCSTR lpszFormat)98c2c66affSColin Finck RegisterClipboardFormatA(LPCSTR lpszFormat)
99c2c66affSColin Finck {
10038db0744SSerge Gautherie UINT ret;
101c2c66affSColin Finck UNICODE_STRING usFormat = {0};
102c2c66affSColin Finck
103c2c66affSColin Finck if (lpszFormat == NULL)
104c2c66affSColin Finck {
105c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
106c2c66affSColin Finck return 0;
107c2c66affSColin Finck }
108c2c66affSColin Finck
10938db0744SSerge Gautherie if (*lpszFormat == ANSI_NULL)
110c2c66affSColin Finck {
111c2c66affSColin Finck SetLastError(ERROR_INVALID_NAME);
112c2c66affSColin Finck return 0;
113c2c66affSColin Finck }
114c2c66affSColin Finck
11538db0744SSerge Gautherie if (!RtlCreateUnicodeStringFromAsciiz(&usFormat, lpszFormat))
116c2c66affSColin Finck {
117*7804cf03SSerge Gautherie SetLastError(ERROR_NOT_ENOUGH_MEMORY);
11838db0744SSerge Gautherie return 0;
119c2c66affSColin Finck }
120c2c66affSColin Finck
12138db0744SSerge Gautherie ret = NtUserRegisterWindowMessage(&usFormat); //(LPCWSTR)
12238db0744SSerge Gautherie
12338db0744SSerge Gautherie RtlFreeUnicodeString(&usFormat);
12438db0744SSerge Gautherie
125c2c66affSColin Finck return ret;
126c2c66affSColin Finck }
127c2c66affSColin Finck
128c2c66affSColin Finck /*
129c2c66affSColin Finck * @implemented
130c2c66affSColin Finck */
131c2c66affSColin Finck UINT
132c2c66affSColin Finck WINAPI
RegisterClipboardFormatW(LPCWSTR lpszFormat)133c2c66affSColin Finck RegisterClipboardFormatW(LPCWSTR lpszFormat)
134c2c66affSColin Finck {
135c2c66affSColin Finck UNICODE_STRING usFormat = {0};
136c2c66affSColin Finck
137c2c66affSColin Finck if (lpszFormat == NULL)
138c2c66affSColin Finck {
139c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
140c2c66affSColin Finck return 0;
141c2c66affSColin Finck }
142c2c66affSColin Finck
14338db0744SSerge Gautherie if (*lpszFormat == UNICODE_NULL)
144c2c66affSColin Finck {
145c2c66affSColin Finck SetLastError(ERROR_INVALID_NAME);
146c2c66affSColin Finck return 0;
147c2c66affSColin Finck }
148c2c66affSColin Finck
149c2c66affSColin Finck RtlInitUnicodeString(&usFormat, lpszFormat);
15038db0744SSerge Gautherie return NtUserRegisterWindowMessage(&usFormat);
151c2c66affSColin Finck }
152c2c66affSColin Finck
153c2c66affSColin Finck static PVOID WINAPI
IntSynthesizeMultiByte(PVOID pwStr,DWORD cbStr,BOOL bOem)154c2c66affSColin Finck IntSynthesizeMultiByte(PVOID pwStr, DWORD cbStr, BOOL bOem)
155c2c66affSColin Finck {
156c2c66affSColin Finck HANDLE hGlobal;
157c2c66affSColin Finck PVOID pGlobal;
158c2c66affSColin Finck INT cbGlobal;
159c2c66affSColin Finck
160c2c66affSColin Finck cbGlobal = WideCharToMultiByte(bOem ? CP_OEMCP : CP_ACP,
161c2c66affSColin Finck 0, pwStr, cbStr / sizeof(WCHAR),
162c2c66affSColin Finck NULL, 0, NULL, NULL);
163c2c66affSColin Finck hGlobal = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbGlobal);
164c2c66affSColin Finck if (!hGlobal)
165c2c66affSColin Finck return NULL;
166c2c66affSColin Finck
167c2c66affSColin Finck pGlobal = GlobalLock(hGlobal);
168c2c66affSColin Finck WideCharToMultiByte(bOem ? CP_OEMCP : CP_ACP,
169c2c66affSColin Finck 0, pwStr, cbStr / sizeof(WCHAR),
170c2c66affSColin Finck pGlobal, cbGlobal, NULL, NULL);
171c2c66affSColin Finck return pGlobal;
172c2c66affSColin Finck }
173c2c66affSColin Finck
174c2c66affSColin Finck static PVOID WINAPI
IntSynthesizeWideChar(PVOID pwStr,DWORD cbStr,BOOL bOem)175c2c66affSColin Finck IntSynthesizeWideChar(PVOID pwStr, DWORD cbStr, BOOL bOem)
176c2c66affSColin Finck {
177c2c66affSColin Finck HANDLE hGlobal;
178c2c66affSColin Finck PVOID pGlobal;
179c2c66affSColin Finck INT cbGlobal;
180c2c66affSColin Finck
181c2c66affSColin Finck cbGlobal = MultiByteToWideChar(bOem ? CP_OEMCP : CP_ACP,
182c2c66affSColin Finck 0, pwStr, cbStr, NULL, 0) * sizeof(WCHAR);
183c2c66affSColin Finck hGlobal = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbGlobal);
184c2c66affSColin Finck if (!hGlobal)
185c2c66affSColin Finck return NULL;
186c2c66affSColin Finck
187c2c66affSColin Finck pGlobal = GlobalLock(hGlobal);
188c2c66affSColin Finck MultiByteToWideChar(bOem ? CP_OEMCP : CP_ACP,
189c2c66affSColin Finck 0, pwStr, cbStr, pGlobal, cbGlobal);
190c2c66affSColin Finck return pGlobal;
191c2c66affSColin Finck }
192c2c66affSColin Finck
193c2c66affSColin Finck /*
194c2c66affSColin Finck * @implemented
195c2c66affSColin Finck */
196c2c66affSColin Finck HANDLE
197c2c66affSColin Finck WINAPI
GetClipboardData(UINT uFormat)198c2c66affSColin Finck GetClipboardData(UINT uFormat)
199c2c66affSColin Finck {
200c2c66affSColin Finck HANDLE hData = NULL;
201c2c66affSColin Finck PVOID pData = NULL;
202c2c66affSColin Finck DWORD cbData = 0;
203c2c66affSColin Finck GETCLIPBDATA gcd;
204c2c66affSColin Finck
205c2c66affSColin Finck hData = NtUserGetClipboardData(uFormat, &gcd);
206c2c66affSColin Finck if (!hData)
207c2c66affSColin Finck return NULL;
208c2c66affSColin Finck
209da264743Sjimtabor switch (uFormat)
210da264743Sjimtabor {
211da264743Sjimtabor case CF_DSPMETAFILEPICT:
212da264743Sjimtabor case CF_METAFILEPICT:
213da264743Sjimtabor return GdiCreateLocalMetaFilePict(hData);
214da264743Sjimtabor case CF_DSPENHMETAFILE:
215da264743Sjimtabor case CF_ENHMETAFILE:
216da264743Sjimtabor return GdiCreateLocalEnhMetaFile(hData);
217da264743Sjimtabor }
218da264743Sjimtabor
219c2c66affSColin Finck if (gcd.fGlobalHandle)
220c2c66affSColin Finck {
221c2c66affSColin Finck HANDLE hGlobal;
222c2c66affSColin Finck
223c2c66affSColin Finck NtUserCreateLocalMemHandle(hData, NULL, 0, &cbData);
224c2c66affSColin Finck hGlobal = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbData);
225c2c66affSColin Finck pData = GlobalLock(hGlobal);
226c2c66affSColin Finck NtUserCreateLocalMemHandle(hData, pData, cbData, NULL);
227c2c66affSColin Finck hData = hGlobal;
228c2c66affSColin Finck }
229c2c66affSColin Finck
230c2c66affSColin Finck if (gcd.uFmtRet != uFormat)
231c2c66affSColin Finck {
232c2c66affSColin Finck SETCLIPBDATA scd = {FALSE, FALSE};
233c2c66affSColin Finck HANDLE hNewData = NULL;
234c2c66affSColin Finck PVOID pNewData = NULL;
235c2c66affSColin Finck
236c2c66affSColin Finck /* Synthesize requested format */
237c2c66affSColin Finck switch (uFormat)
238c2c66affSColin Finck {
239c2c66affSColin Finck case CF_TEXT:
240c2c66affSColin Finck if (gcd.uFmtRet == CF_UNICODETEXT)
241c2c66affSColin Finck pNewData = IntSynthesizeMultiByte(pData, cbData, uFormat == CF_OEMTEXT);
242c2c66affSColin Finck else // CF_OEMTEXT
243c2c66affSColin Finck OemToCharBuffA(pData, pData, cbData);
244c2c66affSColin Finck break;
245c2c66affSColin Finck case CF_OEMTEXT:
246c2c66affSColin Finck if (gcd.uFmtRet == CF_UNICODETEXT)
247c2c66affSColin Finck pNewData = IntSynthesizeMultiByte(pData, cbData, uFormat == CF_OEMTEXT);
248c2c66affSColin Finck else
249c2c66affSColin Finck CharToOemBuffA(pData, pData, cbData);
250c2c66affSColin Finck break;
251c2c66affSColin Finck case CF_UNICODETEXT:
252c2c66affSColin Finck pNewData = IntSynthesizeWideChar(pData, cbData, gcd.uFmtRet == CF_OEMTEXT);
253c2c66affSColin Finck break;
254c2c66affSColin Finck default:
255c2c66affSColin Finck FIXME("Format: %u != %u\n", uFormat, gcd.uFmtRet);
256c2c66affSColin Finck }
257c2c66affSColin Finck
258c2c66affSColin Finck /* Is it a global handle? */
259c2c66affSColin Finck if (pNewData)
260c2c66affSColin Finck hNewData = GlobalHandle(pNewData);
261c2c66affSColin Finck
262c2c66affSColin Finck if (hNewData)
263c2c66affSColin Finck {
264c2c66affSColin Finck /* Free old data */
265c2c66affSColin Finck if (pData)
266c2c66affSColin Finck {
267c2c66affSColin Finck GlobalUnlock(hData);
268c2c66affSColin Finck GlobalFree(hData);
269c2c66affSColin Finck }
270c2c66affSColin Finck hData = hNewData;
271c2c66affSColin Finck pData = pNewData;
272c2c66affSColin Finck }
273c2c66affSColin Finck
274c2c66affSColin Finck /* Save synthesized format in clipboard */
275c2c66affSColin Finck if (pData)
276c2c66affSColin Finck {
277c2c66affSColin Finck HANDLE hMem;
278c2c66affSColin Finck
279c2c66affSColin Finck scd.fGlobalHandle = TRUE;
280c2c66affSColin Finck hMem = NtUserConvertMemHandle(pData, GlobalSize(hData));
281c2c66affSColin Finck NtUserSetClipboardData(uFormat, hMem, &scd);
282c2c66affSColin Finck }
283c2c66affSColin Finck else if (hData)
284c2c66affSColin Finck NtUserSetClipboardData(uFormat, hData, &scd);
285c2c66affSColin Finck }
286c2c66affSColin Finck
287c2c66affSColin Finck /* Unlock global handle */
288c2c66affSColin Finck if (pData)
289c2c66affSColin Finck GlobalUnlock(hData);
290c2c66affSColin Finck
291c2c66affSColin Finck return hData;
292c2c66affSColin Finck }
293c2c66affSColin Finck
294c2c66affSColin Finck /*
295c2c66affSColin Finck * @implemented
296c2c66affSColin Finck */
297c2c66affSColin Finck HANDLE
298c2c66affSColin Finck WINAPI
SetClipboardData(UINT uFormat,HANDLE hMem)299c2c66affSColin Finck SetClipboardData(UINT uFormat, HANDLE hMem)
300c2c66affSColin Finck {
301c2c66affSColin Finck DWORD dwSize;
302c2c66affSColin Finck HANDLE hGlobal;
303c2c66affSColin Finck LPVOID pMem;
30473558e94Sjimtabor HANDLE hRet = NULL, hTemp;
305c2c66affSColin Finck SETCLIPBDATA scd = {FALSE, FALSE};
306c2c66affSColin Finck
307c2c66affSColin Finck /* Check if this is a delayed rendering */
308c2c66affSColin Finck if (hMem == NULL)
309c2c66affSColin Finck return NtUserSetClipboardData(uFormat, NULL, &scd);
310c2c66affSColin Finck
311c2c66affSColin Finck if (hMem <= (HANDLE)4)
312c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
313c2c66affSColin Finck /* Bitmaps and palette does not use global handles */
314c2c66affSColin Finck else if (uFormat == CF_BITMAP || uFormat == CF_DSPBITMAP || uFormat == CF_PALETTE)
315c2c66affSColin Finck hRet = NtUserSetClipboardData(uFormat, hMem, &scd);
316c2c66affSColin Finck /* Meta files are probably checked for validity */
317da264743Sjimtabor else if (uFormat == CF_DSPMETAFILEPICT || uFormat == CF_METAFILEPICT )
318c2c66affSColin Finck {
31973558e94Sjimtabor hTemp = GdiConvertMetaFilePict( hMem );
32073558e94Sjimtabor hRet = NtUserSetClipboardData(uFormat, hTemp, &scd); // Note : LOL, it returns a BOOL not a HANDLE!!!!
32173558e94Sjimtabor if (hRet == hTemp) hRet = hMem; // If successful "TRUE", return the original handle.
322da264743Sjimtabor }
323da264743Sjimtabor else if (uFormat == CF_DSPENHMETAFILE || uFormat == CF_ENHMETAFILE)
324da264743Sjimtabor {
32573558e94Sjimtabor hTemp = GdiConvertEnhMetaFile( hMem );
32673558e94Sjimtabor hRet = NtUserSetClipboardData(uFormat, hTemp, &scd);
32773558e94Sjimtabor if (hRet == hTemp) hRet = hMem;
328c2c66affSColin Finck }
329c2c66affSColin Finck else
330c2c66affSColin Finck {
331c2c66affSColin Finck /* Some formats accept only global handles, other accept global handles or integer values */
332c2c66affSColin Finck pMem = GlobalLock(hMem);
333c2c66affSColin Finck dwSize = GlobalSize(hMem);
334c2c66affSColin Finck
335c2c66affSColin Finck if (pMem || uFormat == CF_DIB || uFormat == CF_DIBV5 ||
336c2c66affSColin Finck uFormat == CF_DSPTEXT || uFormat == CF_LOCALE ||
337c2c66affSColin Finck uFormat == CF_OEMTEXT || uFormat == CF_TEXT ||
338c2c66affSColin Finck uFormat == CF_UNICODETEXT)
339c2c66affSColin Finck {
340c2c66affSColin Finck if (pMem)
341c2c66affSColin Finck {
342c2c66affSColin Finck /* This is a local memory. Make global memory object */
343c2c66affSColin Finck hGlobal = NtUserConvertMemHandle(pMem, dwSize);
344c2c66affSColin Finck
345c2c66affSColin Finck /* Unlock memory */
346c2c66affSColin Finck GlobalUnlock(hMem);
347c2c66affSColin Finck /* FIXME: free hMem when CloseClipboard is called */
348c2c66affSColin Finck
349c2c66affSColin Finck if (hGlobal)
350c2c66affSColin Finck {
351c2c66affSColin Finck /* Save data */
352c2c66affSColin Finck scd.fGlobalHandle = TRUE;
353c2c66affSColin Finck hRet = NtUserSetClipboardData(uFormat, hGlobal, &scd);
354c2c66affSColin Finck }
355c2c66affSColin Finck
356c2c66affSColin Finck /* On success NtUserSetClipboardData returns pMem
357c2c66affSColin Finck however caller expects us to return hMem */
358c2c66affSColin Finck if (hRet == hGlobal)
359c2c66affSColin Finck hRet = hMem;
360c2c66affSColin Finck }
361c2c66affSColin Finck else
362c2c66affSColin Finck SetLastError(ERROR_INVALID_HANDLE);
363c2c66affSColin Finck }
364c2c66affSColin Finck else
365c2c66affSColin Finck {
366c2c66affSColin Finck /* Save a number */
367c2c66affSColin Finck hRet = NtUserSetClipboardData(uFormat, hMem, &scd);
368c2c66affSColin Finck }
369c2c66affSColin Finck }
370c2c66affSColin Finck
371c2c66affSColin Finck if (!hRet)
372c2c66affSColin Finck ERR("SetClipboardData(%u, %p) failed\n", uFormat, hMem);
373c2c66affSColin Finck
374c2c66affSColin Finck return hRet;
375c2c66affSColin Finck }
376c2c66affSColin Finck
377c2c66affSColin Finck /*
378c2c66affSColin Finck * @unimplemented
379c2c66affSColin Finck */
380c2c66affSColin Finck BOOL
381c2c66affSColin Finck WINAPI
AddClipboardFormatListener(HWND hwnd)382c2c66affSColin Finck AddClipboardFormatListener(HWND hwnd)
383c2c66affSColin Finck {
384c2c66affSColin Finck UNIMPLEMENTED;
385c2c66affSColin Finck return FALSE;
386c2c66affSColin Finck }
387c2c66affSColin Finck /*
388c2c66affSColin Finck * @unimplemented
389c2c66affSColin Finck */
390c2c66affSColin Finck BOOL
391c2c66affSColin Finck WINAPI
RemoveClipboardFormatListener(HWND hwnd)392c2c66affSColin Finck RemoveClipboardFormatListener(HWND hwnd)
393c2c66affSColin Finck {
394c2c66affSColin Finck UNIMPLEMENTED;
395c2c66affSColin Finck return FALSE;
396c2c66affSColin Finck }
397c2c66affSColin Finck
398c2c66affSColin Finck /*
399c2c66affSColin Finck * @unimplemented
400c2c66affSColin Finck */
401c2c66affSColin Finck BOOL
402c2c66affSColin Finck WINAPI
GetUpdatedClipboardFormats(PUINT lpuiFormats,UINT cFormats,PUINT pcFormatsOut)403c2c66affSColin Finck GetUpdatedClipboardFormats(PUINT lpuiFormats,
404c2c66affSColin Finck UINT cFormats,
405c2c66affSColin Finck PUINT pcFormatsOut)
406c2c66affSColin Finck {
407c2c66affSColin Finck UNIMPLEMENTED;
408c2c66affSColin Finck return FALSE;
409c2c66affSColin Finck }
410