I'm trying to use JNA to query the effective permissions for a file in Windows. Eventually, I plan on using the GetEffectiveRightsFromAcl function, but to do so, I need to provide a pointer to a populated TRUSTEE structure. The JNA Platform (platform.jar) doesn't appear define this struct, so I'm trying to define it myself instead. Here's what I have so far:
public static class TRUSTEE extends Structure {
public TRUSTEE() {
super();
}
public TRUSTEE(Pointer p) {
super(p);
read();
}
public Pointer pMultipleTrustee;
public int MultipleTrusteeOperation;
public int TrusteeForm;
public int TrusteeType;
public Pointer ptstrName;
}
I'm trying to populate the structure like this:
private TRUSTEE createTrusteeForCurrentUser() {
TRUSTEE result = new TRUSTEE();
result.TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_NAME;
result.TrusteeType = TRUSTEE_TYPE.TRUSTEE_IS_USER;
String strName = "CURRENT_USER";
// How can I set result.ptstrName using strName?
}
This Google Groups thread recommends using String fields in structures when a char * is called for. However, I don't think this is appropriate in my situation, considering the ptstrName field is allowed to point to different types of things, depending on the value of TrusteeForm. So, I think I somehow need to convert from String to Pointer instead. I found the NativeString class in JNA, which would work, except it's a package-private class.
What's the recommended way to convert a Java String to a native format and obtain a Pointer to it? Am I even using the right data type for the TRUSTEE struct? I'm somewhat new to JNA, so please excuse me if I'm missing something obvious.
Update
I found a solution to my problem, but if anyone has a better solution I'd still like to hear it.
Assuming you want char * on the native side (you may need more memory allocated if the string contains non-ascii characters),
String myString = "CURRENT_USER";
Pointer m = new Memory(myString.length() + 1); // WARNING: assumes ascii-only string
m.setString(0, myString);
You can then use m wherever you need to reference the "native" string.
For wide strings (wchar_t *),
String myString = "CURRENT_USER";
Pointer m = new Memory(Native.WCHAR_SIZE * (myString.length() + 1));
m.setWideString(0, myString);
I solved the problem by copying the source code for package-private NativeString class and creating a public copy in my project. I had to make one minor alteration due to the use of a package-private method in the constructor.
Update: As #fragorl notes in the comments, the implementation of NativeString shown below is by now quite out-of-date.
Usage:
private static TRUSTEE createTrusteeForCurrentUser() {
TRUSTEE result = new TRUSTEE();
result.TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_NAME;
result.TrusteeType = TRUSTEE_TYPE.TRUSTEE_IS_USER;
result.ptstrName = new NativeString("CURRENT_USER",true).getPointer();
result.write();
return result;
}
NativeString.java:
/** Provides a temporary allocation of an immutable C string
* (<code>const char*</code> or <code>const wchar_t*</code>) for use when
* converting a Java String into a native memory function argument.
*
* #author Todd Fast, todd.fast#sun.com
* #author twall#users.sf.net
*/
public class NativeString implements CharSequence, Comparable {
private Pointer pointer;
private boolean wide;
/** Create a native string (NUL-terminated array of <code>char</code>).<p>
* If the system property <code>jna.encoding</code> is set, its value will
* be used to encode the native string. If not set or if the encoding
* is unavailable, the default platform encoding will be used.
*/
public NativeString(String string) {
this(string, false);
}
/** Create a native string as a NUL-terminated array of <code>wchar_t</code>
* (if <code>wide</code> is true) or <code>char</code>.<p>
* If the system property <code>jna.encoding</code> is set, its value will
* be used to encode the native <code>char</code>string.
* If not set or if the encoding is unavailable, the default platform
* encoding will be used.
*
* #param string value to write to native memory
* #param wide whether to store the String as <code>wchar_t</code>
*/
public NativeString(String string, boolean wide) {
if (string == null) {
throw new NullPointerException("String must not be null");
}
// Allocate the memory to hold the string. Note, we have to
// make this 1 element longer in order to accommodate the terminating
// NUL (which is generated in Pointer.setString()).
this.wide = wide;
if (wide) {
int len = (string.length() + 1 ) * Native.WCHAR_SIZE;
pointer = new Memory(len);
pointer.setString(0, string, true);
}
else {
byte[] data = Native.toByteArray(string);
pointer = new Memory(data.length + 1);
pointer.write(0, data, 0, data.length);
pointer.setByte(data.length, (byte)0);
}
}
public int hashCode() {
return toString().hashCode();
}
public boolean equals(Object other) {
if (other instanceof CharSequence) {
return compareTo(other) == 0;
}
return false;
}
public String toString() {
String s = wide ? "const wchar_t*" : "const char*";
s += "(" + pointer.getString(0, wide) + ")";
return s;
}
public Pointer getPointer() {
return pointer;
}
public char charAt(int index) {
return toString().charAt(index);
}
public int length() {
return toString().length();
}
public CharSequence subSequence(int start, int end) {
return CharBuffer.wrap(toString()).subSequence(start, end);
}
public int compareTo(Object other) {
if (other == null)
return 1;
return toString().compareTo(other.toString());
}
}
try using Pointer class in http://jna.java.net/javadoc/com/sun/jna/Pointer.html.
Related
I am using JNA and writing some code to enumerate through all of the modules available in a process. I successfully obtain the snapshot handle via CreateToolhelp32Snapshot, however on my first Module32First call, I am getting error code 87 for "Invalid Parameter".
Below is the relevant code that I am using:
Code in question:
private void getModule() {
Pointer hSnapshot = this.kernel32.CreateToolhelp32Snapshot(WinAPI.TH32CS_SNAPMODULE, this.processId);
if(hSnapshot != null) {
WinAPI.MODULEENTRY32 moduleEntry32 = new WinAPI.MODULEENTRY32();
moduleEntry32.write(); // Write the struct in memory (for dwSize to be registered)
Pointer moduleEntry32Pointer = moduleEntry32.getPointer();
if(this.kernel32.Module32First(hSnapshot, moduleEntry32Pointer)) {
// irrelevant stuff here
}
}
System.out.println(this.kernel32.GetLastError()); // Prints out "87"
this.kernel32.CloseHandle(hSnapshot);
}
Kernel32 Mapper Class:
Pointer CreateToolhelp32Snapshot(int dwFlags, int th32ProcessID);
boolean Module32First(Pointer hSnapshot, Pointer lpme);
boolean Module32Next(Pointer hSnapshot, Pointer lpme);
ModuleEntry32 Structure:
public static class MODULEENTRY32 extends Structure {
public int dwSize = this.size();
public int th32ModuleID;
public int th32ProcessID;
public int GlblcntUsage;
public int ProccntUsage;
public Pointer modBaseAddr;
public int modBaseSize;
public Pointer hModule;
public String szModule;
public String szExePath;
public MODULEENTRY32() {
super();
}
public MODULEENTRY32(Pointer p) {
super(p);
}
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] {"dwSize", "th32ModuleID", "th32ProcessID", "GlblcntUsage", "ProccntUsage", "modBaseAddr", "modBaseSize", "hModule", "szModule", "szExePath"});
}
}
And finally, this is "WinAPI.TH32CS_SNAPMODULE":
public static final int TH32CS_SNAPMODULE = 0x00000008;
Note: The process I am enumerating on is already opened with OpenProcess and is valid. The processId is valid as well, and is obtained properly as well.
Any help would be appreciated.
Your mapping of a pointer as the second argument, while technically correct, requires you to do a lot more overhead with writing it. It is better to simply put the structure type as an argument. Structures are treated as .ByReference when used as function/method arguments, and handle all of the auto-read and write for you. So if you do this, you can omit your write() call:
boolean Module32First(Pointer hSnapshot, WinAPI.MODULEENTRY32 lpme);
boolean Module32Next(Pointer hSnapshot, WinAPI.MODULEENTRY32 lpme);
That said, the comment on your write call points to the root cause here: you need to set the dwSize value to the size of the structure. However, because of the order of initialization of Java Objects, the Structure does not have the information it needs to determine the size when initializing the dwSize variable, so this part is not giving you the correct size:
public int dwSize = this.size();
To solve this, just declare that variable and set the size later on in the constructor, e.g.,
public static class MODULEENTRY32 extends Structure {
public int dwSize;
// other declarations
public MODULEENTRY32() {
super();
dwSize = size();
}
}
In addition your mappings for szModule and szExePath are incorrect. You've only provided Pointers (a total of 16 bytes) in the structure's memory allocation, but these are fixed length character arrays. They should be defined:
public char[] szModule = new char[MAX_MODULE_NAME32 + 1];
public char[] szExePath = new char[MAX_PATH];
Note the char[] mapping is for the Unicode (_W) version of the mapping which is a reasonably safe assumption.
But rather than write yourself, you should use the mappings that already exists in the JNA user-contributed mappings in jna-platform. The MODULEENTRY32W type is already there (yes it uses DWORD so your version is simpler; but you can look at the code to see how they handled the size.) And the Module32FirstW and Module32NextW functions are also mapped. (The W suffix is for wide characters (Unicode) which all modern Windows systems use now.)
I have struggled a lot to make it work (a call to win32 API : SendMessage with WM_COPYDATA and COPYDATASTRUCT to hold the data) and as it works on my windows 7 computer now, I am wondering if my mapping is the good one and if there is no side effect of my solution ?
Here is my code :
/**
* For usage with WM_COPYDATA
* cf : https://msdn.microsoft.com/en-us/library/windows/desktop/ms649010(v=vs.85).aspx
*/
long SendMessage(HWND hWnd, int msg, WPARAM wParam, COPYDATASTRUCT.ByReference lParam);
int WM_COPYDATA = 0x004A;
//cf : https://msdn.microsoft.com/en-us/library/windows/desktop/ms649010(v=vs.85).aspx
class COPYDATASTRUCT extends Structure {
public static class ByReference extends COPYDATASTRUCT implements Structure.ByReference {
}
public COPYDATASTRUCT() {
super();
}
public int dwData;
public long cbData;
public Pointer lpData;
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "dwData", "cbData", "lpData" });
}
}
And the calling code with 2 examples :
User32Extension.COPYDATASTRUCT.ByReference dataStruct = new User32Extension.COPYDATASTRUCT.ByReference();
String message = "Hello ! :-) !";
Memory m = new Memory(message.length() + 1);
m.setString(0, message);
dataStruct.dwData = 10;
dataStruct.cbData = message.length() + 1;
dataStruct.lpData = m;
dataStruct.write(); // writes to native memory the structure.
result = user32.SendMessage(hwndTarget, // target hwnd.
User32Extension.WM_COPYDATA, // copy data message.
wparam, // current hwnd
dataStruct // data by reference here
);
User32Extension.COPYDATASTRUCT.ByReference myDataStruct = new User32Extension.COPYDATASTRUCT.ByReference();
User32Extension.TEST_STRUCT myStruct = new User32Extension.TEST_STRUCT();
//simple C structure here with 4 fields of C types int, char, char and long.
myStruct.iNumber = 677;
myStruct.cCode = 'E';
myStruct.cCode2 = 'T';
myStruct.lLong1 = new NativeLong(123456789L);
myStruct.write();
LOGGER.trace("myStruct (size=" + myStruct.size() + ")=" + myStruct.toString(true));
myDataStruct.dwData = 11;
myDataStruct.cbData = myStruct.size();
myDataStruct.lpData = myStruct.getPointer();
myDataStruct.write(); // writes to native memory the structure.
result = user32.SendMessage(hwndTarget, // target hwnd.
User32Extension.WM_COPYDATA, // copy data message.
wparam, // current hwnd
myDataStruct // data
);
The key thing is this code compared to everything I have found on the net, is that COPYDATASTRUCT attribute cbData is of type long.
If I set to int, it does not work (data is not correctly received in WndProc of the legacy C application). Is it correct to map a DWORD to a long java type ? Would it be better with a NativeLong ?
Another thing, that is to be noted, is the explicit call to Structure.write() for all the instantiated Structures (myStruct and myDataStruct). It is necessary in order to not have an empty memory before calling the SendMessage api.
Do you think it is normal ? Or jna should call it automatically before invoking the SendMessage ?
Thanks in advance.
This native code:
typedef struct tagCOPYDATASTRUCT {
ULONG_PTR dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
maps to this JNA Structure definition:
public class COPYDATASTRUCT extends Structure {
ULONG_PTR dwData;
DWORD cbData; // or use "int"
Pointer lpData;
}
The first and last fields will be of different size (and the structure will have different alignment/padding) depending on whether you're running 32- or 64-bit.
I'm still pretty new to Java and right now I'm trying to make a copy of Menu. I think I've done a little bit of it where I created a new Menu object with new MenuItems in it. MenuItems is another class with two string variables and a double variable, the itemName and itemDescription and the itemPrice. So I'm trying to copy the contents, the three variables of the original MenuItems into the MenuItems copy, but I don't know how. I got stuck on trying to set the clone copy's name to the original's name.
public class Menu
{
Menu()
{
}
final int maxItems = 50;
MenuItem[] food = new MenuItem[maxItems + 1];
public Object clone()
{
Menu menuClone = new Menu();
MenuItem[] foodClone = new MenuItem[maxItems + 1];
for(int i = 1; i <= maxItems + 1; i++)
{
foodClone[i] = new MenuItem();
foodClone[i] = food[i].setItemName();
}
}
This is the MenuItem class:
public class MenuItem
{
private String name;
private String descrip;
private double price;
MenuItem()
{
}
public String getItemName()
{
return name;
}
public String getItemDescrip()
{
return descrip;
}
public double getPrice()
{
return price;
}
public void setItemName(String itemName)
{
name = itemName;
}
public void setItemDescrip(String itemDescrip)
{
descrip = itemDescrip;
}
public void setPrice(double itemPrice) throws IllegalArgumentException
{
if(itemPrice >= 0.0)
price = itemPrice;
else
throw new IllegalArgumentException("Enter only positive values");
}
public String toString(){
return "Name: " + name + ", Desc: " + descrip;
}
}
You are almost there, where you have:
foodClone[i] = food[i].setItemName();
You probably want (in addition to the other variables of MenuItem)
foodClone[i].setItemName(food[i].getItemName())`
However, it's best to use the clone method or a copy constructor (well, copy constructor arguably might be best).
I do prefer using a copy constructor, such an example would be:
MenuItem(MenuItem menuItemToClone)
{
this.name = menuItemToClone.name;
this.descrip = menuItemToClone.descrip;
this.price = menuItemToClone.price;
}
Then you would just do:
foodClone[i] = new MenuItem(food[i]);
Cloning only provides a shallow copy, despite some of the previous recommendations.
A common solution to the deep copy problem is to use Java Object Serialization (JOS). The idea is simple: Write the object to an array using JOS’s ObjectOutputStream and then use ObjectInputStream to reconstitute a copy of the object. The result will be a completely distinct object, with completely distinct referenced objects. JOS takes care of all of the details: superclass fields, following object graphs, and handling repeated references to the same object within the graph. Figure 3 shows a first draft of a utility class that uses JOS for making deep copies.
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
/**
* Utility for making deep copies (vs. clone()'s shallow copies) of
* objects. Objects are first serialized and then deserialized. Error
* checking is fairly minimal in this implementation. If an object is
* encountered that cannot be serialized (or that references an object
* that cannot be serialized) an error is printed to System.err and
* null is returned. Depending on your specific application, it might
* make more sense to have copy(...) re-throw the exception.
*
* A later version of this class includes some minor optimizations.
*/
public class UnoptimizedDeepCopy {
/**
* Returns a copy of the object, or null if the object cannot
* be serialized.
*/
public static Object copy(Object orig) {
Object obj = null;
try {
// Write the object out to a byte array
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(orig);
out.flush();
out.close();
// Make an input stream from the byte array and read
// a copy of the object back in.
ObjectInputStream in = new ObjectInputStream(
new ByteArrayInputStream(bos.toByteArray()));
obj = in.readObject();
}
catch(IOException e) {
e.printStackTrace();
}
catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
return obj;
}
}
Unfortunately, this approach has some problems:
It will only work when the object being copied, as well as all of the other objects references directly or indirectly by the object, are serializable. (In other words, they must implement java.io.Serializable.) Fortunately it is often sufficient to simply declare that a given class implements java.io.Serializable and let Java’s default serialization mechanisms do their thing.
Java Object Serialization is slow, and using it to make a deep copy requires both serializing and deserializing. There are ways to speed it up (e.g., by pre-computing serial version ids and defining custom readObject() and writeObject() methods), but this will usually be the primary bottleneck.
The byte array stream implementations included in the java.io package are designed to be general enough to perform reasonable well for data of different sizes and to be safe to use in a multi-threaded environment. These characteristics, however, slow down ByteArrayOutputStream and (to a lesser extent) ByteArrayInputStream.
Source: http://javatechniques.com/blog/faster-deep-copies-of-java-objects/
I'm writing a small library.
public class MyClass {
public static String doSomethingWithString(final String s) {
new MyClass().doSomething(s);
}
public String doSomething(final String s) {
return null;
}
}
Or I can do like this.
public class MyClass {
public static String doSomethingWithString(final String s) {
return null;
}
public String doSomething(final String s) {
return doSomethingWithString(s);
}
}
Which style is preferable? Are they same?
UPDATE
Thank you for comments and answers.
Here are two classes.
public class IdEncoder {
private static String block(final long decoded) {
final StringBuilder builder = new StringBuilder(Long.toString(decoded));
builder.append(Integer.toString(
ThreadLocalRandom.current().nextInt(9) + 1)); // 1-9
builder.append(Integer.toString(
ThreadLocalRandom.current().nextInt(9) + 1)); // 1-9
builder.reverse();
return Long.toString(
Long.parseLong(builder.toString()), Character.MAX_RADIX);
}
public static String encodeLong(final long decoded) {
return block(decoded >>> 0x20) + "-" + block(decoded & 0xFFFFFFFFL);
}
public String encode(final long decoded) {
return encodeLong(decoded);
}
}
And another style.
public class IdDecoder {
public static long decodeLong(final String encoded) {
return new IdDecoder().decode(encoded);
}
public long decode(final String encoded) {
final int index = encoded.indexOf('-');
if (index == -1) {
throw new IllegalArgumentException("wrong encoded: " + encoded);
}
return (block(encoded.substring(0, index)) << 32)
| (block(encoded.substring(index + 1)));
}
private long block(final String encoded) {
final StringBuilder builder = new StringBuilder(
Long.toString(Long.parseLong(encoded, Character.MAX_RADIX)));
builder.reverse();
builder.deleteCharAt(builder.length() - 1);
builder.deleteCharAt(builder.length() - 1);
return Long.parseLong(builder.toString());
}
}
If you are just picking between these 2 options, take the second one.
The reason is the first requires you to allocate a new dummy object on the heap just to call a method. If there is truly no other difference, don't waste the time and space and just call the static method from the class.
The second is more akin to a static Utility function, which are a fine coding practice.
When writing a library, ease of use dramatically trumps general best practices. Your method should be static if it doesn't make sense for a user to instantiate something in order to access it. However often it is actually much cleaner and more powerful for a method to be part of an object, because it allows the user (as well as the library writer) to override it in child classes.
In a sense, you aren't actually asking a programming question, but a UX question. Ask yourself how your users would best benefit from accessing your code, and implement it that way. As a good benchmark, look at the Guava API; it consists of many static utility classes, but just as many classes and interfaces designed to be easily extended. Do what you think is best.
Suppose to have a two-characters String, which should represent the ISO 639 country or language name.
You know, Locale class has two functions getISOLanguages and getISOCountries that return an array of String with all the ISO languages and ISO countries, respectively.
To check if a specific String object is a valid ISO language or ISO country I should look inside that arrays for a matching String. Ok, I can do that by using a binary search (e.g. Arrays.binarySearch or the ApacheCommons ArrayUtils.contains).
The question is: exists any utility (e.g. from Guava or Apache Commons libraries) that provides a cleaner way, e.g. a function that returns a boolean to validate a String as a valid ISO 639 language or ISO 639 Country?
For instance:
public static boolean isValidISOLanguage(String s)
public static boolean isValidISOCountry(String s)
I wouldn't bother using either a binary search or any third party libraries - HashSet is fine for this:
public final class IsoUtil {
private static final Set<String> ISO_LANGUAGES = Set.of(Locale.getISOLanguages());
private static final Set<String> ISO_COUNTRIES = Set.of(Locale.getISOCountries());
private IsoUtil() {}
public static boolean isValidISOLanguage(String s) {
return ISO_LANGUAGES.contains(s);
}
public static boolean isValidISOCountry(String s) {
return ISO_COUNTRIES.contains(s);
}
}
You could check for the string length first, but I'm not sure I'd bother - at least not unless you want to protect yourself against performance attacks where you're given enormous strings which would take a long time to hash.
EDIT: If you do want to use a 3rd party library, ICU4J is the most likely contender - but that may well have a more up-to-date list than the ones supported by Locale, so you would want to move to use ICU4J everywhere, probably.
As far I know there is no any such method in any library but at least you can declare it yourself like:
import static java.util.Arrays.binarySearch;
import java.util.Locale;
/**
* Validator of country code.
* Uses binary search over array of sorted country codes.
* Country code has two ASCII letters so we need at least two bytes to represent the code.
* Two bytes are represented in Java by short type. This is useful for us because we can use Arrays.binarySearch(short[] a, short needle)
* Each country code is converted to short via countryCodeNeedle() function.
*
* Average speed of the method is 246.058 ops/ms which is twice slower than lookup over HashSet (523.678 ops/ms).
* Complexity is O(log(N)) instead of O(1) for HashSet.
* But it consumes only 520 bytes of RAM to keep the list of country codes instead of 22064 (> 21 Kb) to hold HashSet of country codes.
*/
public class CountryValidator {
/** Sorted array of country codes converted to short */
private static final short[] COUNTRIES_SHORT = initShortArray(Locale.getISOCountries());
public static boolean isValidCountryCode(String countryCode) {
if (countryCode == null || countryCode.length() != 2 || countryCodeIsNotAlphaUppercase(countryCode)) {
return false;
}
short needle = countryCodeNeedle(countryCode);
return binarySearch(COUNTRIES_SHORT, needle) >= 0;
}
private static boolean countryCodeIsNotAlphaUppercase(String countryCode) {
char c1 = countryCode.charAt(0);
if (c1 < 'A' || c1 > 'Z') {
return true;
}
char c2 = countryCode.charAt(1);
return c2 < 'A' || c2 > 'Z';
}
/**
* Country code has two ASCII letters so we need at least two bytes to represent the code.
* Two bytes are represented in Java by short type. So we should convert two bytes of country code to short.
* We can use something like:
* short val = (short)((hi << 8) | lo);
* But in fact very similar logic is done inside of String.hashCode() function.
* And what is even more important is that each string object already has cached hash code.
* So for us the conversion of two letter country code to short can be immediately.
* We can relay on String's hash code because it's specified in JLS
**/
private static short countryCodeNeedle(String countryCode) {
return (short) countryCode.hashCode();
}
private static short[] initShortArray(String[] isoCountries) {
short[] countriesShortArray = new short[isoCountries.length];
for (int i = 0; i < isoCountries.length; i++) {
String isoCountry = isoCountries[i];
countriesShortArray[i] = countryCodeNeedle(isoCountry);
}
return countriesShortArray;
}
}
The Locale.getISOCountries() will always create a new array so we should store it into a static field to avoid non necessary allocations.
In the same time HashSet or TreeSet consumes a lot of memory so this validator will use a binary search on array. This is a trade off between speed and memory.