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