1 /*
   2  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "awt.h"
  27 #include "awt_DataTransferer.h"
  28 #include "awt_DnDDT.h"
  29 #include "awt_TextComponent.h"
  30 #include <shlobj.h>
  31 #include <shellapi.h>
  32 #include <sun_awt_datatransfer_DataTransferer.h>
  33 #include <sun_awt_windows_WDataTransferer.h>
  34 
  35 #include "locale_str.h"
  36 
  37 #define GALLOCFLG (GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT)
  38 #define WIN_TO_JAVA_PIXEL(r, g, b) (0xFF000000 | (r) << 16 | (g) << 8  | (b) << 0)
  39 
  40 DECLARE_JAVA_CLASS(dataTransfererClazz, "sun/awt/datatransfer/DataTransferer");
  41 
  42 jobject
  43 AwtDataTransferer::GetDataTransferer(JNIEnv* env) {
  44     DECLARE_STATIC_OBJECT_JAVA_METHOD(getInstanceMethodID, dataTransfererClazz,
  45                                       "getInstance",
  46                                       "()Lsun/awt/datatransfer/DataTransferer;");
  47     return env->CallStaticObjectMethod(clazz, getInstanceMethodID);
  48 }
  49 
  50 jbyteArray
  51 AwtDataTransferer::ConvertData(JNIEnv* env, jobject source, jobject contents,
  52                                jlong format, jobject formatMap) {
  53     jobject transferer = GetDataTransferer(env);
  54 
  55     if (!JNU_IsNull(env, transferer)) {
  56         jbyteArray ret = NULL;
  57         DECLARE_OBJECT_JAVA_METHOD(convertDataMethodID, dataTransfererClazz,
  58                                    "convertData",
  59                                    "(Ljava/lang/Object;Ljava/awt/datatransfer/Transferable;JLjava/util/Map;Z)[B");
  60 
  61         ret = (jbyteArray)env->CallObjectMethod(transferer, convertDataMethodID,
  62                                                 source, contents, format,
  63                                                 formatMap, AwtToolkit::IsMainThread());
  64 
  65         if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) {
  66             env->ExceptionDescribe();
  67             env->ExceptionClear();
  68         }
  69 
  70         env->DeleteLocalRef(transferer);
  71 
  72         return ret;
  73     } else {
  74         return NULL;
  75     }
  76 }
  77 
  78 jobject
  79 AwtDataTransferer::ConcatData(JNIEnv* env, jobject obj1, jobject obj2) {
  80     jobject transferer = GetDataTransferer(env);
  81 
  82     if (!JNU_IsNull(env, transferer)) {
  83         jobject ret = NULL;
  84         DECLARE_OBJECT_JAVA_METHOD(concatDataMethodID, dataTransfererClazz,
  85                                    "concatData",
  86                                    "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
  87 
  88         ret = env->CallObjectMethod(transferer, concatDataMethodID, obj1, obj2);
  89 
  90         if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) {
  91             env->ExceptionDescribe();
  92             env->ExceptionClear();
  93         }
  94 
  95         env->DeleteLocalRef(transferer);
  96 
  97         return ret;
  98     } else {
  99         return NULL;
 100     }
 101 }
 102 
 103 /**
 104  * This routine retrieves palette entries from enhanced metafile or
 105  * a logical color palette, builds appropriate LOGPALETTE structure,
 106  * writes it into a created Java byte array and returns a local
 107  * reference to the array.
 108  * This routine is used for image data transfer.
 109  *
 110  * @param hGdiObj - a handle to the GDI object to retrieve palette entries from,
 111  *        it can be a handle to either a logical color palette (OBJ_PAL type)
 112  *        or an enhanced metafile (OBJ_ENHMETAFILE). If it is neither of these
 113  *        types the routine fails(see bFailSafe).
 114  * @param dwGdiObjType - a type of the passed GDI object. It should be specified
 115  *        if the type of the passed GDI object is known to the caller. Otherwise
 116  *        pass 0.
 117  * @param bFailSafe - if FALSE, the routine will return NULL in case of failure,
 118  *        otherwise it will return an array with empty LOGPALETTE structure
 119  *        in case of failure.
 120  * @return a local reference to Java byte array which contains LOGPALETTE
 121  *        structure which defines a logical color palette or a palette of
 122  *        an enhanced metafile.
 123  */
 124 jbyteArray
 125 AwtDataTransferer::GetPaletteBytes(HGDIOBJ hGdiObj, DWORD dwGdiObjType,
 126                                    BOOL bFailSafe) {
 127 
 128     if (hGdiObj == NULL) {
 129         dwGdiObjType = 0;
 130     } else if (dwGdiObjType == 0) {
 131         dwGdiObjType = ::GetObjectType(hGdiObj);
 132     } else {
 133         DASSERT(::GetObjectType(hGdiObj) == dwGdiObjType);
 134     }
 135 
 136     if (!bFailSafe && dwGdiObjType == 0) {
 137         return NULL;
 138     }
 139 
 140     UINT nEntries = 0;
 141 
 142     switch (dwGdiObjType) {
 143     case OBJ_PAL:
 144         nEntries =
 145             ::GetPaletteEntries((HPALETTE)hGdiObj, 0, 0, NULL);
 146         break;
 147     case OBJ_ENHMETAFILE:
 148         nEntries =
 149             ::GetEnhMetaFilePaletteEntries((HENHMETAFILE)hGdiObj, 0, NULL);
 150         break;
 151     }
 152 
 153     if (!bFailSafe && (nEntries == 0 || nEntries == GDI_ERROR)) {
 154         return NULL;
 155     }
 156 
 157     JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 158     jsize size = sizeof(LOGPALETTE) + nEntries * sizeof(PALETTEENTRY);
 159 
 160     jbyteArray paletteBytes = env->NewByteArray(size);
 161     if (JNU_IsNull(env, paletteBytes)) {
 162         throw std::bad_alloc();
 163     }
 164 
 165     LOGPALETTE* pLogPalette =
 166         (LOGPALETTE*)env->GetPrimitiveArrayCritical(paletteBytes, NULL);
 167     PALETTEENTRY* pPalEntries = (PALETTEENTRY*)pLogPalette->palPalEntry;
 168 
 169     pLogPalette->palVersion = 0x300;
 170     pLogPalette->palNumEntries = nEntries;
 171 
 172     switch (dwGdiObjType) {
 173     case OBJ_PAL:
 174         VERIFY(::GetPaletteEntries((HPALETTE)hGdiObj, 0, nEntries,
 175                                    pPalEntries) == nEntries);
 176         break;
 177     case OBJ_ENHMETAFILE:
 178         VERIFY(::GetEnhMetaFilePaletteEntries((HENHMETAFILE)hGdiObj, nEntries,
 179                                               pPalEntries) == nEntries);
 180         break;
 181     }
 182 
 183     env->ReleasePrimitiveArrayCritical(paletteBytes, pLogPalette, 0);
 184 
 185     return paletteBytes;
 186 }
 187 
 188 jbyteArray
 189 AwtDataTransferer::LCIDToTextEncoding(JNIEnv *env, LCID lcid) {
 190     LANGID langID = LANGIDFROMLCID(lcid);
 191     const char *encoding = getEncodingFromLangID(langID);
 192 
 193     // Warning C4244.
 194     // Cast SIZE_T (__int64 on 64-bit/unsigned int on 32-bit)
 195     // to jsize (long).
 196     // We assume that the encoding name length cannot exceed INT_MAX.
 197     jsize length = (jsize)strlen(encoding);
 198 
 199     jbyteArray retval = env->NewByteArray(length);
 200     if (retval == NULL) {
 201         throw std::bad_alloc();
 202     }
 203     env->SetByteArrayRegion(retval, 0, length, (jbyte *)encoding);
 204     free((void *)encoding);
 205     return retval;
 206 }
 207 
 208 static VOID CALLBACK
 209 IdleFunc() {
 210     /*
 211      * Fix for 4485987 and 4669873.
 212      * If IdleFunc is a noop, the secondary message pump occasionally occupies
 213      * all processor time and causes drag freezes. GetQueueStatus is needed to
 214      * mark all messages that are currently in the queue as old, otherwise
 215      * WaitMessage will return immediatelly as we selectively get messages from
 216      * the queue.
 217      */
 218     ::WaitMessage();
 219     ::GetQueueStatus(QS_ALLINPUT);
 220 }
 221 
 222 static BOOL CALLBACK
 223 PeekMessageFunc(MSG& msg) {
 224     return ::PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE) ||
 225            ::PeekMessage(&msg, NULL, WM_AWT_INVOKE_METHOD, WM_AWT_INVOKE_METHOD, PM_REMOVE) ||
 226            ::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE);
 227 }
 228 
 229 void
 230 AwtDataTransferer::SecondaryMessageLoop() {
 231     DASSERT(AwtToolkit::MainThread() == ::GetCurrentThreadId());
 232 
 233     AwtToolkit::GetInstance().MessageLoop(IdleFunc,
 234                                           PeekMessageFunc);
 235 }
 236 
 237 extern "C" {
 238 
 239 /*
 240  * Class:     sun_awt_datatransfer_DataTransferer
 241  * Method:    draqQueryFile
 242  * Signature: ([B)[Ljava/lang/String;
 243  */
 244 JNIEXPORT jobjectArray JNICALL
 245 Java_sun_awt_windows_WDataTransferer_dragQueryFile
 246     (JNIEnv *env, jobject obj, jbyteArray bytes)
 247 {
 248     TRY;
 249 
 250     /*
 251      * Fix for the BugTraq ID 4327064 - inter-jvm DnD crashes the droping jvm.
 252      * On Win9X DragQueryFile() doesn't accept a pointer to the local help as the first
 253      * argument, so we should dump the bits into global memory.
 254      */
 255     UINT size = env->GetArrayLength(bytes);
 256     HGLOBAL hglobal = NULL;
 257     jbyte *bBytes = NULL;
 258     HDROP hdrop = NULL;
 259     LPTSTR buffer = NULL;
 260 
 261     hglobal = ::GlobalAlloc(GALLOCFLG, size);
 262 
 263     if (hglobal == NULL) {
 264         throw std::bad_alloc();
 265     }
 266 
 267     try {
 268 
 269         bBytes = (jbyte*)::GlobalLock(hglobal);
 270         env->GetByteArrayRegion(bytes, 0, size, bBytes);
 271 
 272         hdrop = (HDROP)bBytes;
 273 
 274         UINT nFilenames = ::DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0);
 275 
 276         jclass str_clazz = env->FindClass("java/lang/String");
 277         DASSERT(str_clazz != NULL);
 278         jobjectArray filenames = env->NewObjectArray(nFilenames, str_clazz,
 279                                                      NULL);
 280         if (filenames == NULL) {
 281             throw std::bad_alloc();
 282         }
 283 
 284         UINT bufsize = 512; // in characters, not in bytes
 285         buffer = (LPTSTR)safe_Malloc(bufsize*sizeof(TCHAR));
 286 
 287         for (UINT i = 0; i < nFilenames; i++) {
 288             UINT size = ::DragQueryFile(hdrop, i, NULL, 0);
 289             if (size > bufsize) {
 290                 bufsize = size;
 291                 buffer = (LPTSTR)safe_Realloc(buffer, bufsize*sizeof(TCHAR));
 292             }
 293             ::DragQueryFile(hdrop, i, buffer, bufsize);
 294 
 295             jstring name = JNU_NewStringPlatform(env, buffer);
 296             if (name == NULL) {
 297                 throw std::bad_alloc();
 298             }
 299 
 300             env->SetObjectArrayElement(filenames, i, name);
 301         }
 302 
 303         free(buffer);
 304         ::GlobalUnlock(hglobal);
 305         ::GlobalFree(hglobal);
 306         return filenames;
 307 
 308     } catch (std::bad_alloc&) {
 309         free(buffer);
 310         ::GlobalUnlock(hglobal);
 311         ::GlobalFree(hglobal);
 312         throw;
 313     }
 314 
 315     CATCH_BAD_ALLOC_RET(NULL);
 316 }
 317 
 318 /*
 319  * Class:     sun_awt_windows_WDataTransferer
 320  * Method:    platformImageBytesToImageData
 321  * Signature: ([BI)[I
 322  */
 323 JNIEXPORT jintArray JNICALL
 324 Java_sun_awt_windows_WDataTransferer_platformImageBytesToImageData(
 325     JNIEnv *env, jobject self, jbyteArray bytes, jlong format) {
 326 
 327     TRY;
 328 
 329     HDC hdc = NULL;
 330 
 331     LOGPALETTE* pLogPalette = NULL;
 332     WORD uPaletteEntries = 0;
 333     SIZE_T uOffset = 0;
 334     HPALETTE hPalette = NULL;
 335     HPALETTE hOldPalette = NULL;
 336 
 337     BITMAPINFO* pSrcBmi = NULL;
 338     BITMAPINFOHEADER* pSrcBmih = NULL;
 339     LPVOID pSrcBits = NULL;
 340     BITMAPINFO* pDstBmi = NULL;
 341     BITMAPINFOHEADER* pDstBmih = NULL;
 342     LPVOID pDstBits = NULL;
 343 
 344     LPBYTE lpEnhMetaFileBits = NULL;
 345     HENHMETAFILE hEnhMetaFile = NULL;
 346 
 347     HBITMAP hDibSection = NULL;
 348     HBITMAP hOldBitmap = NULL;
 349     jintArray buffer = NULL;
 350     LONG width = 0;
 351     LONG height = 0;
 352     int numPixels = 0;
 353 
 354     if (JNU_IsNull(env, bytes)) {
 355         return NULL;
 356     }
 357 
 358     jsize size = env->GetArrayLength(bytes);
 359     if (size == 0) {
 360         return NULL;
 361     }
 362 
 363     jbyte* bBytes = (jbyte*)safe_Malloc(size * sizeof(jbyte));
 364 
 365     try {
 366 
 367         env->GetByteArrayRegion(bytes, 0, size, bBytes);
 368 
 369         pLogPalette = (LOGPALETTE*)bBytes;
 370         uPaletteEntries = pLogPalette->palNumEntries;
 371         uOffset = sizeof(LOGPALETTE) + uPaletteEntries * sizeof(PALETTEENTRY);
 372         DASSERT(uOffset < (SIZE_T)size);
 373 
 374         if (uPaletteEntries == 0) {
 375             pLogPalette = NULL;
 376         }
 377 
 378         hdc = ::CreateCompatibleDC(NULL);
 379         if (hdc == NULL) {
 380             free(bBytes);
 381             return NULL;
 382         }
 383 
 384         switch (format) {
 385         case CF_DIB:
 386 
 387             pSrcBmi = (BITMAPINFO*)((LPSTR)bBytes + uOffset);
 388             pSrcBmih = &pSrcBmi->bmiHeader;
 389 
 390             width = pSrcBmih->biWidth;
 391             height = abs(pSrcBmih->biHeight);
 392 
 393             {
 394                 DWORD nColorEntries = 0;
 395 
 396                 switch (pSrcBmih->biBitCount) {
 397                 case  0: nColorEntries = 0; break;
 398                 case  1: nColorEntries = 2; break;
 399                 case  4:
 400                 case  8:
 401                     nColorEntries = (pSrcBmih->biClrUsed != 0) ?
 402                         pSrcBmih->biClrUsed : (1 << pSrcBmih->biBitCount);
 403                     break;
 404                 case 16:
 405                 case 24:
 406                 case 32:
 407                     nColorEntries = pSrcBmih->biClrUsed;
 408                     // If biBitCount is 16 or 32 and biCompression is
 409                     // BI_BITFIELDS the color table will be prefixed with
 410                     // three DWORD color masks.
 411                     if (pSrcBmih->biCompression == BI_BITFIELDS &&
 412                         (pSrcBmih->biBitCount == 16 ||
 413                          pSrcBmih->biBitCount == 32)) {
 414                         nColorEntries += 3;
 415                     }
 416                     break;
 417                 default:
 418                     // The header is probably corrupted.
 419                     // Fail immediatelly to avoid memory access violation.
 420                     free(bBytes);
 421                     ::DeleteDC(hdc);
 422                     return NULL;
 423                 }
 424 
 425                 pSrcBits = (LPSTR)pSrcBmi + pSrcBmih->biSize
 426                     + nColorEntries * sizeof(RGBQUAD);
 427             }
 428             break;
 429         case CF_ENHMETAFILE:
 430         case CF_METAFILEPICT:
 431             lpEnhMetaFileBits = (BYTE*)bBytes + uOffset;
 432             // Warning C4244. size is jsize, uOffset is SIZE_T.
 433             // We assert that size > uOffset, so it is safe to cast to jsize.
 434             hEnhMetaFile = ::SetEnhMetaFileBits(size - (jsize)uOffset,
 435                                                 lpEnhMetaFileBits);
 436             DASSERT(hEnhMetaFile != NULL);
 437 
 438             {
 439                 UINT uHeaderSize =
 440                     ::GetEnhMetaFileHeader(hEnhMetaFile, 0, NULL);
 441                 DASSERT(uHeaderSize != 0);
 442                 ENHMETAHEADER* lpemh = (ENHMETAHEADER*)safe_Malloc(uHeaderSize);
 443                 VERIFY(::GetEnhMetaFileHeader(hEnhMetaFile, uHeaderSize,
 444                                               lpemh) == uHeaderSize);
 445                 LPRECTL lpFrame = &lpemh->rclFrame;
 446                 POINT p = { abs(lpFrame->right - lpFrame->left),
 447                             abs(lpFrame->bottom - lpFrame->top) };
 448                 VERIFY(::SaveDC(hdc));
 449                 VERIFY(::SetMapMode(hdc, MM_HIMETRIC));
 450                 VERIFY(::LPtoDP(hdc, &p, 1));
 451                 VERIFY(::RestoreDC(hdc, -1));
 452                 width = p.x;
 453                 height = -p.y;
 454 
 455                 free(lpemh);
 456             }
 457             break;
 458         default:
 459             DASSERT(FALSE); // Other formats are not supported yet.
 460             free(bBytes);
 461             ::DeleteDC(hdc);
 462             return NULL;
 463         }
 464 
 465         // JNI doesn't allow to store more than INT_MAX in a single array.
 466         // We report conversion failure in this case.
 467         if (width * height > INT_MAX) {
 468             free(bBytes);
 469             ::DeleteDC(hdc);
 470             return NULL;
 471         }
 472 
 473         numPixels = width * height;
 474 
 475         if (pLogPalette != NULL) {
 476             hPalette = ::CreatePalette(pLogPalette);
 477             if (hPalette == NULL) {
 478                 free(bBytes);
 479                 ::DeleteDC(hdc);
 480                 return NULL;
 481             }
 482             hOldPalette = ::SelectPalette(hdc, hPalette, FALSE);
 483             ::RealizePalette(hdc);
 484         }
 485 
 486         // allocate memory for BITMAPINFO
 487         pDstBmi = (BITMAPINFO *)safe_Calloc(1, sizeof(BITMAPINFO));
 488         pDstBmih = &pDstBmi->bmiHeader;
 489 
 490         static const int BITS_PER_PIXEL = 32;
 491 
 492         // prepare BITMAPINFO for a 32-bit RGB bitmap
 493         pDstBmih->biSize = sizeof(BITMAPINFOHEADER);
 494         pDstBmih->biWidth = width;
 495         pDstBmih->biHeight = -height; // negative height means a top-down DIB
 496         pDstBmih->biPlanes = 1;
 497         pDstBmih->biBitCount = BITS_PER_PIXEL;
 498         pDstBmih->biCompression = BI_RGB;
 499         // NOTE: MSDN says that biSizeImage may be set to 0 for BI_RGB bitmaps,
 500         // but this causes CreateDIBSection to allocate zero-size memory block
 501         // for DIB data. It works okay when biSizeImage is explicitly specified.
 502         pDstBmih->biSizeImage = width * height * (BITS_PER_PIXEL >> 3);
 503 
 504         hDibSection = ::CreateDIBSection(hdc, (BITMAPINFO*)pDstBmi,
 505                                          DIB_RGB_COLORS, &pDstBits,
 506                                          NULL, 0);
 507 
 508         if (hDibSection == NULL) {
 509             free(pDstBmi); pDstBmi = NULL;
 510             if (hPalette != NULL) {
 511                 VERIFY(::SelectPalette(hdc, hOldPalette, FALSE) != NULL);
 512                 hOldPalette = NULL;
 513                 VERIFY(::DeleteObject(hPalette)); hPalette = NULL;
 514             }
 515             VERIFY(::DeleteDC(hdc)); hdc = NULL;
 516             free(bBytes); bBytes = NULL;
 517 
 518             JNU_ThrowIOException(env, "failed to get drop data");
 519             return NULL;
 520         }
 521 
 522         hOldBitmap = (HBITMAP)::SelectObject(hdc, hDibSection);
 523         DASSERT(hOldBitmap != NULL);
 524 
 525         switch (format) {
 526         case CF_DIB:
 527             VERIFY(::StretchDIBits(hdc,
 528                                    0, 0, width, height,
 529                                    0, 0, width, height,
 530                                    pSrcBits, pSrcBmi,
 531                                    DIB_RGB_COLORS, SRCCOPY) != GDI_ERROR);
 532             break;
 533         case CF_ENHMETAFILE:
 534         case CF_METAFILEPICT: {
 535             RECT rect = { 0, 0, width, height };
 536 
 537             VERIFY(::PlayEnhMetaFile(hdc, hEnhMetaFile, &rect));
 538             VERIFY(::DeleteEnhMetaFile(hEnhMetaFile)); hEnhMetaFile = NULL;
 539             break;
 540         }
 541         default:
 542             // Other formats are not supported yet.
 543             DASSERT(FALSE);
 544             break;
 545         }
 546 
 547         // convert Win32 pixel format (BGRX) to Java format (ARGB)
 548         DASSERT(sizeof(jint) == sizeof(RGBQUAD));
 549         RGBQUAD* prgbq = (RGBQUAD*)pDstBits;
 550         for(int nPixel = 0; nPixel < numPixels; nPixel++, prgbq++) {
 551             jint jpixel = WIN_TO_JAVA_PIXEL(prgbq->rgbRed,
 552                                             prgbq->rgbGreen,
 553                                             prgbq->rgbBlue);
 554             // stuff the 32-bit pixel back into the 32-bit RGBQUAD
 555             *prgbq = *((RGBQUAD*)(&jpixel));
 556         }
 557 
 558         buffer = env->NewIntArray(numPixels + 2);
 559         if (buffer == NULL) {
 560             throw std::bad_alloc();
 561         }
 562 
 563         // copy pixels into Java array
 564         env->SetIntArrayRegion(buffer, 0, numPixels, (jint*)pDstBits);
 565 
 566         // copy dimensions into Java array
 567         env->SetIntArrayRegion(buffer, numPixels, 1, (jint*)&width);
 568         env->SetIntArrayRegion(buffer, numPixels + 1, 1, (jint*)&height);
 569 
 570         VERIFY(::SelectObject(hdc, hOldBitmap) != NULL); hOldBitmap = NULL;
 571         VERIFY(::DeleteObject(hDibSection)); hDibSection = NULL;
 572         free(pDstBmi); pDstBmi = NULL;
 573         if (hPalette != NULL) {
 574             VERIFY(::SelectPalette(hdc, hOldPalette, FALSE) != NULL);
 575             hOldPalette = NULL;
 576             VERIFY(::DeleteObject(hPalette)); hPalette = NULL;
 577         }
 578         VERIFY(::DeleteDC(hdc)); hdc = NULL;
 579         free(bBytes); bBytes = NULL;
 580     } catch (...) {
 581         if (hdc != NULL && hOldBitmap != NULL) {
 582             VERIFY(::SelectObject(hdc, hOldBitmap) != NULL); hOldBitmap = NULL;
 583         }
 584         if (hDibSection != NULL) {
 585             VERIFY(::DeleteObject(hDibSection)); hDibSection = NULL;
 586         }
 587         if (pDstBmi != NULL) {
 588             free(pDstBmi); pDstBmi = NULL;
 589         }
 590         if (hPalette != NULL) {
 591             if (hdc != NULL) {
 592                 VERIFY(::SelectPalette(hdc, hOldPalette, FALSE) != NULL);
 593                 hOldPalette = NULL;
 594             }
 595             VERIFY(::DeleteObject(hPalette)); hPalette = NULL;
 596         }
 597         if (hdc != NULL) {
 598             VERIFY(::DeleteDC(hdc)); hdc = NULL;
 599         }
 600         if (hEnhMetaFile != NULL) {
 601             VERIFY(::DeleteEnhMetaFile(hEnhMetaFile)); hEnhMetaFile = NULL;
 602         }
 603         if (bBytes != NULL) {
 604             free(bBytes); bBytes = NULL;
 605         }
 606         throw;
 607     }
 608 
 609     return buffer;
 610 
 611     CATCH_BAD_ALLOC_RET(NULL);
 612 }
 613 
 614 /*
 615  * Class:     sun_awt_windows_WDataTransferer
 616  * Method:    imageDataToPlatformImageBytes
 617  * Signature: ([BIII)[B
 618  */
 619 JNIEXPORT jbyteArray JNICALL
 620 Java_sun_awt_windows_WDataTransferer_imageDataToPlatformImageBytes(JNIEnv *env,
 621                                                jobject self, jbyteArray imageData,
 622                                                jint width, jint height,
 623                                                jlong format) {
 624 
 625     TRY;
 626 
 627     if (JNU_IsNull(env, imageData)) {
 628         return NULL;
 629     }
 630 
 631     UINT size = env->GetArrayLength(imageData);
 632     if (size == 0) {
 633         return NULL;
 634     }
 635 
 636     // In the passed imageData array all lines are padded with zeroes except for
 637     // the last one, so we have to add one pad size here.
 638     int mod = (width * 3) % 4;
 639     int pad = mod > 0 ? 4 - mod : 0;
 640     int nBytes = sizeof(BITMAPINFO) + size + pad;
 641     BITMAPINFO* pinfo = (BITMAPINFO*)safe_Calloc(1, nBytes);
 642 
 643     static const int BITS_PER_PIXEL = 24;
 644 
 645     // prepare BITMAPINFO for a 24-bit BGR bitmap
 646     pinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
 647     pinfo->bmiHeader.biWidth = width;
 648     pinfo->bmiHeader.biHeight = height; // positive height means a bottom-up DIB
 649     pinfo->bmiHeader.biPlanes = 1;
 650     pinfo->bmiHeader.biBitCount = BITS_PER_PIXEL;
 651     pinfo->bmiHeader.biCompression = BI_RGB;
 652     // NOTE: MSDN says that biSizeImage may be set to 0 for BI_RGB bitmaps,
 653     // but some programs (e.g. Imaging for Windows NT by Wang Laboratories)
 654     // don't handle such DIBs correctly, so we specify the size explicitly.
 655     pinfo->bmiHeader.biSizeImage = size + pad;
 656 
 657     jbyte *array = (jbyte*)((LPSTR)pinfo + sizeof(BITMAPINFOHEADER));
 658     env->GetByteArrayRegion(imageData, 0, size, array);
 659     HRESULT hr = S_OK;
 660 
 661     jbyteArray bytes = NULL;
 662     switch (format) {
 663     case CF_DIB:
 664         bytes = env->NewByteArray(nBytes);
 665         if( NULL == bytes ) {
 666             hr = E_OUTOFMEMORY;
 667         } else {
 668             env->SetByteArrayRegion(bytes, 0, nBytes, (jbyte*)pinfo);
 669         }
 670         break;
 671     case CF_ENHMETAFILE:
 672     {
 673         HDC hdc = ::GetDC(NULL);
 674         if( NULL == hdc) {
 675             hr = HRESULT_FROM_WIN32(::GetLastError());
 676         } else {
 677             POINT p = { width, height };
 678             //We are trying to support context-independent metafile.
 679             //To implement it we have to select correct MM_HIMETRIC map mode.
 680             VERIFY(::SetMapMode(hdc, MM_HIMETRIC));
 681             VERIFY(::DPtoLP(hdc, &p, 1));
 682             //In accordance with CreateEnhMetaFile documentation the rectangle have to
 683             //be normal (left <= right, top <= bottom)
 684             RECT r = { min(0, p.x), min(0, p.y), max(0, p.x), max(0, p.y) };
 685             //Due to inversed row order in source bitmap the destination
 686             //height have to be negative.
 687             HDC hemfdc = ::CreateEnhMetaFile(NULL, NULL, &r, NULL);
 688             if( NULL == hemfdc) {
 689                 hr = HRESULT_FROM_WIN32(::GetLastError());
 690             } else {
 691                 int iMFHeight = r.bottom - r.top;
 692                 int iMFWidth = r.right - r.left;
 693                 VERIFY(::SetMapMode(hemfdc, MM_HIMETRIC));
 694                 if( GDI_ERROR == ::StretchDIBits(hemfdc,
 695                     0, iMFHeight, iMFWidth, -iMFHeight,
 696                     0, 0, width, height,
 697                     (LPVOID)array, pinfo,
 698                     DIB_RGB_COLORS, SRCCOPY))
 699                 {
 700                     hr = HRESULT_FROM_WIN32(::GetLastError());
 701                 }
 702                 HENHMETAFILE hemf = ::CloseEnhMetaFile(hemfdc);
 703                 if( NULL == hemf) {
 704                     hr = HRESULT_FROM_WIN32(::GetLastError());
 705                 } else {
 706                     if(SUCCEEDED(hr)){
 707                         UINT uEmfSize = ::GetEnhMetaFileBits(hemf, 0, NULL);
 708                         if( 0 == uEmfSize) {
 709                             hr = HRESULT_FROM_WIN32(::GetLastError());
 710                         } else {
 711                             LPBYTE lpbEmfBuffer = NULL;
 712                             try {
 713                                 lpbEmfBuffer = (LPBYTE)safe_Malloc(uEmfSize);
 714                                 VERIFY(::GetEnhMetaFileBits(hemf, uEmfSize,
 715                                                             lpbEmfBuffer) == uEmfSize);
 716                                 bytes = env->NewByteArray(uEmfSize);
 717                                 if(NULL == bytes) {
 718                                     hr = E_OUTOFMEMORY;
 719                                 } else {
 720                                     env->SetByteArrayRegion(bytes, 0, uEmfSize, (jbyte*)lpbEmfBuffer);
 721                                 }
 722                             } catch (std::bad_alloc &) {
 723                                 hr = E_OUTOFMEMORY;
 724                             }
 725                             free(lpbEmfBuffer);
 726                         }
 727                     }
 728                     VERIFY(::DeleteEnhMetaFile(hemf));
 729                 }
 730             }
 731             VERIFY(::ReleaseDC(NULL, hdc));
 732         }
 733         break;
 734     }
 735     case CF_METAFILEPICT:
 736     {
 737         HDC hdc = ::GetDC(NULL);
 738         if( NULL == hdc) {
 739             hr = HRESULT_FROM_WIN32(::GetLastError());
 740         } else {
 741             POINT p = { width, height };
 742             VERIFY(::SetMapMode(hdc, MM_HIMETRIC));
 743             VERIFY(::DPtoLP(hdc, &p, 1));
 744             RECT r = { min(0, p.x), min(0, p.y), max(0, p.x), max(0, p.y) };
 745             HDC hmfdc = ::CreateMetaFile(NULL);
 746             if( NULL == hmfdc) {
 747                 hr = HRESULT_FROM_WIN32(::GetLastError());
 748             } else {
 749                 VERIFY(::SetMapMode(hmfdc, MM_HIMETRIC));
 750                 int iMFHeight = r.bottom - r.top;
 751                 int iMFWidth = r.right - r.left;
 752                 //The destination Y coordinate (3d parameter in StretchDIBits call) is different for
 753                 //CF_ENHMETAFILE and CF_METAFILEPICT formats due to applying MM_ANISOTROPIC map mode
 754                 //at very last moment. MM_ANISOTROPIC map mode changes the Y-axis direction and can be
 755                 //selected just for metafile header.
 756                 if( GDI_ERROR == ::StretchDIBits(hmfdc,
 757                     0, 0, iMFWidth, -iMFHeight,
 758                     0, 0, width, height,
 759                     (LPVOID)array, pinfo,
 760                     DIB_RGB_COLORS, SRCCOPY))
 761                 {
 762                     hr = HRESULT_FROM_WIN32(::GetLastError());
 763                 }
 764                 HMETAFILE hmf = ::CloseMetaFile(hmfdc);
 765                 if( NULL == hmf) {
 766                     hr = HRESULT_FROM_WIN32(::GetLastError());
 767                 } else {
 768                     if(SUCCEEDED(hr)){
 769                         UINT uMfSize = ::GetMetaFileBitsEx(hmf, 0, NULL);
 770                         if( 0 == uMfSize) {
 771                             hr = HRESULT_FROM_WIN32(::GetLastError());
 772                         } else {
 773                             LPBYTE lpbMfBuffer = NULL;
 774                             try {
 775                                 UINT uMfSizeWithHead = uMfSize + sizeof(METAFILEPICT);
 776 
 777                                 lpbMfBuffer = (LPBYTE)safe_Malloc(uMfSizeWithHead);
 778                                 VERIFY(::GetMetaFileBitsEx(hmf, uMfSize,
 779                                                             lpbMfBuffer + sizeof(METAFILEPICT)) == uMfSize);
 780                                 bytes = env->NewByteArray(uMfSizeWithHead);
 781                                 if(NULL == bytes) {
 782                                     hr = E_OUTOFMEMORY;
 783                                 } else {
 784                                     LPMETAFILEPICT lpMfp = (LPMETAFILEPICT)lpbMfBuffer;
 785                                     lpMfp->mm = MM_ANISOTROPIC; // should use MM_ANISOTROPIC exactly (MSDN)
 786                                     lpMfp->xExt = iMFWidth;
 787                                     lpMfp->yExt = iMFHeight;
 788                                     env->SetByteArrayRegion(bytes, 0, uMfSizeWithHead, (jbyte*)lpbMfBuffer);
 789                                 }
 790                             } catch (std::bad_alloc &) {
 791                                 hr = E_OUTOFMEMORY;
 792                             }
 793                             free(lpbMfBuffer);
 794                         }
 795                     }
 796                     VERIFY(::DeleteMetaFile(hmf));
 797                 }
 798             }
 799             VERIFY(::ReleaseDC(NULL, hdc));
 800         }
 801         break;
 802     }
 803     default:
 804         DASSERT(FALSE); // Other formats are not supported yet.
 805         hr = E_NOTIMPL;
 806         break;
 807     }
 808     free(pinfo);
 809     if(FAILED(hr)){
 810         if(E_OUTOFMEMORY == hr)
 811             throw std::bad_alloc();
 812         return NULL;
 813     }
 814     return bytes;
 815     CATCH_BAD_ALLOC_RET(NULL);
 816 }
 817 
 818 /*
 819  * Class:     sun_awt_windows_WDataTransferer
 820  * Method:    registerClipboardFormat
 821  * Signature: (Ljava/lang/String;)J
 822  */
 823 JNIEXPORT jlong JNICALL
 824 Java_sun_awt_windows_WDataTransferer_registerClipboardFormat(JNIEnv *env,
 825                                                              jclass cls,
 826                                                              jstring str)
 827 {
 828     TRY;
 829 
 830     LPCTSTR cStr = JNU_GetStringPlatformChars(env, str, NULL);
 831     jlong value = ::RegisterClipboardFormat(cStr);
 832     JNU_ReleaseStringPlatformChars(env, str, cStr);
 833 
 834     return value;
 835 
 836     CATCH_BAD_ALLOC_RET(0);
 837 }
 838 
 839 /*
 840  * Class:     sun_awt_windows_WDataTransferer
 841  * Method:    getClipboardFormatName
 842  * Signature: (J)Ljava/lang/String;
 843  */
 844 JNIEXPORT jstring JNICALL
 845 Java_sun_awt_windows_WDataTransferer_getClipboardFormatName(JNIEnv *env,
 846                                                             jclass cls,
 847                                                             jlong format)
 848 {
 849     TRY;
 850 
 851     LPTSTR buf = new TCHAR[512]; // perhaps a bad idea to limit ourselves to 512
 852     VERIFY(::GetClipboardFormatName((UINT)format, buf, 512));
 853     jstring name = JNU_NewStringPlatform(env, buf);
 854     delete [] buf;
 855     if (name == NULL) {
 856         throw std::bad_alloc();
 857     }
 858     return name;
 859 
 860     CATCH_BAD_ALLOC_RET(NULL);
 861 }
 862 
 863 /*
 864  * Class:     sun_awt_windows_WToolkitThreadBlockedHandler
 865  * Method:    startSecondaryEventLoop
 866  * Signature: ()V;
 867  */
 868 JNIEXPORT void JNICALL
 869 Java_sun_awt_windows_WToolkitThreadBlockedHandler_startSecondaryEventLoop(JNIEnv *env, jclass)
 870 {
 871     TRY;
 872 
 873     AwtDataTransferer::SecondaryMessageLoop();
 874 
 875     CATCH_BAD_ALLOC;
 876 }
 877 
 878 }