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