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.

490 lines
13 KiB

  1. //Copyright (c) 1998 - 1999 Microsoft Corporation
  2. /******************************************************************************
  3. *
  4. * QUSER.C
  5. *
  6. * query user information
  7. *
  8. *
  9. *******************************************************************************/
  10. #include <nt.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. #include <windows.h>
  14. #include <winstaw.h>
  15. #include <assert.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <time.h>
  19. #include <utilsub.h>
  20. #include <process.h>
  21. #include <string.h>
  22. #include <malloc.h>
  23. #include <locale.h>
  24. #include <printfoa.h>
  25. #include "quser.h"
  26. HANDLE hServerName = SERVERNAME_CURRENT;
  27. WCHAR ServerName[MAX_IDS_LEN+1];
  28. WCHAR user_string[MAX_IDS_LEN+1];
  29. USHORT help_flag = FALSE;
  30. ULONG CurrentLogonId = (ULONG) -1;
  31. BOOLEAN MatchedOne = FALSE;
  32. TOKMAP ptm[] = {
  33. {L" ", TMFLAG_OPTIONAL, TMFORM_STRING, MAX_IDS_LEN, user_string},
  34. {L"/server", TMFLAG_OPTIONAL, TMFORM_STRING, MAX_IDS_LEN, ServerName},
  35. {L"/?", TMFLAG_OPTIONAL, TMFORM_BOOLEAN,sizeof(USHORT), &help_flag},
  36. {0, 0, 0, 0, 0}
  37. };
  38. /*
  39. * Local function prototypes.
  40. */
  41. void DisplayLastInputTime( LARGE_INTEGER * pCurrentTime, LARGE_INTEGER * pTime );
  42. void DisplayUserInfo( HANDLE hServer , PLOGONID pId, PWCHAR pMatchName );
  43. void Usage( BOOLEAN bError );
  44. /*******************************************************************************
  45. *
  46. * main
  47. *
  48. ******************************************************************************/
  49. int __cdecl
  50. main(INT argc, CHAR **argv)
  51. {
  52. PLOGONID pLogonId;
  53. UINT TermCount;
  54. ULONG Status;
  55. ULONG rc;
  56. WCHAR **argvW;
  57. int i;
  58. setlocale(LC_ALL, ".OCP");
  59. /*
  60. * Massage the command line.
  61. */
  62. argvW = MassageCommandLine((DWORD)argc);
  63. if (argvW == NULL) {
  64. ErrorPrintf(IDS_ERROR_MALLOC);
  65. return(FAILURE);
  66. }
  67. /*
  68. * parse the cmd line without parsing the program name (argc-1, argv+1)
  69. */
  70. rc = ParseCommandLine(argc-1, argvW+1, ptm, 0);
  71. /*
  72. * Check for error from ParseCommandLine
  73. */
  74. if ( help_flag || (rc && !(rc & PARSE_FLAG_NO_PARMS)) ) {
  75. if ( !help_flag ) {
  76. Usage(TRUE);
  77. return(FAILURE);
  78. } else {
  79. Usage(FALSE);
  80. return(SUCCESS);
  81. }
  82. }
  83. // If no remote server was specified, then check if we are running under Terminal Server
  84. if ((!IsTokenPresent(ptm, L"/server") ) && (!AreWeRunningTerminalServices()))
  85. {
  86. ErrorPrintf(IDS_ERROR_NOT_TS);
  87. return(FAILURE);
  88. }
  89. /*
  90. * Open the specified server
  91. */
  92. if( ServerName[0] ) {
  93. hServerName = WinStationOpenServer( ServerName );
  94. if( hServerName == NULL ) {
  95. StringErrorPrintf(IDS_ERROR_SERVER,ServerName);
  96. PutStdErr( GetLastError(), 0 );
  97. return(FAILURE);
  98. }
  99. }
  100. /*
  101. * if no user input, then default to all usernames on system
  102. */
  103. if ( !(*user_string) )
  104. wcscpy( user_string, L"*" );
  105. /*
  106. * Get current LogonId
  107. */
  108. CurrentLogonId = GetCurrentLogonId();
  109. /*
  110. * Get list of active WinStations & display user info.
  111. */
  112. if ( WinStationEnumerate( hServerName, &pLogonId, &TermCount) ) {
  113. for ( i=0; i< (int)TermCount; i++ )
  114. DisplayUserInfo( hServerName , &pLogonId[i], user_string );
  115. WinStationFreeMemory(pLogonId);
  116. } else {
  117. Status = GetLastError();
  118. ErrorPrintf(IDS_ERROR_WINSTATION_ENUMERATE, Status);
  119. PutStdErr( Status, 0 );
  120. return(FAILURE);
  121. }
  122. /*
  123. * Check for at least one match
  124. */
  125. if ( !MatchedOne ) {
  126. StringErrorPrintf(IDS_ERROR_USER_NOT_FOUND, user_string);
  127. return(FAILURE);
  128. }
  129. return(SUCCESS);
  130. }
  131. /*******************************************************************************
  132. *
  133. * DisplayTime
  134. *
  135. * This routine displays time
  136. *
  137. *
  138. * ENTRY:
  139. * pTime (input)
  140. * pointer to system time
  141. *
  142. * EXIT:
  143. * nothing
  144. *
  145. ******************************************************************************/
  146. void
  147. DisplayTime( LARGE_INTEGER * pTime )
  148. {
  149. FILETIME LocalTime;
  150. SYSTEMTIME stime;
  151. LPTSTR lpTimeStr;
  152. int nLen;
  153. TCHAR TimeString[MAX_DATE_TIME_LENGTH];
  154. if ( FileTimeToLocalFileTime( (FILETIME*)pTime, &LocalTime ) &&
  155. FileTimeToSystemTime( &LocalTime, &stime ) ) {
  156. //NBD
  157. // wprintf( L"%02d/%02d/%02d %02d:%02d",
  158. // stime.wMonth, stime.wDay, stime.wYear % 100,
  159. // stime.wHour, stime.wMinute );
  160. //
  161. //Get DateFormat
  162. nLen = GetDateFormat(
  163. LOCALE_USER_DEFAULT,
  164. DATE_SHORTDATE,
  165. &stime,
  166. NULL,
  167. NULL,
  168. 0);
  169. if (nLen == 0)
  170. {
  171. goto unknowntime;
  172. }
  173. lpTimeStr = (LPTSTR) GlobalAlloc(GPTR, (nLen + 1) * sizeof(TCHAR));
  174. if (lpTimeStr == NULL)
  175. {
  176. goto unknowntime;
  177. }
  178. nLen = GetDateFormat(
  179. LOCALE_USER_DEFAULT,
  180. DATE_SHORTDATE,
  181. &stime,
  182. NULL,
  183. lpTimeStr,
  184. nLen);
  185. if (nLen == 0)
  186. {
  187. goto unknowntime;
  188. }
  189. wcscpy(TimeString, lpTimeStr);
  190. wcscat(TimeString, L" ");
  191. GlobalFree(lpTimeStr);
  192. //Get Time Format
  193. nLen = GetTimeFormat(
  194. LOCALE_USER_DEFAULT,
  195. TIME_NOSECONDS,
  196. &stime,
  197. NULL,
  198. NULL,
  199. 0);
  200. if (nLen == 0)
  201. {
  202. goto unknowntime;
  203. }
  204. lpTimeStr = (LPTSTR) GlobalAlloc(GPTR, (nLen + 1) * sizeof(TCHAR));
  205. if (lpTimeStr == NULL)
  206. {
  207. goto unknowntime;
  208. }
  209. nLen = GetTimeFormat(
  210. LOCALE_USER_DEFAULT,
  211. TIME_NOSECONDS,
  212. &stime,
  213. NULL,
  214. lpTimeStr,
  215. nLen);
  216. if (nLen == 0)
  217. {
  218. goto unknowntime;
  219. }
  220. wcscat(TimeString, lpTimeStr);
  221. GlobalFree(lpTimeStr);
  222. wprintf(TimeString );
  223. return;
  224. unknowntime:
  225. // Use a localized "unknown" string if at all possible
  226. wprintf(GetUnknownString() ? GetUnknownString() : L"Unknown");
  227. return;
  228. }
  229. } /* DisplayTime() */
  230. /*******************************************************************************
  231. *
  232. * DisplayLastInputTime
  233. *
  234. * This routine displays the time of last terminal input
  235. *
  236. *
  237. * ENTRY:
  238. * pCurrentTime
  239. * pointer to current system time
  240. * pTime (input)
  241. * pointer to system time of last input
  242. *
  243. * EXIT:
  244. * nothing
  245. *
  246. ******************************************************************************/
  247. void
  248. DisplayLastInputTime( LARGE_INTEGER * pCurrentTime, LARGE_INTEGER * pTime )
  249. {
  250. LARGE_INTEGER InputTime;
  251. LARGE_INTEGER CurrentTime;
  252. LARGE_INTEGER DiffTime;
  253. ULONG d_time;
  254. ULONG minutes;
  255. ULONG hours;
  256. ULONG days;
  257. WCHAR buf[40];
  258. if ( (pTime->HighPart == 0 && pTime->LowPart == 0 ) ||
  259. (pCurrentTime->HighPart == 0 && pCurrentTime->LowPart == 0 ) ) {
  260. goto badtime;
  261. }
  262. /*
  263. * Get the number of seconds since last input
  264. */
  265. DiffTime = RtlLargeIntegerSubtract( *pCurrentTime, *pTime );
  266. DiffTime = RtlExtendedLargeIntegerDivide( DiffTime, 10000000, NULL );
  267. d_time = DiffTime.LowPart;
  268. /*
  269. * Get the number of 'days:hours:minutes' since last input
  270. */
  271. days = (USHORT)(d_time / 86400L); // days since last input
  272. d_time = d_time % 86400L; // seconds into partial day
  273. hours = (USHORT)(d_time / 3600L); // hours since last input
  274. d_time = d_time % 3600L; // seconds into partial hour
  275. minutes = (USHORT)(d_time / 60L); // minutes since last input
  276. /*
  277. * Output
  278. */
  279. if ( days > 0 )
  280. wsprintf( buf, L"%u+%02u:%02u", days, hours, minutes );
  281. else if ( hours > 0 )
  282. wsprintf( buf, L"%u:%02u", hours, minutes );
  283. else if ( minutes > 0 )
  284. wsprintf( buf, L"%u", minutes );
  285. else
  286. wsprintf( buf, L"." );
  287. wprintf( L"%9s ", buf );
  288. return;
  289. /*
  290. * error returns
  291. */
  292. badtime:
  293. if (LoadString(NULL, IDS_NONE, buf, sizeof(buf) / sizeof( WCHAR ) ) != 0)
  294. {
  295. wprintf(buf);
  296. }
  297. else
  298. {
  299. wprintf( L" none " );
  300. }
  301. } /* DisplayLastInputTime() */
  302. /*******************************************************************************
  303. *
  304. * DisplayUserInfo
  305. *
  306. * This routine displays user information for one user
  307. *
  308. *
  309. * ENTRY:
  310. * hServer ( input )
  311. * handle to termsrv
  312. * LogonId (input)
  313. * window station id
  314. * pUsername (input)
  315. * user name to display (or winstation name)
  316. *
  317. * EXIT:
  318. * nothing
  319. *
  320. ******************************************************************************/
  321. void
  322. DisplayUserInfo( HANDLE hServer , PLOGONID pId, PWCHAR pMatchName )
  323. {
  324. WINSTATIONINFORMATION Info;
  325. ULONG Length;
  326. ULONG LogonId;
  327. LogonId = pId->LogonId;
  328. if( WinStationObjectMatch( hServer, pId, pMatchName ) ) {
  329. /*
  330. * Query information
  331. */
  332. if ( !WinStationQueryInformation( hServer,
  333. LogonId,
  334. WinStationInformation,
  335. &Info,
  336. sizeof(Info),
  337. &Length ) ) {
  338. goto done;
  339. }
  340. if ( Info.UserName[0] == UNICODE_NULL )
  341. goto done;
  342. TruncateString( _wcslwr(Info.UserName), 20 );
  343. TruncateString( _wcslwr(Info.WinStationName), 15 );
  344. /*
  345. * If first time - output title
  346. */
  347. if ( !MatchedOne ) {
  348. Message(IDS_TITLE);
  349. MatchedOne = TRUE;
  350. }
  351. /* output current */
  352. if ( (hServer == SERVERNAME_CURRENT) && (Info.LogonId == CurrentLogonId ) )
  353. wprintf( L">" );
  354. else
  355. wprintf( L" " );
  356. {
  357. #define MAX_PRINTFOA_BUFFER_SIZE 1024
  358. char pUserName[MAX_PRINTFOA_BUFFER_SIZE];
  359. char pWinStationName[MAX_PRINTFOA_BUFFER_SIZE];
  360. char pConnectState[MAX_PRINTFOA_BUFFER_SIZE];
  361. WideCharToMultiByte(CP_OEMCP, 0,
  362. Info.UserName, -1,
  363. pUserName, sizeof(pUserName),
  364. NULL, NULL);
  365. WideCharToMultiByte(CP_OEMCP, 0,
  366. Info.WinStationName, -1,
  367. pWinStationName, sizeof(pWinStationName),
  368. NULL, NULL);
  369. WideCharToMultiByte(CP_OEMCP, 0,
  370. StrConnectState(Info.ConnectState, TRUE), -1,
  371. pConnectState, sizeof(pConnectState),
  372. NULL, NULL);
  373. fprintf( stdout,"%-20s %-15s ", pUserName,
  374. (Info.ConnectState == State_Disconnected) ?
  375. "" : pWinStationName );
  376. fprintf( stdout,"%4u %-6s ", Info.LogonId, pConnectState );
  377. }
  378. DisplayLastInputTime( &Info.CurrentTime, &Info.LastInputTime );
  379. DisplayTime( &Info.LogonTime );
  380. wprintf( L"\n" );
  381. }
  382. done:
  383. return;
  384. } /* DisplayUserInfo() */
  385. /*******************************************************************************
  386. *
  387. * Usage
  388. *
  389. * Output the usage message for this utility.
  390. *
  391. * ENTRY:
  392. * bError (input)
  393. * TRUE if the 'invalid parameter(s)' message should preceed the usage
  394. * message and the output go to stderr; FALSE for no such error
  395. * string and output goes to stdout.
  396. *
  397. * EXIT:
  398. *
  399. *
  400. ******************************************************************************/
  401. void
  402. Usage( BOOLEAN bError )
  403. {
  404. if ( bError ) {
  405. ErrorPrintf(IDS_ERROR_INVALID_PARAMETERS);
  406. ErrorPrintf(IDS_HELP_USAGE1);
  407. ErrorPrintf(IDS_HELP_USAGE2);
  408. ErrorPrintf(IDS_HELP_USAGE3);
  409. ErrorPrintf(IDS_HELP_USAGE4);
  410. ErrorPrintf(IDS_HELP_USAGE5);
  411. ErrorPrintf(IDS_HELP_USAGE6);
  412. } else {
  413. Message(IDS_HELP_USAGE1);
  414. Message(IDS_HELP_USAGE2);
  415. Message(IDS_HELP_USAGE3);
  416. Message(IDS_HELP_USAGE4);
  417. Message(IDS_HELP_USAGE5);
  418. Message(IDS_HELP_USAGE6);
  419. }
  420. } /* Usage() */