~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/programs/svchost/svchost.c

Version: ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Implementation of svchost.exe
  3  *
  4  * Copyright 2007 Google (Roy Shea)
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 
 21 /* Usage:
 22  * Starting a service group:
 23  *
 24  *      svchost /k service_group_name
 25  */
 26 
 27 #include <stdarg.h>
 28 
 29 #include "windef.h"
 30 #include "winbase.h"
 31 #include "winreg.h"
 32 #include "winsvc.h"
 33 #include "wine/debug.h"
 34 
 35 WINE_DEFAULT_DEBUG_CHANNEL(svchost);
 36 
 37 /* Static strings used throughout svchost */
 38 static const WCHAR kd[] = {'-','k',0};
 39 
 40 static const WCHAR ks[] = {'/','k',0};
 41 
 42 static const WCHAR reg_separator[] = {'\\',0};
 43 
 44 static const WCHAR service_reg_path[] = {
 45     'S','y','s','t','e','m',
 46     '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
 47     '\\','S','e','r','v','i','c','e','s',0};
 48 
 49 static const WCHAR parameters[] = {
 50     'P','a','r','a','m','e','t','e','r','s',0};
 51 
 52 static const WCHAR service_dll[] = {
 53     'S','e','r','v','i','c','e','D','l','l',0};
 54 
 55 static const WCHAR svchost_path[] = {
 56     'S','o','f','t','w','a','r','e',
 57     '\\','M','i','c','r','o','s','o','f','t',
 58     '\\','W','i','n','d','o','w','s',' ','N','T',
 59     '\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n',
 60     '\\','S','v','c','h','o','s','t',0};
 61 
 62 static const CHAR service_main[] = "ServiceMain";
 63 
 64 /* Allocate and initialize a WSTR containing the queried value */
 65 static LPWSTR GetRegValue(HKEY service_key, const WCHAR *value_name)
 66 {
 67     DWORD type;
 68     DWORD reg_size;
 69     DWORD size;
 70     LONG ret;
 71     LPWSTR value;
 72 
 73     WINE_TRACE("\n");
 74 
 75     ret = RegQueryValueExW(service_key, value_name, NULL, &type, NULL, &reg_size);
 76     if (ret != ERROR_SUCCESS)
 77     {
 78         return NULL;
 79     }
 80 
 81     /* Add space for potentially missing NULL terminators in initial alloc.
 82      * The worst case REG_MULTI_SZ requires two NULL terminators. */
 83     size = reg_size + (2 * sizeof(WCHAR));
 84     value = HeapAlloc(GetProcessHeap(), 0, size);
 85 
 86     ret = RegQueryValueExW(service_key, value_name, NULL, &type,
 87             (LPBYTE)value, &reg_size);
 88     if (ret != ERROR_SUCCESS)
 89     {
 90         HeapFree(GetProcessHeap(), 0, value);
 91         return NULL;
 92     }
 93 
 94     /* Explicitly NULL terminate the result */
 95     value[size / sizeof(WCHAR) - 1] = '\0';
 96     value[size / sizeof(WCHAR) - 2] = '\0';
 97 
 98     return value;
 99 }
100 
101 /* Allocate and initialize a WSTR containing the expanded string */
102 static LPWSTR ExpandEnv(LPWSTR string)
103 {
104     DWORD size;
105     LPWSTR expanded_string;
106 
107     WINE_TRACE("\n");
108 
109     size = 0;
110     size = ExpandEnvironmentStringsW(string, NULL, size);
111     if (size == 0)
112     {
113         WINE_ERR("cannot expand env vars in %s: %u\n",
114                 wine_dbgstr_w(string), GetLastError());
115         return NULL;
116     }
117     expanded_string = HeapAlloc(GetProcessHeap(), 0,
118             (size + 1) * sizeof(WCHAR));
119     if (ExpandEnvironmentStringsW(string, expanded_string, size) == 0)
120     {
121         WINE_ERR("cannot expand env vars in %s: %u\n",
122                 wine_dbgstr_w(string), GetLastError());
123         HeapFree(GetProcessHeap(), 0, expanded_string);
124         return NULL;
125     }
126     return expanded_string;
127 }
128 
129 /* Fill in service table entry for a specified service */
130 static BOOL AddServiceElem(LPWSTR service_name,
131         SERVICE_TABLE_ENTRYW *service_table_entry)
132 {
133     LONG ret;
134     HKEY service_hkey = NULL;
135     LPWSTR service_param_key = NULL;
136     LPWSTR dll_name_short = NULL;
137     LPWSTR dll_name_long = NULL;
138     LPSTR dll_service_main = NULL;
139     HMODULE library = NULL;
140     LPSERVICE_MAIN_FUNCTIONW service_main_func = NULL;
141     BOOL success = FALSE;
142     DWORD reg_size;
143     DWORD size;
144 
145     WINE_TRACE("Adding element for %s\n", wine_dbgstr_w(service_name));
146 
147     /* Construct registry path to the service's parameters key */
148     size = (lstrlenW(service_reg_path) + lstrlenW(reg_separator) +
149             lstrlenW(service_name) + lstrlenW(reg_separator) +
150             lstrlenW(parameters) + 1);
151     service_param_key = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
152     lstrcpyW(service_param_key, service_reg_path);
153     lstrcatW(service_param_key, reg_separator);
154     lstrcatW(service_param_key, service_name);
155     lstrcatW(service_param_key, reg_separator);
156     lstrcatW(service_param_key, parameters);
157     service_param_key[size - 1] = '\0';
158     ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, service_param_key, 0,
159             KEY_READ, &service_hkey);
160     if (ret != ERROR_SUCCESS)
161     {
162         WINE_ERR("cannot open key %s, err=%d\n",
163                 wine_dbgstr_w(service_param_key), ret);
164         goto cleanup;
165     }
166 
167     /* Find DLL associate with service from key */
168     dll_name_short = GetRegValue(service_hkey, service_dll);
169     if (!dll_name_short)
170     {
171         WINE_ERR("cannot find registry value %s for service %s\n",
172                 wine_dbgstr_w(service_dll), wine_dbgstr_w(service_name));
173         RegCloseKey(service_hkey);
174         goto cleanup;
175     }
176 
177     /* Expand environment variables in ServiceDll name*/
178     dll_name_long = ExpandEnv(dll_name_short);
179     if (!dll_name_long)
180     {
181         WINE_ERR("failed to expand string %s\n",
182                 wine_dbgstr_w(dll_name_short));
183         RegCloseKey(service_hkey);
184         goto cleanup;
185     }
186 
187     /* Look for alternate to default ServiceMain entry point */
188     ret = RegQueryValueExA(service_hkey, service_main, NULL, NULL, NULL, &reg_size);
189     if (ret == ERROR_SUCCESS)
190     {
191         /* Add space for potentially missing NULL terminator, allocate, and
192          * fill with the registry value */
193         size = reg_size + 1;
194         dll_service_main = HeapAlloc(GetProcessHeap(), 0, size);
195         ret = RegQueryValueExA(service_hkey, service_main, NULL, NULL,
196                 (LPBYTE)dll_service_main, &reg_size);
197         if (ret != ERROR_SUCCESS)
198         {
199             RegCloseKey(service_hkey);
200             goto cleanup;
201         }
202         dll_service_main[size - 1] = '\0';
203     }
204     RegCloseKey(service_hkey);
205 
206     /* Load the DLL and obtain a pointer to ServiceMain entry point */
207     library = LoadLibraryW(dll_name_long);
208     if (!library)
209     {
210         WINE_ERR("failed to load library %s, err=%u\n",
211                 wine_dbgstr_w(dll_name_long), GetLastError());
212         goto cleanup;
213     }
214     if (dll_service_main)
215     {
216         service_main_func =
217             (LPSERVICE_MAIN_FUNCTIONW) GetProcAddress(library, dll_service_main);
218     }
219     else
220     {
221         service_main_func =
222             (LPSERVICE_MAIN_FUNCTIONW) GetProcAddress(library, service_main);
223     }
224     if (!service_main_func)
225     {
226         WINE_ERR("cannot locate ServiceMain procedure in DLL for %s\n",
227                 wine_dbgstr_w(service_name));
228         FreeLibrary(library);
229         goto cleanup;
230     }
231 
232     if (GetProcAddress(library, "SvchostPushServiceGlobals"))
233     {
234         WINE_FIXME("library %s expects undocumented SvchostPushServiceGlobals function to be called\n",
235                    wine_dbgstr_w(dll_name_long));
236     }
237 
238     /* Fill in the service table entry */
239     service_table_entry->lpServiceName = service_name;
240     service_table_entry->lpServiceProc = service_main_func;
241     success = TRUE;
242 
243 cleanup:
244     HeapFree(GetProcessHeap(), 0, service_param_key);
245     HeapFree(GetProcessHeap(), 0, dll_name_short);
246     HeapFree(GetProcessHeap(), 0, dll_name_long);
247     HeapFree(GetProcessHeap(), 0, dll_service_main);
248     return success;
249 }
250 
251 /* Initialize the service table for a list (REG_MULTI_SZ) of services */
252 static BOOL StartGroupServices(LPWSTR services)
253 {
254     LPWSTR service_name = NULL;
255     SERVICE_TABLE_ENTRYW *service_table = NULL;
256     DWORD service_count;
257 
258     /* Count the services to load */
259     service_count = 0;
260     service_name = services;
261     while (*service_name != '\0')
262     {
263         ++service_count;
264         service_name = service_name + lstrlenW(service_name);
265         ++service_name;
266     }
267     WINE_TRACE("Service group %s contains %d services\n",
268             wine_dbgstr_w(services), service_count);
269 
270     /* Populate the service table */
271     service_table = HeapAlloc(GetProcessHeap(), 0,
272             (service_count + 1) * sizeof(SERVICE_TABLE_ENTRYW));
273     service_count = 0;
274     service_name = services;
275     while (*service_name != '\0')
276     {
277         if (!AddServiceElem(service_name, &service_table[service_count]))
278         {
279             HeapFree(GetProcessHeap(), 0, service_table);
280             return FALSE;
281         }
282         ++service_count;
283         service_name = service_name + lstrlenW(service_name);
284         ++service_name;
285     }
286     service_table[service_count].lpServiceName = NULL;
287     service_table[service_count].lpServiceProc = NULL;
288 
289     /* Start the services */
290     if (!StartServiceCtrlDispatcherW(service_table))
291     {
292         WINE_ERR("StartServiceCtrlDispatcherW failed to start %s: %u\n",
293                 wine_dbgstr_w(services), GetLastError());
294         HeapFree(GetProcessHeap(), 0, service_table);
295         return FALSE;
296     }
297     HeapFree(GetProcessHeap(), 0, service_table);
298     return TRUE;
299 }
300 
301 /* Find the list of services associated with a group name and start those
302  * services */
303 static BOOL LoadGroup(PWCHAR group_name)
304 {
305     HKEY group_hkey = NULL;
306     LPWSTR services = NULL;
307     LONG ret;
308 
309     WINE_TRACE("Loading service group for %s\n", wine_dbgstr_w(group_name));
310 
311     /* Lookup group_name value of svchost registry entry */
312     ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, svchost_path, 0,
313             KEY_READ, &group_hkey);
314     if (ret != ERROR_SUCCESS)
315     {
316         WINE_ERR("cannot open key %s, err=%d\n",
317                 wine_dbgstr_w(svchost_path), ret);
318         return FALSE;
319     }
320     services = GetRegValue(group_hkey, group_name);
321     RegCloseKey(group_hkey);
322     if (!services)
323     {
324         WINE_ERR("cannot find registry value %s in %s\n",
325                 wine_dbgstr_w(group_name), wine_dbgstr_w(svchost_path));
326         return FALSE;
327     }
328 
329     /* Start services */
330     if (StartGroupServices(services) == FALSE)
331     {
332         WINE_TRACE("Failed to start service group\n");
333         HeapFree(GetProcessHeap(), 0, services);
334         return FALSE;
335     }
336     HeapFree(GetProcessHeap(), 0, services);
337     return TRUE;
338 }
339 
340 /* Load svchost group specified on the command line via the /k option */
341 int wmain(int argc, WCHAR *argv[])
342 {
343     int option_index;
344 
345     WINE_TRACE("\n");
346 
347     for (option_index = 1; option_index < argc; option_index++)
348     {
349         if (lstrcmpiW(argv[option_index], ks) == 0 ||
350                 lstrcmpiW(argv[option_index], kd) == 0)
351         {
352             ++option_index;
353             if (option_index >= argc)
354             {
355                 WINE_ERR("Must specify group to initialize\n");
356                 return 0;
357             }
358             if (!LoadGroup(argv[option_index]))
359             {
360                 WINE_ERR("Failed to load requested group: %s\n",
361                         wine_dbgstr_w(argv[option_index]));
362                 return 0;
363             }
364         }
365         else
366         {
367             WINE_FIXME("Unrecognized option: %s\n",
368                     wine_dbgstr_w(argv[option_index]));
369             return 0;
370         }
371     }
372 
373     return 0;
374 }
375 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.