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