1 /* 2 * Copyright (c) 1997, 2016, 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 #pragma push_macro("bad_alloc") 27 //"bad_alloc" would be introduced in STL as "std::zbad_alloc" and discarded by linker 28 //by this action we avoid the conflict with AWT implementation of "bad_alloc" 29 //we need <new> inclusion for STL "new" oprators set. 30 #define bad_alloc zbad_alloc 31 #include <new> 32 33 #if defined(_DEBUG) || defined(DEBUG) 34 extern void * operator new(size_t size, const char * filename, int linenumber); 35 void * operator new(size_t size) {return operator new(size, "stl", 1);} 36 #endif 37 #include <map> 38 39 #pragma pop_macro("bad_alloc") 40 //"bad_alloc" is undefined from here 41 42 #include <awt.h> 43 #include <shlobj.h> 44 45 #include "jlong.h" 46 #include "awt_DataTransferer.h" 47 #include "awt_DnDDS.h" 48 #include "awt_DnDDT.h" 49 #include "awt_Cursor.h" 50 #include "awt_Toolkit.h" 51 #include "awt_Component.h" 52 53 #include "java_awt_event_InputEvent.h" 54 #include "java_awt_dnd_DnDConstants.h" 55 #include "sun_awt_windows_WDragSourceContextPeer.h" 56 57 #include "awt_ole.h" 58 #include "awt_DCHolder.h" 59 60 bool operator < (const FORMATETC &fr, const FORMATETC &fl) { 61 return memcmp(&fr, &fl, sizeof(FORMATETC)) < 0; 62 } 63 64 typedef std::map<FORMATETC, STGMEDIUM> CDataMap; 65 66 #define GALLOCFLG (GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT) 67 #define JAVA_BUTTON_MASK (java_awt_event_InputEvent_BUTTON1_DOWN_MASK | \ 68 java_awt_event_InputEvent_BUTTON2_DOWN_MASK | \ 69 java_awt_event_InputEvent_BUTTON3_DOWN_MASK) 70 71 extern "C" { 72 DWORD __cdecl convertActionsToDROPEFFECT(jint actions); 73 jint __cdecl convertDROPEFFECTToActions(DWORD effects); 74 } 75 76 class PictureDragHelper 77 { 78 private: 79 static CDataMap st; 80 static IDragSourceHelper *pHelper; 81 public: 82 static HRESULT Create( 83 JNIEnv* env, 84 jintArray imageData, 85 int imageWidth, 86 int imageHeight, 87 int anchorX, 88 int anchorY, 89 IDataObject *pIDataObject) 90 { 91 if (NULL == imageData) { 92 return S_FALSE; 93 } 94 OLE_TRY 95 OLE_HRT( CoCreateInstance( 96 CLSID_DragDropHelper, 97 NULL, 98 CLSCTX_ALL, 99 IID_IDragSourceHelper, 100 (LPVOID*)&pHelper)) 101 102 jintArray ia = imageData; 103 jsize iPointCoint = env->GetArrayLength(ia); 104 105 DCHolder ph; 106 ph.Create(NULL, imageWidth, imageHeight, TRUE); 107 env->GetIntArrayRegion(ia, 0, iPointCoint, (jint*)ph.m_pPoints); 108 109 SHDRAGIMAGE sdi; 110 sdi.sizeDragImage.cx = imageWidth; 111 sdi.sizeDragImage.cy = imageHeight; 112 sdi.ptOffset.x = anchorX; 113 sdi.ptOffset.y = anchorY; 114 sdi.crColorKey = 0xFFFFFFFF; 115 sdi.hbmpDragImage = ph; 116 117 // this call assures that the bitmap will be dragged around 118 OLE_HR = pHelper->InitializeFromBitmap( 119 &sdi, 120 pIDataObject 121 ); 122 // in case of an error we need to destroy the image, else the helper object takes ownership 123 if (FAILED(OLE_HR)) { 124 DeleteObject(sdi.hbmpDragImage); 125 } 126 OLE_CATCH 127 OLE_RETURN_HR 128 } 129 130 static void Destroy() 131 { 132 if (NULL!=pHelper) { 133 CleanFormatMap(); 134 pHelper->Release(); 135 pHelper = NULL; 136 } 137 } 138 139 static void CleanFormatMap() 140 { 141 for (CDataMap::iterator i = st.begin(); st.end() != i; i = st.erase(i)) { 142 ::ReleaseStgMedium(&i->second); 143 } 144 } 145 static void SetData(const FORMATETC &format, const STGMEDIUM &medium) 146 { 147 CDataMap::iterator i = st.find(format); 148 if (st.end() != i) { 149 ::ReleaseStgMedium(&i->second); 150 i->second = medium; 151 } else { 152 st[format] = medium; 153 } 154 } 155 static const FORMATETC *FindFormat(const FORMATETC &format) 156 { 157 static FORMATETC fm = {0}; 158 CDataMap::iterator i = st.find(format); 159 if (st.end() != i) { 160 return &i->first; 161 } 162 for (i = st.begin(); st.end() != i; ++i) { 163 if (i->first.cfFormat==format.cfFormat) { 164 return &i->first; 165 } 166 } 167 return NULL; 168 } 169 static STGMEDIUM *FindData(const FORMATETC &format) 170 { 171 CDataMap::iterator i = st.find(format); 172 if (st.end() != i) { 173 return &i->second; 174 } 175 for (i = st.begin(); st.end() != i; ++i) { 176 const FORMATETC &f = i->first; 177 if (f.cfFormat==format.cfFormat && (f.tymed == (f.tymed & format.tymed))) { 178 return &i->second; 179 } 180 } 181 return NULL; 182 } 183 }; 184 185 186 CDataMap PictureDragHelper::st; 187 IDragSourceHelper *PictureDragHelper::pHelper = NULL; 188 189 extern const CLIPFORMAT CF_PERFORMEDDROPEFFECT = ::RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT); 190 extern const CLIPFORMAT CF_FILEGROUPDESCRIPTORW = ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW); 191 extern const CLIPFORMAT CF_FILEGROUPDESCRIPTORA = ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA); 192 extern const CLIPFORMAT CF_FILECONTENTS = ::RegisterClipboardFormat(CFSTR_FILECONTENTS); 193 194 typedef struct { 195 AwtDragSource* dragSource; 196 jobject cursor; 197 jintArray imageData; 198 jint imageWidth; 199 jint imageHeight; 200 jint x; 201 jint y; 202 } StartDragRec; 203 204 /** 205 * StartDrag 206 */ 207 208 void AwtDragSource::StartDrag( 209 AwtDragSource* self, 210 jobject cursor, 211 jintArray imageData, 212 jint imageWidth, 213 jint imageHeight, 214 jint x, 215 jint y) 216 { 217 StartDragRec* sdrp = new StartDragRec; 218 sdrp->dragSource = self; 219 sdrp->imageData = imageData; 220 sdrp->cursor = cursor; 221 sdrp->imageWidth = imageWidth; 222 sdrp->imageHeight = imageHeight; 223 sdrp->x = x; 224 sdrp->y = y; 225 226 AwtToolkit::GetInstance().WaitForSingleObject(self->m_mutex); 227 228 AwtToolkit::GetInstance().InvokeFunctionLater((void (*)(void *))&AwtDragSource::_DoDragDrop, (void *)sdrp); 229 230 self->WaitUntilSignalled(FALSE); 231 } 232 233 /** 234 * DoDragDrop - called from message pump thread 235 */ 236 237 void AwtDragSource::_DoDragDrop(void* param) { 238 StartDragRec* sdrp = (StartDragRec*)param; 239 AwtDragSource* dragSource = sdrp->dragSource; 240 DWORD effects = DROPEFFECT_NONE; 241 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 242 jobject peer = env->NewLocalRef(dragSource->GetPeer()); 243 244 if (sdrp->imageData) { 245 PictureDragHelper::Create( 246 env, 247 sdrp->imageData, 248 sdrp->imageWidth, 249 sdrp->imageHeight, 250 sdrp->x, 251 sdrp->y, 252 (IDataObject*)dragSource); 253 env->DeleteGlobalRef(sdrp->imageData); 254 } 255 dragSource->SetCursor(sdrp->cursor); 256 env->DeleteGlobalRef(sdrp->cursor); 257 delete sdrp; 258 259 HRESULT res; 260 261 // StartDrag has caused dragSource->m_mutex to be held by our thread now 262 263 AwtDropTarget::SetCurrentDnDDataObject(dragSource); 264 265 ::GetCursorPos(&dragSource->m_dragPoint); 266 267 dragSource->Signal(); 268 269 AwtToolkit &toolkit = AwtToolkit::GetInstance(); 270 toolkit.isInDoDragDropLoop = TRUE; 271 res = ::DoDragDrop(dragSource, 272 dragSource, 273 convertActionsToDROPEFFECT(dragSource->m_actions), 274 &effects 275 ); 276 toolkit.isInDoDragDropLoop = FALSE; 277 278 if (effects == DROPEFFECT_NONE && dragSource->m_dwPerformedDropEffect != DROPEFFECT_NONE) { 279 effects = dragSource->m_dwPerformedDropEffect; 280 } 281 dragSource->m_dwPerformedDropEffect = DROPEFFECT_NONE; 282 283 call_dSCddfinished(env, peer, res == DRAGDROP_S_DROP && effects != DROPEFFECT_NONE, 284 convertDROPEFFECTToActions(effects), 285 dragSource->m_dragPoint.x, dragSource->m_dragPoint.y); 286 287 env->DeleteLocalRef(peer); 288 289 DASSERT(AwtDropTarget::IsCurrentDnDDataObject(dragSource)); 290 AwtDropTarget::SetCurrentDnDDataObject(NULL); 291 292 PictureDragHelper::Destroy(); 293 dragSource->Release(); 294 } 295 296 /** 297 * constructor 298 */ 299 300 AwtDragSource::AwtDragSource(JNIEnv* env, jobject peer, jobject component, 301 jobject transferable, jobject trigger, 302 jint actions, jlongArray formats, 303 jobject formatMap) { 304 m_peer = env->NewGlobalRef(peer); 305 306 m_refs = 1; 307 308 m_actions = actions; 309 310 m_ntypes = 0; 311 312 m_initmods = 0; 313 m_lastmods = 0; 314 315 m_droptarget = NULL; 316 m_enterpending = TRUE; 317 318 m_cursor = NULL; 319 320 m_mutex = ::CreateMutex(NULL, FALSE, NULL); 321 322 m_component = env->NewGlobalRef(component); 323 m_transferable = env->NewGlobalRef(transferable); 324 m_formatMap = env->NewGlobalRef(formatMap); 325 326 m_dragPoint.x = 0; 327 m_dragPoint.y = 0; 328 329 m_fNC = TRUE; 330 m_dropPoint.x = 0; 331 m_dropPoint.y = 0; 332 333 m_dwPerformedDropEffect = DROPEFFECT_NONE; 334 m_bRestoreNodropCustomCursor = FALSE; 335 336 LoadCache(formats); 337 } 338 339 /** 340 * destructor 341 */ 342 343 AwtDragSource::~AwtDragSource() { 344 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 345 346 // fix for 6212440: on application shutdown, this object's 347 // destruction might be suppressed due to dangling COM references. 348 // On destruction, VM might be shut down already, so we should make 349 // a null check on env. 350 if (env) { 351 env->DeleteGlobalRef(m_peer); 352 env->DeleteGlobalRef(m_component); 353 env->DeleteGlobalRef(m_transferable); 354 env->DeleteGlobalRef(m_formatMap); 355 } 356 357 ::CloseHandle(m_mutex); 358 359 UnloadCache(); 360 } 361 362 /** 363 * _compar 364 * 365 * compare format's then tymed's .... only one tymed bit may be set 366 * at any time in a FORMATETC in the cache. 367 */ 368 369 int AwtDragSource::_compar(const void* first, const void* second) { 370 FORMATETC *fp = (FORMATETC *)first; 371 FORMATETC *sp = (FORMATETC *)second; 372 int r = fp->cfFormat - sp->cfFormat; 373 374 return r != 0 ? r : fp->tymed - sp->tymed; 375 } 376 377 /** 378 * LoadCache 379 */ 380 381 void AwtDragSource::LoadCache(jlongArray formats) { 382 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 383 unsigned int items = 0; 384 unsigned int i = 0; 385 unsigned int idx = 0; 386 387 if (m_types != (FORMATETC *)NULL) { 388 UnloadCache(); 389 } 390 391 items = env->GetArrayLength(formats); 392 393 if (items == 0) { 394 return; 395 } 396 397 jboolean isCopy; 398 jlong *lFormats = env->GetLongArrayElements(formats, &isCopy), 399 *saveFormats = lFormats; 400 401 for (i = 0, m_ntypes = 0; i < items; i++, lFormats++) { 402 // Warning C4244. 403 // Cast from jlong to CLIPFORMAT (WORD). 404 CLIPFORMAT fmt = (CLIPFORMAT)*lFormats; 405 switch (fmt) { 406 case CF_ENHMETAFILE: 407 m_ntypes++; // Only TYMED_ENHMF 408 break; 409 case CF_METAFILEPICT: 410 m_ntypes++; // Only TYMED_MFPICT 411 break; 412 case CF_HDROP: 413 m_ntypes++; // Only TYMED_HGLOBAL 414 break; 415 default: 416 m_ntypes += 2; // TYMED_HGLOBAL and TYMED_ISTREAM 417 break; 418 } 419 } 420 421 try { 422 m_types = (FORMATETC *)safe_Calloc(sizeof(FORMATETC), m_ntypes); 423 } catch (std::bad_alloc&) { 424 m_ntypes = 0; 425 if (saveFormats != NULL) { 426 env->ReleaseLongArrayElements(formats, saveFormats, 0); 427 } 428 throw; 429 } 430 431 lFormats = saveFormats; 432 433 for (i = 0, idx = 0; i < items; i++, lFormats++) { 434 // Warning C4244. 435 // Cast from jlong to CLIPFORMAT (WORD). 436 CLIPFORMAT fmt = (CLIPFORMAT)*lFormats; 437 438 m_types[idx].cfFormat = fmt; 439 m_types[idx].dwAspect = DVASPECT_CONTENT; 440 m_types[idx].lindex = -1; 441 442 switch (fmt) { 443 default: 444 m_types[idx].tymed = TYMED_ISTREAM; 445 idx++; 446 447 // now make a copy, but with a TYMED of HGLOBAL 448 m_types[idx] = m_types[idx-1]; 449 m_types[idx].tymed = TYMED_HGLOBAL; 450 idx++; 451 break; 452 case CF_HDROP: 453 m_types[idx].tymed = TYMED_HGLOBAL; 454 idx++; 455 break; 456 case CF_ENHMETAFILE: 457 m_types[idx].tymed = TYMED_ENHMF; 458 idx++; 459 break; 460 case CF_METAFILEPICT: 461 m_types[idx].tymed = TYMED_MFPICT; 462 idx++; 463 break; 464 } 465 } 466 DASSERT(idx == m_ntypes); 467 468 env->ReleaseLongArrayElements(formats, saveFormats, 0); 469 470 // sort them in ascending order of format 471 qsort((void *)m_types, (size_t)m_ntypes, (size_t)sizeof(FORMATETC), 472 _compar); 473 } 474 475 /** 476 * UnloadCache 477 */ 478 479 void AwtDragSource::UnloadCache() { 480 if (m_ntypes == 0) { 481 return; 482 } 483 484 free((void*)m_types); 485 m_ntypes = 0; 486 m_types = (FORMATETC *)NULL; 487 } 488 489 /** 490 * ChangeCursor 491 */ 492 HRESULT AwtDragSource::ChangeCursor() 493 { 494 if (m_cursor != NULL) { 495 ::SetCursor(m_cursor->GetHCursor()); 496 return S_OK; 497 } 498 return DRAGDROP_S_USEDEFAULTCURSORS; 499 } 500 501 /** 502 * SetCursor 503 */ 504 void AwtDragSource::SetCursor(jobject cursor) { 505 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 506 507 if (JNU_IsNull(env, cursor)) { 508 m_cursor = NULL; 509 return; 510 } 511 512 jlong pData = env->GetLongField(cursor, AwtCursor::pDataID); 513 // Warning C4312. 514 // Cast jlong (__int64) to pointer. 515 m_cursor = (AwtCursor*)pData; 516 517 if (m_cursor == NULL) { 518 m_cursor = AwtCursor::CreateSystemCursor(cursor); 519 } 520 } 521 522 /** 523 * MatchFormatEtc 524 */ 525 526 HRESULT __stdcall 527 AwtDragSource::MatchFormatEtc(FORMATETC __RPC_FAR *pFormatEtcIn, 528 FORMATETC *cacheEnt) { 529 TRY; 530 531 const FORMATETC *pFormat = PictureDragHelper::FindFormat(*pFormatEtcIn); 532 if (NULL != pFormat) { 533 if (NULL != cacheEnt) { 534 *cacheEnt = *pFormat; 535 } 536 return S_OK; 537 } 538 539 if ((pFormatEtcIn->tymed & (TYMED_HGLOBAL | TYMED_ISTREAM | TYMED_ENHMF | 540 TYMED_MFPICT)) == 0) { 541 return DV_E_TYMED; 542 } else if (pFormatEtcIn->lindex != -1) { 543 return DV_E_LINDEX; 544 } else if (pFormatEtcIn->dwAspect != DVASPECT_CONTENT) { 545 return DV_E_DVASPECT; 546 } 547 548 FORMATETC tmp = *pFormatEtcIn; 549 550 static const DWORD supportedTymeds[] = 551 { TYMED_ISTREAM, TYMED_HGLOBAL, TYMED_ENHMF, TYMED_MFPICT }; 552 static const int nSupportedTymeds = 4; 553 554 for (int i = 0; i < nSupportedTymeds; i++) { 555 /* 556 * Fix for BugTraq Id 4426805. 557 * Match only if the tymed is supported by the requester. 558 */ 559 if ((pFormatEtcIn->tymed & supportedTymeds[i]) == 0) { 560 continue; 561 } 562 563 tmp.tymed = supportedTymeds[i]; 564 pFormat = (const FORMATETC *)bsearch((const void *)&tmp, 565 (const void *)m_types, 566 (size_t) m_ntypes, 567 (size_t) sizeof(FORMATETC), 568 _compar 569 ); 570 if (NULL != pFormat) { 571 if (cacheEnt != (FORMATETC *)NULL) { 572 *cacheEnt = *pFormat; 573 } 574 return S_OK; 575 } 576 } 577 578 return DV_E_FORMATETC; 579 580 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 581 } 582 583 /** 584 * QueryInterface 585 */ 586 587 HRESULT __stdcall AwtDragSource::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) { 588 TRY; 589 590 if (riid == IID_IUnknown) { 591 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IUnknown*)(IDropSource*)this; 592 AddRef(); 593 return S_OK; 594 } else if (riid == IID_IDropSource) { 595 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IDropSource*)this; 596 AddRef(); 597 return S_OK; 598 } else if (riid == IID_IDataObject) { 599 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IDataObject*)this; 600 AddRef(); 601 return S_OK; 602 } else { 603 *ppvObject = (void __RPC_FAR *__RPC_FAR)NULL; 604 return E_NOINTERFACE; 605 } 606 607 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 608 } 609 610 /** 611 * AddRef 612 */ 613 614 ULONG __stdcall AwtDragSource::AddRef() { 615 return (ULONG)++m_refs; 616 } 617 618 /** 619 * Release 620 */ 621 622 ULONG __stdcall AwtDragSource::Release() { 623 int refs; 624 625 if ((refs = --m_refs) == 0) delete this; 626 627 return (ULONG)refs; 628 } 629 630 /** 631 * QueryContinueDrag 632 */ 633 634 HRESULT __stdcall AwtDragSource::QueryContinueDrag(BOOL fEscapeKeyPressed, DWORD grfKeyState) { 635 AwtToolkit::GetInstance().eventNumber++; 636 TRY; 637 638 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 639 640 if (fEscapeKeyPressed) 641 return DRAGDROP_S_CANCEL; 642 643 jint modifiers = AwtComponent::GetJavaModifiers(); 644 645 POINT dragPoint; 646 647 ::GetCursorPos(&dragPoint); 648 649 if ( (dragPoint.x != m_dragPoint.x || dragPoint.y != m_dragPoint.y) && 650 m_lastmods == modifiers) {//cannot move before cursor change 651 call_dSCmouseMoved(env, m_peer, 652 m_actions, modifiers, dragPoint.x, dragPoint.y); 653 JNU_CHECK_EXCEPTION_RETURN(env, E_UNEXPECTED); 654 m_dragPoint = dragPoint; 655 } 656 657 if ((modifiers & JAVA_BUTTON_MASK) == 0) { 658 return DRAGDROP_S_DROP; 659 } else if (m_initmods == 0) { 660 m_initmods = modifiers; 661 } else if ((modifiers & JAVA_BUTTON_MASK) != (m_initmods & JAVA_BUTTON_MASK)) { 662 return DRAGDROP_S_CANCEL; 663 } else if (m_lastmods != modifiers) { 664 call_dSCchanged(env, m_peer, 665 m_actions, modifiers, dragPoint.x, dragPoint.y); 666 m_bRestoreNodropCustomCursor = TRUE; 667 } 668 669 m_lastmods = modifiers; 670 671 //CR 6480706 - MS Bug on hold 672 HCURSOR hNeedCursor; 673 if ( 674 m_bRestoreNodropCustomCursor && 675 m_cursor != NULL && 676 (hNeedCursor = m_cursor->GetHCursor()) != ::GetCursor() ) 677 { 678 ChangeCursor(); 679 m_bRestoreNodropCustomCursor = FALSE; 680 } 681 return S_OK; 682 683 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 684 } 685 686 /** 687 * GiveFeedback 688 */ 689 690 HRESULT __stdcall AwtDragSource::GiveFeedback(DWORD dwEffect) { 691 AwtToolkit::GetInstance().eventNumber++; 692 TRY; 693 694 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 695 jint modifiers = 0; 696 SHORT mods = 0; 697 698 m_actions = convertDROPEFFECTToActions(dwEffect); 699 700 if (::GetKeyState(VK_LBUTTON) & 0xff00) { 701 mods |= MK_LBUTTON; 702 } else if (::GetKeyState(VK_MBUTTON) & 0xff00) { 703 mods |= MK_MBUTTON; 704 } else if (::GetKeyState(VK_RBUTTON) & 0xff00) { 705 mods |= MK_RBUTTON; 706 } 707 708 if (::GetKeyState(VK_SHIFT) & 0xff00) 709 mods |= MK_SHIFT; 710 if (::GetKeyState(VK_CONTROL) & 0xff00) 711 mods |= MK_CONTROL; 712 if (::GetKeyState(VK_MENU) & 0xff00) 713 mods |= MK_ALT; 714 715 modifiers = AwtComponent::GetJavaModifiers(); 716 717 POINT curs; 718 719 ::GetCursorPos(&curs); 720 721 m_droptarget = ::WindowFromPoint(curs); 722 723 int invalid = (dwEffect == DROPEFFECT_NONE); 724 725 if (invalid) { 726 // Don't call dragExit if dragEnter and dragOver haven't been called. 727 if (!m_enterpending) { 728 call_dSCexit(env, m_peer, curs.x, curs.y); 729 } 730 m_droptarget = (HWND)NULL; 731 m_enterpending = TRUE; 732 } else if (m_droptarget != NULL) { 733 (*(m_enterpending ? call_dSCenter : call_dSCmotion)) 734 (env, m_peer, m_actions, modifiers, curs.x, curs.y); 735 736 m_enterpending = FALSE; 737 } 738 739 if (m_droptarget != NULL) { 740 RECT rect; 741 POINT client = curs; 742 VERIFY(::ScreenToClient(m_droptarget, &client)); 743 VERIFY(::GetClientRect(m_droptarget, &rect)); 744 if (::PtInRect(&rect, client)) { 745 m_fNC = FALSE; 746 m_dropPoint = client; 747 } else { 748 m_fNC = TRUE; 749 m_dropPoint = curs; 750 } 751 } else { 752 m_fNC = TRUE; 753 m_dropPoint.x = 0; 754 m_dropPoint.y = 0; 755 } 756 757 m_bRestoreNodropCustomCursor = (dwEffect == DROPEFFECT_NONE); 758 759 return ChangeCursor(); 760 761 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 762 } 763 764 765 /** 766 * GetData 767 */ 768 769 HRESULT __stdcall AwtDragSource::GetData(FORMATETC __RPC_FAR *pFormatEtc, 770 STGMEDIUM __RPC_FAR *pmedium) { 771 AwtToolkit::GetInstance().eventNumber++; 772 TRY; 773 STGMEDIUM *pPicMedia = PictureDragHelper::FindData(*pFormatEtc); 774 if (NULL != pPicMedia) { 775 *pmedium = *pPicMedia; 776 //return outside, so AddRef the instance of pstm or hGlobal! 777 if (pmedium->tymed == TYMED_ISTREAM) { 778 pmedium->pstm->AddRef(); 779 pmedium->pUnkForRelease = (IUnknown *)NULL; 780 } else if (pmedium->tymed == TYMED_HGLOBAL) { 781 AddRef(); 782 pmedium->pUnkForRelease = (IDropSource *)this; 783 } 784 return S_OK; 785 } 786 787 HRESULT res = GetProcessId(pFormatEtc, pmedium); 788 if (res == S_OK) { 789 return res; 790 } 791 792 FORMATETC matchedFormatEtc; 793 res = MatchFormatEtc(pFormatEtc, &matchedFormatEtc); 794 if (res != S_OK) { 795 return res; 796 } 797 798 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 799 800 if (env->PushLocalFrame(2) < 0) { 801 return E_OUTOFMEMORY; 802 } 803 804 jbyteArray bytes = 805 AwtDataTransferer::ConvertData(env, m_component, m_transferable, 806 (jlong)matchedFormatEtc.cfFormat, 807 m_formatMap); 808 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 809 env->ExceptionDescribe(); 810 env->ExceptionClear(); 811 env->PopLocalFrame(NULL); 812 return E_UNEXPECTED; 813 } 814 if (bytes == NULL) { 815 env->PopLocalFrame(NULL); 816 return E_UNEXPECTED; 817 } 818 819 jint nBytes = env->GetArrayLength(bytes); 820 821 if ((matchedFormatEtc.tymed & TYMED_ISTREAM) != 0) { 822 ADSIStreamProxy *istream = new ADSIStreamProxy(this, bytes, nBytes); 823 824 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 825 env->ExceptionDescribe(); 826 env->ExceptionClear(); 827 env->PopLocalFrame(NULL); 828 return E_UNEXPECTED; 829 } 830 831 pmedium->tymed = TYMED_ISTREAM; 832 pmedium->pstm = istream; 833 pmedium->pUnkForRelease = (IUnknown *)NULL; 834 835 env->PopLocalFrame(NULL); 836 return S_OK; 837 } else if ((matchedFormatEtc.tymed & TYMED_HGLOBAL) != 0) { 838 HGLOBAL copy = ::GlobalAlloc(GALLOCFLG, nBytes + 839 ((matchedFormatEtc.cfFormat == CF_HDROP) 840 ? sizeof(DROPFILES) 841 : 0)); 842 if (copy == NULL) { 843 env->PopLocalFrame(NULL); 844 throw std::bad_alloc(); 845 } 846 847 char *dataout = (char *)::GlobalLock(copy); 848 849 if (matchedFormatEtc.cfFormat == CF_HDROP) { 850 DROPFILES *dropfiles = (DROPFILES *)dataout; 851 dropfiles->pFiles = sizeof(DROPFILES); 852 dropfiles->pt.x = m_dropPoint.x; 853 dropfiles->pt.y = m_dropPoint.y; 854 dropfiles->fNC = m_fNC; 855 dropfiles->fWide = TRUE; // we publish only Unicode 856 dataout += sizeof(DROPFILES); 857 } 858 859 env->GetByteArrayRegion(bytes, 0, nBytes, (jbyte *)dataout); 860 ::GlobalUnlock(copy); 861 862 pmedium->tymed = TYMED_HGLOBAL; 863 pmedium->hGlobal = copy; 864 pmedium->pUnkForRelease = (IUnknown *)NULL; 865 866 env->PopLocalFrame(NULL); 867 return S_OK; 868 } else if ((matchedFormatEtc.tymed & TYMED_ENHMF) != 0) { 869 LPBYTE lpbEmfBuffer = 870 (LPBYTE)env->GetPrimitiveArrayCritical(bytes, NULL); 871 if (lpbEmfBuffer == NULL) { 872 env->PopLocalFrame(NULL); 873 throw std::bad_alloc(); 874 } 875 876 HENHMETAFILE hemf = ::SetEnhMetaFileBits(nBytes, lpbEmfBuffer); 877 878 env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbEmfBuffer, JNI_ABORT); 879 880 if (hemf == NULL) { 881 env->PopLocalFrame(NULL); 882 return E_UNEXPECTED; 883 } 884 885 pmedium->tymed = TYMED_ENHMF; 886 pmedium->hEnhMetaFile = hemf; 887 pmedium->pUnkForRelease = (IUnknown *)NULL; 888 889 env->PopLocalFrame(NULL); 890 return S_OK; 891 } else if ((matchedFormatEtc.tymed & TYMED_MFPICT) != 0) { 892 LPBYTE lpbMfpBuffer = 893 (LPBYTE)env->GetPrimitiveArrayCritical(bytes, NULL); 894 if (lpbMfpBuffer == NULL) { 895 env->PopLocalFrame(NULL); 896 throw std::bad_alloc(); 897 } 898 899 HMETAFILE hmf = ::SetMetaFileBitsEx(nBytes - sizeof(METAFILEPICT), 900 lpbMfpBuffer + sizeof(METAFILEPICT)); 901 if (hmf == NULL) { 902 env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbMfpBuffer, JNI_ABORT); 903 env->PopLocalFrame(NULL); 904 return E_UNEXPECTED; 905 } 906 907 LPMETAFILEPICT lpMfpOld = (LPMETAFILEPICT)lpbMfpBuffer; 908 909 HMETAFILEPICT hmfp = ::GlobalAlloc(GALLOCFLG, sizeof(METAFILEPICT)); 910 if (hmfp == NULL) { 911 VERIFY(::DeleteMetaFile(hmf)); 912 env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbMfpBuffer, JNI_ABORT); 913 env->PopLocalFrame(NULL); 914 throw std::bad_alloc(); 915 } 916 917 LPMETAFILEPICT lpMfp = (LPMETAFILEPICT)::GlobalLock(hmfp); 918 lpMfp->mm = lpMfpOld->mm; 919 lpMfp->xExt = lpMfpOld->xExt; 920 lpMfp->yExt = lpMfpOld->yExt; 921 lpMfp->hMF = hmf; 922 ::GlobalUnlock(hmfp); 923 924 env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbMfpBuffer, JNI_ABORT); 925 926 pmedium->tymed = TYMED_MFPICT; 927 pmedium->hMetaFilePict = hmfp; 928 pmedium->pUnkForRelease = (IUnknown *)NULL; 929 930 env->PopLocalFrame(NULL); 931 return S_OK; 932 } 933 934 env->PopLocalFrame(NULL); 935 return DV_E_TYMED; 936 937 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 938 } 939 940 /** 941 * GetDataHere 942 */ 943 944 HRESULT __stdcall AwtDragSource::GetDataHere(FORMATETC __RPC_FAR *pFormatEtc, 945 STGMEDIUM __RPC_FAR *pmedium) { 946 AwtToolkit::GetInstance().eventNumber++; 947 TRY; 948 949 if (pmedium->pUnkForRelease != (IUnknown *)NULL) { 950 return E_INVALIDARG; 951 } 952 953 HRESULT res = GetProcessId(pFormatEtc, pmedium); 954 if (res == S_OK) { 955 return res; 956 } 957 958 FORMATETC matchedFormatEtc; 959 res = MatchFormatEtc(pFormatEtc, &matchedFormatEtc); 960 if (res != S_OK) { 961 return res; 962 } 963 964 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 965 966 if (env->PushLocalFrame(2) < 0) { 967 return E_OUTOFMEMORY; 968 } 969 970 jbyteArray bytes = 971 AwtDataTransferer::ConvertData(env, m_component, m_transferable, 972 (jlong)matchedFormatEtc.cfFormat, 973 m_formatMap); 974 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 975 env->ExceptionDescribe(); 976 env->ExceptionClear(); 977 env->PopLocalFrame(NULL); 978 return E_UNEXPECTED; 979 } 980 if (bytes == NULL) { 981 env->PopLocalFrame(NULL); 982 return E_UNEXPECTED; 983 } 984 985 jint nBytes = env->GetArrayLength(bytes); 986 987 // NOTE: TYMED_ENHMF and TYMED_MFPICT are not valid for GetDataHere(). 988 if ((matchedFormatEtc.tymed & TYMED_ISTREAM) != 0) { 989 jboolean isCopy; 990 jbyte *bBytes = env->GetByteArrayElements(bytes, &isCopy); 991 if (bBytes == NULL) { 992 env->PopLocalFrame(NULL); 993 return E_UNEXPECTED; 994 } 995 996 ULONG act; 997 HRESULT res = pmedium->pstm->Write((const void *)bBytes, (ULONG)nBytes, 998 &act); 999 1000 env->ReleaseByteArrayElements(bytes, bBytes, JNI_ABORT); 1001 1002 env->PopLocalFrame(NULL); 1003 return S_OK; 1004 } else if ((matchedFormatEtc.tymed & TYMED_HGLOBAL) != 0) { 1005 ::SetLastError(0); // clear error 1006 // Warning C4244. 1007 SIZE_T mBytes = ::GlobalSize(pmedium->hGlobal); 1008 if (::GetLastError() != 0) { 1009 env->PopLocalFrame(NULL); 1010 return E_UNEXPECTED; 1011 } 1012 1013 if (nBytes + ((matchedFormatEtc.cfFormat == CF_HDROP) 1014 ? sizeof(DROPFILES) : 0) > mBytes) { 1015 env->PopLocalFrame(NULL); 1016 return STG_E_MEDIUMFULL; 1017 } 1018 1019 char *dataout = (char *)::GlobalLock(pmedium->hGlobal); 1020 1021 if (matchedFormatEtc.cfFormat == CF_HDROP) { 1022 DROPFILES *dropfiles = (DROPFILES *)dataout; 1023 dropfiles->pFiles = sizeof(DROPFILES); 1024 dropfiles->pt.x = m_dropPoint.x; 1025 dropfiles->pt.y = m_dropPoint.y; 1026 dropfiles->fNC = m_fNC; 1027 dropfiles->fWide = TRUE; // good guess! 1028 dataout += sizeof(DROPFILES); 1029 } 1030 1031 env->GetByteArrayRegion(bytes, 0, nBytes, (jbyte *)dataout); 1032 ::GlobalUnlock(pmedium->hGlobal); 1033 1034 env->PopLocalFrame(NULL); 1035 return S_OK; 1036 } 1037 1038 env->PopLocalFrame(NULL); 1039 return DV_E_TYMED; 1040 1041 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1042 } 1043 1044 /** 1045 * QueryGetData 1046 */ 1047 1048 HRESULT __stdcall AwtDragSource::QueryGetData(FORMATETC __RPC_FAR *pFormatEtc) { 1049 AwtToolkit::GetInstance().eventNumber++; 1050 TRY; 1051 1052 return MatchFormatEtc(pFormatEtc, (FORMATETC *)NULL); 1053 1054 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1055 } 1056 1057 1058 /** 1059 * GetCanonicalFormatEtc 1060 */ 1061 1062 HRESULT __stdcall AwtDragSource::GetCanonicalFormatEtc(FORMATETC __RPC_FAR *pFormatEtcIn, FORMATETC __RPC_FAR *pFormatEtcOut) { 1063 AwtToolkit::GetInstance().eventNumber++; 1064 TRY; 1065 1066 HRESULT res = MatchFormatEtc(pFormatEtcIn, (FORMATETC *)NULL); 1067 1068 if (res != S_OK) return res; 1069 1070 *pFormatEtcOut = *pFormatEtcIn; 1071 1072 pFormatEtcOut->ptd = NULL; 1073 1074 return DATA_S_SAMEFORMATETC; 1075 1076 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1077 } 1078 1079 /** 1080 * SetData 1081 */ 1082 1083 HRESULT __stdcall AwtDragSource::SetData(FORMATETC __RPC_FAR *pFormatEtc, STGMEDIUM __RPC_FAR *pmedium, BOOL fRelease) { 1084 AwtToolkit::GetInstance().eventNumber++; 1085 if (pFormatEtc->cfFormat == CF_PERFORMEDDROPEFFECT && pmedium->tymed == TYMED_HGLOBAL) { 1086 m_dwPerformedDropEffect = *(DWORD*)::GlobalLock(pmedium->hGlobal); 1087 ::GlobalUnlock(pmedium->hGlobal); 1088 if (fRelease) { 1089 ::ReleaseStgMedium(pmedium); 1090 } 1091 return S_OK; 1092 } 1093 1094 if (fRelease) { 1095 //we are copying pmedium as a structure for further use, so no any release! 1096 PictureDragHelper::SetData(*pFormatEtc, *pmedium); 1097 return S_OK; 1098 } 1099 return E_UNEXPECTED; 1100 } 1101 1102 /** 1103 * EnumFormatEtc 1104 */ 1105 1106 HRESULT __stdcall AwtDragSource::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC *__RPC_FAR *ppenumFormatEtc) { 1107 AwtToolkit::GetInstance().eventNumber++; 1108 TRY; 1109 1110 *ppenumFormatEtc = new ADSIEnumFormatEtc(this); 1111 return S_OK; 1112 1113 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1114 } 1115 1116 /** 1117 * DAdvise 1118 */ 1119 1120 HRESULT __stdcall AwtDragSource::DAdvise(FORMATETC __RPC_FAR *pFormatEtc, DWORD advf, IAdviseSink __RPC_FAR *pAdvSink, DWORD __RPC_FAR *pdwConnection) { 1121 AwtToolkit::GetInstance().eventNumber++; 1122 return E_NOTIMPL; 1123 } 1124 1125 /** 1126 * DUnadvise 1127 */ 1128 1129 HRESULT __stdcall AwtDragSource::DUnadvise(DWORD dwConnection) { 1130 AwtToolkit::GetInstance().eventNumber++; 1131 return OLE_E_ADVISENOTSUPPORTED; 1132 } 1133 1134 /** 1135 * EnumAdvise 1136 */ 1137 1138 HRESULT __stdcall AwtDragSource::EnumDAdvise(IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise) { 1139 AwtToolkit::GetInstance().eventNumber++; 1140 return OLE_E_ADVISENOTSUPPORTED; 1141 } 1142 1143 const UINT AwtDragSource::PROCESS_ID_FORMAT = 1144 ::RegisterClipboardFormat(TEXT("_SUNW_JAVA_AWT_PROCESS_ID")); 1145 1146 HRESULT __stdcall AwtDragSource::GetProcessId(FORMATETC __RPC_FAR *pFormatEtc, STGMEDIUM __RPC_FAR *pmedium) { 1147 AwtToolkit::GetInstance().eventNumber++; 1148 if ((pFormatEtc->tymed & TYMED_HGLOBAL) == 0) { 1149 return DV_E_TYMED; 1150 } else if (pFormatEtc->lindex != -1) { 1151 return DV_E_LINDEX; 1152 } else if (pFormatEtc->dwAspect != DVASPECT_CONTENT) { 1153 return DV_E_DVASPECT; 1154 } else if (pFormatEtc->cfFormat != PROCESS_ID_FORMAT) { 1155 return DV_E_FORMATETC; 1156 } 1157 1158 DWORD id = ::CoGetCurrentProcess(); 1159 1160 HGLOBAL copy = ::GlobalAlloc(GALLOCFLG, sizeof(id)); 1161 1162 if (copy == NULL) { 1163 throw std::bad_alloc(); 1164 } 1165 1166 char *dataout = (char *)::GlobalLock(copy); 1167 1168 memcpy(dataout, &id, sizeof(id)); 1169 ::GlobalUnlock(copy); 1170 1171 pmedium->tymed = TYMED_HGLOBAL; 1172 pmedium->hGlobal = copy; 1173 pmedium->pUnkForRelease = (IUnknown *)NULL; 1174 1175 return S_OK; 1176 } 1177 1178 DECLARE_JAVA_CLASS(dSCClazz, "sun/awt/windows/WDragSourceContextPeer") 1179 1180 void 1181 AwtDragSource::call_dSCenter(JNIEnv* env, jobject self, jint targetActions, 1182 jint modifiers, jint x, jint y) { 1183 DECLARE_VOID_JAVA_METHOD(dSCenter, dSCClazz, "dragEnter", "(IIII)V"); 1184 DASSERT(!JNU_IsNull(env, self)); 1185 env->CallVoidMethod(self, dSCenter, targetActions, modifiers, x, y); 1186 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1187 env->ExceptionDescribe(); 1188 env->ExceptionClear(); 1189 } 1190 } 1191 1192 void 1193 AwtDragSource::call_dSCmotion(JNIEnv* env, jobject self, jint targetActions, 1194 jint modifiers, jint x, jint y) { 1195 DECLARE_VOID_JAVA_METHOD(dSCmotion, dSCClazz, "dragMotion", "(IIII)V"); 1196 DASSERT(!JNU_IsNull(env, self)); 1197 env->CallVoidMethod(self, dSCmotion, targetActions, modifiers, x, y); 1198 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1199 env->ExceptionDescribe(); 1200 env->ExceptionClear(); 1201 } 1202 } 1203 1204 void 1205 AwtDragSource::call_dSCchanged(JNIEnv* env, jobject self, jint targetActions, 1206 jint modifiers, jint x, jint y) { 1207 DECLARE_VOID_JAVA_METHOD(dSCchanged, dSCClazz, "operationChanged", 1208 "(IIII)V"); 1209 DASSERT(!JNU_IsNull(env, self)); 1210 env->CallVoidMethod(self, dSCchanged, targetActions, modifiers, x, y); 1211 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1212 env->ExceptionDescribe(); 1213 env->ExceptionClear(); 1214 } 1215 } 1216 1217 void 1218 AwtDragSource::call_dSCexit(JNIEnv* env, jobject self, jint x, jint y) { 1219 DECLARE_VOID_JAVA_METHOD(dSCexit, dSCClazz, "dragExit", "(II)V"); 1220 DASSERT(!JNU_IsNull(env, self)); 1221 env->CallVoidMethod(self, dSCexit, x, y); 1222 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1223 env->ExceptionDescribe(); 1224 env->ExceptionClear(); 1225 } 1226 } 1227 1228 void 1229 AwtDragSource::call_dSCddfinished(JNIEnv* env, jobject self, jboolean success, 1230 jint operations, jint x, jint y) { 1231 DECLARE_VOID_JAVA_METHOD(dSCddfinished, dSCClazz, "dragDropFinished", "(ZIII)V"); 1232 DASSERT(!JNU_IsNull(env, self)); 1233 env->CallVoidMethod(self, dSCddfinished, success, operations, x, y); 1234 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1235 env->ExceptionDescribe(); 1236 env->ExceptionClear(); 1237 } 1238 } 1239 1240 void 1241 AwtDragSource::call_dSCmouseMoved(JNIEnv* env, jobject self, jint targetActions, 1242 jint modifiers, jint x, jint y) { 1243 DECLARE_VOID_JAVA_METHOD(dSCmouseMoved, dSCClazz, "dragMouseMoved", 1244 "(IIII)V"); 1245 DASSERT(!JNU_IsNull(env, self)); 1246 env->CallVoidMethod(self, dSCmouseMoved, targetActions, modifiers, x, y); 1247 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1248 env->ExceptionDescribe(); 1249 env->ExceptionClear(); 1250 } 1251 } 1252 1253 DECLARE_JAVA_CLASS(awtIEClazz, "java/awt/event/InputEvent") 1254 1255 /** 1256 * Constructor 1257 */ 1258 1259 AwtDragSource::ADSIEnumFormatEtc::ADSIEnumFormatEtc(AwtDragSource* parent) { 1260 m_parent = parent; 1261 m_idx = 0; 1262 1263 m_refs = 0; 1264 1265 m_parent->AddRef(); 1266 1267 AddRef(); 1268 } 1269 1270 /** 1271 * Destructor 1272 */ 1273 1274 AwtDragSource::ADSIEnumFormatEtc::~ADSIEnumFormatEtc() { 1275 m_parent->Release(); 1276 } 1277 1278 /** 1279 * QueryInterface 1280 */ 1281 1282 HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) { 1283 TRY; 1284 1285 if (riid == IID_IUnknown) { 1286 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IUnknown*)this; 1287 AddRef(); 1288 return S_OK; 1289 } else if (riid == IID_IEnumFORMATETC) { 1290 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IEnumFORMATETC*)this; 1291 AddRef(); 1292 return S_OK; 1293 } else { 1294 *ppvObject = (void __RPC_FAR *__RPC_FAR)NULL; 1295 return E_NOINTERFACE; 1296 } 1297 1298 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1299 } 1300 1301 /** 1302 * AddRef 1303 */ 1304 1305 ULONG __stdcall AwtDragSource::ADSIEnumFormatEtc::AddRef(void) { 1306 return (ULONG)++m_refs; 1307 } 1308 1309 /** 1310 * Release 1311 */ 1312 1313 ULONG __stdcall AwtDragSource::ADSIEnumFormatEtc::Release(void) { 1314 int refs; 1315 1316 if ((refs = --m_refs) == 0) delete this; 1317 1318 return (ULONG)refs; 1319 } 1320 1321 /** 1322 * Next 1323 */ 1324 1325 HRESULT _stdcall AwtDragSource::ADSIEnumFormatEtc::Next(ULONG celt, FORMATETC __RPC_FAR *rgelt, ULONG __RPC_FAR *pceltFetched) { 1326 TRY; 1327 1328 unsigned int len = m_parent->getNTypes(); 1329 unsigned int i; 1330 1331 for (i = 0; i < celt && m_idx < len; i++, m_idx++) { 1332 FORMATETC fetc = m_parent->getType(m_idx); 1333 rgelt[i] = fetc; 1334 } 1335 1336 if (pceltFetched != NULL) *pceltFetched = i; 1337 1338 return i == celt ? S_OK : S_FALSE; 1339 1340 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1341 } 1342 1343 /** 1344 * Skip 1345 */ 1346 1347 HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::Skip(ULONG celt) { 1348 TRY; 1349 1350 unsigned int len = m_parent->getNTypes(); 1351 unsigned int tmp = m_idx + celt; 1352 1353 if (tmp < len) { 1354 m_idx = tmp; 1355 1356 return S_OK; 1357 } else { 1358 m_idx = len; 1359 1360 return S_FALSE; 1361 } 1362 1363 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1364 } 1365 1366 /** 1367 * Reset 1368 */ 1369 1370 HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::Reset(void) { 1371 m_idx = 0; 1372 1373 return S_OK; 1374 } 1375 1376 /** 1377 * Clone 1378 */ 1379 1380 HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::Clone(IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenum) { 1381 TRY; 1382 1383 *ppenum = new ADSIEnumFormatEtc(m_parent); 1384 (*ppenum)->Skip(m_idx); 1385 return S_OK; 1386 1387 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1388 } 1389 1390 /** 1391 * constructor 1392 */ 1393 1394 AwtDragSource::ADSIStreamProxy::ADSIStreamProxy(AwtDragSource* parent, jbyteArray buffer, jint blen) { 1395 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1396 1397 m_parent = parent; 1398 1399 m_buffer = (signed char *)safe_Calloc(sizeof(signed char), m_blen = blen); 1400 1401 env->GetByteArrayRegion(buffer, 0, blen, m_buffer); 1402 1403 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) return; 1404 1405 m_off = 0; 1406 1407 m_cloneof = (ADSIStreamProxy*)NULL; 1408 1409 m_refs = 0; 1410 1411 FILETIME now; 1412 1413 ::CoFileTimeNow(&now); 1414 1415 m_statstg.pwcsName = (LPWSTR)NULL; 1416 m_statstg.type = STGTY_STREAM; 1417 m_statstg.cbSize.HighPart = 0; 1418 m_statstg.cbSize.LowPart = m_blen; 1419 m_statstg.mtime = now; 1420 m_statstg.ctime = now; 1421 m_statstg.atime = now; 1422 m_statstg.grfMode = STGM_READ; 1423 m_statstg.grfLocksSupported = FALSE; 1424 m_statstg.clsid = CLSID_NULL; 1425 m_statstg.grfStateBits = 0; 1426 m_statstg.reserved = 0; 1427 1428 m_parent->AddRef(); 1429 1430 AddRef(); 1431 } 1432 1433 /** 1434 * constructor (clone) 1435 */ 1436 1437 AwtDragSource::ADSIStreamProxy::ADSIStreamProxy(ADSIStreamProxy* cloneof) { 1438 m_cloneof = cloneof; 1439 1440 m_parent = cloneof->m_parent; 1441 1442 m_buffer = cloneof->m_buffer; 1443 m_blen = cloneof->m_blen; 1444 m_off = cloneof->m_off; 1445 1446 m_statstg = cloneof->m_statstg; 1447 1448 m_refs = 0; 1449 1450 m_parent->AddRef(); 1451 m_cloneof->AddRef(); 1452 } 1453 1454 /** 1455 * destructor 1456 */ 1457 1458 AwtDragSource::ADSIStreamProxy::~ADSIStreamProxy() { 1459 if (m_cloneof == (ADSIStreamProxy*)NULL) 1460 free((void *)m_buffer); 1461 else { 1462 m_cloneof->Release(); 1463 } 1464 1465 m_parent->Release(); 1466 } 1467 1468 /** 1469 * QueryInterface 1470 */ 1471 1472 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) { 1473 TRY; 1474 1475 if (riid == IID_IUnknown) { 1476 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IUnknown*)this; 1477 AddRef(); 1478 return S_OK; 1479 } else if (riid == IID_IStream) { 1480 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IStream*)this; 1481 AddRef(); 1482 return S_OK; 1483 } else { 1484 *ppvObject = (void __RPC_FAR *__RPC_FAR)NULL; 1485 return E_NOINTERFACE; 1486 } 1487 1488 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1489 } 1490 1491 /** 1492 * AddRef 1493 */ 1494 1495 ULONG __stdcall AwtDragSource::ADSIStreamProxy::AddRef(void) { 1496 return (ULONG)++m_refs; 1497 } 1498 1499 /** 1500 * Release 1501 */ 1502 1503 ULONG __stdcall AwtDragSource::ADSIStreamProxy::Release(void) { 1504 int refs; 1505 1506 if ((refs = --m_refs) == 0) delete this; 1507 1508 return (ULONG)refs; 1509 } 1510 1511 /** 1512 * Read 1513 */ 1514 1515 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead) { 1516 TRY; 1517 1518 unsigned int rem = m_blen - m_off; 1519 int read = cb > rem ? rem : cb; 1520 1521 if (read > 0) memmove(pv, (void *)(m_buffer + m_off), read); 1522 1523 m_off += read; 1524 1525 if (pcbRead != (ULONG __RPC_FAR *)NULL) { 1526 *pcbRead = read; 1527 } 1528 1529 FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; 1530 1531 return S_OK; 1532 1533 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1534 } 1535 1536 /** 1537 * Write 1538 */ 1539 1540 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Write(const void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbWritten) { 1541 TRY; 1542 1543 if (pcbWritten != (ULONG __RPC_FAR *)NULL) { 1544 *pcbWritten = 0; 1545 } 1546 1547 FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; 1548 1549 return STG_E_CANTSAVE; // don't support writing 1550 1551 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1552 } 1553 1554 /** 1555 * Seek 1556 */ 1557 1558 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER __RPC_FAR *plibNewPosition) { 1559 TRY; 1560 1561 if (dlibMove.HighPart != 0) return STG_E_INVALIDPOINTER; 1562 1563 if (plibNewPosition != (ULARGE_INTEGER __RPC_FAR *)NULL) { 1564 plibNewPosition->HighPart = 0; 1565 plibNewPosition->LowPart = 0; 1566 } 1567 1568 switch (dwOrigin) { 1569 case STREAM_SEEK_SET: { 1570 if (dlibMove.HighPart != 0 || dlibMove.LowPart >= m_blen) return STG_E_INVALIDPOINTER; 1571 1572 m_off = dlibMove.LowPart; 1573 } 1574 break; 1575 1576 case STREAM_SEEK_CUR: 1577 case STREAM_SEEK_END: { 1578 if (dlibMove.HighPart > 0) return STG_E_INVALIDPOINTER; 1579 1580 long newoff = (dwOrigin == STREAM_SEEK_END ? m_blen : m_off) + dlibMove.LowPart; 1581 1582 if (newoff < 0 || newoff >= (long)m_blen) 1583 return STG_E_INVALIDPOINTER; 1584 else 1585 m_off = newoff; 1586 } 1587 break; 1588 1589 default: return STG_E_INVALIDFUNCTION; 1590 } 1591 1592 if (plibNewPosition != (ULARGE_INTEGER __RPC_FAR *)NULL) 1593 plibNewPosition->LowPart = m_off; 1594 1595 FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; 1596 1597 return S_OK; 1598 1599 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1600 } 1601 1602 /** 1603 * SetSize 1604 */ 1605 1606 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::SetSize(ULARGE_INTEGER libNewSize) { 1607 return STG_E_INVALIDFUNCTION; 1608 } 1609 1610 /** 1611 * CopyTo 1612 */ 1613 1614 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::CopyTo(IStream __RPC_FAR *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER __RPC_FAR *pcbRead, ULARGE_INTEGER __RPC_FAR *pcbWritten) { 1615 TRY; 1616 1617 ULONG written = 0; 1618 1619 pcbWritten->HighPart = (ULONG)0; 1620 pcbWritten->LowPart = (ULONG)0; 1621 1622 pcbRead->HighPart = (ULONG)0; 1623 1624 unsigned int rem = m_blen - m_off; 1625 int ovrflow = cb.LowPart >= rem; 1626 1627 1628 if (cb.HighPart != 0) return STG_E_INVALIDPOINTER; 1629 1630 ULONG nbytes = pcbRead->LowPart = (ULONG)(ovrflow ? rem : cb.LowPart); 1631 1632 HRESULT res = pstm->Write((const void *)(m_buffer + m_off), nbytes, &written); 1633 1634 pcbWritten->LowPart = written; 1635 1636 FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; 1637 1638 return res; 1639 1640 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1641 } 1642 1643 /** 1644 * Commit 1645 */ 1646 1647 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Commit(DWORD grfCommitFlags) { 1648 return S_OK; 1649 } 1650 1651 /** 1652 * Revert 1653 */ 1654 1655 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Revert() { 1656 return S_OK; 1657 } 1658 1659 /** 1660 * LockRegion 1661 */ 1662 1663 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { 1664 return STG_E_INVALIDFUNCTION; 1665 } 1666 1667 /** 1668 * UnlockRegion 1669 */ 1670 1671 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { 1672 return STG_E_INVALIDFUNCTION; 1673 } 1674 1675 /** 1676 * Stat 1677 */ 1678 1679 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Stat(STATSTG __RPC_FAR *pstatstg, DWORD grfStatFlag) { 1680 TRY; 1681 1682 *pstatstg = m_statstg; 1683 1684 FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; 1685 1686 return S_OK; 1687 1688 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1689 } 1690 1691 /** 1692 * Clone 1693 */ 1694 1695 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Clone(IStream __RPC_FAR *__RPC_FAR *ppstm) { 1696 TRY; 1697 1698 *ppstm = new ADSIStreamProxy(this); 1699 return S_OK; 1700 1701 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1702 } 1703 1704 /*****************************************************************************/ 1705 1706 extern "C" { 1707 1708 /** 1709 * setNativeCursor 1710 */ 1711 1712 JNIEXPORT void JNICALL 1713 Java_sun_awt_windows_WDragSourceContextPeer_setNativeCursor(JNIEnv* env, 1714 jobject self, 1715 jlong nativeCtxt, 1716 jobject cursor, 1717 jint type) { 1718 TRY; 1719 1720 AwtDragSource* ds = (AwtDragSource*)nativeCtxt; 1721 if (ds != NULL) { 1722 ds->SetCursor(cursor); 1723 } 1724 1725 CATCH_BAD_ALLOC; 1726 } 1727 1728 /** 1729 * createDragSource 1730 */ 1731 1732 JNIEXPORT jlong JNICALL 1733 Java_sun_awt_windows_WDragSourceContextPeer_createDragSource( 1734 JNIEnv* env, jobject self, jobject component, jobject transferable, 1735 jobject trigger, jint actions, 1736 jlongArray formats, jobject formatMap) 1737 { 1738 TRY; 1739 1740 if (!AwtDropTarget::IsCurrentDnDDataObject(NULL)) { 1741 JNU_ThrowByName(env, "java/awt/dnd/InvalidDnDOperationException", 1742 "Drag and drop is in progress"); 1743 return (jlong)NULL; 1744 } 1745 1746 AwtDragSource* ds = new AwtDragSource(env, self, component, 1747 transferable, trigger, actions, 1748 formats, formatMap); 1749 1750 DASSERT(AwtDropTarget::IsLocalDataObject(ds)); 1751 1752 return (jlong)ds; 1753 1754 CATCH_BAD_ALLOC_RET(0); 1755 } 1756 1757 /** 1758 * doDragDrop 1759 */ 1760 1761 JNIEXPORT void JNICALL Java_sun_awt_windows_WDragSourceContextPeer_doDragDrop( 1762 JNIEnv* env, 1763 jobject self, 1764 jlong nativeCtxt, 1765 jobject cursor, 1766 jintArray imageData, 1767 jint imageWidth, jint imageHeight, 1768 jint x, jint y) 1769 { 1770 TRY; 1771 1772 cursor = env->NewGlobalRef(cursor); 1773 if (NULL != imageData) { 1774 imageData = (jintArray)env->NewGlobalRef(imageData); 1775 } 1776 1777 AwtDragSource::StartDrag( 1778 (AwtDragSource*)nativeCtxt, 1779 cursor, 1780 imageData, 1781 imageWidth, imageHeight, 1782 x, y); 1783 1784 CATCH_BAD_ALLOC; 1785 } 1786 1787 } /* extern "C" */