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