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