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