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