Added new Service Control utitlity.
[reactos.git] / reactos / apps / utils / sc / main.c
1 /*
2 * ReactOS SC - service control console program
3 *
4 * main.c
5 *
6 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include <windows.h>
24 #include <tchar.h>
25 #include "main.h"
26
27
28 #define VERSION 1
29
30 #ifdef UNICODE
31 #define TARGET "UNICODE"
32 #else
33 #define TARGET "MBCS"
34 #endif
35
36 BOOL verbose_flagged = 0;
37 BOOL status_flagged = 0;
38
39 HANDLE OutputHandle;
40 HANDLE InputHandle;
41
42
43 void dprintf(char* fmt, ...)
44 {
45 va_list args;
46 char buffer[255];
47
48 va_start(args, fmt);
49 wvsprintfA(buffer, fmt, args);
50 WriteConsoleA(OutputHandle, buffer, lstrlenA(buffer), NULL, NULL);
51 va_end(args);
52 }
53
54 long getinput(char* buf, int buflen)
55 {
56 DWORD result;
57
58 ReadConsoleA(InputHandle, buf, buflen, &result, NULL);
59 return (long)result;
60 }
61
62 DWORD ReportLastError(void)
63 {
64 DWORD dwError = GetLastError();
65 if (dwError != ERROR_SUCCESS) {
66 PTSTR msg = NULL;
67 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
68 0, dwError, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (PTSTR)&msg, 0, NULL)) {
69 if (msg != NULL) {
70 dprintf("ReportLastError() %d - %s\n", dwError, msg);
71 } else {
72 dprintf("ERROR: ReportLastError() %d - returned TRUE but with no msg string!\n", dwError);
73 }
74 } else {
75 dprintf("ReportLastError() %d - unknown error\n", dwError);
76 }
77 if (msg != NULL) {
78 LocalFree(msg);
79 }
80 }
81 return dwError;
82 }
83
84 int usage(char* argv0)
85 {
86 dprintf("DESCRIPTION:\n");
87 dprintf("\tSC is a command line program used for communicating with\n");
88 dprintf("\tthe Service Control Manager and its services.\n");
89 dprintf("USAGE:\n");
90 dprintf("\tsc <server> [command] [service name] <option1> <option2>...\n");
91
92 dprintf("\tThe optional parameter <server> has the form \"\\ServerName\"\n");
93 dprintf("\tFurther help on commands can be obtained by typing: \"sc [command]\"\n");
94 dprintf("\tService Commands:\n");
95 dprintf("\t query : Queries the status for a service, or\n");
96 dprintf("\t enumerates the status for types of services.\n");
97 dprintf("\t queryex : Queries the extended status for a service, or\n");
98 dprintf("\t enumerates the status for types of services.\n");
99 dprintf("\t start : Starts a service.\n");
100 dprintf("\t pause : Sends a PAUSE control request to a service.\n");
101 dprintf("\t interrogate : Sends a INTERROGATE control request to a service.\n");
102 dprintf("\t continue : Sends a CONTINUE control request to a service.\n");
103 dprintf("\t stop : Sends a STOP request to a service.\n");
104 dprintf("\t config : Changes the configuration of a service (persistant).\n");
105 dprintf("\t description : Changes the description of a service.\n");
106 dprintf("\t failure : Changes the actions taken by a service upon failure.\n");
107 dprintf("\t qc : Queries the configuration information for a service.\n");
108 dprintf("\t qdescription : Queries the description for a service.\n");
109 dprintf("\t qfailure : Queries the actions taken by a service upon failure.\n");
110 dprintf("\t delete : Deletes a service (from the registry).\n");
111 dprintf("\t create : Creates a service. (adds it to the registry).\n");
112 dprintf("\t control : Sends a control to a service.\n");
113 // dprintf("\t sdshow : Displays a service's security descriptor.\n");
114 // dprintf("\t sdset : Sets a service's security descriptor.\n");
115 dprintf("\t GetDisplayName : Gets the DisplayName for a service.\n");
116 dprintf("\t GetKeyName : Gets the ServiceKeyName for a service.\n");
117 dprintf("\t EnumDepend : Enumerates Service Dependencies.\n");
118 dprintf("\n");
119 dprintf("\tService Name Independant Commands:\n");
120 dprintf("\t boot : (ok | bad) Indicates whether the last boot should\n");
121 dprintf("\t be saved as the last-known-good boot configuration\n");
122 dprintf("\t Lock : Locks the SCM Database\n");
123 dprintf("\t QueryLock : Queries the LockStatus for the SCM Database\n");
124
125 return 0;
126 }
127
128
129 typedef int (*sc_cmd_proc)(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[]);
130
131 typedef struct {
132 SC_CMDS sc_cmd;
133 const char* cmd_str;
134 sc_cmd_proc funcptr;
135 DWORD dwDesiredAccess;
136 } sc_cmd_entry;
137
138 sc_cmd_entry sc_cmds_table[] = {
139 { SC_CMD_QUERY, "query", sc_query, SC_MANAGER_ALL_ACCESS },
140 { SC_CMD_QUERYEX, "queryex", sc_query, SC_MANAGER_ALL_ACCESS },
141 { SC_CMD_START, "start", sc_command, 0L },
142 { SC_CMD_PAUSE, "pause", sc_command, 0L },
143 { SC_CMD_INTERROGATE, "interrogate", sc_command, 0L },
144 { SC_CMD_CONTINUE, "continue", sc_command, 0L },
145 { SC_CMD_STOP, "stop", sc_command, 0L },
146 { SC_CMD_CONFIG, "config", sc_setup, 0L },
147 { SC_CMD_DESCRIPTION, "description", sc_setup, 0L },
148 { SC_CMD_FAILURE, "failure", sc_setup, 0L },
149 { SC_CMD_QC, "qc", sc_query, 0L },
150 { SC_CMD_QDESCRIPTION, "qdescription", sc_query, 0L },
151 { SC_CMD_QFAILURE, "qfailure", sc_query, 0L },
152 { SC_CMD_DELETE, "delete", sc_setup, 0L },
153 { SC_CMD_CREATE, "create", sc_setup, 0L },
154 { SC_CMD_CONTROL, "control", sc_setup, 0L },
155 { SC_CMD_SDSHOW, "sdshow", sc_query, 0L },
156 { SC_CMD_SDSET, "sdset", sc_setup, 0L },
157 { SC_CMD_GETDISPLAYNAME, "GetDisplayName", sc_query, 0L },
158 { SC_CMD_GETKEYNAME, "GetKeyName", sc_query, 0L },
159 { SC_CMD_ENUMDEPEND, "EnumDepend", sc_query, 0L },
160 { SC_CMD_BOOT, "boot", sc_config, 0L },
161 { SC_CMD_LOCK, "Lock", sc_config, 0L },
162 { SC_CMD_QUERYLOCK, "QueryLock", sc_config, 0L }
163 };
164
165
166 int sc_main(const sc_cmd_entry* cmd_entry,
167 const char* sc_machine_name,
168 char* sc_cmd_arg[])
169 {
170 int result = 1;
171 SC_HANDLE hSCManager;
172 DWORD dwDesiredAccess;
173
174 dprintf("sc_main(%s) - called.\n", cmd_entry->cmd_str);
175 if (sc_machine_name) {
176 dprintf("remote service control not yet implemented.\n");
177 return 2;
178 }
179 dwDesiredAccess = cmd_entry->dwDesiredAccess;
180 if (!dwDesiredAccess) dwDesiredAccess = SC_MANAGER_CONNECT + GENERIC_READ;
181
182 hSCManager = OpenSCManagerA(sc_machine_name, NULL, dwDesiredAccess);
183 if (hSCManager != NULL) {
184 result = cmd_entry->funcptr(hSCManager, cmd_entry->sc_cmd, sc_cmd_arg);
185 if (!CloseServiceHandle(hSCManager)) {
186 dprintf("Failed to CLOSE handle to SCM.\n");
187 ReportLastError();
188 }
189 } else {
190 dprintf("Failed to open Service Control Manager.\n");
191 ReportLastError();
192 }
193 return result;
194 }
195
196
197 int __cdecl main(int argc, char* argv[])
198 {
199 int i;
200 const char* sc_machine_name = NULL;
201 const char* sc_cmd_str = argv[1];
202 char** sc_cmd_arg = NULL;
203
204 AllocConsole();
205 InputHandle = GetStdHandle(STD_INPUT_HANDLE);
206 OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
207
208 dprintf("%s application - build %03d (default: %s)\n", argv[0], VERSION, TARGET);
209 if (argc < 2) {
210 return usage(argv[0]);
211 }
212
213 if ((argv[1][0] == '\\') && (argv[1][1] == '\\')) {
214 if (argc < 3) {
215 return usage(argv[0]);
216 }
217 sc_machine_name = argv[1];
218 sc_cmd_str = argv[2];
219 sc_cmd_arg = &argv[3];
220 } else {
221 sc_machine_name = NULL;
222 sc_cmd_str = argv[1];
223 sc_cmd_arg = &argv[2];
224 }
225
226 for (i = 0; i < sizeof(sc_cmds_table)/sizeof(sc_cmd_entry); i++) {
227 sc_cmd_entry* cmd_entry = &(sc_cmds_table[i]);
228 if (lstrcmpiA(sc_cmd_str, cmd_entry->cmd_str) == 0) {
229 return sc_main(cmd_entry, sc_machine_name, sc_cmd_arg);
230 }
231 }
232 return usage(argv[0]);
233 }
234
235
236 #ifdef _NOCRT
237
238 //char* args[] = { "sc.exe", "pause", "smplserv" };
239 char* args[] = { "sc.exe", "EnumDepend", "" };
240
241 int __cdecl mainCRTStartup(void)
242 {
243 main(3, args);
244 return 0;
245 }
246
247 #endif /*_NOCRT*/