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 throw; 426 } 427 428 lFormats = saveFormats; 429 430 for (i = 0, idx = 0; i < items; i++, lFormats++) { 431 // Warning C4244. 432 // Cast from jlong to CLIPFORMAT (WORD). 433 CLIPFORMAT fmt = (CLIPFORMAT)*lFormats; 434 435 m_types[idx].cfFormat = fmt; 436 m_types[idx].dwAspect = DVASPECT_CONTENT; 437 m_types[idx].lindex = -1; 438 439 switch (fmt) { 440 default: 441 m_types[idx].tymed = TYMED_ISTREAM; 442 idx++; 443 444 // now make a copy, but with a TYMED of HGLOBAL 445 m_types[idx] = m_types[idx-1]; 446 m_types[idx].tymed = TYMED_HGLOBAL; 447 idx++; 448 break; 449 case CF_HDROP: 450 m_types[idx].tymed = TYMED_HGLOBAL; 451 idx++; 452 break; 453 case CF_ENHMETAFILE: 454 m_types[idx].tymed = TYMED_ENHMF; 455 idx++; 456 break; 457 case CF_METAFILEPICT: 458 m_types[idx].tymed = TYMED_MFPICT; 459 idx++; 460 break; 461 } 462 } 463 DASSERT(idx == m_ntypes); 464 465 env->ReleaseLongArrayElements(formats, saveFormats, 0); 466 467 // sort them in ascending order of format 468 qsort((void *)m_types, (size_t)m_ntypes, (size_t)sizeof(FORMATETC), 469 _compar); 470 } 471 472 /** 473 * UnloadCache 474 */ 475 476 void AwtDragSource::UnloadCache() { 477 if (m_ntypes == 0) { 478 return; 479 } 480 481 free((void*)m_types); 482 m_ntypes = 0; 483 m_types = (FORMATETC *)NULL; 484 } 485 486 /** 487 * ChangeCursor 488 */ 489 HRESULT AwtDragSource::ChangeCursor() 490 { 491 if (m_cursor != NULL) { 492 ::SetCursor(m_cursor->GetHCursor()); 493 return S_OK; 494 } 495 return DRAGDROP_S_USEDEFAULTCURSORS; 496 } 497 498 /** 499 * SetCursor 500 */ 501 void AwtDragSource::SetCursor(jobject cursor) { 502 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 503 504 if (JNU_IsNull(env, cursor)) { 505 m_cursor = NULL; 506 return; 507 } 508 509 jlong pData = env->GetLongField(cursor, AwtCursor::pDataID); 510 // Warning C4312. 511 // Cast jlong (__int64) to pointer. 512 m_cursor = (AwtCursor*)pData; 513 514 if (m_cursor == NULL) { 515 m_cursor = AwtCursor::CreateSystemCursor(cursor); 516 } 517 } 518 519 /** 520 * MatchFormatEtc 521 */ 522 523 HRESULT __stdcall 524 AwtDragSource::MatchFormatEtc(FORMATETC __RPC_FAR *pFormatEtcIn, 525 FORMATETC *cacheEnt) { 526 TRY; 527 528 const FORMATETC *pFormat = PictureDragHelper::FindFormat(*pFormatEtcIn); 529 if (NULL != pFormat) { 530 if (NULL != cacheEnt) { 531 *cacheEnt = *pFormat; 532 } 533 return S_OK; 534 } 535 536 if ((pFormatEtcIn->tymed & (TYMED_HGLOBAL | TYMED_ISTREAM | TYMED_ENHMF | 537 TYMED_MFPICT)) == 0) { 538 return DV_E_TYMED; 539 } else if (pFormatEtcIn->lindex != -1) { 540 return DV_E_LINDEX; 541 } else if (pFormatEtcIn->dwAspect != DVASPECT_CONTENT) { 542 return DV_E_DVASPECT; 543 } 544 545 FORMATETC tmp = *pFormatEtcIn; 546 547 static const DWORD supportedTymeds[] = 548 { TYMED_ISTREAM, TYMED_HGLOBAL, TYMED_ENHMF, TYMED_MFPICT }; 549 static const int nSupportedTymeds = 4; 550 551 for (int i = 0; i < nSupportedTymeds; i++) { 552 /* 553 * Fix for BugTraq Id 4426805. 554 * Match only if the tymed is supported by the requester. 555 */ 556 if ((pFormatEtcIn->tymed & supportedTymeds[i]) == 0) { 557 continue; 558 } 559 560 tmp.tymed = supportedTymeds[i]; 561 pFormat = (const FORMATETC *)bsearch((const void *)&tmp, 562 (const void *)m_types, 563 (size_t) m_ntypes, 564 (size_t) sizeof(FORMATETC), 565 _compar 566 ); 567 if (NULL != pFormat) { 568 if (cacheEnt != (FORMATETC *)NULL) { 569 *cacheEnt = *pFormat; 570 } 571 return S_OK; 572 } 573 } 574 575 return DV_E_FORMATETC; 576 577 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 578 } 579 580 /** 581 * QueryInterface 582 */ 583 584 HRESULT __stdcall AwtDragSource::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) { 585 TRY; 586 587 if (riid == IID_IUnknown) { 588 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IUnknown*)(IDropSource*)this; 589 AddRef(); 590 return S_OK; 591 } else if (riid == IID_IDropSource) { 592 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IDropSource*)this; 593 AddRef(); 594 return S_OK; 595 } else if (riid == IID_IDataObject) { 596 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IDataObject*)this; 597 AddRef(); 598 return S_OK; 599 } else { 600 *ppvObject = (void __RPC_FAR *__RPC_FAR)NULL; 601 return E_NOINTERFACE; 602 } 603 604 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 605 } 606 607 /** 608 * AddRef 609 */ 610 611 ULONG __stdcall AwtDragSource::AddRef() { 612 return (ULONG)++m_refs; 613 } 614 615 /** 616 * Release 617 */ 618 619 ULONG __stdcall AwtDragSource::Release() { 620 int refs; 621 622 if ((refs = --m_refs) == 0) delete this; 623 624 return (ULONG)refs; 625 } 626 627 /** 628 * QueryContinueDrag 629 */ 630 631 HRESULT __stdcall AwtDragSource::QueryContinueDrag(BOOL fEscapeKeyPressed, DWORD grfKeyState) { 632 AwtToolkit::GetInstance().eventNumber++; 633 TRY; 634 635 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 636 637 if (fEscapeKeyPressed) 638 return DRAGDROP_S_CANCEL; 639 640 jint modifiers = AwtComponent::GetJavaModifiers(); 641 642 POINT dragPoint; 643 644 ::GetCursorPos(&dragPoint); 645 646 if ( (dragPoint.x != m_dragPoint.x || dragPoint.y != m_dragPoint.y) && 647 m_lastmods == modifiers) {//cannot move before cursor change 648 call_dSCmouseMoved(env, m_peer, 649 m_actions, modifiers, dragPoint.x, dragPoint.y); 650 JNU_CHECK_EXCEPTION_RETURN(env, E_UNEXPECTED); 651 m_dragPoint = dragPoint; 652 } 653 654 if ((modifiers & JAVA_BUTTON_MASK) == 0) { 655 return DRAGDROP_S_DROP; 656 } else if (m_initmods == 0) { 657 m_initmods = modifiers; 658 } else if ((modifiers & JAVA_BUTTON_MASK) != (m_initmods & JAVA_BUTTON_MASK)) { 659 return DRAGDROP_S_CANCEL; 660 } else if (m_lastmods != modifiers) { 661 call_dSCchanged(env, m_peer, 662 m_actions, modifiers, dragPoint.x, dragPoint.y); 663 m_bRestoreNodropCustomCursor = TRUE; 664 } 665 666 m_lastmods = modifiers; 667 668 //CR 6480706 - MS Bug on hold 669 HCURSOR hNeedCursor; 670 if ( 671 m_bRestoreNodropCustomCursor && 672 m_cursor != NULL && 673 (hNeedCursor = m_cursor->GetHCursor()) != ::GetCursor() ) 674 { 675 ChangeCursor(); 676 m_bRestoreNodropCustomCursor = FALSE; 677 } 678 return S_OK; 679 680 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 681 } 682 683 /** 684 * GiveFeedback 685 */ 686 687 HRESULT __stdcall AwtDragSource::GiveFeedback(DWORD dwEffect) { 688 AwtToolkit::GetInstance().eventNumber++; 689 TRY; 690 691 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 692 jint modifiers = 0; 693 SHORT mods = 0; 694 695 m_actions = convertDROPEFFECTToActions(dwEffect); 696 697 if (::GetKeyState(VK_LBUTTON) & 0xff00) { 698 mods |= MK_LBUTTON; 699 } else if (::GetKeyState(VK_MBUTTON) & 0xff00) { 700 mods |= MK_MBUTTON; 701 } else if (::GetKeyState(VK_RBUTTON) & 0xff00) { 702 mods |= MK_RBUTTON; 703 } 704 705 if (::GetKeyState(VK_SHIFT) & 0xff00) 706 mods |= MK_SHIFT; 707 if (::GetKeyState(VK_CONTROL) & 0xff00) 708 mods |= MK_CONTROL; 709 if (::GetKeyState(VK_MENU) & 0xff00) 710 mods |= MK_ALT; 711 712 modifiers = AwtComponent::GetJavaModifiers(); 713 714 POINT curs; 715 716 ::GetCursorPos(&curs); 717 718 m_droptarget = ::WindowFromPoint(curs); 719 720 int invalid = (dwEffect == DROPEFFECT_NONE); 721 722 if (invalid) { 723 // Don't call dragExit if dragEnter and dragOver haven't been called. 724 if (!m_enterpending) { 725 call_dSCexit(env, m_peer, curs.x, curs.y); 726 } 727 m_droptarget = (HWND)NULL; 728 m_enterpending = TRUE; 729 } else if (m_droptarget != NULL) { 730 (*(m_enterpending ? call_dSCenter : call_dSCmotion)) 731 (env, m_peer, m_actions, modifiers, curs.x, curs.y); 732 733 m_enterpending = FALSE; 734 } 735 736 if (m_droptarget != NULL) { 737 RECT rect; 738 POINT client = curs; 739 VERIFY(::ScreenToClient(m_droptarget, &client)); 740 VERIFY(::GetClientRect(m_droptarget, &rect)); 741 if (::PtInRect(&rect, client)) { 742 m_fNC = FALSE; 743 m_dropPoint = client; 744 } else { 745 m_fNC = TRUE; 746 m_dropPoint = curs; 747 } 748 } else { 749 m_fNC = TRUE; 750 m_dropPoint.x = 0; 751 m_dropPoint.y = 0; 752 } 753 754 m_bRestoreNodropCustomCursor = (dwEffect == DROPEFFECT_NONE); 755 756 return ChangeCursor(); 757 758 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 759 } 760 761 762 /** 763 * GetData 764 */ 765 766 HRESULT __stdcall AwtDragSource::GetData(FORMATETC __RPC_FAR *pFormatEtc, 767 STGMEDIUM __RPC_FAR *pmedium) { 768 AwtToolkit::GetInstance().eventNumber++; 769 TRY; 770 STGMEDIUM *pPicMedia = PictureDragHelper::FindData(*pFormatEtc); 771 if (NULL != pPicMedia) { 772 *pmedium = *pPicMedia; 773 //return outside, so AddRef the instance of pstm or hGlobal! 774 if (pmedium->tymed == TYMED_ISTREAM) { 775 pmedium->pstm->AddRef(); 776 pmedium->pUnkForRelease = (IUnknown *)NULL; 777 } else if (pmedium->tymed == TYMED_HGLOBAL) { 778 AddRef(); 779 pmedium->pUnkForRelease = (IDropSource *)this; 780 } 781 return S_OK; 782 } 783 784 HRESULT res = GetProcessId(pFormatEtc, pmedium); 785 if (res == S_OK) { 786 return res; 787 } 788 789 FORMATETC matchedFormatEtc; 790 res = MatchFormatEtc(pFormatEtc, &matchedFormatEtc); 791 if (res != S_OK) { 792 return res; 793 } 794 795 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 796 797 if (env->PushLocalFrame(2) < 0) { 798 return E_OUTOFMEMORY; 799 } 800 801 jbyteArray bytes = 802 AwtDataTransferer::ConvertData(env, m_component, m_transferable, 803 (jlong)matchedFormatEtc.cfFormat, 804 m_formatMap); 805 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 806 env->ExceptionDescribe(); 807 env->ExceptionClear(); 808 env->PopLocalFrame(NULL); 809 return E_UNEXPECTED; 810 } 811 if (bytes == NULL) { 812 env->PopLocalFrame(NULL); 813 return E_UNEXPECTED; 814 } 815 816 jint nBytes = env->GetArrayLength(bytes); 817 818 if ((matchedFormatEtc.tymed & TYMED_ISTREAM) != 0) { 819 ADSIStreamProxy *istream = new ADSIStreamProxy(this, bytes, nBytes); 820 821 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 822 env->ExceptionDescribe(); 823 env->ExceptionClear(); 824 env->PopLocalFrame(NULL); 825 return E_UNEXPECTED; 826 } 827 828 pmedium->tymed = TYMED_ISTREAM; 829 pmedium->pstm = istream; 830 pmedium->pUnkForRelease = (IUnknown *)NULL; 831 832 env->PopLocalFrame(NULL); 833 return S_OK; 834 } else if ((matchedFormatEtc.tymed & TYMED_HGLOBAL) != 0) { 835 HGLOBAL copy = ::GlobalAlloc(GALLOCFLG, nBytes + 836 ((matchedFormatEtc.cfFormat == CF_HDROP) 837 ? sizeof(DROPFILES) 838 : 0)); 839 if (copy == NULL) { 840 env->PopLocalFrame(NULL); 841 throw std::bad_alloc(); 842 } 843 844 char *dataout = (char *)::GlobalLock(copy); 845 846 if (matchedFormatEtc.cfFormat == CF_HDROP) { 847 DROPFILES *dropfiles = (DROPFILES *)dataout; 848 dropfiles->pFiles = sizeof(DROPFILES); 849 dropfiles->pt.x = m_dropPoint.x; 850 dropfiles->pt.y = m_dropPoint.y; 851 dropfiles->fNC = m_fNC; 852 dropfiles->fWide = TRUE; // we publish only Unicode 853 dataout += sizeof(DROPFILES); 854 } 855 856 env->GetByteArrayRegion(bytes, 0, nBytes, (jbyte *)dataout); 857 ::GlobalUnlock(copy); 858 859 pmedium->tymed = TYMED_HGLOBAL; 860 pmedium->hGlobal = copy; 861 pmedium->pUnkForRelease = (IUnknown *)NULL; 862 863 env->PopLocalFrame(NULL); 864 return S_OK; 865 } else if ((matchedFormatEtc.tymed & TYMED_ENHMF) != 0) { 866 LPBYTE lpbEmfBuffer = 867 (LPBYTE)env->GetPrimitiveArrayCritical(bytes, NULL); 868 if (lpbEmfBuffer == NULL) { 869 env->PopLocalFrame(NULL); 870 throw std::bad_alloc(); 871 } 872 873 HENHMETAFILE hemf = ::SetEnhMetaFileBits(nBytes, lpbEmfBuffer); 874 875 env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbEmfBuffer, JNI_ABORT); 876 877 if (hemf == NULL) { 878 env->PopLocalFrame(NULL); 879 return E_UNEXPECTED; 880 } 881 882 pmedium->tymed = TYMED_ENHMF; 883 pmedium->hEnhMetaFile = hemf; 884 pmedium->pUnkForRelease = (IUnknown *)NULL; 885 886 env->PopLocalFrame(NULL); 887 return S_OK; 888 } else if ((matchedFormatEtc.tymed & TYMED_MFPICT) != 0) { 889 LPBYTE lpbMfpBuffer = 890 (LPBYTE)env->GetPrimitiveArrayCritical(bytes, NULL); 891 if (lpbMfpBuffer == NULL) { 892 env->PopLocalFrame(NULL); 893 throw std::bad_alloc(); 894 } 895 896 HMETAFILE hmf = ::SetMetaFileBitsEx(nBytes - sizeof(METAFILEPICT), 897 lpbMfpBuffer + sizeof(METAFILEPICT)); 898 if (hmf == NULL) { 899 env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbMfpBuffer, JNI_ABORT); 900 env->PopLocalFrame(NULL); 901 return E_UNEXPECTED; 902 } 903 904 LPMETAFILEPICT lpMfpOld = (LPMETAFILEPICT)lpbMfpBuffer; 905 906 HMETAFILEPICT hmfp = ::GlobalAlloc(GALLOCFLG, sizeof(METAFILEPICT)); 907 if (hmfp == NULL) { 908 VERIFY(::DeleteMetaFile(hmf)); 909 env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbMfpBuffer, JNI_ABORT); 910 env->PopLocalFrame(NULL); 911 throw std::bad_alloc(); 912 } 913 914 LPMETAFILEPICT lpMfp = (LPMETAFILEPICT)::GlobalLock(hmfp); 915 lpMfp->mm = lpMfpOld->mm; 916 lpMfp->xExt = lpMfpOld->xExt; 917 lpMfp->yExt = lpMfpOld->yExt; 918 lpMfp->hMF = hmf; 919 ::GlobalUnlock(hmfp); 920 921 env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbMfpBuffer, JNI_ABORT); 922 923 pmedium->tymed = TYMED_MFPICT; 924 pmedium->hMetaFilePict = hmfp; 925 pmedium->pUnkForRelease = (IUnknown *)NULL; 926 927 env->PopLocalFrame(NULL); 928 return S_OK; 929 } 930 931 env->PopLocalFrame(NULL); 932 return DV_E_TYMED; 933 934 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 935 } 936 937 /** 938 * GetDataHere 939 */ 940 941 HRESULT __stdcall AwtDragSource::GetDataHere(FORMATETC __RPC_FAR *pFormatEtc, 942 STGMEDIUM __RPC_FAR *pmedium) { 943 AwtToolkit::GetInstance().eventNumber++; 944 TRY; 945 946 if (pmedium->pUnkForRelease != (IUnknown *)NULL) { 947 return E_INVALIDARG; 948 } 949 950 HRESULT res = GetProcessId(pFormatEtc, pmedium); 951 if (res == S_OK) { 952 return res; 953 } 954 955 FORMATETC matchedFormatEtc; 956 res = MatchFormatEtc(pFormatEtc, &matchedFormatEtc); 957 if (res != S_OK) { 958 return res; 959 } 960 961 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 962 963 if (env->PushLocalFrame(2) < 0) { 964 return E_OUTOFMEMORY; 965 } 966 967 jbyteArray bytes = 968 AwtDataTransferer::ConvertData(env, m_component, m_transferable, 969 (jlong)matchedFormatEtc.cfFormat, 970 m_formatMap); 971 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 972 env->ExceptionDescribe(); 973 env->ExceptionClear(); 974 env->PopLocalFrame(NULL); 975 return E_UNEXPECTED; 976 } 977 if (bytes == NULL) { 978 env->PopLocalFrame(NULL); 979 return E_UNEXPECTED; 980 } 981 982 jint nBytes = env->GetArrayLength(bytes); 983 984 // NOTE: TYMED_ENHMF and TYMED_MFPICT are not valid for GetDataHere(). 985 if ((matchedFormatEtc.tymed & TYMED_ISTREAM) != 0) { 986 jboolean isCopy; 987 jbyte *bBytes = env->GetByteArrayElements(bytes, &isCopy); 988 if (bBytes == NULL) { 989 env->PopLocalFrame(NULL); 990 return E_UNEXPECTED; 991 } 992 993 ULONG act; 994 HRESULT res = pmedium->pstm->Write((const void *)bBytes, (ULONG)nBytes, 995 &act); 996 997 env->ReleaseByteArrayElements(bytes, bBytes, JNI_ABORT); 998 999 env->PopLocalFrame(NULL); 1000 return S_OK; 1001 } else if ((matchedFormatEtc.tymed & TYMED_HGLOBAL) != 0) { 1002 ::SetLastError(0); // clear error 1003 // Warning C4244. 1004 SIZE_T mBytes = ::GlobalSize(pmedium->hGlobal); 1005 if (::GetLastError() != 0) { 1006 env->PopLocalFrame(NULL); 1007 return E_UNEXPECTED; 1008 } 1009 1010 if (nBytes + ((matchedFormatEtc.cfFormat == CF_HDROP) 1011 ? sizeof(DROPFILES) : 0) > mBytes) { 1012 env->PopLocalFrame(NULL); 1013 return STG_E_MEDIUMFULL; 1014 } 1015 1016 char *dataout = (char *)::GlobalLock(pmedium->hGlobal); 1017 1018 if (matchedFormatEtc.cfFormat == CF_HDROP) { 1019 DROPFILES *dropfiles = (DROPFILES *)dataout; 1020 dropfiles->pFiles = sizeof(DROPFILES); 1021 dropfiles->pt.x = m_dropPoint.x; 1022 dropfiles->pt.y = m_dropPoint.y; 1023 dropfiles->fNC = m_fNC; 1024 dropfiles->fWide = TRUE; // good guess! 1025 dataout += sizeof(DROPFILES); 1026 } 1027 1028 env->GetByteArrayRegion(bytes, 0, nBytes, (jbyte *)dataout); 1029 ::GlobalUnlock(pmedium->hGlobal); 1030 1031 env->PopLocalFrame(NULL); 1032 return S_OK; 1033 } 1034 1035 env->PopLocalFrame(NULL); 1036 return DV_E_TYMED; 1037 1038 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1039 } 1040 1041 /** 1042 * QueryGetData 1043 */ 1044 1045 HRESULT __stdcall AwtDragSource::QueryGetData(FORMATETC __RPC_FAR *pFormatEtc) { 1046 AwtToolkit::GetInstance().eventNumber++; 1047 TRY; 1048 1049 return MatchFormatEtc(pFormatEtc, (FORMATETC *)NULL); 1050 1051 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1052 } 1053 1054 1055 /** 1056 * GetCanonicalFormatEtc 1057 */ 1058 1059 HRESULT __stdcall AwtDragSource::GetCanonicalFormatEtc(FORMATETC __RPC_FAR *pFormatEtcIn, FORMATETC __RPC_FAR *pFormatEtcOut) { 1060 AwtToolkit::GetInstance().eventNumber++; 1061 TRY; 1062 1063 HRESULT res = MatchFormatEtc(pFormatEtcIn, (FORMATETC *)NULL); 1064 1065 if (res != S_OK) return res; 1066 1067 *pFormatEtcOut = *pFormatEtcIn; 1068 1069 pFormatEtcOut->ptd = NULL; 1070 1071 return DATA_S_SAMEFORMATETC; 1072 1073 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1074 } 1075 1076 /** 1077 * SetData 1078 */ 1079 1080 HRESULT __stdcall AwtDragSource::SetData(FORMATETC __RPC_FAR *pFormatEtc, STGMEDIUM __RPC_FAR *pmedium, BOOL fRelease) { 1081 AwtToolkit::GetInstance().eventNumber++; 1082 if (pFormatEtc->cfFormat == CF_PERFORMEDDROPEFFECT && pmedium->tymed == TYMED_HGLOBAL) { 1083 m_dwPerformedDropEffect = *(DWORD*)::GlobalLock(pmedium->hGlobal); 1084 ::GlobalUnlock(pmedium->hGlobal); 1085 if (fRelease) { 1086 ::ReleaseStgMedium(pmedium); 1087 } 1088 return S_OK; 1089 } 1090 1091 if (fRelease) { 1092 //we are copying pmedium as a structure for further use, so no any release! 1093 PictureDragHelper::SetData(*pFormatEtc, *pmedium); 1094 return S_OK; 1095 } 1096 return E_UNEXPECTED; 1097 } 1098 1099 /** 1100 * EnumFormatEtc 1101 */ 1102 1103 HRESULT __stdcall AwtDragSource::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC *__RPC_FAR *ppenumFormatEtc) { 1104 AwtToolkit::GetInstance().eventNumber++; 1105 TRY; 1106 1107 *ppenumFormatEtc = new ADSIEnumFormatEtc(this); 1108 return S_OK; 1109 1110 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1111 } 1112 1113 /** 1114 * DAdvise 1115 */ 1116 1117 HRESULT __stdcall AwtDragSource::DAdvise(FORMATETC __RPC_FAR *pFormatEtc, DWORD advf, IAdviseSink __RPC_FAR *pAdvSink, DWORD __RPC_FAR *pdwConnection) { 1118 AwtToolkit::GetInstance().eventNumber++; 1119 return E_NOTIMPL; 1120 } 1121 1122 /** 1123 * DUnadvise 1124 */ 1125 1126 HRESULT __stdcall AwtDragSource::DUnadvise(DWORD dwConnection) { 1127 AwtToolkit::GetInstance().eventNumber++; 1128 return OLE_E_ADVISENOTSUPPORTED; 1129 } 1130 1131 /** 1132 * EnumAdvise 1133 */ 1134 1135 HRESULT __stdcall AwtDragSource::EnumDAdvise(IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise) { 1136 AwtToolkit::GetInstance().eventNumber++; 1137 return OLE_E_ADVISENOTSUPPORTED; 1138 } 1139 1140 const UINT AwtDragSource::PROCESS_ID_FORMAT = 1141 ::RegisterClipboardFormat(TEXT("_SUNW_JAVA_AWT_PROCESS_ID")); 1142 1143 HRESULT __stdcall AwtDragSource::GetProcessId(FORMATETC __RPC_FAR *pFormatEtc, STGMEDIUM __RPC_FAR *pmedium) { 1144 AwtToolkit::GetInstance().eventNumber++; 1145 if ((pFormatEtc->tymed & TYMED_HGLOBAL) == 0) { 1146 return DV_E_TYMED; 1147 } else if (pFormatEtc->lindex != -1) { 1148 return DV_E_LINDEX; 1149 } else if (pFormatEtc->dwAspect != DVASPECT_CONTENT) { 1150 return DV_E_DVASPECT; 1151 } else if (pFormatEtc->cfFormat != PROCESS_ID_FORMAT) { 1152 return DV_E_FORMATETC; 1153 } 1154 1155 DWORD id = ::CoGetCurrentProcess(); 1156 1157 HGLOBAL copy = ::GlobalAlloc(GALLOCFLG, sizeof(id)); 1158 1159 if (copy == NULL) { 1160 throw std::bad_alloc(); 1161 } 1162 1163 char *dataout = (char *)::GlobalLock(copy); 1164 1165 memcpy(dataout, &id, sizeof(id)); 1166 ::GlobalUnlock(copy); 1167 1168 pmedium->tymed = TYMED_HGLOBAL; 1169 pmedium->hGlobal = copy; 1170 pmedium->pUnkForRelease = (IUnknown *)NULL; 1171 1172 return S_OK; 1173 } 1174 1175 DECLARE_JAVA_CLASS(dSCClazz, "sun/awt/windows/WDragSourceContextPeer") 1176 1177 void 1178 AwtDragSource::call_dSCenter(JNIEnv* env, jobject self, jint targetActions, 1179 jint modifiers, jint x, jint y) { 1180 DECLARE_VOID_JAVA_METHOD(dSCenter, dSCClazz, "dragEnter", "(IIII)V"); 1181 DASSERT(!JNU_IsNull(env, self)); 1182 env->CallVoidMethod(self, dSCenter, targetActions, modifiers, x, y); 1183 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1184 env->ExceptionDescribe(); 1185 env->ExceptionClear(); 1186 } 1187 } 1188 1189 void 1190 AwtDragSource::call_dSCmotion(JNIEnv* env, jobject self, jint targetActions, 1191 jint modifiers, jint x, jint y) { 1192 DECLARE_VOID_JAVA_METHOD(dSCmotion, dSCClazz, "dragMotion", "(IIII)V"); 1193 DASSERT(!JNU_IsNull(env, self)); 1194 env->CallVoidMethod(self, dSCmotion, targetActions, modifiers, x, y); 1195 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1196 env->ExceptionDescribe(); 1197 env->ExceptionClear(); 1198 } 1199 } 1200 1201 void 1202 AwtDragSource::call_dSCchanged(JNIEnv* env, jobject self, jint targetActions, 1203 jint modifiers, jint x, jint y) { 1204 DECLARE_VOID_JAVA_METHOD(dSCchanged, dSCClazz, "operationChanged", 1205 "(IIII)V"); 1206 DASSERT(!JNU_IsNull(env, self)); 1207 env->CallVoidMethod(self, dSCchanged, targetActions, modifiers, x, y); 1208 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1209 env->ExceptionDescribe(); 1210 env->ExceptionClear(); 1211 } 1212 } 1213 1214 void 1215 AwtDragSource::call_dSCexit(JNIEnv* env, jobject self, jint x, jint y) { 1216 DECLARE_VOID_JAVA_METHOD(dSCexit, dSCClazz, "dragExit", "(II)V"); 1217 DASSERT(!JNU_IsNull(env, self)); 1218 env->CallVoidMethod(self, dSCexit, x, y); 1219 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1220 env->ExceptionDescribe(); 1221 env->ExceptionClear(); 1222 } 1223 } 1224 1225 void 1226 AwtDragSource::call_dSCddfinished(JNIEnv* env, jobject self, jboolean success, 1227 jint operations, jint x, jint y) { 1228 DECLARE_VOID_JAVA_METHOD(dSCddfinished, dSCClazz, "dragDropFinished", "(ZIII)V"); 1229 DASSERT(!JNU_IsNull(env, self)); 1230 env->CallVoidMethod(self, dSCddfinished, success, operations, x, y); 1231 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1232 env->ExceptionDescribe(); 1233 env->ExceptionClear(); 1234 } 1235 } 1236 1237 void 1238 AwtDragSource::call_dSCmouseMoved(JNIEnv* env, jobject self, jint targetActions, 1239 jint modifiers, jint x, jint y) { 1240 DECLARE_VOID_JAVA_METHOD(dSCmouseMoved, dSCClazz, "dragMouseMoved", 1241 "(IIII)V"); 1242 DASSERT(!JNU_IsNull(env, self)); 1243 env->CallVoidMethod(self, dSCmouseMoved, targetActions, modifiers, x, y); 1244 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1245 env->ExceptionDescribe(); 1246 env->ExceptionClear(); 1247 } 1248 } 1249 1250 DECLARE_JAVA_CLASS(awtIEClazz, "java/awt/event/InputEvent") 1251 1252 /** 1253 * Constructor 1254 */ 1255 1256 AwtDragSource::ADSIEnumFormatEtc::ADSIEnumFormatEtc(AwtDragSource* parent) { 1257 m_parent = parent; 1258 m_idx = 0; 1259 1260 m_refs = 0; 1261 1262 m_parent->AddRef(); 1263 1264 AddRef(); 1265 } 1266 1267 /** 1268 * Destructor 1269 */ 1270 1271 AwtDragSource::ADSIEnumFormatEtc::~ADSIEnumFormatEtc() { 1272 m_parent->Release(); 1273 } 1274 1275 /** 1276 * QueryInterface 1277 */ 1278 1279 HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) { 1280 TRY; 1281 1282 if (riid == IID_IUnknown) { 1283 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IUnknown*)this; 1284 AddRef(); 1285 return S_OK; 1286 } else if (riid == IID_IEnumFORMATETC) { 1287 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IEnumFORMATETC*)this; 1288 AddRef(); 1289 return S_OK; 1290 } else { 1291 *ppvObject = (void __RPC_FAR *__RPC_FAR)NULL; 1292 return E_NOINTERFACE; 1293 } 1294 1295 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1296 } 1297 1298 /** 1299 * AddRef 1300 */ 1301 1302 ULONG __stdcall AwtDragSource::ADSIEnumFormatEtc::AddRef(void) { 1303 return (ULONG)++m_refs; 1304 } 1305 1306 /** 1307 * Release 1308 */ 1309 1310 ULONG __stdcall AwtDragSource::ADSIEnumFormatEtc::Release(void) { 1311 int refs; 1312 1313 if ((refs = --m_refs) == 0) delete this; 1314 1315 return (ULONG)refs; 1316 } 1317 1318 /** 1319 * Next 1320 */ 1321 1322 HRESULT _stdcall AwtDragSource::ADSIEnumFormatEtc::Next(ULONG celt, FORMATETC __RPC_FAR *rgelt, ULONG __RPC_FAR *pceltFetched) { 1323 TRY; 1324 1325 unsigned int len = m_parent->getNTypes(); 1326 unsigned int i; 1327 1328 for (i = 0; i < celt && m_idx < len; i++, m_idx++) { 1329 FORMATETC fetc = m_parent->getType(m_idx); 1330 rgelt[i] = fetc; 1331 } 1332 1333 if (pceltFetched != NULL) *pceltFetched = i; 1334 1335 return i == celt ? S_OK : S_FALSE; 1336 1337 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1338 } 1339 1340 /** 1341 * Skip 1342 */ 1343 1344 HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::Skip(ULONG celt) { 1345 TRY; 1346 1347 unsigned int len = m_parent->getNTypes(); 1348 unsigned int tmp = m_idx + celt; 1349 1350 if (tmp < len) { 1351 m_idx = tmp; 1352 1353 return S_OK; 1354 } else { 1355 m_idx = len; 1356 1357 return S_FALSE; 1358 } 1359 1360 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1361 } 1362 1363 /** 1364 * Reset 1365 */ 1366 1367 HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::Reset(void) { 1368 m_idx = 0; 1369 1370 return S_OK; 1371 } 1372 1373 /** 1374 * Clone 1375 */ 1376 1377 HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::Clone(IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenum) { 1378 TRY; 1379 1380 *ppenum = new ADSIEnumFormatEtc(m_parent); 1381 (*ppenum)->Skip(m_idx); 1382 return S_OK; 1383 1384 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1385 } 1386 1387 /** 1388 * constructor 1389 */ 1390 1391 AwtDragSource::ADSIStreamProxy::ADSIStreamProxy(AwtDragSource* parent, jbyteArray buffer, jint blen) { 1392 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1393 1394 m_parent = parent; 1395 1396 m_buffer = (signed char *)safe_Calloc(sizeof(signed char), m_blen = blen); 1397 1398 env->GetByteArrayRegion(buffer, 0, blen, m_buffer); 1399 1400 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) return; 1401 1402 m_off = 0; 1403 1404 m_cloneof = (ADSIStreamProxy*)NULL; 1405 1406 m_refs = 0; 1407 1408 FILETIME now; 1409 1410 ::CoFileTimeNow(&now); 1411 1412 m_statstg.pwcsName = (LPWSTR)NULL; 1413 m_statstg.type = STGTY_STREAM; 1414 m_statstg.cbSize.HighPart = 0; 1415 m_statstg.cbSize.LowPart = m_blen; 1416 m_statstg.mtime = now; 1417 m_statstg.ctime = now; 1418 m_statstg.atime = now; 1419 m_statstg.grfMode = STGM_READ; 1420 m_statstg.grfLocksSupported = FALSE; 1421 m_statstg.clsid = CLSID_NULL; 1422 m_statstg.grfStateBits = 0; 1423 m_statstg.reserved = 0; 1424 1425 m_parent->AddRef(); 1426 1427 AddRef(); 1428 } 1429 1430 /** 1431 * constructor (clone) 1432 */ 1433 1434 AwtDragSource::ADSIStreamProxy::ADSIStreamProxy(ADSIStreamProxy* cloneof) { 1435 m_cloneof = cloneof; 1436 1437 m_parent = cloneof->m_parent; 1438 1439 m_buffer = cloneof->m_buffer; 1440 m_blen = cloneof->m_blen; 1441 m_off = cloneof->m_off; 1442 1443 m_statstg = cloneof->m_statstg; 1444 1445 m_refs = 0; 1446 1447 m_parent->AddRef(); 1448 m_cloneof->AddRef(); 1449 } 1450 1451 /** 1452 * destructor 1453 */ 1454 1455 AwtDragSource::ADSIStreamProxy::~ADSIStreamProxy() { 1456 if (m_cloneof == (ADSIStreamProxy*)NULL) 1457 free((void *)m_buffer); 1458 else { 1459 m_cloneof->Release(); 1460 } 1461 1462 m_parent->Release(); 1463 } 1464 1465 /** 1466 * QueryInterface 1467 */ 1468 1469 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) { 1470 TRY; 1471 1472 if (riid == IID_IUnknown) { 1473 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IUnknown*)this; 1474 AddRef(); 1475 return S_OK; 1476 } else if (riid == IID_IStream) { 1477 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IStream*)this; 1478 AddRef(); 1479 return S_OK; 1480 } else { 1481 *ppvObject = (void __RPC_FAR *__RPC_FAR)NULL; 1482 return E_NOINTERFACE; 1483 } 1484 1485 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1486 } 1487 1488 /** 1489 * AddRef 1490 */ 1491 1492 ULONG __stdcall AwtDragSource::ADSIStreamProxy::AddRef(void) { 1493 return (ULONG)++m_refs; 1494 } 1495 1496 /** 1497 * Release 1498 */ 1499 1500 ULONG __stdcall AwtDragSource::ADSIStreamProxy::Release(void) { 1501 int refs; 1502 1503 if ((refs = --m_refs) == 0) delete this; 1504 1505 return (ULONG)refs; 1506 } 1507 1508 /** 1509 * Read 1510 */ 1511 1512 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead) { 1513 TRY; 1514 1515 unsigned int rem = m_blen - m_off; 1516 int read = cb > rem ? rem : cb; 1517 1518 if (read > 0) memmove(pv, (void *)(m_buffer + m_off), read); 1519 1520 m_off += read; 1521 1522 if (pcbRead != (ULONG __RPC_FAR *)NULL) { 1523 *pcbRead = read; 1524 } 1525 1526 FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; 1527 1528 return S_OK; 1529 1530 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1531 } 1532 1533 /** 1534 * Write 1535 */ 1536 1537 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Write(const void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbWritten) { 1538 TRY; 1539 1540 if (pcbWritten != (ULONG __RPC_FAR *)NULL) { 1541 *pcbWritten = 0; 1542 } 1543 1544 FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; 1545 1546 return STG_E_CANTSAVE; // don't support writing 1547 1548 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1549 } 1550 1551 /** 1552 * Seek 1553 */ 1554 1555 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER __RPC_FAR *plibNewPosition) { 1556 TRY; 1557 1558 if (dlibMove.HighPart != 0) return STG_E_INVALIDPOINTER; 1559 1560 if (plibNewPosition != (ULARGE_INTEGER __RPC_FAR *)NULL) { 1561 plibNewPosition->HighPart = 0; 1562 plibNewPosition->LowPart = 0; 1563 } 1564 1565 switch (dwOrigin) { 1566 case STREAM_SEEK_SET: { 1567 if (dlibMove.HighPart != 0 || dlibMove.LowPart >= m_blen) return STG_E_INVALIDPOINTER; 1568 1569 m_off = dlibMove.LowPart; 1570 } 1571 break; 1572 1573 case STREAM_SEEK_CUR: 1574 case STREAM_SEEK_END: { 1575 if (dlibMove.HighPart > 0) return STG_E_INVALIDPOINTER; 1576 1577 long newoff = (dwOrigin == STREAM_SEEK_END ? m_blen : m_off) + dlibMove.LowPart; 1578 1579 if (newoff < 0 || newoff >= (long)m_blen) 1580 return STG_E_INVALIDPOINTER; 1581 else 1582 m_off = newoff; 1583 } 1584 break; 1585 1586 default: return STG_E_INVALIDFUNCTION; 1587 } 1588 1589 if (plibNewPosition != (ULARGE_INTEGER __RPC_FAR *)NULL) 1590 plibNewPosition->LowPart = m_off; 1591 1592 FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; 1593 1594 return S_OK; 1595 1596 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1597 } 1598 1599 /** 1600 * SetSize 1601 */ 1602 1603 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::SetSize(ULARGE_INTEGER libNewSize) { 1604 return STG_E_INVALIDFUNCTION; 1605 } 1606 1607 /** 1608 * CopyTo 1609 */ 1610 1611 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::CopyTo(IStream __RPC_FAR *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER __RPC_FAR *pcbRead, ULARGE_INTEGER __RPC_FAR *pcbWritten) { 1612 TRY; 1613 1614 ULONG written = 0; 1615 1616 pcbWritten->HighPart = (ULONG)0; 1617 pcbWritten->LowPart = (ULONG)0; 1618 1619 pcbRead->HighPart = (ULONG)0; 1620 1621 unsigned int rem = m_blen - m_off; 1622 int ovrflow = cb.LowPart >= rem; 1623 1624 1625 if (cb.HighPart != 0) return STG_E_INVALIDPOINTER; 1626 1627 ULONG nbytes = pcbRead->LowPart = (ULONG)(ovrflow ? rem : cb.LowPart); 1628 1629 HRESULT res = pstm->Write((const void *)(m_buffer + m_off), nbytes, &written); 1630 1631 pcbWritten->LowPart = written; 1632 1633 FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; 1634 1635 return res; 1636 1637 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1638 } 1639 1640 /** 1641 * Commit 1642 */ 1643 1644 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Commit(DWORD grfCommitFlags) { 1645 return S_OK; 1646 } 1647 1648 /** 1649 * Revert 1650 */ 1651 1652 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Revert() { 1653 return S_OK; 1654 } 1655 1656 /** 1657 * LockRegion 1658 */ 1659 1660 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { 1661 return STG_E_INVALIDFUNCTION; 1662 } 1663 1664 /** 1665 * UnlockRegion 1666 */ 1667 1668 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { 1669 return STG_E_INVALIDFUNCTION; 1670 } 1671 1672 /** 1673 * Stat 1674 */ 1675 1676 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Stat(STATSTG __RPC_FAR *pstatstg, DWORD grfStatFlag) { 1677 TRY; 1678 1679 *pstatstg = m_statstg; 1680 1681 FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; 1682 1683 return S_OK; 1684 1685 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1686 } 1687 1688 /** 1689 * Clone 1690 */ 1691 1692 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Clone(IStream __RPC_FAR *__RPC_FAR *ppstm) { 1693 TRY; 1694 1695 *ppstm = new ADSIStreamProxy(this); 1696 return S_OK; 1697 1698 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1699 } 1700 1701 /*****************************************************************************/ 1702 1703 extern "C" { 1704 1705 /** 1706 * setNativeCursor 1707 */ 1708 1709 JNIEXPORT void JNICALL 1710 Java_sun_awt_windows_WDragSourceContextPeer_setNativeCursor(JNIEnv* env, 1711 jobject self, 1712 jlong nativeCtxt, 1713 jobject cursor, 1714 jint type) { 1715 TRY; 1716 1717 AwtDragSource* ds = (AwtDragSource*)nativeCtxt; 1718 if (ds != NULL) { 1719 ds->SetCursor(cursor); 1720 } 1721 1722 CATCH_BAD_ALLOC; 1723 } 1724 1725 /** 1726 * createDragSource 1727 */ 1728 1729 JNIEXPORT jlong JNICALL 1730 Java_sun_awt_windows_WDragSourceContextPeer_createDragSource( 1731 JNIEnv* env, jobject self, jobject component, jobject transferable, 1732 jobject trigger, jint actions, 1733 jlongArray formats, jobject formatMap) 1734 { 1735 TRY; 1736 1737 if (!AwtDropTarget::IsCurrentDnDDataObject(NULL)) { 1738 JNU_ThrowByName(env, "java/awt/dnd/InvalidDnDOperationException", 1739 "Drag and drop is in progress"); 1740 return (jlong)NULL; 1741 } 1742 1743 AwtDragSource* ds = new AwtDragSource(env, self, component, 1744 transferable, trigger, actions, 1745 formats, formatMap); 1746 1747 DASSERT(AwtDropTarget::IsLocalDataObject(ds)); 1748 1749 return (jlong)ds; 1750 1751 CATCH_BAD_ALLOC_RET(0); 1752 } 1753 1754 /** 1755 * doDragDrop 1756 */ 1757 1758 JNIEXPORT void JNICALL Java_sun_awt_windows_WDragSourceContextPeer_doDragDrop( 1759 JNIEnv* env, 1760 jobject self, 1761 jlong nativeCtxt, 1762 jobject cursor, 1763 jintArray imageData, 1764 jint imageWidth, jint imageHeight, 1765 jint x, jint y) 1766 { 1767 TRY; 1768 1769 cursor = env->NewGlobalRef(cursor); 1770 if (NULL != imageData) { 1771 imageData = (jintArray)env->NewGlobalRef(imageData); 1772 } 1773 1774 AwtDragSource::StartDrag( 1775 (AwtDragSource*)nativeCtxt, 1776 cursor, 1777 imageData, 1778 imageWidth, imageHeight, 1779 x, y); 1780 1781 CATCH_BAD_ALLOC; 1782 } 1783 1784 } /* extern "C" */