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 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 } 410