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