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