1 /* 2 * Copyright (c) 1997, 2010, 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_dnd_SunDragSourceContextPeer.h" 56 #include "sun_awt_windows_WDragSourceContextPeer.h" 57 58 #include "awt_ole.h" 59 #include "awt_DCHolder.h" 60 61 bool operator < (const FORMATETC &fr, const FORMATETC &fl) { 62 return memcmp(&fr, &fl, sizeof(FORMATETC)) < 0; 63 } 64 65 typedef std::map<FORMATETC, STGMEDIUM> CDataMap; 66 67 #define GALLOCFLG (GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT) 68 #define JAVA_BUTTON_MASK (java_awt_event_InputEvent_BUTTON1_DOWN_MASK | \ 69 java_awt_event_InputEvent_BUTTON2_DOWN_MASK | \ 70 java_awt_event_InputEvent_BUTTON3_DOWN_MASK) 71 72 extern "C" { 73 DWORD __cdecl convertActionsToDROPEFFECT(jint actions); 74 jint __cdecl convertDROPEFFECTToActions(DWORD effects); 75 } 76 77 class PictureDragHelper 78 { 79 private: 80 static CDataMap st; 81 static IDragSourceHelper *pHelper; 82 public: 83 static HRESULT Create( 84 JNIEnv* env, 85 jintArray imageData, 86 int imageWidth, 87 int imageHeight, 88 int anchorX, 89 int anchorY, 90 IDataObject *pIDataObject) 91 { 92 if (NULL == imageData) { 93 return S_FALSE; 94 } 95 OLE_TRY 96 OLE_HRT( CoCreateInstance( 97 CLSID_DragDropHelper, 98 NULL, 99 CLSCTX_ALL, 100 IID_IDragSourceHelper, 101 (LPVOID*)&pHelper)) 102 103 jintArray ia = imageData; 104 jsize iPointCoint = env->GetArrayLength(ia); 105 106 DCHolder ph; 107 ph.Create(NULL, imageWidth, imageHeight, TRUE); 108 env->GetIntArrayRegion(ia, 0, iPointCoint, (jint*)ph.m_pPoints); 109 110 SHDRAGIMAGE sdi; 111 sdi.sizeDragImage.cx = imageWidth; 112 sdi.sizeDragImage.cy = imageHeight; 113 sdi.ptOffset.x = anchorX; 114 sdi.ptOffset.y = anchorY; 115 sdi.crColorKey = 0xFFFFFFFF; 116 sdi.hbmpDragImage = ph; 117 118 // this call assures that the bitmap will be dragged around 119 OLE_HR = pHelper->InitializeFromBitmap( 120 &sdi, 121 pIDataObject 122 ); 123 // in case of an error we need to destroy the image, else the helper object takes ownership 124 if (FAILED(OLE_HR)) { 125 DeleteObject(sdi.hbmpDragImage); 126 } 127 OLE_CATCH 128 OLE_RETURN_HR 129 } 130 131 static void Destroy() 132 { 133 if (NULL!=pHelper) { 134 CleanFormatMap(); 135 pHelper->Release(); 136 pHelper = NULL; 137 } 138 } 139 140 static void CleanFormatMap() 141 { 142 for (CDataMap::iterator i = st.begin(); st.end() != i; i = st.erase(i)) { 143 ::ReleaseStgMedium(&i->second); 144 } 145 } 146 static void SetData(const FORMATETC &format, const STGMEDIUM &medium) 147 { 148 CDataMap::iterator i = st.find(format); 149 if (st.end() != i) { 150 ::ReleaseStgMedium(&i->second); 151 i->second = medium; 152 } else { 153 st[format] = medium; 154 } 155 } 156 static const FORMATETC *FindFormat(const FORMATETC &format) 157 { 158 static FORMATETC fm = {0}; 159 CDataMap::iterator i = st.find(format); 160 if (st.end() != i) { 161 return &i->first; 162 } 163 for (i = st.begin(); st.end() != i; ++i) { 164 if (i->first.cfFormat==format.cfFormat) { 165 return &i->first; 166 } 167 } 168 return NULL; 169 } 170 static STGMEDIUM *FindData(const FORMATETC &format) 171 { 172 CDataMap::iterator i = st.find(format); 173 if (st.end() != i) { 174 return &i->second; 175 } 176 for (i = st.begin(); st.end() != i; ++i) { 177 const FORMATETC &f = i->first; 178 if (f.cfFormat==format.cfFormat && (f.tymed == (f.tymed & format.tymed))) { 179 return &i->second; 180 } 181 } 182 return NULL; 183 } 184 }; 185 186 187 CDataMap PictureDragHelper::st; 188 IDragSourceHelper *PictureDragHelper::pHelper = NULL; 189 190 extern const CLIPFORMAT CF_PERFORMEDDROPEFFECT = ::RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT); 191 extern const CLIPFORMAT CF_FILEGROUPDESCRIPTORW = ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW); 192 extern const CLIPFORMAT CF_FILEGROUPDESCRIPTORA = ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA); 193 extern const CLIPFORMAT CF_FILECONTENTS = ::RegisterClipboardFormat(CFSTR_FILECONTENTS); 194 195 typedef struct { 196 AwtDragSource* dragSource; 197 jobject cursor; 198 jintArray imageData; 199 jint imageWidth; 200 jint imageHeight; 201 jint x; 202 jint y; 203 } StartDragRec; 204 205 /** 206 * StartDrag 207 */ 208 209 void AwtDragSource::StartDrag( 210 AwtDragSource* self, 211 jobject cursor, 212 jintArray imageData, 213 jint imageWidth, 214 jint imageHeight, 215 jint x, 216 jint y) 217 { 218 StartDragRec* sdrp = new StartDragRec; 219 sdrp->dragSource = self; 220 sdrp->imageData = imageData; 221 sdrp->cursor = cursor; 222 sdrp->imageWidth = imageWidth; 223 sdrp->imageHeight = imageHeight; 224 sdrp->x = x; 225 sdrp->y = y; 226 227 AwtToolkit::GetInstance().WaitForSingleObject(self->m_mutex); 228 229 AwtToolkit::GetInstance().InvokeFunctionLater((void (*)(void *))&AwtDragSource::_DoDragDrop, (void *)sdrp); 230 231 self->WaitUntilSignalled(FALSE); 232 } 233 234 /** 235 * DoDragDrop - called from message pump thread 236 */ 237 238 void AwtDragSource::_DoDragDrop(void* param) { 239 StartDragRec* sdrp = (StartDragRec*)param; 240 AwtDragSource* dragSource = sdrp->dragSource; 241 DWORD effects = DROPEFFECT_NONE; 242 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 243 jobject peer = env->NewLocalRef(dragSource->GetPeer()); 244 245 if (sdrp->imageData) { 246 PictureDragHelper::Create( 247 env, 248 sdrp->imageData, 249 sdrp->imageWidth, 250 sdrp->imageHeight, 251 sdrp->x, 252 sdrp->y, 253 (IDataObject*)dragSource); 254 env->DeleteGlobalRef(sdrp->imageData); 255 } 256 dragSource->SetCursor(sdrp->cursor); 257 env->DeleteGlobalRef(sdrp->cursor); 258 delete sdrp; 259 260 HRESULT res; 261 262 // StartDrag has caused dragSource->m_mutex to be held by our thread now 263 264 AwtDropTarget::SetCurrentDnDDataObject(dragSource); 265 266 ::GetCursorPos(&dragSource->m_dragPoint); 267 268 dragSource->Signal(); 269 270 res = ::DoDragDrop(dragSource, 271 dragSource, 272 convertActionsToDROPEFFECT(dragSource->m_actions), 273 &effects 274 ); 275 276 if (effects == DROPEFFECT_NONE && dragSource->m_dwPerformedDropEffect != DROPEFFECT_NONE) { 277 effects = dragSource->m_dwPerformedDropEffect; 278 } 279 dragSource->m_dwPerformedDropEffect = DROPEFFECT_NONE; 280 281 call_dSCddfinished(env, peer, res == DRAGDROP_S_DROP && effects != DROPEFFECT_NONE, 282 convertDROPEFFECTToActions(effects), 283 dragSource->m_dragPoint.x, dragSource->m_dragPoint.y); 284 285 env->DeleteLocalRef(peer); 286 287 DASSERT(AwtDropTarget::IsCurrentDnDDataObject(dragSource)); 288 AwtDropTarget::SetCurrentDnDDataObject(NULL); 289 290 PictureDragHelper::Destroy(); 291 dragSource->Release(); 292 } 293 294 /** 295 * constructor 296 */ 297 298 AwtDragSource::AwtDragSource(JNIEnv* env, jobject peer, jobject component, 299 jobject transferable, jobject trigger, 300 jint actions, jlongArray formats, 301 jobject formatMap) { 302 m_peer = env->NewGlobalRef(peer); 303 304 m_refs = 1; 305 306 m_actions = actions; 307 308 m_ntypes = 0; 309 310 m_initmods = 0; 311 m_lastmods = 0; 312 313 m_droptarget = NULL; 314 m_enterpending = TRUE; 315 316 m_cursor = NULL; 317 318 m_mutex = ::CreateMutex(NULL, FALSE, NULL); 319 320 m_component = env->NewGlobalRef(component); 321 m_transferable = env->NewGlobalRef(transferable); 322 m_formatMap = env->NewGlobalRef(formatMap); 323 324 m_dragPoint.x = 0; 325 m_dragPoint.y = 0; 326 327 m_fNC = TRUE; 328 m_dropPoint.x = 0; 329 m_dropPoint.y = 0; 330 331 m_dwPerformedDropEffect = DROPEFFECT_NONE; 332 m_bRestoreNodropCustomCursor = FALSE; 333 334 LoadCache(formats); 335 } 336 337 /** 338 * destructor 339 */ 340 341 AwtDragSource::~AwtDragSource() { 342 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 343 344 // fix for 6212440: on application shutdown, this object's 345 // destruction might be suppressed due to dangling COM references. 346 // On destruction, VM might be shut down already, so we should make 347 // a null check on env. 348 if (env) { 349 env->DeleteGlobalRef(m_peer); 350 env->DeleteGlobalRef(m_component); 351 env->DeleteGlobalRef(m_transferable); 352 env->DeleteGlobalRef(m_formatMap); 353 } 354 355 ::CloseHandle(m_mutex); 356 357 UnloadCache(); 358 } 359 360 /** 361 * _compar 362 * 363 * compare format's then tymed's .... only one tymed bit may be set 364 * at any time in a FORMATETC in the cache. 365 */ 366 367 int AwtDragSource::_compar(const void* first, const void* second) { 368 FORMATETC *fp = (FORMATETC *)first; 369 FORMATETC *sp = (FORMATETC *)second; 370 int r = fp->cfFormat - sp->cfFormat; 371 372 return r != 0 ? r : fp->tymed - sp->tymed; 373 } 374 375 /** 376 * LoadCache 377 */ 378 379 void AwtDragSource::LoadCache(jlongArray formats) { 380 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 381 unsigned int items = 0; 382 unsigned int i = 0; 383 unsigned int idx = 0; 384 385 if (m_types != (FORMATETC *)NULL) { 386 UnloadCache(); 387 } 388 389 items = env->GetArrayLength(formats); 390 391 if (items == 0) { 392 return; 393 } 394 395 jboolean isCopy; 396 jlong *lFormats = env->GetLongArrayElements(formats, &isCopy), 397 *saveFormats = lFormats; 398 399 for (i = 0, m_ntypes = 0; i < items; i++, lFormats++) { 400 // Warning C4244. 401 // Cast from jlong to CLIPFORMAT (WORD). 402 CLIPFORMAT fmt = (CLIPFORMAT)*lFormats; 403 switch (fmt) { 404 case CF_ENHMETAFILE: 405 m_ntypes++; // Only TYMED_ENHMF 406 break; 407 case CF_METAFILEPICT: 408 m_ntypes++; // Only TYMED_MFPICT 409 break; 410 case CF_HDROP: 411 m_ntypes++; // Only TYMED_HGLOBAL 412 break; 413 default: 414 m_ntypes += 2; // TYMED_HGLOBAL and TYMED_ISTREAM 415 break; 416 } 417 } 418 419 try { 420 m_types = (FORMATETC *)safe_Calloc(sizeof(FORMATETC), m_ntypes); 421 } catch (std::bad_alloc&) { 422 m_ntypes = 0; 423 throw; 424 } 425 426 lFormats = saveFormats; 427 428 for (i = 0, idx = 0; i < items; i++, lFormats++) { 429 // Warning C4244. 430 // Cast from jlong to CLIPFORMAT (WORD). 431 CLIPFORMAT fmt = (CLIPFORMAT)*lFormats; 432 433 m_types[idx].cfFormat = fmt; 434 m_types[idx].dwAspect = DVASPECT_CONTENT; 435 m_types[idx].lindex = -1; 436 437 switch (fmt) { 438 default: 439 m_types[idx].tymed = TYMED_ISTREAM; 440 idx++; 441 442 // now make a copy, but with a TYMED of HGLOBAL 443 m_types[idx] = m_types[idx-1]; 444 m_types[idx].tymed = TYMED_HGLOBAL; 445 idx++; 446 break; 447 case CF_HDROP: 448 m_types[idx].tymed = TYMED_HGLOBAL; 449 idx++; 450 break; 451 case CF_ENHMETAFILE: 452 m_types[idx].tymed = TYMED_ENHMF; 453 idx++; 454 break; 455 case CF_METAFILEPICT: 456 m_types[idx].tymed = TYMED_MFPICT; 457 idx++; 458 break; 459 } 460 } 461 DASSERT(idx == m_ntypes); 462 463 env->ReleaseLongArrayElements(formats, saveFormats, 0); 464 465 // sort them in ascending order of format 466 qsort((void *)m_types, (size_t)m_ntypes, (size_t)sizeof(FORMATETC), 467 _compar); 468 } 469 470 /** 471 * UnloadCache 472 */ 473 474 void AwtDragSource::UnloadCache() { 475 if (m_ntypes == 0) { 476 return; 477 } 478 479 free((void*)m_types); 480 m_ntypes = 0; 481 m_types = (FORMATETC *)NULL; 482 } 483 484 /** 485 * ChangeCursor 486 */ 487 HRESULT AwtDragSource::ChangeCursor() 488 { 489 if (m_cursor != NULL) { 490 ::SetCursor(m_cursor->GetHCursor()); 491 return S_OK; 492 } 493 return DRAGDROP_S_USEDEFAULTCURSORS; 494 } 495 496 /** 497 * SetCursor 498 */ 499 void AwtDragSource::SetCursor(jobject cursor) { 500 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 501 502 if (JNU_IsNull(env, cursor)) { 503 m_cursor = NULL; 504 return; 505 } 506 507 jlong pData = env->GetLongField(cursor, AwtCursor::pDataID); 508 // Warning C4312. 509 // Cast jlong (__int64) to pointer. 510 m_cursor = (AwtCursor*)pData; 511 512 if (m_cursor == NULL) { 513 m_cursor = AwtCursor::CreateSystemCursor(cursor); 514 } 515 } 516 517 /** 518 * MatchFormatEtc 519 */ 520 521 HRESULT __stdcall 522 AwtDragSource::MatchFormatEtc(FORMATETC __RPC_FAR *pFormatEtcIn, 523 FORMATETC *cacheEnt) { 524 TRY; 525 526 const FORMATETC *pFormat = PictureDragHelper::FindFormat(*pFormatEtcIn); 527 if (NULL != pFormat) { 528 if (NULL != cacheEnt) { 529 *cacheEnt = *pFormat; 530 } 531 return S_OK; 532 } 533 534 if ((pFormatEtcIn->tymed & (TYMED_HGLOBAL | TYMED_ISTREAM | TYMED_ENHMF | 535 TYMED_MFPICT)) == 0) { 536 return DV_E_TYMED; 537 } else if (pFormatEtcIn->lindex != -1) { 538 return DV_E_LINDEX; 539 } else if (pFormatEtcIn->dwAspect != DVASPECT_CONTENT) { 540 return DV_E_DVASPECT; 541 } 542 543 FORMATETC tmp = *pFormatEtcIn; 544 545 static const DWORD supportedTymeds[] = 546 { TYMED_ISTREAM, TYMED_HGLOBAL, TYMED_ENHMF, TYMED_MFPICT }; 547 static const int nSupportedTymeds = 4; 548 549 for (int i = 0; i < nSupportedTymeds; i++) { 550 /* 551 * Fix for BugTraq Id 4426805. 552 * Match only if the tymed is supported by the requester. 553 */ 554 if ((pFormatEtcIn->tymed & supportedTymeds[i]) == 0) { 555 continue; 556 } 557 558 tmp.tymed = supportedTymeds[i]; 559 pFormat = (const FORMATETC *)bsearch((const void *)&tmp, 560 (const void *)m_types, 561 (size_t) m_ntypes, 562 (size_t) sizeof(FORMATETC), 563 _compar 564 ); 565 if (NULL != pFormat) { 566 if (cacheEnt != (FORMATETC *)NULL) { 567 *cacheEnt = *pFormat; 568 } 569 return S_OK; 570 } 571 } 572 573 return DV_E_FORMATETC; 574 575 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 576 } 577 578 /** 579 * QueryInterface 580 */ 581 582 HRESULT __stdcall AwtDragSource::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) { 583 TRY; 584 585 if (riid == IID_IUnknown) { 586 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IUnknown*)(IDropSource*)this; 587 AddRef(); 588 return S_OK; 589 } else if (riid == IID_IDropSource) { 590 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IDropSource*)this; 591 AddRef(); 592 return S_OK; 593 } else if (riid == IID_IDataObject) { 594 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IDataObject*)this; 595 AddRef(); 596 return S_OK; 597 } else { 598 *ppvObject = (void __RPC_FAR *__RPC_FAR)NULL; 599 return E_NOINTERFACE; 600 } 601 602 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 603 } 604 605 /** 606 * AddRef 607 */ 608 609 ULONG __stdcall AwtDragSource::AddRef() { 610 return (ULONG)++m_refs; 611 } 612 613 /** 614 * Release 615 */ 616 617 ULONG __stdcall AwtDragSource::Release() { 618 int refs; 619 620 if ((refs = --m_refs) == 0) delete this; 621 622 return (ULONG)refs; 623 } 624 625 /** 626 * QueryContinueDrag 627 */ 628 629 HRESULT __stdcall AwtDragSource::QueryContinueDrag(BOOL fEscapeKeyPressed, DWORD grfKeyState) { 630 TRY; 631 632 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 633 634 if (fEscapeKeyPressed) 635 return DRAGDROP_S_CANCEL; 636 637 jint modifiers = AwtComponent::GetJavaModifiers(); 638 639 POINT dragPoint; 640 641 ::GetCursorPos(&dragPoint); 642 643 if ( (dragPoint.x != m_dragPoint.x || dragPoint.y != m_dragPoint.y) && 644 m_lastmods == modifiers) {//cannot move before cursor change 645 call_dSCmouseMoved(env, m_peer, 646 m_actions, modifiers, dragPoint.x, dragPoint.y); 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; // good guess! 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 982 ULONG act; 983 HRESULT res = pmedium->pstm->Write((const void *)bBytes, (ULONG)nBytes, 984 &act); 985 986 env->ReleaseByteArrayElements(bytes, bBytes, JNI_ABORT); 987 988 env->PopLocalFrame(NULL); 989 return S_OK; 990 } else if ((matchedFormatEtc.tymed & TYMED_HGLOBAL) != 0) { 991 ::SetLastError(0); // clear error 992 // Warning C4244. 993 SIZE_T mBytes = ::GlobalSize(pmedium->hGlobal); 994 if (::GetLastError() != 0) { 995 env->PopLocalFrame(NULL); 996 return E_UNEXPECTED; 997 } 998 999 if (nBytes + ((matchedFormatEtc.cfFormat == CF_HDROP) 1000 ? sizeof(DROPFILES) : 0) > mBytes) { 1001 env->PopLocalFrame(NULL); 1002 return STG_E_MEDIUMFULL; 1003 } 1004 1005 char *dataout = (char *)::GlobalLock(pmedium->hGlobal); 1006 1007 if (matchedFormatEtc.cfFormat == CF_HDROP) { 1008 DROPFILES *dropfiles = (DROPFILES *)dataout; 1009 dropfiles->pFiles = sizeof(DROPFILES); 1010 dropfiles->pt.x = m_dropPoint.x; 1011 dropfiles->pt.y = m_dropPoint.y; 1012 dropfiles->fNC = m_fNC; 1013 dropfiles->fWide = TRUE; // good guess! 1014 dataout += sizeof(DROPFILES); 1015 } 1016 1017 env->GetByteArrayRegion(bytes, 0, nBytes, (jbyte *)dataout); 1018 ::GlobalUnlock(pmedium->hGlobal); 1019 1020 env->PopLocalFrame(NULL); 1021 return S_OK; 1022 } 1023 1024 env->PopLocalFrame(NULL); 1025 return DV_E_TYMED; 1026 1027 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1028 } 1029 1030 /** 1031 * QueryGetData 1032 */ 1033 1034 HRESULT __stdcall AwtDragSource::QueryGetData(FORMATETC __RPC_FAR *pFormatEtc) { 1035 TRY; 1036 1037 return MatchFormatEtc(pFormatEtc, (FORMATETC *)NULL); 1038 1039 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1040 } 1041 1042 1043 /** 1044 * GetCanonicalFormatEtc 1045 */ 1046 1047 HRESULT __stdcall AwtDragSource::GetCanonicalFormatEtc(FORMATETC __RPC_FAR *pFormatEtcIn, FORMATETC __RPC_FAR *pFormatEtcOut) { 1048 TRY; 1049 1050 HRESULT res = MatchFormatEtc(pFormatEtcIn, (FORMATETC *)NULL); 1051 1052 if (res != S_OK) return res; 1053 1054 *pFormatEtcOut = *pFormatEtcIn; 1055 1056 pFormatEtcOut->ptd = NULL; 1057 1058 return DATA_S_SAMEFORMATETC; 1059 1060 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1061 } 1062 1063 /** 1064 * SetData 1065 */ 1066 1067 HRESULT __stdcall AwtDragSource::SetData(FORMATETC __RPC_FAR *pFormatEtc, STGMEDIUM __RPC_FAR *pmedium, BOOL fRelease) { 1068 if (pFormatEtc->cfFormat == CF_PERFORMEDDROPEFFECT && pmedium->tymed == TYMED_HGLOBAL) { 1069 m_dwPerformedDropEffect = *(DWORD*)::GlobalLock(pmedium->hGlobal); 1070 ::GlobalUnlock(pmedium->hGlobal); 1071 if (fRelease) { 1072 ::ReleaseStgMedium(pmedium); 1073 } 1074 return S_OK; 1075 } 1076 1077 if (fRelease) { 1078 //we are copying pmedium as a structure for further use, so no any release! 1079 PictureDragHelper::SetData(*pFormatEtc, *pmedium); 1080 return S_OK; 1081 } 1082 return E_UNEXPECTED; 1083 } 1084 1085 /** 1086 * EnumFormatEtc 1087 */ 1088 1089 HRESULT __stdcall AwtDragSource::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC *__RPC_FAR *ppenumFormatEtc) { 1090 TRY; 1091 1092 *ppenumFormatEtc = new ADSIEnumFormatEtc(this); 1093 return S_OK; 1094 1095 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1096 } 1097 1098 /** 1099 * DAdvise 1100 */ 1101 1102 HRESULT __stdcall AwtDragSource::DAdvise(FORMATETC __RPC_FAR *pFormatEtc, DWORD advf, IAdviseSink __RPC_FAR *pAdvSink, DWORD __RPC_FAR *pdwConnection) { 1103 return E_NOTIMPL; 1104 } 1105 1106 /** 1107 * DUnadvise 1108 */ 1109 1110 HRESULT __stdcall AwtDragSource::DUnadvise(DWORD dwConnection) { 1111 return OLE_E_ADVISENOTSUPPORTED; 1112 } 1113 1114 /** 1115 * EnumAdvise 1116 */ 1117 1118 HRESULT __stdcall AwtDragSource::EnumDAdvise(IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise) { 1119 return OLE_E_ADVISENOTSUPPORTED; 1120 } 1121 1122 const UINT AwtDragSource::PROCESS_ID_FORMAT = 1123 ::RegisterClipboardFormat(TEXT("_SUNW_JAVA_AWT_PROCESS_ID")); 1124 1125 HRESULT __stdcall AwtDragSource::GetProcessId(FORMATETC __RPC_FAR *pFormatEtc, STGMEDIUM __RPC_FAR *pmedium) { 1126 1127 if ((pFormatEtc->tymed & TYMED_HGLOBAL) == 0) { 1128 return DV_E_TYMED; 1129 } else if (pFormatEtc->lindex != -1) { 1130 return DV_E_LINDEX; 1131 } else if (pFormatEtc->dwAspect != DVASPECT_CONTENT) { 1132 return DV_E_DVASPECT; 1133 } else if (pFormatEtc->cfFormat != PROCESS_ID_FORMAT) { 1134 return DV_E_FORMATETC; 1135 } 1136 1137 DWORD id = ::CoGetCurrentProcess(); 1138 1139 HGLOBAL copy = ::GlobalAlloc(GALLOCFLG, sizeof(id)); 1140 1141 if (copy == NULL) { 1142 throw std::bad_alloc(); 1143 } 1144 1145 char *dataout = (char *)::GlobalLock(copy); 1146 1147 memcpy(dataout, &id, sizeof(id)); 1148 ::GlobalUnlock(copy); 1149 1150 pmedium->tymed = TYMED_HGLOBAL; 1151 pmedium->hGlobal = copy; 1152 pmedium->pUnkForRelease = (IUnknown *)NULL; 1153 1154 return S_OK; 1155 } 1156 1157 DECLARE_JAVA_CLASS(dSCClazz, "sun/awt/windows/WDragSourceContextPeer") 1158 1159 void 1160 AwtDragSource::call_dSCenter(JNIEnv* env, jobject self, jint targetActions, 1161 jint modifiers, jint x, jint y) { 1162 DECLARE_VOID_JAVA_METHOD(dSCenter, dSCClazz, "dragEnter", "(IIII)V"); 1163 DASSERT(!JNU_IsNull(env, self)); 1164 env->CallVoidMethod(self, dSCenter, targetActions, modifiers, x, y); 1165 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1166 env->ExceptionDescribe(); 1167 env->ExceptionClear(); 1168 } 1169 } 1170 1171 void 1172 AwtDragSource::call_dSCmotion(JNIEnv* env, jobject self, jint targetActions, 1173 jint modifiers, jint x, jint y) { 1174 DECLARE_VOID_JAVA_METHOD(dSCmotion, dSCClazz, "dragMotion", "(IIII)V"); 1175 DASSERT(!JNU_IsNull(env, self)); 1176 env->CallVoidMethod(self, dSCmotion, targetActions, modifiers, x, y); 1177 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1178 env->ExceptionDescribe(); 1179 env->ExceptionClear(); 1180 } 1181 } 1182 1183 void 1184 AwtDragSource::call_dSCchanged(JNIEnv* env, jobject self, jint targetActions, 1185 jint modifiers, jint x, jint y) { 1186 DECLARE_VOID_JAVA_METHOD(dSCchanged, dSCClazz, "operationChanged", 1187 "(IIII)V"); 1188 DASSERT(!JNU_IsNull(env, self)); 1189 env->CallVoidMethod(self, dSCchanged, targetActions, modifiers, x, y); 1190 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1191 env->ExceptionDescribe(); 1192 env->ExceptionClear(); 1193 } 1194 } 1195 1196 void 1197 AwtDragSource::call_dSCexit(JNIEnv* env, jobject self, jint x, jint y) { 1198 DECLARE_VOID_JAVA_METHOD(dSCexit, dSCClazz, "dragExit", "(II)V"); 1199 DASSERT(!JNU_IsNull(env, self)); 1200 env->CallVoidMethod(self, dSCexit, x, y); 1201 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1202 env->ExceptionDescribe(); 1203 env->ExceptionClear(); 1204 } 1205 } 1206 1207 void 1208 AwtDragSource::call_dSCddfinished(JNIEnv* env, jobject self, jboolean success, 1209 jint operations, jint x, jint y) { 1210 DECLARE_VOID_JAVA_METHOD(dSCddfinished, dSCClazz, "dragDropFinished", "(ZIII)V"); 1211 DASSERT(!JNU_IsNull(env, self)); 1212 env->CallVoidMethod(self, dSCddfinished, success, operations, x, y); 1213 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1214 env->ExceptionDescribe(); 1215 env->ExceptionClear(); 1216 } 1217 } 1218 1219 void 1220 AwtDragSource::call_dSCmouseMoved(JNIEnv* env, jobject self, jint targetActions, 1221 jint modifiers, jint x, jint y) { 1222 DECLARE_VOID_JAVA_METHOD(dSCmouseMoved, dSCClazz, "dragMouseMoved", 1223 "(IIII)V"); 1224 DASSERT(!JNU_IsNull(env, self)); 1225 env->CallVoidMethod(self, dSCmouseMoved, targetActions, modifiers, x, y); 1226 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 1227 env->ExceptionDescribe(); 1228 env->ExceptionClear(); 1229 } 1230 } 1231 1232 DECLARE_JAVA_CLASS(awtIEClazz, "java/awt/event/InputEvent") 1233 1234 /** 1235 * Constructor 1236 */ 1237 1238 AwtDragSource::ADSIEnumFormatEtc::ADSIEnumFormatEtc(AwtDragSource* parent) { 1239 m_parent = parent; 1240 m_idx = 0; 1241 1242 m_refs = 0; 1243 1244 m_parent->AddRef(); 1245 1246 AddRef(); 1247 } 1248 1249 /** 1250 * Destructor 1251 */ 1252 1253 AwtDragSource::ADSIEnumFormatEtc::~ADSIEnumFormatEtc() { 1254 m_parent->Release(); 1255 } 1256 1257 /** 1258 * QueryInterface 1259 */ 1260 1261 HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) { 1262 TRY; 1263 1264 if (riid == IID_IUnknown) { 1265 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IUnknown*)this; 1266 AddRef(); 1267 return S_OK; 1268 } else if (riid == IID_IEnumFORMATETC) { 1269 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IEnumFORMATETC*)this; 1270 AddRef(); 1271 return S_OK; 1272 } else { 1273 *ppvObject = (void __RPC_FAR *__RPC_FAR)NULL; 1274 return E_NOINTERFACE; 1275 } 1276 1277 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1278 } 1279 1280 /** 1281 * AddRef 1282 */ 1283 1284 ULONG __stdcall AwtDragSource::ADSIEnumFormatEtc::AddRef(void) { 1285 return (ULONG)++m_refs; 1286 } 1287 1288 /** 1289 * Release 1290 */ 1291 1292 ULONG __stdcall AwtDragSource::ADSIEnumFormatEtc::Release(void) { 1293 int refs; 1294 1295 if ((refs = --m_refs) == 0) delete this; 1296 1297 return (ULONG)refs; 1298 } 1299 1300 /** 1301 * Next 1302 */ 1303 1304 HRESULT _stdcall AwtDragSource::ADSIEnumFormatEtc::Next(ULONG celt, FORMATETC __RPC_FAR *rgelt, ULONG __RPC_FAR *pceltFetched) { 1305 TRY; 1306 1307 unsigned int len = m_parent->getNTypes(); 1308 unsigned int i; 1309 1310 for (i = 0; i < celt && m_idx < len; i++, m_idx++) { 1311 FORMATETC fetc = m_parent->getType(m_idx); 1312 rgelt[i] = fetc; 1313 } 1314 1315 if (pceltFetched != NULL) *pceltFetched = i; 1316 1317 return i == celt ? S_OK : S_FALSE; 1318 1319 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1320 } 1321 1322 /** 1323 * Skip 1324 */ 1325 1326 HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::Skip(ULONG celt) { 1327 TRY; 1328 1329 unsigned int len = m_parent->getNTypes(); 1330 unsigned int tmp = m_idx + celt; 1331 1332 if (tmp < len) { 1333 m_idx = tmp; 1334 1335 return S_OK; 1336 } else { 1337 m_idx = len; 1338 1339 return S_FALSE; 1340 } 1341 1342 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1343 } 1344 1345 /** 1346 * Reset 1347 */ 1348 1349 HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::Reset(void) { 1350 m_idx = 0; 1351 1352 return S_OK; 1353 } 1354 1355 /** 1356 * Clone 1357 */ 1358 1359 HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::Clone(IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenum) { 1360 TRY; 1361 1362 *ppenum = new ADSIEnumFormatEtc(m_parent); 1363 (*ppenum)->Skip(m_idx); 1364 return S_OK; 1365 1366 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1367 } 1368 1369 /** 1370 * constructor 1371 */ 1372 1373 AwtDragSource::ADSIStreamProxy::ADSIStreamProxy(AwtDragSource* parent, jbyteArray buffer, jint blen) { 1374 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1375 1376 m_parent = parent; 1377 1378 m_buffer = (signed char *)safe_Calloc(sizeof(signed char), m_blen = blen); 1379 1380 env->GetByteArrayRegion(buffer, 0, blen, m_buffer); 1381 1382 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) return; 1383 1384 m_off = 0; 1385 1386 m_cloneof = (ADSIStreamProxy*)NULL; 1387 1388 m_refs = 0; 1389 1390 FILETIME now; 1391 1392 ::CoFileTimeNow(&now); 1393 1394 m_statstg.pwcsName = (LPWSTR)NULL; 1395 m_statstg.type = STGTY_STREAM; 1396 m_statstg.cbSize.HighPart = 0; 1397 m_statstg.cbSize.LowPart = m_blen; 1398 m_statstg.mtime = now; 1399 m_statstg.ctime = now; 1400 m_statstg.atime = now; 1401 m_statstg.grfMode = STGM_READ; 1402 m_statstg.grfLocksSupported = FALSE; 1403 m_statstg.clsid = CLSID_NULL; 1404 m_statstg.grfStateBits = 0; 1405 m_statstg.reserved = 0; 1406 1407 m_parent->AddRef(); 1408 1409 AddRef(); 1410 } 1411 1412 /** 1413 * constructor (clone) 1414 */ 1415 1416 AwtDragSource::ADSIStreamProxy::ADSIStreamProxy(ADSIStreamProxy* cloneof) { 1417 m_cloneof = cloneof; 1418 1419 m_parent = cloneof->m_parent; 1420 1421 m_buffer = cloneof->m_buffer; 1422 m_blen = cloneof->m_blen; 1423 m_off = cloneof->m_off; 1424 1425 m_statstg = cloneof->m_statstg; 1426 1427 m_refs = 0; 1428 1429 m_parent->AddRef(); 1430 m_cloneof->AddRef(); 1431 } 1432 1433 /** 1434 * destructor 1435 */ 1436 1437 AwtDragSource::ADSIStreamProxy::~ADSIStreamProxy() { 1438 if (m_cloneof == (ADSIStreamProxy*)NULL) 1439 free((void *)m_buffer); 1440 else { 1441 m_cloneof->Release(); 1442 } 1443 1444 m_parent->Release(); 1445 } 1446 1447 /** 1448 * QueryInterface 1449 */ 1450 1451 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) { 1452 TRY; 1453 1454 if (riid == IID_IUnknown) { 1455 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IUnknown*)this; 1456 AddRef(); 1457 return S_OK; 1458 } else if (riid == IID_IStream) { 1459 *ppvObject = (void __RPC_FAR *__RPC_FAR)(IStream*)this; 1460 AddRef(); 1461 return S_OK; 1462 } else { 1463 *ppvObject = (void __RPC_FAR *__RPC_FAR)NULL; 1464 return E_NOINTERFACE; 1465 } 1466 1467 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1468 } 1469 1470 /** 1471 * AddRef 1472 */ 1473 1474 ULONG __stdcall AwtDragSource::ADSIStreamProxy::AddRef(void) { 1475 return (ULONG)++m_refs; 1476 } 1477 1478 /** 1479 * Release 1480 */ 1481 1482 ULONG __stdcall AwtDragSource::ADSIStreamProxy::Release(void) { 1483 int refs; 1484 1485 if ((refs = --m_refs) == 0) delete this; 1486 1487 return (ULONG)refs; 1488 } 1489 1490 /** 1491 * Read 1492 */ 1493 1494 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead) { 1495 TRY; 1496 1497 unsigned int rem = m_blen - m_off; 1498 int read = cb > rem ? rem : cb; 1499 1500 if (read > 0) memmove(pv, (void *)(m_buffer + m_off), read); 1501 1502 m_off += read; 1503 1504 if (pcbRead != (ULONG __RPC_FAR *)NULL) { 1505 *pcbRead = read; 1506 } 1507 1508 FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; 1509 1510 return S_OK; 1511 1512 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1513 } 1514 1515 /** 1516 * Write 1517 */ 1518 1519 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Write(const void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbWritten) { 1520 TRY; 1521 1522 if (pcbWritten != (ULONG __RPC_FAR *)NULL) { 1523 *pcbWritten = 0; 1524 } 1525 1526 FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; 1527 1528 return STG_E_CANTSAVE; // dont support writing 1529 1530 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1531 } 1532 1533 /** 1534 * Seek 1535 */ 1536 1537 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER __RPC_FAR *plibNewPosition) { 1538 TRY; 1539 1540 if (dlibMove.HighPart != 0) return STG_E_INVALIDPOINTER; 1541 1542 if (plibNewPosition != (ULARGE_INTEGER __RPC_FAR *)NULL) { 1543 plibNewPosition->HighPart = 0; 1544 plibNewPosition->LowPart = 0; 1545 } 1546 1547 switch (dwOrigin) { 1548 case STREAM_SEEK_SET: { 1549 if (dlibMove.HighPart != 0 || dlibMove.LowPart >= m_blen) return STG_E_INVALIDPOINTER; 1550 1551 m_off = dlibMove.LowPart; 1552 } 1553 break; 1554 1555 case STREAM_SEEK_CUR: 1556 case STREAM_SEEK_END: { 1557 if (dlibMove.HighPart > 0) return STG_E_INVALIDPOINTER; 1558 1559 long newoff = (dwOrigin == STREAM_SEEK_END ? m_blen : m_off) + dlibMove.LowPart; 1560 1561 if (newoff < 0 || newoff >= (long)m_blen) 1562 return STG_E_INVALIDPOINTER; 1563 else 1564 m_off = newoff; 1565 } 1566 break; 1567 1568 default: return STG_E_INVALIDFUNCTION; 1569 } 1570 1571 if (plibNewPosition != (ULARGE_INTEGER __RPC_FAR *)NULL) 1572 plibNewPosition->LowPart = m_off; 1573 1574 FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; 1575 1576 return S_OK; 1577 1578 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1579 } 1580 1581 /** 1582 * SetSize 1583 */ 1584 1585 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::SetSize(ULARGE_INTEGER libNewSize) { 1586 return STG_E_INVALIDFUNCTION; 1587 } 1588 1589 /** 1590 * CopyTo 1591 */ 1592 1593 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::CopyTo(IStream __RPC_FAR *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER __RPC_FAR *pcbRead, ULARGE_INTEGER __RPC_FAR *pcbWritten) { 1594 TRY; 1595 1596 ULONG written = 0; 1597 1598 pcbWritten->HighPart = (ULONG)0; 1599 pcbWritten->LowPart = (ULONG)0; 1600 1601 pcbRead->HighPart = (ULONG)0; 1602 1603 unsigned int rem = m_blen - m_off; 1604 int ovrflow = cb.LowPart >= rem; 1605 1606 1607 if (cb.HighPart != 0) return STG_E_INVALIDPOINTER; 1608 1609 ULONG nbytes = pcbRead->LowPart = (ULONG)(ovrflow ? rem : cb.LowPart); 1610 1611 HRESULT res = pstm->Write((const void *)(m_buffer + m_off), nbytes, &written); 1612 1613 pcbWritten->LowPart = written; 1614 1615 FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; 1616 1617 return res; 1618 1619 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1620 } 1621 1622 /** 1623 * Commit 1624 */ 1625 1626 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Commit(DWORD grfCommitFlags) { 1627 return S_OK; 1628 } 1629 1630 /** 1631 * Revert 1632 */ 1633 1634 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Revert() { 1635 return S_OK; 1636 } 1637 1638 /** 1639 * LockRegion 1640 */ 1641 1642 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { 1643 return STG_E_INVALIDFUNCTION; 1644 } 1645 1646 /** 1647 * UnlockRegion 1648 */ 1649 1650 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { 1651 return STG_E_INVALIDFUNCTION; 1652 } 1653 1654 /** 1655 * Stat 1656 */ 1657 1658 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Stat(STATSTG __RPC_FAR *pstatstg, DWORD grfStatFlag) { 1659 TRY; 1660 1661 *pstatstg = m_statstg; 1662 1663 FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; 1664 1665 return S_OK; 1666 1667 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1668 } 1669 1670 /** 1671 * Clone 1672 */ 1673 1674 HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Clone(IStream __RPC_FAR *__RPC_FAR *ppstm) { 1675 TRY; 1676 1677 *ppstm = new ADSIStreamProxy(this); 1678 return S_OK; 1679 1680 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); 1681 } 1682 1683 /*****************************************************************************/ 1684 1685 extern "C" { 1686 1687 /** 1688 * setNativeCursor 1689 */ 1690 1691 JNIEXPORT void JNICALL 1692 Java_sun_awt_windows_WDragSourceContextPeer_setNativeCursor(JNIEnv* env, 1693 jobject self, 1694 jlong nativeCtxt, 1695 jobject cursor, 1696 jint type) { 1697 TRY; 1698 1699 AwtDragSource* ds = (AwtDragSource*)nativeCtxt; 1700 if (ds != NULL) { 1701 ds->SetCursor(cursor); 1702 } 1703 1704 CATCH_BAD_ALLOC; 1705 } 1706 1707 /** 1708 * createDragSource 1709 */ 1710 1711 JNIEXPORT jlong JNICALL 1712 Java_sun_awt_windows_WDragSourceContextPeer_createDragSource( 1713 JNIEnv* env, jobject self, jobject component, jobject transferable, 1714 jobject trigger, jint actions, 1715 jlongArray formats, jobject formatMap) 1716 { 1717 TRY; 1718 1719 if (!AwtDropTarget::IsCurrentDnDDataObject(NULL)) { 1720 JNU_ThrowByName(env, "java/awt/dnd/InvalidDnDOperationException", 1721 "Drag and drop is in progress"); 1722 return (jlong)NULL; 1723 } 1724 1725 AwtDragSource* ds = new AwtDragSource(env, self, component, 1726 transferable, trigger, actions, 1727 formats, formatMap); 1728 1729 DASSERT(AwtDropTarget::IsLocalDataObject(ds)); 1730 1731 return (jlong)ds; 1732 1733 CATCH_BAD_ALLOC_RET(0); 1734 } 1735 1736 /** 1737 * doDragDrop 1738 */ 1739 1740 JNIEXPORT void JNICALL Java_sun_awt_windows_WDragSourceContextPeer_doDragDrop( 1741 JNIEnv* env, 1742 jobject self, 1743 jlong nativeCtxt, 1744 jobject cursor, 1745 jintArray imageData, 1746 jint imageWidth, jint imageHeight, 1747 jint x, jint y) 1748 { 1749 TRY; 1750 1751 cursor = env->NewGlobalRef(cursor); 1752 if (NULL != imageData) { 1753 imageData = (jintArray)env->NewGlobalRef(imageData); 1754 } 1755 1756 AwtDragSource::StartDrag( 1757 (AwtDragSource*)nativeCtxt, 1758 cursor, 1759 imageData, 1760 imageWidth, imageHeight, 1761 x, y); 1762 1763 CATCH_BAD_ALLOC; 1764 } 1765 1766 } /* extern "C" */