Partial merge of the condrv_restructure branch, including:
[reactos.git] / reactos / base / applications / sc / create.c
1 /*
2 * PROJECT: ReactOS Services
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/sc/create.c
5 * PURPOSE: Create a service
6 * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com>
7 * Roel Messiant <roelmessiant@gmail.com>
8 *
9 */
10
11 #include "sc.h"
12
13 typedef struct
14 {
15 LPCTSTR lpOption;
16 DWORD dwValue;
17 } OPTION_INFO;
18
19 typedef struct
20 {
21 LPCTSTR lpServiceName;
22 LPCTSTR lpDisplayName;
23 DWORD dwServiceType;
24 DWORD dwStartType;
25 DWORD dwErrorControl;
26 LPCTSTR lpBinaryPathName;
27 LPCTSTR lpLoadOrderGroup;
28 DWORD dwTagId;
29 LPCTSTR lpDependencies;
30 LPCTSTR lpServiceStartName;
31 LPCTSTR lpPassword;
32
33 BOOL bTagId;
34 } SERVICE_CREATE_INFO, *LPSERVICE_CREATE_INFO;
35
36
37 static const OPTION_INFO TypeOpts[] =
38 {
39 { _T("own"), SERVICE_WIN32_OWN_PROCESS },
40 { _T("share"), SERVICE_WIN32_SHARE_PROCESS },
41 { _T("interact"), SERVICE_INTERACTIVE_PROCESS },
42 { _T("kernel"), SERVICE_KERNEL_DRIVER },
43 { _T("filesys"), SERVICE_FILE_SYSTEM_DRIVER },
44 { _T("rec"), SERVICE_RECOGNIZER_DRIVER }
45 };
46
47 static const OPTION_INFO StartOpts[] =
48 {
49 { _T("boot"), SERVICE_BOOT_START },
50 { _T("system"), SERVICE_SYSTEM_START },
51 { _T("auto"), SERVICE_AUTO_START },
52 { _T("demand"), SERVICE_DEMAND_START },
53 { _T("disabled"), SERVICE_DISABLED }
54 };
55
56 static const OPTION_INFO ErrorOpts[] =
57 {
58 { _T("normal"), SERVICE_ERROR_NORMAL },
59 { _T("severe"), SERVICE_ERROR_SEVERE },
60 { _T("critical"), SERVICE_ERROR_CRITICAL },
61 { _T("ignore"), SERVICE_ERROR_IGNORE }
62 };
63
64 static const OPTION_INFO TagOpts[] =
65 {
66 { _T("yes"), TRUE },
67 { _T("no"), FALSE }
68 };
69
70
71 static BOOL ParseCreateArguments(
72 LPCTSTR *ServiceArgs,
73 INT ArgCount,
74 OUT LPSERVICE_CREATE_INFO lpServiceInfo
75 )
76 {
77 INT i, ArgIndex = 1;
78
79 if (ArgCount < 1)
80 return FALSE;
81
82 ZeroMemory(lpServiceInfo, sizeof(SERVICE_CREATE_INFO));
83
84 lpServiceInfo->lpServiceName = ServiceArgs[0];
85
86 ArgCount--;
87
88 while (ArgCount > 1)
89 {
90 if (!lstrcmpi(ServiceArgs[ArgIndex], _T("type=")))
91 {
92 for (i = 0; i < sizeof(TypeOpts) / sizeof(TypeOpts[0]); i++)
93 if (!lstrcmpi(ServiceArgs[ArgIndex + 1], TypeOpts[i].lpOption))
94 {
95 lpServiceInfo->dwServiceType |= TypeOpts[i].dwValue;
96 break;
97 }
98
99 if (i == sizeof(TypeOpts) / sizeof(TypeOpts[0]))
100 break;
101 }
102 else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("start=")))
103 {
104 for (i = 0; i < sizeof(StartOpts) / sizeof(StartOpts[0]); i++)
105 if (!lstrcmpi(ServiceArgs[ArgIndex + 1], StartOpts[i].lpOption))
106 {
107 lpServiceInfo->dwStartType = StartOpts[i].dwValue;
108 break;
109 }
110
111 if (i == sizeof(StartOpts) / sizeof(StartOpts[0]))
112 break;
113 }
114 else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("error=")))
115 {
116 for (i = 0; i < sizeof(ErrorOpts) / sizeof(ErrorOpts[0]); i++)
117 if (!lstrcmpi(ServiceArgs[ArgIndex + 1], ErrorOpts[i].lpOption))
118 {
119 lpServiceInfo->dwErrorControl = ErrorOpts[i].dwValue;
120 break;
121 }
122
123 if (i == sizeof(ErrorOpts) / sizeof(ErrorOpts[0]))
124 break;
125 }
126 else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("tag=")))
127 {
128 for (i = 0; i < sizeof(TagOpts) / sizeof(TagOpts[0]); i++)
129 if (!lstrcmpi(ServiceArgs[ArgIndex + 1], TagOpts[i].lpOption))
130 {
131 lpServiceInfo->bTagId = TagOpts[i].dwValue;
132 break;
133 }
134
135 if (i == sizeof(TagOpts) / sizeof(TagOpts[0]))
136 break;
137 }
138 else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("binpath=")))
139 {
140 lpServiceInfo->lpBinaryPathName = ServiceArgs[ArgIndex + 1];
141 }
142 else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("group=")))
143 {
144 lpServiceInfo->lpLoadOrderGroup = ServiceArgs[ArgIndex + 1];
145 }
146 else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("depend=")))
147 {
148 lpServiceInfo->lpDependencies = ServiceArgs[ArgIndex + 1];
149 }
150 else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("obj=")))
151 {
152 lpServiceInfo->lpServiceStartName = ServiceArgs[ArgIndex + 1];
153 }
154 else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("displayname=")))
155 {
156 lpServiceInfo->lpDisplayName = ServiceArgs[ArgIndex + 1];
157 }
158 else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("password=")))
159 {
160 lpServiceInfo->lpPassword = ServiceArgs[ArgIndex + 1];
161 }
162
163 ArgIndex += 2;
164 ArgCount -= 2;
165 }
166
167 return (ArgCount == 0);
168 }
169
170 BOOL Create(LPCTSTR *ServiceArgs, INT ArgCount)
171 {
172 SC_HANDLE hSCManager;
173 SC_HANDLE hSc;
174 BOOL bRet = FALSE;
175
176 INT i;
177 INT Length;
178 LPTSTR lpBuffer = NULL;
179 SERVICE_CREATE_INFO ServiceInfo;
180
181 if (!ParseCreateArguments(ServiceArgs, ArgCount, &ServiceInfo))
182 {
183 CreateUsage();
184 return FALSE;
185 }
186
187 if (!ServiceInfo.dwServiceType)
188 ServiceInfo.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
189
190 if (!ServiceInfo.dwStartType)
191 ServiceInfo.dwStartType = SERVICE_DEMAND_START;
192
193 if (!ServiceInfo.dwErrorControl)
194 ServiceInfo.dwErrorControl = SERVICE_ERROR_NORMAL;
195
196 if (ServiceInfo.lpDependencies)
197 {
198 Length = lstrlen(ServiceInfo.lpDependencies);
199
200 lpBuffer = HeapAlloc(GetProcessHeap(),
201 0,
202 (Length + 2) * sizeof(TCHAR));
203
204 for (i = 0; i < Length; i++)
205 if (ServiceInfo.lpDependencies[i] == _T('/'))
206 lpBuffer[i] = 0;
207 else
208 lpBuffer[i] = ServiceInfo.lpDependencies[i];
209
210 lpBuffer[Length] = 0;
211 lpBuffer[Length + 1] = 0;
212
213 ServiceInfo.lpDependencies = lpBuffer;
214 }
215
216 #ifdef SCDBG
217 _tprintf(_T("service name - %s\n"), ServiceInfo.lpServiceName);
218 _tprintf(_T("display name - %s\n"), ServiceInfo.lpDisplayName);
219 _tprintf(_T("service type - %lu\n"), ServiceInfo.dwServiceType);
220 _tprintf(_T("start type - %lu\n"), ServiceInfo.dwStartType);
221 _tprintf(_T("error control - %lu\n"), ServiceInfo.dwErrorControl);
222 _tprintf(_T("Binary path - %s\n"), ServiceInfo.lpBinaryPathName);
223 _tprintf(_T("load order group - %s\n"), ServiceInfo.lpLoadOrderGroup);
224 _tprintf(_T("tag - %lu\n"), ServiceInfo.dwTagId);
225 _tprintf(_T("dependencies - %s\n"), ServiceInfo.lpDependencies);
226 _tprintf(_T("account start name - %s\n"), ServiceInfo.lpServiceStartName);
227 _tprintf(_T("account password - %s\n"), ServiceInfo.lpPassword);
228 #endif
229
230 hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
231
232 if (hSCManager != NULL)
233 {
234 hSc = CreateService(hSCManager,
235 ServiceInfo.lpServiceName,
236 ServiceInfo.lpDisplayName,
237 SERVICE_ALL_ACCESS,
238 ServiceInfo.dwServiceType,
239 ServiceInfo.dwStartType,
240 ServiceInfo.dwErrorControl,
241 ServiceInfo.lpBinaryPathName,
242 ServiceInfo.lpLoadOrderGroup,
243 ServiceInfo.bTagId ? &ServiceInfo.dwTagId : NULL,
244 ServiceInfo.lpDependencies,
245 ServiceInfo.lpServiceStartName,
246 ServiceInfo.lpPassword);
247
248 if (hSc != NULL)
249 {
250 _tprintf(_T("[SC] CreateService SUCCESS\n"));
251
252 CloseServiceHandle(hSc);
253 bRet = TRUE;
254 }
255 else
256 ReportLastError();
257
258 CloseServiceHandle(hSCManager);
259 }
260 else
261 ReportLastError();
262
263 if (lpBuffer != NULL)
264 HeapFree(GetProcessHeap(), 0, lpBuffer);
265
266 return bRet;
267 }