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