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