oleaut32: Fix remaining memory leak (coverity).
[wine.git] / dlls / advapi32 / service.c
blob07b9e4bc078d917846da23fa34b68ea0f41ceb7e
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] );
551 else return FALSE;
555 /******************************************************************************
556 * StartServiceCtrlDispatcherA [ADVAPI32.@]
558 * See StartServiceCtrlDispatcherW.
560 BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
562 service_data *info;
563 unsigned int i;
564 BOOL ret = TRUE;
566 TRACE("%p\n", servent);
568 if (nb_services)
570 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
571 return FALSE;
573 while (servent[nb_services].lpServiceName) nb_services++;
574 if (!nb_services)
576 SetLastError( ERROR_INVALID_PARAMETER );
577 return FALSE;
580 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
582 for (i = 0; i < nb_services; i++)
584 DWORD len = MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, NULL, 0);
585 DWORD sz = FIELD_OFFSET( service_data, name[len] );
586 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
587 MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, info->name, len);
588 info->proc.a = servent[i].lpServiceProc;
589 info->unicode = FALSE;
590 services[i] = info;
593 service_run_main_thread();
595 return ret;
598 /******************************************************************************
599 * StartServiceCtrlDispatcherW [ADVAPI32.@]
601 * Connects a process containing one or more services to the service control
602 * manager.
604 * PARAMS
605 * servent [I] A list of the service names and service procedures
607 * RETURNS
608 * Success: TRUE.
609 * Failure: FALSE.
611 BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
613 service_data *info;
614 unsigned int i;
615 BOOL ret = TRUE;
617 TRACE("%p\n", servent);
619 if (nb_services)
621 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
622 return FALSE;
624 while (servent[nb_services].lpServiceName) nb_services++;
625 if (!nb_services)
627 SetLastError( ERROR_INVALID_PARAMETER );
628 return FALSE;
631 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
633 for (i = 0; i < nb_services; i++)
635 DWORD len = strlenW(servent[i].lpServiceName) + 1;
636 DWORD sz = FIELD_OFFSET( service_data, name[len] );
637 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
638 strcpyW(info->name, servent[i].lpServiceName);
639 info->proc.w = servent[i].lpServiceProc;
640 info->unicode = TRUE;
641 services[i] = info;
644 service_run_main_thread();
646 return ret;
649 /******************************************************************************
650 * LockServiceDatabase [ADVAPI32.@]
652 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
654 SC_RPC_LOCK hLock = NULL;
655 DWORD err;
657 TRACE("%p\n",hSCManager);
659 __TRY
661 err = svcctl_LockServiceDatabase(hSCManager, &hLock);
663 __EXCEPT(rpc_filter)
665 err = map_exception_code(GetExceptionCode());
667 __ENDTRY
668 if (err != ERROR_SUCCESS)
670 SetLastError(err);
671 return NULL;
673 return hLock;
676 /******************************************************************************
677 * UnlockServiceDatabase [ADVAPI32.@]
679 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
681 DWORD err;
682 SC_RPC_LOCK hRpcLock = ScLock;
684 TRACE("%p\n",ScLock);
686 __TRY
688 err = svcctl_UnlockServiceDatabase(&hRpcLock);
690 __EXCEPT(rpc_filter)
692 err = map_exception_code(GetExceptionCode());
694 __ENDTRY
695 if (err != ERROR_SUCCESS)
697 SetLastError(err);
698 return FALSE;
700 return TRUE;
703 /******************************************************************************
704 * SetServiceStatus [ADVAPI32.@]
706 * PARAMS
707 * hService []
708 * lpStatus []
710 BOOL WINAPI
711 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
713 DWORD err;
715 TRACE("%p %x %x %x %x %x %x %x\n", hService,
716 lpStatus->dwServiceType, lpStatus->dwCurrentState,
717 lpStatus->dwControlsAccepted, lpStatus->dwWin32ExitCode,
718 lpStatus->dwServiceSpecificExitCode, lpStatus->dwCheckPoint,
719 lpStatus->dwWaitHint);
721 __TRY
723 err = svcctl_SetServiceStatus( hService, lpStatus );
725 __EXCEPT(rpc_filter)
727 err = map_exception_code(GetExceptionCode());
729 __ENDTRY
730 if (err != ERROR_SUCCESS)
732 SetLastError(err);
733 return FALSE;
736 if (lpStatus->dwCurrentState == SERVICE_STOPPED) {
737 SetEvent(stop_event);
738 CloseServiceHandle((SC_HANDLE)hService);
741 return TRUE;
745 /******************************************************************************
746 * OpenSCManagerA [ADVAPI32.@]
748 * Establish a connection to the service control manager and open its database.
750 * PARAMS
751 * lpMachineName [I] Pointer to machine name string
752 * lpDatabaseName [I] Pointer to database name string
753 * dwDesiredAccess [I] Type of access
755 * RETURNS
756 * Success: A Handle to the service control manager database
757 * Failure: NULL
759 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
760 DWORD dwDesiredAccess )
762 LPWSTR lpMachineNameW, lpDatabaseNameW;
763 SC_HANDLE ret;
765 lpMachineNameW = SERV_dup(lpMachineName);
766 lpDatabaseNameW = SERV_dup(lpDatabaseName);
767 ret = OpenSCManagerW(lpMachineNameW, lpDatabaseNameW, dwDesiredAccess);
768 HeapFree(GetProcessHeap(), 0, lpDatabaseNameW);
769 HeapFree(GetProcessHeap(), 0, lpMachineNameW);
770 return ret;
773 /******************************************************************************
774 * OpenSCManagerW [ADVAPI32.@]
776 * See OpenSCManagerA.
778 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
779 DWORD dwDesiredAccess )
781 SC_HANDLE handle = 0;
782 LONG r;
784 TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
785 debugstr_w(lpDatabaseName), dwDesiredAccess);
787 __TRY
789 r = svcctl_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, (SC_RPC_HANDLE *)&handle);
791 __EXCEPT(rpc_filter)
793 r = map_exception_code(GetExceptionCode());
795 __ENDTRY
797 if (r!=ERROR_SUCCESS)
799 SetLastError( r );
800 handle = 0;
803 TRACE("returning %p\n", handle);
804 return handle;
807 /******************************************************************************
808 * ControlService [ADVAPI32.@]
810 * Send a control code to a service.
812 * PARAMS
813 * hService [I] Handle of the service control manager database
814 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
815 * lpServiceStatus [O] Destination for the status of the service, if available
817 * RETURNS
818 * Success: TRUE.
819 * Failure: FALSE.
821 * BUGS
822 * Unlike M$' implementation, control requests are not serialized and may be
823 * processed asynchronously.
825 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
826 LPSERVICE_STATUS lpServiceStatus )
828 DWORD err;
830 TRACE("%p %d %p\n", hService, dwControl, lpServiceStatus);
832 __TRY
834 err = svcctl_ControlService(hService, dwControl, lpServiceStatus);
836 __EXCEPT(rpc_filter)
838 err = map_exception_code(GetExceptionCode());
840 __ENDTRY
841 if (err != ERROR_SUCCESS)
843 SetLastError(err);
844 return FALSE;
847 return TRUE;
850 /******************************************************************************
851 * CloseServiceHandle [ADVAPI32.@]
853 * Close a handle to a service or the service control manager database.
855 * PARAMS
856 * hSCObject [I] Handle to service or service control manager database
858 * RETURNS
859 * Success: TRUE
860 * Failure: FALSE
862 BOOL WINAPI
863 CloseServiceHandle( SC_HANDLE hSCObject )
865 DWORD err;
867 TRACE("%p\n", hSCObject);
869 __TRY
871 err = svcctl_CloseServiceHandle((SC_RPC_HANDLE *)&hSCObject);
873 __EXCEPT(rpc_filter)
875 err = map_exception_code(GetExceptionCode());
877 __ENDTRY
879 if (err != ERROR_SUCCESS)
881 SetLastError(err);
882 return FALSE;
884 return TRUE;
888 /******************************************************************************
889 * OpenServiceA [ADVAPI32.@]
891 * Open a handle to a service.
893 * PARAMS
894 * hSCManager [I] Handle of the service control manager database
895 * lpServiceName [I] Name of the service to open
896 * dwDesiredAccess [I] Access required to the service
898 * RETURNS
899 * Success: Handle to the service
900 * Failure: NULL
902 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
903 DWORD dwDesiredAccess )
905 LPWSTR lpServiceNameW;
906 SC_HANDLE ret;
908 TRACE("%p %s %d\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
910 lpServiceNameW = SERV_dup(lpServiceName);
911 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
912 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
913 return ret;
917 /******************************************************************************
918 * OpenServiceW [ADVAPI32.@]
920 * See OpenServiceA.
922 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
923 DWORD dwDesiredAccess)
925 SC_HANDLE handle = 0;
926 DWORD err;
928 TRACE("%p %s %d\n", hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
930 if (!hSCManager)
932 SetLastError( ERROR_INVALID_HANDLE );
933 return 0;
936 __TRY
938 err = svcctl_OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess, (SC_RPC_HANDLE *)&handle);
940 __EXCEPT(rpc_filter)
942 err = map_exception_code(GetExceptionCode());
944 __ENDTRY
946 if (err != ERROR_SUCCESS)
948 SetLastError(err);
949 handle = 0;
952 TRACE("returning %p\n",handle);
953 return handle;
956 /******************************************************************************
957 * CreateServiceW [ADVAPI32.@]
959 SC_HANDLE WINAPI
960 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
961 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
962 DWORD dwServiceType, DWORD dwStartType,
963 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
964 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
965 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
966 LPCWSTR lpPassword )
968 SC_HANDLE handle = 0;
969 DWORD err;
970 SIZE_T passwdlen;
972 TRACE("%p %s %s\n", hSCManager,
973 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
975 if (!hSCManager)
977 SetLastError( ERROR_INVALID_HANDLE );
978 return 0;
981 if (lpPassword)
982 passwdlen = (strlenW(lpPassword) + 1) * sizeof(WCHAR);
983 else
984 passwdlen = 0;
986 __TRY
988 err = svcctl_CreateServiceW(hSCManager, lpServiceName,
989 lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
990 lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, (const BYTE*)lpDependencies,
991 multisz_cb(lpDependencies), lpServiceStartName, (const BYTE*)lpPassword, passwdlen,
992 (SC_RPC_HANDLE *)&handle);
994 __EXCEPT(rpc_filter)
996 err = map_exception_code(GetExceptionCode());
998 __ENDTRY
1000 if (err != ERROR_SUCCESS)
1002 SetLastError(err);
1003 handle = 0;
1005 return handle;
1009 /******************************************************************************
1010 * CreateServiceA [ADVAPI32.@]
1012 SC_HANDLE WINAPI
1013 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1014 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
1015 DWORD dwServiceType, DWORD dwStartType,
1016 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1017 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1018 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
1019 LPCSTR lpPassword )
1021 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
1022 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
1023 SC_HANDLE r;
1025 TRACE("%p %s %s\n", hSCManager,
1026 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
1028 lpServiceNameW = SERV_dup( lpServiceName );
1029 lpDisplayNameW = SERV_dup( lpDisplayName );
1030 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
1031 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
1032 lpDependenciesW = SERV_dupmulti( lpDependencies );
1033 lpServiceStartNameW = SERV_dup( lpServiceStartName );
1034 lpPasswordW = SERV_dup( lpPassword );
1036 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
1037 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1038 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
1039 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
1041 HeapFree( GetProcessHeap(), 0, lpServiceNameW );
1042 HeapFree( GetProcessHeap(), 0, lpDisplayNameW );
1043 HeapFree( GetProcessHeap(), 0, lpBinaryPathNameW );
1044 HeapFree( GetProcessHeap(), 0, lpLoadOrderGroupW );
1045 HeapFree( GetProcessHeap(), 0, lpDependenciesW );
1046 HeapFree( GetProcessHeap(), 0, lpServiceStartNameW );
1047 HeapFree( GetProcessHeap(), 0, lpPasswordW );
1049 return r;
1053 /******************************************************************************
1054 * DeleteService [ADVAPI32.@]
1056 * Delete a service from the service control manager database.
1058 * PARAMS
1059 * hService [I] Handle of the service to delete
1061 * RETURNS
1062 * Success: TRUE
1063 * Failure: FALSE
1065 BOOL WINAPI DeleteService( SC_HANDLE hService )
1067 DWORD err;
1069 __TRY
1071 err = svcctl_DeleteService(hService);
1073 __EXCEPT(rpc_filter)
1075 err = map_exception_code(GetExceptionCode());
1077 __ENDTRY
1078 if (err != 0)
1080 SetLastError(err);
1081 return FALSE;
1084 return TRUE;
1088 /******************************************************************************
1089 * StartServiceA [ADVAPI32.@]
1091 * Start a service
1093 * PARAMS
1094 * hService [I] Handle of service
1095 * dwNumServiceArgs [I] Number of arguments
1096 * lpServiceArgVectors [I] Address of array of argument strings
1098 * NOTES
1099 * - NT implements this function using an obscure RPC call.
1100 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1101 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
1102 * - This will only work for shared address space. How should the service
1103 * args be transferred when address spaces are separated?
1104 * - Can only start one service at a time.
1105 * - Has no concept of privilege.
1107 * RETURNS
1108 * Success: TRUE.
1109 * Failure: FALSE
1111 BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
1112 LPCSTR *lpServiceArgVectors )
1114 LPWSTR *lpwstr=NULL;
1115 unsigned int i;
1116 BOOL r;
1118 TRACE("(%p,%d,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
1120 if (dwNumServiceArgs)
1121 lpwstr = HeapAlloc( GetProcessHeap(), 0,
1122 dwNumServiceArgs*sizeof(LPWSTR) );
1124 for(i=0; i<dwNumServiceArgs; i++)
1125 lpwstr[i]=SERV_dup(lpServiceArgVectors[i]);
1127 r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
1129 if (dwNumServiceArgs)
1131 for(i=0; i<dwNumServiceArgs; i++)
1132 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
1133 HeapFree(GetProcessHeap(), 0, lpwstr);
1136 return r;
1140 /******************************************************************************
1141 * StartServiceW [ADVAPI32.@]
1143 * See StartServiceA.
1145 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1146 LPCWSTR *lpServiceArgVectors)
1148 DWORD err;
1150 TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1152 __TRY
1154 err = svcctl_StartServiceW(hService, dwNumServiceArgs, lpServiceArgVectors);
1156 __EXCEPT(rpc_filter)
1158 err = map_exception_code(GetExceptionCode());
1160 __ENDTRY
1161 if (err != ERROR_SUCCESS)
1163 SetLastError(err);
1164 return FALSE;
1167 return TRUE;
1170 /******************************************************************************
1171 * QueryServiceStatus [ADVAPI32.@]
1173 * PARAMS
1174 * hService [I] Handle to service to get information about
1175 * lpservicestatus [O] buffer to receive the status information for the service
1178 BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
1179 LPSERVICE_STATUS lpservicestatus)
1181 SERVICE_STATUS_PROCESS SvcStatusData;
1182 BOOL ret;
1183 DWORD dummy;
1185 TRACE("%p %p\n", hService, lpservicestatus);
1187 if (!hService)
1189 SetLastError(ERROR_INVALID_HANDLE);
1190 return FALSE;
1192 if (!lpservicestatus)
1194 SetLastError(ERROR_INVALID_ADDRESS);
1195 return FALSE;
1198 ret = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&SvcStatusData,
1199 sizeof(SERVICE_STATUS_PROCESS), &dummy);
1200 if (ret) memcpy(lpservicestatus, &SvcStatusData, sizeof(SERVICE_STATUS)) ;
1201 return ret;
1205 /******************************************************************************
1206 * QueryServiceStatusEx [ADVAPI32.@]
1208 * Get information about a service.
1210 * PARAMS
1211 * hService [I] Handle to service to get information about
1212 * InfoLevel [I] Level of information to get
1213 * lpBuffer [O] Destination for requested information
1214 * cbBufSize [I] Size of lpBuffer in bytes
1215 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1217 * RETURNS
1218 * Success: TRUE
1219 * FAILURE: FALSE
1221 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1222 LPBYTE lpBuffer, DWORD cbBufSize,
1223 LPDWORD pcbBytesNeeded)
1225 DWORD err;
1227 TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1229 if (InfoLevel != SC_STATUS_PROCESS_INFO)
1231 err = ERROR_INVALID_LEVEL;
1233 else if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
1235 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
1236 err = ERROR_INSUFFICIENT_BUFFER;
1238 else
1240 __TRY
1242 err = svcctl_QueryServiceStatusEx(hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1244 __EXCEPT(rpc_filter)
1246 err = map_exception_code(GetExceptionCode());
1248 __ENDTRY
1250 if (err != ERROR_SUCCESS)
1252 SetLastError(err);
1253 return FALSE;
1255 return TRUE;
1258 /******************************************************************************
1259 * QueryServiceConfigA [ADVAPI32.@]
1261 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1262 DWORD size, LPDWORD needed )
1264 DWORD n;
1265 LPSTR p, buffer;
1266 BOOL ret;
1267 QUERY_SERVICE_CONFIGW *configW;
1269 TRACE("%p %p %d %p\n", hService, config, size, needed);
1271 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, 2 * size )))
1273 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1274 return FALSE;
1276 configW = (QUERY_SERVICE_CONFIGW *)buffer;
1277 ret = QueryServiceConfigW( hService, configW, 2 * size, needed );
1278 if (!ret) goto done;
1280 config->dwServiceType = configW->dwServiceType;
1281 config->dwStartType = configW->dwStartType;
1282 config->dwErrorControl = configW->dwErrorControl;
1283 config->lpBinaryPathName = NULL;
1284 config->lpLoadOrderGroup = NULL;
1285 config->dwTagId = configW->dwTagId;
1286 config->lpDependencies = NULL;
1287 config->lpServiceStartName = NULL;
1288 config->lpDisplayName = NULL;
1290 p = (LPSTR)(config + 1);
1291 n = size - sizeof(*config);
1292 ret = FALSE;
1294 #define MAP_STR(str) \
1295 do { \
1296 if (configW->str) \
1298 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1299 if (!sz) goto done; \
1300 config->str = p; \
1301 p += sz; \
1302 n -= sz; \
1304 } while (0)
1306 MAP_STR( lpBinaryPathName );
1307 MAP_STR( lpLoadOrderGroup );
1308 MAP_STR( lpDependencies );
1309 MAP_STR( lpServiceStartName );
1310 MAP_STR( lpDisplayName );
1311 #undef MAP_STR
1313 *needed = p - (LPSTR)config;
1314 ret = TRUE;
1316 done:
1317 HeapFree( GetProcessHeap(), 0, buffer );
1318 return ret;
1321 static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
1323 DWORD cb;
1325 if (!*string_ptr)
1327 cb = sizeof(WCHAR);
1328 memset(*buf, 0, cb);
1330 else
1332 cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
1333 memcpy(*buf, *string_ptr, cb);
1334 MIDL_user_free(*string_ptr);
1337 *string_ptr = (LPWSTR)*buf;
1338 *buf += cb;
1340 return cb;
1343 static DWORD size_string(LPCWSTR string)
1345 return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
1348 /******************************************************************************
1349 * QueryServiceConfigW [ADVAPI32.@]
1351 BOOL WINAPI
1352 QueryServiceConfigW( SC_HANDLE hService,
1353 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1354 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1356 QUERY_SERVICE_CONFIGW config;
1357 DWORD total;
1358 DWORD err;
1359 BYTE *bufpos;
1361 TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1362 cbBufSize, pcbBytesNeeded);
1364 memset(&config, 0, sizeof(config));
1366 __TRY
1368 err = svcctl_QueryServiceConfigW(hService, &config);
1370 __EXCEPT(rpc_filter)
1372 err = map_exception_code(GetExceptionCode());
1374 __ENDTRY
1376 if (err != ERROR_SUCCESS)
1378 TRACE("services.exe: error %u\n", err);
1379 SetLastError(err);
1380 return FALSE;
1383 /* calculate the size required first */
1384 total = sizeof (QUERY_SERVICE_CONFIGW);
1385 total += size_string(config.lpBinaryPathName);
1386 total += size_string(config.lpLoadOrderGroup);
1387 total += size_string(config.lpDependencies);
1388 total += size_string(config.lpServiceStartName);
1389 total += size_string(config.lpDisplayName);
1391 *pcbBytesNeeded = total;
1393 /* if there's not enough memory, return an error */
1394 if( total > cbBufSize )
1396 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1397 MIDL_user_free(config.lpBinaryPathName);
1398 MIDL_user_free(config.lpLoadOrderGroup);
1399 MIDL_user_free(config.lpDependencies);
1400 MIDL_user_free(config.lpServiceStartName);
1401 MIDL_user_free(config.lpDisplayName);
1402 return FALSE;
1405 *lpServiceConfig = config;
1406 bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
1407 move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
1408 move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
1409 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
1410 move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
1411 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
1413 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1414 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1415 TRACE("Dependencies = %s\n", debugstr_w(lpServiceConfig->lpDependencies) );
1416 TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig->lpServiceStartName) );
1417 TRACE("Display name = %s\n", debugstr_w(lpServiceConfig->lpDisplayName) );
1419 return TRUE;
1422 /******************************************************************************
1423 * QueryServiceConfig2A [ADVAPI32.@]
1425 * Note
1426 * observed under win2k:
1427 * The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
1428 * required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
1430 BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1431 DWORD size, LPDWORD needed)
1433 BOOL ret;
1434 LPBYTE bufferW = NULL;
1436 if(buffer && size)
1437 bufferW = HeapAlloc( GetProcessHeap(), 0, size);
1439 ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
1440 if(!ret) goto cleanup;
1442 switch(dwLevel) {
1443 case SERVICE_CONFIG_DESCRIPTION:
1444 if (buffer && bufferW) {
1445 LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
1446 LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
1447 if (configW->lpDescription && (size > sizeof(SERVICE_DESCRIPTIONA))) {
1448 DWORD sz;
1449 configA->lpDescription = (LPSTR)(configA + 1);
1450 sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
1451 configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
1452 if (!sz) {
1453 FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1454 ret = FALSE;
1455 configA->lpDescription = NULL;
1458 else configA->lpDescription = NULL;
1460 break;
1461 case SERVICE_CONFIG_PRESHUTDOWN_INFO:
1462 if (buffer && bufferW && *needed<=size)
1463 memcpy(buffer, bufferW, *needed);
1464 break;
1465 default:
1466 FIXME("conversation W->A not implemented for level %d\n", dwLevel);
1467 ret = FALSE;
1468 break;
1471 cleanup:
1472 HeapFree( GetProcessHeap(), 0, bufferW);
1473 return ret;
1476 /******************************************************************************
1477 * QueryServiceConfig2W [ADVAPI32.@]
1479 * See QueryServiceConfig2A.
1481 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1482 DWORD size, LPDWORD needed)
1484 DWORD err;
1486 if(dwLevel!=SERVICE_CONFIG_DESCRIPTION && dwLevel!=SERVICE_CONFIG_PRESHUTDOWN_INFO) {
1487 FIXME("Level %d not implemented\n", dwLevel);
1488 SetLastError(ERROR_INVALID_LEVEL);
1489 return FALSE;
1492 if(!buffer && size) {
1493 SetLastError(ERROR_INVALID_ADDRESS);
1494 return FALSE;
1497 TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
1499 __TRY
1501 err = svcctl_QueryServiceConfig2W(hService, dwLevel, buffer, size, needed);
1503 __EXCEPT(rpc_filter)
1505 err = map_exception_code(GetExceptionCode());
1507 __ENDTRY
1509 if (err != ERROR_SUCCESS)
1511 SetLastError( err );
1512 return FALSE;
1515 switch (dwLevel)
1517 case SERVICE_CONFIG_DESCRIPTION:
1518 if (buffer)
1520 SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
1521 if (descr->lpDescription) /* make it an absolute pointer */
1522 descr->lpDescription = (WCHAR *)(buffer + (ULONG_PTR)descr->lpDescription);
1523 break;
1527 return TRUE;
1530 /******************************************************************************
1531 * EnumServicesStatusA [ADVAPI32.@]
1533 BOOL WINAPI
1534 EnumServicesStatusA( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSA
1535 services, DWORD size, LPDWORD needed, LPDWORD returned,
1536 LPDWORD resume_handle )
1538 BOOL ret;
1539 unsigned int i;
1540 ENUM_SERVICE_STATUSW *servicesW = NULL;
1541 DWORD sz, n;
1542 char *p;
1544 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
1545 returned, resume_handle);
1547 sz = max( 2 * size, sizeof(*servicesW) );
1548 if (!(servicesW = HeapAlloc( GetProcessHeap(), 0, sz )))
1550 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1551 return FALSE;
1554 ret = EnumServicesStatusW( hmngr, type, state, servicesW, sz, needed, returned, resume_handle );
1555 if (!ret) goto done;
1557 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUSA);
1558 n = size - (p - (char *)services);
1559 ret = FALSE;
1560 for (i = 0; i < *returned; i++)
1562 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
1563 if (!sz) goto done;
1564 services[i].lpServiceName = p;
1565 p += sz;
1566 n -= sz;
1567 if (servicesW[i].lpDisplayName)
1569 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
1570 if (!sz) goto done;
1571 services[i].lpDisplayName = p;
1572 p += sz;
1573 n -= sz;
1575 else services[i].lpDisplayName = NULL;
1576 services[i].ServiceStatus = servicesW[i].ServiceStatus;
1579 ret = TRUE;
1581 done:
1582 HeapFree( GetProcessHeap(), 0, servicesW );
1583 return ret;
1586 /******************************************************************************
1587 * EnumServicesStatusW [ADVAPI32.@]
1589 BOOL WINAPI
1590 EnumServicesStatusW( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSW
1591 services, DWORD size, LPDWORD needed, LPDWORD returned,
1592 LPDWORD resume_handle )
1594 DWORD err, i;
1595 ENUM_SERVICE_STATUSW dummy_status;
1597 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
1598 returned, resume_handle);
1600 if (resume_handle)
1601 FIXME("resume handle not supported\n");
1603 if (!hmngr)
1605 SetLastError( ERROR_INVALID_HANDLE );
1606 return FALSE;
1609 /* make sure we pass a valid pointer */
1610 if (!services || size < sizeof(*services))
1612 services = &dummy_status;
1613 size = sizeof(dummy_status);
1616 __TRY
1618 err = svcctl_EnumServicesStatusW( hmngr, type, state, (BYTE *)services, size, needed, returned );
1620 __EXCEPT(rpc_filter)
1622 err = map_exception_code( GetExceptionCode() );
1624 __ENDTRY
1626 if (err != ERROR_SUCCESS)
1628 SetLastError( err );
1629 return FALSE;
1632 for (i = 0; i < *returned; i++)
1634 /* convert buffer offsets into pointers */
1635 services[i].lpServiceName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpServiceName);
1636 if (services[i].lpDisplayName)
1637 services[i].lpDisplayName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpDisplayName);
1640 return TRUE;
1643 /******************************************************************************
1644 * EnumServicesStatusExA [ADVAPI32.@]
1646 BOOL WINAPI
1647 EnumServicesStatusExA( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state,
1648 LPBYTE buffer, DWORD size, LPDWORD needed, LPDWORD returned,
1649 LPDWORD resume_handle, LPCSTR group )
1651 BOOL ret;
1652 unsigned int i;
1653 ENUM_SERVICE_STATUS_PROCESSA *services = (ENUM_SERVICE_STATUS_PROCESSA *)buffer;
1654 ENUM_SERVICE_STATUS_PROCESSW *servicesW = NULL;
1655 WCHAR *groupW = NULL;
1656 DWORD sz, n;
1657 char *p;
1659 TRACE("%p %u 0x%x 0x%x %p %u %p %p %p %s\n", hmngr, level, type, state, buffer,
1660 size, needed, returned, resume_handle, debugstr_a(group));
1662 sz = max( 2 * size, sizeof(*servicesW) );
1663 if (!(servicesW = HeapAlloc( GetProcessHeap(), 0, sz )))
1665 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1666 return FALSE;
1668 if (group)
1670 int len = MultiByteToWideChar( CP_ACP, 0, group, -1, NULL, 0 );
1671 if (!(groupW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1673 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1674 HeapFree( GetProcessHeap(), 0, servicesW );
1675 return FALSE;
1677 MultiByteToWideChar( CP_ACP, 0, group, -1, groupW, len * sizeof(WCHAR) );
1680 ret = EnumServicesStatusExW( hmngr, level, type, state, (BYTE *)servicesW, sz,
1681 needed, returned, resume_handle, groupW );
1682 if (!ret) goto done;
1684 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUS_PROCESSA);
1685 n = size - (p - (char *)services);
1686 ret = FALSE;
1687 for (i = 0; i < *returned; i++)
1689 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
1690 if (!sz) goto done;
1691 services[i].lpServiceName = p;
1692 p += sz;
1693 n -= sz;
1694 if (servicesW[i].lpDisplayName)
1696 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
1697 if (!sz) goto done;
1698 services[i].lpDisplayName = p;
1699 p += sz;
1700 n -= sz;
1702 else services[i].lpDisplayName = NULL;
1703 services[i].ServiceStatusProcess = servicesW[i].ServiceStatusProcess;
1706 ret = TRUE;
1708 done:
1709 HeapFree( GetProcessHeap(), 0, servicesW );
1710 HeapFree( GetProcessHeap(), 0, groupW );
1711 return ret;
1714 /******************************************************************************
1715 * EnumServicesStatusExW [ADVAPI32.@]
1717 BOOL WINAPI
1718 EnumServicesStatusExW( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state,
1719 LPBYTE buffer, DWORD size, LPDWORD needed, LPDWORD returned,
1720 LPDWORD resume_handle, LPCWSTR group )
1722 DWORD err, i;
1723 ENUM_SERVICE_STATUS_PROCESSW dummy_status;
1724 ENUM_SERVICE_STATUS_PROCESSW *services = (ENUM_SERVICE_STATUS_PROCESSW *)buffer;
1726 TRACE("%p %u 0x%x 0x%x %p %u %p %p %p %s\n", hmngr, level, type, state, buffer,
1727 size, needed, returned, resume_handle, debugstr_w(group));
1729 if (resume_handle)
1730 FIXME("resume handle not supported\n");
1732 if (level != SC_ENUM_PROCESS_INFO)
1734 SetLastError( ERROR_INVALID_LEVEL );
1735 return FALSE;
1737 if (!hmngr)
1739 SetLastError( ERROR_INVALID_HANDLE );
1740 return FALSE;
1743 /* make sure we pass a valid buffer pointer */
1744 if (!services || size < sizeof(*services))
1746 buffer = (BYTE *)&dummy_status;
1747 size = sizeof(dummy_status);
1750 __TRY
1752 err = svcctl_EnumServicesStatusExW( hmngr, type, state, buffer, size, needed,
1753 returned, group );
1755 __EXCEPT(rpc_filter)
1757 err = map_exception_code( GetExceptionCode() );
1759 __ENDTRY
1761 if (err != ERROR_SUCCESS)
1763 SetLastError( err );
1764 return FALSE;
1767 for (i = 0; i < *returned; i++)
1769 /* convert buffer offsets into pointers */
1770 services[i].lpServiceName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpServiceName);
1771 if (services[i].lpDisplayName)
1772 services[i].lpDisplayName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpDisplayName);
1775 return TRUE;
1778 /******************************************************************************
1779 * GetServiceKeyNameA [ADVAPI32.@]
1781 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1782 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1784 LPWSTR lpDisplayNameW, lpServiceNameW;
1785 DWORD sizeW;
1786 BOOL ret = FALSE;
1788 TRACE("%p %s %p %p\n", hSCManager,
1789 debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1791 lpDisplayNameW = SERV_dup(lpDisplayName);
1792 if (lpServiceName)
1793 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1794 else
1795 lpServiceNameW = NULL;
1797 sizeW = *lpcchBuffer;
1798 if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
1800 if (lpServiceName && *lpcchBuffer)
1801 lpServiceName[0] = 0;
1802 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1803 goto cleanup;
1806 if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
1807 *lpcchBuffer, NULL, NULL ))
1809 if (*lpcchBuffer && lpServiceName)
1810 lpServiceName[0] = 0;
1811 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
1812 goto cleanup;
1815 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1816 ret = TRUE;
1818 cleanup:
1819 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1820 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1821 return ret;
1824 /******************************************************************************
1825 * GetServiceKeyNameW [ADVAPI32.@]
1827 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1828 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1830 DWORD err;
1831 WCHAR buffer[2];
1832 DWORD size;
1834 TRACE("%p %s %p %p\n", hSCManager,
1835 debugstr_w(lpDisplayName), lpServiceName, lpcchBuffer);
1837 if (!hSCManager)
1839 SetLastError( ERROR_INVALID_HANDLE );
1840 return 0;
1843 /* provide a buffer if the caller didn't */
1844 if (!lpServiceName || *lpcchBuffer < 2)
1846 lpServiceName = buffer;
1847 /* A size of 1 would be enough, but tests show that Windows returns 2,
1848 * probably because of a WCHAR/bytes mismatch in their code.
1850 *lpcchBuffer = 2;
1853 /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
1854 * includes the nul-terminator on input. */
1855 size = *lpcchBuffer - 1;
1857 __TRY
1859 err = svcctl_GetServiceKeyNameW(hSCManager, lpDisplayName, lpServiceName,
1860 &size);
1862 __EXCEPT(rpc_filter)
1864 err = map_exception_code(GetExceptionCode());
1866 __ENDTRY
1868 /* The value of *lpcchBuffer excludes nul-terminator on output. */
1869 if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
1870 *lpcchBuffer = size;
1872 if (err)
1873 SetLastError(err);
1874 return err == ERROR_SUCCESS;
1877 /******************************************************************************
1878 * QueryServiceLockStatusA [ADVAPI32.@]
1880 BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
1881 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1882 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1884 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1886 return FALSE;
1889 /******************************************************************************
1890 * QueryServiceLockStatusW [ADVAPI32.@]
1892 BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
1893 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1894 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1896 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1898 return FALSE;
1901 /******************************************************************************
1902 * GetServiceDisplayNameA [ADVAPI32.@]
1904 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1905 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1907 LPWSTR lpServiceNameW, lpDisplayNameW;
1908 DWORD sizeW;
1909 BOOL ret = FALSE;
1911 TRACE("%p %s %p %p\n", hSCManager,
1912 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1914 lpServiceNameW = SERV_dup(lpServiceName);
1915 if (lpDisplayName)
1916 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1917 else
1918 lpDisplayNameW = NULL;
1920 sizeW = *lpcchBuffer;
1921 if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
1923 if (lpDisplayName && *lpcchBuffer)
1924 lpDisplayName[0] = 0;
1925 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1926 goto cleanup;
1929 if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
1930 *lpcchBuffer, NULL, NULL ))
1932 if (*lpcchBuffer && lpDisplayName)
1933 lpDisplayName[0] = 0;
1934 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
1935 goto cleanup;
1938 /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
1939 * (but if the function succeeded it means that is a good upper estimation of the size) */
1940 ret = TRUE;
1942 cleanup:
1943 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1944 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1945 return ret;
1948 /******************************************************************************
1949 * GetServiceDisplayNameW [ADVAPI32.@]
1951 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1952 LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1954 DWORD err;
1955 DWORD size;
1956 WCHAR buffer[2];
1958 TRACE("%p %s %p %p\n", hSCManager,
1959 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1961 if (!hSCManager)
1963 SetLastError( ERROR_INVALID_HANDLE );
1964 return 0;
1967 /* provide a buffer if the caller didn't */
1968 if (!lpDisplayName || *lpcchBuffer < 2)
1970 lpDisplayName = buffer;
1971 /* A size of 1 would be enough, but tests show that Windows returns 2,
1972 * probably because of a WCHAR/bytes mismatch in their code.
1974 *lpcchBuffer = 2;
1977 /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
1978 * includes the nul-terminator on input. */
1979 size = *lpcchBuffer - 1;
1981 __TRY
1983 err = svcctl_GetServiceDisplayNameW(hSCManager, lpServiceName, lpDisplayName,
1984 &size);
1986 __EXCEPT(rpc_filter)
1988 err = map_exception_code(GetExceptionCode());
1990 __ENDTRY
1992 /* The value of *lpcchBuffer excludes nul-terminator on output. */
1993 if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
1994 *lpcchBuffer = size;
1996 if (err)
1997 SetLastError(err);
1998 return err == ERROR_SUCCESS;
2001 /******************************************************************************
2002 * ChangeServiceConfigW [ADVAPI32.@]
2004 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
2005 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
2006 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
2007 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
2009 DWORD cb_pwd;
2010 DWORD err;
2012 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2013 hService, dwServiceType, dwStartType, dwErrorControl,
2014 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
2015 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
2016 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
2018 cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
2020 __TRY
2022 err = svcctl_ChangeServiceConfigW(hService, dwServiceType,
2023 dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId,
2024 (const BYTE *)lpDependencies, multisz_cb(lpDependencies), lpServiceStartName,
2025 (const BYTE *)lpPassword, cb_pwd, lpDisplayName);
2027 __EXCEPT(rpc_filter)
2029 err = map_exception_code(GetExceptionCode());
2031 __ENDTRY
2033 if (err != ERROR_SUCCESS)
2034 SetLastError(err);
2036 return err == ERROR_SUCCESS;
2039 /******************************************************************************
2040 * ChangeServiceConfigA [ADVAPI32.@]
2042 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
2043 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
2044 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
2045 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
2047 LPWSTR wBinaryPathName, wLoadOrderGroup, wDependencies;
2048 LPWSTR wServiceStartName, wPassword, wDisplayName;
2049 BOOL r;
2051 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2052 hService, dwServiceType, dwStartType, dwErrorControl,
2053 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
2054 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
2055 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
2057 wBinaryPathName = SERV_dup( lpBinaryPathName );
2058 wLoadOrderGroup = SERV_dup( lpLoadOrderGroup );
2059 wDependencies = SERV_dupmulti( lpDependencies );
2060 wServiceStartName = SERV_dup( lpServiceStartName );
2061 wPassword = SERV_dup( lpPassword );
2062 wDisplayName = SERV_dup( lpDisplayName );
2064 r = ChangeServiceConfigW( hService, dwServiceType,
2065 dwStartType, dwErrorControl, wBinaryPathName,
2066 wLoadOrderGroup, lpdwTagId, wDependencies,
2067 wServiceStartName, wPassword, wDisplayName);
2069 HeapFree( GetProcessHeap(), 0, wBinaryPathName );
2070 HeapFree( GetProcessHeap(), 0, wLoadOrderGroup );
2071 HeapFree( GetProcessHeap(), 0, wDependencies );
2072 HeapFree( GetProcessHeap(), 0, wServiceStartName );
2073 HeapFree( GetProcessHeap(), 0, wPassword );
2074 HeapFree( GetProcessHeap(), 0, wDisplayName );
2076 return r;
2079 /******************************************************************************
2080 * ChangeServiceConfig2A [ADVAPI32.@]
2082 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
2083 LPVOID lpInfo)
2085 BOOL r = FALSE;
2087 TRACE("%p %d %p\n",hService, dwInfoLevel, lpInfo);
2089 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2091 LPSERVICE_DESCRIPTIONA sd = lpInfo;
2092 SERVICE_DESCRIPTIONW sdw;
2094 sdw.lpDescription = SERV_dup( sd->lpDescription );
2096 r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
2098 HeapFree( GetProcessHeap(), 0, sdw.lpDescription );
2100 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
2102 LPSERVICE_FAILURE_ACTIONSA fa = lpInfo;
2103 SERVICE_FAILURE_ACTIONSW faw;
2105 faw.dwResetPeriod = fa->dwResetPeriod;
2106 faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg );
2107 faw.lpCommand = SERV_dup( fa->lpCommand );
2108 faw.cActions = fa->cActions;
2109 faw.lpsaActions = fa->lpsaActions;
2111 r = ChangeServiceConfig2W( hService, dwInfoLevel, &faw );
2113 HeapFree( GetProcessHeap(), 0, faw.lpRebootMsg );
2114 HeapFree( GetProcessHeap(), 0, faw.lpCommand );
2116 else if (dwInfoLevel == SERVICE_CONFIG_PRESHUTDOWN_INFO)
2118 r = ChangeServiceConfig2W( hService, dwInfoLevel, lpInfo);
2120 else
2121 SetLastError( ERROR_INVALID_PARAMETER );
2123 return r;
2126 /******************************************************************************
2127 * ChangeServiceConfig2W [ADVAPI32.@]
2129 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
2130 LPVOID lpInfo)
2132 DWORD err;
2134 __TRY
2136 err = svcctl_ChangeServiceConfig2W( hService, dwInfoLevel, lpInfo );
2138 __EXCEPT(rpc_filter)
2140 err = map_exception_code(GetExceptionCode());
2142 __ENDTRY
2144 if (err != ERROR_SUCCESS)
2145 SetLastError(err);
2147 return err == ERROR_SUCCESS;
2150 /******************************************************************************
2151 * QueryServiceObjectSecurity [ADVAPI32.@]
2153 BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
2154 SECURITY_INFORMATION dwSecurityInformation,
2155 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2156 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2158 SECURITY_DESCRIPTOR descriptor;
2159 DWORD size;
2160 BOOL succ;
2161 ACL acl;
2163 FIXME("%p %d %p %u %p - semi-stub\n", hService, dwSecurityInformation,
2164 lpSecurityDescriptor, cbBufSize, pcbBytesNeeded);
2166 if (dwSecurityInformation != DACL_SECURITY_INFORMATION)
2167 FIXME("information %d not supported\n", dwSecurityInformation);
2169 InitializeSecurityDescriptor(&descriptor, SECURITY_DESCRIPTOR_REVISION);
2171 InitializeAcl(&acl, sizeof(ACL), ACL_REVISION);
2172 SetSecurityDescriptorDacl(&descriptor, TRUE, &acl, TRUE);
2174 size = cbBufSize;
2175 succ = MakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
2176 *pcbBytesNeeded = size;
2177 return succ;
2180 /******************************************************************************
2181 * SetServiceObjectSecurity [ADVAPI32.@]
2183 BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService,
2184 SECURITY_INFORMATION dwSecurityInformation,
2185 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2187 FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
2188 return TRUE;
2191 /******************************************************************************
2192 * SetServiceBits [ADVAPI32.@]
2194 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
2195 DWORD dwServiceBits,
2196 BOOL bSetBitsOn,
2197 BOOL bUpdateImmediately)
2199 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
2200 bSetBitsOn, bUpdateImmediately);
2201 return TRUE;
2204 /* thunk for calling the RegisterServiceCtrlHandler handler function */
2205 static DWORD WINAPI ctrl_handler_thunk( DWORD control, DWORD type, void *data, void *context )
2207 LPHANDLER_FUNCTION func = context;
2209 func( control );
2210 return ERROR_SUCCESS;
2213 /******************************************************************************
2214 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
2216 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER_FUNCTION handler )
2218 return RegisterServiceCtrlHandlerExA( name, ctrl_handler_thunk, handler );
2221 /******************************************************************************
2222 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
2224 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLER_FUNCTION handler )
2226 return RegisterServiceCtrlHandlerExW( name, ctrl_handler_thunk, handler );
2229 /******************************************************************************
2230 * RegisterServiceCtrlHandlerExA [ADVAPI32.@]
2232 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDLER_FUNCTION_EX handler, LPVOID context )
2234 LPWSTR nameW;
2235 SERVICE_STATUS_HANDLE ret;
2237 nameW = SERV_dup(name);
2238 ret = RegisterServiceCtrlHandlerExW( nameW, handler, context );
2239 HeapFree( GetProcessHeap(), 0, nameW );
2240 return ret;
2243 /******************************************************************************
2244 * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
2246 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
2247 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2249 service_data *service;
2250 SC_HANDLE hService = 0;
2251 BOOL found = FALSE;
2253 TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
2255 EnterCriticalSection( &service_cs );
2256 if ((service = find_service_by_name( lpServiceName )))
2258 service->handler = lpHandlerProc;
2259 service->context = lpContext;
2260 hService = service->handle;
2261 found = TRUE;
2263 LeaveCriticalSection( &service_cs );
2265 if (!found) SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
2267 return (SERVICE_STATUS_HANDLE)hService;
2270 /******************************************************************************
2271 * EnumDependentServicesA [ADVAPI32.@]
2273 BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState,
2274 LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize,
2275 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2277 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2278 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2280 *lpServicesReturned = 0;
2281 return TRUE;
2284 /******************************************************************************
2285 * EnumDependentServicesW [ADVAPI32.@]
2287 BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
2288 LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize,
2289 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2291 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2292 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2294 *lpServicesReturned = 0;
2295 return TRUE;