Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

288 lines
6.9 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: users.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 8-10-99 JBrezak Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <nt.h>
  18. #include <ntrtl.h>
  19. #include <nturtl.h>
  20. #include <windows.h>
  21. #define SECURITY_WIN32
  22. #include <rpc.h>
  23. #include <ntsecapi.h>
  24. #include <sspi.h>
  25. extern "C" {
  26. #include <secint.h>
  27. }
  28. #include <stdio.h>
  29. #include <winsta.h>
  30. #include <ntdsapi.h>
  31. LPTSTR FormatUserUpn(
  32. BOOL UseUpn,
  33. PSECURITY_STRING Domain,
  34. PSECURITY_STRING User
  35. )
  36. {
  37. HANDLE hDs;
  38. ULONG NetStatus;
  39. PDS_NAME_RESULT Result;
  40. TCHAR DName[DOMAIN_LENGTH + 1];
  41. static TCHAR UName[DOMAIN_LENGTH + USERNAME_LENGTH + 2];
  42. LPTSTR Name = UName;
  43. swprintf(DName, TEXT("%wZ"), Domain);
  44. swprintf(UName, TEXT("%wZ\\%wZ"), Domain, User);
  45. if (!UseUpn)
  46. return UName;
  47. NetStatus = DsBind(NULL, DName, &hDs);
  48. if (NetStatus != 0) {
  49. #ifdef DBGX
  50. wprintf(TEXT("DsBind failed -0x%x\n"), NetStatus);
  51. #endif
  52. return UName;
  53. }
  54. NetStatus = DsCrackNames(hDs, DS_NAME_NO_FLAGS, DS_NT4_ACCOUNT_NAME,
  55. DS_USER_PRINCIPAL_NAME, 1, &Name, &Result);
  56. if (NetStatus != 0) {
  57. #ifdef DBGX
  58. wprintf(TEXT("DsCrackNames failed -0x%x\n"), NetStatus);
  59. #endif
  60. return UName;
  61. }
  62. if (Result->rItems[0].pName)
  63. return Result->rItems[0].pName;
  64. else
  65. return UName;
  66. }
  67. static LPCTSTR dt_output_dhms = TEXT("%d %s %02d:%02d:%02d");
  68. static LPCTSTR dt_day_plural = TEXT("days");
  69. static LPCTSTR dt_day_singular = TEXT("day");
  70. static LPCTSTR dt_output_donly = TEXT("%d %s");
  71. static LPCTSTR dt_output_ms = TEXT("%d:%02d");
  72. static LPCTSTR dt_output_hms = TEXT("%d:%02d:%02d");
  73. static LPCTSTR ftime_default_fmt = TEXT("%02d/%02d/%02d %02d:%02d");
  74. LPTSTR FormatIdleTime(long dt)
  75. {
  76. static TCHAR buf2[80];
  77. int days, hours, minutes, seconds, tt;
  78. days = (int) (dt / (24*3600l));
  79. tt = dt % (24*3600l);
  80. hours = (int) (tt / 3600);
  81. tt %= 3600;
  82. minutes = (int) (tt / 60);
  83. seconds = (int) (tt % 60);
  84. if (days) {
  85. if (hours || minutes || seconds) {
  86. wsprintf(buf2, dt_output_dhms, days,
  87. (days > 1) ? dt_day_plural : dt_day_singular,
  88. hours, minutes, seconds);
  89. }
  90. else {
  91. wsprintf(buf2, dt_output_donly, days,
  92. (days > 1) ? dt_day_plural : dt_day_singular);
  93. }
  94. }
  95. else {
  96. wsprintf(buf2, dt_output_hms, hours, minutes, seconds);
  97. }
  98. return buf2;
  99. }
  100. LPTSTR FormatLogonType(ULONG LogonType)
  101. {
  102. static TCHAR buf[20];
  103. switch((SECURITY_LOGON_TYPE)LogonType) {
  104. case Interactive:
  105. lstrcpy(buf, TEXT("Interactive"));
  106. break;
  107. case Network:
  108. lstrcpy(buf, TEXT("Network"));
  109. break;
  110. case Batch:
  111. lstrcpy(buf, TEXT("Batch"));
  112. break;
  113. case Service:
  114. lstrcpy(buf, TEXT("Service"));
  115. break;
  116. case Proxy:
  117. lstrcpy(buf, TEXT("Proxy"));
  118. break;
  119. case Unlock:
  120. lstrcpy(buf, TEXT("Unlock"));
  121. break;
  122. case NetworkCleartext:
  123. lstrcpy(buf, TEXT("NetworkCleartext"));
  124. break;
  125. case NewCredentials:
  126. lstrcpy(buf, TEXT("NewCredentials"));
  127. break;
  128. default:
  129. swprintf(buf, TEXT("(%d)"), LogonType);
  130. break;
  131. }
  132. return buf;
  133. }
  134. void Usage(void)
  135. {
  136. wprintf(TEXT("\
  137. Usage: users [-u] [-a]\n\
  138. -u = Print userPrincipalName\n\
  139. -a = Print all logon sessions\n"));
  140. ExitProcess(0);
  141. }
  142. void __cdecl main (int argc, char *argv[])
  143. {
  144. ULONG LogonSessionCount;
  145. PLUID LogonSessions;
  146. int i;
  147. DWORD err;
  148. PSECURITY_LOGON_SESSION_DATA SessionData;
  149. DWORD all = FALSE;
  150. DWORD UPN = FALSE;
  151. WINSTATIONINFORMATION WinStationInfo;
  152. DWORD WinStationInfoLen;
  153. char *ptr;
  154. FILETIME LocalTime;
  155. SYSTEMTIME LogonTime;
  156. TCHAR DateStr[40], TimeStr[40];
  157. WINSTATIONNAME WinStationName = TEXT("inactive");
  158. long IdleTime = 0L;
  159. for (i = 1; i < argc; i++) {
  160. if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
  161. for (ptr = (argv[i] + 1); *ptr; ptr++) {
  162. switch(toupper(*ptr)) {
  163. case 'A':
  164. all = TRUE;
  165. break;
  166. case 'U':
  167. UPN = TRUE;
  168. break;
  169. case '?':
  170. default:
  171. Usage();
  172. break;
  173. }
  174. }
  175. }
  176. }
  177. err = LsaEnumerateLogonSessions(&LogonSessionCount, &LogonSessions);
  178. if (err != ERROR_SUCCESS) {
  179. printf("LsaEnumeratelogonSession failed - 0x%x\n", err);
  180. ExitProcess(1);
  181. }
  182. for (i = 0; i < (int)LogonSessionCount; i++) {
  183. err = LsaGetLogonSessionData(&LogonSessions[i], &SessionData);
  184. if (err != ERROR_SUCCESS) {
  185. printf("LsaGetLogonSessionData failed - 0x%x\n", err);
  186. continue;
  187. }
  188. if (SessionData->LogonType != 0 &&
  189. (all || ((SECURITY_LOGON_TYPE)SessionData->LogonType == Interactive))) {
  190. ZeroMemory(DateStr, sizeof(DateStr));
  191. ZeroMemory(TimeStr, sizeof(TimeStr));
  192. if (!FileTimeToLocalFileTime((LPFILETIME)&SessionData->LogonTime,
  193. &LocalTime) ||
  194. !FileTimeToSystemTime(&LocalTime, &LogonTime)) {
  195. printf("Time conversion failed - 0x%x\n", GetLastError());
  196. }
  197. else {
  198. if (!GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE,
  199. &LogonTime, NULL,
  200. DateStr, sizeof(DateStr))) {
  201. printf("Date format failed - 0x%x\n", GetLastError());
  202. }
  203. if (!GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS,
  204. &LogonTime, NULL,
  205. TimeStr, sizeof(TimeStr))) {
  206. printf("Time format failed - 0x%x\n", GetLastError());
  207. }
  208. }
  209. if (WinStationQueryInformation(SERVERNAME_CURRENT,
  210. SessionData->Session,
  211. WinStationInformation,
  212. &WinStationInfo,
  213. sizeof(WinStationInfo),
  214. &WinStationInfoLen)) {
  215. if (WinStationInfo.ConnectState != State_Idle) {
  216. wcscpy(WinStationName, WinStationInfo.WinStationName);
  217. }
  218. const long TPS = (10*1000*1000);
  219. FILETIME CurrentFileTime;
  220. LARGE_INTEGER Quad;
  221. GetSystemTimeAsFileTime(&CurrentFileTime);
  222. Quad.LowPart = CurrentFileTime.dwLowDateTime;
  223. Quad.HighPart = CurrentFileTime.dwHighDateTime;
  224. IdleTime = (long)
  225. ((Quad.QuadPart - WinStationInfo.LastInputTime.QuadPart) / TPS);
  226. }
  227. else if (GetLastError() == ERROR_APP_WRONG_OS) {
  228. wcscpy(WinStationName, TEXT("Console"));
  229. }
  230. else {
  231. #ifdef DBGX
  232. printf("Query failed for %wZ\\%wZ @ %d - 0x%x\n",
  233. &SessionData->LogonDomain, &SessionData->UserName,
  234. SessionData->Session,
  235. GetLastError());
  236. #endif
  237. continue;
  238. }
  239. wprintf(TEXT("%-30.30s"),
  240. FormatUserUpn(UPN, &SessionData->LogonDomain,
  241. &SessionData->UserName));
  242. if (all)
  243. wprintf(TEXT(" %-12.12s"),
  244. FormatLogonType(SessionData->LogonType));
  245. wprintf(TEXT(" %8.8s %s %s"), WinStationName, DateStr, TimeStr);
  246. if (all)
  247. wprintf(TEXT(" %wZ"),
  248. &SessionData->AuthenticationPackage);
  249. if (all && (IdleTime > 10))
  250. wprintf(TEXT(" %-12.12s"), FormatIdleTime(IdleTime));
  251. wprintf(TEXT("\n"));
  252. }
  253. }
  254. ExitProcess(0);
  255. }