77f2bbcca784320da10c1a06de2cf697af2c3a90
[public/netxms.git] / src / agent / subagents / winnt / main.cpp
1 /*
2 ** Windows platform subagent
3 ** Copyright (C) 2003-2016 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** File: main.cpp
20 **
21 **/
22
23 #include "winnt_subagent.h"
24 #include "lm.h"
25
26 /**
27 * Externlals
28 */
29 LONG H_ActiveUserSessions(const TCHAR *cmd, const TCHAR *arg, StringList *value, AbstractCommSession *session);
30 LONG H_AgentDesktop(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
31 LONG H_AppAddressSpace(const TCHAR *pszCmd, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session);
32 LONG H_ArpCache(const TCHAR *cmd, const TCHAR *arg, StringList *value, AbstractCommSession *session);
33 LONG H_ConnectedUsers(const TCHAR *pszCmd, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session);
34 LONG H_Desktops(const TCHAR *cmd, const TCHAR *arg, StringList *value, AbstractCommSession *session);
35 LONG H_HandleCount(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
36 LONG H_InstalledProducts(const TCHAR *cmd, const TCHAR *arg, Table *value, AbstractCommSession *);
37 LONG H_InterfaceList(const TCHAR *cmd, const TCHAR *arg, StringList *value, AbstractCommSession *session);
38 LONG H_InterfaceNames(const TCHAR *cmd, const TCHAR *arg, StringList *value, AbstractCommSession *session);
39 LONG H_IPRoutingTable(const TCHAR *cmd, const TCHAR *arg, StringList *pValue, AbstractCommSession *session);
40 LONG H_NetInterface64bitSupport(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
41 LONG H_NetInterfaceStats(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
42 LONG H_NetIPStats(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
43 LONG H_RemoteShareStatus(const TCHAR *pszCmd, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session);
44 LONG H_ProcessList(const TCHAR *cmd, const TCHAR *arg, StringList *value, AbstractCommSession *session);
45 LONG H_ProcessTable(const TCHAR *cmd, const TCHAR *arg, Table *value, AbstractCommSession *);
46 LONG H_ProcCount(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
47 LONG H_ProcCountSpecific(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
48 LONG H_ProcInfo(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
49 LONG H_ServiceList(const TCHAR *pszCmd, const TCHAR *pArg, StringList *value, AbstractCommSession *session);
50 LONG H_ServiceState(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
51 LONG H_ServiceTable(const TCHAR *pszCmd, const TCHAR *pArg, Table *value, AbstractCommSession *session);
52 LONG H_SysUpdateTime(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
53 LONG H_ThreadCount(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
54 LONG H_WindowStations(const TCHAR *cmd, const TCHAR *arg, StringList *value, AbstractCommSession *session);
55
56 /**
57 * Optional imports
58 */
59 DWORD (__stdcall *imp_GetIfEntry2)(PMIB_IF_ROW2) = NULL;
60
61 /**
62 * Windows XP/Windows Server 2003 flag
63 */
64 bool g_isWin5 = false;
65
66 /**
67 * Import symbols
68 */
69 static void ImportSymbols()
70 {
71 HMODULE hModule;
72
73 // IPHLPAPI.DLL
74 hModule = LoadLibrary(_T("IPHLPAPI.DLL"));
75 if (hModule != NULL)
76 {
77 imp_GetIfEntry2 = (DWORD (__stdcall *)(PMIB_IF_ROW2))GetProcAddress(hModule, "GetIfEntry2");
78 }
79 else
80 {
81 AgentWriteLog(NXLOG_WARNING, _T("Unable to load IPHLPAPI.DLL"));
82 }
83 }
84
85 /**
86 * Set or clear current privilege
87 */
88 static BOOL SetCurrentPrivilege(LPCTSTR pszPrivilege, BOOL bEnablePrivilege)
89 {
90 HANDLE hToken;
91 LUID luid;
92 TOKEN_PRIVILEGES tp, tpPrevious;
93 DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
94 BOOL bSuccess = FALSE;
95
96 if (!LookupPrivilegeValue(NULL, pszPrivilege, &luid))
97 return FALSE;
98
99 if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
100 return FALSE;
101
102 tp.PrivilegeCount = 1;
103 tp.Privileges[0].Luid = luid;
104 tp.Privileges[0].Attributes = 0;
105
106 if (AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
107 &tpPrevious, &cbPrevious))
108 {
109 tpPrevious.PrivilegeCount = 1;
110 tpPrevious.Privileges[0].Luid = luid;
111
112 if (bEnablePrivilege)
113 tpPrevious.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED;
114 else
115 tpPrevious.Privileges[0].Attributes &= ~SE_PRIVILEGE_ENABLED;
116
117 bSuccess = AdjustTokenPrivileges(hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL);
118 }
119
120 CloseHandle(hToken);
121
122 return bSuccess;
123 }
124
125 /**
126 * Shutdown system
127 */
128 static LONG H_ActionShutdown(const TCHAR *action, StringList *args, const TCHAR *data, AbstractCommSession *session)
129 {
130 LONG nRet = ERR_INTERNAL_ERROR;
131
132 if (SetCurrentPrivilege(SE_SHUTDOWN_NAME, TRUE))
133 {
134 if (InitiateSystemShutdown(NULL, NULL, 0, TRUE, (*data == _T('R')) ? TRUE : FALSE))
135 nRet = ERR_SUCCESS;
136 }
137 return nRet;
138 }
139
140 /**
141 * Change user's password
142 * Parameters: user new_password
143 */
144 static LONG H_ChangeUserPassword(const TCHAR *action, StringList *args, const TCHAR *data, AbstractCommSession *session)
145 {
146 if (args->size() < 2)
147 return ERR_INTERNAL_ERROR;
148
149 USER_INFO_1003 ui;
150 ui.usri1003_password = (TCHAR *)args->get(1);
151 NET_API_STATUS status = NetUserSetInfo(NULL, args->get(0), 1003, (LPBYTE)&ui, NULL);
152 AgentWriteDebugLog(2, _T("WINNT: change password for user %s status=%d"), args->get(0), status);
153 return (status == NERR_Success) ? ERR_SUCCESS : ERR_INTERNAL_ERROR;
154 }
155
156 /**
157 * Supported parameters
158 */
159 static NETXMS_SUBAGENT_PARAM m_parameters[] =
160 {
161 { _T("Agent.Desktop"), H_AgentDesktop, NULL, DCI_DT_STRING, _T("Desktop associated with agent process") },
162 { _T("Net.Interface.64BitCounters"), H_NetInterface64bitSupport, NULL, DCI_DT_INT, DCIDESC_NET_INTERFACE_64BITCOUNTERS },
163 { _T("Net.Interface.AdminStatus(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_ADMIN_STATUS, DCI_DT_INT, DCIDESC_NET_INTERFACE_ADMINSTATUS },
164 { _T("Net.Interface.BytesIn(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_BYTES_IN, DCI_DT_UINT, DCIDESC_NET_INTERFACE_BYTESIN },
165 { _T("Net.Interface.BytesIn64(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_BYTES_IN_64, DCI_DT_UINT64, DCIDESC_NET_INTERFACE_BYTESIN },
166 { _T("Net.Interface.BytesOut(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_BYTES_OUT, DCI_DT_UINT, DCIDESC_NET_INTERFACE_BYTESOUT },
167 { _T("Net.Interface.BytesOut64(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_BYTES_OUT_64, DCI_DT_UINT64, DCIDESC_NET_INTERFACE_BYTESOUT },
168 { _T("Net.Interface.Description(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_DESCR, DCI_DT_STRING, DCIDESC_NET_INTERFACE_DESCRIPTION },
169 { _T("Net.Interface.InErrors(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_IN_ERRORS, DCI_DT_UINT, DCIDESC_NET_INTERFACE_INERRORS },
170 { _T("Net.Interface.Link(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_OPER_STATUS, DCI_DT_DEPRECATED, DCIDESC_DEPRECATED },
171 { _T("Net.Interface.MTU(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_MTU, DCI_DT_UINT, DCIDESC_NET_INTERFACE_MTU },
172 { _T("Net.Interface.OperStatus(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_OPER_STATUS, DCI_DT_INT, DCIDESC_NET_INTERFACE_OPERSTATUS },
173 { _T("Net.Interface.OutErrors(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_OUT_ERRORS, DCI_DT_UINT, DCIDESC_NET_INTERFACE_OUTERRORS },
174 { _T("Net.Interface.PacketsIn(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_PACKETS_IN, DCI_DT_UINT, DCIDESC_NET_INTERFACE_PACKETSIN },
175 { _T("Net.Interface.PacketsIn64(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_PACKETS_IN_64, DCI_DT_UINT64, DCIDESC_NET_INTERFACE_PACKETSIN },
176 { _T("Net.Interface.PacketsOut(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_PACKETS_OUT, DCI_DT_UINT, DCIDESC_NET_INTERFACE_PACKETSOUT },
177 { _T("Net.Interface.PacketsOut64(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_PACKETS_OUT_64, DCI_DT_UINT64, DCIDESC_NET_INTERFACE_PACKETSOUT },
178 { _T("Net.Interface.Speed(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_SPEED, DCI_DT_UINT64, DCIDESC_NET_INTERFACE_SPEED },
179 { _T("Net.IP.Forwarding"), H_NetIPStats, (TCHAR *)NETINFO_IP_FORWARDING, DCI_DT_INT, DCIDESC_NET_IP_FORWARDING },
180 { _T("Net.RemoteShareStatus(*)"), H_RemoteShareStatus, _T("C"), DCI_DT_INT, _T("Status of remote shared resource") },
181 { _T("Net.RemoteShareStatusText(*)"), H_RemoteShareStatus, _T("T"), DCI_DT_STRING, _T("Status of remote shared resource as text") },
182 { _T("Process.Count(*)"), H_ProcCountSpecific, _T("N"), DCI_DT_INT, DCIDESC_PROCESS_COUNT },
183 { _T("Process.CountEx(*)"), H_ProcCountSpecific, _T("E"), DCI_DT_INT, DCIDESC_PROCESS_COUNTEX },
184 { _T("Process.CPUTime(*)"), H_ProcInfo, (TCHAR *)PROCINFO_CPUTIME, DCI_DT_UINT64, DCIDESC_PROCESS_CPUTIME },
185 { _T("Process.GDIObjects(*)"), H_ProcInfo, (TCHAR *)PROCINFO_GDI_OBJ, DCI_DT_UINT64, DCIDESC_PROCESS_GDIOBJ },
186 { _T("Process.Handles(*)"), H_ProcInfo, (TCHAR *)PROCINFO_HANDLES, DCI_DT_UINT, DCIDESC_PROCESS_HANDLES },
187 { _T("Process.IO.OtherB(*)"), H_ProcInfo, (TCHAR *)PROCINFO_IO_OTHER_B, DCI_DT_UINT64, DCIDESC_PROCESS_IO_OTHERB },
188 { _T("Process.IO.OtherOp(*)"), H_ProcInfo, (TCHAR *)PROCINFO_IO_OTHER_OP, DCI_DT_UINT64, DCIDESC_PROCESS_IO_OTHEROP },
189 { _T("Process.IO.ReadB(*)"), H_ProcInfo, (TCHAR *)PROCINFO_IO_READ_B, DCI_DT_UINT64, DCIDESC_PROCESS_IO_READB },
190 { _T("Process.IO.ReadOp(*)"), H_ProcInfo, (TCHAR *)PROCINFO_IO_READ_OP, DCI_DT_UINT64, DCIDESC_PROCESS_IO_READOP },
191 { _T("Process.IO.WriteB(*)"), H_ProcInfo, (TCHAR *)PROCINFO_IO_WRITE_B, DCI_DT_UINT64, DCIDESC_PROCESS_IO_WRITEB },
192 { _T("Process.IO.WriteOp(*)"), H_ProcInfo, (TCHAR *)PROCINFO_IO_WRITE_OP, DCI_DT_UINT64, DCIDESC_PROCESS_IO_WRITEOP },
193 { _T("Process.KernelTime(*)"), H_ProcInfo, (TCHAR *)PROCINFO_KTIME, DCI_DT_UINT64, DCIDESC_PROCESS_KERNELTIME },
194 { _T("Process.PageFaults(*)"), H_ProcInfo, (TCHAR *)PROCINFO_PF, DCI_DT_UINT64, DCIDESC_PROCESS_PAGEFAULTS },
195 { _T("Process.UserObjects(*)"), H_ProcInfo, (TCHAR *)PROCINFO_USER_OBJ, DCI_DT_UINT64, DCIDESC_PROCESS_USEROBJ },
196 { _T("Process.UserTime(*)"), H_ProcInfo, (TCHAR *)PROCINFO_UTIME, DCI_DT_UINT64, DCIDESC_PROCESS_USERTIME },
197 { _T("Process.VMSize(*)"), H_ProcInfo, (TCHAR *)PROCINFO_VMSIZE, DCI_DT_UINT64, DCIDESC_PROCESS_VMSIZE },
198 { _T("Process.WkSet(*)"), H_ProcInfo, (TCHAR *)PROCINFO_WKSET, DCI_DT_UINT64, DCIDESC_PROCESS_WKSET },
199 { _T("System.AppAddressSpace"), H_AppAddressSpace, NULL, DCI_DT_UINT, DCIDESC_SYSTEM_APPADDRESSSPACE },
200 { _T("System.ConnectedUsers"), H_ConnectedUsers, NULL, DCI_DT_INT, DCIDESC_SYSTEM_CONNECTEDUSERS },
201 { _T("System.HandleCount"), H_HandleCount, NULL, DCI_DT_UINT, DCIDESC_SYSTEM_HANDLECOUNT },
202 { _T("System.ProcessCount"), H_ProcCount, NULL, DCI_DT_UINT, DCIDESC_SYSTEM_PROCESSCOUNT },
203 { _T("System.ServiceState(*)"), H_ServiceState, NULL, DCI_DT_INT, DCIDESC_SYSTEM_SERVICESTATE },
204 { _T("System.ThreadCount"), H_ThreadCount, NULL, DCI_DT_UINT, DCIDESC_SYSTEM_THREADCOUNT },
205 { _T("System.Update.LastDetectTime"), H_SysUpdateTime, _T("Detect"), DCI_DT_INT64, _T("System update: last detect time") },
206 { _T("System.Update.LastDownloadTime"), H_SysUpdateTime, _T("Download"), DCI_DT_INT64, _T("System update: last download time") },
207 { _T("System.Update.LastInstallTime"), H_SysUpdateTime, _T("Install"), DCI_DT_INT64, _T("System update: last install time") }
208 };
209
210 /**
211 * Supported lists
212 */
213 static NETXMS_SUBAGENT_LIST m_lists[] =
214 {
215 { _T("Net.ArpCache"), H_ArpCache, NULL },
216 { _T("Net.InterfaceList"), H_InterfaceList, NULL },
217 { _T("Net.InterfaceNames"), H_InterfaceNames, NULL },
218 { _T("Net.IP.RoutingTable"), H_IPRoutingTable, NULL },
219 { _T("System.ActiveUserSessions"), H_ActiveUserSessions, NULL },
220 { _T("System.Desktops(*)"), H_Desktops, NULL },
221 { _T("System.ProcessList"), H_ProcessList, NULL },
222 { _T("System.Services"), H_ServiceList, NULL },
223 { _T("System.WindowStations"), H_WindowStations, NULL }
224 };
225
226 /**
227 * Supported tables
228 */
229 static NETXMS_SUBAGENT_TABLE m_tables[] =
230 {
231 { _T("System.InstalledProducts"), H_InstalledProducts, NULL, _T("NAME"), DCTDESC_SYSTEM_INSTALLED_PRODUCTS },
232 { _T("System.Processes"), H_ProcessTable, NULL, _T("PID"), DCTDESC_SYSTEM_PROCESSES },
233 { _T("System.Services"), H_ServiceTable, NULL, _T("Name"), _T("Services") }
234 };
235
236 /**
237 * Supported actions
238 */
239 static NETXMS_SUBAGENT_ACTION m_actions[] =
240 {
241 { _T("System.Restart"), H_ActionShutdown, _T("R"), _T("Restart system") },
242 { _T("System.Shutdown"), H_ActionShutdown, _T("S"), _T("Shutdown system") },
243 { _T("User.ChangePassword"), H_ChangeUserPassword, NULL, _T("Change password for given user") }
244 };
245
246 /**
247 * Subagent information
248 */
249 static NETXMS_SUBAGENT_INFO m_info =
250 {
251 NETXMS_SUBAGENT_INFO_MAGIC,
252 _T("WinNT"), NETXMS_VERSION_STRING,
253 NULL, NULL, NULL,
254 sizeof(m_parameters) / sizeof(NETXMS_SUBAGENT_PARAM),
255 m_parameters,
256 sizeof(m_lists) / sizeof(NETXMS_SUBAGENT_LIST),
257 m_lists,
258 sizeof(m_tables) / sizeof(NETXMS_SUBAGENT_TABLE),
259 m_tables,
260 sizeof(m_actions) / sizeof(NETXMS_SUBAGENT_ACTION),
261 m_actions,
262 0, NULL // push parameters
263 };
264
265 /**
266 * Entry point for NetXMS agent
267 */
268 DECLARE_SUBAGENT_ENTRY_POINT(WINNT)
269 {
270 *ppInfo = &m_info;
271 ImportSymbols();
272
273 OSVERSIONINFO ver;
274 ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
275 if (GetVersionEx(&ver))
276 {
277 if (ver.dwMajorVersion < 6)
278 g_isWin5 = true;
279 }
280 return TRUE;
281 }
282
283 /**
284 * DLL entry point
285 */
286 BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
287 {
288 if (dwReason == DLL_PROCESS_ATTACH)
289 DisableThreadLibraryCalls(hInstance);
290 return TRUE;
291 }