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