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