From 013de9b18d2002a9f7d5daef2f87626e890a2286 Mon Sep 17 00:00:00 2001 From: Lyor Goldstein Date: Wed, 22 Apr 2015 10:56:42 +0300 Subject: [PATCH 1/4] Added some Wincon.h related functions and definitions --- .../com/sun/jna/platform/win32/Kernel32.java | 5 +- .../com/sun/jna/platform/win32/Wincon.java | 224 ++++++++++++++++++ 2 files changed, 227 insertions(+), 2 deletions(-) create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/Wincon.java diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java b/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java index 46bb1486ed..369785bb9b 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java @@ -23,9 +23,10 @@ /** * Interface definitions for kernel32.dll. Includes additional - * alternate mappings from {@link WinNT} which make use of NIO buffers. + * alternate mappings from {@link WinNT} which make use of NIO buffers, + * {@link Wincon} for console API. */ -public interface Kernel32 extends WinNT { +public interface Kernel32 extends WinNT, Wincon { /** The instance. */ Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Wincon.java b/contrib/platform/src/com/sun/jna/platform/win32/Wincon.java new file mode 100644 index 0000000000..9eebb0dce9 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/Wincon.java @@ -0,0 +1,224 @@ +/* Copyright (c) 2007 Timothy Wall, All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + */ +package com.sun.jna.platform.win32; + +import com.sun.jna.platform.win32.WinDef.HWND; +import com.sun.jna.platform.win32.WinNT.HANDLE; +import com.sun.jna.ptr.IntByReference; + +/** + * Ported from Wincon.h. + * @author lgoldstein + */ +public interface Wincon { + /** + * Allocates a new console for the calling process. + * @return {@code true} if successful - if {@code false} then use + * {@code GetLastError()} to get extended error information + * @see AllocConsole + * documentation + */ + boolean AllocConsole(); + + /** + * Detaches the calling process from its console + * @return {@code true} if successful - if {@code false} then use + * {@code GetLastError()} to get extended error information + * @see FreeConsole + * documentation + */ + boolean FreeConsole(); + + int ATTACH_PARENT_PROCESS=(-1); + /** + * Attaches the calling process to the console of the specified process + * @param dwProcessId The identifier of the process whose console is to + * be used. Can be either the process ID or the special {@link #ATTACH_PARENT_PROCESS} + * value to indicate the console of the parent of the current process. + * @return {@code true} if successful - if {@code false} then use + * {@code GetLastError()} to get extended error information + * @see AttachConsole + * documentation + */ + boolean AttachConsole(int dwProcessId); + + /** + * Flushes the console input buffer. All input records currently in the input + * buffer are discarded. + * @param hConsoleInput A handle to the console input buffer. The handle must + * have the GENERIC_WRITE access right. + * @return {@code true} if successful - if {@code false} then use + * {@code GetLastError()} to get extended error information + * @see FlushConsoleInputBuffer + * documentation + */ + boolean FlushConsoleInputBuffer(HANDLE hConsoleInput); + + /* Events to be sent by GenerateConsoleCtrlEvent */ + int CTRL_C_EVENT=0; + int CTRL_BREAK_EVENT=1; + + /** + * Sends a specified signal to a console process group that shares the console + * associated with the calling process. + * @param dwCtrlEvent The type of signal to be generated. + * @param dwProcessGroupId The identifier of the process group to receive the signal + * @return {@code true} if successful - if {@code false} then use + * {@code GetLastError()} to get extended error information + * @see GenerateConsoleCtrlEvent + * documentation + */ + boolean GenerateConsoleCtrlEvent(int dwCtrlEvent, int dwProcessGroupId); + + /** + * @return Code that identifies the code page + * @see Code page identifiers + */ + int GetConsoleCP(); + + /** + * @param wCodePageID The identifier of the code page to be set + * @return {@code true} if successful - if {@code false} then use + * {@code GetLastError()} to get extended error information + * @see SetConsoleCP + * documentation + */ + boolean SetConsoleCP(int wCodePageID); + + /** + * @return Retrieves the output code page used by the console associated with the calling process. + * @see Code page identifiers + */ + int GetConsoleOutputCP(); + + /** + * @param wCodePageID The output code page used by the console associated with the calling process. + * @return {@code true} if successful - if {@code false} then use + * {@code GetLastError()} to get extended error information + * @see SetConsoleOutputCP + * documentation + */ + boolean SetConsoleOutputCP(int wCodePageID); + + /** + * @return The window handle used by the console associated with the calling process + */ + HWND GetConsoleWindow(); + + /** + * @param hConsoleInput A handle to the console input buffer. The handle must + * have the GENERIC_READ access right + * @param lpcNumberOfEvents A pointer to a variable that receives the number + * of unread input records in the console's input buffer + * @return {@code true} if successful - if {@code false} then use + * {@code GetLastError()} to get extended error information + * @see GetNumberOfConsoleInputEvents + * documentation + */ + boolean GetNumberOfConsoleInputEvents(HANDLE hConsoleInput, IntByReference lpcNumberOfEvents); + + /** + * @param lpNumberOfMouseButtons A pointer to a variable that receives the number + * of mouse buttons + * @return {@code true} if successful - if {@code false} then use + * {@code GetLastError()} to get extended error information + * @see GetNumberOfConsoleMouseButtons + * documentation + */ + boolean GetNumberOfConsoleMouseButtons(IntByReference lpNumberOfMouseButtons); + + /* The values to use for Get/SetStdHandle */ + int STD_INPUT_HANDLE=(-10); + int STD_OUTPUT_HANDLE=(-11); + int STD_ERROR_HANDLE=(-12); + + /** + * @param nStdHandle The standard device identifier + * @return A handle to the specified standard device (standard input, output, or error) + */ + HANDLE GetStdHandle(int nStdHandle); + + /** + * @param nStdHandle The standard device identifier + * @param hHandle The handle for the standard device + * @return {@code true} if successful - if {@code false} then use + * {@code GetLastError()} to get extended error information + * @see SetStdHandle + * documentation + */ + boolean SetStdHandle(int nStdHandle, HANDLE hHandle); + + /* console mode values */ + int CONSOLE_FULLSCREEN=1; + int CONSOLE_FULLSCREEN_HARDWARE=2; + + /** + * Retrieves the display mode of the current console + * @param lpModeFlags The display mode of the console + * @return {@code true} if successful - if {@code false} then use + * {@code GetLastError()} to get extended error information + * @see GetConsoleDisplayMode + * documentation + */ + boolean GetConsoleDisplayMode(IntByReference lpModeFlags); + + /* console modes used by Get/SetConsoleMode */ + int ENABLE_PROCESSED_INPUT=0x0001; + int ENABLE_LINE_INPUT=0x0002; + int ENABLE_ECHO_INPUT=0x0004; + int ENABLE_WINDOW_INPUT=0x0008; + int ENABLE_MOUSE_INPUT=0x0010; + int ENABLE_INSERT_MODE=0x0020; + int ENABLE_QUICK_EDIT_MODE=0x0040; + int ENABLE_EXTENDED_FLAGS=0x0080; + + /* If the hConsoleHandle parameter is a screen buffer handle, the mode + * can be one or more of the following values + */ + int ENABLE_PROCESSED_OUTPUT=0x0001; + int ENABLE_WRAP_AT_EOL_OUTPUT=0x0002; + + /** + * @param hConsoleHandle A handle to the console input buffer or the console + * screen buffer. The handle must have the GENERIC_READ access right + * @param lpMode A pointer to a variable that receives the current mode of + * the specified buffer + * @return {@code true} if successful - if {@code false} then use + * {@code GetLastError()} to get extended error information + * @see GetConsoleMode + * documentation + */ + boolean GetConsoleMode(HANDLE hConsoleHandle, IntByReference lpMode); + + /** + * @param hConsoleHandle A handle to the console input buffer or a + * console screen buffer. The handle must have the GENERIC_READ access right + * @param dwMode The input or output mode mask to be set + * @return {@code true} if successful - if {@code false} then use + * {@code GetLastError()} to get extended error information + * @see SetConsoleMode + * documentation + */ + boolean SetConsoleMode(HANDLE hConsoleHandle, int dwMode); + + int MAX_CONSOLE_TITLE_LENGTH=64 * 1024; + /** + * @param lpConsoleTitle The string to be displayed in the title bar of the console window. + * The total size must be less than {@link #MAX_CONSOLE_TITLE_LENGTH}. + * @return {@code true} if successful - if {@code false} then use + * {@code GetLastError()} to get extended error information + * @see SetConsoleTitle + * documentation + */ + boolean SetConsoleTitle(String lpConsoleTitle); +} From 8bfd3850fcf67a5814be569b924b345a0ccb9411 Mon Sep 17 00:00:00 2001 From: Lyor Goldstein Date: Sun, 26 Apr 2015 09:04:35 +0300 Subject: [PATCH 2/4] Added WinconTest --- .../com/sun/jna/platform/win32/Wincon.java | 33 ++++ .../sun/jna/platform/win32/WinconTest.java | 151 ++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 contrib/platform/test/com/sun/jna/platform/win32/WinconTest.java diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Wincon.java b/contrib/platform/src/com/sun/jna/platform/win32/Wincon.java index 9eebb0dce9..a21db29ab2 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/Wincon.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Wincon.java @@ -12,6 +12,7 @@ */ package com.sun.jna.platform.win32; +import com.sun.jna.Native; import com.sun.jna.platform.win32.WinDef.HWND; import com.sun.jna.platform.win32.WinNT.HANDLE; import com.sun.jna.ptr.IntByReference; @@ -212,6 +213,38 @@ public interface Wincon { boolean SetConsoleMode(HANDLE hConsoleHandle, int dwMode); int MAX_CONSOLE_TITLE_LENGTH=64 * 1024; + + /** + * @param lpConsoleTitle A pointer to a buffer that receives a null-terminated + * string containing the title. If the buffer is too small to store the title, + * the function stores as many characters of the title as will fit in the buffer, + * ending with a null terminator. Note: use {@link Native#toString(char[])} + * to convert it to a {@link String} value + * @param nSize The size of the buffer pointed to by the lpConsoleTitle parameter, + * in characters. + * @return If the function succeeds, the return value is the length of the console + * window's title, in characters. If the function fails, the return value is zero + * and {@code GetLastError} returns the error code. + * @see GetConsoleTitle + * documentation + */ + int GetConsoleTitle(char[] lpConsoleTitle, int nSize); + + /** + * @param lpConsoleTitle A pointer to a buffer that receives a null-terminated + * string containing the original title. Note: use {@link Native#toString(char[])} + * to convert it to a {@link String} value + * @param nSize The size of the lpConsoleTitle buffer, in characters + * @return If the function succeeds, the return value is the length of the + * string copied to the buffer, in characters. If the buffer is not large enough + * to store the title, the return value is zero and {@code GetLastError} returns + * {@code ERROR_SUCCESS}. If the function fails, the return value is zero + * and {@code GetLastError} returns the error code. + * @see GetConsoleOriginalTitle + * documentation + */ + int GetConsoleOriginalTitle(char[] lpConsoleTitle, int nSize); + /** * @param lpConsoleTitle The string to be displayed in the title bar of the console window. * The total size must be less than {@link #MAX_CONSOLE_TITLE_LENGTH}. diff --git a/contrib/platform/test/com/sun/jna/platform/win32/WinconTest.java b/contrib/platform/test/com/sun/jna/platform/win32/WinconTest.java new file mode 100644 index 0000000000..d3e8a19008 --- /dev/null +++ b/contrib/platform/test/com/sun/jna/platform/win32/WinconTest.java @@ -0,0 +1,151 @@ +/* Copyright (c) 2007 Timothy Wall, All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + */ +package com.sun.jna.platform.win32; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.WinDef.HWND; +import com.sun.jna.platform.win32.WinNT.HANDLE; +import com.sun.jna.ptr.IntByReference; + +/** + * @author lgoldstein + */ +public class WinconTest extends Assert { + private static final Wincon INSTANCE=Kernel32.INSTANCE; + + @Test + public void testGetConsoleDisplayMode() { + IntByReference curMode=new IntByReference(); + assertCallSucceeded("Initial display mode value retrieval", INSTANCE.GetConsoleDisplayMode(curMode)); + System.out.println("GetConsoleDisplayMode: " + curMode.getValue()); + } + + @Test + public void testConsoleCP() { + int curCP=INSTANCE.GetConsoleCP(); + System.out.println("Console CP=" + curCP); + // NOTE: we use the same code page value just in case the "SetConsoleCP" call fails + assertCallSucceeded("Restore CP=" + curCP, INSTANCE.SetConsoleCP(curCP)); + } + + @Test + public void testConsoleOutputCP() { + int curCP=INSTANCE.GetConsoleOutputCP(); + System.out.println("Console output CP=" + curCP); + // NOTE: we use the same code page value just in case the "SetConsoleOutputCP" call fails + assertCallSucceeded("Restore CP=" + curCP, INSTANCE.SetConsoleOutputCP(curCP)); + } + + @Test + public void testGetConsoleWindow() { + HWND hwnd=INSTANCE.GetConsoleWindow(); + // don't really care what the handle value is - just ensure that API can be called + System.out.println("Console window=" + hwnd); + } + + @Test + public void testGetNumberOfConsoleMouseButtons() { + IntByReference numButtons=new IntByReference(0); + assertCallSucceeded("Initial display mode value retrieval", INSTANCE.GetNumberOfConsoleMouseButtons(numButtons)); + System.out.println("GetNumberOfConsoleMouseButtons: " + numButtons.getValue()); + } + + @Test + public void testGetStdHandle() { + for (int nHandle : new int[] { Wincon.STD_INPUT_HANDLE, Wincon.STD_OUTPUT_HANDLE, Wincon.STD_ERROR_HANDLE }) { + HANDLE hndl=INSTANCE.GetStdHandle(nHandle); + assertNotEquals("Bad handle value for std handle=" + nHandle, WinBase.INVALID_HANDLE_VALUE, hndl); + // don't really care what the handle value is - just ensure that API can be called + System.out.println("GetStdHandle(" + nHandle + "): " + hndl); + + /* + * According to the API documentation: + * + * If an application does not have associated standard handles, + * such as a service running on an interactive desktop, and has + * not redirected them, the return value is NULL. + */ + Pointer ptr=hndl.getPointer(); + if (ptr == Pointer.NULL) { + System.out.println("NULL standard handle for type=" + nHandle); + } else { + assertCallSucceeded("SetStdHandle(" + nHandle + ")", INSTANCE.SetStdHandle(nHandle, hndl)); + } + } + } + + @Test + @Ignore("For some reason we get hr=6 - ERROR_INVALID_HANDLE - even though the documentation stipulates that GetStdHandle can be used") + public void testGetConsoleMode() { + for (int nHandle : new int[] { Wincon.STD_INPUT_HANDLE, Wincon.STD_OUTPUT_HANDLE, Wincon.STD_ERROR_HANDLE }) { + HANDLE hndl=INSTANCE.GetStdHandle(nHandle); + Pointer ptr=hndl.getPointer(); + if (ptr == Pointer.NULL) { + System.out.println("NULL standard handle for type=" + nHandle); + continue; // can happen for interactive desktop application + } + + IntByReference lpMode=new IntByReference(0); + assertCallSucceeded("GetConsoleMode(" + nHandle + ")", INSTANCE.GetConsoleMode(hndl, lpMode)); + + int dwMode=lpMode.getValue(); + // don't really care what the mode is just want to make sure API can be called + assertCallSucceeded("SetConsoleMode(" + nHandle + "," + dwMode + ")", INSTANCE.SetConsoleMode(hndl, dwMode)); + } + } + + @Test + public void testGetConsoleTitle() { + char[] lpConsoleTitle=new char[WinNT.MAX_PATH]; + int len=INSTANCE.GetConsoleTitle(lpConsoleTitle, lpConsoleTitle.length); + assertCallSucceeded("GetConsoleTitle", (len > 0)); + + String title=Native.toString(lpConsoleTitle); + System.out.println("Console title(len=" + len + "): " + title); + assertCallSucceeded("SetConsoleTitle", INSTANCE.SetConsoleTitle(title)); + } + + @Test + public void testGetConsoleOriginalTitle() { + char[] lpConsoleTitle=new char[WinNT.MAX_PATH]; + int len=INSTANCE.GetConsoleOriginalTitle(lpConsoleTitle, lpConsoleTitle.length); + if (len <= 0) { + int hr=Kernel32.INSTANCE.GetLastError(); + if (hr == 0) { // don't fail the test - we just want to see if the API can be called + System.err.println("Buffer not large enough to hold the title"); + } else { + fail("Call failed: hr=0x" + Integer.toHexString(hr)); + } + } else { + System.out.println("Console original title (len=" + len + "): " + Native.toString(lpConsoleTitle)); + } + } + + private static void assertCallSucceeded(String message, boolean result) { + if (result) { + return; + } + + int hr=Kernel32.INSTANCE.GetLastError(); + if (hr == 0) { + fail(message + " failed with unknown reason code"); + } else { + fail(message + " failed: hr=0x" + Integer.toHexString(hr)); + } + } +} From 133b58a52756942be7db1e955741b08f5be3c372 Mon Sep 17 00:00:00 2001 From: Lyor Goldstein Date: Sun, 26 Apr 2015 09:06:20 +0300 Subject: [PATCH 3/4] Updated Changes.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index c17dc149c4..e6846fb64b 100755 --- a/CHANGES.md +++ b/CHANGES.md @@ -41,6 +41,7 @@ Features * [#421](https://github.com/twall/jna/pull/421): Added `XGrabKeyboard` and `XUngrabKeyboard` to `X11` interface. * [#422](https://github.com/twall/jna/pull/422): Update libffi to v3.2.1. * [#425](https://github.com/twall/jna/pull/425): Add support for PPCLE [@tdaitx](https://github.com/tdaix). +* [#428](https://github.com/twall/jna/pull/428): Added some Wincon.h related functions and definitions Bug Fixes --------- From 5de126f772be8349752e46a4027780f633cfc5a3 Mon Sep 17 00:00:00 2001 From: Lyor Goldstein Date: Sun, 26 Apr 2015 16:08:26 +0300 Subject: [PATCH 4/4] Removed printing to stdout in WinconTest --- .../com/sun/jna/platform/win32/WinconTest.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/contrib/platform/test/com/sun/jna/platform/win32/WinconTest.java b/contrib/platform/test/com/sun/jna/platform/win32/WinconTest.java index d3e8a19008..3cdc473b17 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/WinconTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/WinconTest.java @@ -32,13 +32,11 @@ public class WinconTest extends Assert { public void testGetConsoleDisplayMode() { IntByReference curMode=new IntByReference(); assertCallSucceeded("Initial display mode value retrieval", INSTANCE.GetConsoleDisplayMode(curMode)); - System.out.println("GetConsoleDisplayMode: " + curMode.getValue()); } @Test public void testConsoleCP() { int curCP=INSTANCE.GetConsoleCP(); - System.out.println("Console CP=" + curCP); // NOTE: we use the same code page value just in case the "SetConsoleCP" call fails assertCallSucceeded("Restore CP=" + curCP, INSTANCE.SetConsoleCP(curCP)); } @@ -46,7 +44,6 @@ public void testConsoleCP() { @Test public void testConsoleOutputCP() { int curCP=INSTANCE.GetConsoleOutputCP(); - System.out.println("Console output CP=" + curCP); // NOTE: we use the same code page value just in case the "SetConsoleOutputCP" call fails assertCallSucceeded("Restore CP=" + curCP, INSTANCE.SetConsoleOutputCP(curCP)); } @@ -55,14 +52,13 @@ public void testConsoleOutputCP() { public void testGetConsoleWindow() { HWND hwnd=INSTANCE.GetConsoleWindow(); // don't really care what the handle value is - just ensure that API can be called - System.out.println("Console window=" + hwnd); + assertNotNull("No console window handle", hwnd); } @Test public void testGetNumberOfConsoleMouseButtons() { IntByReference numButtons=new IntByReference(0); assertCallSucceeded("Initial display mode value retrieval", INSTANCE.GetNumberOfConsoleMouseButtons(numButtons)); - System.out.println("GetNumberOfConsoleMouseButtons: " + numButtons.getValue()); } @Test @@ -71,7 +67,6 @@ public void testGetStdHandle() { HANDLE hndl=INSTANCE.GetStdHandle(nHandle); assertNotEquals("Bad handle value for std handle=" + nHandle, WinBase.INVALID_HANDLE_VALUE, hndl); // don't really care what the handle value is - just ensure that API can be called - System.out.println("GetStdHandle(" + nHandle + "): " + hndl); /* * According to the API documentation: @@ -82,7 +77,7 @@ public void testGetStdHandle() { */ Pointer ptr=hndl.getPointer(); if (ptr == Pointer.NULL) { - System.out.println("NULL standard handle for type=" + nHandle); + continue; } else { assertCallSucceeded("SetStdHandle(" + nHandle + ")", INSTANCE.SetStdHandle(nHandle, hndl)); } @@ -96,7 +91,6 @@ public void testGetConsoleMode() { HANDLE hndl=INSTANCE.GetStdHandle(nHandle); Pointer ptr=hndl.getPointer(); if (ptr == Pointer.NULL) { - System.out.println("NULL standard handle for type=" + nHandle); continue; // can happen for interactive desktop application } @@ -116,7 +110,6 @@ public void testGetConsoleTitle() { assertCallSucceeded("GetConsoleTitle", (len > 0)); String title=Native.toString(lpConsoleTitle); - System.out.println("Console title(len=" + len + "): " + title); assertCallSucceeded("SetConsoleTitle", INSTANCE.SetConsoleTitle(title)); } @@ -127,12 +120,10 @@ public void testGetConsoleOriginalTitle() { if (len <= 0) { int hr=Kernel32.INSTANCE.GetLastError(); if (hr == 0) { // don't fail the test - we just want to see if the API can be called - System.err.println("Buffer not large enough to hold the title"); + fail("Buffer not large enough to hold the title"); } else { fail("Call failed: hr=0x" + Integer.toHexString(hr)); } - } else { - System.out.println("Console original title (len=" + len + "): " + Native.toString(lpConsoleTitle)); } }