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