--- /dev/null 2014-04-18 17:39:37.000000000 +0400 +++ new/test/java/awt/dnd/Win32TYMEDSelectionTest/Makefile 2014-04-18 17:39:35.693592100 +0400 @@ -0,0 +1,5 @@ +all: child.cpp + cl -o child.exe child.cpp user32.lib ole32.lib gdi32.lib + +clean: + rm -f child.exe child.obj --- /dev/null 2014-04-18 17:39:39.000000000 +0400 +++ new/test/java/awt/dnd/Win32TYMEDSelectionTest/Win32TYMEDSelectionTest.html 2014-04-18 17:39:38.578757100 +0400 @@ -0,0 +1,21 @@ + + + + + + + +

Win32TYMEDSelectionTest
Bug ID: 4426805

+ +

This is an AUTOMATIC test, simply wait for completion

+ + + + --- /dev/null 2014-04-18 17:39:41.000000000 +0400 +++ new/test/java/awt/dnd/Win32TYMEDSelectionTest/Win32TYMEDSelectionTest.java 2014-04-18 17:39:40.740880800 +0400 @@ -0,0 +1,193 @@ +/* + test + @bug 4426805 4427837 + @summary tests that drag source provides data in the requested tymed + in java-to-native drag-and-drop operation on Win32 + @author das@sparc.spb.su area=dnd + @run applet Win32TYMEDSelectionTest.html +*/ + +/** + * Win32TYMEDSelectionTest.java + * + * summary: tests that drag source provides data in the requested tymed + * in java-to-native drag-and-drop operation on Win32 + */ + +import java.applet.Applet; +import java.awt.*; +import java.awt.datatransfer.*; +import java.awt.dnd.*; +import java.awt.event.*; +import java.io.*; + + +public class Win32TYMEDSelectionTest extends Applet implements Runnable { + + /* + * NOTE: These constants are duplicated in child.cpp. + * Be sure to keep them is sync. + */ + public static final int CODE_NOT_RETURNED = -1; + public static final int CODE_OK = 0; + public static final int CODE_INVALID_TYMED_FAILURE = 1; + public static final int CODE_INVALID_DATA_FAILURE = 2; + public static final String TEST_TEXT = "TEST TEXT"; + public static final int X = 300; + public static final int Y = 300; + public static final int WIDTH = 100; + public static final int HEIGHT = 100; + + public static final int ACTIVATION_TIMEOUT = 2000; + + private transient int retCode = CODE_NOT_RETURNED; + + final Frame frame = new Frame(); + final Button button = new DragSourceButton(); + private Process process; + + public void run() { + try { + Thread.sleep(ACTIVATION_TIMEOUT); + + final Point sourcePoint = button.getLocationOnScreen(); + final Dimension d = button.getSize(); + sourcePoint.translate(d.width / 2, d.height / 2); + final Point targetPoint = new Point(X + WIDTH / 2, Y + HEIGHT / 2); + + final Robot robot = new Robot(); + robot.mouseMove(sourcePoint.x, sourcePoint.y); + robot.keyPress(KeyEvent.VK_CONTROL); + robot.mousePress(InputEvent.BUTTON1_MASK); + for (;!sourcePoint.equals(targetPoint); + sourcePoint.translate(sign(targetPoint.x - sourcePoint.x), + sign(targetPoint.y - sourcePoint.y))) { + + robot.mouseMove(sourcePoint.x, sourcePoint.y); + Thread.sleep(10); + } + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.keyRelease(KeyEvent.VK_CONTROL); + + Thread.sleep(ACTIVATION_TIMEOUT); + + if (retCode == CODE_NOT_RETURNED) { + process.destroy(); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } // run() + + public static int sign(int n) { + return n < 0 ? -1 : n == 0 ? 0 : 1; + } + + public void start() { + + if (System.getProperty("os.name").startsWith("Windows")) { + frame.setTitle("DragSource frame"); + frame.setLocation(200, 200); + frame.add(button); + frame.pack(); + frame.setVisible(true); + + String testPath = System.getProperty("test.src", "."); + + try { + Process process = Runtime.getRuntime().exec("cp " + testPath + File.separator + "child.exe ."); + process.waitFor(); + process = Runtime.getRuntime().exec("chmod 755 child.exe"); + process.waitFor(); + }catch (InterruptedException ire) { + ire.printStackTrace(); + } catch (IOException ie) { + ie.printStackTrace(); + } + + String command = "./child.exe"; + try { + process = Runtime.getRuntime().exec(command); + new Thread(this).start(); + + retCode = process.waitFor(); + + InputStream errorStream = process.getErrorStream(); + int count = errorStream.available(); + if (count > 0) { + byte[] b = new byte[count]; + errorStream.read(b); + System.err.println("========= Child VM System.err ========"); + System.err.print(new String(b)); + System.err.println("======================================"); + } + + } catch (Exception e) { + e.printStackTrace(); + } + System.err.println("Child VM: returned: " + retCode); + switch (retCode) { + case CODE_NOT_RETURNED: + System.err.println("Child VM: failed to start"); + break; + case CODE_OK: + System.err.println("Child VM: normal termination"); + break; + default: + System.err.println("Child VM: other failure"); + break; + case CODE_INVALID_TYMED_FAILURE: + System.err.println("Child VM: invalid tymed detected"); + throw new RuntimeException("The test failed."); + case CODE_INVALID_DATA_FAILURE: + System.err.println("Child VM: invalid transfer data detected"); + throw new RuntimeException("The test failed."); + } + } + } // start() +} // class Win32TYMEDSelectionTest + +class DragSourceButton extends Button implements Serializable, + DragGestureListener, + Transferable { + static final DataFlavor[] flavors = + new DataFlavor[] { DataFlavor.stringFlavor, DataFlavor.imageFlavor }; + + public DragSourceButton() { + this("DragSourceButton"); + } + + public DragSourceButton(String str) { + super(str); + + DragSource ds = DragSource.getDefaultDragSource(); + ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY, + this); + } + + public void dragGestureRecognized(DragGestureEvent dge) { + dge.startDrag(null, this, + new DragSourceAdapter() {}); + } + + public DataFlavor[] getTransferDataFlavors() { + return flavors; + } + + public boolean isDataFlavorSupported(DataFlavor flavor) { + return DataFlavor.stringFlavor.equals(flavor) || + DataFlavor.imageFlavor.equals(flavor); + } + + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException, IOException { + if (DataFlavor.stringFlavor.equals(flavor)) { + return Win32TYMEDSelectionTest.TEST_TEXT; + } else if (DataFlavor.imageFlavor.equals(flavor)) { + return createImage(10, 10); + } else { + throw new UnsupportedFlavorException(flavor); + } + } +} + --- /dev/null 2014-04-18 17:39:43.000000000 +0400 +++ new/test/java/awt/dnd/Win32TYMEDSelectionTest/child.cpp 2014-04-18 17:39:42.898004200 +0400 @@ -0,0 +1,315 @@ +#define STRICT +#include +#include +#include + +/* + * NOTE: These constants are duplicated in Win32TYMEDSelectionTest.java. + * Be sure to keep them is sync. + */ +static const int CODE_OK = 0; +static const int CODE_INVALID_TYMED_FAILURE = 1; +static const int CODE_INVALID_DATA_FAILURE = 2; +static const int CODE_OTHER_FAILURE = 3; +static const char* TEST_TEXT = "TEST TEXT"; +static const int X = 300; +static const int Y = 300; +static const int WIDTH = 100; +static const int HEIGHT = 100; + +static const char szClassName[] = "test window"; + +class TestDropTarget : virtual public IDropTarget { + public: + TestDropTarget(); + virtual ~TestDropTarget(); + + virtual HRESULT __stdcall QueryInterface(REFIID riid, + void __RPC_FAR*__RPC_FAR *ppvObject); + virtual ULONG __stdcall AddRef(void); + virtual ULONG __stdcall Release(void); + virtual HRESULT __stdcall DragEnter(IDataObject __RPC_FAR *pDataObject, + DWORD grfKeyState, POINTL pt, + DWORD __RPC_FAR *pdwEffect); + virtual HRESULT __stdcall DragOver(DWORD grfKeyState, POINTL pt, + DWORD __RPC_FAR *pdwEffect); + virtual HRESULT __stdcall DragLeave(void); + virtual HRESULT __stdcall Drop(IDataObject __RPC_FAR *pDataObject, + DWORD grfKeyState, POINTL pt, + DWORD __RPC_FAR *pdwEffect); + virtual int CheckTransferTymed(IDataObject __RPC_FAR *pDataObj, + DWORD tymed); + virtual void DumpTestResult(DWORD tymed, int nTestResult); + private: + unsigned int m_refs; +}; + +TestDropTarget::TestDropTarget() { + m_refs = 0U; + AddRef(); +} + +TestDropTarget::~TestDropTarget() {} + +HRESULT __stdcall +TestDropTarget::QueryInterface(REFIID riid, + void __RPC_FAR *__RPC_FAR *ppvObject) { + if (riid == IID_IUnknown) { + *ppvObject = (void __RPC_FAR *__RPC_FAR)(IUnknown*)this; + AddRef(); + return S_OK; + } else if (riid == IID_IDropTarget) { + *ppvObject = (void __RPC_FAR *__RPC_FAR)(IDropTarget*)this; + AddRef(); + return S_OK; + } else { + *ppvObject = (void __RPC_FAR *__RPC_FAR)NULL; + return E_NOINTERFACE; + } +} + +ULONG __stdcall +TestDropTarget::AddRef() { + return (ULONG)++m_refs; +} + +ULONG __stdcall +TestDropTarget::Release() { + int refs; + if ((refs = --m_refs) == 0) delete this; + return (ULONG)refs; +} + +HRESULT __stdcall +TestDropTarget::DragEnter(IDataObject __RPC_FAR *pDataObj, DWORD grfKeyState, + POINTL pt, DWORD __RPC_FAR *pdwEffect) { + *pdwEffect = DROPEFFECT_COPY; + return S_OK; +} + +HRESULT __stdcall +TestDropTarget::DragOver(DWORD grfKeyState, POINTL pt, + DWORD __RPC_FAR *pdwEffect) { + *pdwEffect = DROPEFFECT_COPY; + return S_OK; +} + +HRESULT __stdcall +TestDropTarget::DragLeave() { + return S_OK; +} + +HRESULT __stdcall +TestDropTarget::Drop(IDataObject __RPC_FAR *pDataObj, DWORD grfKeyState, + POINTL pt, DWORD __RPC_FAR *pdwEffect) { + int nExitCode = CODE_OTHER_FAILURE; + HRESULT res = S_OK; + + *pdwEffect = DROPEFFECT_NONE; + + nExitCode = CheckTransferTymed(pDataObj, TYMED_HGLOBAL); + if (nExitCode == CODE_OK) { + nExitCode = CheckTransferTymed(pDataObj, TYMED_ISTREAM); + } + if (nExitCode == CODE_OK) { + nExitCode = CheckTransferTymed(pDataObj, TYMED_ENHMF); + } + + if (nExitCode == CODE_OK) { + *pdwEffect = DROPEFFECT_COPY; + } + ::PostQuitMessage(nExitCode); + return res; +} + +int +TestDropTarget::CheckTransferTymed(IDataObject __RPC_FAR *pDataObj, + DWORD tymed) { + int nExitCode = CODE_OTHER_FAILURE; + FORMATETC format; + + switch (tymed) { + case TYMED_HGLOBAL: + case TYMED_ISTREAM: + format.cfFormat = CF_TEXT; + break; + case TYMED_ENHMF: + format.cfFormat = CF_ENHMETAFILE; + break; + } + format.ptd = NULL; + format.lindex = -1; + format.dwAspect = DVASPECT_CONTENT; + format.tymed = tymed; + + STGMEDIUM stgmedium; + + HRESULT res = pDataObj->GetData(&format, &stgmedium); + if (res == S_OK) { + if (stgmedium.tymed == tymed) { + nExitCode = CODE_INVALID_DATA_FAILURE; + + switch (tymed) { + case TYMED_HGLOBAL: { + DWORD size = ::GlobalSize(stgmedium.hGlobal); + if (size != 0) { + LPVOID data = ::GlobalLock(stgmedium.hGlobal); + if (strcmp((const char*)data, TEST_TEXT) == 0) { + nExitCode = CODE_OK; + } + } + break; + } + case TYMED_ISTREAM: { + IStream* pstm = stgmedium.pstm; + if (pstm != NULL) { + STATSTG statstg; + if (pstm->Stat(&statstg, STATFLAG_NONAME) == S_OK) { + if (statstg.cbSize.LowPart >= strlen(TEST_TEXT) && + statstg.cbSize.HighPart == 0) { + ULONG size = (ULONG)statstg.cbSize.QuadPart; + ULONG act = 0; + LPVOID buf = calloc(1, size); + if (buf != NULL) { + if (pstm->Read((void*)buf,size,&act) == S_OK && + strcmp((const char*)buf, TEST_TEXT) == 0) { + + nExitCode = CODE_OK; + } + free(buf); + } + } + } + } + break; + } + case TYMED_ENHMF: { + HENHMETAFILE hemf = stgmedium.hEnhMetaFile; + UINT size = ::GetEnhMetaFileHeader(hemf, 0, NULL); + BOOL headerValid = FALSE; + if (size != 0) { + LPENHMETAHEADER lpemh = (LPENHMETAHEADER)calloc(1, size); + if (lpemh != NULL) { + if (::GetEnhMetaFileHeader(hemf, size, lpemh) == size) { + headerValid = TRUE; + } + free(lpemh); + } + } + if (headerValid == TRUE) { + UINT size = ::GetEnhMetaFileBits(hemf, 0, NULL); + if (size != 0) { + LPBYTE lpbits = (LPBYTE)calloc(1, size); + if (lpbits != NULL) { + if (::GetEnhMetaFileBits(hemf, size, lpbits) == size) { + nExitCode = CODE_OK; + } + free(lpbits); + } + } + } + break; + } + } + } else { + nExitCode = CODE_INVALID_TYMED_FAILURE; + } + } + + DumpTestResult(tymed, nExitCode); + ::ReleaseStgMedium(&stgmedium); + return nExitCode; +} + +void +TestDropTarget::DumpTestResult(DWORD tymed, int nTestResult) { + switch (tymed) { + case TYMED_HGLOBAL: + fprintf(stderr,"Test transfer for TYMED_HGLOBAL: "); + break; + case TYMED_ISTREAM: + fprintf(stderr,"Test transfer for TYMED_ISTREAM: "); + break; + case TYMED_ENHMF: + fprintf(stderr,"Test transfer for TYMED_ENHMF: "); + break; + default: + fprintf(stderr,"Test transfer for unknown TYMED %d: ", tymed); + break; + } + + switch (nTestResult) { + case CODE_OK: + fprintf(stderr,"PASSED"); + break; + case CODE_INVALID_TYMED_FAILURE: + fprintf(stderr,"FAILED: invalid TYMED detected"); + break; + case CODE_INVALID_DATA_FAILURE: + fprintf(stderr,"FAILED: invalid transfer data detected"); + break; + case CODE_OTHER_FAILURE: + fprintf(stderr,"FAILED: other failure detected"); + break; + default: + fprintf(stderr,"FAILED: unknown test result %d", nTestResult); + break; + } + + fprintf(stderr,"\n"); +} + +LRESULT CALLBACK +WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam ) { + switch (iMessage) { + case WM_DESTROY: + ::RevokeDragDrop(hWnd); + ::OleUninitialize(); + ::PostQuitMessage(0); + break; + default: + return ::DefWindowProc( hWnd, iMessage, wParam, lParam ); + } + return 0; +} + +int +main(int argc, char* argv[]) { + + HMODULE hInstance = ::GetModuleHandle(NULL); + WNDCLASS wndclass; + wndclass.style = CS_OWNDC; + wndclass.lpfnWndProc = WndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInstance; + wndclass.hIcon = NULL; + wndclass.hCursor = NULL; + wndclass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = szClassName; + if (::RegisterClass(&wndclass) == 0) { + exit( FALSE ); + } + HWND hMainWnd = ::CreateWindowEx(WS_EX_CLIENTEDGE, szClassName, szClassName, + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, + X, Y, WIDTH, HEIGHT, + NULL, NULL, hInstance, NULL); + if (hMainWnd == NULL) { + exit(FALSE); + } + ::ShowWindow(hMainWnd, SW_SHOWNORMAL); + ::UpdateWindow(hMainWnd); + ::OleInitialize(NULL); + HRESULT res = ::RegisterDragDrop(hMainWnd, new TestDropTarget()); + MSG msg; + + while (::GetMessage(&msg, NULL, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::OleUninitialize(); + ::UnregisterClass(szClassName, hInstance); + return msg.wParam; +}