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