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