fixed some signed/unsigned comparison warnings with -Wsign-compare
[reactos.git] / reactos / subsys / system / sm / sm.c
1 /*
2 * ReactOS Win32 Applications
3 * Copyright (C) 2005 ReactOS Team
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 /* $Id$
20 *
21 * COPYRIGHT : See COPYING in the top level directory
22 * PROJECT : ReactOS/Win32 Session Manager Control Tool
23 * FILE : subsys/system/sm/sm.c
24 * PROGRAMMER: Emanuele Aliberti (ea@reactos.com)
25 */
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <tchar.h>
30 #include "resource.h"
31
32 #include <windows.h>
33 #define NTOS_MODE_USER
34 #include <ndk/ntndk.h>
35
36 #include <sm/helper.h>
37
38 #define SM_CMD(n) cmd_##n
39 #define SM_CMD_DECL(n) int SM_CMD(n)(int argc, char * argv[])
40 #define SM_CMD_CALL(n,c,v) SM_CMD(n)((c),(v))
41
42 HANDLE hSmApiPort = (HANDLE) 0;
43
44 typedef struct _SM_CMD_DESCRIPTOR
45 {
46 TCHAR Name[RC_STRING_MAX_SIZE];
47 int (*EntryPoint)(int,TCHAR**);
48 TCHAR Synopsis[RC_STRING_MAX_SIZE];
49 TCHAR Description[RC_STRING_MAX_SIZE];
50
51 } SM_CMD_DESCRIPTOR, *PSM_CMD_DESCRIPTOR;
52
53 SM_CMD_DECL(boot);
54 SM_CMD_DECL(help);
55 SM_CMD_DECL(info);
56 SM_CMD_DECL(reboot);
57 SM_CMD_DECL(shutdown);
58
59 /* internal commands directory */
60 SM_CMD_DESCRIPTOR Command [] =
61 {
62 {"boot", SM_CMD(boot), _T("boot subsystem_name"), _T("bootstrap an optional environment subsystem;")},
63 {"help", SM_CMD(help), _T("help [command]"), _T("print help for command;")},
64 {"info", SM_CMD(info), _T("info [subsystem_id]"), _T("print information about a booted subsystem\n"
65 "if subsystem_id is omitted, a list of booted\n"
66 "environment subsystems is printed.")},
67 {"reboot", SM_CMD(reboot), _T("reboot subsystem_id"), _T("reboot an optional environment subsystem;")},
68 {"shutdown", SM_CMD(shutdown), _T("shutdown subsystem_id"), _T("shutdown an optional environment subsystem;")},
69 };
70
71 TCHAR UsageMessage[RC_STRING_MAX_SIZE];
72 void loadlang(PSM_CMD_DESCRIPTOR );
73
74 PSM_CMD_DESCRIPTOR LookupCommand (const TCHAR * CommandName)
75 {
76 int i;
77 const int command_count = (sizeof Command / sizeof Command[0]);
78
79 /* parse the command... */
80
81 for (i=0; (i < command_count); i ++)
82 {
83 if (0 == _tcscmp(CommandName, Command[i].Name))
84 {
85 break;
86 }
87 }
88 if (i == command_count)
89 {
90 LoadString( GetModuleHandle(NULL), IDS_Unknown, (LPTSTR) UsageMessage,RC_STRING_MAX_SIZE);
91
92 _ftprintf(stderr, _T("%s '%s'.\n"), UsageMessage, CommandName);
93 return NULL;
94 }
95 return & Command [i];
96 }
97
98 /* user commands */
99
100 SM_CMD_DECL(boot)
101 {
102 int rc = EXIT_SUCCESS;
103 ANSI_STRING ProgramA;
104 UNICODE_STRING ProgramW;
105 NTSTATUS Status = STATUS_SUCCESS;
106
107 if (3 == argc)
108 {
109 #ifndef _UNICODE
110 RtlInitAnsiString (& ProgramA, argv[2]);
111 RtlAnsiStringToUnicodeString (& ProgramW, & ProgramA, TRUE);
112 Status = SmExecuteProgram (hSmApiPort, & ProgramW);
113 RtlFreeUnicodeString (& ProgramW);
114 #else
115 ProgramW = &argv[2];
116 Status = SmExecuteProgram (hSmApiPort, & ProgramW);
117 #endif
118 if (STATUS_SUCCESS != Status)
119 {
120 LoadString( GetModuleHandle(NULL), IDS_Status, (LPTSTR) UsageMessage,RC_STRING_MAX_SIZE);
121
122 _tprintf(UsageMessage, Status);
123 }
124
125 }
126 else
127 {
128 argv[2]=_T("boot");
129 return SM_CMD_CALL(help,3,argv);
130 }
131 return rc;
132 }
133
134 SM_CMD_DECL(help)
135 {
136 unsigned int i = 0;
137 PSM_CMD_DESCRIPTOR cmd = NULL;
138 int rc = EXIT_SUCCESS;
139
140 switch (argc)
141 {
142 case 2:
143 for (i=0; (i < (sizeof Command / sizeof Command[0])); i ++)
144 {
145 _tprintf(_T("%s\n"), Command[i].Synopsis);
146 }
147 break;
148 case 3:
149 cmd = LookupCommand (argv[2]);
150 if (NULL == cmd)
151 {
152 rc = EXIT_FAILURE;
153 break;
154 }
155 _tprintf(_T("%s\n%s\n\n%s\n"),
156 cmd->Name,
157 cmd->Synopsis,
158 cmd->Description);
159 break;
160 }
161 return rc;
162 }
163
164 SM_CMD_DECL(info)
165 {
166 int rc = EXIT_SUCCESS;
167 NTSTATUS Status = STATUS_SUCCESS;
168 SM_INFORMATION_CLASS InformationClass = SmBasicInformation;
169 union {
170 SM_BASIC_INFORMATION bi;
171 SM_SUBSYSTEM_INFORMATION ssi;
172 } Info;
173 ULONG DataLength = 0;
174 ULONG ReturnDataLength = 0;
175 INT i = 0;
176
177 RtlZeroMemory (& Info, sizeof Info);
178 switch (argc)
179 {
180 case 2: /* sm info */
181 InformationClass = SmBasicInformation;
182 DataLength = sizeof Info.bi;
183 break;
184 case 3: /* sm info id */
185 InformationClass = SmSubSystemInformation;
186 DataLength = sizeof Info.ssi;
187 Info.ssi.SubSystemId = atol(argv[2]);
188 break;
189 default:
190 return EXIT_FAILURE;
191 break;
192 }
193 Status = SmQueryInformation (hSmApiPort,
194 InformationClass,
195 & Info,
196 DataLength,
197 & ReturnDataLength);
198 if (STATUS_SUCCESS != Status)
199 {
200 LoadString( GetModuleHandle(NULL), IDS_Status, (LPTSTR) UsageMessage,RC_STRING_MAX_SIZE);
201 _tprintf(UsageMessage, Status);
202 return EXIT_FAILURE;
203 }
204 switch (argc)
205 {
206 case 2:
207 LoadString( GetModuleHandle(NULL), IDS_SM1, (LPTSTR) UsageMessage,RC_STRING_MAX_SIZE);
208 _tprintf(UsageMessage);
209
210 LoadString( GetModuleHandle(NULL), IDS_SM2, (LPTSTR) UsageMessage,RC_STRING_MAX_SIZE);
211 for (i = 0; i < Info.bi.SubSystemCount; i ++)
212 {
213 _tprintf(UsageMessage,
214 Info.bi.SubSystem[i].Id,
215 Info.bi.SubSystem[i].ProcessId,
216 Info.bi.SubSystem[i].Flags);
217 }
218 break;
219 case 3:
220 LoadString( GetModuleHandle(NULL), IDS_ID, (LPTSTR) UsageMessage,RC_STRING_MAX_SIZE);
221
222 _tprintf (UsageMessage, Info.ssi.SubSystemId, Info.ssi.Flags, Info.ssi.ProcessId);
223 wprintf(L" NSRootNode: '%s'\n", Info.ssi.NameSpaceRootNode);
224 break;
225 default:
226 break;
227 }
228 return rc;
229 }
230
231 SM_CMD_DECL(shutdown)
232 {
233 int rc = EXIT_SUCCESS;
234
235 LoadString( GetModuleHandle(NULL), IDS_Not_Imp, (LPTSTR) UsageMessage,RC_STRING_MAX_SIZE);
236
237 _ftprintf(stderr,UsageMessage);
238 return rc;
239 }
240
241 SM_CMD_DECL(reboot)
242 {
243 int rc = SM_CMD(shutdown)(argc,argv);
244 if(EXIT_SUCCESS == rc)
245 {
246 rc = SM_CMD(boot)(argc,argv);
247 }
248 return rc;
249 }
250
251 /* print command's synopsys */
252 int print_synopsys (int argc, TCHAR *argv[])
253 {
254 LoadString( GetModuleHandle(NULL), IDS_Mangers, (LPTSTR) UsageMessage,RC_STRING_MAX_SIZE);
255 _ftprintf (stderr, UsageMessage);
256
257 LoadString( GetModuleHandle(NULL), IDS_USING, (LPTSTR) UsageMessage,RC_STRING_MAX_SIZE);
258 _tprintf (UsageMessage);
259 return EXIT_SUCCESS;
260 }
261
262 /* parse and execute */
263 int pande (int argc, TCHAR *argv[])
264 {
265 PSM_CMD_DESCRIPTOR Command = NULL;
266 NTSTATUS Status = STATUS_SUCCESS;
267
268 /* Lookup the user command... */
269 Command = LookupCommand (argv[1]);
270 if (NULL == Command)
271 {
272 return EXIT_FAILURE;
273 }
274 /* Connect to the SM in non-registering mode. */
275 Status = SmConnectApiPort (0, 0, 0, & hSmApiPort);
276 if (STATUS_SUCCESS == Status)
277 {
278 /* ...and execute it */
279 return Command->EntryPoint (argc, argv);
280 }
281 LoadString( GetModuleHandle(NULL), IDS_FAILS_MNG, (LPTSTR) UsageMessage,RC_STRING_MAX_SIZE);
282 _ftprintf (stderr, UsageMessage, Status);
283
284 return EXIT_FAILURE;
285 }
286
287 void loadlang(PSM_CMD_DESCRIPTOR cmd)
288 {
289 int i=0;
290 if (cmd==NULL) return;
291 for (i=0;i < 5; i++)
292 {
293 LoadString( GetModuleHandle(NULL), IDS_boot+i, (LPTSTR) &cmd->Synopsis[i],RC_STRING_MAX_SIZE);
294 }
295 }
296
297 int _tmain (int argc, TCHAR *argv[])
298 {
299 loadlang(Command);
300
301 return (1==argc)
302 ? print_synopsys (argc, argv)
303 : pande (argc, argv);
304 }
305 /* EOF */