Sync with trunk r65656.
[reactos.git] / win32ss / user / user32 / windows / clipboard.c
1 /*
2 * PROJECT: ReactOS user32.dll
3 * FILE: lib/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 /* INCLUDES ******************************************************************/
13
14 #include <user32.h>
15
16 #define NDEBUG
17
18 #include <wine/debug.h>
19 WINE_DEFAULT_DEBUG_CHANNEL(user32);
20
21 #define QUERY_SIZE 0
22
23 /* FUNCTIONS *****************************************************************/
24
25 /*
26 * @implemented
27 */
28 BOOL
29 WINAPI
30 OpenClipboard(HWND hWndNewOwner)
31 {
32 return NtUserOpenClipboard(hWndNewOwner, 0);
33 }
34
35 /*
36 * @implemented
37 */
38 UINT
39 WINAPI
40 EnumClipboardFormats(UINT format)
41 {
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 if (gcd.fGlobalHandle)
212 {
213 HANDLE hGlobal;
214
215 NtUserCreateLocalMemHandle(hData, NULL, 0, &cbData);
216 hGlobal = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbData);
217 pData = GlobalLock(hGlobal);
218 NtUserCreateLocalMemHandle(hData, pData, cbData, NULL);
219 hData = hGlobal;
220 }
221
222 if (gcd.uFmtRet != uFormat)
223 {
224 SETCLIPBDATA scd = {FALSE, FALSE};
225 HANDLE hNewData = NULL;
226 PVOID pNewData = NULL;
227
228 /* Synthesize requested format */
229 switch (uFormat)
230 {
231 case CF_TEXT:
232 if (gcd.uFmtRet == CF_UNICODETEXT)
233 pNewData = IntSynthesizeMultiByte(pData, cbData, uFormat == CF_OEMTEXT);
234 else // CF_OEMTEXT
235 OemToCharBuffA(pData, pData, cbData);
236 break;
237 case CF_OEMTEXT:
238 if (gcd.uFmtRet == CF_UNICODETEXT)
239 pNewData = IntSynthesizeMultiByte(pData, cbData, uFormat == CF_OEMTEXT);
240 else
241 CharToOemBuffA(pData, pData, cbData);
242 break;
243 case CF_UNICODETEXT:
244 pNewData = IntSynthesizeWideChar(pData, cbData, gcd.uFmtRet == CF_OEMTEXT);
245 break;
246 default:
247 FIXME("Format: %u != %u\n", uFormat, gcd.uFmtRet);
248 }
249
250 /* Is it a global handle? */
251 if (pNewData)
252 hNewData = GlobalHandle(pNewData);
253
254 if (hNewData)
255 {
256 /* Free old data */
257 if (pData)
258 {
259 GlobalUnlock(hData);
260 GlobalFree(hData);
261 }
262 hData = hNewData;
263 pData = pNewData;
264 }
265
266 /* Save synthesized format in clibboard */
267 if (pData)
268 {
269 HANDLE hMem;
270
271 scd.fGlobalHandle = TRUE;
272 hMem = NtUserConvertMemHandle(pData, GlobalSize(hData));
273 NtUserSetClipboardData(uFormat, hMem, &scd);
274 }
275 else if (hData)
276 NtUserSetClipboardData(uFormat, hData, &scd);
277 }
278
279 /* Unlock global handle */
280 if (pData)
281 GlobalUnlock(hData);
282
283 return hData;
284 }
285
286 /*
287 * @implemented
288 */
289 HANDLE
290 WINAPI
291 SetClipboardData(UINT uFormat, HANDLE hMem)
292 {
293 DWORD dwSize;
294 HANDLE hGlobal;
295 LPVOID pMem;
296 HANDLE hRet = NULL;
297 SETCLIPBDATA scd = {FALSE, FALSE};
298
299 /* Check if this is delayed render */
300 if (hMem == NULL)
301 return NtUserSetClipboardData(uFormat, NULL, &scd);
302
303 if (hMem <= (HANDLE)4)
304 SetLastError(ERROR_INVALID_PARAMETER);
305 /* Bitmaps and palette does not use global handles */
306 else if (uFormat == CF_BITMAP || uFormat == CF_DSPBITMAP || uFormat == CF_PALETTE)
307 hRet = NtUserSetClipboardData(uFormat, hMem, &scd);
308 /* Meta files are probably checked for validity */
309 else if (uFormat == CF_DSPMETAFILEPICT || uFormat == CF_METAFILEPICT ||
310 uFormat == CF_DSPENHMETAFILE || uFormat == CF_ENHMETAFILE)
311 hRet = NULL; // not supported yet
312 else
313 {
314 /* Some formats accept only global handles, other accept global handles or integer values */
315 pMem = GlobalLock(hMem);
316 dwSize = GlobalSize(hMem);
317
318 if (pMem || uFormat == CF_DIB || uFormat == CF_DIBV5 ||
319 uFormat == CF_DSPTEXT || uFormat == CF_LOCALE ||
320 uFormat == CF_OEMTEXT || uFormat == CF_TEXT ||
321 uFormat == CF_UNICODETEXT)
322 {
323 if (pMem)
324 {
325 /* This is a local memory. Make global memory object */
326 hGlobal = NtUserConvertMemHandle(pMem, dwSize);
327
328 /* Unlock memory */
329 GlobalUnlock(hMem);
330 /* FIXME: free hMem when CloseClipboard is called */
331
332 if (hGlobal)
333 {
334 /* Save data */
335 scd.fGlobalHandle = TRUE;
336 hRet = NtUserSetClipboardData(uFormat, hGlobal, &scd);
337 }
338
339 /* On success NtUserSetClipboardData returns pMem
340 however caller expects us to return hMem */
341 if (hRet == hGlobal)
342 hRet = hMem;
343 }
344 else
345 SetLastError(ERROR_INVALID_HANDLE);
346 }
347 else
348 {
349 /* Save a number */
350 hRet = NtUserSetClipboardData(uFormat, hMem, &scd);
351 }
352 }
353
354 if (!hRet)
355 ERR("SetClipboardData(%u, %p) failed\n", uFormat, hMem);
356
357 return hRet;
358 }
359
360 /*
361 * @unimplemented
362 */
363 BOOL
364 WINAPI
365 AddClipboardFormatListener(HWND hwnd)
366 {
367 UNIMPLEMENTED;
368 return FALSE;
369 }
370 /*
371 * @unimplemented
372 */
373 BOOL
374 WINAPI
375 RemoveClipboardFormatListener(HWND hwnd)
376 {
377 UNIMPLEMENTED;
378 return FALSE;
379 }
380
381 /*
382 * @unimplemented
383 */
384 BOOL
385 WINAPI
386 GetUpdatedClipboardFormats(PUINT lpuiFormats,
387 UINT cFormats,
388 PUINT pcFormatsOut)
389 {
390 UNIMPLEMENTED;
391 return FALSE;
392 }