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