/* * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #pragma push_macro("bad_alloc") //"bad_alloc" would be introduced in STL as "std::zbad_alloc" and discarded by linker //by this action we avoid the conflict with AWT implementation of "bad_alloc" //we need inclusion for STL "new" oprators set. #define bad_alloc zbad_alloc #include #if defined(_DEBUG) || defined(DEBUG) extern void * operator new(size_t size, const char * filename, int linenumber); void * operator new(size_t size) {return operator new(size, "stl", 1);} #endif #include #pragma pop_macro("bad_alloc") //"bad_alloc" is undefined from here #include #include #include "jlong.h" #include "awt_DataTransferer.h" #include "awt_DnDDS.h" #include "awt_DnDDT.h" #include "awt_Cursor.h" #include "awt_Toolkit.h" #include "awt_Component.h" #include "java_awt_event_InputEvent.h" #include "java_awt_dnd_DnDConstants.h" #include "sun_awt_dnd_SunDragSourceContextPeer.h" #include "sun_awt_windows_WDragSourceContextPeer.h" #include "awt_ole.h" #include "awt_DCHolder.h" bool operator < (const FORMATETC &fr, const FORMATETC &fl) { return memcmp(&fr, &fl, sizeof(FORMATETC)) < 0; } typedef std::map CDataMap; #define GALLOCFLG (GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT) #define JAVA_BUTTON_MASK (java_awt_event_InputEvent_BUTTON1_DOWN_MASK | \ java_awt_event_InputEvent_BUTTON2_DOWN_MASK | \ java_awt_event_InputEvent_BUTTON3_DOWN_MASK) extern "C" { DWORD __cdecl convertActionsToDROPEFFECT(jint actions); jint __cdecl convertDROPEFFECTToActions(DWORD effects); } class PictureDragHelper { private: static CDataMap st; static IDragSourceHelper *pHelper; public: static HRESULT Create( JNIEnv* env, jintArray imageData, int imageWidth, int imageHeight, int anchorX, int anchorY, IDataObject *pIDataObject) { if (NULL == imageData) { return S_FALSE; } OLE_TRY OLE_HRT( CoCreateInstance( CLSID_DragDropHelper, NULL, CLSCTX_ALL, IID_IDragSourceHelper, (LPVOID*)&pHelper)) jintArray ia = imageData; jsize iPointCoint = env->GetArrayLength(ia); DCHolder ph; ph.Create(NULL, imageWidth, imageHeight, TRUE); env->GetIntArrayRegion(ia, 0, iPointCoint, (jint*)ph.m_pPoints); SHDRAGIMAGE sdi; sdi.sizeDragImage.cx = imageWidth; sdi.sizeDragImage.cy = imageHeight; sdi.ptOffset.x = anchorX; sdi.ptOffset.y = anchorY; sdi.crColorKey = 0xFFFFFFFF; sdi.hbmpDragImage = ph; // this call assures that the bitmap will be dragged around OLE_HR = pHelper->InitializeFromBitmap( &sdi, pIDataObject ); // in case of an error we need to destroy the image, else the helper object takes ownership if (FAILED(OLE_HR)) { DeleteObject(sdi.hbmpDragImage); } OLE_CATCH OLE_RETURN_HR } static void Destroy() { if (NULL!=pHelper) { CleanFormatMap(); pHelper->Release(); pHelper = NULL; } } static void CleanFormatMap() { for (CDataMap::iterator i = st.begin(); st.end() != i; i = st.erase(i)) { ::ReleaseStgMedium(&i->second); } } static void SetData(const FORMATETC &format, const STGMEDIUM &medium) { CDataMap::iterator i = st.find(format); if (st.end() != i) { ::ReleaseStgMedium(&i->second); i->second = medium; } else { st[format] = medium; } } static const FORMATETC *FindFormat(const FORMATETC &format) { static FORMATETC fm = {0}; CDataMap::iterator i = st.find(format); if (st.end() != i) { return &i->first; } for (i = st.begin(); st.end() != i; ++i) { if (i->first.cfFormat==format.cfFormat) { return &i->first; } } return NULL; } static STGMEDIUM *FindData(const FORMATETC &format) { CDataMap::iterator i = st.find(format); if (st.end() != i) { return &i->second; } for (i = st.begin(); st.end() != i; ++i) { const FORMATETC &f = i->first; if (f.cfFormat==format.cfFormat && (f.tymed == (f.tymed & format.tymed))) { return &i->second; } } return NULL; } }; CDataMap PictureDragHelper::st; IDragSourceHelper *PictureDragHelper::pHelper = NULL; extern const CLIPFORMAT CF_PERFORMEDDROPEFFECT = ::RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT); extern const CLIPFORMAT CF_FILEGROUPDESCRIPTORW = ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW); extern const CLIPFORMAT CF_FILEGROUPDESCRIPTORA = ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA); extern const CLIPFORMAT CF_FILECONTENTS = ::RegisterClipboardFormat(CFSTR_FILECONTENTS); typedef struct { AwtDragSource* dragSource; jobject cursor; jintArray imageData; jint imageWidth; jint imageHeight; jint x; jint y; } StartDragRec; /** * StartDrag */ void AwtDragSource::StartDrag( AwtDragSource* self, jobject cursor, jintArray imageData, jint imageWidth, jint imageHeight, jint x, jint y) { StartDragRec* sdrp = new StartDragRec; sdrp->dragSource = self; sdrp->imageData = imageData; sdrp->cursor = cursor; sdrp->imageWidth = imageWidth; sdrp->imageHeight = imageHeight; sdrp->x = x; sdrp->y = y; AwtToolkit::GetInstance().WaitForSingleObject(self->m_mutex); AwtToolkit::GetInstance().InvokeFunctionLater((void (*)(void *))&AwtDragSource::_DoDragDrop, (void *)sdrp); self->WaitUntilSignalled(FALSE); } /** * DoDragDrop - called from message pump thread */ void AwtDragSource::_DoDragDrop(void* param) { StartDragRec* sdrp = (StartDragRec*)param; AwtDragSource* dragSource = sdrp->dragSource; DWORD effects = DROPEFFECT_NONE; JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); jobject peer = env->NewLocalRef(dragSource->GetPeer()); if (sdrp->imageData) { PictureDragHelper::Create( env, sdrp->imageData, sdrp->imageWidth, sdrp->imageHeight, sdrp->x, sdrp->y, (IDataObject*)dragSource); env->DeleteGlobalRef(sdrp->imageData); } dragSource->SetCursor(sdrp->cursor); env->DeleteGlobalRef(sdrp->cursor); delete sdrp; HRESULT res; // StartDrag has caused dragSource->m_mutex to be held by our thread now AwtDropTarget::SetCurrentDnDDataObject(dragSource); ::GetCursorPos(&dragSource->m_dragPoint); dragSource->Signal(); res = ::DoDragDrop(dragSource, dragSource, convertActionsToDROPEFFECT(dragSource->m_actions), &effects ); if (effects == DROPEFFECT_NONE && dragSource->m_dwPerformedDropEffect != DROPEFFECT_NONE) { effects = dragSource->m_dwPerformedDropEffect; } dragSource->m_dwPerformedDropEffect = DROPEFFECT_NONE; call_dSCddfinished(env, peer, res == DRAGDROP_S_DROP && effects != DROPEFFECT_NONE, convertDROPEFFECTToActions(effects), dragSource->m_dragPoint.x, dragSource->m_dragPoint.y); env->DeleteLocalRef(peer); DASSERT(AwtDropTarget::IsCurrentDnDDataObject(dragSource)); AwtDropTarget::SetCurrentDnDDataObject(NULL); PictureDragHelper::Destroy(); dragSource->Release(); } /** * constructor */ AwtDragSource::AwtDragSource(JNIEnv* env, jobject peer, jobject component, jobject transferable, jobject trigger, jint actions, jlongArray formats, jobject formatMap) { m_peer = env->NewGlobalRef(peer); m_refs = 1; m_actions = actions; m_ntypes = 0; m_initmods = 0; m_lastmods = 0; m_droptarget = NULL; m_enterpending = TRUE; m_cursor = NULL; m_mutex = ::CreateMutex(NULL, FALSE, NULL); m_component = env->NewGlobalRef(component); m_transferable = env->NewGlobalRef(transferable); m_formatMap = env->NewGlobalRef(formatMap); m_dragPoint.x = 0; m_dragPoint.y = 0; m_fNC = TRUE; m_dropPoint.x = 0; m_dropPoint.y = 0; m_dwPerformedDropEffect = DROPEFFECT_NONE; m_bRestoreNodropCustomCursor = FALSE; LoadCache(formats); } /** * destructor */ AwtDragSource::~AwtDragSource() { JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); // fix for 6212440: on application shutdown, this object's // destruction might be suppressed due to dangling COM references. // On destruction, VM might be shut down already, so we should make // a null check on env. if (env) { env->DeleteGlobalRef(m_peer); env->DeleteGlobalRef(m_component); env->DeleteGlobalRef(m_transferable); env->DeleteGlobalRef(m_formatMap); } ::CloseHandle(m_mutex); UnloadCache(); } /** * _compar * * compare format's then tymed's .... only one tymed bit may be set * at any time in a FORMATETC in the cache. */ int AwtDragSource::_compar(const void* first, const void* second) { FORMATETC *fp = (FORMATETC *)first; FORMATETC *sp = (FORMATETC *)second; int r = fp->cfFormat - sp->cfFormat; return r != 0 ? r : fp->tymed - sp->tymed; } /** * LoadCache */ void AwtDragSource::LoadCache(jlongArray formats) { JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); unsigned int items = 0; unsigned int i = 0; unsigned int idx = 0; if (m_types != (FORMATETC *)NULL) { UnloadCache(); } items = env->GetArrayLength(formats); if (items == 0) { return; } jboolean isCopy; jlong *lFormats = env->GetLongArrayElements(formats, &isCopy), *saveFormats = lFormats; for (i = 0, m_ntypes = 0; i < items; i++, lFormats++) { // Warning C4244. // Cast from jlong to CLIPFORMAT (WORD). CLIPFORMAT fmt = (CLIPFORMAT)*lFormats; switch (fmt) { case CF_ENHMETAFILE: m_ntypes++; // Only TYMED_ENHMF break; case CF_METAFILEPICT: m_ntypes++; // Only TYMED_MFPICT break; case CF_HDROP: m_ntypes++; // Only TYMED_HGLOBAL break; default: m_ntypes += 2; // TYMED_HGLOBAL and TYMED_ISTREAM break; } } try { m_types = (FORMATETC *)safe_Calloc(sizeof(FORMATETC), m_ntypes); } catch (std::bad_alloc&) { m_ntypes = 0; throw; } lFormats = saveFormats; for (i = 0, idx = 0; i < items; i++, lFormats++) { // Warning C4244. // Cast from jlong to CLIPFORMAT (WORD). CLIPFORMAT fmt = (CLIPFORMAT)*lFormats; m_types[idx].cfFormat = fmt; m_types[idx].dwAspect = DVASPECT_CONTENT; m_types[idx].lindex = -1; switch (fmt) { default: m_types[idx].tymed = TYMED_ISTREAM; idx++; // now make a copy, but with a TYMED of HGLOBAL m_types[idx] = m_types[idx-1]; m_types[idx].tymed = TYMED_HGLOBAL; idx++; break; case CF_HDROP: m_types[idx].tymed = TYMED_HGLOBAL; idx++; break; case CF_ENHMETAFILE: m_types[idx].tymed = TYMED_ENHMF; idx++; break; case CF_METAFILEPICT: m_types[idx].tymed = TYMED_MFPICT; idx++; break; } } DASSERT(idx == m_ntypes); env->ReleaseLongArrayElements(formats, saveFormats, 0); // sort them in ascending order of format qsort((void *)m_types, (size_t)m_ntypes, (size_t)sizeof(FORMATETC), _compar); } /** * UnloadCache */ void AwtDragSource::UnloadCache() { if (m_ntypes == 0) { return; } free((void*)m_types); m_ntypes = 0; m_types = (FORMATETC *)NULL; } /** * ChangeCursor */ HRESULT AwtDragSource::ChangeCursor() { if (m_cursor != NULL) { ::SetCursor(m_cursor->GetHCursor()); return S_OK; } return DRAGDROP_S_USEDEFAULTCURSORS; } /** * SetCursor */ void AwtDragSource::SetCursor(jobject cursor) { JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); if (JNU_IsNull(env, cursor)) { m_cursor = NULL; return; } jlong pData = env->GetLongField(cursor, AwtCursor::pDataID); // Warning C4312. // Cast jlong (__int64) to pointer. m_cursor = (AwtCursor*)pData; if (m_cursor == NULL) { m_cursor = AwtCursor::CreateSystemCursor(cursor); } } /** * MatchFormatEtc */ HRESULT __stdcall AwtDragSource::MatchFormatEtc(FORMATETC __RPC_FAR *pFormatEtcIn, FORMATETC *cacheEnt) { TRY; const FORMATETC *pFormat = PictureDragHelper::FindFormat(*pFormatEtcIn); if (NULL != pFormat) { if (NULL != cacheEnt) { *cacheEnt = *pFormat; } return S_OK; } if ((pFormatEtcIn->tymed & (TYMED_HGLOBAL | TYMED_ISTREAM | TYMED_ENHMF | TYMED_MFPICT)) == 0) { return DV_E_TYMED; } else if (pFormatEtcIn->lindex != -1) { return DV_E_LINDEX; } else if (pFormatEtcIn->dwAspect != DVASPECT_CONTENT) { return DV_E_DVASPECT; } FORMATETC tmp = *pFormatEtcIn; static const DWORD supportedTymeds[] = { TYMED_ISTREAM, TYMED_HGLOBAL, TYMED_ENHMF, TYMED_MFPICT }; static const int nSupportedTymeds = 4; for (int i = 0; i < nSupportedTymeds; i++) { /* * Fix for BugTraq Id 4426805. * Match only if the tymed is supported by the requester. */ if ((pFormatEtcIn->tymed & supportedTymeds[i]) == 0) { continue; } tmp.tymed = supportedTymeds[i]; pFormat = (const FORMATETC *)bsearch((const void *)&tmp, (const void *)m_types, (size_t) m_ntypes, (size_t) sizeof(FORMATETC), _compar ); if (NULL != pFormat) { if (cacheEnt != (FORMATETC *)NULL) { *cacheEnt = *pFormat; } return S_OK; } } return DV_E_FORMATETC; CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * QueryInterface */ HRESULT __stdcall AwtDragSource::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) { TRY; if (riid == IID_IUnknown) { *ppvObject = (void __RPC_FAR *__RPC_FAR)(IUnknown*)(IDropSource*)this; AddRef(); return S_OK; } else if (riid == IID_IDropSource) { *ppvObject = (void __RPC_FAR *__RPC_FAR)(IDropSource*)this; AddRef(); return S_OK; } else if (riid == IID_IDataObject) { *ppvObject = (void __RPC_FAR *__RPC_FAR)(IDataObject*)this; AddRef(); return S_OK; } else { *ppvObject = (void __RPC_FAR *__RPC_FAR)NULL; return E_NOINTERFACE; } CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * AddRef */ ULONG __stdcall AwtDragSource::AddRef() { return (ULONG)++m_refs; } /** * Release */ ULONG __stdcall AwtDragSource::Release() { int refs; if ((refs = --m_refs) == 0) delete this; return (ULONG)refs; } /** * QueryContinueDrag */ HRESULT __stdcall AwtDragSource::QueryContinueDrag(BOOL fEscapeKeyPressed, DWORD grfKeyState) { TRY; JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); if (fEscapeKeyPressed) return DRAGDROP_S_CANCEL; jint modifiers = AwtComponent::GetJavaModifiers(); POINT dragPoint; ::GetCursorPos(&dragPoint); if ( (dragPoint.x != m_dragPoint.x || dragPoint.y != m_dragPoint.y) && m_lastmods == modifiers) {//cannot move before cursor change call_dSCmouseMoved(env, m_peer, m_actions, modifiers, dragPoint.x, dragPoint.y); m_dragPoint = dragPoint; } if ((modifiers & JAVA_BUTTON_MASK) == 0) { return DRAGDROP_S_DROP; } else if (m_initmods == 0) { m_initmods = modifiers; } else if ((modifiers & JAVA_BUTTON_MASK) != (m_initmods & JAVA_BUTTON_MASK)) { return DRAGDROP_S_CANCEL; } else if (m_lastmods != modifiers) { call_dSCchanged(env, m_peer, m_actions, modifiers, dragPoint.x, dragPoint.y); m_bRestoreNodropCustomCursor = TRUE; } m_lastmods = modifiers; //CR 6480706 - MS Bug on hold HCURSOR hNeedCursor; if ( m_bRestoreNodropCustomCursor && m_cursor != NULL && (hNeedCursor = m_cursor->GetHCursor()) != ::GetCursor() ) { ChangeCursor(); m_bRestoreNodropCustomCursor = FALSE; } return S_OK; CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * GiveFeedback */ HRESULT __stdcall AwtDragSource::GiveFeedback(DWORD dwEffect) { TRY; JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); jint modifiers = 0; SHORT mods = 0; m_actions = convertDROPEFFECTToActions(dwEffect); if (::GetKeyState(VK_LBUTTON) & 0xff00) { mods |= MK_LBUTTON; } else if (::GetKeyState(VK_MBUTTON) & 0xff00) { mods |= MK_MBUTTON; } else if (::GetKeyState(VK_RBUTTON) & 0xff00) { mods |= MK_RBUTTON; } if (::GetKeyState(VK_SHIFT) & 0xff00) mods |= MK_SHIFT; if (::GetKeyState(VK_CONTROL) & 0xff00) mods |= MK_CONTROL; if (::GetKeyState(VK_MENU) & 0xff00) mods |= MK_ALT; modifiers = AwtComponent::GetJavaModifiers(); POINT curs; ::GetCursorPos(&curs); m_droptarget = ::WindowFromPoint(curs); int invalid = (dwEffect == DROPEFFECT_NONE); if (invalid) { // Don't call dragExit if dragEnter and dragOver haven't been called. if (!m_enterpending) { call_dSCexit(env, m_peer, curs.x, curs.y); } m_droptarget = (HWND)NULL; m_enterpending = TRUE; } else if (m_droptarget != NULL) { (*(m_enterpending ? call_dSCenter : call_dSCmotion)) (env, m_peer, m_actions, modifiers, curs.x, curs.y); m_enterpending = FALSE; } if (m_droptarget != NULL) { RECT rect; POINT client = curs; VERIFY(::ScreenToClient(m_droptarget, &client)); VERIFY(::GetClientRect(m_droptarget, &rect)); if (::PtInRect(&rect, client)) { m_fNC = FALSE; m_dropPoint = client; } else { m_fNC = TRUE; m_dropPoint = curs; } } else { m_fNC = TRUE; m_dropPoint.x = 0; m_dropPoint.y = 0; } m_bRestoreNodropCustomCursor = (dwEffect == DROPEFFECT_NONE); return ChangeCursor(); CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * GetData */ HRESULT __stdcall AwtDragSource::GetData(FORMATETC __RPC_FAR *pFormatEtc, STGMEDIUM __RPC_FAR *pmedium) { TRY; STGMEDIUM *pPicMedia = PictureDragHelper::FindData(*pFormatEtc); if (NULL != pPicMedia) { *pmedium = *pPicMedia; //return outside, so AddRef the instance of pstm or hGlobal! if (pmedium->tymed == TYMED_ISTREAM) { pmedium->pstm->AddRef(); pmedium->pUnkForRelease = (IUnknown *)NULL; } else if (pmedium->tymed == TYMED_HGLOBAL) { AddRef(); pmedium->pUnkForRelease = (IDropSource *)this; } return S_OK; } HRESULT res = GetProcessId(pFormatEtc, pmedium); if (res == S_OK) { return res; } FORMATETC matchedFormatEtc; res = MatchFormatEtc(pFormatEtc, &matchedFormatEtc); if (res != S_OK) { return res; } JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); if (env->PushLocalFrame(2) < 0) { return E_OUTOFMEMORY; } jbyteArray bytes = AwtDataTransferer::ConvertData(env, m_component, m_transferable, (jlong)matchedFormatEtc.cfFormat, m_formatMap); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return E_UNEXPECTED; } if (bytes == NULL) { env->PopLocalFrame(NULL); return E_UNEXPECTED; } jint nBytes = env->GetArrayLength(bytes); if ((matchedFormatEtc.tymed & TYMED_ISTREAM) != 0) { ADSIStreamProxy *istream = new ADSIStreamProxy(this, bytes, nBytes); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return E_UNEXPECTED; } pmedium->tymed = TYMED_ISTREAM; pmedium->pstm = istream; pmedium->pUnkForRelease = (IUnknown *)NULL; env->PopLocalFrame(NULL); return S_OK; } else if ((matchedFormatEtc.tymed & TYMED_HGLOBAL) != 0) { HGLOBAL copy = ::GlobalAlloc(GALLOCFLG, nBytes + ((matchedFormatEtc.cfFormat == CF_HDROP) ? sizeof(DROPFILES) : 0)); if (copy == NULL) { env->PopLocalFrame(NULL); throw std::bad_alloc(); } char *dataout = (char *)::GlobalLock(copy); if (matchedFormatEtc.cfFormat == CF_HDROP) { DROPFILES *dropfiles = (DROPFILES *)dataout; dropfiles->pFiles = sizeof(DROPFILES); dropfiles->pt.x = m_dropPoint.x; dropfiles->pt.y = m_dropPoint.y; dropfiles->fNC = m_fNC; dropfiles->fWide = TRUE; // good guess! dataout += sizeof(DROPFILES); } env->GetByteArrayRegion(bytes, 0, nBytes, (jbyte *)dataout); ::GlobalUnlock(copy); pmedium->tymed = TYMED_HGLOBAL; pmedium->hGlobal = copy; pmedium->pUnkForRelease = (IUnknown *)NULL; env->PopLocalFrame(NULL); return S_OK; } else if ((matchedFormatEtc.tymed & TYMED_ENHMF) != 0) { LPBYTE lpbEmfBuffer = (LPBYTE)env->GetPrimitiveArrayCritical(bytes, NULL); if (lpbEmfBuffer == NULL) { env->PopLocalFrame(NULL); throw std::bad_alloc(); } HENHMETAFILE hemf = ::SetEnhMetaFileBits(nBytes, lpbEmfBuffer); env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbEmfBuffer, JNI_ABORT); if (hemf == NULL) { env->PopLocalFrame(NULL); return E_UNEXPECTED; } pmedium->tymed = TYMED_ENHMF; pmedium->hEnhMetaFile = hemf; pmedium->pUnkForRelease = (IUnknown *)NULL; env->PopLocalFrame(NULL); return S_OK; } else if ((matchedFormatEtc.tymed & TYMED_MFPICT) != 0) { LPBYTE lpbMfpBuffer = (LPBYTE)env->GetPrimitiveArrayCritical(bytes, NULL); if (lpbMfpBuffer == NULL) { env->PopLocalFrame(NULL); throw std::bad_alloc(); } HMETAFILE hmf = ::SetMetaFileBitsEx(nBytes - sizeof(METAFILEPICT), lpbMfpBuffer + sizeof(METAFILEPICT)); if (hmf == NULL) { env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbMfpBuffer, JNI_ABORT); env->PopLocalFrame(NULL); return E_UNEXPECTED; } LPMETAFILEPICT lpMfpOld = (LPMETAFILEPICT)lpbMfpBuffer; HMETAFILEPICT hmfp = ::GlobalAlloc(GALLOCFLG, sizeof(METAFILEPICT)); if (hmfp == NULL) { VERIFY(::DeleteMetaFile(hmf)); env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbMfpBuffer, JNI_ABORT); env->PopLocalFrame(NULL); throw std::bad_alloc(); } LPMETAFILEPICT lpMfp = (LPMETAFILEPICT)::GlobalLock(hmfp); lpMfp->mm = lpMfpOld->mm; lpMfp->xExt = lpMfpOld->xExt; lpMfp->yExt = lpMfpOld->yExt; lpMfp->hMF = hmf; ::GlobalUnlock(hmfp); env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbMfpBuffer, JNI_ABORT); pmedium->tymed = TYMED_MFPICT; pmedium->hMetaFilePict = hmfp; pmedium->pUnkForRelease = (IUnknown *)NULL; env->PopLocalFrame(NULL); return S_OK; } env->PopLocalFrame(NULL); return DV_E_TYMED; CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * GetDataHere */ HRESULT __stdcall AwtDragSource::GetDataHere(FORMATETC __RPC_FAR *pFormatEtc, STGMEDIUM __RPC_FAR *pmedium) { TRY; if (pmedium->pUnkForRelease != (IUnknown *)NULL) { return E_INVALIDARG; } HRESULT res = GetProcessId(pFormatEtc, pmedium); if (res == S_OK) { return res; } FORMATETC matchedFormatEtc; res = MatchFormatEtc(pFormatEtc, &matchedFormatEtc); if (res != S_OK) { return res; } JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); if (env->PushLocalFrame(2) < 0) { return E_OUTOFMEMORY; } jbyteArray bytes = AwtDataTransferer::ConvertData(env, m_component, m_transferable, (jlong)matchedFormatEtc.cfFormat, m_formatMap); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return E_UNEXPECTED; } if (bytes == NULL) { env->PopLocalFrame(NULL); return E_UNEXPECTED; } jint nBytes = env->GetArrayLength(bytes); // NOTE: TYMED_ENHMF and TYMED_MFPICT are not valid for GetDataHere(). if ((matchedFormatEtc.tymed & TYMED_ISTREAM) != 0) { jboolean isCopy; jbyte *bBytes = env->GetByteArrayElements(bytes, &isCopy); ULONG act; HRESULT res = pmedium->pstm->Write((const void *)bBytes, (ULONG)nBytes, &act); env->ReleaseByteArrayElements(bytes, bBytes, JNI_ABORT); env->PopLocalFrame(NULL); return S_OK; } else if ((matchedFormatEtc.tymed & TYMED_HGLOBAL) != 0) { ::SetLastError(0); // clear error // Warning C4244. SIZE_T mBytes = ::GlobalSize(pmedium->hGlobal); if (::GetLastError() != 0) { env->PopLocalFrame(NULL); return E_UNEXPECTED; } if (nBytes + ((matchedFormatEtc.cfFormat == CF_HDROP) ? sizeof(DROPFILES) : 0) > mBytes) { env->PopLocalFrame(NULL); return STG_E_MEDIUMFULL; } char *dataout = (char *)::GlobalLock(pmedium->hGlobal); if (matchedFormatEtc.cfFormat == CF_HDROP) { DROPFILES *dropfiles = (DROPFILES *)dataout; dropfiles->pFiles = sizeof(DROPFILES); dropfiles->pt.x = m_dropPoint.x; dropfiles->pt.y = m_dropPoint.y; dropfiles->fNC = m_fNC; dropfiles->fWide = TRUE; // good guess! dataout += sizeof(DROPFILES); } env->GetByteArrayRegion(bytes, 0, nBytes, (jbyte *)dataout); ::GlobalUnlock(pmedium->hGlobal); env->PopLocalFrame(NULL); return S_OK; } env->PopLocalFrame(NULL); return DV_E_TYMED; CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * QueryGetData */ HRESULT __stdcall AwtDragSource::QueryGetData(FORMATETC __RPC_FAR *pFormatEtc) { TRY; return MatchFormatEtc(pFormatEtc, (FORMATETC *)NULL); CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * GetCanonicalFormatEtc */ HRESULT __stdcall AwtDragSource::GetCanonicalFormatEtc(FORMATETC __RPC_FAR *pFormatEtcIn, FORMATETC __RPC_FAR *pFormatEtcOut) { TRY; HRESULT res = MatchFormatEtc(pFormatEtcIn, (FORMATETC *)NULL); if (res != S_OK) return res; *pFormatEtcOut = *pFormatEtcIn; pFormatEtcOut->ptd = NULL; return DATA_S_SAMEFORMATETC; CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * SetData */ HRESULT __stdcall AwtDragSource::SetData(FORMATETC __RPC_FAR *pFormatEtc, STGMEDIUM __RPC_FAR *pmedium, BOOL fRelease) { if (pFormatEtc->cfFormat == CF_PERFORMEDDROPEFFECT && pmedium->tymed == TYMED_HGLOBAL) { m_dwPerformedDropEffect = *(DWORD*)::GlobalLock(pmedium->hGlobal); ::GlobalUnlock(pmedium->hGlobal); if (fRelease) { ::ReleaseStgMedium(pmedium); } return S_OK; } if (fRelease) { //we are copying pmedium as a structure for further use, so no any release! PictureDragHelper::SetData(*pFormatEtc, *pmedium); return S_OK; } return E_UNEXPECTED; } /** * EnumFormatEtc */ HRESULT __stdcall AwtDragSource::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC *__RPC_FAR *ppenumFormatEtc) { TRY; *ppenumFormatEtc = new ADSIEnumFormatEtc(this); return S_OK; CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * DAdvise */ HRESULT __stdcall AwtDragSource::DAdvise(FORMATETC __RPC_FAR *pFormatEtc, DWORD advf, IAdviseSink __RPC_FAR *pAdvSink, DWORD __RPC_FAR *pdwConnection) { return E_NOTIMPL; } /** * DUnadvise */ HRESULT __stdcall AwtDragSource::DUnadvise(DWORD dwConnection) { return OLE_E_ADVISENOTSUPPORTED; } /** * EnumAdvise */ HRESULT __stdcall AwtDragSource::EnumDAdvise(IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise) { return OLE_E_ADVISENOTSUPPORTED; } const UINT AwtDragSource::PROCESS_ID_FORMAT = ::RegisterClipboardFormat(TEXT("_SUNW_JAVA_AWT_PROCESS_ID")); HRESULT __stdcall AwtDragSource::GetProcessId(FORMATETC __RPC_FAR *pFormatEtc, STGMEDIUM __RPC_FAR *pmedium) { if ((pFormatEtc->tymed & TYMED_HGLOBAL) == 0) { return DV_E_TYMED; } else if (pFormatEtc->lindex != -1) { return DV_E_LINDEX; } else if (pFormatEtc->dwAspect != DVASPECT_CONTENT) { return DV_E_DVASPECT; } else if (pFormatEtc->cfFormat != PROCESS_ID_FORMAT) { return DV_E_FORMATETC; } DWORD id = ::CoGetCurrentProcess(); HGLOBAL copy = ::GlobalAlloc(GALLOCFLG, sizeof(id)); if (copy == NULL) { throw std::bad_alloc(); } char *dataout = (char *)::GlobalLock(copy); memcpy(dataout, &id, sizeof(id)); ::GlobalUnlock(copy); pmedium->tymed = TYMED_HGLOBAL; pmedium->hGlobal = copy; pmedium->pUnkForRelease = (IUnknown *)NULL; return S_OK; } DECLARE_JAVA_CLASS(dSCClazz, "sun/awt/windows/WDragSourceContextPeer") void AwtDragSource::call_dSCenter(JNIEnv* env, jobject self, jint targetActions, jint modifiers, jint x, jint y) { DECLARE_VOID_JAVA_METHOD(dSCenter, dSCClazz, "dragEnter", "(IIII)V"); DASSERT(!JNU_IsNull(env, self)); env->CallVoidMethod(self, dSCenter, targetActions, modifiers, x, y); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); } } void AwtDragSource::call_dSCmotion(JNIEnv* env, jobject self, jint targetActions, jint modifiers, jint x, jint y) { DECLARE_VOID_JAVA_METHOD(dSCmotion, dSCClazz, "dragMotion", "(IIII)V"); DASSERT(!JNU_IsNull(env, self)); env->CallVoidMethod(self, dSCmotion, targetActions, modifiers, x, y); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); } } void AwtDragSource::call_dSCchanged(JNIEnv* env, jobject self, jint targetActions, jint modifiers, jint x, jint y) { DECLARE_VOID_JAVA_METHOD(dSCchanged, dSCClazz, "operationChanged", "(IIII)V"); DASSERT(!JNU_IsNull(env, self)); env->CallVoidMethod(self, dSCchanged, targetActions, modifiers, x, y); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); } } void AwtDragSource::call_dSCexit(JNIEnv* env, jobject self, jint x, jint y) { DECLARE_VOID_JAVA_METHOD(dSCexit, dSCClazz, "dragExit", "(II)V"); DASSERT(!JNU_IsNull(env, self)); env->CallVoidMethod(self, dSCexit, x, y); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); } } void AwtDragSource::call_dSCddfinished(JNIEnv* env, jobject self, jboolean success, jint operations, jint x, jint y) { DECLARE_VOID_JAVA_METHOD(dSCddfinished, dSCClazz, "dragDropFinished", "(ZIII)V"); DASSERT(!JNU_IsNull(env, self)); env->CallVoidMethod(self, dSCddfinished, success, operations, x, y); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); } } void AwtDragSource::call_dSCmouseMoved(JNIEnv* env, jobject self, jint targetActions, jint modifiers, jint x, jint y) { DECLARE_VOID_JAVA_METHOD(dSCmouseMoved, dSCClazz, "dragMouseMoved", "(IIII)V"); DASSERT(!JNU_IsNull(env, self)); env->CallVoidMethod(self, dSCmouseMoved, targetActions, modifiers, x, y); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); } } DECLARE_JAVA_CLASS(awtIEClazz, "java/awt/event/InputEvent") /** * Constructor */ AwtDragSource::ADSIEnumFormatEtc::ADSIEnumFormatEtc(AwtDragSource* parent) { m_parent = parent; m_idx = 0; m_refs = 0; m_parent->AddRef(); AddRef(); } /** * Destructor */ AwtDragSource::ADSIEnumFormatEtc::~ADSIEnumFormatEtc() { m_parent->Release(); } /** * QueryInterface */ HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) { TRY; if (riid == IID_IUnknown) { *ppvObject = (void __RPC_FAR *__RPC_FAR)(IUnknown*)this; AddRef(); return S_OK; } else if (riid == IID_IEnumFORMATETC) { *ppvObject = (void __RPC_FAR *__RPC_FAR)(IEnumFORMATETC*)this; AddRef(); return S_OK; } else { *ppvObject = (void __RPC_FAR *__RPC_FAR)NULL; return E_NOINTERFACE; } CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * AddRef */ ULONG __stdcall AwtDragSource::ADSIEnumFormatEtc::AddRef(void) { return (ULONG)++m_refs; } /** * Release */ ULONG __stdcall AwtDragSource::ADSIEnumFormatEtc::Release(void) { int refs; if ((refs = --m_refs) == 0) delete this; return (ULONG)refs; } /** * Next */ HRESULT _stdcall AwtDragSource::ADSIEnumFormatEtc::Next(ULONG celt, FORMATETC __RPC_FAR *rgelt, ULONG __RPC_FAR *pceltFetched) { TRY; unsigned int len = m_parent->getNTypes(); unsigned int i; for (i = 0; i < celt && m_idx < len; i++, m_idx++) { FORMATETC fetc = m_parent->getType(m_idx); rgelt[i] = fetc; } if (pceltFetched != NULL) *pceltFetched = i; return i == celt ? S_OK : S_FALSE; CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * Skip */ HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::Skip(ULONG celt) { TRY; unsigned int len = m_parent->getNTypes(); unsigned int tmp = m_idx + celt; if (tmp < len) { m_idx = tmp; return S_OK; } else { m_idx = len; return S_FALSE; } CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * Reset */ HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::Reset(void) { m_idx = 0; return S_OK; } /** * Clone */ HRESULT __stdcall AwtDragSource::ADSIEnumFormatEtc::Clone(IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenum) { TRY; *ppenum = new ADSIEnumFormatEtc(m_parent); (*ppenum)->Skip(m_idx); return S_OK; CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * constructor */ AwtDragSource::ADSIStreamProxy::ADSIStreamProxy(AwtDragSource* parent, jbyteArray buffer, jint blen) { JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); m_parent = parent; m_buffer = (signed char *)safe_Calloc(sizeof(signed char), m_blen = blen); env->GetByteArrayRegion(buffer, 0, blen, m_buffer); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) return; m_off = 0; m_cloneof = (ADSIStreamProxy*)NULL; m_refs = 0; FILETIME now; ::CoFileTimeNow(&now); m_statstg.pwcsName = (LPWSTR)NULL; m_statstg.type = STGTY_STREAM; m_statstg.cbSize.HighPart = 0; m_statstg.cbSize.LowPart = m_blen; m_statstg.mtime = now; m_statstg.ctime = now; m_statstg.atime = now; m_statstg.grfMode = STGM_READ; m_statstg.grfLocksSupported = FALSE; m_statstg.clsid = CLSID_NULL; m_statstg.grfStateBits = 0; m_statstg.reserved = 0; m_parent->AddRef(); AddRef(); } /** * constructor (clone) */ AwtDragSource::ADSIStreamProxy::ADSIStreamProxy(ADSIStreamProxy* cloneof) { m_cloneof = cloneof; m_parent = cloneof->m_parent; m_buffer = cloneof->m_buffer; m_blen = cloneof->m_blen; m_off = cloneof->m_off; m_statstg = cloneof->m_statstg; m_refs = 0; m_parent->AddRef(); m_cloneof->AddRef(); } /** * destructor */ AwtDragSource::ADSIStreamProxy::~ADSIStreamProxy() { if (m_cloneof == (ADSIStreamProxy*)NULL) free((void *)m_buffer); else { m_cloneof->Release(); } m_parent->Release(); } /** * QueryInterface */ HRESULT __stdcall AwtDragSource::ADSIStreamProxy::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) { TRY; if (riid == IID_IUnknown) { *ppvObject = (void __RPC_FAR *__RPC_FAR)(IUnknown*)this; AddRef(); return S_OK; } else if (riid == IID_IStream) { *ppvObject = (void __RPC_FAR *__RPC_FAR)(IStream*)this; AddRef(); return S_OK; } else { *ppvObject = (void __RPC_FAR *__RPC_FAR)NULL; return E_NOINTERFACE; } CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * AddRef */ ULONG __stdcall AwtDragSource::ADSIStreamProxy::AddRef(void) { return (ULONG)++m_refs; } /** * Release */ ULONG __stdcall AwtDragSource::ADSIStreamProxy::Release(void) { int refs; if ((refs = --m_refs) == 0) delete this; return (ULONG)refs; } /** * Read */ HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead) { TRY; unsigned int rem = m_blen - m_off; int read = cb > rem ? rem : cb; if (read > 0) memmove(pv, (void *)(m_buffer + m_off), read); m_off += read; if (pcbRead != (ULONG __RPC_FAR *)NULL) { *pcbRead = read; } FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; return S_OK; CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * Write */ HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Write(const void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbWritten) { TRY; if (pcbWritten != (ULONG __RPC_FAR *)NULL) { *pcbWritten = 0; } FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; return STG_E_CANTSAVE; // dont support writing CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * Seek */ HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER __RPC_FAR *plibNewPosition) { TRY; if (dlibMove.HighPart != 0) return STG_E_INVALIDPOINTER; if (plibNewPosition != (ULARGE_INTEGER __RPC_FAR *)NULL) { plibNewPosition->HighPart = 0; plibNewPosition->LowPart = 0; } switch (dwOrigin) { case STREAM_SEEK_SET: { if (dlibMove.HighPart != 0 || dlibMove.LowPart >= m_blen) return STG_E_INVALIDPOINTER; m_off = dlibMove.LowPart; } break; case STREAM_SEEK_CUR: case STREAM_SEEK_END: { if (dlibMove.HighPart > 0) return STG_E_INVALIDPOINTER; long newoff = (dwOrigin == STREAM_SEEK_END ? m_blen : m_off) + dlibMove.LowPart; if (newoff < 0 || newoff >= (long)m_blen) return STG_E_INVALIDPOINTER; else m_off = newoff; } break; default: return STG_E_INVALIDFUNCTION; } if (plibNewPosition != (ULARGE_INTEGER __RPC_FAR *)NULL) plibNewPosition->LowPart = m_off; FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; return S_OK; CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * SetSize */ HRESULT __stdcall AwtDragSource::ADSIStreamProxy::SetSize(ULARGE_INTEGER libNewSize) { return STG_E_INVALIDFUNCTION; } /** * CopyTo */ HRESULT __stdcall AwtDragSource::ADSIStreamProxy::CopyTo(IStream __RPC_FAR *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER __RPC_FAR *pcbRead, ULARGE_INTEGER __RPC_FAR *pcbWritten) { TRY; ULONG written = 0; pcbWritten->HighPart = (ULONG)0; pcbWritten->LowPart = (ULONG)0; pcbRead->HighPart = (ULONG)0; unsigned int rem = m_blen - m_off; int ovrflow = cb.LowPart >= rem; if (cb.HighPart != 0) return STG_E_INVALIDPOINTER; ULONG nbytes = pcbRead->LowPart = (ULONG)(ovrflow ? rem : cb.LowPart); HRESULT res = pstm->Write((const void *)(m_buffer + m_off), nbytes, &written); pcbWritten->LowPart = written; FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; return res; CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * Commit */ HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Commit(DWORD grfCommitFlags) { return S_OK; } /** * Revert */ HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Revert() { return S_OK; } /** * LockRegion */ HRESULT __stdcall AwtDragSource::ADSIStreamProxy::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { return STG_E_INVALIDFUNCTION; } /** * UnlockRegion */ HRESULT __stdcall AwtDragSource::ADSIStreamProxy::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { return STG_E_INVALIDFUNCTION; } /** * Stat */ HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Stat(STATSTG __RPC_FAR *pstatstg, DWORD grfStatFlag) { TRY; *pstatstg = m_statstg; FILETIME now; ::CoFileTimeNow(&now); m_statstg.atime = now; return S_OK; CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /** * Clone */ HRESULT __stdcall AwtDragSource::ADSIStreamProxy::Clone(IStream __RPC_FAR *__RPC_FAR *ppstm) { TRY; *ppstm = new ADSIStreamProxy(this); return S_OK; CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY); } /*****************************************************************************/ extern "C" { /** * setNativeCursor */ JNIEXPORT void JNICALL Java_sun_awt_windows_WDragSourceContextPeer_setNativeCursor(JNIEnv* env, jobject self, jlong nativeCtxt, jobject cursor, jint type) { TRY; AwtDragSource* ds = (AwtDragSource*)nativeCtxt; if (ds != NULL) { ds->SetCursor(cursor); } CATCH_BAD_ALLOC; } /** * createDragSource */ 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) { TRY; if (!AwtDropTarget::IsCurrentDnDDataObject(NULL)) { JNU_ThrowByName(env, "java/awt/dnd/InvalidDnDOperationException", "Drag and drop is in progress"); return (jlong)NULL; } AwtDragSource* ds = new AwtDragSource(env, self, component, transferable, trigger, actions, formats, formatMap); DASSERT(AwtDropTarget::IsLocalDataObject(ds)); return (jlong)ds; CATCH_BAD_ALLOC_RET(0); } /** * doDragDrop */ JNIEXPORT void JNICALL Java_sun_awt_windows_WDragSourceContextPeer_doDragDrop( JNIEnv* env, jobject self, jlong nativeCtxt, jobject cursor, jintArray imageData, jint imageWidth, jint imageHeight, jint x, jint y) { TRY; cursor = env->NewGlobalRef(cursor); if (NULL != imageData) { imageData = (jintArray)env->NewGlobalRef(imageData); } AwtDragSource::StartDrag( (AwtDragSource*)nativeCtxt, cursor, imageData, imageWidth, imageHeight, x, y); CATCH_BAD_ALLOC; } } /* extern "C" */