wine  6.0.1
About: Wine is an Open Source implementation of the MS Windows API on top of X, OpenGL, and Unix. Think of Wine as a compatibility layer for running Windows programs.
  Fossies Dox: wine-6.0.1.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

service.c
Go to the documentation of this file.
1 /*
2  * Service control API
3  *
4  * Copyright 1995 Sven Verdoolaege
5  * Copyright 2005 Mike McCormack
6  * Copyright 2007 Rolf Kalbermatter
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library 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 GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 #define NONAMELESSUNION
24 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winsvc.h"
28 #include "winternl.h"
29 #include "winuser.h"
30 #include "dbt.h"
31 
32 #include "wine/debug.h"
33 #include "wine/exception.h"
34 #include "wine/heap.h"
35 #include "wine/list.h"
36 
37 #include "svcctl.h"
38 #include "plugplay.h"
39 
41 
43 {
44  SC_HANDLE service;
45  SC_RPC_NOTIFY_PARAMS params;
46  SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2 cparams;
47  SC_NOTIFY_RPC_HANDLE notify_handle;
50  struct list entry;
51 };
52 
53 static struct list notify_list = LIST_INIT(notify_list);
54 
57 {
58  0, 0, &service_cs,
61  0, 0, { (DWORD_PTR)(__FILE__ ": service_cs") }
62 };
63 static CRITICAL_SECTION service_cs = { &service_cs_debug, -1, 0, 0, 0, 0 };
64 
66 {
68  void *context;
70  SC_HANDLE handle;
71  SC_HANDLE full_access_handle;
72  unsigned int unicode : 1;
73  union
74  {
77  } proc;
79  WCHAR name[1];
80 };
81 
83 {
84  SC_HANDLE manager;
86 };
87 
88 static struct service_data **services;
89 static unsigned int nb_services;
92 
94 
95 static WCHAR *heap_strdupAtoW( const char *src )
96 {
97  WCHAR *dst = NULL;
98  if (src)
99  {
100  DWORD len = MultiByteToWideChar( CP_ACP, 0, src, -1, NULL, 0 );
101  if ((dst = heap_alloc( len * sizeof(WCHAR) ))) MultiByteToWideChar( CP_ACP, 0, src, -1, dst, len );
102  }
103  return dst;
104 }
105 
106 static WCHAR *heap_strdup_multi_AtoW( const char *src )
107 {
108  WCHAR *dst = NULL;
109  const char *p = src;
110  DWORD len;
111 
112  if (!src) return NULL;
113 
114  while (*p) p += strlen(p) + 1;
115  for (p = src; *p; p += strlen(p) + 1);
116  p++; /* final null */
117  len = MultiByteToWideChar( CP_ACP, 0, src, p - src, NULL, 0 );
118  if ((dst = heap_alloc( len * sizeof(WCHAR) ))) MultiByteToWideChar( CP_ACP, 0, src, p - src, dst, len );
119  return dst;
120 }
121 
122 static inline DWORD multisz_size( const WCHAR *str )
123 {
124  const WCHAR *p = str;
125 
126  if (!str) return 0;
127 
128  while (*p) p += wcslen(p) + 1;
129  return (p - str + 1) * sizeof(WCHAR);
130 }
131 
132 void __RPC_FAR * __RPC_USER MIDL_user_allocate( SIZE_T len )
133 {
134  return heap_alloc(len);
135 }
136 
137 void __RPC_USER MIDL_user_free( void __RPC_FAR *ptr )
138 {
139  heap_free(ptr);
140 }
141 
143 {
145 }
146 
147 static DWORD map_exception_code( DWORD exception_code )
148 {
149  switch (exception_code)
150  {
152  return ERROR_INVALID_ADDRESS;
158  return ERROR_INVALID_HANDLE;
159  default:
160  return exception_code;
161  }
162 }
163 
165 {
166  WCHAR transport[] = SVCCTL_TRANSPORT;
167  WCHAR endpoint[] = SVCCTL_ENDPOINT;
168  RPC_WSTR binding_str;
169  RPC_STATUS status;
170  handle_t rpc_handle;
171 
172  status = RpcStringBindingComposeW( NULL, transport, str, endpoint, NULL, &binding_str );
173  if (status != RPC_S_OK)
174  {
175  ERR("RpcStringBindingComposeW failed, error %d\n", status);
176  return NULL;
177  }
178 
179  status = RpcBindingFromStringBindingW( binding_str, &rpc_handle );
180  RpcStringFreeW( &binding_str );
181 
182  if (status != RPC_S_OK)
183  {
184  ERR("Couldn't connect to services.exe, error %d\n", status);
185  return NULL;
186  }
187 
188  return rpc_handle;
189 }
190 
192 {
193  RPC_CSTR transport = (RPC_CSTR)SVCCTL_TRANSPORTA;
194  RPC_CSTR endpoint = (RPC_CSTR)SVCCTL_ENDPOINTA;
195  RPC_CSTR binding_str;
196  RPC_STATUS status;
197  handle_t rpc_handle;
198 
199  status = RpcStringBindingComposeA( NULL, transport, str, endpoint, NULL, &binding_str );
200  if (status != RPC_S_OK)
201  {
202  ERR("RpcStringBindingComposeA failed, error %d\n", status);
203  return NULL;
204  }
205 
206  status = RpcBindingFromStringBindingA( binding_str, &rpc_handle );
207  RpcStringFreeA( &binding_str );
208 
209  if (status != RPC_S_OK)
210  {
211  ERR("Couldn't connect to services.exe, error %d\n", status);
212  return NULL;
213  }
214 
215  return rpc_handle;
216 }
217 
218 DECLSPEC_HIDDEN handle_t __RPC_USER MACHINE_HANDLEA_bind( MACHINE_HANDLEA name )
219 {
220  return rpc_cstr_bind( (RPC_CSTR)name );
221 }
222 
223 DECLSPEC_HIDDEN void __RPC_USER MACHINE_HANDLEA_unbind( MACHINE_HANDLEA name, handle_t h )
224 {
225  RpcBindingFree( &h );
226 }
227 
228 DECLSPEC_HIDDEN handle_t __RPC_USER MACHINE_HANDLEW_bind( MACHINE_HANDLEW name )
229 {
230  return rpc_wstr_bind( (RPC_WSTR)name );
231 }
232 
233 DECLSPEC_HIDDEN void __RPC_USER MACHINE_HANDLEW_unbind( MACHINE_HANDLEW name, handle_t h )
234 {
235  RpcBindingFree( &h );
236 }
237 
238 DECLSPEC_HIDDEN handle_t __RPC_USER SVCCTL_HANDLEW_bind( SVCCTL_HANDLEW name )
239 {
240  return rpc_wstr_bind( (RPC_WSTR)name );
241 }
242 
243 DECLSPEC_HIDDEN void __RPC_USER SVCCTL_HANDLEW_unbind( SVCCTL_HANDLEW name, handle_t h )
244 {
245  RpcBindingFree( &h );
246 }
247 
249 {
250  if (err) SetLastError( err );
251  return !err;
252 }
253 
254 /******************************************************************************
255  * OpenSCManagerA (sechost.@)
256  */
257 SC_HANDLE WINAPI DECLSPEC_HOTPATCH OpenSCManagerA( const char *machine, const char *database, DWORD access )
258 {
259  WCHAR *machineW, *databaseW;
260  SC_HANDLE ret;
261 
262  machineW = heap_strdupAtoW( machine );
263  databaseW = heap_strdupAtoW( database );
264  ret = OpenSCManagerW( machineW, databaseW, access );
265  heap_free( databaseW );
266  heap_free( machineW );
267  return ret;
268 }
269 
270 /******************************************************************************
271  * OpenSCManagerW (sechost.@)
272  */
273 SC_HANDLE WINAPI DECLSPEC_HOTPATCH OpenSCManagerW( const WCHAR *machine, const WCHAR *database, DWORD access )
274 {
275  SC_RPC_HANDLE handle = NULL;
276  DWORD err;
277 
278  TRACE( "%s %s %#x\n", debugstr_w(machine), debugstr_w(database), access );
279 
280  __TRY
281  {
282  err = svcctl_OpenSCManagerW( machine, database, access, &handle );
283  }
285  {
287  }
288  __ENDTRY
289 
290  if (!err) return handle;
291  SetLastError( err );
292  return NULL;
293 }
294 
295 /******************************************************************************
296  * OpenServiceA (sechost.@)
297  */
298 SC_HANDLE WINAPI DECLSPEC_HOTPATCH OpenServiceA( SC_HANDLE manager, const char *name, DWORD access )
299 {
300  WCHAR *nameW;
301  SC_HANDLE ret;
302 
303  TRACE( "%p %s %#x\n", manager, debugstr_a(name), access );
304 
305  nameW = heap_strdupAtoW( name );
306  ret = OpenServiceW( manager, nameW, access );
307  heap_free( nameW );
308  return ret;
309 }
310 
311 /******************************************************************************
312  * OpenServiceW (sechost.@)
313  */
315 {
316  SC_RPC_HANDLE handle = NULL;
317  DWORD err;
318 
319  TRACE( "%p %s %#x\n", manager, debugstr_w(name), access );
320 
321  if (!manager)
322  {
324  return NULL;
325  }
326 
327  __TRY
328  {
330  }
332  {
334  }
335  __ENDTRY
336 
337  if (!err) return handle;
338  SetLastError( err );
339  return 0;
340 }
341 
342 /******************************************************************************
343  * CreateServiceA (sechost.@)
344  */
345 SC_HANDLE WINAPI DECLSPEC_HOTPATCH CreateServiceA( SC_HANDLE manager, const char *name, const char *display_name,
346  DWORD access, DWORD service_type, DWORD start_type,
347  DWORD error_control, const char *path, const char *group,
348  DWORD *tag, const char *dependencies, const char *username,
349  const char *password )
350 {
351  WCHAR *nameW, *display_nameW, *pathW, *groupW, *dependenciesW, *usernameW, *passwordW;
352  SC_HANDLE handle;
353 
354  TRACE( "%p %s %s\n", manager, debugstr_a(name), debugstr_a(display_name) );
355 
356  nameW = heap_strdupAtoW( name );
357  display_nameW = heap_strdupAtoW( display_name );
358  pathW = heap_strdupAtoW( path );
359  groupW = heap_strdupAtoW( group );
360  dependenciesW = heap_strdupAtoW( dependencies );
361  usernameW = heap_strdupAtoW( username );
362  passwordW = heap_strdupAtoW( password );
363 
364  handle = CreateServiceW( manager, nameW, display_nameW, access, service_type, start_type, error_control,
365  pathW, groupW, tag, dependenciesW, usernameW, passwordW );
366 
367  heap_free( nameW );
368  heap_free( display_nameW );
369  heap_free( pathW );
370  heap_free( groupW );
371  heap_free( dependenciesW );
372  heap_free( usernameW );
373  heap_free( passwordW );
374 
375  return handle;
376 }
377 
378 /******************************************************************************
379  * CreateServiceW (sechost.@)
380  */
381 SC_HANDLE WINAPI DECLSPEC_HOTPATCH CreateServiceW( SC_HANDLE manager, const WCHAR *name, const WCHAR *display_name,
382  DWORD access, DWORD service_type, DWORD start_type,
383  DWORD error_control, const WCHAR *path, const WCHAR *group,
384  DWORD *tag, const WCHAR *dependencies, const WCHAR *username,
385  const WCHAR *password )
386 {
387  SC_RPC_HANDLE handle = NULL;
388  DWORD err;
389  SIZE_T password_size = 0;
390 
391  TRACE( "%p %s %s\n", manager, debugstr_w(name), debugstr_w(display_name) );
392 
393  if (!manager)
394  {
396  return 0;
397  }
398 
399  if (password) password_size = (wcslen(password) + 1) * sizeof(WCHAR);
400 
401  __TRY
402  {
403  BOOL is_wow64;
404 
406  err = svcctl_CreateServiceWOW64W( manager, name, display_name, access, service_type, start_type,
407  error_control, path, group, tag, (const BYTE *)dependencies,
408  multisz_size( dependencies ), username, (const BYTE *)password,
409  password_size, &handle );
410  else
411  err = svcctl_CreateServiceW( manager, name, display_name, access, service_type, start_type,
412  error_control, path, group, tag, (const BYTE *)dependencies,
413  multisz_size( dependencies ), username, (const BYTE *)password,
414  password_size, &handle );
415  }
417  {
419  }
420  __ENDTRY
421 
422  if (!err) return handle;
423  SetLastError( err );
424  return NULL;
425 }
426 
427 /******************************************************************************
428  * DeleteService (sechost.@)
429  */
431 {
432  DWORD err;
433 
434  TRACE( "%p\n", service );
435 
436  __TRY
437  {
438  err = svcctl_DeleteService( service );
439  }
441  {
443  }
444  __ENDTRY
445 
446  return set_error( err );
447 }
448 
449 /******************************************************************************
450  * CloseServiceHandle (sechost.@)
451  */
453 {
454  DWORD err;
455 
456  TRACE( "%p\n", handle );
457 
458  __TRY
459  {
460  err = svcctl_CloseServiceHandle( (SC_RPC_HANDLE *)&handle );
461  }
463  {
465  }
466  __ENDTRY
467 
468  return set_error( err );
469 }
470 
471 /******************************************************************************
472  * ChangeServiceConfig2A (sechost.@)
473  */
474 BOOL WINAPI DECLSPEC_HOTPATCH ChangeServiceConfig2A( SC_HANDLE service, DWORD level, void *info)
475 {
476  BOOL r = FALSE;
477 
478  TRACE( "%p %d %p\n", service, level, info );
479 
480  if (level == SERVICE_CONFIG_DESCRIPTION)
481  {
484 
486 
487  r = ChangeServiceConfig2W( service, level, &sdw );
488 
489  heap_free( sdw.lpDescription );
490  }
491  else if (level == SERVICE_CONFIG_FAILURE_ACTIONS)
492  {
495 
496  faw.dwResetPeriod = fa->dwResetPeriod;
498  faw.lpCommand = heap_strdupAtoW( fa->lpCommand );
499  faw.cActions = fa->cActions;
500  faw.lpsaActions = fa->lpsaActions;
501 
502  r = ChangeServiceConfig2W( service, level, &faw );
503 
504  heap_free( faw.lpRebootMsg );
505  heap_free( faw.lpCommand );
506  }
507  else if (level == SERVICE_CONFIG_PRESHUTDOWN_INFO)
508  {
509  r = ChangeServiceConfig2W( service, level, info );
510  }
511  else
513 
514  return r;
515 }
516 
517 /******************************************************************************
518  * ChangeServiceConfig2W (sechost.@)
519  */
520 BOOL WINAPI DECLSPEC_HOTPATCH ChangeServiceConfig2W( SC_HANDLE service, DWORD level, void *info )
521 {
522  SERVICE_RPC_REQUIRED_PRIVILEGES_INFO rpc_privinfo;
523  DWORD err;
524 
525  __TRY
526  {
527  SC_RPC_CONFIG_INFOW rpc_info;
528 
529  rpc_info.dwInfoLevel = level;
531  {
533 
534  rpc_privinfo.cbRequiredPrivileges = multisz_size( privinfo->pmszRequiredPrivileges );
535  rpc_privinfo.pRequiredPrivileges = (BYTE *)privinfo->pmszRequiredPrivileges;
536  rpc_info.u.privinfo = &rpc_privinfo;
537  }
538  else
539  rpc_info.u.descr = info;
540  err = svcctl_ChangeServiceConfig2W( service, rpc_info );
541  }
543  {
545  }
546  __ENDTRY
547 
548  return set_error( err );
549 }
550 
551 /******************************************************************************
552  * ChangeServiceConfigA (sechost.@)
553  */
554 BOOL WINAPI DECLSPEC_HOTPATCH ChangeServiceConfigA( SC_HANDLE service, DWORD service_type, DWORD start_type,
555  DWORD error_control, const char *path, const char *group,
556  DWORD *tag, const char *dependencies, const char *username,
557  const char *password, const char *display_name )
558 {
559  WCHAR *pathW, *groupW, *dependenciesW, *usernameW, *passwordW, *display_nameW;
560  BOOL r;
561 
562  TRACE( "%p %d %d %d %s %s %p %p %s %s %s\n", service, service_type, start_type,
563  error_control, debugstr_a(path), debugstr_a(group), tag, dependencies,
564  debugstr_a(username), debugstr_a(password), debugstr_a(display_name) );
565 
566  pathW = heap_strdupAtoW( path );
567  groupW = heap_strdupAtoW( group );
568  dependenciesW = heap_strdup_multi_AtoW( dependencies );
569  usernameW = heap_strdupAtoW( username );
570  passwordW = heap_strdupAtoW( password );
571  display_nameW = heap_strdupAtoW( display_name );
572 
573  r = ChangeServiceConfigW( service, service_type, start_type, error_control, pathW,
574  groupW, tag, dependenciesW, usernameW, passwordW, display_nameW );
575 
576  heap_free( pathW );
577  heap_free( groupW );
578  heap_free( dependenciesW );
579  heap_free( usernameW );
580  heap_free( passwordW );
581  heap_free( display_nameW );
582 
583  return r;
584 }
585 
586 /******************************************************************************
587  * ChangeServiceConfigW (sechost.@)
588  */
589 BOOL WINAPI DECLSPEC_HOTPATCH ChangeServiceConfigW( SC_HANDLE service, DWORD service_type, DWORD start_type,
590  DWORD error_control, const WCHAR *path, const WCHAR *group,
591  DWORD *tag, const WCHAR *dependencies, const WCHAR *username,
592  const WCHAR *password, const WCHAR *display_name )
593 {
594  DWORD password_size;
595  DWORD err;
596 
597  TRACE( "%p %d %d %d %s %s %p %p %s %s %s\n", service, service_type, start_type,
598  error_control, debugstr_w(path), debugstr_w(group), tag, dependencies,
599  debugstr_w(username), debugstr_w(password), debugstr_w(display_name) );
600 
601  password_size = password ? (wcslen(password) + 1) * sizeof(WCHAR) : 0;
602 
603  __TRY
604  {
605  err = svcctl_ChangeServiceConfigW( service, service_type, start_type, error_control, path, group, tag,
606  (const BYTE *)dependencies, multisz_size(dependencies), username,
607  (const BYTE *)password, password_size, display_name );
608  }
610  {
612  }
613  __ENDTRY
614 
615  return set_error( err );
616 }
617 
618 /******************************************************************************
619  * QueryServiceConfigA (sechost.@)
620  */
622  DWORD size, DWORD *ret_size )
623 {
624  DWORD n;
625  char *p, *buffer;
626  BOOL ret;
627  QUERY_SERVICE_CONFIGW *configW;
628 
629  TRACE( "%p %p %d %p\n", service, config, size, ret_size );
630 
631  if (!(buffer = heap_alloc( 2 * size ))) return set_error( ERROR_NOT_ENOUGH_MEMORY );
632  configW = (QUERY_SERVICE_CONFIGW *)buffer;
633  ret = QueryServiceConfigW( service, configW, 2 * size, ret_size );
634  if (!ret) goto done;
635 
636  config->dwServiceType = configW->dwServiceType;
637  config->dwStartType = configW->dwStartType;
638  config->dwErrorControl = configW->dwErrorControl;
639  config->lpBinaryPathName = NULL;
640  config->lpLoadOrderGroup = NULL;
641  config->dwTagId = configW->dwTagId;
642  config->lpDependencies = NULL;
643  config->lpServiceStartName = NULL;
644  config->lpDisplayName = NULL;
645 
646  p = (char *)(config + 1);
647  n = size - sizeof(*config);
648  ret = FALSE;
649 
650 #define MAP_STR(str) \
651  do { \
652  if (configW->str) \
653  { \
654  DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
655  if (!sz) goto done; \
656  config->str = p; \
657  p += sz; \
658  n -= sz; \
659  } \
660  } while (0)
661 
662  MAP_STR( lpBinaryPathName );
663  MAP_STR( lpLoadOrderGroup );
664  MAP_STR( lpDependencies );
665  MAP_STR( lpServiceStartName );
666  MAP_STR( lpDisplayName );
667 #undef MAP_STR
668 
669  *ret_size = p - (char *)config;
670  ret = TRUE;
671 
672 done:
673  heap_free( buffer );
674  return ret;
675 }
676 
677 static DWORD move_string_to_buffer(BYTE **buf, WCHAR **string_ptr)
678 {
679  DWORD cb;
680 
681  if (!*string_ptr)
682  {
683  cb = sizeof(WCHAR);
684  memset(*buf, 0, cb);
685  }
686  else
687  {
688  cb = (wcslen( *string_ptr ) + 1) * sizeof(WCHAR);
689  memcpy(*buf, *string_ptr, cb);
690  MIDL_user_free( *string_ptr );
691  }
692 
693  *string_ptr = (WCHAR *)*buf;
694  *buf += cb;
695 
696  return cb;
697 }
698 
699 static DWORD size_string( const WCHAR *string )
700 {
701  return (string ? (wcslen( string ) + 1) * sizeof(WCHAR) : sizeof(WCHAR));
702 }
703 
704 /******************************************************************************
705  * QueryServiceConfigW (sechost.@)
706  */
708  DWORD size, DWORD *ret_size )
709 {
711  DWORD total;
712  DWORD err;
713  BYTE *bufpos;
714 
715  TRACE( "%p %p %d %p\n", service, ret_config, size, ret_size );
716 
717  memset(&config, 0, sizeof(config));
718 
719  __TRY
720  {
721  err = svcctl_QueryServiceConfigW( service, &config, size, ret_size );
722  }
724  {
726  }
727  __ENDTRY
728 
729  if (err) return set_error( err );
730 
731  /* calculate the size required first */
732  total = sizeof(QUERY_SERVICE_CONFIGW);
733  total += size_string( config.lpBinaryPathName );
734  total += size_string( config.lpLoadOrderGroup );
735  total += size_string( config.lpDependencies );
736  total += size_string( config.lpServiceStartName );
737  total += size_string( config.lpDisplayName );
738 
739  *ret_size = total;
740 
741  /* if there's not enough memory, return an error */
742  if (size < total)
743  {
745  MIDL_user_free( config.lpBinaryPathName );
746  MIDL_user_free( config.lpLoadOrderGroup );
747  MIDL_user_free( config.lpDependencies );
748  MIDL_user_free( config.lpServiceStartName );
749  MIDL_user_free( config.lpDisplayName );
750  return FALSE;
751  }
752 
753  *ret_config = config;
754  bufpos = ((BYTE *)ret_config) + sizeof(QUERY_SERVICE_CONFIGW);
755  move_string_to_buffer( &bufpos, &ret_config->lpBinaryPathName );
756  move_string_to_buffer( &bufpos, &ret_config->lpLoadOrderGroup );
757  move_string_to_buffer( &bufpos, &ret_config->lpDependencies );
758  move_string_to_buffer( &bufpos, &ret_config->lpServiceStartName );
759  move_string_to_buffer( &bufpos, &ret_config->lpDisplayName );
760 
761  TRACE( "Image path = %s\n", debugstr_w( ret_config->lpBinaryPathName ) );
762  TRACE( "Group = %s\n", debugstr_w( ret_config->lpLoadOrderGroup ) );
763  TRACE( "Dependencies = %s\n", debugstr_w( ret_config->lpDependencies ) );
764  TRACE( "Service account name = %s\n", debugstr_w( ret_config->lpServiceStartName ) );
765  TRACE( "Display name = %s\n", debugstr_w( ret_config->lpDisplayName ) );
766 
767  return TRUE;
768 }
769 
770 /******************************************************************************
771  * QueryServiceConfig2A (sechost.@)
772  */
774  DWORD size, DWORD *ret_size )
775 {
776  BYTE *bufferW = NULL;
777 
778  TRACE( "%p %u %p %u %p\n", service, level, buffer, size, ret_size );
779 
780  if (buffer && size)
781  bufferW = heap_alloc( size );
782 
783  if (!QueryServiceConfig2W( service, level, bufferW, size, ret_size ))
784  {
785  heap_free( bufferW );
786  return FALSE;
787  }
788 
789  switch (level)
790  {
792  if (buffer && bufferW) {
794  SERVICE_DESCRIPTIONW *configW = (SERVICE_DESCRIPTIONW *)bufferW;
795  if (configW->lpDescription && size > sizeof(SERVICE_DESCRIPTIONA))
796  {
797  configA->lpDescription = (char *)(configA + 1);
798  WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1, configA->lpDescription,
799  size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
800  }
801  else configA->lpDescription = NULL;
802  }
803  break;
805  if (buffer && bufferW && *ret_size <= size)
806  memcpy(buffer, bufferW, *ret_size);
807  break;
808  default:
809  FIXME("conversion W->A not implemented for level %d\n", level);
810  heap_free( bufferW );
811  return FALSE;
812  }
813 
814  heap_free( bufferW );
815  return TRUE;
816 }
817 
818 /******************************************************************************
819  * QueryServiceConfig2W (sechost.@)
820  */
822  DWORD size, DWORD *ret_size )
823 {
824  BYTE *bufptr;
825  DWORD err;
826 
827  TRACE( "%p %u %p %u %p\n", service, level, buffer, size, ret_size );
828 
829  if (!buffer && size)
830  {
832  return FALSE;
833  }
834 
835  switch (level)
836  {
838  if (!(bufptr = heap_alloc( size )))
839  {
841  return FALSE;
842  }
843  break;
844 
846  bufptr = buffer;
847  break;
848 
849  default:
850  FIXME("Level %d not implemented\n", level);
852  return FALSE;
853  }
854 
855  if (!ret_size)
856  {
857  if (level == SERVICE_CONFIG_DESCRIPTION) heap_free( bufptr );
859  return FALSE;
860  }
861 
862  __TRY
863  {
864  err = svcctl_QueryServiceConfig2W( service, level, bufptr, size, ret_size );
865  }
867  {
869  }
870  __ENDTRY
871 
872  switch (level)
873  {
875  {
877  struct service_description *s = (struct service_description *)bufptr;
878 
880  {
881  heap_free( bufptr );
882  SetLastError( err );
883  return FALSE;
884  }
885 
886  /* adjust for potentially larger SERVICE_DESCRIPTIONW structure */
887  if (*ret_size == sizeof(*s))
888  *ret_size = sizeof(*desc);
889  else
890  *ret_size = *ret_size - FIELD_OFFSET(struct service_description, description) + sizeof(*desc);
891 
892  if (size < *ret_size)
893  {
894  heap_free( bufptr );
896  return FALSE;
897  }
898  if (desc)
899  {
900  if (!s->size) desc->lpDescription = NULL;
901  else
902  {
903  desc->lpDescription = (WCHAR *)(desc + 1);
904  memcpy( desc->lpDescription, s->description, s->size );
905  }
906  }
907  heap_free( bufptr );
908  break;
909  }
911  return set_error( err );
912 
913  default:
914  break;
915  }
916 
917  return TRUE;
918 }
919 
920 /******************************************************************************
921  * GetServiceDisplayNameW (sechost.@)
922  */
924  WCHAR *display_name, DWORD *len )
925 {
926  DWORD err;
927  DWORD size;
928  WCHAR buffer[2];
929 
930  TRACE( "%p %s %p %p\n", manager, debugstr_w(service), display_name, len );
931 
932  if (!manager)
933  {
935  return FALSE;
936  }
937 
938  /* provide a buffer if the caller didn't */
939  if (!display_name || *len < sizeof(WCHAR))
940  {
941  display_name = buffer;
942  /* A size of 1 would be enough, but tests show that Windows returns 2,
943  * probably because of a WCHAR/bytes mismatch in their code. */
944  *len = 2;
945  }
946 
947  /* RPC call takes size excluding nul-terminator, whereas *len
948  * includes the nul-terminator on input. */
949  size = *len - 1;
950 
951  __TRY
952  {
953  err = svcctl_GetServiceDisplayNameW( manager, service, display_name, &size );
954  }
956  {
958  }
959  __ENDTRY
960 
961  /* The value of *len excludes nul-terminator on output. */
963  *len = size;
964  return set_error( err );
965 }
966 
967 /******************************************************************************
968  * GetServiceKeyNameW (sechost.@)
969  */
971  WCHAR *key_name, DWORD *len )
972 {
973  DWORD err;
974  WCHAR buffer[2];
975  DWORD size;
976 
977  TRACE( "%p %s %p %p\n", manager, debugstr_w(display_name), key_name, len );
978 
979  if (!manager)
980  {
982  return FALSE;
983  }
984 
985  /* provide a buffer if the caller didn't */
986  if (!key_name || *len < 2)
987  {
988  key_name = buffer;
989  /* A size of 1 would be enough, but tests show that Windows returns 2,
990  * probably because of a WCHAR/bytes mismatch in their code.
991  */
992  *len = 2;
993  }
994 
995  /* RPC call takes size excluding nul-terminator, whereas *len
996  * includes the nul-terminator on input. */
997  size = *len - 1;
998 
999  __TRY
1000  {
1001  err = svcctl_GetServiceKeyNameW( manager, display_name, key_name, &size );
1002  }
1004  {
1006  }
1007  __ENDTRY
1008 
1009  /* The value of *lpcchBuffer excludes nul-terminator on output. */
1011  *len = size;
1012  return set_error( err );
1013 }
1014 
1015 /******************************************************************************
1016  * StartServiceA (sechost.@)
1017  */
1018 BOOL WINAPI DECLSPEC_HOTPATCH StartServiceA( SC_HANDLE service, DWORD argc, const char **argv )
1019 {
1020  WCHAR **argvW = NULL;
1021  DWORD i;
1022  BOOL r;
1023 
1024  if (argc)
1025  argvW = heap_alloc( argc * sizeof(WCHAR) );
1026 
1027  for (i = 0; i < argc; i++)
1028  argvW[i] = heap_strdupAtoW( argv[i] );
1029 
1030  r = StartServiceW( service, argc, (const WCHAR **)argvW );
1031 
1032  for (i = 0; i < argc; i++)
1033  heap_free( argvW[i] );
1034  heap_free( argvW );
1035  return r;
1036 }
1037 
1038 
1039 /******************************************************************************
1040  * StartServiceW (sechost.@)
1041  */
1042 BOOL WINAPI DECLSPEC_HOTPATCH StartServiceW( SC_HANDLE service, DWORD argc, const WCHAR **argv )
1043 {
1044  DWORD err;
1045 
1046  TRACE( "%p %u %p\n", service, argc, argv );
1047 
1048  __TRY
1049  {
1050  err = svcctl_StartServiceW( service, argc, argv );
1051  }
1053  {
1055  }
1056  __ENDTRY
1057 
1058  return set_error( err );
1059 }
1060 
1061 /******************************************************************************
1062  * ControlService (sechost.@)
1063  */
1065 {
1066  DWORD err;
1067 
1068  TRACE( "%p %d %p\n", service, control, status );
1069 
1070  __TRY
1071  {
1072  err = svcctl_ControlService( service, control, status );
1073  }
1075  {
1077  }
1078  __ENDTRY
1079 
1080  return set_error( err );
1081 }
1082 
1083 /******************************************************************************
1084  * QueryServiceStatus (sechost.@)
1085  */
1087 {
1088  SERVICE_STATUS_PROCESS process_status;
1089  BOOL ret;
1090  DWORD size;
1091 
1092  TRACE( "%p %p\n", service, status );
1093 
1094  if (!service) return set_error( ERROR_INVALID_HANDLE );
1095  if (!status) return set_error( ERROR_INVALID_ADDRESS );
1096 
1097  ret = QueryServiceStatusEx( service, SC_STATUS_PROCESS_INFO, (BYTE *)&process_status,
1098  sizeof(SERVICE_STATUS_PROCESS), &size );
1099  if (ret) memcpy(status, &process_status, sizeof(SERVICE_STATUS) );
1100  return ret;
1101 }
1102 
1103 /******************************************************************************
1104  * QueryServiceStatusEx (sechost.@)
1105  */
1107  BYTE *buffer, DWORD size, DWORD *ret_size )
1108 {
1109  DWORD err;
1110 
1111  TRACE( "%p %d %p %d %p\n", service, level, buffer, size, ret_size );
1112 
1113  if (level != SC_STATUS_PROCESS_INFO) return set_error( ERROR_INVALID_LEVEL );
1114 
1115  if (size < sizeof(SERVICE_STATUS_PROCESS))
1116  {
1117  *ret_size = sizeof(SERVICE_STATUS_PROCESS);
1119  }
1120 
1121  __TRY
1122  {
1123  err = svcctl_QueryServiceStatusEx( service, level, buffer, size, ret_size );
1124  }
1126  {
1128  }
1129  __ENDTRY
1130 
1131  return set_error( err );
1132 }
1133 
1134 /******************************************************************************
1135  * EnumServicesStatusExW (sechost.@)
1136  */
1138  BYTE *buffer, DWORD size, DWORD *needed, DWORD *returned,
1139  DWORD *resume_handle, const WCHAR *group )
1140 {
1141  DWORD err, i, offset, buflen, count, total_size = 0;
1143  struct enum_service_status_process *entry;
1144  const WCHAR *str;
1145  BYTE *buf;
1146 
1147  TRACE( "%p %u 0x%x 0x%x %p %u %p %p %p %s\n", manager, level, type, state, buffer,
1148  size, needed, returned, resume_handle, debugstr_w(group) );
1149 
1150  if (level != SC_ENUM_PROCESS_INFO) return set_error( ERROR_INVALID_LEVEL );
1151  if (!manager) return set_error( ERROR_INVALID_HANDLE );
1152  if (!needed || !returned) return set_error( ERROR_INVALID_ADDRESS );
1153 
1154  /* make sure we pass a valid pointer */
1155  buflen = max( size, sizeof(*services) );
1156  if (!(buf = heap_alloc( buflen ))) return set_error( ERROR_NOT_ENOUGH_MEMORY );
1157 
1158  __TRY
1159  {
1161  &count, resume_handle, group );
1162  }
1164  {
1166  }
1167  __ENDTRY
1168 
1169  *returned = 0;
1170  if (err != ERROR_SUCCESS)
1171  {
1172  /* double the needed size to fit the potentially larger ENUM_SERVICE_STATUS_PROCESSW */
1173  if (err == ERROR_MORE_DATA) *needed *= 2;
1174  heap_free( buf );
1175  SetLastError( err );
1176  return FALSE;
1177  }
1178 
1179  entry = (struct enum_service_status_process *)buf;
1180  for (i = 0; i < count; i++)
1181  {
1182  total_size += sizeof(*services);
1183  if (entry->service_name)
1184  {
1185  str = (const WCHAR *)(buf + entry->service_name);
1186  total_size += (wcslen( str ) + 1) * sizeof(WCHAR);
1187  }
1188  if (entry->display_name)
1189  {
1190  str = (const WCHAR *)(buf + entry->display_name);
1191  total_size += (wcslen( str ) + 1) * sizeof(WCHAR);
1192  }
1193  entry++;
1194  }
1195 
1196  if (total_size > size)
1197  {
1198  heap_free( buf );
1199  *needed = total_size;
1201  return FALSE;
1202  }
1203 
1204  offset = count * sizeof(*services);
1205  entry = (struct enum_service_status_process *)buf;
1206  for (i = 0; i < count; i++)
1207  {
1208  DWORD str_size;
1209  str = (const WCHAR *)(buf + entry->service_name);
1210  str_size = (wcslen( str ) + 1) * sizeof(WCHAR);
1211  services[i].lpServiceName = (WCHAR *)((char *)services + offset);
1212  memcpy( services[i].lpServiceName, str, str_size );
1213  offset += str_size;
1214 
1215  if (!entry->display_name) services[i].lpDisplayName = NULL;
1216  else
1217  {
1218  str = (const WCHAR *)(buf + entry->display_name);
1219  str_size = (wcslen( str ) + 1) * sizeof(WCHAR);
1220  services[i].lpDisplayName = (WCHAR *)((char *)services + offset);
1221  memcpy( services[i].lpDisplayName, str, str_size );
1222  offset += str_size;
1223  }
1224  services[i].ServiceStatusProcess = entry->service_status_process;
1225  entry++;
1226  }
1227 
1228  heap_free( buf );
1229  *needed = 0;
1230  *returned = count;
1231  return TRUE;
1232 }
1233 
1234 /******************************************************************************
1235  * EnumDependentServicesW (sechost.@)
1236  */
1237 BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
1238  LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize,
1239  LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
1240 {
1241  FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
1242  lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
1243 
1244  *lpServicesReturned = 0;
1245  return TRUE;
1246 }
1247 
1248 /******************************************************************************
1249  * QueryServiceObjectSecurity (sechost.@)
1250  */
1252  PSECURITY_DESCRIPTOR ret_descriptor, DWORD size, DWORD *ret_size )
1253 {
1254  SECURITY_DESCRIPTOR descriptor;
1255  NTSTATUS status;
1256  ACL acl;
1257 
1258  FIXME( "%p %d %p %u %p - semi-stub\n", service, type, ret_descriptor, size, ret_size );
1259 
1261  FIXME("information %d not supported\n", type);
1262 
1264 
1265  InitializeAcl( &acl, sizeof(ACL), ACL_REVISION );
1266  SetSecurityDescriptorDacl( &descriptor, TRUE, &acl, TRUE );
1267 
1268  status = RtlMakeSelfRelativeSD( &descriptor, ret_descriptor, &size );
1269  *ret_size = size;
1270 
1271  return set_error( RtlNtStatusToDosError( status ) );
1272 }
1273 
1274 /******************************************************************************
1275  * SetServiceObjectSecurity (sechost.@)
1276  */
1278  SECURITY_INFORMATION dwSecurityInformation,
1279  PSECURITY_DESCRIPTOR lpSecurityDescriptor)
1280 {
1281  FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
1282  return TRUE;
1283 }
1284 
1285 static DWORD WINAPI notify_thread(void *user)
1286 {
1287  DWORD err;
1288  struct notify_data *data = user;
1289  SC_RPC_NOTIFY_PARAMS_LIST *list = NULL;
1290  SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2 *cparams;
1291  BOOL dummy;
1292 
1293  __TRY
1294  {
1295  /* GetNotifyResults blocks until there is an event */
1296  err = svcctl_GetNotifyResults(data->notify_handle, &list);
1297  }
1299  {
1301  }
1302  __ENDTRY
1303 
1305 
1306  list_remove(&data->entry);
1307 
1309 
1310  if (err == ERROR_SUCCESS && list)
1311  {
1312  cparams = list->NotifyParamsArray[0].u.params;
1313 
1314  data->notify_buffer->dwNotificationStatus = cparams->dwNotificationStatus;
1315  memcpy(&data->notify_buffer->ServiceStatus, &cparams->ServiceStatus,
1316  sizeof(SERVICE_STATUS_PROCESS));
1317  data->notify_buffer->dwNotificationTriggered = cparams->dwNotificationTriggered;
1318  data->notify_buffer->pszServiceNames = NULL;
1319 
1320  QueueUserAPC((PAPCFUNC)data->notify_buffer->pfnNotifyCallback,
1321  data->calling_thread, (ULONG_PTR)data->notify_buffer);
1322 
1323  HeapFree(GetProcessHeap(), 0, list);
1324  }
1325  else
1326  WARN("GetNotifyResults server call failed: %u\n", err);
1327 
1328 
1329  __TRY
1330  {
1331  err = svcctl_CloseNotifyHandle(&data->notify_handle, &dummy);
1332  }
1334  {
1336  }
1337  __ENDTRY
1338 
1339  if (err != ERROR_SUCCESS)
1340  WARN("CloseNotifyHandle server call failed: %u\n", err);
1341 
1342  CloseHandle(data->calling_thread);
1343  HeapFree(GetProcessHeap(), 0, data);
1344 
1345  return 0;
1346 }
1347 
1348 /******************************************************************************
1349  * NotifyServiceStatusChangeW (sechost.@)
1350  */
1353 {
1354  DWORD err;
1355  BOOL b_dummy = FALSE;
1356  GUID g_dummy = {0};
1357  struct notify_data *data;
1358 
1359  TRACE( "%p 0x%x %p\n", service, mask, notify_buffer );
1360 
1361  if (!(data = heap_alloc_zero( sizeof(*data) )))
1362  return ERROR_NOT_ENOUGH_MEMORY;
1363 
1364  data->service = service;
1365  data->notify_buffer = notify_buffer;
1367  &data->calling_thread, 0, FALSE, DUPLICATE_SAME_ACCESS ))
1368  {
1369  ERR("DuplicateHandle failed: %u\n", GetLastError());
1370  heap_free( data );
1371  return ERROR_NOT_ENOUGH_MEMORY;
1372  }
1373 
1374  data->params.dwInfoLevel = 2;
1375  data->params.u.params = &data->cparams;
1376 
1377  data->cparams.dwNotifyMask = mask;
1378 
1380 
1381  __TRY
1382  {
1383  err = svcctl_NotifyServiceStatusChange( service, data->params, &g_dummy,
1384  &g_dummy, &b_dummy, &data->notify_handle );
1385  }
1387  {
1389  }
1390  __ENDTRY
1391 
1392  if (err != ERROR_SUCCESS)
1393  {
1394  WARN("NotifyServiceStatusChange server call failed: %u\n", err);
1396  CloseHandle( data->calling_thread );
1397  CloseHandle( data->ready_evt );
1398  heap_free( data );
1399  return err;
1400  }
1401 
1403 
1404  list_add_tail( &notify_list, &data->entry );
1405 
1407 
1408  return ERROR_SUCCESS;
1409 }
1410 
1411 /* thunk for calling the RegisterServiceCtrlHandler handler function */
1413 {
1415 
1416  func( control );
1417  return ERROR_SUCCESS;
1418 }
1419 
1420 /******************************************************************************
1421  * RegisterServiceCtrlHandlerA (sechost.@)
1422  */
1424  const char *name, LPHANDLER_FUNCTION handler )
1425 {
1427 }
1428 
1429 /******************************************************************************
1430  * RegisterServiceCtrlHandlerW (sechost.@)
1431  */
1434 {
1436 }
1437 
1438 /******************************************************************************
1439  * RegisterServiceCtrlHandlerExA (sechost.@)
1440  */
1442  const char *name, LPHANDLER_FUNCTION_EX handler, void *context )
1443 {
1444  WCHAR *nameW;
1445  SERVICE_STATUS_HANDLE ret;
1446 
1447  nameW = heap_strdupAtoW( name );
1449  heap_free( nameW );
1450  return ret;
1451 }
1452 
1454 {
1455  unsigned int i;
1456 
1457  if (nb_services == 1) /* only one service (FIXME: should depend on OWN_PROCESS etc.) */
1458  return services[0];
1459  for (i = 0; i < nb_services; i++)
1460  if (!wcsicmp( name, services[i]->name )) return services[i];
1461  return NULL;
1462 }
1463 
1464 /******************************************************************************
1465  * RegisterServiceCtrlHandlerExW (sechost.@)
1466  */
1469 {
1470  struct service_data *service;
1471  SC_HANDLE handle = 0;
1472 
1473  TRACE( "%s %p %p\n", debugstr_w(name), handler, context );
1474 
1476  if ((service = find_service_by_name( name )))
1477  {
1478  service->handler = handler;
1479  service->context = context;
1480  handle = service->handle;
1481  }
1483 
1485  return (SERVICE_STATUS_HANDLE)handle;
1486 }
1487 
1488 /******************************************************************************
1489  * SetServiceStatus (sechost.@)
1490  */
1492 {
1493  DWORD err;
1494 
1495  TRACE( "%p %#x %#x %#x %#x %#x %#x %#x\n", service, status->dwServiceType,
1496  status->dwCurrentState, status->dwControlsAccepted, status->dwWin32ExitCode,
1497  status->dwServiceSpecificExitCode, status->dwCheckPoint, status->dwWaitHint );
1498 
1499  __TRY
1500  {
1501  err = svcctl_SetServiceStatus( service, status );
1502  }
1504  {
1506  }
1507  __ENDTRY
1508 
1509  if (!set_error( err ))
1510  return FALSE;
1511 
1512  if (status->dwCurrentState == SERVICE_STOPPED)
1513  {
1514  unsigned int i, count = 0;
1516  for (i = 0; i < nb_services; i++)
1517  {
1518  if (services[i]->handle == (SC_HANDLE)service) continue;
1519  if (services[i]->thread) count++;
1520  }
1521  if (!count)
1522  {
1523  stop_service = TRUE;
1524  SetEvent( service_event ); /* notify the main loop */
1525  }
1527  }
1528 
1529  return TRUE;
1530 }
1531 
1533 {
1534  static const WCHAR format[] = L"\\\\.\\pipe\\net\\NtControlPipe%u";
1535  WCHAR *name;
1536  DWORD len;
1538  DWORD service_current;
1539  LONG ret;
1540  DWORD type;
1541 
1543  L"SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent",
1545  if (ret != ERROR_SUCCESS)
1546  return NULL;
1547 
1548  len = sizeof(service_current);
1550  (BYTE *)&service_current, &len );
1552  if (ret != ERROR_SUCCESS || type != REG_DWORD)
1553  return NULL;
1554 
1555  len = ARRAY_SIZE(format) + 10 /* strlenW("4294967295") */;
1556  name = heap_alloc(len * sizeof(WCHAR));
1557  if (!name)
1558  return NULL;
1559 
1560  swprintf( name, len, format, service_current );
1561  return name;
1562 }
1563 
1565 {
1566  WCHAR *pipe_name = service_get_pipe_name();
1568 
1569  do
1570  {
1572  0, NULL, OPEN_ALWAYS, 0, NULL );
1574  break;
1575  if (GetLastError() != ERROR_PIPE_BUSY)
1576  break;
1577  } while (WaitNamedPipeW( pipe_name, NMPWAIT_USE_DEFAULT_WAIT ));
1578  heap_free(pipe_name);
1579 
1580  return handle;
1581 }
1582 
1583 static DWORD WINAPI service_thread( void *arg )
1584 {
1585  struct service_data *info = arg;
1586  WCHAR *str = info->args;
1587  DWORD argc = 0, len = 0;
1588 
1589  TRACE("%p\n", arg);
1590 
1591  while (str[len])
1592  {
1593  len += wcslen( &str[len] ) + 1;
1594  argc++;
1595  }
1596  len++;
1597 
1598  if (info->unicode)
1599  {
1600  WCHAR **argv, *p;
1601 
1602  argv = heap_alloc( (argc+1)*sizeof(*argv) );
1603  for (argc = 0, p = str; *p; p += wcslen( p ) + 1)
1604  argv[argc++] = p;
1605  argv[argc] = NULL;
1606 
1607  info->proc.w( argc, argv );
1608  heap_free( argv );
1609  }
1610  else
1611  {
1612  char *strA, **argv, *p;
1613  DWORD lenA;
1614 
1615  lenA = WideCharToMultiByte( CP_ACP,0, str, len, NULL, 0, NULL, NULL );
1616  strA = heap_alloc(lenA);
1617  WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL);
1618 
1619  argv = heap_alloc( (argc+1)*sizeof(*argv) );
1620  for (argc = 0, p = strA; *p; p += strlen( p ) + 1)
1621  argv[argc++] = p;
1622  argv[argc] = NULL;
1623 
1624  info->proc.a( argc, argv );
1625  heap_free( argv );
1626  heap_free( strA );
1627  }
1628  return 0;
1629 }
1630 
1631 static DWORD service_handle_start( struct service_data *service, const void *data, DWORD data_size )
1632 {
1633  DWORD count = data_size / sizeof(WCHAR);
1634 
1635  if (service->thread)
1636  {
1637  WARN("service is not stopped\n");
1639  }
1640 
1641  heap_free( service->args );
1642  service->args = heap_alloc( (count + 2) * sizeof(WCHAR) );
1643  if (count) memcpy( service->args, data, count * sizeof(WCHAR) );
1644  service->args[count++] = 0;
1645  service->args[count++] = 0;
1646 
1647  service->thread = CreateThread( NULL, 0, service_thread,
1648  service, 0, NULL );
1649  SetEvent( service_event ); /* notify the main loop */
1650  return 0;
1651 }
1652 
1653 static DWORD service_handle_control( struct service_data *service, DWORD control, const void *data, DWORD data_size )
1654 {
1656 
1657  TRACE( "%s control %u data %p data_size %u\n", debugstr_w(service->name), control, data, data_size );
1658 
1659  if (control == SERVICE_CONTROL_START)
1660  ret = service_handle_start( service, data, data_size );
1661  else if (service->handler)
1662  ret = service->handler( control, 0, (void *)data, service->context );
1663  return ret;
1664 }
1665 
1667 {
1668  struct dispatcher_data *disp = arg;
1669 
1670  /* dispatcher loop */
1671  while (1)
1672  {
1673  struct service_data *service;
1675  BYTE *data = NULL;
1676  WCHAR *name;
1677  BOOL r;
1678  DWORD data_size = 0, count, result;
1679 
1680  r = ReadFile( disp->pipe, &info, FIELD_OFFSET(service_start_info,data), &count, NULL );
1681  if (!r)
1682  {
1684  ERR( "pipe read failed error %u\n", GetLastError() );
1685  break;
1686  }
1687  if (count != FIELD_OFFSET(service_start_info,data))
1688  {
1689  ERR( "partial pipe read %u\n", count );
1690  break;
1691  }
1692  if (count < info.total_size)
1693  {
1694  data_size = info.total_size - FIELD_OFFSET(service_start_info,data);
1695  data = heap_alloc( data_size );
1696  r = ReadFile( disp->pipe, data, data_size, &count, NULL );
1697  if (!r)
1698  {
1700  ERR( "pipe read failed error %u\n", GetLastError() );
1701  heap_free( data );
1702  break;
1703  }
1704  if (count != data_size)
1705  {
1706  ERR( "partial pipe read %u/%u\n", count, data_size );
1707  heap_free( data );
1708  break;
1709  }
1710  }
1711 
1713 
1714  /* validate service name */
1715  name = (WCHAR *)data;
1716  if (!info.name_size || data_size < info.name_size * sizeof(WCHAR) || name[info.name_size - 1])
1717  {
1718  ERR( "got request without valid service name\n" );
1719  result = ERROR_INVALID_PARAMETER;
1720  goto done;
1721  }
1722 
1723  if (info.magic != SERVICE_PROTOCOL_MAGIC)
1724  {
1725  ERR( "received invalid request for service %s\n", debugstr_w(name) );
1726  result = ERROR_INVALID_PARAMETER;
1727  goto done;
1728  }
1729 
1730  /* find the service */
1731  if (!(service = find_service_by_name( name )))
1732  {
1733  FIXME( "got request for unknown service %s\n", debugstr_w(name) );
1734  result = ERROR_INVALID_PARAMETER;
1735  goto done;
1736  }
1737 
1738  if (!service->handle)
1739  {
1740  if (!(service->handle = OpenServiceW( disp->manager, name, SERVICE_SET_STATUS )) ||
1741  !(service->full_access_handle = OpenServiceW( disp->manager, name,
1743  FIXME( "failed to open service %s\n", debugstr_w(name) );
1744  }
1745 
1746  data_size -= info.name_size * sizeof(WCHAR);
1747  result = service_handle_control(service, info.control, data_size ?
1748  &data[info.name_size * sizeof(WCHAR)] : NULL, data_size);
1749 
1750  done:
1752  WriteFile( disp->pipe, &result, sizeof(result), &count, NULL );
1753  heap_free( data );
1754  }
1755 
1756  CloseHandle( disp->pipe );
1757  CloseServiceHandle( disp->manager );
1758  heap_free( disp );
1759  return 1;
1760 }
1761 
1762 /* wait for services which accept this type of message to become STOPPED */
1763 static void handle_shutdown_msg(DWORD msg, DWORD accept)
1764 {
1765  SERVICE_STATUS st;
1767  DWORD i, n = 0, sz, timeout = 2000;
1768  ULONGLONG stop_time;
1769  BOOL res, done = TRUE;
1770  SC_HANDLE *wait_handles = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SC_HANDLE) * nb_services );
1771 
1773  for (i = 0; i < nb_services; i++)
1774  {
1776  if (!res || st.dwCurrentState == SERVICE_STOPPED || !(st.dwControlsAccepted & accept))
1777  continue;
1778 
1779  done = FALSE;
1780 
1781  if (accept == SERVICE_ACCEPT_PRESHUTDOWN)
1782  {
1784  (BYTE *)&spi, sizeof(spi), &sz );
1785  if (res)
1786  {
1787  FIXME( "service should be able to delay shutdown\n" );
1788  timeout = max( spi.dwPreshutdownTimeout, timeout );
1789  }
1790  }
1791 
1793  wait_handles[n++] = services[i]->full_access_handle;
1794  }
1796 
1797  /* FIXME: these timeouts should be more generous, but we can't currently delay prefix shutdown */
1798  timeout = min( timeout, 3000 );
1799  stop_time = GetTickCount64() + timeout;
1800 
1801  while (!done && GetTickCount64() < stop_time)
1802  {
1803  done = TRUE;
1804  for (i = 0; i < n; i++)
1805  {
1806  res = QueryServiceStatus( wait_handles[i], &st );
1807  if (!res || st.dwCurrentState == SERVICE_STOPPED)
1808  continue;
1809 
1810  done = FALSE;
1811  Sleep( 100 );
1812  break;
1813  }
1814  }
1815 
1816  HeapFree( GetProcessHeap(), 0, wait_handles );
1817 }
1818 
1820 {
1821  DWORD i, n, ret;
1822  HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
1823  UINT wait_services[MAXIMUM_WAIT_OBJECTS];
1824  struct dispatcher_data *disp = heap_alloc( sizeof(*disp) );
1825 
1827  if (!disp->manager)
1828  {
1829  ERR("failed to open service manager error %u\n", GetLastError());
1830  heap_free( disp );
1831  return FALSE;
1832  }
1833 
1834  disp->pipe = service_open_pipe();
1835  if (disp->pipe == INVALID_HANDLE_VALUE)
1836  {
1837  WARN("failed to create control pipe error %u\n", GetLastError());
1838  CloseServiceHandle( disp->manager );
1839  heap_free( disp );
1841  return FALSE;
1842  }
1843 
1845  stop_service = FALSE;
1846 
1847  /* FIXME: service_control_dispatcher should be merged into the main thread */
1848  wait_handles[0] = __wine_make_process_system();
1849  wait_handles[1] = CreateThread( NULL, 0, service_control_dispatcher, disp, 0, NULL );
1850  wait_handles[2] = service_event;
1851 
1852  TRACE("Starting %d services running as process %d\n",
1854 
1855  /* wait for all the threads to pack up and exit */
1856  while (!stop_service)
1857  {
1859  for (i = 0, n = 3; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
1860  {
1861  if (!services[i]->thread) continue;
1862  wait_services[n] = i;
1863  wait_handles[n++] = services[i]->thread;
1864  }
1866 
1867  ret = WaitForMultipleObjects( n, wait_handles, FALSE, INFINITE );
1868  if (!ret) /* system process event */
1869  {
1872  ExitProcess(0);
1873  }
1874  else if (ret == 1)
1875  {
1876  TRACE( "control dispatcher exited, shutting down\n" );
1877  /* FIXME: we should maybe send a shutdown control to running services */
1878  ExitProcess(0);
1879  }
1880  else if (ret == 2)
1881  {
1882  continue; /* rebuild the list */
1883  }
1884  else if (ret < n)
1885  {
1886  i = wait_services[ret];
1888  CloseHandle( services[i]->thread );
1889  services[i]->thread = NULL;
1891  }
1892  else return FALSE;
1893  }
1894 
1895  return TRUE;
1896 }
1897 
1898 /******************************************************************************
1899  * StartServiceCtrlDispatcherA (sechost.@)
1900  */
1902 {
1903  struct service_data *info;
1904  unsigned int i;
1905 
1906  TRACE("%p\n", servent);
1907 
1908  if (nb_services)
1909  {
1911  return FALSE;
1912  }
1913  while (servent[nb_services].lpServiceName) nb_services++;
1914  if (!nb_services)
1915  {
1917  return FALSE;
1918  }
1919 
1920  services = heap_alloc( nb_services * sizeof(*services) );
1921 
1922  for (i = 0; i < nb_services; i++)
1923  {
1924  DWORD len = MultiByteToWideChar( CP_ACP, 0, servent[i].lpServiceName, -1, NULL, 0 );
1925  DWORD sz = FIELD_OFFSET( struct service_data, name[len] );
1926  info = heap_alloc_zero( sz );
1927  MultiByteToWideChar( CP_ACP, 0, servent[i].lpServiceName, -1, info->name, len );
1928  info->proc.a = servent[i].lpServiceProc;
1929  info->unicode = FALSE;
1930  services[i] = info;
1931  }
1932 
1933  return service_run_main_thread();
1934 }
1935 
1936 /******************************************************************************
1937  * StartServiceCtrlDispatcherW (sechost.@)
1938  */
1940 {
1941  struct service_data *info;
1942  unsigned int i;
1943 
1944  TRACE("%p\n", servent);
1945 
1946  if (nb_services)
1947  {
1949  return FALSE;
1950  }
1951  while (servent[nb_services].lpServiceName) nb_services++;
1952  if (!nb_services)
1953  {
1955  return FALSE;
1956  }
1957 
1958  services = heap_alloc( nb_services * sizeof(*services) );
1959 
1960  for (i = 0; i < nb_services; i++)
1961  {
1962  DWORD len = wcslen( servent[i].lpServiceName ) + 1;
1963  DWORD sz = FIELD_OFFSET( struct service_data, name[len] );
1964  info = heap_alloc_zero( sz );
1965  wcscpy( info->name, servent[i].lpServiceName );
1966  info->proc.w = servent[i].lpServiceProc;
1967  info->unicode = TRUE;
1968  services[i] = info;
1969  }
1970 
1971  return service_run_main_thread();
1972 }
1973 
1975 {
1978 };
1979 
1982 
1984 {
1985  struct list entry;
1987 };
1988 
1989 static DWORD WINAPI device_notify_proc( void *arg )
1990 {
1991  WCHAR endpoint[] = L"\\pipe\\wine_plugplay";
1992  WCHAR protseq[] = L"ncalrpc";
1993  RPC_WSTR binding_str;
1995  struct device_notify_registration *registration;
1996  plugplay_rpc_handle handle = NULL;
1997  DWORD code = 0;
1998  unsigned int size;
1999  BYTE *buf;
2000 
2001  if ((err = RpcStringBindingComposeW( NULL, protseq, NULL, endpoint, NULL, &binding_str )))
2002  {
2003  ERR("RpcStringBindingCompose() failed, error %#x\n", err);
2004  return err;
2005  }
2006  err = RpcBindingFromStringBindingW( binding_str, &plugplay_binding_handle );
2007  RpcStringFreeW( &binding_str );
2008  if (err)
2009  {
2010  ERR("RpcBindingFromStringBinding() failed, error %#x\n", err);
2011  return err;
2012  }
2013 
2014  __TRY
2015  {
2016  handle = plugplay_register_listener();
2017  }
2019  {
2021  }
2022  __ENDTRY
2023 
2024  if (!handle)
2025  {
2026  ERR("failed to open RPC handle, error %u\n", err);
2027  return 1;
2028  }
2029 
2030  for (;;)
2031  {
2032  buf = NULL;
2033  __TRY
2034  {
2035  code = plugplay_get_event( handle, &buf, &size );
2036  err = ERROR_SUCCESS;
2037  }
2039  {
2041  }
2042  __ENDTRY
2043 
2044  if (err)
2045  {
2046  ERR("failed to get event, error %u\n", err);
2047  break;
2048  }
2049 
2052  {
2053  registration->details.cb( registration->details.handle, code, (DEV_BROADCAST_HDR *)buf );
2054  }
2056  MIDL_user_free(buf);
2057  }
2058 
2059  __TRY
2060  {
2061  plugplay_unregister_listener( handle );
2062  }
2064  {
2065  }
2066  __ENDTRY
2067 
2068  RpcBindingFree( &plugplay_binding_handle );
2069  return 0;
2070 }
2071 
2072 /******************************************************************************
2073  * I_ScRegisterDeviceNotification (sechost.@)
2074  */
2076  void *filter, DWORD flags )
2077 {
2078  struct device_notify_registration *registration;
2079 
2080  TRACE("callback %p, handle %p, filter %p, flags %#x\n", details->cb, details->handle, filter, flags);
2081 
2082  if (filter) FIXME("Notification filters are not yet implemented.\n");
2083 
2084  if (!(registration = heap_alloc(sizeof(struct device_notify_registration))))
2085  {
2087  return NULL;
2088  }
2089 
2090  registration->details = *details;
2091 
2093  list_add_tail( &device_notify_list, &registration->entry );
2094 
2095  if (!device_notify_thread)
2097 
2099 
2100  return registration;
2101 }
2102 
2103 /******************************************************************************
2104  * I_ScUnregisterDeviceNotification (sechost.@)
2105  */
2107 {
2108  struct device_notify_registration *registration = handle;
2109 
2110  TRACE("%p\n", handle);
2111 
2112  if (!handle)
2113  return FALSE;
2114 
2116  list_remove( &registration->entry );
2118  heap_free( registration );
2119  return TRUE;
2120 }
const UINT description
Definition: action.c:7430
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7432
ULONG_PTR DWORD_PTR
Definition: basetsd.h:131
unsigned long ULONG_PTR
Definition: basetsd.h:130
ULONG_PTR SIZE_T
Definition: basetsd.h:264
LONG NTSTATUS
Definition: bcrypt.h:40
#define WINAPI
Definition: bcrypt.h:23
enum shader_type type
struct config_s config
Definition: config.pm:10
Definition: type.pm:7
#define ERR(...)
Definition: cocoa_app.h:61
DWORD mask
Definition: fontdlg.c:120
static int WINAPIV swprintf(wchar_t *buffer, size_t size, const wchar_t *format,...)
DETAILS details
Definition: details.c:23
void * dummy
Definition: debugger.c:35
void ExitProcess(DWORD status)
Definition: process.c:204
HANDLE CreateFileW(LPCWSTR filename, DWORD access, DWORD sharing, LPSECURITY_ATTRIBUTES sa, DWORD creation, DWORD attributes, HANDLE template)
Definition: file.c:732
BOOL ReadFile(HANDLE file, LPVOID buffer, DWORD count, LPDWORD result, LPOVERLAPPED overlapped)
Definition: file.c:3344
BOOL WriteFile(HANDLE file, LPCVOID buffer, DWORD count, LPDWORD result, LPOVERLAPPED overlapped)
Definition: file.c:3720
BOOL DuplicateHandle(HANDLE source_process, HANDLE source, HANDLE dest_process, HANDLE *dest, DWORD access, BOOL inherit, DWORD options)
Definition: process.c:656
BOOL IsWow64Process(HANDLE process, PBOOL wow64)
Definition: process.c:1006
BOOL CloseHandle(HANDLE handle)
Definition: process.c:390
LSTATUS RegQueryValueExW(HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
Definition: registry.c:1424
LSTATUS RegOpenKeyExW(HKEY hkey, LPCWSTR name, DWORD options, REGSAM access, PHKEY retkey)
Definition: registry.c:465
LSTATUS RegCloseKey(HKEY hkey)
Definition: registry.c:964
HANDLE CreateThread(SECURITY_ATTRIBUTES *sa, SIZE_T stack, LPTHREAD_START_ROUTINE start, LPVOID param, DWORD flags, LPDWORD id)
Definition: thread.c:111
DWORD QueueUserAPC(PAPCFUNC func, HANDLE thread, ULONG_PTR data)
Definition: thread.c:376
size_t strlen(const char *str)
Definition: string.c:1502
void * memcpy(void *dst, const void *src, size_t n)
Definition: string.c:2580
void * memset(void *dst, int c, size_t n)
Definition: string.c:2588
static LONG rpc_filter(EXCEPTION_POINTERS *eptr)
Definition: service.c:142
SERVICE_STATUS_HANDLE RegisterServiceCtrlHandlerExW(const WCHAR *name, LPHANDLER_FUNCTION_EX handler, void *context)
Definition: service.c:1467
static struct list device_notify_list
Definition: service.c:1981
BOOL DeleteService(SC_HANDLE service)
Definition: service.c:430
BOOL ChangeServiceConfigW(SC_HANDLE service, DWORD service_type, DWORD start_type, DWORD error_control, const WCHAR *path, const WCHAR *group, DWORD *tag, const WCHAR *dependencies, const WCHAR *username, const WCHAR *password, const WCHAR *display_name)
Definition: service.c:589
static DWORD service_control_dispatcher(void *arg)
Definition: service.c:1666
BOOL StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA *servent)
Definition: service.c:1901
SC_HANDLE CreateServiceW(SC_HANDLE manager, const WCHAR *name, const WCHAR *display_name, DWORD access, DWORD service_type, DWORD start_type, DWORD error_control, const WCHAR *path, const WCHAR *group, DWORD *tag, const WCHAR *dependencies, const WCHAR *username, const WCHAR *password)
Definition: service.c:381
static struct service_data * find_service_by_name(const WCHAR *name)
Definition: service.c:1453
BOOL QueryServiceConfigW(SC_HANDLE service, QUERY_SERVICE_CONFIGW *ret_config, DWORD size, DWORD *ret_size)
Definition: service.c:707
static WCHAR * heap_strdupAtoW(const char *src)
Definition: service.c:95
handle_t __RPC_USER SVCCTL_HANDLEW_bind(SVCCTL_HANDLEW name)
Definition: service.c:238
DWORD NotifyServiceStatusChangeW(SC_HANDLE service, DWORD mask, SERVICE_NOTIFYW *notify_buffer)
Definition: service.c:1351
static DWORD service_handle_start(struct service_data *service, const void *data, DWORD data_size)
Definition: service.c:1631
static DWORD multisz_size(const WCHAR *str)
Definition: service.c:122
BOOL StartServiceW(SC_HANDLE service, DWORD argc, const WCHAR **argv)
Definition: service.c:1042
static HANDLE service_event
Definition: service.c:90
BOOL SetServiceStatus(SERVICE_STATUS_HANDLE service, SERVICE_STATUS *status)
Definition: service.c:1491
SC_HANDLE OpenServiceA(SC_HANDLE manager, const char *name, DWORD access)
Definition: service.c:298
static handle_t rpc_cstr_bind(RPC_CSTR str)
Definition: service.c:191
void __RPC_USER MACHINE_HANDLEA_unbind(MACHINE_HANDLEA name, handle_t h)
Definition: service.c:223
SC_HANDLE CreateServiceA(SC_HANDLE manager, const char *name, const char *display_name, DWORD access, DWORD service_type, DWORD start_type, DWORD error_control, const char *path, const char *group, DWORD *tag, const char *dependencies, const char *username, const char *password)
Definition: service.c:345
handle_t __RPC_USER MACHINE_HANDLEW_bind(MACHINE_HANDLEW name)
Definition: service.c:228
BOOL CloseServiceHandle(SC_HANDLE handle)
Definition: service.c:452
static DWORD notify_thread(void *user)
Definition: service.c:1285
static struct service_data ** services
Definition: service.c:88
BOOL SetServiceObjectSecurity(SC_HANDLE hService, SECURITY_INFORMATION dwSecurityInformation, PSECURITY_DESCRIPTOR lpSecurityDescriptor)
Definition: service.c:1277
BOOL ChangeServiceConfig2W(SC_HANDLE service, DWORD level, void *info)
Definition: service.c:520
void __RPC_USER MIDL_user_free(void __RPC_FAR *ptr)
Definition: service.c:137
BOOL QueryServiceConfig2A(SC_HANDLE service, DWORD level, BYTE *buffer, DWORD size, DWORD *ret_size)
Definition: service.c:773
BOOL StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW *servent)
Definition: service.c:1939
handle_t __RPC_USER MACHINE_HANDLEA_bind(MACHINE_HANDLEA name)
Definition: service.c:218
BOOL QueryServiceStatus(SC_HANDLE service, SERVICE_STATUS *status)
Definition: service.c:1086
BOOL GetServiceDisplayNameW(SC_HANDLE manager, const WCHAR *service, WCHAR *display_name, DWORD *len)
Definition: service.c:923
static HANDLE service_open_pipe(void)
Definition: service.c:1564
HDEVNOTIFY I_ScRegisterDeviceNotification(struct device_notification_details *details, void *filter, DWORD flags)
Definition: service.c:2075
SC_HANDLE OpenSCManagerA(const char *machine, const char *database, DWORD access)
Definition: service.c:257
SC_HANDLE OpenServiceW(SC_HANDLE manager, const WCHAR *name, DWORD access)
Definition: service.c:314
static BOOL stop_service
Definition: service.c:91
static handle_t rpc_wstr_bind(RPC_WSTR str)
Definition: service.c:164
static BOOL service_run_main_thread(void)
Definition: service.c:1819
SERVICE_STATUS_HANDLE RegisterServiceCtrlHandlerA(const char *name, LPHANDLER_FUNCTION handler)
Definition: service.c:1423
static CRITICAL_SECTION_DEBUG service_cs_debug
Definition: service.c:56
static unsigned int nb_services
Definition: service.c:89
BOOL EnumDependentServicesW(SC_HANDLE hService, DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned)
Definition: service.c:1237
static DWORD device_notify_proc(void *arg)
Definition: service.c:1989
static DWORD ctrl_handler_thunk(DWORD control, DWORD type, void *data, void *context)
Definition: service.c:1412
static DWORD size_string(const WCHAR *string)
Definition: service.c:699
BOOL QueryServiceStatusEx(SC_HANDLE service, SC_STATUS_TYPE level, BYTE *buffer, DWORD size, DWORD *ret_size)
Definition: service.c:1106
SC_HANDLE OpenSCManagerW(const WCHAR *machine, const WCHAR *database, DWORD access)
Definition: service.c:273
HANDLE __wine_make_process_system(void)
Definition: process.c:1763
SERVICE_STATUS_HANDLE RegisterServiceCtrlHandlerW(const WCHAR *name, LPHANDLER_FUNCTION handler)
Definition: service.c:1432
void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW name, handle_t h)
Definition: service.c:233
static WCHAR * heap_strdup_multi_AtoW(const char *src)
Definition: service.c:106
BOOL ChangeServiceConfig2A(SC_HANDLE service, DWORD level, void *info)
Definition: service.c:474
static DWORD move_string_to_buffer(BYTE **buf, WCHAR **string_ptr)
Definition: service.c:677
BOOL QueryServiceConfig2W(SC_HANDLE service, DWORD level, BYTE *buffer, DWORD size, DWORD *ret_size)
Definition: service.c:821
void __RPC_USER SVCCTL_HANDLEW_unbind(SVCCTL_HANDLEW name, handle_t h)
Definition: service.c:243
void __RPC_FAR *__RPC_USER MIDL_user_allocate(SIZE_T len)
Definition: service.c:132
BOOL QueryServiceObjectSecurity(SC_HANDLE service, SECURITY_INFORMATION type, PSECURITY_DESCRIPTOR ret_descriptor, DWORD size, DWORD *ret_size)
Definition: service.c:1251
static HANDLE device_notify_thread
Definition: service.c:1980
SERVICE_STATUS_HANDLE RegisterServiceCtrlHandlerExA(const char *name, LPHANDLER_FUNCTION_EX handler, void *context)
Definition: service.c:1441
BOOL ChangeServiceConfigA(SC_HANDLE service, DWORD service_type, DWORD start_type, DWORD error_control, const char *path, const char *group, DWORD *tag, const char *dependencies, const char *username, const char *password, const char *display_name)
Definition: service.c:554
BOOL I_ScUnregisterDeviceNotification(HDEVNOTIFY handle)
Definition: service.c:2106
static DWORD service_handle_control(struct service_data *service, DWORD control, const void *data, DWORD data_size)
Definition: service.c:1653
BOOL StartServiceA(SC_HANDLE service, DWORD argc, const char **argv)
Definition: service.c:1018
BOOL EnumServicesStatusExW(SC_HANDLE manager, SC_ENUM_TYPE level, DWORD type, DWORD state, BYTE *buffer, DWORD size, DWORD *needed, DWORD *returned, DWORD *resume_handle, const WCHAR *group)
Definition: service.c:1137
static void handle_shutdown_msg(DWORD msg, DWORD accept)
Definition: service.c:1763
static struct list notify_list
Definition: service.c:53
static WCHAR * service_get_pipe_name(void)
Definition: service.c:1532
BOOL ControlService(SC_HANDLE service, DWORD control, SERVICE_STATUS *status)
Definition: service.c:1064
#define MAP_STR(str)
static CRITICAL_SECTION service_cs
Definition: service.c:55
static DWORD service_thread(void *arg)
Definition: service.c:1583
BOOL QueryServiceConfigA(SC_HANDLE service, QUERY_SERVICE_CONFIGA *config, DWORD size, DWORD *ret_size)
Definition: service.c:621
static BOOL set_error(DWORD err)
Definition: service.c:248
static DWORD map_exception_code(DWORD exception_code)
Definition: service.c:147
BOOL GetServiceKeyNameW(SC_HANDLE manager, const WCHAR *display_name, WCHAR *key_name, DWORD *len)
Definition: service.c:970
@ L
Definition: bidi.c:78
unsigned int UINT
Definition: dxgicommon.idl:20
long BOOL
Definition: dxgitype.idl:24
NTSTATUS status
Definition: except.c:81
#define __TRY
Definition: exception.h:136
#define __ENDTRY
Definition: exception.h:179
#define __EXCEPT(func)
Definition: exception.h:143
#define GetExceptionCode()
Definition: exception.h:222
GLuint err
Definition: glu.c:32
const char * str
Definition: glu.c:32
static void heap_free(void *mem)
Definition: heap.h:44
#define WINE_DEFAULT_DEBUG_CHANNEL(ch)
Definition: debug.h:499
#define SERVICE_CONFIG_DESCRIPTION
Definition: svcctl.idl:163
SERVICE_CONTROL_FORWARD_FLAG struct service_start_info_t service_start_info
#define SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO
Definition: svcctl.idl:168
#define SERVICE_CONFIG_PRESHUTDOWN_INFO
Definition: svcctl.idl:169
#define SERVICE_CONFIG_FAILURE_ACTIONS
Definition: svcctl.idl:164
static int access(const char *path, int mode)
Definition: io.h:110
BYTE flags
Definition: ioports.c:48
ULONGLONG GetTickCount64(void)
Definition: sync.c:84
WCHAR key_name[128]
Definition: locale.c:4138
INT WideCharToMultiByte(UINT codepage, DWORD flags, LPCWSTR src, INT srclen, LPSTR dst, INT dstlen, LPCSTR defchar, BOOL *used)
Definition: locale.c:5806
INT MultiByteToWideChar(UINT codepage, DWORD flags, const char *src, INT srclen, WCHAR *dst, INT dstlen)
Definition: locale.c:5510
BOOL InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR descr, DWORD revision)
Definition: security.c:1151
BOOL InitializeAcl(PACL acl, DWORD size, DWORD rev)
Definition: security.c:1469
BOOL SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR descr, BOOL present, PACL dacl, BOOL defaulted)
Definition: security.c:1250
HANDLE CreateEventW(SECURITY_ATTRIBUTES *sa, BOOL manual_reset, BOOL initial_state, LPCWSTR name)
Definition: sync.c:391
DWORD WaitForMultipleObjects(DWORD count, const HANDLE *handles, BOOL wait_all, DWORD timeout)
Definition: sync.c:317
BOOL WaitNamedPipeW(LPCWSTR name, DWORD timeout)
Definition: sync.c:1452
BOOL SetEvent(HANDLE handle)
Definition: sync.c:504
void Sleep(DWORD timeout)
Definition: sync.c:265
struct version_info info
Definition: version.c:140
BOOL is_wow64
Definition: main.c:37
static void list_remove(struct list *elem)
Definition: list.h:98
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:188
#define LIST_INIT(list)
Definition: list.h:227
static void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:92
#define DECLSPEC_HIDDEN
Definition: macdrv_cocoa.h:96
#define min(a, b)
Definition: minmax.h:28
#define max(a, b)
Definition: minmax.h:25
MonoAssembly int argc
static void size_t len
void * buffer
Definition: ntddk.h:198
ULONG RtlNtStatusToDosError(NTSTATUS status)
Definition: error.c:79
ULONG offset
Definition: error.c:1729
USHORT * data
Definition: env.c:81
HRESULT(* func)(HTMLDocumentNode *, DWORD, VARIANT *, VARIANT *)
Definition: olecmd.c:734
static void size_t size
Definition: oledb_private.h:32
plugplay_rpc_handle plugplay_register_listener(void)
Definition: main.c:94
DWORD plugplay_get_event(plugplay_rpc_handle handle, BYTE **data, unsigned int *size)
Definition: main.c:111
void plugplay_unregister_listener(plugplay_rpc_handle handle)
Definition: main.c:135
DWORD svcctl_ChangeServiceConfigW(SC_RPC_HANDLE hService, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName, LPCWSTR lpLoadOrderGroup, DWORD *lpdwTagId, const BYTE *lpDependencies, DWORD dwDependenciesSize, LPCWSTR lpServiceStartName, const BYTE *lpPassword, DWORD dwPasswordSize, LPCWSTR lpDisplayName)
Definition: rpc.c:718
DWORD svcctl_ControlService(SC_RPC_HANDLE hService, DWORD dwControl, SERVICE_STATUS *lpServiceStatus)
Definition: rpc.c:1240
DWORD svcctl_DeleteService(SC_RPC_HANDLE hService)
Definition: rpc.c:668
DWORD svcctl_OpenServiceW(SC_RPC_HANDLE hSCManager, LPCWSTR lpServiceName, DWORD dwDesiredAccess, SC_RPC_HANDLE *phService)
Definition: rpc.c:447
DWORD svcctl_NotifyServiceStatusChange(SC_RPC_HANDLE handle, SC_RPC_NOTIFY_PARAMS params, GUID *clientprocessguid, GUID *scmprocessguid, BOOL *createremotequeue, SC_NOTIFY_RPC_HANDLE *hNotify)
Definition: rpc.c:1670
DWORD svcctl_CreateServiceW(SC_RPC_HANDLE hSCManager, LPCWSTR lpServiceName, LPCWSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName, LPCWSTR lpLoadOrderGroup, DWORD *lpdwTagId, const BYTE *lpDependencies, DWORD dwDependenciesSize, LPCWSTR lpServiceStartName, const BYTE *lpPassword, DWORD dwPasswordSize, SC_RPC_HANDLE *phService)
Definition: rpc.c:644
DWORD svcctl_CloseNotifyHandle(SC_NOTIFY_RPC_HANDLE *hNotify, BOOL *apc_fired)
Definition: rpc.c:1789
DWORD svcctl_GetServiceKeyNameW(SC_RPC_HANDLE hSCManager, LPCWSTR lpServiceDisplayName, WCHAR *lpBuffer, DWORD *cchBufSize)
Definition: rpc.c:377
DWORD svcctl_ChangeServiceConfig2W(SC_RPC_HANDLE hService, SC_RPC_CONFIG_INFOW config)
Definition: rpc.c:923
DWORD svcctl_SetServiceStatus(SC_RPC_HANDLE handle, SERVICE_STATUS *status)
Definition: rpc.c:869
DWORD svcctl_OpenSCManagerW(MACHINE_HANDLEW MachineName, LPCWSTR DatabaseName, DWORD dwAccessMask, SC_RPC_HANDLE *handle)
Definition: rpc.c:268
DWORD svcctl_QueryServiceConfig2W(SC_RPC_HANDLE hService, DWORD level, BYTE *buffer, DWORD size, LPDWORD needed)
Definition: rpc.c:976
DWORD svcctl_EnumServicesStatusExW(SC_RPC_HANDLE hmngr, SC_ENUM_TYPE info_level, DWORD type, DWORD state, BYTE *buffer, DWORD size, LPDWORD needed, LPDWORD returned, DWORD *resume_handle, LPCWSTR group)
Definition: rpc.c:1523
DWORD svcctl_StartServiceW(SC_RPC_HANDLE hService, DWORD dwNumServiceArgs, LPCWSTR *lpServiceArgVectors)
Definition: rpc.c:1215
DWORD svcctl_GetNotifyResults(SC_NOTIFY_RPC_HANDLE hNotify, SC_RPC_NOTIFY_PARAMS_LIST **pList)
Definition: rpc.c:1750
DWORD svcctl_CreateServiceWOW64W(SC_RPC_HANDLE scmanager, LPCWSTR servicename, LPCWSTR displayname, DWORD accessmask, DWORD service_type, DWORD start_type, DWORD error_control, LPCWSTR imagepath, LPCWSTR loadordergroup, DWORD *tagid, const BYTE *dependencies, DWORD depend_size, LPCWSTR start_name, const BYTE *password, DWORD password_size, SC_RPC_HANDLE *service)
Definition: rpc.c:1641
DWORD svcctl_QueryServiceConfigW(SC_RPC_HANDLE hService, QUERY_SERVICE_CONFIGW *config, DWORD buf_size, DWORD *needed_size)
Definition: rpc.c:689
DWORD svcctl_QueryServiceStatusEx(SC_RPC_HANDLE hService, SC_STATUS_TYPE InfoLevel, BYTE *lpBuffer, DWORD cbBufSize, LPDWORD pcbBytesNeeded)
Definition: rpc.c:1037
DWORD svcctl_CloseServiceHandle(SC_RPC_HANDLE *handle)
Definition: rpc.c:1357
DWORD svcctl_GetServiceDisplayNameW(SC_RPC_HANDLE hSCManager, LPCWSTR lpServiceName, WCHAR *lpBuffer, DWORD *cchBufSize)
Definition: rpc.c:333
static HKEY service_current_key
Definition: services.c:49
char * tag
Definition: main.c:53
void * heap_alloc(size_t len)
Definition: util.c:30
WCHAR name[22]
Definition: registrar.c:32
RPC_STATUS RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq, RPC_CSTR NetworkAddr, RPC_CSTR Endpoint, RPC_CSTR Options, RPC_CSTR *StringBinding)
Definition: rpc_binding.c:457
RPC_STATUS RpcBindingFromStringBindingA(RPC_CSTR StringBinding, RPC_BINDING_HANDLE *Binding)
Definition: rpc_binding.c:835
RPC_STATUS RpcBindingFromStringBindingW(RPC_WSTR StringBinding, RPC_BINDING_HANDLE *Binding)
Definition: rpc_binding.c:875
RPC_STATUS RpcBindingFree(RPC_BINDING_HANDLE *Binding)
Definition: rpc_binding.c:782
RPC_STATUS RpcStringBindingComposeW(RPC_WSTR ObjUuid, RPC_WSTR Protseq, RPC_WSTR NetworkAddr, RPC_WSTR Endpoint, RPC_WSTR Options, RPC_WSTR *StringBinding)
Definition: rpc_binding.c:510
RPCRTAPI int RPC_ENTRY I_RpcExceptionFilter(ULONG)
unsigned short * RPC_WSTR
Definition: rpcdce.h:46
unsigned char * RPC_CSTR
Definition: rpcdce.h:45
RPC_BINDING_HANDLE handle_t
Definition: rpcdce.h:51
#define RPC_S_OK
Definition: rpcnterr.h:22
RPC_STATUS RpcStringFreeW(RPC_WSTR *String)
Definition: rpcrt4_main.c:180
RPC_STATUS RpcStringFreeA(RPC_CSTR *String)
Definition: rpcrt4_main.c:164
NTSTATUS RtlMakeSelfRelativeSD(PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, LPDWORD lpdwBufferLength)
Definition: sec.c:836
Definition: windef.h:320
Definition: winnt.h:4397
PEXCEPTION_RECORD ExceptionRecord
Definition: winnt.h:2731
DWORD ExceptionCode
Definition: winnt.h:2694
LPWSTR lpServiceStartName
Definition: winsvc.h:283
LPWSTR lpBinaryPathName
Definition: winsvc.h:279
LPWSTR lpLoadOrderGroup
Definition: winsvc.h:280
LIST_ENTRY ProcessLocksList
Definition: winnt.h:6198
LPWSTR lpDescription
Definition: winsvc.h:302
SC_ACTION * lpsaActions
Definition: winsvc.h:325
SC_ACTION * lpsaActions
Definition: winsvc.h:333
DWORD dwControlsAccepted
Definition: winsvc.h:143
DWORD dwCurrentState
Definition: winsvc.h:142
LPSERVICE_MAIN_FUNCTIONA lpServiceProc
Definition: winsvc.h:216
LPWSTR lpServiceName
Definition: winsvc.h:220
LPSERVICE_MAIN_FUNCTIONW lpServiceProc
Definition: winsvc.h:221
Definition: inflate.c:134
DWORD(* cb)(HANDLE handle, DWORD flags, DEV_BROADCAST_HDR *header)
Definition: service.c:1976
struct device_notification_details details
Definition: service.c:1986
SC_HANDLE manager
Definition: service.c:84
HANDLE pipe
Definition: service.c:85
Definition: filter.c:165
Definition: token.c:125
Definition: signal.c:51
Definition: msg.c:48
Definition: list.h:27
Definition: main.c:535
Definition: msg.c:61
Definition: name.c:36
SC_RPC_NOTIFY_PARAMS params
Definition: service.c:45
HANDLE calling_thread
Definition: service.c:49
SC_HANDLE service
Definition: service.c:44
SC_NOTIFY_RPC_HANDLE notify_handle
Definition: service.c:47
struct list entry
Definition: service.c:50
HANDLE ready_evt
Definition: service.c:49
SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2 cparams
Definition: service.c:46
SERVICE_NOTIFYW * notify_buffer
Definition: service.c:48
Definition: wrctypes.h:93
HANDLE thread
Definition: service.c:69
LPHANDLER_FUNCTION_EX handler
Definition: service.c:67
void * context
Definition: service.c:68
unsigned int unicode
Definition: service.c:72
SC_HANDLE handle
Definition: service.c:70
WCHAR * args
Definition: service.c:78
WCHAR name[1]
Definition: service.c:79
union service_data::@409 proc
LPSERVICE_MAIN_FUNCTIONW w
Definition: service.c:76
SC_HANDLE full_access_handle
Definition: service.c:71
LPSERVICE_MAIN_FUNCTIONA a
Definition: service.c:75
Definition: ticket.c:41
Definition: thread.h:50
#define NULL
Definition: ungif.h:66
#define TRUE
Definition: ungif.h:59
#define FALSE
Definition: ungif.h:62
#define wcslen(str)
Definition: unix_private.h:469
#define wcscpy(dst, src)
Definition: unix_private.h:470
#define wcsicmp(s1, s2)
Definition: unix_private.h:477
BATCH_CONTEXT * context
Definition: wcmdmain.c:38
YY_BUFFER_STATE state
Definition: parser.l:85
#define ARRAY_SIZE(x)
Definition: utils.h:37
DECLSPEC_IMPORT DWORD WINAPI GetLastError(void)
DECLSPEC_IMPORT DWORD WINAPI GetCurrentProcessId(void)
DECLSPEC_IMPORT void WINAPI LeaveCriticalSection(CRITICAL_SECTION *lpCrit)
DECLSPEC_IMPORT HANDLE WINAPI GetCurrentProcess(void)
#define NMPWAIT_USE_DEFAULT_WAIT
Definition: winbase.h:922
#define INVALID_HANDLE_VALUE
Definition: winbase.h:336
DECLSPEC_IMPORT BOOL WINAPI HeapFree(HANDLE, DWORD, LPVOID)
DECLSPEC_IMPORT VOID WINAPI SetLastError(DWORD)
DECLSPEC_IMPORT HANDLE WINAPI GetCurrentThread(void)
#define OPEN_ALWAYS
Definition: winbase.h:731
#define INFINITE
Definition: winbase.h:377
DECLSPEC_IMPORT HANDLE WINAPI GetProcessHeap(void)
DECLSPEC_IMPORT void WINAPI EnterCriticalSection(CRITICAL_SECTION *lpCrit)
DECLSPEC_IMPORT LPVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T) __WINE_ALLOC_SIZE(3)
#define CDECL
Definition: windef.h:198
unsigned char BYTE
Definition: windef.h:250
unsigned int * LPDWORD
Definition: windef.h:261
unsigned int DWORD
Definition: windef.h:261
#define CALLBACK
Definition: windef.h:194
#define ERROR_NOT_ENOUGH_MEMORY
Definition: winerror.h:118
#define ERROR_INVALID_ADDRESS
Definition: winerror.h:417
#define ERROR_INVALID_PARAMETER
Definition: winerror.h:178
#define ERROR_SERVICE_ALREADY_RUNNING
Definition: winerror.h:722
#define ERROR_INVALID_LEVEL
Definition: winerror.h:203
#define RPC_X_ENUM_VALUE_OUT_OF_RANGE
Definition: winerror.h:1229
#define RPC_X_SS_IN_NULL_CONTEXT
Definition: winerror.h:1224
#define ERROR_MORE_DATA
Definition: winerror.h:293
#define ERROR_BROKEN_PIPE
Definition: winerror.h:190
#define ERROR_PIPE_BUSY
Definition: winerror.h:290
#define ERROR_SERVICE_DOES_NOT_EXIST
Definition: winerror.h:726
#define RPC_X_NULL_REF_POINTER
Definition: winerror.h:1228
#define ERROR_INSUFFICIENT_BUFFER
Definition: winerror.h:201
#define RPC_X_BYTE_COUNT_TOO_SMALL
Definition: winerror.h:1230
#define ERROR_INVALID_HANDLE
Definition: winerror.h:116
#define ERROR_INVALID_SERVICE_CONTROL
Definition: winerror.h:718
#define ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
Definition: winerror.h:729
#define RPC_S_INVALID_BINDING
Definition: winerror.h:1153
#define ERROR_SUCCESS
Definition: winerror.h:110
#define CP_ACP
Definition: winnls.h:358
#define DACL_SECURITY_INFORMATION
Definition: winnt.h:6012
unsigned short WCHAR
Definition: winnt.h:468
PVOID PSECURITY_DESCRIPTOR
Definition: winnt.h:4258
#define FIELD_OFFSET(type, field)
Definition: winnt.h:822
#define MAXIMUM_WAIT_OBJECTS
Definition: winnt.h:2665
#define DECLSPEC_HOTPATCH
Definition: winnt.h:184
#define KEY_QUERY_VALUE
Definition: winnt.h:6040
#define GENERIC_READ
Definition: winnt.h:5390
int LONG
Definition: winnt.h:459
#define SECURITY_DESCRIPTOR_REVISION
Definition: winnt.h:4424
#define DUPLICATE_SAME_ACCESS
Definition: winnt.h:5528
unsigned long long ULONGLONG
Definition: winnt.h:485
#define ACL_REVISION
Definition: winnt.h:4395
DWORD SECURITY_INFORMATION
Definition: winnt.h:4577
#define REG_DWORD
Definition: winnt.h:5633
#define GENERIC_WRITE
Definition: winnt.h:5391
#define HEAP_ZERO_MEMORY
Definition: winnt.h:906
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:30
#define SERVICE_ACCEPT_PRESHUTDOWN
Definition: winsvc.h:87
#define SERVICE_STOPPED
Definition: winsvc.h:70
@ SC_STATUS_PROCESS_INFO
Definition: winsvc.h:203
VOID(CALLBACK * LPSERVICE_MAIN_FUNCTIONA)(DWORD, LPSTR *)
Definition: winsvc.h:208
#define SC_MANAGER_CONNECT
Definition: winsvc.h:92
struct _QUERY_SERVICE_CONFIGW QUERY_SERVICE_CONFIGW
VOID(WINAPI * LPHANDLER_FUNCTION)(DWORD)
Definition: winsvc.h:384
#define SERVICE_CONTROL_SHUTDOWN
Definition: winsvc.h:57
DWORD(WINAPI * LPHANDLER_FUNCTION_EX)(DWORD, DWORD, LPVOID, LPVOID)
Definition: winsvc.h:385
#define SERVICE_CONTROL_PRESHUTDOWN
Definition: winsvc.h:67
enum _SC_STATUS_TYPE SC_STATUS_TYPE
#define SERVICE_ACCEPT_SHUTDOWN
Definition: winsvc.h:81
enum _SC_ENUM_TYPE SC_ENUM_TYPE
@ SC_ENUM_PROCESS_INFO
Definition: winsvc.h:260
struct _SERVICE_STATUS_PROCESS SERVICE_STATUS_PROCESS
VOID(CALLBACK * LPSERVICE_MAIN_FUNCTIONW)(DWORD, LPWSTR *)
Definition: winsvc.h:209
PVOID HDEVNOTIFY
Definition: winuser.h:3114
static void * heap_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: wusa.h:88