Reputation: 23
RasEnumConnections function which realized in JNA is returning incomplete data.
What wrong? This is my code:
public static void main(String[] args) {
Connected();
}
private static void Connected () {
boolean state = false;
ArrayList<String> connectedNames = new ArrayList<>();
IntByReference lpcb = new IntByReference(0);
IntByReference lpcConnections = new IntByReference(0);
Rasapi32.INSTANCE.RasEnumConnections(null, lpcb,lpcConnections);
WinRas.RASCONN conn = new WinRas.RASCONN();
conn.dwSize = lpcb.getValue();
WinRas.RASCONN[] connArray;
if(lpcConnections.getValue() > 0)
connArray = (WinRas.RASCONN[])conn.toArray(lpcConnections.getValue());
else
connArray = (WinRas.RASCONN[])conn.toArray(1);
System.out.println("lpcb: " + lpcb.getValue() + " lpcConnections: " + lpcConnections.getValue() + " RASCONN Size: " + conn.dwSize);
int error = Rasapi32.INSTANCE.RasEnumConnections(connArray, lpcb,lpcConnections);
if(error == WinError.ERROR_SUCCESS) {
System.out.println("Entry name: " + Native.toString(connArray[0].szEntryName)
+ " Guid string: " + connArray[0].guidEntry.toGuidString());
System.out.println(connArray[0].guidEntry.Data1);
System.out.println(connArray[0].guidEntry.Data2);
System.out.println(connArray[0].guidEntry.Data3);
}
else System.out.println("Error: " + error);
WinRas.RASENTRY.ByReference entry = getPhoneBookEntry("test1");
if(entry != null) {
System.out.println("test1 guid: "+ entry.guidId.toGuidString());
System.out.println(entry.guidId.Data1);
System.out.println(entry.guidId.Data2);
System.out.println(entry.guidId.Data3);
}
else System.out.println("Error: " + Native.getLastError());
}
}
Char array szEntryName contains only 3 last chars of connection name. (Connection name is "test1")
Upvotes: 1
Views: 133
Reputation: 31
This is still an issue in X64 but I believe I got it working. The JNA RASCON constructor just needs updating.
I followed the recommendation for a new RASCON struct copying the entire WinRas class in adding the .
public interface WinRas64 {
...
public static class RASCONN64 extends Structure {
...
public RASCONN64(int alignData) {
super(alignData);
dwSize = size();
}
...
...
I created my own interface (copying from Rasapi32) to the 32bit dll so that my new RASCON64 struct could be used.
public interface Rasapi64 extends StdCallLibrary {
org.example.ras.windows.Rasapi64 INSTANCE =
Native.load("Rasapi32",
org.example.ras.windows.Rasapi64.class,
W32APIOptions.DEFAULT_OPTIONS);
...
int RasEnumConnections(RASCONN64[] lprasconn, IntByReference lpcb, IntByReference lpcConnections);
And it appears I can fully enumerate the RAS connection. NOTE I was surprised only CONNECTED connections show up from this call.
IntByReference lpcb = new IntByReference(0);
IntByReference lpcConnections = new IntByReference();
int err = Rasapi64.INSTANCE.RasEnumConnections(null, lpcb, lpcConnections);
if (err != WinError.ERROR_SUCCESS && err != WinRas64.ERROR_BUFFER_TOO_SMALL) throw new Ras32Exception(err);
if (lpcb.getValue() == 0) return null;
// get the connections
WinRas64.RASCONN64[] connections = new WinRas64.RASCONN64[lpcConnections.getValue()];
for (int i = 0; i < lpcConnections.getValue(); i++) {
//connections[i] = new WinRas.RASCONN();
connections[i] = new WinRas64.RASCONN64(1);
connections[i].dwSize = lpcb.getValue(); //reset connection struct size according to first RasEnumConn call
}
err = Rasapi64.INSTANCE.RasEnumConnections(connections, lpcb, lpcConnections);
if (err != WinError.ERROR_SUCCESS) throw new Ras32Exception(err);
Upvotes: 0
Reputation: 9130
As I've noted in the comments, the debug output gives you a strong hint at what's happening. The missing "t" and "e" characters appear as 0x74 and 0x65 in the midst of what JNA expects to be a 64-bit pointer. The logical conclusion is that Windows is returning a 32-bit pointer followed by the string, 4 bytes earlier than JNA expected.
RasEnumConnections
states a few things regarding the buffer you are passing as connArray
:
On input, an application must set the dwSize member of the first RASCONN structure in the buffer to sizeof(RASCONN) in order to identify the version of the structure being passed.
In your sample code above you are leaving this value the same as the value from the initial return. This is specifying the "wrong" version of the structure. Instead, you should set the dwSize
member to the size you want in your JNA structure:
conn.dwSize = conn.size();
Actually, the constructor for RASCONN sets this for you! So you actually don't have to do this. But in your code sample above, you are overwriting what was pre-set; just delete your conn.dwSize
line.
Note that since you are now requesting a (4-bytes per array element) larger buffer by definining the structure size, you also need to pass the increased size in the (second) RasEnumConnections()
call. It's set as the number of elements times the (smaller) structure size, but you should reset to the number of elements times the (larger) size like this:
lpcb.setValue(conn.size() * lpcConnections.getValue());
prior to fetching the full array. Otherwise you'll get the error 632 (Incorrect Structure Size).
For reference (or perhaps a suitable replacement for your own code), take a look at the code as implemented in the getRasConnection(String connName)
method in JNA's Rasapi32Util.java class.
Upvotes: 0