advapi32: Return from StartServiceCtrlDispatcher when service status is changed to...
[wine/multimedia.git] / dlls / advapi32 / service.c
blob1f585dcd8b6d36a1324e9ae4b8308acc939030a5
1 /*
2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
5 * Copyright 2005 Mike McCormack
6 * Copyright 2007 Rolf Kalbermatter
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.
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.
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
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <string.h>
28 #include <time.h>
29 #include <assert.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winsvc.h"
34 #include "winerror.h"
35 #include "winreg.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
38 #include "winternl.h"
39 #include "lmcons.h"
40 #include "lmserver.h"
42 #include "svcctl.h"
44 #include "advapi32_misc.h"
46 #include "wine/exception.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(service);
50 void __RPC_FAR * __RPC_USER MIDL_user_allocate(SIZE_T len)
52 return HeapAlloc(GetProcessHeap(), 0, len);
55 void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
57 HeapFree(GetProcessHeap(), 0, ptr);
60 typedef struct service_data_t
62 LPHANDLER_FUNCTION_EX handler;
63 LPVOID context;
64 HANDLE thread;
65 SC_HANDLE handle;
66 SC_HANDLE full_access_handle;
67 BOOL unicode : 1;
68 union {
69 LPSERVICE_MAIN_FUNCTIONA a;
70 LPSERVICE_MAIN_FUNCTIONW w;
71 } proc;
72 LPWSTR args;
73 WCHAR name[1];
74 } service_data;
76 static CRITICAL_SECTION service_cs;
77 static CRITICAL_SECTION_DEBUG service_cs_debug =
79 0, 0, &service_cs,
80 { &service_cs_debug.ProcessLocksList,
81 &service_cs_debug.ProcessLocksList },
82 0, 0, { (DWORD_PTR)(__FILE__ ": service_cs") }
84 static CRITICAL_SECTION service_cs = { &service_cs_debug, -1, 0, 0, 0, 0 };
86 static service_data **services;
87 static unsigned int nb_services;
88 static HANDLE service_event;
89 static HANDLE stop_event;
91 extern HANDLE CDECL __wine_make_process_system(void);
93 /******************************************************************************
94 * String management functions (same behaviour as strdup)
95 * NOTE: the caller of those functions is responsible for calling HeapFree
96 * in order to release the memory allocated by those functions.
98 LPWSTR SERV_dup( LPCSTR str )
100 UINT len;
101 LPWSTR wstr;
103 if( !str )
104 return NULL;
105 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
106 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
107 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
108 return wstr;
111 static inline LPWSTR SERV_dupmulti(LPCSTR str)
113 UINT len = 0, n = 0;
114 LPWSTR wstr;
116 if( !str )
117 return NULL;
118 do {
119 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
120 n += (strlen( &str[n] ) + 1);
121 } while (str[n]);
122 len++;
123 n++;
125 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
126 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
127 return wstr;
130 static inline DWORD multisz_cb(LPCWSTR wmultisz)
132 const WCHAR *wptr = wmultisz;
134 if (wmultisz == NULL)
135 return 0;
137 while (*wptr)
138 wptr += lstrlenW(wptr)+1;
139 return (wptr - wmultisz + 1)*sizeof(WCHAR);
142 /******************************************************************************
143 * RPC connection with services.exe
146 DECLSPEC_HIDDEN handle_t __RPC_USER MACHINE_HANDLEW_bind(MACHINE_HANDLEW MachineName)
148 WCHAR transport[] = SVCCTL_TRANSPORT;
149 WCHAR endpoint[] = SVCCTL_ENDPOINT;
150 RPC_WSTR binding_str;
151 RPC_STATUS status;
152 handle_t rpc_handle;
154 status = RpcStringBindingComposeW(NULL, transport, (RPC_WSTR)MachineName, endpoint, NULL, &binding_str);
155 if (status != RPC_S_OK)
157 ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD)status);
158 return NULL;
161 status = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
162 RpcStringFreeW(&binding_str);
164 if (status != RPC_S_OK)
166 ERR("Couldn't connect to services.exe: error code %u\n", (DWORD)status);
167 return NULL;
170 return rpc_handle;
173 DECLSPEC_HIDDEN void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName, handle_t h)
175 RpcBindingFree(&h);
178 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr)
180 return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode);
183 static DWORD map_exception_code(DWORD exception_code)
185 switch (exception_code)
187 case RPC_X_NULL_REF_POINTER:
188 return ERROR_INVALID_ADDRESS;
189 case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
190 case RPC_X_BYTE_COUNT_TOO_SMALL:
191 return ERROR_INVALID_PARAMETER;
192 case RPC_S_INVALID_BINDING:
193 case RPC_X_SS_IN_NULL_CONTEXT:
194 return ERROR_INVALID_HANDLE;
195 default:
196 return exception_code;
200 /******************************************************************************
201 * Service IPC functions
203 static LPWSTR service_get_pipe_name(void)
205 static const WCHAR format[] = { '\\','\\','.','\\','p','i','p','e','\\',
206 'n','e','t','\\','N','t','C','o','n','t','r','o','l','P','i','p','e','%','u',0};
207 static const WCHAR service_current_key_str[] = { 'S','Y','S','T','E','M','\\',
208 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
209 'C','o','n','t','r','o','l','\\',
210 'S','e','r','v','i','c','e','C','u','r','r','e','n','t',0};
211 LPWSTR name;
212 DWORD len;
213 HKEY service_current_key;
214 DWORD service_current;
215 LONG ret;
216 DWORD type;
218 ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, service_current_key_str, 0,
219 KEY_QUERY_VALUE, &service_current_key);
220 if (ret != ERROR_SUCCESS)
221 return NULL;
222 len = sizeof(service_current);
223 ret = RegQueryValueExW(service_current_key, NULL, NULL, &type,
224 (BYTE *)&service_current, &len);
225 RegCloseKey(service_current_key);
226 if (ret != ERROR_SUCCESS || type != REG_DWORD)
227 return NULL;
228 len = sizeof(format)/sizeof(WCHAR) + 10 /* strlenW("4294967295") */;
229 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
230 if (!name)
231 return NULL;
232 snprintfW(name, len, format, service_current);
233 return name;
236 static HANDLE service_open_pipe(void)
238 LPWSTR szPipe = service_get_pipe_name();
239 HANDLE handle = INVALID_HANDLE_VALUE;
241 do {
242 handle = CreateFileW(szPipe, GENERIC_READ|GENERIC_WRITE,
243 0, NULL, OPEN_ALWAYS, 0, NULL);
244 if (handle != INVALID_HANDLE_VALUE)
245 break;
246 if (GetLastError() != ERROR_PIPE_BUSY)
247 break;
248 } while (WaitNamedPipeW(szPipe, NMPWAIT_USE_DEFAULT_WAIT));
249 HeapFree(GetProcessHeap(), 0, szPipe);
251 return handle;
254 static service_data *find_service_by_name( const WCHAR *name )
256 unsigned int i;
258 if (nb_services == 1) /* only one service (FIXME: should depend on OWN_PROCESS etc.) */
259 return services[0];
260 for (i = 0; i < nb_services; i++)
261 if (!strcmpiW( name, services[i]->name )) return services[i];
262 return NULL;
265 /******************************************************************************
266 * service_thread
268 * Call into the main service routine provided by StartServiceCtrlDispatcher.
270 static DWORD WINAPI service_thread(LPVOID arg)
272 service_data *info = arg;
273 LPWSTR str = info->args;
274 DWORD argc = 0, len = 0;
276 TRACE("%p\n", arg);
278 while (str[len])
280 len += strlenW(&str[len]) + 1;
281 argc++;
283 len++;
285 if (info->unicode)
287 LPWSTR *argv, p;
289 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR));
290 for (argc=0, p=str; *p; p += strlenW(p) + 1)
291 argv[argc++] = p;
292 argv[argc] = NULL;
294 info->proc.w(argc, argv);
295 HeapFree(GetProcessHeap(), 0, argv);
297 else
299 LPSTR strA, *argv, p;
300 DWORD lenA;
302 lenA = WideCharToMultiByte(CP_ACP,0, str, len, NULL, 0, NULL, NULL);
303 strA = HeapAlloc(GetProcessHeap(), 0, lenA);
304 WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL);
306 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPSTR));
307 for (argc=0, p=strA; *p; p += strlen(p) + 1)
308 argv[argc++] = p;
309 argv[argc] = NULL;
311 info->proc.a(argc, argv);
312 HeapFree(GetProcessHeap(), 0, argv);
313 HeapFree(GetProcessHeap(), 0, strA);
315 return 0;
318 /******************************************************************************
319 * service_handle_start
321 static DWORD service_handle_start(service_data *service, const WCHAR *data, DWORD count)
323 TRACE("%s argsize %u\n", debugstr_w(service->name), count);
325 if (service->thread)
327 WARN("service is not stopped\n");
328 return ERROR_SERVICE_ALREADY_RUNNING;
331 HeapFree(GetProcessHeap(), 0, service->args);
332 service->args = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
333 memcpy( service->args, data, count * sizeof(WCHAR) );
334 service->thread = CreateThread( NULL, 0, service_thread,
335 service, 0, NULL );
336 SetEvent( service_event ); /* notify the main loop */
337 return 0;
340 /******************************************************************************
341 * service_handle_control
343 static DWORD service_handle_control(const service_data *service, DWORD dwControl)
345 DWORD ret = ERROR_INVALID_SERVICE_CONTROL;
347 TRACE("%s control %u\n", debugstr_w(service->name), dwControl);
349 if (service->handler)
350 ret = service->handler(dwControl, 0, NULL, service->context);
351 return ret;
354 /******************************************************************************
355 * service_control_dispatcher
357 static DWORD WINAPI service_control_dispatcher(LPVOID arg)
359 SC_HANDLE manager;
360 HANDLE pipe;
362 if (!(manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
364 ERR("failed to open service manager error %u\n", GetLastError());
365 return 0;
368 pipe = service_open_pipe();
370 if (pipe==INVALID_HANDLE_VALUE)
372 WARN("failed to create control pipe error = %d\n", GetLastError());
373 return 0;
376 /* dispatcher loop */
377 while (1)
379 service_data *service;
380 service_start_info info;
381 WCHAR *data = NULL;
382 BOOL r;
383 DWORD data_size = 0, count, result;
385 r = ReadFile( pipe, &info, FIELD_OFFSET(service_start_info,data), &count, NULL );
386 if (!r)
388 if (GetLastError() != ERROR_BROKEN_PIPE)
389 ERR( "pipe read failed error %u\n", GetLastError() );
390 break;
392 if (count != FIELD_OFFSET(service_start_info,data))
394 ERR( "partial pipe read %u\n", count );
395 break;
397 if (count < info.total_size)
399 data_size = info.total_size - FIELD_OFFSET(service_start_info,data);
400 data = HeapAlloc( GetProcessHeap(), 0, data_size );
401 r = ReadFile( pipe, data, data_size, &count, NULL );
402 if (!r)
404 if (GetLastError() != ERROR_BROKEN_PIPE)
405 ERR( "pipe read failed error %u\n", GetLastError() );
406 HeapFree( GetProcessHeap(), 0, data );
407 break;
409 if (count != data_size)
411 ERR( "partial pipe read %u/%u\n", count, data_size );
412 HeapFree( GetProcessHeap(), 0, data );
413 break;
417 /* find the service */
419 if (!(service = find_service_by_name( data )))
421 FIXME( "got request %u for unknown service %s\n", info.cmd, debugstr_w(data));
422 result = ERROR_INVALID_PARAMETER;
423 goto done;
426 TRACE( "got request %u for service %s\n", info.cmd, debugstr_w(data) );
428 /* handle the request */
429 switch (info.cmd)
431 case WINESERV_STARTINFO:
432 if (!service->handle)
434 if (!(service->handle = OpenServiceW( manager, data, SERVICE_SET_STATUS )) ||
435 !(service->full_access_handle = OpenServiceW( manager, data, GENERIC_READ|GENERIC_WRITE )))
436 FIXME( "failed to open service %s\n", debugstr_w(data) );
438 result = service_handle_start(service, data, data_size / sizeof(WCHAR));
439 break;
440 case WINESERV_SENDCONTROL:
441 result = service_handle_control(service, info.control);
442 break;
443 default:
444 ERR("received invalid command %u\n", info.cmd);
445 result = ERROR_INVALID_PARAMETER;
446 break;
449 done:
450 WriteFile(pipe, &result, sizeof(result), &count, NULL);
451 HeapFree( GetProcessHeap(), 0, data );
454 CloseHandle(pipe);
455 CloseServiceHandle( manager );
456 return 1;
459 /******************************************************************************
460 * service_run_main_thread
462 static BOOL service_run_main_thread(void)
464 DWORD i, n, ret;
465 HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
466 UINT wait_services[MAXIMUM_WAIT_OBJECTS];
468 service_event = CreateEventW( NULL, FALSE, FALSE, NULL );
469 stop_event = CreateEventW( NULL, FALSE, FALSE, NULL );
471 /* FIXME: service_control_dispatcher should be merged into the main thread */
472 wait_handles[0] = __wine_make_process_system();
473 wait_handles[1] = CreateThread( NULL, 0, service_control_dispatcher, NULL, 0, NULL );
474 wait_handles[2] = service_event;
475 wait_handles[3] = stop_event;
477 TRACE("Starting %d services running as process %d\n",
478 nb_services, GetCurrentProcessId());
480 /* wait for all the threads to pack up and exit */
481 for (;;)
483 EnterCriticalSection( &service_cs );
484 for (i = 0, n = 4; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
486 if (!services[i]->thread) continue;
487 wait_services[n] = i;
488 wait_handles[n++] = services[i]->thread;
490 LeaveCriticalSection( &service_cs );
492 ret = WaitForMultipleObjects( n, wait_handles, FALSE, INFINITE );
493 if (!ret) /* system process event */
495 SERVICE_STATUS st;
496 SERVICE_PRESHUTDOWN_INFO spi;
497 DWORD timeout = 5000;
498 BOOL res;
500 EnterCriticalSection( &service_cs );
501 n = 0;
502 for (i = 0; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
504 if (!services[i]->thread) continue;
506 res = QueryServiceStatus(services[i]->full_access_handle, &st);
507 ret = ERROR_SUCCESS;
508 if (res && (st.dwControlsAccepted & SERVICE_ACCEPT_PRESHUTDOWN))
510 res = QueryServiceConfig2W( services[i]->full_access_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
511 (LPBYTE)&spi, sizeof(spi), &i );
512 if (res)
514 FIXME("service should be able to delay shutdown\n");
515 timeout += spi.dwPreshutdownTimeout;
516 ret = service_handle_control( services[i], SERVICE_CONTROL_PRESHUTDOWN );
517 wait_handles[n++] = services[i]->thread;
520 else if (res && (st.dwControlsAccepted & SERVICE_ACCEPT_SHUTDOWN))
522 ret = service_handle_control( services[i], SERVICE_CONTROL_SHUTDOWN );
523 wait_handles[n++] = services[i]->thread;
526 LeaveCriticalSection( &service_cs );
528 TRACE("last user process exited, shutting down (timeout: %d)\n", timeout);
529 WaitForMultipleObjects( n, wait_handles, TRUE, timeout );
530 ExitProcess(0);
532 else if (ret == 1)
534 TRACE( "control dispatcher exited, shutting down\n" );
535 /* FIXME: we should maybe send a shutdown control to running services */
536 ExitProcess(0);
538 else if (ret == 2)
540 continue; /* rebuild the list */
542 else if (ret == 3)
544 return TRUE;
546 else if (ret < n)
548 services[wait_services[ret]]->thread = 0;
549 CloseHandle( wait_handles[ret] );
550 if (n == 5) return TRUE; /* it was the last running thread */
552 else return FALSE;
556 /******************************************************************************
557 * StartServiceCtrlDispatcherA [ADVAPI32.@]
559 * See StartServiceCtrlDispatcherW.
561 BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
563 service_data *info;
564 unsigned int i;
565 BOOL ret = TRUE;
567 TRACE("%p\n", servent);
569 if (nb_services)
571 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
572 return FALSE;
574 while (servent[nb_services].lpServiceName) nb_services++;
575 if (!nb_services)
577 SetLastError( ERROR_INVALID_PARAMETER );
578 return FALSE;
581 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
583 for (i = 0; i < nb_services; i++)
585 DWORD len = MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, NULL, 0);
586 DWORD sz = FIELD_OFFSET( service_data, name[len] );
587 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
588 MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, info->name, len);
589 info->proc.a = servent[i].lpServiceProc;
590 info->unicode = FALSE;
591 services[i] = info;
594 service_run_main_thread();
596 return ret;
599 /******************************************************************************
600 * StartServiceCtrlDispatcherW [ADVAPI32.@]
602 * Connects a process containing one or more services to the service control
603 * manager.
605 * PARAMS
606 * servent [I] A list of the service names and service procedures
608 * RETURNS
609 * Success: TRUE.
610 * Failure: FALSE.
612 BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
614 service_data *info;
615 unsigned int i;
616 BOOL ret = TRUE;
618 TRACE("%p\n", servent);
620 if (nb_services)
622 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
623 return FALSE;
625 while (servent[nb_services].lpServiceName) nb_services++;
626 if (!nb_services)
628 SetLastError( ERROR_INVALID_PARAMETER );
629 return FALSE;
632 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
634 for (i = 0; i < nb_services; i++)
636 DWORD len = strlenW(servent[i].lpServiceName) + 1;
637 DWORD sz = FIELD_OFFSET( service_data, name[len] );
638 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
639 strcpyW(info->name, servent[i].lpServiceName);
640 info->proc.w = servent[i].lpServiceProc;
641 info->unicode = TRUE;
642 services[i] = info;
645 service_run_main_thread();
647 return ret;
650 /******************************************************************************
651 * LockServiceDatabase [ADVAPI32.@]
653 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
655 SC_RPC_LOCK hLock = NULL;
656 DWORD err;
658 TRACE("%p\n",hSCManager);
660 __TRY
662 err = svcctl_LockServiceDatabase(hSCManager, &hLock);
664 __EXCEPT(rpc_filter)
666 err = map_exception_code(GetExceptionCode());
668 __ENDTRY
669 if (err != ERROR_SUCCESS)
671 SetLastError(err);
672 return NULL;
674 return hLock;
677 /******************************************************************************
678 * UnlockServiceDatabase [ADVAPI32.@]
680 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
682 DWORD err;
683 SC_RPC_LOCK hRpcLock = ScLock;
685 TRACE("%p\n",ScLock);
687 __TRY
689 err = svcctl_UnlockServiceDatabase(&hRpcLock);
691 __EXCEPT(rpc_filter)
693 err = map_exception_code(GetExceptionCode());
695 __ENDTRY
696 if (err != ERROR_SUCCESS)
698 SetLastError(err);
699 return FALSE;
701 return TRUE;
704 /******************************************************************************
705 * SetServiceStatus [ADVAPI32.@]
707 * PARAMS
708 * hService []
709 * lpStatus []
711 BOOL WINAPI
712 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
714 DWORD err;
716 TRACE("%p %x %x %x %x %x %x %x\n", hService,
717 lpStatus->dwServiceType, lpStatus->dwCurrentState,
718 lpStatus->dwControlsAccepted, lpStatus->dwWin32ExitCode,
719 lpStatus->dwServiceSpecificExitCode, lpStatus->dwCheckPoint,
720 lpStatus->dwWaitHint);
722 __TRY
724 err = svcctl_SetServiceStatus( hService, lpStatus );
726 __EXCEPT(rpc_filter)
728 err = map_exception_code(GetExceptionCode());
730 __ENDTRY
731 if (err != ERROR_SUCCESS)
733 SetLastError(err);
734 return FALSE;
737 if (lpStatus->dwCurrentState == SERVICE_STOPPED) {
738 SetEvent(stop_event);
739 CloseServiceHandle((SC_HANDLE)hService);
742 return TRUE;
746 /******************************************************************************
747 * OpenSCManagerA [ADVAPI32.@]
749 * Establish a connection to the service control manager and open its database.
751 * PARAMS
752 * lpMachineName [I] Pointer to machine name string
753 * lpDatabaseName [I] Pointer to database name string
754 * dwDesiredAccess [I] Type of access
756 * RETURNS
757 * Success: A Handle to the service control manager database
758 * Failure: NULL
760 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
761 DWORD dwDesiredAccess )
763 LPWSTR lpMachineNameW, lpDatabaseNameW;
764 SC_HANDLE ret;
766 lpMachineNameW = SERV_dup(lpMachineName);
767 lpDatabaseNameW = SERV_dup(lpDatabaseName);
768 ret = OpenSCManagerW(lpMachineNameW, lpDatabaseNameW, dwDesiredAccess);
769 HeapFree(GetProcessHeap(), 0, lpDatabaseNameW);
770 HeapFree(GetProcessHeap(), 0, lpMachineNameW);
771 return ret;
774 /******************************************************************************
775 * OpenSCManagerW [ADVAPI32.@]
777 * See OpenSCManagerA.
779 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
780 DWORD dwDesiredAccess )
782 SC_HANDLE handle = 0;
783 LONG r;
785 TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
786 debugstr_w(lpDatabaseName), dwDesiredAccess);
788 __TRY
790 r = svcctl_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, (SC_RPC_HANDLE *)&handle);
792 __EXCEPT(rpc_filter)
794 r = map_exception_code(GetExceptionCode());
796 __ENDTRY
798 if (r!=ERROR_SUCCESS)
800 SetLastError( r );
801 handle = 0;
804 TRACE("returning %p\n", handle);
805 return handle;
808 /******************************************************************************
809 * ControlService [ADVAPI32.@]
811 * Send a control code to a service.
813 * PARAMS
814 * hService [I] Handle of the service control manager database
815 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
816 * lpServiceStatus [O] Destination for the status of the service, if available
818 * RETURNS
819 * Success: TRUE.
820 * Failure: FALSE.
822 * BUGS
823 * Unlike M$' implementation, control requests are not serialized and may be
824 * processed asynchronously.
826 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
827 LPSERVICE_STATUS lpServiceStatus )
829 DWORD err;
831 TRACE("%p %d %p\n", hService, dwControl, lpServiceStatus);
833 __TRY
835 err = svcctl_ControlService(hService, dwControl, lpServiceStatus);
837 __EXCEPT(rpc_filter)
839 err = map_exception_code(GetExceptionCode());
841 __ENDTRY
842 if (err != ERROR_SUCCESS)
844 SetLastError(err);
845 return FALSE;
848 return TRUE;
851 /******************************************************************************
852 * CloseServiceHandle [ADVAPI32.@]
854 * Close a handle to a service or the service control manager database.
856 * PARAMS
857 * hSCObject [I] Handle to service or service control manager database
859 * RETURNS
860 * Success: TRUE
861 * Failure: FALSE
863 BOOL WINAPI
864 CloseServiceHandle( SC_HANDLE hSCObject )
866 DWORD err;
868 TRACE("%p\n", hSCObject);
870 __TRY
872 err = svcctl_CloseServiceHandle((SC_RPC_HANDLE *)&hSCObject);
874 __EXCEPT(rpc_filter)
876 err = map_exception_code(GetExceptionCode());
878 __ENDTRY
880 if (err != ERROR_SUCCESS)
882 SetLastError(err);
883 return FALSE;
885 return TRUE;
889 /******************************************************************************
890 * OpenServiceA [ADVAPI32.@]
892 * Open a handle to a service.
894 * PARAMS
895 * hSCManager [I] Handle of the service control manager database
896 * lpServiceName [I] Name of the service to open
897 * dwDesiredAccess [I] Access required to the service
899 * RETURNS
900 * Success: Handle to the service
901 * Failure: NULL
903 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
904 DWORD dwDesiredAccess )
906 LPWSTR lpServiceNameW;
907 SC_HANDLE ret;
909 TRACE("%p %s %d\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
911 lpServiceNameW = SERV_dup(lpServiceName);
912 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
913 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
914 return ret;
918 /******************************************************************************
919 * OpenServiceW [ADVAPI32.@]
921 * See OpenServiceA.
923 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
924 DWORD dwDesiredAccess)
926 SC_HANDLE handle = 0;
927 DWORD err;
929 TRACE("%p %s %d\n", hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
931 if (!hSCManager)
933 SetLastError( ERROR_INVALID_HANDLE );
934 return 0;
937 __TRY
939 err = svcctl_OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess, (SC_RPC_HANDLE *)&handle);
941 __EXCEPT(rpc_filter)
943 err = map_exception_code(GetExceptionCode());
945 __ENDTRY
947 if (err != ERROR_SUCCESS)
949 SetLastError(err);
950 handle = 0;
953 TRACE("returning %p\n",handle);
954 return handle;
957 /******************************************************************************
958 * CreateServiceW [ADVAPI32.@]
960 SC_HANDLE WINAPI
961 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
962 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
963 DWORD dwServiceType, DWORD dwStartType,
964 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
965 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
966 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
967 LPCWSTR lpPassword )
969 SC_HANDLE handle = 0;
970 DWORD err;
971 SIZE_T passwdlen;
973 TRACE("%p %s %s\n", hSCManager,
974 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
976 if (!hSCManager)
978 SetLastError( ERROR_INVALID_HANDLE );
979 return 0;
982 if (lpPassword)
983 passwdlen = (strlenW(lpPassword) + 1) * sizeof(WCHAR);
984 else
985 passwdlen = 0;
987 __TRY
989 err = svcctl_CreateServiceW(hSCManager, lpServiceName,
990 lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
991 lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, (const BYTE*)lpDependencies,
992 multisz_cb(lpDependencies), lpServiceStartName, (const BYTE*)lpPassword, passwdlen,
993 (SC_RPC_HANDLE *)&handle);
995 __EXCEPT(rpc_filter)
997 err = map_exception_code(GetExceptionCode());
999 __ENDTRY
1001 if (err != ERROR_SUCCESS)
1003 SetLastError(err);
1004 handle = 0;
1006 return handle;
1010 /******************************************************************************
1011 * CreateServiceA [ADVAPI32.@]
1013 SC_HANDLE WINAPI
1014 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1015 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
1016 DWORD dwServiceType, DWORD dwStartType,
1017 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1018 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1019 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
1020 LPCSTR lpPassword )
1022 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
1023 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
1024 SC_HANDLE r;
1026 TRACE("%p %s %s\n", hSCManager,
1027 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
1029 lpServiceNameW = SERV_dup( lpServiceName );
1030 lpDisplayNameW = SERV_dup( lpDisplayName );
1031 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
1032 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
1033 lpDependenciesW = SERV_dupmulti( lpDependencies );
1034 lpServiceStartNameW = SERV_dup( lpServiceStartName );
1035 lpPasswordW = SERV_dup( lpPassword );
1037 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
1038 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1039 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
1040 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
1042 HeapFree( GetProcessHeap(), 0, lpServiceNameW );
1043 HeapFree( GetProcessHeap(), 0, lpDisplayNameW );
1044 HeapFree( GetProcessHeap(), 0, lpBinaryPathNameW );
1045 HeapFree( GetProcessHeap(), 0, lpLoadOrderGroupW );
1046 HeapFree( GetProcessHeap(), 0, lpDependenciesW );
1047 HeapFree( GetProcessHeap(), 0, lpServiceStartNameW );
1048 HeapFree( GetProcessHeap(), 0, lpPasswordW );
1050 return r;
1054 /******************************************************************************
1055 * DeleteService [ADVAPI32.@]
1057 * Delete a service from the service control manager database.
1059 * PARAMS
1060 * hService [I] Handle of the service to delete
1062 * RETURNS
1063 * Success: TRUE
1064 * Failure: FALSE
1066 BOOL WINAPI DeleteService( SC_HANDLE hService )
1068 DWORD err;
1070 __TRY
1072 err = svcctl_DeleteService(hService);
1074 __EXCEPT(rpc_filter)
1076 err = map_exception_code(GetExceptionCode());
1078 __ENDTRY
1079 if (err != 0)
1081 SetLastError(err);
1082 return FALSE;
1085 return TRUE;
1089 /******************************************************************************
1090 * StartServiceA [ADVAPI32.@]
1092 * Start a service
1094 * PARAMS
1095 * hService [I] Handle of service
1096 * dwNumServiceArgs [I] Number of arguments
1097 * lpServiceArgVectors [I] Address of array of argument strings
1099 * NOTES
1100 * - NT implements this function using an obscure RPC call.
1101 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1102 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
1103 * - This will only work for shared address space. How should the service
1104 * args be transferred when address spaces are separated?
1105 * - Can only start one service at a time.
1106 * - Has no concept of privilege.
1108 * RETURNS
1109 * Success: TRUE.
1110 * Failure: FALSE
1112 BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
1113 LPCSTR *lpServiceArgVectors )
1115 LPWSTR *lpwstr=NULL;
1116 unsigned int i;
1117 BOOL r;
1119 TRACE("(%p,%d,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
1121 if (dwNumServiceArgs)
1122 lpwstr = HeapAlloc( GetProcessHeap(), 0,
1123 dwNumServiceArgs*sizeof(LPWSTR) );
1125 for(i=0; i<dwNumServiceArgs; i++)
1126 lpwstr[i]=SERV_dup(lpServiceArgVectors[i]);
1128 r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
1130 if (dwNumServiceArgs)
1132 for(i=0; i<dwNumServiceArgs; i++)
1133 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
1134 HeapFree(GetProcessHeap(), 0, lpwstr);
1137 return r;
1141 /******************************************************************************
1142 * StartServiceW [ADVAPI32.@]
1144 * See StartServiceA.
1146 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1147 LPCWSTR *lpServiceArgVectors)
1149 DWORD err;
1151 TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1153 __TRY
1155 err = svcctl_StartServiceW(hService, dwNumServiceArgs, lpServiceArgVectors);
1157 __EXCEPT(rpc_filter)
1159 err = map_exception_code(GetExceptionCode());
1161 __ENDTRY
1162 if (err != ERROR_SUCCESS)
1164 SetLastError(err);
1165 return FALSE;
1168 return TRUE;
1171 /******************************************************************************
1172 * QueryServiceStatus [ADVAPI32.@]
1174 * PARAMS
1175 * hService [I] Handle to service to get information about
1176 * lpservicestatus [O] buffer to receive the status information for the service
1179 BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
1180 LPSERVICE_STATUS lpservicestatus)
1182 SERVICE_STATUS_PROCESS SvcStatusData;
1183 BOOL ret;
1184 DWORD dummy;
1186 TRACE("%p %p\n", hService, lpservicestatus);
1188 if (!hService)
1190 SetLastError(ERROR_INVALID_HANDLE);
1191 return FALSE;
1193 if (!lpservicestatus)
1195 SetLastError(ERROR_INVALID_ADDRESS);
1196 return FALSE;
1199 ret = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&SvcStatusData,
1200 sizeof(SERVICE_STATUS_PROCESS), &dummy);
1201 if (ret) memcpy(lpservicestatus, &SvcStatusData, sizeof(SERVICE_STATUS)) ;
1202 return ret;
1206 /******************************************************************************
1207 * QueryServiceStatusEx [ADVAPI32.@]
1209 * Get information about a service.
1211 * PARAMS
1212 * hService [I] Handle to service to get information about
1213 * InfoLevel [I] Level of information to get
1214 * lpBuffer [O] Destination for requested information
1215 * cbBufSize [I] Size of lpBuffer in bytes
1216 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1218 * RETURNS
1219 * Success: TRUE
1220 * FAILURE: FALSE
1222 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1223 LPBYTE lpBuffer, DWORD cbBufSize,
1224 LPDWORD pcbBytesNeeded)
1226 DWORD err;
1228 TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1230 if (InfoLevel != SC_STATUS_PROCESS_INFO)
1232 err = ERROR_INVALID_LEVEL;
1234 else if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
1236 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
1237 err = ERROR_INSUFFICIENT_BUFFER;
1239 else
1241 __TRY
1243 err = svcctl_QueryServiceStatusEx(hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1245 __EXCEPT(rpc_filter)
1247 err = map_exception_code(GetExceptionCode());
1249 __ENDTRY
1251 if (err != ERROR_SUCCESS)
1253 SetLastError(err);
1254 return FALSE;
1256 return TRUE;
1259 /******************************************************************************
1260 * QueryServiceConfigA [ADVAPI32.@]
1262 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1263 DWORD size, LPDWORD needed )
1265 DWORD n;
1266 LPSTR p, buffer;
1267 BOOL ret;
1268 QUERY_SERVICE_CONFIGW *configW;
1270 TRACE("%p %p %d %p\n", hService, config, size, needed);
1272 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, 2 * size )))
1274 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1275 return FALSE;
1277 configW = (QUERY_SERVICE_CONFIGW *)buffer;
1278 ret = QueryServiceConfigW( hService, configW, 2 * size, needed );
1279 if (!ret) goto done;
1281 config->dwServiceType = configW->dwServiceType;
1282 config->dwStartType = configW->dwStartType;
1283 config->dwErrorControl = configW->dwErrorControl;
1284 config->lpBinaryPathName = NULL;
1285 config->lpLoadOrderGroup = NULL;
1286 config->dwTagId = configW->dwTagId;
1287 config->lpDependencies = NULL;
1288 config->lpServiceStartName = NULL;
1289 config->lpDisplayName = NULL;
1291 p = (LPSTR)(config + 1);
1292 n = size - sizeof(*config);
1293 ret = FALSE;
1295 #define MAP_STR(str) \
1296 do { \
1297 if (configW->str) \
1299 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1300 if (!sz) goto done; \
1301 config->str = p; \
1302 p += sz; \
1303 n -= sz; \
1305 } while (0)
1307 MAP_STR( lpBinaryPathName );
1308 MAP_STR( lpLoadOrderGroup );
1309 MAP_STR( lpDependencies );
1310 MAP_STR( lpServiceStartName );
1311 MAP_STR( lpDisplayName );
1312 #undef MAP_STR
1314 *needed = p - (LPSTR)config;
1315 ret = TRUE;
1317 done:
1318 HeapFree( GetProcessHeap(), 0, buffer );
1319 return ret;
1322 static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
1324 DWORD cb;
1326 if (!*string_ptr)
1328 cb = sizeof(WCHAR);
1329 memset(*buf, 0, cb);
1331 else
1333 cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
1334 memcpy(*buf, *string_ptr, cb);
1335 MIDL_user_free(*string_ptr);
1338 *string_ptr = (LPWSTR)*buf;
1339 *buf += cb;
1341 return cb;
1344 static DWORD size_string(LPCWSTR string)
1346 return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
1349 /******************************************************************************
1350 * QueryServiceConfigW [ADVAPI32.@]
1352 BOOL WINAPI
1353 QueryServiceConfigW( SC_HANDLE hService,
1354 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1355 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1357 QUERY_SERVICE_CONFIGW config;
1358 DWORD total;
1359 DWORD err;
1360 BYTE *bufpos;
1362 TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1363 cbBufSize, pcbBytesNeeded);
1365 memset(&config, 0, sizeof(config));
1367 __TRY
1369 err = svcctl_QueryServiceConfigW(hService, &config);
1371 __EXCEPT(rpc_filter)
1373 err = map_exception_code(GetExceptionCode());
1375 __ENDTRY
1377 if (err != ERROR_SUCCESS)
1379 TRACE("services.exe: error %u\n", err);
1380 SetLastError(err);
1381 return FALSE;
1384 /* calculate the size required first */
1385 total = sizeof (QUERY_SERVICE_CONFIGW);
1386 total += size_string(config.lpBinaryPathName);
1387 total += size_string(config.lpLoadOrderGroup);
1388 total += size_string(config.lpDependencies);
1389 total += size_string(config.lpServiceStartName);
1390 total += size_string(config.lpDisplayName);
1392 *pcbBytesNeeded = total;
1394 /* if there's not enough memory, return an error */
1395 if( total > cbBufSize )
1397 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1398 MIDL_user_free(config.lpBinaryPathName);
1399 MIDL_user_free(config.lpLoadOrderGroup);
1400 MIDL_user_free(config.lpDependencies);
1401 MIDL_user_free(config.lpServiceStartName);
1402 MIDL_user_free(config.lpDisplayName);
1403 return FALSE;
1406 *lpServiceConfig = config;
1407 bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
1408 move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
1409 move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
1410 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
1411 move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
1412 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
1414 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1415 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1416 TRACE("Dependencies = %s\n", debugstr_w(lpServiceConfig->lpDependencies) );
1417 TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig->lpServiceStartName) );
1418 TRACE("Display name = %s\n", debugstr_w(lpServiceConfig->lpDisplayName) );
1420 return TRUE;
1423 /******************************************************************************
1424 * QueryServiceConfig2A [ADVAPI32.@]
1426 * Note
1427 * observed under win2k:
1428 * The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
1429 * required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
1431 BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1432 DWORD size, LPDWORD needed)
1434 BOOL ret;
1435 LPBYTE bufferW = NULL;
1437 if(buffer && size)
1438 bufferW = HeapAlloc( GetProcessHeap(), 0, size);
1440 ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
1441 if(!ret) goto cleanup;
1443 switch(dwLevel) {
1444 case SERVICE_CONFIG_DESCRIPTION:
1445 if (buffer && bufferW) {
1446 LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
1447 LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
1448 if (configW->lpDescription && (size > sizeof(SERVICE_DESCRIPTIONA))) {
1449 DWORD sz;
1450 configA->lpDescription = (LPSTR)(configA + 1);
1451 sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
1452 configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
1453 if (!sz) {
1454 FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1455 ret = FALSE;
1456 configA->lpDescription = NULL;
1459 else configA->lpDescription = NULL;
1461 break;
1462 case SERVICE_CONFIG_PRESHUTDOWN_INFO:
1463 if (buffer && bufferW && *needed<=size)
1464 memcpy(buffer, bufferW, *needed);
1465 break;
1466 default:
1467 FIXME("conversation W->A not implemented for level %d\n", dwLevel);
1468 ret = FALSE;
1469 break;
1472 cleanup:
1473 HeapFree( GetProcessHeap(), 0, bufferW);
1474 return ret;
1477 /******************************************************************************
1478 * QueryServiceConfig2W [ADVAPI32.@]
1480 * See QueryServiceConfig2A.
1482 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1483 DWORD size, LPDWORD needed)
1485 DWORD err;
1487 if(dwLevel!=SERVICE_CONFIG_DESCRIPTION && dwLevel!=SERVICE_CONFIG_PRESHUTDOWN_INFO) {
1488 FIXME("Level %d not implemented\n", dwLevel);
1489 SetLastError(ERROR_INVALID_LEVEL);
1490 return FALSE;
1493 if(!buffer && size) {
1494 SetLastError(ERROR_INVALID_ADDRESS);
1495 return FALSE;
1498 TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
1500 __TRY
1502 err = svcctl_QueryServiceConfig2W(hService, dwLevel, buffer, size, needed);
1504 __EXCEPT(rpc_filter)
1506 err = map_exception_code(GetExceptionCode());
1508 __ENDTRY
1510 if (err != ERROR_SUCCESS)
1512 SetLastError( err );
1513 return FALSE;
1516 switch (dwLevel)
1518 case SERVICE_CONFIG_DESCRIPTION:
1519 if (buffer)
1521 SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
1522 if (descr->lpDescription) /* make it an absolute pointer */
1523 descr->lpDescription = (WCHAR *)(buffer + (ULONG_PTR)descr->lpDescription);
1524 break;
1528 return TRUE;
1531 /******************************************************************************
1532 * EnumServicesStatusA [ADVAPI32.@]
1534 BOOL WINAPI
1535 EnumServicesStatusA( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSA
1536 services, DWORD size, LPDWORD needed, LPDWORD returned,
1537 LPDWORD resume_handle )
1539 BOOL ret;
1540 unsigned int i;
1541 ENUM_SERVICE_STATUSW *servicesW = NULL;
1542 DWORD sz, n;
1543 char *p;
1545 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
1546 returned, resume_handle);
1548 sz = max( 2 * size, sizeof(*servicesW) );
1549 if (!(servicesW = HeapAlloc( GetProcessHeap(), 0, sz )))
1551 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1552 return FALSE;
1555 ret = EnumServicesStatusW( hmngr, type, state, servicesW, sz, needed, returned, resume_handle );
1556 if (!ret) goto done;
1558 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUSA);
1559 n = size - (p - (char *)services);
1560 ret = FALSE;
1561 for (i = 0; i < *returned; i++)
1563 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
1564 if (!sz) goto done;
1565 services[i].lpServiceName = p;
1566 p += sz;
1567 n -= sz;
1568 if (servicesW[i].lpDisplayName)
1570 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
1571 if (!sz) goto done;
1572 services[i].lpDisplayName = p;
1573 p += sz;
1574 n -= sz;
1576 else services[i].lpDisplayName = NULL;
1577 services[i].ServiceStatus = servicesW[i].ServiceStatus;
1580 ret = TRUE;
1582 done:
1583 HeapFree( GetProcessHeap(), 0, servicesW );
1584 return ret;
1587 /******************************************************************************
1588 * EnumServicesStatusW [ADVAPI32.@]
1590 BOOL WINAPI
1591 EnumServicesStatusW( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSW
1592 services, DWORD size, LPDWORD needed, LPDWORD returned,
1593 LPDWORD resume_handle )
1595 DWORD err, i;
1596 ENUM_SERVICE_STATUSW dummy_status;
1598 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
1599 returned, resume_handle);
1601 if (resume_handle)
1602 FIXME("resume handle not supported\n");
1604 if (!hmngr)
1606 SetLastError( ERROR_INVALID_HANDLE );
1607 return FALSE;
1610 /* make sure we pass a valid pointer */
1611 if (!services || size < sizeof(*services))
1613 services = &dummy_status;
1614 size = sizeof(dummy_status);
1617 __TRY
1619 err = svcctl_EnumServicesStatusW( hmngr, type, state, (BYTE *)services, size, needed, returned );
1621 __EXCEPT(rpc_filter)
1623 err = map_exception_code( GetExceptionCode() );
1625 __ENDTRY
1627 if (err != ERROR_SUCCESS)
1629 SetLastError( err );
1630 return FALSE;
1633 for (i = 0; i < *returned; i++)
1635 /* convert buffer offsets into pointers */
1636 services[i].lpServiceName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpServiceName);
1637 if (services[i].lpDisplayName)
1638 services[i].lpDisplayName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpDisplayName);
1641 return TRUE;
1644 /******************************************************************************
1645 * EnumServicesStatusExA [ADVAPI32.@]
1647 BOOL WINAPI
1648 EnumServicesStatusExA( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state,
1649 LPBYTE buffer, DWORD size, LPDWORD needed, LPDWORD returned,
1650 LPDWORD resume_handle, LPCSTR group )
1652 BOOL ret;
1653 unsigned int i;
1654 ENUM_SERVICE_STATUS_PROCESSA *services = (ENUM_SERVICE_STATUS_PROCESSA *)buffer;
1655 ENUM_SERVICE_STATUS_PROCESSW *servicesW = NULL;
1656 WCHAR *groupW = NULL;
1657 DWORD sz, n;
1658 char *p;
1660 TRACE("%p %u 0x%x 0x%x %p %u %p %p %p %s\n", hmngr, level, type, state, buffer,
1661 size, needed, returned, resume_handle, debugstr_a(group));
1663 sz = max( 2 * size, sizeof(*servicesW) );
1664 if (!(servicesW = HeapAlloc( GetProcessHeap(), 0, sz )))
1666 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1667 return FALSE;
1669 if (group)
1671 int len = MultiByteToWideChar( CP_ACP, 0, group, -1, NULL, 0 );
1672 if (!(groupW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1674 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1675 HeapFree( GetProcessHeap(), 0, servicesW );
1676 return FALSE;
1678 MultiByteToWideChar( CP_ACP, 0, group, -1, groupW, len * sizeof(WCHAR) );
1681 ret = EnumServicesStatusExW( hmngr, level, type, state, (BYTE *)servicesW, sz,
1682 needed, returned, resume_handle, groupW );
1683 if (!ret) goto done;
1685 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUS_PROCESSA);
1686 n = size - (p - (char *)services);
1687 ret = FALSE;
1688 for (i = 0; i < *returned; i++)
1690 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
1691 if (!sz) goto done;
1692 services[i].lpServiceName = p;
1693 p += sz;
1694 n -= sz;
1695 if (servicesW[i].lpDisplayName)
1697 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
1698 if (!sz) goto done;
1699 services[i].lpDisplayName = p;
1700 p += sz;
1701 n -= sz;
1703 else services[i].lpDisplayName = NULL;
1704 services[i].ServiceStatusProcess = servicesW[i].ServiceStatusProcess;
1707 ret = TRUE;
1709 done:
1710 HeapFree( GetProcessHeap(), 0, servicesW );
1711 HeapFree( GetProcessHeap(), 0, groupW );
1712 return ret;
1715 /******************************************************************************
1716 * EnumServicesStatusExW [ADVAPI32.@]
1718 BOOL WINAPI
1719 EnumServicesStatusExW( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state,
1720 LPBYTE buffer, DWORD size, LPDWORD needed, LPDWORD returned,
1721 LPDWORD resume_handle, LPCWSTR group )
1723 DWORD err, i;
1724 ENUM_SERVICE_STATUS_PROCESSW dummy_status;
1725 ENUM_SERVICE_STATUS_PROCESSW *services = (ENUM_SERVICE_STATUS_PROCESSW *)buffer;
1727 TRACE("%p %u 0x%x 0x%x %p %u %p %p %p %s\n", hmngr, level, type, state, buffer,
1728 size, needed, returned, resume_handle, debugstr_w(group));
1730 if (resume_handle)
1731 FIXME("resume handle not supported\n");
1733 if (level != SC_ENUM_PROCESS_INFO)
1735 SetLastError( ERROR_INVALID_LEVEL );
1736 return FALSE;
1738 if (!hmngr)
1740 SetLastError( ERROR_INVALID_HANDLE );
1741 return FALSE;
1744 /* make sure we pass a valid buffer pointer */
1745 if (!services || size < sizeof(*services))
1747 buffer = (BYTE *)&dummy_status;
1748 size = sizeof(dummy_status);
1751 __TRY
1753 err = svcctl_EnumServicesStatusExW( hmngr, type, state, buffer, size, needed,
1754 returned, group );
1756 __EXCEPT(rpc_filter)
1758 err = map_exception_code( GetExceptionCode() );
1760 __ENDTRY
1762 if (err != ERROR_SUCCESS)
1764 SetLastError( err );
1765 return FALSE;
1768 for (i = 0; i < *returned; i++)
1770 /* convert buffer offsets into pointers */
1771 services[i].lpServiceName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpServiceName);
1772 if (services[i].lpDisplayName)
1773 services[i].lpDisplayName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpDisplayName);
1776 return TRUE;
1779 /******************************************************************************
1780 * GetServiceKeyNameA [ADVAPI32.@]
1782 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1783 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1785 LPWSTR lpDisplayNameW, lpServiceNameW;
1786 DWORD sizeW;
1787 BOOL ret = FALSE;
1789 TRACE("%p %s %p %p\n", hSCManager,
1790 debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1792 lpDisplayNameW = SERV_dup(lpDisplayName);
1793 if (lpServiceName)
1794 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1795 else
1796 lpServiceNameW = NULL;
1798 sizeW = *lpcchBuffer;
1799 if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
1801 if (lpServiceName && *lpcchBuffer)
1802 lpServiceName[0] = 0;
1803 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1804 goto cleanup;
1807 if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
1808 *lpcchBuffer, NULL, NULL ))
1810 if (*lpcchBuffer && lpServiceName)
1811 lpServiceName[0] = 0;
1812 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
1813 goto cleanup;
1816 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1817 ret = TRUE;
1819 cleanup:
1820 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1821 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1822 return ret;
1825 /******************************************************************************
1826 * GetServiceKeyNameW [ADVAPI32.@]
1828 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1829 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1831 DWORD err;
1832 WCHAR buffer[2];
1833 DWORD size;
1835 TRACE("%p %s %p %p\n", hSCManager,
1836 debugstr_w(lpDisplayName), lpServiceName, lpcchBuffer);
1838 if (!hSCManager)
1840 SetLastError( ERROR_INVALID_HANDLE );
1841 return 0;
1844 /* provide a buffer if the caller didn't */
1845 if (!lpServiceName || *lpcchBuffer < 2)
1847 lpServiceName = buffer;
1848 /* A size of 1 would be enough, but tests show that Windows returns 2,
1849 * probably because of a WCHAR/bytes mismatch in their code.
1851 *lpcchBuffer = 2;
1854 /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
1855 * includes the nul-terminator on input. */
1856 size = *lpcchBuffer - 1;
1858 __TRY
1860 err = svcctl_GetServiceKeyNameW(hSCManager, lpDisplayName, lpServiceName,
1861 &size);
1863 __EXCEPT(rpc_filter)
1865 err = map_exception_code(GetExceptionCode());
1867 __ENDTRY
1869 /* The value of *lpcchBuffer excludes nul-terminator on output. */
1870 if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
1871 *lpcchBuffer = size;
1873 if (err)
1874 SetLastError(err);
1875 return err == ERROR_SUCCESS;
1878 /******************************************************************************
1879 * QueryServiceLockStatusA [ADVAPI32.@]
1881 BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
1882 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1883 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1885 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1887 return FALSE;
1890 /******************************************************************************
1891 * QueryServiceLockStatusW [ADVAPI32.@]
1893 BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
1894 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1895 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1897 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1899 return FALSE;
1902 /******************************************************************************
1903 * GetServiceDisplayNameA [ADVAPI32.@]
1905 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1906 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1908 LPWSTR lpServiceNameW, lpDisplayNameW;
1909 DWORD sizeW;
1910 BOOL ret = FALSE;
1912 TRACE("%p %s %p %p\n", hSCManager,
1913 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1915 lpServiceNameW = SERV_dup(lpServiceName);
1916 if (lpDisplayName)
1917 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1918 else
1919 lpDisplayNameW = NULL;
1921 sizeW = *lpcchBuffer;
1922 if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
1924 if (lpDisplayName && *lpcchBuffer)
1925 lpDisplayName[0] = 0;
1926 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1927 goto cleanup;
1930 if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
1931 *lpcchBuffer, NULL, NULL ))
1933 if (*lpcchBuffer && lpDisplayName)
1934 lpDisplayName[0] = 0;
1935 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
1936 goto cleanup;
1939 /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
1940 * (but if the function succeeded it means that is a good upper estimation of the size) */
1941 ret = TRUE;
1943 cleanup:
1944 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1945 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1946 return ret;
1949 /******************************************************************************
1950 * GetServiceDisplayNameW [ADVAPI32.@]
1952 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1953 LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1955 DWORD err;
1956 DWORD size;
1957 WCHAR buffer[2];
1959 TRACE("%p %s %p %p\n", hSCManager,
1960 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1962 if (!hSCManager)
1964 SetLastError( ERROR_INVALID_HANDLE );
1965 return 0;
1968 /* provide a buffer if the caller didn't */
1969 if (!lpDisplayName || *lpcchBuffer < 2)
1971 lpDisplayName = buffer;
1972 /* A size of 1 would be enough, but tests show that Windows returns 2,
1973 * probably because of a WCHAR/bytes mismatch in their code.
1975 *lpcchBuffer = 2;
1978 /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
1979 * includes the nul-terminator on input. */
1980 size = *lpcchBuffer - 1;
1982 __TRY
1984 err = svcctl_GetServiceDisplayNameW(hSCManager, lpServiceName, lpDisplayName,
1985 &size);
1987 __EXCEPT(rpc_filter)
1989 err = map_exception_code(GetExceptionCode());
1991 __ENDTRY
1993 /* The value of *lpcchBuffer excludes nul-terminator on output. */
1994 if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
1995 *lpcchBuffer = size;
1997 if (err)
1998 SetLastError(err);
1999 return err == ERROR_SUCCESS;
2002 /******************************************************************************
2003 * ChangeServiceConfigW [ADVAPI32.@]
2005 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
2006 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
2007 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
2008 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
2010 DWORD cb_pwd;
2011 DWORD err;
2013 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2014 hService, dwServiceType, dwStartType, dwErrorControl,
2015 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
2016 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
2017 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
2019 cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
2021 __TRY
2023 err = svcctl_ChangeServiceConfigW(hService, dwServiceType,
2024 dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId,
2025 (const BYTE *)lpDependencies, multisz_cb(lpDependencies), lpServiceStartName,
2026 (const BYTE *)lpPassword, cb_pwd, lpDisplayName);
2028 __EXCEPT(rpc_filter)
2030 err = map_exception_code(GetExceptionCode());
2032 __ENDTRY
2034 if (err != ERROR_SUCCESS)
2035 SetLastError(err);
2037 return err == ERROR_SUCCESS;
2040 /******************************************************************************
2041 * ChangeServiceConfigA [ADVAPI32.@]
2043 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
2044 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
2045 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
2046 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
2048 LPWSTR wBinaryPathName, wLoadOrderGroup, wDependencies;
2049 LPWSTR wServiceStartName, wPassword, wDisplayName;
2050 BOOL r;
2052 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2053 hService, dwServiceType, dwStartType, dwErrorControl,
2054 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
2055 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
2056 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
2058 wBinaryPathName = SERV_dup( lpBinaryPathName );
2059 wLoadOrderGroup = SERV_dup( lpLoadOrderGroup );
2060 wDependencies = SERV_dupmulti( lpDependencies );
2061 wServiceStartName = SERV_dup( lpServiceStartName );
2062 wPassword = SERV_dup( lpPassword );
2063 wDisplayName = SERV_dup( lpDisplayName );
2065 r = ChangeServiceConfigW( hService, dwServiceType,
2066 dwStartType, dwErrorControl, wBinaryPathName,
2067 wLoadOrderGroup, lpdwTagId, wDependencies,
2068 wServiceStartName, wPassword, wDisplayName);
2070 HeapFree( GetProcessHeap(), 0, wBinaryPathName );
2071 HeapFree( GetProcessHeap(), 0, wLoadOrderGroup );
2072 HeapFree( GetProcessHeap(), 0, wDependencies );
2073 HeapFree( GetProcessHeap(), 0, wServiceStartName );
2074 HeapFree( GetProcessHeap(), 0, wPassword );
2075 HeapFree( GetProcessHeap(), 0, wDisplayName );
2077 return r;
2080 /******************************************************************************
2081 * ChangeServiceConfig2A [ADVAPI32.@]
2083 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
2084 LPVOID lpInfo)
2086 BOOL r = FALSE;
2088 TRACE("%p %d %p\n",hService, dwInfoLevel, lpInfo);
2090 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2092 LPSERVICE_DESCRIPTIONA sd = lpInfo;
2093 SERVICE_DESCRIPTIONW sdw;
2095 sdw.lpDescription = SERV_dup( sd->lpDescription );
2097 r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
2099 HeapFree( GetProcessHeap(), 0, sdw.lpDescription );
2101 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
2103 LPSERVICE_FAILURE_ACTIONSA fa = lpInfo;
2104 SERVICE_FAILURE_ACTIONSW faw;
2106 faw.dwResetPeriod = fa->dwResetPeriod;
2107 faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg );
2108 faw.lpCommand = SERV_dup( fa->lpCommand );
2109 faw.cActions = fa->cActions;
2110 faw.lpsaActions = fa->lpsaActions;
2112 r = ChangeServiceConfig2W( hService, dwInfoLevel, &faw );
2114 HeapFree( GetProcessHeap(), 0, faw.lpRebootMsg );
2115 HeapFree( GetProcessHeap(), 0, faw.lpCommand );
2117 else if (dwInfoLevel == SERVICE_CONFIG_PRESHUTDOWN_INFO)
2119 r = ChangeServiceConfig2W( hService, dwInfoLevel, lpInfo);
2121 else
2122 SetLastError( ERROR_INVALID_PARAMETER );
2124 return r;
2127 /******************************************************************************
2128 * ChangeServiceConfig2W [ADVAPI32.@]
2130 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
2131 LPVOID lpInfo)
2133 DWORD err;
2135 __TRY
2137 err = svcctl_ChangeServiceConfig2W( hService, dwInfoLevel, lpInfo );
2139 __EXCEPT(rpc_filter)
2141 err = map_exception_code(GetExceptionCode());
2143 __ENDTRY
2145 if (err != ERROR_SUCCESS)
2146 SetLastError(err);
2148 return err == ERROR_SUCCESS;
2151 /******************************************************************************
2152 * QueryServiceObjectSecurity [ADVAPI32.@]
2154 BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
2155 SECURITY_INFORMATION dwSecurityInformation,
2156 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2157 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2159 SECURITY_DESCRIPTOR descriptor;
2160 DWORD size;
2161 BOOL succ;
2162 ACL acl;
2164 FIXME("%p %d %p %u %p - semi-stub\n", hService, dwSecurityInformation,
2165 lpSecurityDescriptor, cbBufSize, pcbBytesNeeded);
2167 if (dwSecurityInformation != DACL_SECURITY_INFORMATION)
2168 FIXME("information %d not supported\n", dwSecurityInformation);
2170 InitializeSecurityDescriptor(&descriptor, SECURITY_DESCRIPTOR_REVISION);
2172 InitializeAcl(&acl, sizeof(ACL), ACL_REVISION);
2173 SetSecurityDescriptorDacl(&descriptor, TRUE, &acl, TRUE);
2175 size = cbBufSize;
2176 succ = MakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
2177 *pcbBytesNeeded = size;
2178 return succ;
2181 /******************************************************************************
2182 * SetServiceObjectSecurity [ADVAPI32.@]
2184 BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService,
2185 SECURITY_INFORMATION dwSecurityInformation,
2186 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2188 FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
2189 return TRUE;
2192 /******************************************************************************
2193 * SetServiceBits [ADVAPI32.@]
2195 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
2196 DWORD dwServiceBits,
2197 BOOL bSetBitsOn,
2198 BOOL bUpdateImmediately)
2200 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
2201 bSetBitsOn, bUpdateImmediately);
2202 return TRUE;
2205 /* thunk for calling the RegisterServiceCtrlHandler handler function */
2206 static DWORD WINAPI ctrl_handler_thunk( DWORD control, DWORD type, void *data, void *context )
2208 LPHANDLER_FUNCTION func = context;
2210 func( control );
2211 return ERROR_SUCCESS;
2214 /******************************************************************************
2215 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
2217 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER_FUNCTION handler )
2219 return RegisterServiceCtrlHandlerExA( name, ctrl_handler_thunk, handler );
2222 /******************************************************************************
2223 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
2225 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLER_FUNCTION handler )
2227 return RegisterServiceCtrlHandlerExW( name, ctrl_handler_thunk, handler );
2230 /******************************************************************************
2231 * RegisterServiceCtrlHandlerExA [ADVAPI32.@]
2233 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDLER_FUNCTION_EX handler, LPVOID context )
2235 LPWSTR nameW;
2236 SERVICE_STATUS_HANDLE ret;
2238 nameW = SERV_dup(name);
2239 ret = RegisterServiceCtrlHandlerExW( nameW, handler, context );
2240 HeapFree( GetProcessHeap(), 0, nameW );
2241 return ret;
2244 /******************************************************************************
2245 * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
2247 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
2248 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2250 service_data *service;
2251 SC_HANDLE hService = 0;
2252 BOOL found = FALSE;
2254 TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
2256 EnterCriticalSection( &service_cs );
2257 if ((service = find_service_by_name( lpServiceName )))
2259 service->handler = lpHandlerProc;
2260 service->context = lpContext;
2261 hService = service->handle;
2262 found = TRUE;
2264 LeaveCriticalSection( &service_cs );
2266 if (!found) SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
2268 return (SERVICE_STATUS_HANDLE)hService;
2271 /******************************************************************************
2272 * EnumDependentServicesA [ADVAPI32.@]
2274 BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState,
2275 LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize,
2276 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2278 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2279 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2281 *lpServicesReturned = 0;
2282 return TRUE;
2285 /******************************************************************************
2286 * EnumDependentServicesW [ADVAPI32.@]
2288 BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
2289 LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize,
2290 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2292 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2293 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2295 *lpServicesReturned = 0;
2296 return TRUE;