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