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