blob: 8739fc8f5763bdfa3892ad6ff51f2a8c4199a501 [file] [log] [blame]
/*
* Copyright (c) 1997, 2014, 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.
*/
#include "awt.h"
#include <shlwapi.h>
#include <shellapi.h>
#include <memory.h>
#include "awt_DataTransferer.h"
#include "awt_Toolkit.h"
#include "java_awt_dnd_DnDConstants.h"
#include "sun_awt_windows_WDropTargetContextPeer.h"
#include "awt_Container.h"
#include "alloc.h"
#include "awt_ole.h"
#include "awt_DnDDT.h"
#include "awt_DnDDS.h"
// forwards
extern "C" {
DWORD __cdecl convertActionsToDROPEFFECT(jint actions);
jint __cdecl convertDROPEFFECTToActions(DWORD effects);
DWORD __cdecl mapModsToDROPEFFECT(DWORD, DWORD);
} // extern "C"
IDataObject* AwtDropTarget::sm_pCurrentDnDDataObject = (IDataObject*)NULL;
/**
* constructor
*/
AwtDropTarget::AwtDropTarget(JNIEnv* env, AwtComponent* component) {
m_component = component;
m_window = component->GetHWnd();
m_refs = 1U;
m_target = env->NewGlobalRef(component->GetTarget(env));
m_registered = 0;
m_dataObject = NULL;
m_formats = NULL;
m_nformats = 0;
m_dtcp = NULL;
m_cfFormats = NULL;
m_mutex = ::CreateMutex(NULL, FALSE, NULL);
m_pIDropTargetHelper = NULL;
}
/**
* destructor
*/
AwtDropTarget::~AwtDropTarget() {
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_target);
env->DeleteGlobalRef(m_dtcp);
}
::CloseHandle(m_mutex);
UnloadCache();
}
/**
* QueryInterface
*/
HRESULT __stdcall AwtDropTarget::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) {
if ( IID_IUnknown == riid ||
IID_IDropTarget == riid )
{
*ppvObject = static_cast<IDropTarget*>(this);
AddRef();
return S_OK;
}
*ppvObject = NULL;
return E_NOINTERFACE;
}
/**
* AddRef
*/
ULONG __stdcall AwtDropTarget::AddRef() {
return (ULONG)++m_refs;
}
/**
* Release
*/
ULONG __stdcall AwtDropTarget::Release() {
int refs;
if ((refs = --m_refs) == 0) delete this;
return (ULONG)refs;
}
/**
* DragEnter
*/
HRESULT __stdcall AwtDropTarget::DragEnter(IDataObject __RPC_FAR *pDataObj, DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect) {
TRY;
if (NULL != m_pIDropTargetHelper) {
m_pIDropTargetHelper->DragEnter(
m_window,
pDataObj,
(LPPOINT)&pt,
*pdwEffect);
}
AwtInterfaceLocker _lk(this);
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
HRESULT ret = S_OK;
DWORD retEffect = DROPEFFECT_NONE;
jobject dtcp = NULL;
if ( (!IsLocalDnD() && !IsCurrentDnDDataObject(NULL)) ||
(IsLocalDnD() && !IsLocalDataObject(pDataObj)))
{
*pdwEffect = retEffect;
return ret;
}
dtcp = call_dTCcreate(env);
if (dtcp) {
env->DeleteGlobalRef(m_dtcp);
m_dtcp = env->NewGlobalRef(dtcp);
env->DeleteLocalRef(dtcp);
}
if (JNU_IsNull(env, m_dtcp) || !JNU_IsNull(env, safe_ExceptionOccurred(env))) {
return ret;
}
LoadCache(pDataObj);
{
POINT cp;
RECT wr;
::GetWindowRect(m_window, &wr);
cp.x = pt.x - wr.left;
cp.y = pt.y - wr.top;
jint actions = call_dTCenter(env, m_dtcp, m_target,
(jint)cp.x, (jint)cp.y,
::convertDROPEFFECTToActions(mapModsToDROPEFFECT(*pdwEffect, grfKeyState)),
::convertDROPEFFECTToActions(*pdwEffect),
m_cfFormats, (jlong)this);
try {
if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) {
env->ExceptionDescribe();
env->ExceptionClear();
actions = java_awt_dnd_DnDConstants_ACTION_NONE;
}
} catch (std::bad_alloc&) {
retEffect = ::convertActionsToDROPEFFECT(actions);
*pdwEffect = retEffect;
throw;
}
retEffect = ::convertActionsToDROPEFFECT(actions);
}
*pdwEffect = retEffect;
return ret;
CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY);
}
/**
* DragOver
*/
HRESULT __stdcall AwtDropTarget::DragOver(DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect) {
TRY;
if (NULL != m_pIDropTargetHelper) {
m_pIDropTargetHelper->DragOver(
(LPPOINT)&pt,
*pdwEffect
);
}
AwtInterfaceLocker _lk(this);
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
HRESULT ret = S_OK;
POINT cp;
RECT wr;
jint actions;
if ( (!IsLocalDnD() && !IsCurrentDnDDataObject(m_dataObject)) ||
(IsLocalDnD() && !IsLocalDataObject(m_dataObject)))
{
*pdwEffect = DROPEFFECT_NONE;
return ret;
}
::GetWindowRect(m_window, &wr);
cp.x = pt.x - wr.left;
cp.y = pt.y - wr.top;
actions = call_dTCmotion(env, m_dtcp, m_target,(jint)cp.x, (jint)cp.y,
::convertDROPEFFECTToActions(mapModsToDROPEFFECT(*pdwEffect, grfKeyState)),
::convertDROPEFFECTToActions(*pdwEffect),
m_cfFormats, (jlong)this);
try {
if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) {
env->ExceptionDescribe();
env->ExceptionClear();
actions = java_awt_dnd_DnDConstants_ACTION_NONE;
}
} catch (std::bad_alloc&) {
*pdwEffect = ::convertActionsToDROPEFFECT(actions);
throw;
}
*pdwEffect = ::convertActionsToDROPEFFECT(actions);
return ret;
CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY);
}
/**
* DragLeave
*/
HRESULT __stdcall AwtDropTarget::DragLeave() {
TRY_NO_VERIFY;
if (NULL != m_pIDropTargetHelper) {
m_pIDropTargetHelper->DragLeave();
}
AwtInterfaceLocker _lk(this);
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
HRESULT ret = S_OK;
if ( (!IsLocalDnD() && !IsCurrentDnDDataObject(m_dataObject)) ||
(IsLocalDnD() && !IsLocalDataObject(m_dataObject)))
{
DragCleanup();
return ret;
}
call_dTCexit(env, m_dtcp, m_target, (jlong)this);
try {
if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) {
env->ExceptionDescribe();
env->ExceptionClear();
}
} catch (std::bad_alloc&) {
DragCleanup();
throw;
}
DragCleanup();
return ret;
CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY);
}
/**
* Drop
*/
HRESULT __stdcall AwtDropTarget::Drop(IDataObject __RPC_FAR *pDataObj, DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect) {
TRY;
if (NULL != m_pIDropTargetHelper) {
m_pIDropTargetHelper->Drop(
pDataObj,
(LPPOINT)&pt,
*pdwEffect
);
}
AwtInterfaceLocker _lk(this);
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
HRESULT ret = S_OK;
POINT cp;
RECT wr;
if ( (!IsLocalDnD() && !IsCurrentDnDDataObject(pDataObj)) ||
(IsLocalDnD() && !IsLocalDataObject(pDataObj)))
{
*pdwEffect = DROPEFFECT_NONE;
DragCleanup();
return ret;
}
LoadCache(pDataObj);
::GetWindowRect(m_window, &wr);
cp.x = pt.x - wr.left;
cp.y = pt.y - wr.top;
m_dropActions = java_awt_dnd_DnDConstants_ACTION_NONE;
call_dTCdrop(env, m_dtcp, m_target, (jint)cp.x, (jint)cp.y,
::convertDROPEFFECTToActions(mapModsToDROPEFFECT(*pdwEffect, grfKeyState)),
::convertDROPEFFECTToActions(*pdwEffect),
m_cfFormats, (jlong)this);
try {
if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) {
env->ExceptionDescribe();
env->ExceptionClear();
ret = E_FAIL;
}
} catch (std::bad_alloc&) {
AwtToolkit::GetInstance().MessageLoop(AwtToolkit::SecondaryIdleFunc,
AwtToolkit::CommonPeekMessageFunc);
*pdwEffect = ::convertActionsToDROPEFFECT(m_dropActions);
DragCleanup();
throw;
}
/*
* Fix for 4623377.
* Dispatch all messages in the nested message loop running while the drop is
* processed. This ensures that the modal dialog shown during drop receives
* all events and so it is able to close. This way the app won't deadlock.
*/
AwtToolkit::GetInstance().MessageLoop(AwtToolkit::SecondaryIdleFunc,
AwtToolkit::CommonPeekMessageFunc);
ret = (m_dropSuccess == JNI_TRUE) ? S_OK : E_FAIL;
*pdwEffect = ::convertActionsToDROPEFFECT(m_dropActions);
DragCleanup();
return ret;
CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY);
}
/**
* DoDropDone
*/
void AwtDropTarget::DoDropDone(jboolean success, jint action) {
DropDoneRec ddr = { this, success, action };
AwtToolkit::GetInstance().InvokeFunction(_DropDone, &ddr);
}
/**
* _DropDone
*/
void AwtDropTarget::_DropDone(void* param) {
DropDonePtr ddrp = (DropDonePtr)param;
(ddrp->dropTarget)->DropDone(ddrp->success, ddrp->action);
}
/**
* DropDone
*/
void AwtDropTarget::DropDone(jboolean success, jint action) {
m_dropSuccess = success;
m_dropActions = action;
AwtToolkit::GetInstance().QuitMessageLoop(AwtToolkit::EXIT_ENCLOSING_LOOP);
}
/**
* DoRegisterTarget
*/
void AwtDropTarget::_RegisterTarget(void* param) {
RegisterTargetPtr rtrp = (RegisterTargetPtr)param;
rtrp->dropTarget->RegisterTarget(rtrp->show);
}
/**
* RegisterTarget
*/
void AwtDropTarget::RegisterTarget(WORD show) {
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
HRESULT res;
if (!AwtToolkit::IsMainThread()) {
RegisterTargetRec rtr = { this, show };
AwtToolkit::GetInstance().InvokeFunction(_RegisterTarget, &rtr);
return;
}
// if we are'nt yet visible, defer until the parent is!
if (show) {
OLE_TRY
OLE_HRT(CoCreateInstance(
CLSID_DragDropHelper,
NULL,
CLSCTX_ALL,
IID_IDropTargetHelper,
(LPVOID*)&m_pIDropTargetHelper
))
OLE_HRT(::RegisterDragDrop(m_window, (IDropTarget*)this))
OLE_CATCH
res = OLE_HR;
} else {
res = ::RevokeDragDrop(m_window);
if (NULL != m_pIDropTargetHelper) {
m_pIDropTargetHelper->Release();
}
}
if (res == S_OK) m_registered = show;
}
/**
* DoGetData
*/
jobject AwtDropTarget::DoGetData(jlong format) {
jobject ret = (jobject)NULL;
GetDataRec gdr = { this, format, &ret };
AwtToolkit::GetInstance().WaitForSingleObject(m_mutex);
AwtToolkit::GetInstance().InvokeFunctionLater(_GetData, &gdr);
WaitUntilSignalled(FALSE);
return ret;
}
/**
* _GetData
*/
void AwtDropTarget::_GetData(void* param) {
GetDataPtr gdrp = (GetDataPtr)param;
*(gdrp->ret) = gdrp->dropTarget->GetData(gdrp->format);
gdrp->dropTarget->Signal();
}
/**
* GetData
*
* Returns the data object being transferred.
*/
HRESULT AwtDropTarget::ExtractNativeData(
jlong fmt,
LONG lIndex,
STGMEDIUM *pmedium)
{
FORMATETC format = { (unsigned short)fmt };
HRESULT hr = E_INVALIDARG;
static const DWORD supportedTymeds[] = {
TYMED_ISTREAM,
TYMED_ENHMF,
TYMED_GDI,
TYMED_MFPICT,
TYMED_FILE,
TYMED_HGLOBAL
};
for (int i = 0; i < sizeof(supportedTymeds)/sizeof(supportedTymeds[0]); ++i) {
// Only TYMED_HGLOBAL is supported for CF_LOCALE.
if (fmt == CF_LOCALE && supportedTymeds[i] != TYMED_HGLOBAL) {
continue;
}
format.tymed = supportedTymeds[i];
FORMATETC *cpp = (FORMATETC *)bsearch(
(const void *)&format,
(const void *)m_formats,
(size_t)m_nformats,
(size_t)sizeof(FORMATETC),
_compar);
if (NULL == cpp) {
continue;
}
format = *cpp;
format.lindex = lIndex;
hr = m_dataObject->GetData(&format, pmedium);
if (SUCCEEDED(hr)) {
return hr;
}
}
return hr;
}
HRESULT CheckRetValue(
JNIEnv* env,
jobject ret)
{
if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) {
return E_UNEXPECTED;
} else if (JNU_IsNull(env, ret)) {
return E_INVALIDARG;
}
return S_OK;
}
jobject AwtDropTarget::ConvertNativeData(JNIEnv* env, jlong fmt, STGMEDIUM *pmedium) /*throw std::bad_alloc */
{
jobject ret = NULL;
jbyteArray paletteDataLocal = NULL;
HRESULT hr = S_OK;
switch (pmedium->tymed) {
case TYMED_HGLOBAL: {
if (fmt == CF_LOCALE) {
LCID *lcid = (LCID *)::GlobalLock(pmedium->hGlobal);
if (NULL == lcid) {
hr = E_INVALIDARG;
} else {
try{
ret = AwtDataTransferer::LCIDToTextEncoding(env, *lcid);
hr = CheckRetValue(env, ret);
} catch (std::bad_alloc&) {
hr = E_OUTOFMEMORY;
}
::GlobalUnlock(pmedium->hGlobal);
}
} else {
::SetLastError(0); // clear error
// Warning C4244.
// Cast SIZE_T (__int64 on 64-bit/unsigned int on 32-bit)
// to jsize (long).
SIZE_T globalSize = ::GlobalSize(pmedium->hGlobal);
jsize size = (globalSize <= INT_MAX) ? (jsize)globalSize : INT_MAX;
if (size == 0 && ::GetLastError() != 0) {
hr = E_INVALIDARG;
} else {
jbyteArray bytes = env->NewByteArray(size);
if (NULL == bytes) {
hr = E_OUTOFMEMORY;
} else {
LPVOID data = ::GlobalLock(pmedium->hGlobal);
if (NULL == data) {
hr = E_INVALIDARG;
} else {
env->SetByteArrayRegion(bytes, 0, size, (jbyte *)data);
ret = bytes;
//bytes is not null here => no CheckRetValue call
::GlobalUnlock(pmedium->hGlobal);
}
}
}
}
break;
}
case TYMED_FILE: {
jobject local = JNU_NewStringPlatform(
env,
pmedium->lpszFileName);
if (env->ExceptionCheck()) {
hr = E_OUTOFMEMORY;
break;
}
jstring fileName = (jstring)env->NewGlobalRef(local);
env->DeleteLocalRef(local);
STGMEDIUM *stgm = NULL;
try {
//on success stgm would be deallocated by JAVA call freeStgMedium
stgm = (STGMEDIUM *)safe_Malloc(sizeof(STGMEDIUM));
memcpy(stgm, pmedium, sizeof(STGMEDIUM));
// Warning C4311.
// Cast pointer to jlong (__int64).
ret = call_dTCgetfs(env, fileName, (jlong)stgm);
hr = CheckRetValue(env, ret);
} catch (std::bad_alloc&) {
hr = E_OUTOFMEMORY;
}
if (FAILED(hr)) {
//free just on error
env->DeleteGlobalRef(fileName);
free(stgm);
}
break;
}
case TYMED_ISTREAM: {
WDTCPIStreamWrapper* istream = NULL;
try {
istream = new WDTCPIStreamWrapper(pmedium);
// Warning C4311.
// Cast pointer to jlong (__int64).
ret = call_dTCgetis(env, (jlong)istream);
hr = CheckRetValue(env, ret);
} catch (std::bad_alloc&) {
hr = E_OUTOFMEMORY;
}
if (FAILED(hr) && NULL!=istream) {
//free just on error
istream->Close();
}
break;
}
case TYMED_GDI:
// Currently support only CF_PALETTE for TYMED_GDI.
if (CF_PALETTE == fmt) {
ret = AwtDataTransferer::GetPaletteBytes(
pmedium->hBitmap,
0,
TRUE);
hr = CheckRetValue(env, ret);
}
break;
case TYMED_MFPICT:
case TYMED_ENHMF: {
HENHMETAFILE hEnhMetaFile = NULL;
if (pmedium->tymed == TYMED_MFPICT ) {
//let's create ENHMF from MFPICT to simplify treatment
LPMETAFILEPICT lpMetaFilePict =
(LPMETAFILEPICT)::GlobalLock(pmedium->hMetaFilePict);
if (NULL == lpMetaFilePict) {
hr = E_INVALIDARG;
} else {
UINT uSize = ::GetMetaFileBitsEx(lpMetaFilePict->hMF, 0, NULL);
if (0 == uSize) {
hr = E_INVALIDARG;
} else {
try{
LPBYTE lpMfBits = (LPBYTE)safe_Malloc(uSize);
VERIFY(::GetMetaFileBitsEx(
lpMetaFilePict->hMF,
uSize,
lpMfBits) == uSize);
hEnhMetaFile = ::SetWinMetaFileBits(
uSize,
lpMfBits,
NULL,
lpMetaFilePict);
free(lpMfBits);
} catch (std::bad_alloc&) {
hr = E_OUTOFMEMORY;
}
}
::GlobalUnlock(pmedium->hMetaFilePict);
}
} else {
hEnhMetaFile = pmedium->hEnhMetaFile;
}
if (NULL == hEnhMetaFile) {
hr = E_INVALIDARG;
} else {
try {
paletteDataLocal = AwtDataTransferer::GetPaletteBytes(
hEnhMetaFile,
OBJ_ENHMETAFILE,
FALSE);
//paletteDataLocal can be NULL here - it is not a error!
UINT uEmfSize = ::GetEnhMetaFileBits(hEnhMetaFile, 0, NULL);
DASSERT(uEmfSize != 0);
LPBYTE lpEmfBits = (LPBYTE)safe_Malloc(uEmfSize);
//no chance to throw exception before catch => no more try-blocks
//and no leaks on lpEmfBits
VERIFY(::GetEnhMetaFileBits(
hEnhMetaFile,
uEmfSize,
lpEmfBits) == uEmfSize);
jbyteArray bytes = env->NewByteArray(uEmfSize);
if (NULL == bytes) {
hr = E_OUTOFMEMORY;
} else {
env->SetByteArrayRegion(bytes, 0, uEmfSize, (jbyte*)lpEmfBits);
ret = bytes;
//bytes is not null here => no CheckRetValue call
}
free(lpEmfBits);
} catch (std::bad_alloc&) {
hr = E_OUTOFMEMORY;
}
if (pmedium->tymed == TYMED_MFPICT) {
//because we create it manually
::DeleteEnhMetaFile(hEnhMetaFile);
}
}
break;
}
case TYMED_ISTORAGE:
default:
hr = E_NOTIMPL;
break;
}
if (FAILED(hr)) {
//clear exception garbage for hr = E_UNEXPECTED
ret = NULL;
} else {
switch (fmt) {
case CF_METAFILEPICT:
case CF_ENHMETAFILE:
// If we failed to retrieve palette entries from metafile,
// fall through and try CF_PALETTE format.
case CF_DIB: {
if (JNU_IsNull(env, paletteDataLocal)) {
jobject paletteData = GetData(CF_PALETTE);
if (JNU_IsNull(env, paletteData)) {
paletteDataLocal =
AwtDataTransferer::GetPaletteBytes(NULL, 0, TRUE);
} else {
// GetData() returns a global ref.
// We want to deal with local ref.
paletteDataLocal = (jbyteArray)env->NewLocalRef(paletteData);
env->DeleteGlobalRef(paletteData);
}
}
DASSERT(!JNU_IsNull(env, paletteDataLocal) &&
!JNU_IsNull(env, ret));
jobject concat = AwtDataTransferer::ConcatData(env, paletteDataLocal, ret);
env->DeleteLocalRef(ret);
ret = concat;
hr = CheckRetValue(env, ret);
break;
}
}
}
if (!JNU_IsNull(env, paletteDataLocal) ) {
env->DeleteLocalRef(paletteDataLocal);
}
jobject global = NULL;
if (SUCCEEDED(hr)) {
global = env->NewGlobalRef(ret);
env->DeleteLocalRef(ret);
} else if (E_UNEXPECTED == hr) {
//internal Java non-GPF exception
env->ExceptionDescribe();
env->ExceptionClear();
} else if (E_OUTOFMEMORY == hr) {
throw std::bad_alloc();
} //NULL returns for all other cases
return global;
}
HRESULT AwtDropTarget::SaveIndexToFile(LPCTSTR pFileName, UINT lIndex)
{
OLE_TRY
STGMEDIUM stgmedium;
OLE_HRT( ExtractNativeData(CF_FILECONTENTS, lIndex, &stgmedium) );
OLE_NEXT_TRY
IStreamPtr spSrc;
if (TYMED_HGLOBAL == stgmedium.tymed) {
OLE_HRT( CreateStreamOnHGlobal(
stgmedium.hGlobal,
FALSE,
&spSrc
));
} else if(TYMED_ISTREAM == stgmedium.tymed) {
spSrc = stgmedium.pstm;
}
if (NULL == spSrc) {
OLE_HRT(E_INVALIDARG);
}
IStreamPtr spDst;
OLE_HRT(SHCreateStreamOnFile(
pFileName,
STGM_WRITE | STGM_CREATE,
&spDst
));
STATSTG si = {0};
OLE_HRT( spSrc->Stat(&si, STATFLAG_NONAME ) );
OLE_HRT( spSrc->CopyTo(spDst, si.cbSize, NULL, NULL) );
OLE_CATCH
::ReleaseStgMedium(&stgmedium);
OLE_CATCH
OLE_RETURN_HR;
}
HRESULT GetTempPathWithSlash(JNIEnv *env, _bstr_t &bsTempPath) /*throws _com_error*/
{
static _bstr_t _bsPath;
OLE_TRY
if (0 == _bsPath.length()) {
BOOL bSafeEmergency = TRUE;
TCHAR szPath[MAX_PATH*2];
JLClass systemCls(env, env->FindClass("java/lang/System"));
if (systemCls) {
jmethodID idGetProperty = env->GetStaticMethodID(
systemCls,
"getProperty",
"(Ljava/lang/String;)Ljava/lang/String;");
if (0 != idGetProperty) {
static TCHAR param[] = _T("java.io.tmpdir");
JLString tempdir(env, JNU_NewStringPlatform(env, param));
if (tempdir) {
JLString jsTempPath(env, (jstring)env->CallStaticObjectMethod(
systemCls,
idGetProperty,
(jstring)tempdir
));
if (jsTempPath) {
_bsPath = (LPCWSTR)JavaStringBuffer(env, jsTempPath);
OLE_HRT(SHGetFolderPath(
NULL,
CSIDL_WINDOWS,
NULL,
0,
szPath));
_tcscat(szPath, _T("\\"));
//Dead environment block leads to fact that windows folder becomes temporary path.
//For example while jtreg execution %TEMP%, %TMP% and etc. aren't defined.
bSafeEmergency = ( 0 == _tcsicmp(_bsPath, szPath) );
}
}
}
}
if (bSafeEmergency) {
OLE_HRT(SHGetFolderPath(
NULL,
CSIDL_INTERNET_CACHE|CSIDL_FLAG_CREATE,
NULL,
0,
szPath));
_tcscat(szPath, _T("\\"));
_bsPath = szPath;
}
}
OLE_CATCH
bsTempPath = _bsPath;
OLE_RETURN_HR
}
jobject AwtDropTarget::ConvertMemoryMappedData(JNIEnv* env, jlong fmt, STGMEDIUM *pmedium) /*throw std::bad_alloc */
{
jobject retObj = NULL;
OLE_TRY
if (TYMED_HGLOBAL != pmedium->tymed) {
OLE_HRT(E_INVALIDARG);
}
FILEGROUPDESCRIPTORA *pfgdHead = (FILEGROUPDESCRIPTORA *)::GlobalLock(pmedium->hGlobal);
if (NULL == pfgdHead) {
OLE_HRT(E_INVALIDARG);
}
OLE_NEXT_TRY
if (0 == pfgdHead->cItems) {
OLE_HRT(E_INVALIDARG);
}
IStreamPtr spFileNames;
OLE_HRT( CreateStreamOnHGlobal(
NULL,
TRUE,
&spFileNames
));
_bstr_t sbTempDir;
OLE_HRT( GetTempPathWithSlash(env, sbTempDir) );
FILEDESCRIPTORA *pfgdA = pfgdHead->fgd;
FILEDESCRIPTORW *pfgdW = (FILEDESCRIPTORW *)pfgdA;
for (UINT i = 0; i < pfgdHead->cItems; ++i) {
_bstr_t stFullName(sbTempDir);
if(CF_FILEGROUPDESCRIPTORA == fmt) {
stFullName += pfgdA->cFileName; //as CHAR
++pfgdA;
} else {
stFullName += pfgdW->cFileName; //as WCHAR
++pfgdW;
}
OLE_HRT(SaveIndexToFile(
stFullName,
i));
//write to stream with zero terminator
OLE_HRT( spFileNames->Write((LPCTSTR)stFullName, (stFullName.length() + 1)*sizeof(TCHAR), NULL) );
}
OLE_HRT( spFileNames->Write(_T(""), sizeof(TCHAR), NULL) );
STATSTG st;
OLE_HRT( spFileNames->Stat(&st, STATFLAG_NONAME) );
//empty lists was forbidden: pfgdHead->cItems > 0
jbyteArray bytes = env->NewByteArray(st.cbSize.LowPart);
if (NULL == bytes) {
OLE_HRT(E_OUTOFMEMORY);
} else {
HGLOBAL glob;
OLE_HRT(GetHGlobalFromStream(spFileNames, &glob));
jbyte *pFileListWithDoubleZeroTerminator = (jbyte *)::GlobalLock(glob);
env->SetByteArrayRegion(bytes, 0, st.cbSize.LowPart, pFileListWithDoubleZeroTerminator);
::GlobalUnlock(pFileListWithDoubleZeroTerminator);
retObj = bytes;
}
//std::bad_alloc could happen in JStringBuffer
//no leaks due to wrapper
OLE_CATCH_BAD_ALLOC
::GlobalUnlock(pmedium->hGlobal);
OLE_CATCH
jobject global = NULL;
if (SUCCEEDED(OLE_HR)) {
global = env->NewGlobalRef(retObj);
env->DeleteLocalRef(retObj);
} else if (E_OUTOFMEMORY == OLE_HR) {
throw std::bad_alloc();
}
return global;
}
jobject AwtDropTarget::GetData(jlong fmt)
{
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
if (env->EnsureLocalCapacity(1) < 0) {
return (jobject)NULL;
}
jobject ret = NULL;
OLE_TRY
STGMEDIUM stgmedium;
OLE_HRT( ExtractNativeData(fmt, -1, &stgmedium) );
OLE_NEXT_TRY
if (CF_FILEGROUPDESCRIPTORA == fmt ||
CF_FILEGROUPDESCRIPTORW == fmt)
{
ret = ConvertMemoryMappedData(env, fmt, &stgmedium);
} else {
ret = ConvertNativeData(env, fmt, &stgmedium);
}
OLE_CATCH_BAD_ALLOC
::ReleaseStgMedium(&stgmedium);
OLE_CATCH
if (E_OUTOFMEMORY == OLE_HR) {
throw std::bad_alloc();
}
return ret;
}
/**
*
*/
int __cdecl AwtDropTarget::_compar(const void* first, const void* second) {
FORMATETC *fp = (FORMATETC *)first;
FORMATETC *sp = (FORMATETC *)second;
if (fp->cfFormat == sp->cfFormat) {
return fp->tymed - sp->tymed;
}
return fp->cfFormat - sp->cfFormat;
}
const unsigned int AwtDropTarget::CACHE_INCR = 16;
void AwtDropTarget::LoadCache(IDataObject* pDataObj) {
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
unsigned int cnt = 0;
HRESULT res;
IEnumFORMATETC* pEnumFormatEtc = NULL;
if (m_dataObject != (IDataObject*)NULL) UnloadCache();
if (!IsLocalDnD()) {
SetCurrentDnDDataObject(pDataObj);
}
(m_dataObject = pDataObj)->AddRef();
res = m_dataObject->EnumFormatEtc(DATADIR_GET, &pEnumFormatEtc);
if (res == S_OK) {
for (;;) {
FORMATETC tmp;
ULONG actual = 1;
res = pEnumFormatEtc->Next((ULONG)1, &tmp, &actual);
if (res == S_FALSE)
break;
if (!(tmp.cfFormat >= 1 &&
tmp.ptd == NULL &&
(tmp.lindex == -1 || CF_FILECONTENTS==tmp.cfFormat) &&
tmp.dwAspect == DVASPECT_CONTENT &&
( tmp.tymed == TYMED_HGLOBAL ||
tmp.tymed == TYMED_FILE ||
tmp.tymed == TYMED_ISTREAM ||
tmp.tymed == TYMED_GDI ||
tmp.tymed == TYMED_MFPICT ||
tmp.tymed == TYMED_ENHMF
) // but not ISTORAGE
)
)
continue;
if (m_dataObject->QueryGetData(&tmp) != S_OK) continue;
if (m_nformats % CACHE_INCR == 0) {
m_formats = (FORMATETC *)SAFE_SIZE_ARRAY_REALLOC(safe_Realloc, m_formats,
CACHE_INCR + m_nformats,
sizeof(FORMATETC));
}
memcpy(m_formats + m_nformats, &tmp, sizeof(FORMATETC));
m_nformats++;
}
// We are responsible for releasing the enumerator.
pEnumFormatEtc->Release();
}
if (m_nformats > 0) {
qsort((void*)m_formats, m_nformats, sizeof(FORMATETC),
AwtDropTarget::_compar);
}
if (m_cfFormats != NULL) {
env->DeleteGlobalRef(m_cfFormats);
}
jlongArray l_cfFormats = env->NewLongArray(m_nformats);
if (l_cfFormats == NULL) {
throw std::bad_alloc();
}
m_cfFormats = (jlongArray)env->NewGlobalRef(l_cfFormats);
env->DeleteLocalRef(l_cfFormats);
jboolean isCopy;
jlong *lcfFormats = env->GetLongArrayElements(m_cfFormats, &isCopy),
*saveFormats = lcfFormats;
for (unsigned int i = 0; i < m_nformats; i++, lcfFormats++) {
*lcfFormats = m_formats[i].cfFormat;
}
env->ReleaseLongArrayElements(m_cfFormats, saveFormats, 0);
}
/**
* UnloadCache
*/
void AwtDropTarget::UnloadCache() {
if (m_dataObject == (IDataObject*)NULL) return;
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
free((void*)m_formats);
m_formats = (FORMATETC *)NULL;
m_nformats = 0;
// fix for 6212440: on application shutdown, this object's
// destruction might be suppressed due to dangling COM references.
// This method is called from the destructor.
// On destruction, VM might be shut down already, so we should make
// a null check on env.
if (env) {
env->DeleteGlobalRef(m_cfFormats);
}
m_cfFormats = NULL;
if (!IsLocalDnD()) {
DASSERT(IsCurrentDnDDataObject(m_dataObject));
SetCurrentDnDDataObject(NULL);
}
m_dataObject->Release();
m_dataObject = (IDataObject*)NULL;
}
/**
* DragCleanup
*/
void AwtDropTarget::DragCleanup(void) {
UnloadCache();
}
BOOL AwtDropTarget::IsLocalDataObject(IDataObject __RPC_FAR *pDataObject) {
BOOL local = FALSE;
if (pDataObject != NULL) {
FORMATETC format;
STGMEDIUM stgmedium;
format.cfFormat = AwtDragSource::PROCESS_ID_FORMAT;
format.ptd = NULL;
format.dwAspect = DVASPECT_CONTENT;
format.lindex = -1;
format.tymed = TYMED_HGLOBAL;
if (pDataObject->GetData(&format, &stgmedium) == S_OK) {
::SetLastError(0); // clear error
// Warning C4244.
SIZE_T size = ::GlobalSize(stgmedium.hGlobal);
if (size < sizeof(DWORD) || ::GetLastError() != 0) {
::SetLastError(0); // clear error
} else {
DWORD id = ::CoGetCurrentProcess();
LPVOID data = ::GlobalLock(stgmedium.hGlobal);
if (memcmp(data, &id, sizeof(id)) == 0) {
local = TRUE;
}
::GlobalUnlock(stgmedium.hGlobal);
}
::ReleaseStgMedium(&stgmedium);
}
}
return local;
}
DECLARE_JAVA_CLASS(dTCClazz, "sun/awt/windows/WDropTargetContextPeer")
jobject
AwtDropTarget::call_dTCcreate(JNIEnv* env) {
DECLARE_STATIC_OBJECT_JAVA_METHOD(dTCcreate, dTCClazz,
"getWDropTargetContextPeer",
"()Lsun/awt/windows/WDropTargetContextPeer;");
return env->CallStaticObjectMethod(clazz, dTCcreate);
}
jint
AwtDropTarget::call_dTCenter(JNIEnv* env, jobject self, jobject component, jint x, jint y,
jint dropAction, jint actions, jlongArray formats,
jlong nativeCtxt) {
DECLARE_JINT_JAVA_METHOD(dTCenter, dTCClazz, "handleEnterMessage",
"(Ljava/awt/Component;IIII[JJ)I");
DASSERT(!JNU_IsNull(env, self));
return env->CallIntMethod(self, dTCenter, component, x, y, dropAction,
actions, formats, nativeCtxt);
}
void
AwtDropTarget::call_dTCexit(JNIEnv* env, jobject self, jobject component, jlong nativeCtxt) {
DECLARE_VOID_JAVA_METHOD(dTCexit, dTCClazz, "handleExitMessage",
"(Ljava/awt/Component;J)V");
DASSERT(!JNU_IsNull(env, self));
env->CallVoidMethod(self, dTCexit, component, nativeCtxt);
}
jint
AwtDropTarget::call_dTCmotion(JNIEnv* env, jobject self, jobject component, jint x, jint y,
jint dropAction, jint actions, jlongArray formats,
jlong nativeCtxt) {
DECLARE_JINT_JAVA_METHOD(dTCmotion, dTCClazz, "handleMotionMessage",
"(Ljava/awt/Component;IIII[JJ)I");
DASSERT(!JNU_IsNull(env, self));
return env->CallIntMethod(self, dTCmotion, component, x, y,
dropAction, actions, formats, nativeCtxt);
}
void
AwtDropTarget::call_dTCdrop(JNIEnv* env, jobject self, jobject component, jint x, jint y,
jint dropAction, jint actions, jlongArray formats,
jlong nativeCtxt) {
DECLARE_VOID_JAVA_METHOD(dTCdrop, dTCClazz, "handleDropMessage",
"(Ljava/awt/Component;IIII[JJ)V");
DASSERT(!JNU_IsNull(env, self));
env->CallVoidMethod(self, dTCdrop, component, x, y,
dropAction, actions, formats, nativeCtxt);
}
jobject
AwtDropTarget::call_dTCgetfs(JNIEnv* env, jstring fileName, jlong stgmedium) {
DECLARE_STATIC_OBJECT_JAVA_METHOD(dTCgetfs, dTCClazz, "getFileStream",
"(Ljava/lang/String;J)Ljava/io/FileInputStream;");
return env->CallStaticObjectMethod(clazz, dTCgetfs, fileName, stgmedium);
}
jobject
AwtDropTarget::call_dTCgetis(JNIEnv* env, jlong istream) {
DECLARE_STATIC_OBJECT_JAVA_METHOD(dTCgetis, dTCClazz, "getIStream",
"(J)Ljava/lang/Object;");
return env->CallStaticObjectMethod(clazz, dTCgetis, istream);
}
/*****************************************************************************/
/**
* construct a wrapper
*/
WDTCPIStreamWrapper::WDTCPIStreamWrapper(STGMEDIUM* stgmedium) {
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
m_stgmedium = *stgmedium;
m_istream = stgmedium->pstm;
m_istream->AddRef();
m_mutex = ::CreateMutex(NULL, FALSE, NULL);
}
/**
* destroy a wrapper
*/
WDTCPIStreamWrapper::~WDTCPIStreamWrapper() {
::CloseHandle(m_mutex);
m_istream->Release();
::ReleaseStgMedium(&m_stgmedium);
}
/**
* return available data
*/
jint WDTCPIStreamWrapper::DoAvailable(WDTCPIStreamWrapper* istream) {
WDTCPIStreamWrapperRec iswr = { istream, 0 };
AwtToolkit::GetInstance().WaitForSingleObject(istream->m_mutex);
AwtToolkit::GetInstance().InvokeFunctionLater( _Available, &iswr);
istream->WaitUntilSignalled(FALSE);
return iswr.ret;
}
/**
* return available data
*/
void WDTCPIStreamWrapper::_Available(void *param) {
WDTCPIStreamWrapperPtr iswrp = (WDTCPIStreamWrapperPtr)param;
iswrp->ret = (iswrp->istream)->Available();
iswrp->istream->Signal();
}
/**
* return available data
*/
jint WDTCPIStreamWrapper::Available() {
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
if (m_istream->Stat(&m_statstg, STATFLAG_NONAME) != S_OK) {
JNU_ThrowIOException(env, "IStream::Stat() failed");
return 0;
}
if (m_statstg.cbSize.QuadPart > 0x7ffffffL) {
JNU_ThrowIOException(env, "IStream::Stat() cbSize > 0x7ffffff");
return 0;
}
return (jint)m_statstg.cbSize.LowPart;
}
/**
* read 1 byte
*/
jint WDTCPIStreamWrapper::DoRead(WDTCPIStreamWrapper* istream) {
WDTCPIStreamWrapperRec iswr = { istream, 0 };
AwtToolkit::GetInstance().WaitForSingleObject(istream->m_mutex);
AwtToolkit::GetInstance().InvokeFunctionLater(_Read, &iswr);
istream->WaitUntilSignalled(FALSE);
return iswr.ret;
}
/**
* read 1 byte
*/
void WDTCPIStreamWrapper::_Read(void* param) {
WDTCPIStreamWrapperPtr iswrp = (WDTCPIStreamWrapperPtr)param;
iswrp->ret = (iswrp->istream)->Read();
iswrp->istream->Signal();
}
/**
* read 1 byte
*/
jint WDTCPIStreamWrapper::Read() {
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jint b = 0;
ULONG actual = 0;
HRESULT res;
switch (res = m_istream->Read((void *)&b, (ULONG)1, &actual)) {
case S_FALSE:
return (jint)-1;
case S_OK:
return (jint)(actual == 0 ? -1 : b);
default:
JNU_ThrowIOException(env, "IStream::Read failed");
}
return (jint)-1;
}
/**
* read Buffer
*/
jint WDTCPIStreamWrapper::DoReadBytes(WDTCPIStreamWrapper* istream, jbyteArray array, jint off, jint len) {
WDTCPIStreamWrapperReadBytesRec iswrbr = { istream, 0, array, off, len };
AwtToolkit::GetInstance().WaitForSingleObject(istream->m_mutex);
AwtToolkit::GetInstance().InvokeFunctionLater(_ReadBytes, &iswrbr);
istream->WaitUntilSignalled(FALSE);
return iswrbr.ret;
}
/**
* read buffer
*/
void WDTCPIStreamWrapper::_ReadBytes(void* param) {
WDTCPIStreamWrapperReadBytesPtr iswrbrp =
(WDTCPIStreamWrapperReadBytesPtr)param;
iswrbrp->ret = (iswrbrp->istream)->ReadBytes(iswrbrp->array,
iswrbrp->off,
iswrbrp->len);
iswrbrp->istream->Signal();
}
/**
* read buffer
*/
jint WDTCPIStreamWrapper::ReadBytes(jbyteArray buf, jint off, jint len) {
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jboolean isCopy = JNI_FALSE;
ULONG actual = 0;
jbyte* local = env->GetByteArrayElements(buf, &isCopy);
HRESULT res;
CHECK_NULL_RETURN(local, (jint)-1);
switch (res = m_istream->Read((void *)(local + off), (ULONG)len, &actual)) {
case S_FALSE:
case S_OK: {
int eof = (actual == 0);
env->ReleaseByteArrayElements(buf, local, !eof ? 0 : JNI_ABORT);
return (jint)(!eof ? actual : -1);
}
default:
env->ReleaseByteArrayElements(buf, local, JNI_ABORT);
JNU_ThrowIOException(env, "IStream::Read failed");
}
return (jint)-1;
}
/**
* close
*/
void WDTCPIStreamWrapper::DoClose(WDTCPIStreamWrapper* istream) {
AwtToolkit::GetInstance().InvokeFunctionLater(_Close, istream);
}
/**
* close
*/
void WDTCPIStreamWrapper::_Close(void* param) {
((WDTCPIStreamWrapper*)param)->Close();
}
/**
* close
*/
void WDTCPIStreamWrapper::Close() {
delete this;
}
/*****************************************************************************/
extern "C" {
/**
* awt_dnd_initialize: initial DnD system
*/
void awt_dnd_initialize() {
::OleInitialize((LPVOID)NULL);
}
/**
* awt_dnd_uninitialize: deactivate DnD system
*/
void awt_dnd_uninitialize() {
::OleUninitialize();
}
/**
* convertActionsToDROPEFFECT
*/
DWORD convertActionsToDROPEFFECT(jint actions) {
DWORD effects = DROPEFFECT_NONE;
if (actions & java_awt_dnd_DnDConstants_ACTION_LINK) effects |= DROPEFFECT_LINK;
if (actions & java_awt_dnd_DnDConstants_ACTION_MOVE) effects |= DROPEFFECT_MOVE;
if (actions & java_awt_dnd_DnDConstants_ACTION_COPY) effects |= DROPEFFECT_COPY;
return effects;
}
/**
* convertDROPEFFECTToAction
*/
jint convertDROPEFFECTToActions(DWORD effects) {
jint actions = java_awt_dnd_DnDConstants_ACTION_NONE;
if (effects & DROPEFFECT_LINK) actions |= java_awt_dnd_DnDConstants_ACTION_LINK;
if (effects & DROPEFFECT_MOVE) actions |= java_awt_dnd_DnDConstants_ACTION_MOVE;
if (effects & DROPEFFECT_COPY) actions |= java_awt_dnd_DnDConstants_ACTION_COPY;
return actions;
}
/**
* map keyboard modifiers to a DROPEFFECT
*/
DWORD mapModsToDROPEFFECT(DWORD effects, DWORD mods) {
DWORD ret = DROPEFFECT_NONE;
/*
* Fix for 4285634.
* Calculate the drop action to match Motif DnD behavior.
* If the user selects an operation (by pressing a modifier key),
* return the selected operation or DROPEFFECT_NONE if the selected
* operation is not supported by the drag source.
* If the user doesn't select an operation search the set of operations
* supported by the drag source for DROPEFFECT_MOVE, then for
* DROPEFFECT_COPY, then for DROPEFFECT_LINK and return the first operation
* found.
*/
switch (mods & (MK_CONTROL | MK_SHIFT)) {
case MK_CONTROL:
ret = DROPEFFECT_COPY;
break;
case MK_CONTROL | MK_SHIFT:
ret = DROPEFFECT_LINK;
break;
case MK_SHIFT:
ret = DROPEFFECT_MOVE;
break;
default:
if (effects & DROPEFFECT_MOVE) {
ret = DROPEFFECT_MOVE;
} else if (effects & DROPEFFECT_COPY) {
ret = DROPEFFECT_COPY;
} else if (effects & DROPEFFECT_LINK) {
ret = DROPEFFECT_LINK;
}
break;
}
return ret & effects;
}
/**
* downcall to fetch data ... gets scheduled on message thread
*/
JNIEXPORT jobject JNICALL Java_sun_awt_windows_WDropTargetContextPeer_getData(JNIEnv* env, jobject self, jlong dropTarget, jlong format) {
TRY;
AwtDropTarget* pDropTarget = (AwtDropTarget*)dropTarget;
DASSERT(!::IsBadReadPtr(pDropTarget, sizeof(AwtDropTarget)));
return pDropTarget->DoGetData(format);
CATCH_BAD_ALLOC_RET(NULL);
}
/**
* downcall to signal drop done ... gets scheduled on message thread
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WDropTargetContextPeer_dropDone(JNIEnv* env, jobject self,
jlong dropTarget, jboolean success, jint actions) {
TRY_NO_HANG;
AwtDropTarget* pDropTarget = (AwtDropTarget*)dropTarget;
DASSERT(!::IsBadReadPtr(pDropTarget, sizeof(AwtDropTarget)));
pDropTarget->DoDropDone(success, actions);
CATCH_BAD_ALLOC;
}
/**
* downcall to free up storage medium for FileStream
*/
JNIEXPORT void JNICALL Java_sun_awt_windows_WDropTargetContextPeerFileStream_freeStgMedium(JNIEnv* env, jobject self, jlong stgmedium) {
TRY;
::ReleaseStgMedium((STGMEDIUM*)stgmedium);
free((void*)stgmedium);
CATCH_BAD_ALLOC;
}
/**
*
*/
JNIEXPORT jint JNICALL Java_sun_awt_windows_WDropTargetContextPeerIStream_Available(JNIEnv* env, jobject self, jlong istream) {
TRY;
return WDTCPIStreamWrapper::DoAvailable((WDTCPIStreamWrapper*)istream);
CATCH_BAD_ALLOC_RET(0);
}
/**
*
*/
JNIEXPORT jint JNICALL Java_sun_awt_windows_WDropTargetContextPeerIStream_Read(JNIEnv* env, jobject self, jlong istream) {
TRY;
return WDTCPIStreamWrapper::DoRead((WDTCPIStreamWrapper*)istream);
CATCH_BAD_ALLOC_RET(0);
}
/**
*
*/
JNIEXPORT jint JNICALL Java_sun_awt_windows_WDropTargetContextPeerIStream_ReadBytes(JNIEnv* env, jobject self, jlong istream, jbyteArray buf, jint off, jint len) {
TRY;
return WDTCPIStreamWrapper::DoReadBytes((WDTCPIStreamWrapper*)istream, buf, off, len);
CATCH_BAD_ALLOC_RET(0);
}
/**
*
*/
JNIEXPORT void JNICALL Java_sun_awt_windows_WDropTargetContextPeerIStream_Close(JNIEnv* env, jobject self, jlong istream) {
TRY_NO_VERIFY;
WDTCPIStreamWrapper::DoClose((WDTCPIStreamWrapper*)istream);
CATCH_BAD_ALLOC;
}
} /* extern "C" */