Leaked source code of windows server 2003
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.

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