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.

313 lines
7.6 KiB

  1. /*************************************************************************
  2. *
  3. * shadow.c
  4. *
  5. * Shadow utility
  6. *
  7. * Copyright 1994, Citrix Systems Inc.
  8. *
  9. * Copyright (c) 1998 - 1999 Microsoft Corporation
  10. *
  11. * $Author: tyl $ Mike Discavage
  12. *
  13. * $Log: N:\nt\private\utils\citrix\shadow\VCS\shadow.c $
  14. *
  15. * Rev 1.20 May 04 1998 17:37:40 tyl
  16. * bug 2019 - oem to ansi
  17. *
  18. * Rev 1.19 Jun 26 1997 18:25:40 billm
  19. * move to WF40 tree
  20. *
  21. * Rev 1.18 23 Jun 1997 15:39:22 butchd
  22. * update
  23. *
  24. * Rev 1.17 15 Feb 1997 15:57:34 miked
  25. * update
  26. *
  27. * Rev 1.16 07 Feb 1997 15:56:54 bradp
  28. * update
  29. *
  30. * Rev 1.15 13 Nov 1996 17:14:40 miked
  31. * update
  32. *
  33. * Rev 1.14 30 Sep 1996 08:34:28 butchd
  34. * update
  35. *
  36. * Rev 1.13 11 Sep 1996 09:21:44 bradp
  37. * update
  38. *
  39. *
  40. *************************************************************************/
  41. #define NT
  42. /*
  43. * Includes
  44. */
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <locale.h>
  49. #include <windows.h>
  50. #include <winnlsp.h>
  51. // #include <ntddkbd.h>
  52. // #include <ntddmou.h>
  53. #include <winsta.h>
  54. #include <utilsub.h>
  55. #include <kbd.h> // for KBDCTRL KLB 07-15-95
  56. #include "shadow.h"
  57. #include "printfoa.h"
  58. // max length of the locale string
  59. #define MAX_LOCALE_STRING 64
  60. /*
  61. * Global variables
  62. */
  63. USHORT help_flag = FALSE;
  64. USHORT v_flag = FALSE;
  65. WINSTATIONNAME WSName;
  66. ULONG LogonId;
  67. ULONG Timeout; // timeout in seconds
  68. HANDLE hServerName = SERVERNAME_CURRENT;
  69. WCHAR ServerName[MAX_NAME+1];
  70. TOKMAP ptm[] = {
  71. {TOKEN_WS, TMFLAG_REQUIRED, TMFORM_STRING,
  72. WINSTATIONNAME_LENGTH, WSName },
  73. {TOKEN_SERVER, TMFLAG_OPTIONAL, TMFORM_STRING,
  74. MAX_NAME, ServerName },
  75. {TOKEN_TIMEOUT, TMFLAG_OPTIONAL, TMFORM_ULONG,
  76. sizeof(ULONG), &Timeout },
  77. {TOKEN_VERBOSE, TMFLAG_OPTIONAL, TMFORM_BOOLEAN,
  78. sizeof(USHORT), &v_flag },
  79. {TOKEN_HELP, TMFLAG_OPTIONAL, TMFORM_BOOLEAN,
  80. sizeof(USHORT), &help_flag },
  81. {0, 0, 0, 0, 0}
  82. };
  83. /*
  84. * Private function prototypes.
  85. */
  86. void Usage(BOOLEAN bError);
  87. /*******************************************************************************
  88. *
  89. * main
  90. *
  91. ******************************************************************************/
  92. int __cdecl
  93. main( INT argc, CHAR **argv )
  94. {
  95. WCHAR *CmdLine;
  96. WCHAR **argvW, *endptr;
  97. ULONG rc;
  98. int i;
  99. BOOLEAN Result;
  100. WCHAR wszString[MAX_LOCALE_STRING + 1];
  101. setlocale(LC_ALL, ".OCP");
  102. // We don't want LC_CTYPE set the same as the others or else we will see
  103. // garbage output in the localized version, so we need to explicitly
  104. // set it to correct console output code page
  105. _snwprintf(wszString, sizeof(wszString)/sizeof(WCHAR), L".%d", GetConsoleOutputCP());
  106. wszString[sizeof(wszString)/sizeof(WCHAR) - 1] = L'\0';
  107. _wsetlocale(LC_CTYPE, wszString);
  108. SetThreadUILanguage(0);
  109. /*
  110. * Massage the command line.
  111. */
  112. argvW = MassageCommandLine((DWORD)argc);
  113. if (argvW == NULL) {
  114. ErrorPrintf(IDS_ERROR_MALLOC);
  115. return(FAILURE);
  116. }
  117. /*
  118. * parse the cmd line without parsing the program name (argc-1, argv+1)
  119. */
  120. rc = ParseCommandLine(argc-1, argvW+1, ptm, 0);
  121. /*
  122. * Check for error from ParseCommandLine
  123. */
  124. if ( help_flag || rc ) {
  125. if ( !help_flag ) {
  126. Usage(TRUE);
  127. return(FAILURE);
  128. } else {
  129. Usage(FALSE);
  130. return(SUCCESS);
  131. }
  132. }
  133. //Check if we are running under Terminal Server
  134. if(!AreWeRunningTerminalServices())
  135. {
  136. ErrorPrintf(IDS_ERROR_NOT_TS);
  137. return(FAILURE);
  138. }
  139. /*
  140. * Open the specified server
  141. */
  142. if( ServerName[0] ) {
  143. hServerName = WinStationOpenServer( ServerName );
  144. if( hServerName == NULL ) {
  145. StringErrorPrintf(IDS_ERROR_SERVER,ServerName);
  146. PutStdErr( GetLastError(), 0 );
  147. return(FAILURE);
  148. }
  149. }
  150. /*
  151. * Validate the shadowee.
  152. */
  153. if ( !iswdigit(*WSName) ) {
  154. /*
  155. * Treat the entered string as a WinStation name.
  156. *
  157. */
  158. if ( !LogonIdFromWinStationName(hServerName, WSName, &LogonId) ) {
  159. StringErrorPrintf(IDS_ERROR_WINSTATION_NOT_FOUND, WSName);
  160. return(FAILURE);
  161. }
  162. Message(IDS_SHADOWING_WARNING);
  163. if ( v_flag )
  164. StringMessage(IDS_SHADOWING_WINSTATION, WSName);
  165. } else {
  166. /*
  167. * Treated the entered string as a LogonId.
  168. */
  169. LogonId = wcstoul(WSName, &endptr, 10);
  170. if ( *endptr ) {
  171. StringErrorPrintf(IDS_ERROR_INVALID_LOGONID, WSName);
  172. return(FAILURE);
  173. }
  174. if ( !WinStationNameFromLogonId(hServerName, LogonId, WSName) ) {
  175. ErrorPrintf(IDS_ERROR_LOGONID_NOT_FOUND, LogonId);
  176. return(FAILURE);
  177. }
  178. Message(IDS_SHADOWING_WARNING);
  179. if ( v_flag )
  180. Message(IDS_SHADOWING_LOGONID, LogonId);
  181. }
  182. // Let the warning be displayed
  183. Sleep(500);
  184. /*
  185. * Start shadowing.
  186. */
  187. if ( IsTokenPresent(ptm, TOKEN_TIMEOUT) ) {
  188. Result = WinStationShadow( SERVERNAME_CURRENT,
  189. ServerName,
  190. LogonId,
  191. (BYTE)Timeout,
  192. (WORD)-1);
  193. } else {
  194. Result = WinStationShadow( SERVERNAME_CURRENT,
  195. ServerName,
  196. LogonId,
  197. VK_MULTIPLY,
  198. KBDCTRL ); // ctrl-*
  199. }
  200. /*
  201. * Return success or failure.
  202. */
  203. if ( !Result ) {
  204. ErrorPrintf(IDS_ERROR_SHADOW_FAILURE, GetLastError());
  205. PutStdErr( GetLastError(), 0 );
  206. return(FAILURE);
  207. } else {
  208. if ( v_flag )
  209. Message(IDS_SHADOWING_DONE);
  210. return(SUCCESS);
  211. }
  212. } /* main() */
  213. /*******************************************************************************
  214. *
  215. * Usage
  216. *
  217. * Output the usage message for this utility.
  218. *
  219. * ENTRY:
  220. * bError (input)
  221. * TRUE if the 'invalid parameter(s)' message should preceed the usage
  222. * message and the output go to stderr; FALSE for no such error
  223. * string and output goes to stdout.
  224. *
  225. * EXIT:
  226. *
  227. *
  228. ******************************************************************************/
  229. void
  230. Usage( BOOLEAN bError )
  231. {
  232. if ( bError ) {
  233. ErrorPrintf(IDS_ERROR_INVALID_PARAMETERS);
  234. ErrorPrintf(IDS_USAGE_1);
  235. ErrorPrintf(IDS_USAGE_2);
  236. ErrorPrintf(IDS_USAGE_3);
  237. ErrorPrintf(IDS_USAGE_4);
  238. ErrorPrintf(IDS_USAGE_5);
  239. ErrorPrintf(IDS_USAGE_6);
  240. ErrorPrintf(IDS_USAGE_7);
  241. ErrorPrintf(IDS_USAGE_8);
  242. ErrorPrintf(IDS_USAGE_9);
  243. } else {
  244. Message(IDS_USAGE_1);
  245. Message(IDS_USAGE_2);
  246. Message(IDS_USAGE_3);
  247. Message(IDS_USAGE_4);
  248. Message(IDS_USAGE_5);
  249. Message(IDS_USAGE_6);
  250. Message(IDS_USAGE_7);
  251. Message(IDS_USAGE_8);
  252. Message(IDS_USAGE_9);
  253. }
  254. } /* Usage() */