1
2
3
4
5 package oshi.driver.windows.registry;
6
7 import java.net.InetAddress;
8 import java.net.UnknownHostException;
9 import java.nio.ByteBuffer;
10 import java.nio.ByteOrder;
11 import java.nio.IntBuffer;
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.List;
15
16 import com.sun.jna.Pointer;
17 import com.sun.jna.platform.win32.IPHlpAPI;
18 import com.sun.jna.platform.win32.VersionHelpers;
19 import com.sun.jna.platform.win32.WinBase;
20 import com.sun.jna.platform.win32.WinNT;
21 import com.sun.jna.platform.win32.Wtsapi32;
22 import com.sun.jna.platform.win32.Wtsapi32.WTSINFO;
23 import com.sun.jna.platform.win32.Wtsapi32.WTS_CLIENT_ADDRESS;
24 import com.sun.jna.platform.win32.Wtsapi32.WTS_SESSION_INFO;
25
26 import oshi.annotation.concurrent.ThreadSafe;
27 import oshi.jna.ByRef.CloseableIntByReference;
28 import oshi.jna.ByRef.CloseablePointerByReference;
29 import oshi.software.os.OSSession;
30 import oshi.util.ParseUtil;
31
32
33
34
35 @ThreadSafe
36 public final class SessionWtsData {
37
38 private static final int WTS_ACTIVE = 0;
39 private static final int WTS_CLIENTADDRESS = 14;
40 private static final int WTS_SESSIONINFO = 24;
41 private static final int WTS_CLIENTPROTOCOLTYPE = 16;
42
43 private static final boolean IS_VISTA_OR_GREATER = VersionHelpers.IsWindowsVistaOrGreater();
44
45 private static final Wtsapi32 WTS = Wtsapi32.INSTANCE;
46
47 private SessionWtsData() {
48 }
49
50 public static List<OSSession> queryUserSessions() {
51 List<OSSession> sessions = new ArrayList<>();
52 if (IS_VISTA_OR_GREATER) {
53 try (CloseablePointerByReference ppSessionInfo = new CloseablePointerByReference();
54 CloseableIntByReference pCount = new CloseableIntByReference();
55 CloseablePointerByReference ppBuffer = new CloseablePointerByReference();
56 CloseableIntByReference pBytes = new CloseableIntByReference()) {
57 if (WTS.WTSEnumerateSessions(Wtsapi32.WTS_CURRENT_SERVER_HANDLE, 0, 1, ppSessionInfo, pCount)) {
58 Pointer pSessionInfo = ppSessionInfo.getValue();
59 if (pCount.getValue() > 0) {
60 WTS_SESSION_INFO sessionInfoRef = new WTS_SESSION_INFO(pSessionInfo);
61 WTS_SESSION_INFO[] sessionInfo = (WTS_SESSION_INFO[]) sessionInfoRef.toArray(pCount.getValue());
62 for (WTS_SESSION_INFO session : sessionInfo) {
63 if (session.State == WTS_ACTIVE) {
64
65 WTS.WTSQuerySessionInformation(Wtsapi32.WTS_CURRENT_SERVER_HANDLE, session.SessionId,
66 WTS_CLIENTPROTOCOLTYPE, ppBuffer, pBytes);
67 Pointer pBuffer = ppBuffer.getValue();
68 short protocolType = pBuffer.getShort(0);
69 WTS.WTSFreeMemory(pBuffer);
70
71 if (protocolType > 0) {
72
73 String device = session.pWinStationName;
74
75 WTS.WTSQuerySessionInformation(Wtsapi32.WTS_CURRENT_SERVER_HANDLE,
76 session.SessionId, WTS_SESSIONINFO, ppBuffer, pBytes);
77 pBuffer = ppBuffer.getValue();
78 WTSINFO wtsInfo = new WTSINFO(pBuffer);
79
80 long logonTime = new WinBase.FILETIME(
81 new WinNT.LARGE_INTEGER(wtsInfo.LogonTime.getValue())).toTime();
82 String userName = wtsInfo.getUserName();
83 WTS.WTSFreeMemory(pBuffer);
84
85 WTS.WTSQuerySessionInformation(Wtsapi32.WTS_CURRENT_SERVER_HANDLE,
86 session.SessionId, WTS_CLIENTADDRESS, ppBuffer, pBytes);
87 pBuffer = ppBuffer.getValue();
88 WTS_CLIENT_ADDRESS addr = new WTS_CLIENT_ADDRESS(pBuffer);
89 WTS.WTSFreeMemory(pBuffer);
90 String host = "::";
91 if (addr.AddressFamily == IPHlpAPI.AF_INET) {
92 try {
93 host = InetAddress.getByAddress(Arrays.copyOfRange(addr.Address, 2, 6))
94 .getHostAddress();
95 } catch (UnknownHostException e) {
96
97 host = "Illegal length IP Array";
98 }
99 } else if (addr.AddressFamily == IPHlpAPI.AF_INET6) {
100
101 int[] ipArray = convertBytesToInts(addr.Address);
102 host = ParseUtil.parseUtAddrV6toIP(ipArray);
103 }
104 sessions.add(new OSSession(userName, device, logonTime, host));
105 }
106 }
107 }
108 }
109 WTS.WTSFreeMemory(pSessionInfo);
110 }
111 }
112 }
113 return sessions;
114 }
115
116
117
118
119
120
121
122
123
124
125 private static int[] convertBytesToInts(byte[] address) {
126 IntBuffer intBuf = ByteBuffer.wrap(Arrays.copyOfRange(address, 2, 18)).order(ByteOrder.BIG_ENDIAN)
127 .asIntBuffer();
128 int[] array = new int[intBuf.remaining()];
129 intBuf.get(array);
130 return array;
131 }
132 }