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