Misc addendum to CORE-14271 (#1529)
[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] = ANSI_NULL;
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;
101 UNICODE_STRING usFormat = {0};
102
103 if (lpszFormat == NULL)
104 {
105 SetLastError(ERROR_INVALID_PARAMETER);
106 return 0;
107 }
108
109 if (*lpszFormat == ANSI_NULL)
110 {
111 SetLastError(ERROR_INVALID_NAME);
112 return 0;
113 }
114
115 if (!RtlCreateUnicodeStringFromAsciiz(&usFormat, lpszFormat))
116 {
117 // FIXME: Shouldn't we 'SetLastError(ERROR_NOT_ENOUGH_MEMORY);'?
118 return 0;
119 }
120
121 ret = NtUserRegisterWindowMessage(&usFormat); //(LPCWSTR)
122
123 RtlFreeUnicodeString(&usFormat);
124
125 return ret;
126 }
127
128 /*
129 * @implemented
130 */
131 UINT
132 WINAPI
133 RegisterClipboardFormatW(LPCWSTR lpszFormat)
134 {
135 UNICODE_STRING usFormat = {0};
136
137 if (lpszFormat == NULL)
138 {
139 SetLastError(ERROR_INVALID_PARAMETER);
140 return 0;
141 }
142
143 if (*lpszFormat == UNICODE_NULL)
144 {
145 SetLastError(ERROR_INVALID_NAME);
146 return 0;
147 }
148
149 RtlInitUnicodeString(&usFormat, lpszFormat);
150 return NtUserRegisterWindowMessage(&usFormat);
151 }
152
153 static PVOID WINAPI
154 IntSynthesizeMultiByte(PVOID pwStr, DWORD cbStr, BOOL bOem)
155 {
156 HANDLE hGlobal;
157 PVOID pGlobal;
158 INT cbGlobal;
159
160 cbGlobal = WideCharToMultiByte(bOem ? CP_OEMCP : CP_ACP,
161 0, pwStr, cbStr / sizeof(WCHAR),
162 NULL, 0, NULL, NULL);
163 hGlobal = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbGlobal);
164 if (!hGlobal)
165 return NULL;
166
167 pGlobal = GlobalLock(hGlobal);
168 WideCharToMultiByte(bOem ? CP_OEMCP : CP_ACP,
169 0, pwStr, cbStr / sizeof(WCHAR),
170 pGlobal, cbGlobal, NULL, NULL);
171 return pGlobal;
172 }
173
174 static PVOID WINAPI
175 IntSynthesizeWideChar(PVOID pwStr, DWORD cbStr, BOOL bOem)
176 {
177 HANDLE hGlobal;
178 PVOID pGlobal;
179 INT cbGlobal;
180
181 cbGlobal = MultiByteToWideChar(bOem ? CP_OEMCP : CP_ACP,
182 0, pwStr, cbStr, NULL, 0) * sizeof(WCHAR);
183 hGlobal = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbGlobal);
184 if (!hGlobal)
185 return NULL;
186
187 pGlobal = GlobalLock(hGlobal);
188 MultiByteToWideChar(bOem ? CP_OEMCP : CP_ACP,
189 0, pwStr, cbStr, pGlobal, cbGlobal);
190 return pGlobal;
191 }
192
193 /*
194 * @implemented
195 */
196 HANDLE
197 WINAPI
198 GetClipboardData(UINT uFormat)
199 {
200 HANDLE hData = NULL;
201 PVOID pData = NULL;
202 DWORD cbData = 0;
203 GETCLIPBDATA gcd;
204
205 hData = NtUserGetClipboardData(uFormat, &gcd);
206 if (!hData)
207 return NULL;
208
209 switch (uFormat)
210 {
211 case CF_DSPMETAFILEPICT:
212 case CF_METAFILEPICT:
213 return GdiCreateLocalMetaFilePict(hData);
214 case CF_DSPENHMETAFILE:
215 case CF_ENHMETAFILE:
216 return GdiCreateLocalEnhMetaFile(hData);
217 }
218
219 if (gcd.fGlobalHandle)
220 {
221 HANDLE hGlobal;
222
223 NtUserCreateLocalMemHandle(hData, NULL, 0, &cbData);
224 hGlobal = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbData);
225 pData = GlobalLock(hGlobal);
226 NtUserCreateLocalMemHandle(hData, pData, cbData, NULL);
227 hData = hGlobal;
228 }
229
230 if (gcd.uFmtRet != uFormat)
231 {
232 SETCLIPBDATA scd = {FALSE, FALSE};
233 HANDLE hNewData = NULL;
234 PVOID pNewData = NULL;
235
236 /* Synthesize requested format */
237 switch (uFormat)
238 {
239 case CF_TEXT:
240 if (gcd.uFmtRet == CF_UNICODETEXT)
241 pNewData = IntSynthesizeMultiByte(pData, cbData, uFormat == CF_OEMTEXT);
242 else // CF_OEMTEXT
243 OemToCharBuffA(pData, pData, cbData);
244 break;
245 case CF_OEMTEXT:
246 if (gcd.uFmtRet == CF_UNICODETEXT)
247 pNewData = IntSynthesizeMultiByte(pData, cbData, uFormat == CF_OEMTEXT);
248 else
249 CharToOemBuffA(pData, pData, cbData);
250 break;
251 case CF_UNICODETEXT:
252 pNewData = IntSynthesizeWideChar(pData, cbData, gcd.uFmtRet == CF_OEMTEXT);
253 break;
254 default:
255 FIXME("Format: %u != %u\n", uFormat, gcd.uFmtRet);
256 }
257
258 /* Is it a global handle? */
259 if (pNewData)
260 hNewData = GlobalHandle(pNewData);
261
262 if (hNewData)
263 {
264 /* Free old data */
265 if (pData)
266 {
267 GlobalUnlock(hData);
268 GlobalFree(hData);
269 }
270 hData = hNewData;
271 pData = pNewData;
272 }
273
274 /* Save synthesized format in clipboard */
275 if (pData)
276 {
277 HANDLE hMem;
278
279 scd.fGlobalHandle = TRUE;
280 hMem = NtUserConvertMemHandle(pData, GlobalSize(hData));
281 NtUserSetClipboardData(uFormat, hMem, &scd);
282 }
283 else if (hData)
284 NtUserSetClipboardData(uFormat, hData, &scd);
285 }
286
287 /* Unlock global handle */
288 if (pData)
289 GlobalUnlock(hData);
290
291 return hData;
292 }
293
294 /*
295 * @implemented
296 */
297 HANDLE
298 WINAPI
299 SetClipboardData(UINT uFormat, HANDLE hMem)
300 {
301 DWORD dwSize;
302 HANDLE hGlobal;
303 LPVOID pMem;
304 HANDLE hRet = NULL, hTemp;
305 SETCLIPBDATA scd = {FALSE, FALSE};
306
307 /* Check if this is a delayed rendering */
308 if (hMem == NULL)
309 return NtUserSetClipboardData(uFormat, NULL, &scd);
310
311 if (hMem <= (HANDLE)4)
312 SetLastError(ERROR_INVALID_PARAMETER);
313 /* Bitmaps and palette does not use global handles */
314 else if (uFormat == CF_BITMAP || uFormat == CF_DSPBITMAP || uFormat == CF_PALETTE)
315 hRet = NtUserSetClipboardData(uFormat, hMem, &scd);
316 /* Meta files are probably checked for validity */
317 else if (uFormat == CF_DSPMETAFILEPICT || uFormat == CF_METAFILEPICT )
318 {
319 hTemp = GdiConvertMetaFilePict( hMem );
320 hRet = NtUserSetClipboardData(uFormat, hTemp, &scd); // Note : LOL, it returns a BOOL not a HANDLE!!!!
321 if (hRet == hTemp) hRet = hMem; // If successful "TRUE", return the original handle.
322 }
323 else if (uFormat == CF_DSPENHMETAFILE || uFormat == CF_ENHMETAFILE)
324 {
325 hTemp = GdiConvertEnhMetaFile( hMem );
326 hRet = NtUserSetClipboardData(uFormat, hTemp, &scd);
327 if (hRet == hTemp) hRet = hMem;
328 }
329 else
330 {
331 /* Some formats accept only global handles, other accept global handles or integer values */
332 pMem = GlobalLock(hMem);
333 dwSize = GlobalSize(hMem);
334
335 if (pMem || uFormat == CF_DIB || uFormat == CF_DIBV5 ||
336 uFormat == CF_DSPTEXT || uFormat == CF_LOCALE ||
337 uFormat == CF_OEMTEXT || uFormat == CF_TEXT ||
338 uFormat == CF_UNICODETEXT)
339 {
340 if (pMem)
341 {
342 /* This is a local memory. Make global memory object */
343 hGlobal = NtUserConvertMemHandle(pMem, dwSize);
344
345 /* Unlock memory */
346 GlobalUnlock(hMem);
347 /* FIXME: free hMem when CloseClipboard is called */
348
349 if (hGlobal)
350 {
351 /* Save data */
352 scd.fGlobalHandle = TRUE;
353 hRet = NtUserSetClipboardData(uFormat, hGlobal, &scd);
354 }
355
356 /* On success NtUserSetClipboardData returns pMem
357 however caller expects us to return hMem */
358 if (hRet == hGlobal)
359 hRet = hMem;
360 }
361 else
362 SetLastError(ERROR_INVALID_HANDLE);
363 }
364 else
365 {
366 /* Save a number */
367 hRet = NtUserSetClipboardData(uFormat, hMem, &scd);
368 }
369 }
370
371 if (!hRet)
372 ERR("SetClipboardData(%u, %p) failed\n", uFormat, hMem);
373
374 return hRet;
375 }
376
377 /*
378 * @unimplemented
379 */
380 BOOL
381 WINAPI
382 AddClipboardFormatListener(HWND hwnd)
383 {
384 UNIMPLEMENTED;
385 return FALSE;
386 }
387 /*
388 * @unimplemented
389 */
390 BOOL
391 WINAPI
392 RemoveClipboardFormatListener(HWND hwnd)
393 {
394 UNIMPLEMENTED;
395 return FALSE;
396 }
397
398 /*
399 * @unimplemented
400 */
401 BOOL
402 WINAPI
403 GetUpdatedClipboardFormats(PUINT lpuiFormats,
404 UINT cFormats,
405 PUINT pcFormatsOut)
406 {
407 UNIMPLEMENTED;
408 return FALSE;
409 }