strmbase: Separate BaseFilter destructor from Release.
[wine.git] / dlls / advapi32 / service.c
blob6bfdda60bacdb130ea2caff27e9673ee502a4048
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 "ntstatus.h"
32 #define WIN32_NO_STATUS
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winsvc.h"
36 #include "winerror.h"
37 #include "winreg.h"
38 #include "wine/unicode.h"
39 #include "wine/debug.h"
40 #include "winternl.h"
41 #include "lmcons.h"
42 #include "lmserver.h"
44 #include "svcctl.h"
46 #include "advapi32_misc.h"
48 #include "wine/exception.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(service);
52 void __RPC_FAR * __RPC_USER MIDL_user_allocate(SIZE_T len)
54 return HeapAlloc(GetProcessHeap(), 0, len);
57 void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
59 HeapFree(GetProcessHeap(), 0, ptr);
62 typedef struct service_data_t
64 LPHANDLER_FUNCTION_EX handler;
65 LPVOID context;
66 HANDLE thread;
67 SC_HANDLE handle;
68 SC_HANDLE full_access_handle;
69 BOOL unicode : 1;
70 union {
71 LPSERVICE_MAIN_FUNCTIONA a;
72 LPSERVICE_MAIN_FUNCTIONW w;
73 } proc;
74 LPWSTR args;
75 WCHAR name[1];
76 } service_data;
78 typedef struct dispatcher_data_t
80 SC_HANDLE manager;
81 HANDLE pipe;
82 } dispatcher_data;
84 static CRITICAL_SECTION service_cs;
85 static CRITICAL_SECTION_DEBUG service_cs_debug =
87 0, 0, &service_cs,
88 { &service_cs_debug.ProcessLocksList,
89 &service_cs_debug.ProcessLocksList },
90 0, 0, { (DWORD_PTR)(__FILE__ ": service_cs") }
92 static CRITICAL_SECTION service_cs = { &service_cs_debug, -1, 0, 0, 0, 0 };
94 static service_data **services;
95 static unsigned int nb_services;
96 static HANDLE service_event;
97 static HANDLE stop_event;
99 extern HANDLE CDECL __wine_make_process_system(void);
101 /******************************************************************************
102 * String management functions (same behaviour as strdup)
103 * NOTE: the caller of those functions is responsible for calling HeapFree
104 * in order to release the memory allocated by those functions.
106 LPWSTR SERV_dup( LPCSTR str )
108 UINT len;
109 LPWSTR wstr;
111 if( !str )
112 return NULL;
113 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
114 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
115 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
116 return wstr;
119 static inline LPWSTR SERV_dupmulti(LPCSTR str)
121 UINT len = 0, n = 0;
122 LPWSTR wstr;
124 if( !str )
125 return NULL;
126 do {
127 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
128 n += (strlen( &str[n] ) + 1);
129 } while (str[n]);
130 len++;
131 n++;
133 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
134 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
135 return wstr;
138 static inline DWORD multisz_cb(LPCWSTR wmultisz)
140 const WCHAR *wptr = wmultisz;
142 if (wmultisz == NULL)
143 return 0;
145 while (*wptr)
146 wptr += lstrlenW(wptr)+1;
147 return (wptr - wmultisz + 1)*sizeof(WCHAR);
150 /******************************************************************************
151 * RPC connection with services.exe
154 DECLSPEC_HIDDEN handle_t __RPC_USER MACHINE_HANDLEW_bind(MACHINE_HANDLEW MachineName)
156 WCHAR transport[] = SVCCTL_TRANSPORT;
157 WCHAR endpoint[] = SVCCTL_ENDPOINT;
158 RPC_WSTR binding_str;
159 RPC_STATUS status;
160 handle_t rpc_handle;
162 status = RpcStringBindingComposeW(NULL, transport, (RPC_WSTR)MachineName, endpoint, NULL, &binding_str);
163 if (status != RPC_S_OK)
165 ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD)status);
166 return NULL;
169 status = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
170 RpcStringFreeW(&binding_str);
172 if (status != RPC_S_OK)
174 ERR("Couldn't connect to services.exe: error code %u\n", (DWORD)status);
175 return NULL;
178 return rpc_handle;
181 DECLSPEC_HIDDEN void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName, handle_t h)
183 RpcBindingFree(&h);
186 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr)
188 return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode);
191 static DWORD map_exception_code(DWORD exception_code)
193 switch (exception_code)
195 case RPC_X_NULL_REF_POINTER:
196 return ERROR_INVALID_ADDRESS;
197 case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
198 case RPC_X_BYTE_COUNT_TOO_SMALL:
199 return ERROR_INVALID_PARAMETER;
200 case RPC_S_INVALID_BINDING:
201 case RPC_X_SS_IN_NULL_CONTEXT:
202 return ERROR_INVALID_HANDLE;
203 default:
204 return exception_code;
208 /******************************************************************************
209 * Service IPC functions
211 static LPWSTR service_get_pipe_name(void)
213 static const WCHAR format[] = { '\\','\\','.','\\','p','i','p','e','\\',
214 'n','e','t','\\','N','t','C','o','n','t','r','o','l','P','i','p','e','%','u',0};
215 static const WCHAR service_current_key_str[] = { 'S','Y','S','T','E','M','\\',
216 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
217 'C','o','n','t','r','o','l','\\',
218 'S','e','r','v','i','c','e','C','u','r','r','e','n','t',0};
219 LPWSTR name;
220 DWORD len;
221 HKEY service_current_key;
222 DWORD service_current;
223 LONG ret;
224 DWORD type;
226 ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, service_current_key_str, 0,
227 KEY_QUERY_VALUE, &service_current_key);
228 if (ret != ERROR_SUCCESS)
229 return NULL;
230 len = sizeof(service_current);
231 ret = RegQueryValueExW(service_current_key, NULL, NULL, &type,
232 (BYTE *)&service_current, &len);
233 RegCloseKey(service_current_key);
234 if (ret != ERROR_SUCCESS || type != REG_DWORD)
235 return NULL;
236 len = sizeof(format)/sizeof(WCHAR) + 10 /* strlenW("4294967295") */;
237 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
238 if (!name)
239 return NULL;
240 snprintfW(name, len, format, service_current);
241 return name;
244 static HANDLE service_open_pipe(void)
246 LPWSTR szPipe = service_get_pipe_name();
247 HANDLE handle = INVALID_HANDLE_VALUE;
249 do {
250 handle = CreateFileW(szPipe, GENERIC_READ|GENERIC_WRITE,
251 0, NULL, OPEN_ALWAYS, 0, NULL);
252 if (handle != INVALID_HANDLE_VALUE)
253 break;
254 if (GetLastError() != ERROR_PIPE_BUSY)
255 break;
256 } while (WaitNamedPipeW(szPipe, NMPWAIT_USE_DEFAULT_WAIT));
257 HeapFree(GetProcessHeap(), 0, szPipe);
259 return handle;
262 static service_data *find_service_by_name( const WCHAR *name )
264 unsigned int i;
266 if (nb_services == 1) /* only one service (FIXME: should depend on OWN_PROCESS etc.) */
267 return services[0];
268 for (i = 0; i < nb_services; i++)
269 if (!strcmpiW( name, services[i]->name )) return services[i];
270 return NULL;
273 /******************************************************************************
274 * service_thread
276 * Call into the main service routine provided by StartServiceCtrlDispatcher.
278 static DWORD WINAPI service_thread(LPVOID arg)
280 service_data *info = arg;
281 LPWSTR str = info->args;
282 DWORD argc = 0, len = 0;
284 TRACE("%p\n", arg);
286 while (str[len])
288 len += strlenW(&str[len]) + 1;
289 argc++;
291 len++;
293 if (info->unicode)
295 LPWSTR *argv, p;
297 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR));
298 for (argc=0, p=str; *p; p += strlenW(p) + 1)
299 argv[argc++] = p;
300 argv[argc] = NULL;
302 info->proc.w(argc, argv);
303 HeapFree(GetProcessHeap(), 0, argv);
305 else
307 LPSTR strA, *argv, p;
308 DWORD lenA;
310 lenA = WideCharToMultiByte(CP_ACP,0, str, len, NULL, 0, NULL, NULL);
311 strA = HeapAlloc(GetProcessHeap(), 0, lenA);
312 WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL);
314 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPSTR));
315 for (argc=0, p=strA; *p; p += strlen(p) + 1)
316 argv[argc++] = p;
317 argv[argc] = NULL;
319 info->proc.a(argc, argv);
320 HeapFree(GetProcessHeap(), 0, argv);
321 HeapFree(GetProcessHeap(), 0, strA);
323 return 0;
326 /******************************************************************************
327 * service_handle_start
329 static DWORD service_handle_start(service_data *service, const WCHAR *data, DWORD count)
331 TRACE("%s argsize %u\n", debugstr_w(service->name), count);
333 if (service->thread)
335 WARN("service is not stopped\n");
336 return ERROR_SERVICE_ALREADY_RUNNING;
339 HeapFree(GetProcessHeap(), 0, service->args);
340 service->args = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
341 memcpy( service->args, data, count * sizeof(WCHAR) );
342 service->thread = CreateThread( NULL, 0, service_thread,
343 service, 0, NULL );
344 SetEvent( service_event ); /* notify the main loop */
345 return 0;
348 /******************************************************************************
349 * service_handle_control
351 static DWORD service_handle_control(const service_data *service, DWORD dwControl)
353 DWORD ret = ERROR_INVALID_SERVICE_CONTROL;
355 TRACE("%s control %u\n", debugstr_w(service->name), dwControl);
357 if (service->handler)
358 ret = service->handler(dwControl, 0, NULL, service->context);
359 return ret;
362 /******************************************************************************
363 * service_control_dispatcher
365 static DWORD WINAPI service_control_dispatcher(LPVOID arg)
367 dispatcher_data *disp = arg;
369 /* dispatcher loop */
370 while (1)
372 service_data *service;
373 service_start_info info;
374 WCHAR *data = NULL;
375 BOOL r;
376 DWORD data_size = 0, count, result;
378 r = ReadFile( disp->pipe, &info, FIELD_OFFSET(service_start_info,data), &count, NULL );
379 if (!r)
381 if (GetLastError() != ERROR_BROKEN_PIPE)
382 ERR( "pipe read failed error %u\n", GetLastError() );
383 break;
385 if (count != FIELD_OFFSET(service_start_info,data))
387 ERR( "partial pipe read %u\n", count );
388 break;
390 if (count < info.total_size)
392 data_size = info.total_size - FIELD_OFFSET(service_start_info,data);
393 data = HeapAlloc( GetProcessHeap(), 0, data_size );
394 r = ReadFile( disp->pipe, data, data_size, &count, NULL );
395 if (!r)
397 if (GetLastError() != ERROR_BROKEN_PIPE)
398 ERR( "pipe read failed error %u\n", GetLastError() );
399 HeapFree( GetProcessHeap(), 0, data );
400 break;
402 if (count != data_size)
404 ERR( "partial pipe read %u/%u\n", count, data_size );
405 HeapFree( GetProcessHeap(), 0, data );
406 break;
410 /* find the service */
412 if (!(service = find_service_by_name( data )))
414 FIXME( "got request %u for unknown service %s\n", info.cmd, debugstr_w(data));
415 result = ERROR_INVALID_PARAMETER;
416 goto done;
419 TRACE( "got request %u for service %s\n", info.cmd, debugstr_w(data) );
421 /* handle the request */
422 switch (info.cmd)
424 case WINESERV_STARTINFO:
425 if (!service->handle)
427 if (!(service->handle = OpenServiceW( disp->manager, data, SERVICE_SET_STATUS )) ||
428 !(service->full_access_handle = OpenServiceW( disp->manager, data,
429 GENERIC_READ|GENERIC_WRITE )))
430 FIXME( "failed to open service %s\n", debugstr_w(data) );
432 result = service_handle_start(service, data, data_size / sizeof(WCHAR));
433 break;
434 case WINESERV_SENDCONTROL:
435 result = service_handle_control(service, info.control);
436 break;
437 default:
438 ERR("received invalid command %u\n", info.cmd);
439 result = ERROR_INVALID_PARAMETER;
440 break;
443 done:
444 WriteFile( disp->pipe, &result, sizeof(result), &count, NULL );
445 HeapFree( GetProcessHeap(), 0, data );
448 CloseHandle( disp->pipe );
449 CloseServiceHandle( disp->manager );
450 HeapFree( GetProcessHeap(), 0, disp );
451 return 1;
454 /******************************************************************************
455 * service_run_main_thread
457 static BOOL service_run_main_thread(void)
459 DWORD i, n, ret;
460 HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
461 UINT wait_services[MAXIMUM_WAIT_OBJECTS];
462 dispatcher_data *disp = HeapAlloc( GetProcessHeap(), 0, sizeof(*disp) );
464 disp->manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT );
465 if (!disp->manager)
467 ERR("failed to open service manager error %u\n", GetLastError());
468 HeapFree( GetProcessHeap(), 0, disp );
469 return FALSE;
472 disp->pipe = service_open_pipe();
473 if (disp->pipe == INVALID_HANDLE_VALUE)
475 WARN("failed to create control pipe error %u\n", GetLastError());
476 CloseServiceHandle( disp->manager );
477 HeapFree( GetProcessHeap(), 0, disp );
478 SetLastError( ERROR_FAILED_SERVICE_CONTROLLER_CONNECT );
479 return FALSE;
482 service_event = CreateEventW( NULL, FALSE, FALSE, NULL );
483 stop_event = CreateEventW( NULL, FALSE, FALSE, NULL );
485 /* FIXME: service_control_dispatcher should be merged into the main thread */
486 wait_handles[0] = __wine_make_process_system();
487 wait_handles[1] = CreateThread( NULL, 0, service_control_dispatcher, disp, 0, NULL );
488 wait_handles[2] = service_event;
489 wait_handles[3] = stop_event;
491 TRACE("Starting %d services running as process %d\n",
492 nb_services, GetCurrentProcessId());
494 /* wait for all the threads to pack up and exit */
495 for (;;)
497 EnterCriticalSection( &service_cs );
498 for (i = 0, n = 4; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
500 if (!services[i]->thread) continue;
501 wait_services[n] = i;
502 wait_handles[n++] = services[i]->thread;
504 LeaveCriticalSection( &service_cs );
506 ret = WaitForMultipleObjects( n, wait_handles, FALSE, INFINITE );
507 if (!ret) /* system process event */
509 SERVICE_STATUS st;
510 SERVICE_PRESHUTDOWN_INFO spi;
511 DWORD timeout = 5000;
512 BOOL res;
514 EnterCriticalSection( &service_cs );
515 n = 0;
516 for (i = 0; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
518 if (!services[i]->thread) continue;
520 res = QueryServiceStatus(services[i]->full_access_handle, &st);
521 ret = ERROR_SUCCESS;
522 if (res && (st.dwControlsAccepted & SERVICE_ACCEPT_PRESHUTDOWN))
524 res = QueryServiceConfig2W( services[i]->full_access_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
525 (LPBYTE)&spi, sizeof(spi), &i );
526 if (res)
528 FIXME("service should be able to delay shutdown\n");
529 timeout += spi.dwPreshutdownTimeout;
530 ret = service_handle_control( services[i], SERVICE_CONTROL_PRESHUTDOWN );
531 wait_handles[n++] = services[i]->thread;
534 else if (res && (st.dwControlsAccepted & SERVICE_ACCEPT_SHUTDOWN))
536 ret = service_handle_control( services[i], SERVICE_CONTROL_SHUTDOWN );
537 wait_handles[n++] = services[i]->thread;
540 LeaveCriticalSection( &service_cs );
542 TRACE("last user process exited, shutting down (timeout: %d)\n", timeout);
543 WaitForMultipleObjects( n, wait_handles, TRUE, timeout );
544 ExitProcess(0);
546 else if (ret == 1)
548 TRACE( "control dispatcher exited, shutting down\n" );
549 /* FIXME: we should maybe send a shutdown control to running services */
550 ExitProcess(0);
552 else if (ret == 2)
554 continue; /* rebuild the list */
556 else if (ret == 3)
558 return TRUE;
560 else if (ret < n)
562 services[wait_services[ret]]->thread = 0;
563 CloseHandle( wait_handles[ret] );
565 else return FALSE;
569 /******************************************************************************
570 * StartServiceCtrlDispatcherA [ADVAPI32.@]
572 * See StartServiceCtrlDispatcherW.
574 BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
576 service_data *info;
577 unsigned int i;
579 TRACE("%p\n", servent);
581 if (nb_services)
583 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
584 return FALSE;
586 while (servent[nb_services].lpServiceName) nb_services++;
587 if (!nb_services)
589 SetLastError( ERROR_INVALID_PARAMETER );
590 return FALSE;
593 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
595 for (i = 0; i < nb_services; i++)
597 DWORD len = MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, NULL, 0);
598 DWORD sz = FIELD_OFFSET( service_data, name[len] );
599 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
600 MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, info->name, len);
601 info->proc.a = servent[i].lpServiceProc;
602 info->unicode = FALSE;
603 services[i] = info;
606 return service_run_main_thread();
609 /******************************************************************************
610 * StartServiceCtrlDispatcherW [ADVAPI32.@]
612 * Connects a process containing one or more services to the service control
613 * manager.
615 * PARAMS
616 * servent [I] A list of the service names and service procedures
618 * RETURNS
619 * Success: TRUE.
620 * Failure: FALSE.
622 BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
624 service_data *info;
625 unsigned int i;
627 TRACE("%p\n", servent);
629 if (nb_services)
631 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
632 return FALSE;
634 while (servent[nb_services].lpServiceName) nb_services++;
635 if (!nb_services)
637 SetLastError( ERROR_INVALID_PARAMETER );
638 return FALSE;
641 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
643 for (i = 0; i < nb_services; i++)
645 DWORD len = strlenW(servent[i].lpServiceName) + 1;
646 DWORD sz = FIELD_OFFSET( service_data, name[len] );
647 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
648 strcpyW(info->name, servent[i].lpServiceName);
649 info->proc.w = servent[i].lpServiceProc;
650 info->unicode = TRUE;
651 services[i] = info;
654 return service_run_main_thread();
657 /******************************************************************************
658 * LockServiceDatabase [ADVAPI32.@]
660 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
662 SC_RPC_LOCK hLock = NULL;
663 DWORD err;
665 TRACE("%p\n",hSCManager);
667 __TRY
669 err = svcctl_LockServiceDatabase(hSCManager, &hLock);
671 __EXCEPT(rpc_filter)
673 err = map_exception_code(GetExceptionCode());
675 __ENDTRY
676 if (err != ERROR_SUCCESS)
678 SetLastError(err);
679 return NULL;
681 return hLock;
684 /******************************************************************************
685 * UnlockServiceDatabase [ADVAPI32.@]
687 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
689 DWORD err;
690 SC_RPC_LOCK hRpcLock = ScLock;
692 TRACE("%p\n",ScLock);
694 __TRY
696 err = svcctl_UnlockServiceDatabase(&hRpcLock);
698 __EXCEPT(rpc_filter)
700 err = map_exception_code(GetExceptionCode());
702 __ENDTRY
703 if (err != ERROR_SUCCESS)
705 SetLastError(err);
706 return FALSE;
708 return TRUE;
711 /******************************************************************************
712 * SetServiceStatus [ADVAPI32.@]
714 * PARAMS
715 * hService []
716 * lpStatus []
718 BOOL WINAPI
719 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
721 DWORD err;
723 TRACE("%p %x %x %x %x %x %x %x\n", hService,
724 lpStatus->dwServiceType, lpStatus->dwCurrentState,
725 lpStatus->dwControlsAccepted, lpStatus->dwWin32ExitCode,
726 lpStatus->dwServiceSpecificExitCode, lpStatus->dwCheckPoint,
727 lpStatus->dwWaitHint);
729 __TRY
731 err = svcctl_SetServiceStatus( hService, lpStatus );
733 __EXCEPT(rpc_filter)
735 err = map_exception_code(GetExceptionCode());
737 __ENDTRY
738 if (err != ERROR_SUCCESS)
740 SetLastError(err);
741 return FALSE;
744 if (lpStatus->dwCurrentState == SERVICE_STOPPED) {
745 SetEvent(stop_event);
746 CloseServiceHandle((SC_HANDLE)hService);
749 return TRUE;
753 /******************************************************************************
754 * OpenSCManagerA [ADVAPI32.@]
756 * Establish a connection to the service control manager and open its database.
758 * PARAMS
759 * lpMachineName [I] Pointer to machine name string
760 * lpDatabaseName [I] Pointer to database name string
761 * dwDesiredAccess [I] Type of access
763 * RETURNS
764 * Success: A Handle to the service control manager database
765 * Failure: NULL
767 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
768 DWORD dwDesiredAccess )
770 LPWSTR lpMachineNameW, lpDatabaseNameW;
771 SC_HANDLE ret;
773 lpMachineNameW = SERV_dup(lpMachineName);
774 lpDatabaseNameW = SERV_dup(lpDatabaseName);
775 ret = OpenSCManagerW(lpMachineNameW, lpDatabaseNameW, dwDesiredAccess);
776 HeapFree(GetProcessHeap(), 0, lpDatabaseNameW);
777 HeapFree(GetProcessHeap(), 0, lpMachineNameW);
778 return ret;
781 /******************************************************************************
782 * OpenSCManagerW [ADVAPI32.@]
784 * See OpenSCManagerA.
786 DWORD SERV_OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
787 DWORD dwDesiredAccess, SC_HANDLE *handle )
789 DWORD r;
791 TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
792 debugstr_w(lpDatabaseName), dwDesiredAccess);
794 __TRY
796 r = svcctl_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, (SC_RPC_HANDLE *)handle);
798 __EXCEPT(rpc_filter)
800 r = map_exception_code(GetExceptionCode());
802 __ENDTRY
804 if (r!=ERROR_SUCCESS)
805 *handle = 0;
807 TRACE("returning %p\n", *handle);
808 return r;
811 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
812 DWORD dwDesiredAccess )
814 SC_HANDLE handle = 0;
815 DWORD r;
817 r = SERV_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, &handle);
818 if (r!=ERROR_SUCCESS)
819 SetLastError(r);
820 return handle;
823 /******************************************************************************
824 * ControlService [ADVAPI32.@]
826 * Send a control code to a service.
828 * PARAMS
829 * hService [I] Handle of the service control manager database
830 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
831 * lpServiceStatus [O] Destination for the status of the service, if available
833 * RETURNS
834 * Success: TRUE.
835 * Failure: FALSE.
837 * BUGS
838 * Unlike M$' implementation, control requests are not serialized and may be
839 * processed asynchronously.
841 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
842 LPSERVICE_STATUS lpServiceStatus )
844 DWORD err;
846 TRACE("%p %d %p\n", hService, dwControl, lpServiceStatus);
848 __TRY
850 err = svcctl_ControlService(hService, dwControl, lpServiceStatus);
852 __EXCEPT(rpc_filter)
854 err = map_exception_code(GetExceptionCode());
856 __ENDTRY
857 if (err != ERROR_SUCCESS)
859 SetLastError(err);
860 return FALSE;
863 return TRUE;
866 /******************************************************************************
867 * CloseServiceHandle [ADVAPI32.@]
869 * Close a handle to a service or the service control manager database.
871 * PARAMS
872 * hSCObject [I] Handle to service or service control manager database
874 * RETURNS
875 * Success: TRUE
876 * Failure: FALSE
878 BOOL WINAPI
879 CloseServiceHandle( SC_HANDLE hSCObject )
881 DWORD err;
883 TRACE("%p\n", hSCObject);
885 __TRY
887 err = svcctl_CloseServiceHandle((SC_RPC_HANDLE *)&hSCObject);
889 __EXCEPT(rpc_filter)
891 err = map_exception_code(GetExceptionCode());
893 __ENDTRY
895 if (err != ERROR_SUCCESS)
897 SetLastError(err);
898 return FALSE;
900 return TRUE;
904 /******************************************************************************
905 * OpenServiceA [ADVAPI32.@]
907 * Open a handle to a service.
909 * PARAMS
910 * hSCManager [I] Handle of the service control manager database
911 * lpServiceName [I] Name of the service to open
912 * dwDesiredAccess [I] Access required to the service
914 * RETURNS
915 * Success: Handle to the service
916 * Failure: NULL
918 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
919 DWORD dwDesiredAccess )
921 LPWSTR lpServiceNameW;
922 SC_HANDLE ret;
924 TRACE("%p %s %d\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
926 lpServiceNameW = SERV_dup(lpServiceName);
927 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
928 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
929 return ret;
933 /******************************************************************************
934 * OpenServiceW [ADVAPI32.@]
936 * See OpenServiceA.
938 DWORD SERV_OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
939 DWORD dwDesiredAccess, SC_HANDLE *handle )
941 DWORD err;
943 TRACE("%p %s %d\n", hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
945 if (!hSCManager)
946 return ERROR_INVALID_HANDLE;
948 __TRY
950 err = svcctl_OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess, (SC_RPC_HANDLE *)handle);
952 __EXCEPT(rpc_filter)
954 err = map_exception_code(GetExceptionCode());
956 __ENDTRY
958 if (err != ERROR_SUCCESS)
959 *handle = 0;
961 TRACE("returning %p\n", *handle);
962 return err;
965 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
966 DWORD dwDesiredAccess)
968 SC_HANDLE handle = 0;
969 DWORD err;
971 err = SERV_OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess, &handle);
972 if (err != ERROR_SUCCESS)
973 SetLastError(err);
974 return handle;
977 /******************************************************************************
978 * CreateServiceW [ADVAPI32.@]
980 SC_HANDLE WINAPI
981 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
982 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
983 DWORD dwServiceType, DWORD dwStartType,
984 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
985 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
986 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
987 LPCWSTR lpPassword )
989 SC_HANDLE handle = 0;
990 DWORD err;
991 SIZE_T passwdlen;
993 TRACE("%p %s %s\n", hSCManager,
994 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
996 if (!hSCManager)
998 SetLastError( ERROR_INVALID_HANDLE );
999 return 0;
1002 if (lpPassword)
1003 passwdlen = (strlenW(lpPassword) + 1) * sizeof(WCHAR);
1004 else
1005 passwdlen = 0;
1007 __TRY
1009 err = svcctl_CreateServiceW(hSCManager, lpServiceName,
1010 lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1011 lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, (const BYTE*)lpDependencies,
1012 multisz_cb(lpDependencies), lpServiceStartName, (const BYTE*)lpPassword, passwdlen,
1013 (SC_RPC_HANDLE *)&handle);
1015 __EXCEPT(rpc_filter)
1017 err = map_exception_code(GetExceptionCode());
1019 __ENDTRY
1021 if (err != ERROR_SUCCESS)
1023 SetLastError(err);
1024 handle = 0;
1026 return handle;
1030 /******************************************************************************
1031 * CreateServiceA [ADVAPI32.@]
1033 SC_HANDLE WINAPI
1034 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1035 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
1036 DWORD dwServiceType, DWORD dwStartType,
1037 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1038 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1039 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
1040 LPCSTR lpPassword )
1042 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
1043 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
1044 SC_HANDLE r;
1046 TRACE("%p %s %s\n", hSCManager,
1047 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
1049 lpServiceNameW = SERV_dup( lpServiceName );
1050 lpDisplayNameW = SERV_dup( lpDisplayName );
1051 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
1052 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
1053 lpDependenciesW = SERV_dupmulti( lpDependencies );
1054 lpServiceStartNameW = SERV_dup( lpServiceStartName );
1055 lpPasswordW = SERV_dup( lpPassword );
1057 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
1058 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1059 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
1060 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
1062 HeapFree( GetProcessHeap(), 0, lpServiceNameW );
1063 HeapFree( GetProcessHeap(), 0, lpDisplayNameW );
1064 HeapFree( GetProcessHeap(), 0, lpBinaryPathNameW );
1065 HeapFree( GetProcessHeap(), 0, lpLoadOrderGroupW );
1066 HeapFree( GetProcessHeap(), 0, lpDependenciesW );
1067 HeapFree( GetProcessHeap(), 0, lpServiceStartNameW );
1068 HeapFree( GetProcessHeap(), 0, lpPasswordW );
1070 return r;
1074 /******************************************************************************
1075 * DeleteService [ADVAPI32.@]
1077 * Delete a service from the service control manager database.
1079 * PARAMS
1080 * hService [I] Handle of the service to delete
1082 * RETURNS
1083 * Success: TRUE
1084 * Failure: FALSE
1086 BOOL WINAPI DeleteService( SC_HANDLE hService )
1088 DWORD err;
1090 TRACE("%p\n", hService);
1092 __TRY
1094 err = svcctl_DeleteService(hService);
1096 __EXCEPT(rpc_filter)
1098 err = map_exception_code(GetExceptionCode());
1100 __ENDTRY
1101 if (err != 0)
1103 SetLastError(err);
1104 return FALSE;
1107 return TRUE;
1111 /******************************************************************************
1112 * StartServiceA [ADVAPI32.@]
1114 * Start a service
1116 * PARAMS
1117 * hService [I] Handle of service
1118 * dwNumServiceArgs [I] Number of arguments
1119 * lpServiceArgVectors [I] Address of array of argument strings
1121 * NOTES
1122 * - NT implements this function using an obscure RPC call.
1123 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1124 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
1125 * - This will only work for shared address space. How should the service
1126 * args be transferred when address spaces are separated?
1127 * - Can only start one service at a time.
1128 * - Has no concept of privilege.
1130 * RETURNS
1131 * Success: TRUE.
1132 * Failure: FALSE
1134 BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
1135 LPCSTR *lpServiceArgVectors )
1137 LPWSTR *lpwstr=NULL;
1138 unsigned int i;
1139 BOOL r;
1141 TRACE("(%p,%d,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
1143 if (dwNumServiceArgs)
1144 lpwstr = HeapAlloc( GetProcessHeap(), 0,
1145 dwNumServiceArgs*sizeof(LPWSTR) );
1147 for(i=0; i<dwNumServiceArgs; i++)
1148 lpwstr[i]=SERV_dup(lpServiceArgVectors[i]);
1150 r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
1152 if (dwNumServiceArgs)
1154 for(i=0; i<dwNumServiceArgs; i++)
1155 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
1156 HeapFree(GetProcessHeap(), 0, lpwstr);
1159 return r;
1163 /******************************************************************************
1164 * StartServiceW [ADVAPI32.@]
1166 * See StartServiceA.
1168 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1169 LPCWSTR *lpServiceArgVectors)
1171 DWORD err;
1173 TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1175 __TRY
1177 err = svcctl_StartServiceW(hService, dwNumServiceArgs, lpServiceArgVectors);
1179 __EXCEPT(rpc_filter)
1181 err = map_exception_code(GetExceptionCode());
1183 __ENDTRY
1184 if (err != ERROR_SUCCESS)
1186 SetLastError(err);
1187 return FALSE;
1190 return TRUE;
1193 /******************************************************************************
1194 * QueryServiceStatus [ADVAPI32.@]
1196 * PARAMS
1197 * hService [I] Handle to service to get information about
1198 * lpservicestatus [O] buffer to receive the status information for the service
1201 BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
1202 LPSERVICE_STATUS lpservicestatus)
1204 SERVICE_STATUS_PROCESS SvcStatusData;
1205 BOOL ret;
1206 DWORD dummy;
1208 TRACE("%p %p\n", hService, lpservicestatus);
1210 if (!hService)
1212 SetLastError(ERROR_INVALID_HANDLE);
1213 return FALSE;
1215 if (!lpservicestatus)
1217 SetLastError(ERROR_INVALID_ADDRESS);
1218 return FALSE;
1221 ret = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&SvcStatusData,
1222 sizeof(SERVICE_STATUS_PROCESS), &dummy);
1223 if (ret) memcpy(lpservicestatus, &SvcStatusData, sizeof(SERVICE_STATUS)) ;
1224 return ret;
1228 /******************************************************************************
1229 * QueryServiceStatusEx [ADVAPI32.@]
1231 * Get information about a service.
1233 * PARAMS
1234 * hService [I] Handle to service to get information about
1235 * InfoLevel [I] Level of information to get
1236 * lpBuffer [O] Destination for requested information
1237 * cbBufSize [I] Size of lpBuffer in bytes
1238 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1240 * RETURNS
1241 * Success: TRUE
1242 * FAILURE: FALSE
1244 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1245 LPBYTE lpBuffer, DWORD cbBufSize,
1246 LPDWORD pcbBytesNeeded)
1248 DWORD err;
1250 TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1252 if (InfoLevel != SC_STATUS_PROCESS_INFO)
1254 err = ERROR_INVALID_LEVEL;
1256 else if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
1258 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
1259 err = ERROR_INSUFFICIENT_BUFFER;
1261 else
1263 __TRY
1265 err = svcctl_QueryServiceStatusEx(hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1267 __EXCEPT(rpc_filter)
1269 err = map_exception_code(GetExceptionCode());
1271 __ENDTRY
1273 if (err != ERROR_SUCCESS)
1275 SetLastError(err);
1276 return FALSE;
1278 return TRUE;
1281 /******************************************************************************
1282 * QueryServiceConfigA [ADVAPI32.@]
1284 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1285 DWORD size, LPDWORD needed )
1287 DWORD n;
1288 LPSTR p, buffer;
1289 BOOL ret;
1290 QUERY_SERVICE_CONFIGW *configW;
1292 TRACE("%p %p %d %p\n", hService, config, size, needed);
1294 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, 2 * size )))
1296 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1297 return FALSE;
1299 configW = (QUERY_SERVICE_CONFIGW *)buffer;
1300 ret = QueryServiceConfigW( hService, configW, 2 * size, needed );
1301 if (!ret) goto done;
1303 config->dwServiceType = configW->dwServiceType;
1304 config->dwStartType = configW->dwStartType;
1305 config->dwErrorControl = configW->dwErrorControl;
1306 config->lpBinaryPathName = NULL;
1307 config->lpLoadOrderGroup = NULL;
1308 config->dwTagId = configW->dwTagId;
1309 config->lpDependencies = NULL;
1310 config->lpServiceStartName = NULL;
1311 config->lpDisplayName = NULL;
1313 p = (LPSTR)(config + 1);
1314 n = size - sizeof(*config);
1315 ret = FALSE;
1317 #define MAP_STR(str) \
1318 do { \
1319 if (configW->str) \
1321 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1322 if (!sz) goto done; \
1323 config->str = p; \
1324 p += sz; \
1325 n -= sz; \
1327 } while (0)
1329 MAP_STR( lpBinaryPathName );
1330 MAP_STR( lpLoadOrderGroup );
1331 MAP_STR( lpDependencies );
1332 MAP_STR( lpServiceStartName );
1333 MAP_STR( lpDisplayName );
1334 #undef MAP_STR
1336 *needed = p - (LPSTR)config;
1337 ret = TRUE;
1339 done:
1340 HeapFree( GetProcessHeap(), 0, buffer );
1341 return ret;
1344 static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
1346 DWORD cb;
1348 if (!*string_ptr)
1350 cb = sizeof(WCHAR);
1351 memset(*buf, 0, cb);
1353 else
1355 cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
1356 memcpy(*buf, *string_ptr, cb);
1357 MIDL_user_free(*string_ptr);
1360 *string_ptr = (LPWSTR)*buf;
1361 *buf += cb;
1363 return cb;
1366 static DWORD size_string(LPCWSTR string)
1368 return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
1371 /******************************************************************************
1372 * QueryServiceConfigW [ADVAPI32.@]
1374 BOOL WINAPI
1375 QueryServiceConfigW( SC_HANDLE hService,
1376 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1377 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1379 QUERY_SERVICE_CONFIGW config;
1380 DWORD total;
1381 DWORD err;
1382 BYTE *bufpos;
1384 TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1385 cbBufSize, pcbBytesNeeded);
1387 memset(&config, 0, sizeof(config));
1389 __TRY
1391 err = svcctl_QueryServiceConfigW(hService, &config);
1393 __EXCEPT(rpc_filter)
1395 err = map_exception_code(GetExceptionCode());
1397 __ENDTRY
1399 if (err != ERROR_SUCCESS)
1401 TRACE("services.exe: error %u\n", err);
1402 SetLastError(err);
1403 return FALSE;
1406 /* calculate the size required first */
1407 total = sizeof (QUERY_SERVICE_CONFIGW);
1408 total += size_string(config.lpBinaryPathName);
1409 total += size_string(config.lpLoadOrderGroup);
1410 total += size_string(config.lpDependencies);
1411 total += size_string(config.lpServiceStartName);
1412 total += size_string(config.lpDisplayName);
1414 *pcbBytesNeeded = total;
1416 /* if there's not enough memory, return an error */
1417 if( total > cbBufSize )
1419 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1420 MIDL_user_free(config.lpBinaryPathName);
1421 MIDL_user_free(config.lpLoadOrderGroup);
1422 MIDL_user_free(config.lpDependencies);
1423 MIDL_user_free(config.lpServiceStartName);
1424 MIDL_user_free(config.lpDisplayName);
1425 return FALSE;
1428 *lpServiceConfig = config;
1429 bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
1430 move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
1431 move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
1432 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
1433 move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
1434 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
1436 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1437 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1438 TRACE("Dependencies = %s\n", debugstr_w(lpServiceConfig->lpDependencies) );
1439 TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig->lpServiceStartName) );
1440 TRACE("Display name = %s\n", debugstr_w(lpServiceConfig->lpDisplayName) );
1442 return TRUE;
1445 /******************************************************************************
1446 * QueryServiceConfig2A [ADVAPI32.@]
1448 * Note
1449 * observed under win2k:
1450 * The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
1451 * required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
1453 BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1454 DWORD size, LPDWORD needed)
1456 BOOL ret;
1457 LPBYTE bufferW = NULL;
1459 if(buffer && size)
1460 bufferW = HeapAlloc( GetProcessHeap(), 0, size);
1462 ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
1463 if(!ret) goto cleanup;
1465 switch(dwLevel) {
1466 case SERVICE_CONFIG_DESCRIPTION:
1467 if (buffer && bufferW) {
1468 LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
1469 LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
1470 if (configW->lpDescription && (size > sizeof(SERVICE_DESCRIPTIONA))) {
1471 DWORD sz;
1472 configA->lpDescription = (LPSTR)(configA + 1);
1473 sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
1474 configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
1475 if (!sz) {
1476 FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1477 ret = FALSE;
1478 configA->lpDescription = NULL;
1481 else configA->lpDescription = NULL;
1483 break;
1484 case SERVICE_CONFIG_PRESHUTDOWN_INFO:
1485 if (buffer && bufferW && *needed<=size)
1486 memcpy(buffer, bufferW, *needed);
1487 break;
1488 default:
1489 FIXME("conversation W->A not implemented for level %d\n", dwLevel);
1490 ret = FALSE;
1491 break;
1494 cleanup:
1495 HeapFree( GetProcessHeap(), 0, bufferW);
1496 return ret;
1499 /******************************************************************************
1500 * QueryServiceConfig2W [ADVAPI32.@]
1502 * See QueryServiceConfig2A.
1504 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1505 DWORD size, LPDWORD needed)
1507 DWORD err;
1509 if(dwLevel!=SERVICE_CONFIG_DESCRIPTION && dwLevel!=SERVICE_CONFIG_PRESHUTDOWN_INFO) {
1510 FIXME("Level %d not implemented\n", dwLevel);
1511 SetLastError(ERROR_INVALID_LEVEL);
1512 return FALSE;
1515 if(!buffer && size) {
1516 SetLastError(ERROR_INVALID_ADDRESS);
1517 return FALSE;
1520 TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
1522 __TRY
1524 err = svcctl_QueryServiceConfig2W(hService, dwLevel, buffer, size, needed);
1526 __EXCEPT(rpc_filter)
1528 err = map_exception_code(GetExceptionCode());
1530 __ENDTRY
1532 if (err != ERROR_SUCCESS)
1534 SetLastError( err );
1535 return FALSE;
1538 switch (dwLevel)
1540 case SERVICE_CONFIG_DESCRIPTION:
1541 if (buffer)
1543 SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
1544 if (descr->lpDescription) /* make it an absolute pointer */
1545 descr->lpDescription = (WCHAR *)(buffer + (ULONG_PTR)descr->lpDescription);
1546 break;
1550 return TRUE;
1553 /******************************************************************************
1554 * EnumServicesStatusA [ADVAPI32.@]
1556 BOOL WINAPI
1557 EnumServicesStatusA( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSA
1558 services, DWORD size, LPDWORD needed, LPDWORD returned,
1559 LPDWORD resume_handle )
1561 BOOL ret;
1562 unsigned int i;
1563 ENUM_SERVICE_STATUSW *servicesW = NULL;
1564 DWORD sz, n;
1565 char *p;
1567 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
1568 returned, resume_handle);
1570 sz = max( 2 * size, sizeof(*servicesW) );
1571 if (!(servicesW = HeapAlloc( GetProcessHeap(), 0, sz )))
1573 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1574 return FALSE;
1577 ret = EnumServicesStatusW( hmngr, type, state, servicesW, sz, needed, returned, resume_handle );
1578 if (!ret) goto done;
1580 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUSA);
1581 n = size - (p - (char *)services);
1582 ret = FALSE;
1583 for (i = 0; i < *returned; i++)
1585 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
1586 if (!sz) goto done;
1587 services[i].lpServiceName = p;
1588 p += sz;
1589 n -= sz;
1590 if (servicesW[i].lpDisplayName)
1592 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
1593 if (!sz) goto done;
1594 services[i].lpDisplayName = p;
1595 p += sz;
1596 n -= sz;
1598 else services[i].lpDisplayName = NULL;
1599 services[i].ServiceStatus = servicesW[i].ServiceStatus;
1602 ret = TRUE;
1604 done:
1605 HeapFree( GetProcessHeap(), 0, servicesW );
1606 return ret;
1609 /******************************************************************************
1610 * EnumServicesStatusW [ADVAPI32.@]
1612 BOOL WINAPI
1613 EnumServicesStatusW( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSW
1614 services, DWORD size, LPDWORD needed, LPDWORD returned,
1615 LPDWORD resume_handle )
1617 DWORD err, i;
1618 ENUM_SERVICE_STATUSW dummy_status;
1620 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
1621 returned, resume_handle);
1623 if (resume_handle)
1624 FIXME("resume handle not supported\n");
1626 if (!hmngr)
1628 SetLastError( ERROR_INVALID_HANDLE );
1629 return FALSE;
1632 /* make sure we pass a valid pointer */
1633 if (!services || size < sizeof(*services))
1635 services = &dummy_status;
1636 size = sizeof(dummy_status);
1639 __TRY
1641 err = svcctl_EnumServicesStatusW( hmngr, type, state, (BYTE *)services, size, needed, returned );
1643 __EXCEPT(rpc_filter)
1645 err = map_exception_code( GetExceptionCode() );
1647 __ENDTRY
1649 if (err != ERROR_SUCCESS)
1651 SetLastError( err );
1652 return FALSE;
1655 for (i = 0; i < *returned; i++)
1657 /* convert buffer offsets into pointers */
1658 services[i].lpServiceName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpServiceName);
1659 if (services[i].lpDisplayName)
1660 services[i].lpDisplayName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpDisplayName);
1663 return TRUE;
1666 /******************************************************************************
1667 * EnumServicesStatusExA [ADVAPI32.@]
1669 BOOL WINAPI
1670 EnumServicesStatusExA( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state,
1671 LPBYTE buffer, DWORD size, LPDWORD needed, LPDWORD returned,
1672 LPDWORD resume_handle, LPCSTR group )
1674 BOOL ret;
1675 unsigned int i;
1676 ENUM_SERVICE_STATUS_PROCESSA *services = (ENUM_SERVICE_STATUS_PROCESSA *)buffer;
1677 ENUM_SERVICE_STATUS_PROCESSW *servicesW = NULL;
1678 WCHAR *groupW = NULL;
1679 DWORD sz, n;
1680 char *p;
1682 TRACE("%p %u 0x%x 0x%x %p %u %p %p %p %s\n", hmngr, level, type, state, buffer,
1683 size, needed, returned, resume_handle, debugstr_a(group));
1685 sz = max( 2 * size, sizeof(*servicesW) );
1686 if (!(servicesW = HeapAlloc( GetProcessHeap(), 0, sz )))
1688 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1689 return FALSE;
1691 if (group)
1693 int len = MultiByteToWideChar( CP_ACP, 0, group, -1, NULL, 0 );
1694 if (!(groupW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1696 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1697 HeapFree( GetProcessHeap(), 0, servicesW );
1698 return FALSE;
1700 MultiByteToWideChar( CP_ACP, 0, group, -1, groupW, len * sizeof(WCHAR) );
1703 ret = EnumServicesStatusExW( hmngr, level, type, state, (BYTE *)servicesW, sz,
1704 needed, returned, resume_handle, groupW );
1705 if (!ret) goto done;
1707 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUS_PROCESSA);
1708 n = size - (p - (char *)services);
1709 ret = FALSE;
1710 for (i = 0; i < *returned; i++)
1712 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
1713 if (!sz) goto done;
1714 services[i].lpServiceName = p;
1715 p += sz;
1716 n -= sz;
1717 if (servicesW[i].lpDisplayName)
1719 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
1720 if (!sz) goto done;
1721 services[i].lpDisplayName = p;
1722 p += sz;
1723 n -= sz;
1725 else services[i].lpDisplayName = NULL;
1726 services[i].ServiceStatusProcess = servicesW[i].ServiceStatusProcess;
1729 ret = TRUE;
1731 done:
1732 HeapFree( GetProcessHeap(), 0, servicesW );
1733 HeapFree( GetProcessHeap(), 0, groupW );
1734 return ret;
1737 /******************************************************************************
1738 * EnumServicesStatusExW [ADVAPI32.@]
1740 BOOL WINAPI
1741 EnumServicesStatusExW( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state,
1742 LPBYTE buffer, DWORD size, LPDWORD needed, LPDWORD returned,
1743 LPDWORD resume_handle, LPCWSTR group )
1745 DWORD err, i;
1746 ENUM_SERVICE_STATUS_PROCESSW dummy_status;
1747 ENUM_SERVICE_STATUS_PROCESSW *services = (ENUM_SERVICE_STATUS_PROCESSW *)buffer;
1749 TRACE("%p %u 0x%x 0x%x %p %u %p %p %p %s\n", hmngr, level, type, state, buffer,
1750 size, needed, returned, resume_handle, debugstr_w(group));
1752 if (resume_handle)
1753 FIXME("resume handle not supported\n");
1755 if (level != SC_ENUM_PROCESS_INFO)
1757 SetLastError( ERROR_INVALID_LEVEL );
1758 return FALSE;
1760 if (!hmngr)
1762 SetLastError( ERROR_INVALID_HANDLE );
1763 return FALSE;
1766 /* make sure we pass a valid buffer pointer */
1767 if (!services || size < sizeof(*services))
1769 buffer = (BYTE *)&dummy_status;
1770 size = sizeof(dummy_status);
1773 __TRY
1775 err = svcctl_EnumServicesStatusExW( hmngr, type, state, buffer, size, needed,
1776 returned, group );
1778 __EXCEPT(rpc_filter)
1780 err = map_exception_code( GetExceptionCode() );
1782 __ENDTRY
1784 if (err != ERROR_SUCCESS)
1786 SetLastError( err );
1787 return FALSE;
1790 for (i = 0; i < *returned; i++)
1792 /* convert buffer offsets into pointers */
1793 services[i].lpServiceName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpServiceName);
1794 if (services[i].lpDisplayName)
1795 services[i].lpDisplayName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpDisplayName);
1798 return TRUE;
1801 /******************************************************************************
1802 * GetServiceKeyNameA [ADVAPI32.@]
1804 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1805 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1807 LPWSTR lpDisplayNameW, lpServiceNameW;
1808 DWORD sizeW;
1809 BOOL ret = FALSE;
1811 TRACE("%p %s %p %p\n", hSCManager,
1812 debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1814 lpDisplayNameW = SERV_dup(lpDisplayName);
1815 if (lpServiceName)
1816 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1817 else
1818 lpServiceNameW = NULL;
1820 sizeW = *lpcchBuffer;
1821 if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
1823 if (lpServiceName && *lpcchBuffer)
1824 lpServiceName[0] = 0;
1825 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1826 goto cleanup;
1829 if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
1830 *lpcchBuffer, NULL, NULL ))
1832 if (*lpcchBuffer && lpServiceName)
1833 lpServiceName[0] = 0;
1834 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
1835 goto cleanup;
1838 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1839 ret = TRUE;
1841 cleanup:
1842 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1843 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1844 return ret;
1847 /******************************************************************************
1848 * GetServiceKeyNameW [ADVAPI32.@]
1850 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1851 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1853 DWORD err;
1854 WCHAR buffer[2];
1855 DWORD size;
1857 TRACE("%p %s %p %p\n", hSCManager,
1858 debugstr_w(lpDisplayName), lpServiceName, lpcchBuffer);
1860 if (!hSCManager)
1862 SetLastError( ERROR_INVALID_HANDLE );
1863 return FALSE;
1866 /* provide a buffer if the caller didn't */
1867 if (!lpServiceName || *lpcchBuffer < 2)
1869 lpServiceName = buffer;
1870 /* A size of 1 would be enough, but tests show that Windows returns 2,
1871 * probably because of a WCHAR/bytes mismatch in their code.
1873 *lpcchBuffer = 2;
1876 /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
1877 * includes the nul-terminator on input. */
1878 size = *lpcchBuffer - 1;
1880 __TRY
1882 err = svcctl_GetServiceKeyNameW(hSCManager, lpDisplayName, lpServiceName,
1883 &size);
1885 __EXCEPT(rpc_filter)
1887 err = map_exception_code(GetExceptionCode());
1889 __ENDTRY
1891 /* The value of *lpcchBuffer excludes nul-terminator on output. */
1892 if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
1893 *lpcchBuffer = size;
1895 if (err)
1896 SetLastError(err);
1897 return err == ERROR_SUCCESS;
1900 /******************************************************************************
1901 * QueryServiceLockStatusA [ADVAPI32.@]
1903 BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
1904 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1905 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1907 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1909 return FALSE;
1912 /******************************************************************************
1913 * QueryServiceLockStatusW [ADVAPI32.@]
1915 BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
1916 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1917 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1919 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1921 return FALSE;
1924 /******************************************************************************
1925 * GetServiceDisplayNameA [ADVAPI32.@]
1927 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1928 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1930 LPWSTR lpServiceNameW, lpDisplayNameW;
1931 DWORD sizeW;
1932 BOOL ret = FALSE;
1934 TRACE("%p %s %p %p\n", hSCManager,
1935 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1937 lpServiceNameW = SERV_dup(lpServiceName);
1938 if (lpDisplayName)
1939 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1940 else
1941 lpDisplayNameW = NULL;
1943 sizeW = *lpcchBuffer;
1944 if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
1946 if (lpDisplayName && *lpcchBuffer)
1947 lpDisplayName[0] = 0;
1948 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1949 goto cleanup;
1952 if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
1953 *lpcchBuffer, NULL, NULL ))
1955 if (*lpcchBuffer && lpDisplayName)
1956 lpDisplayName[0] = 0;
1957 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
1958 goto cleanup;
1961 /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
1962 * (but if the function succeeded it means that is a good upper estimation of the size) */
1963 ret = TRUE;
1965 cleanup:
1966 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1967 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1968 return ret;
1971 /******************************************************************************
1972 * GetServiceDisplayNameW [ADVAPI32.@]
1974 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1975 LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1977 DWORD err;
1978 DWORD size;
1979 WCHAR buffer[2];
1981 TRACE("%p %s %p %p\n", hSCManager,
1982 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1984 if (!hSCManager)
1986 SetLastError( ERROR_INVALID_HANDLE );
1987 return FALSE;
1990 /* provide a buffer if the caller didn't */
1991 if (!lpDisplayName || *lpcchBuffer < 2)
1993 lpDisplayName = buffer;
1994 /* A size of 1 would be enough, but tests show that Windows returns 2,
1995 * probably because of a WCHAR/bytes mismatch in their code.
1997 *lpcchBuffer = 2;
2000 /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
2001 * includes the nul-terminator on input. */
2002 size = *lpcchBuffer - 1;
2004 __TRY
2006 err = svcctl_GetServiceDisplayNameW(hSCManager, lpServiceName, lpDisplayName,
2007 &size);
2009 __EXCEPT(rpc_filter)
2011 err = map_exception_code(GetExceptionCode());
2013 __ENDTRY
2015 /* The value of *lpcchBuffer excludes nul-terminator on output. */
2016 if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
2017 *lpcchBuffer = size;
2019 if (err)
2020 SetLastError(err);
2021 return err == ERROR_SUCCESS;
2024 /******************************************************************************
2025 * ChangeServiceConfigW [ADVAPI32.@]
2027 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
2028 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
2029 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
2030 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
2032 DWORD cb_pwd;
2033 DWORD err;
2035 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2036 hService, dwServiceType, dwStartType, dwErrorControl,
2037 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
2038 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
2039 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
2041 cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
2043 __TRY
2045 err = svcctl_ChangeServiceConfigW(hService, dwServiceType,
2046 dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId,
2047 (const BYTE *)lpDependencies, multisz_cb(lpDependencies), lpServiceStartName,
2048 (const BYTE *)lpPassword, cb_pwd, lpDisplayName);
2050 __EXCEPT(rpc_filter)
2052 err = map_exception_code(GetExceptionCode());
2054 __ENDTRY
2056 if (err != ERROR_SUCCESS)
2057 SetLastError(err);
2059 return err == ERROR_SUCCESS;
2062 /******************************************************************************
2063 * ChangeServiceConfigA [ADVAPI32.@]
2065 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
2066 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
2067 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
2068 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
2070 LPWSTR wBinaryPathName, wLoadOrderGroup, wDependencies;
2071 LPWSTR wServiceStartName, wPassword, wDisplayName;
2072 BOOL r;
2074 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2075 hService, dwServiceType, dwStartType, dwErrorControl,
2076 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
2077 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
2078 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
2080 wBinaryPathName = SERV_dup( lpBinaryPathName );
2081 wLoadOrderGroup = SERV_dup( lpLoadOrderGroup );
2082 wDependencies = SERV_dupmulti( lpDependencies );
2083 wServiceStartName = SERV_dup( lpServiceStartName );
2084 wPassword = SERV_dup( lpPassword );
2085 wDisplayName = SERV_dup( lpDisplayName );
2087 r = ChangeServiceConfigW( hService, dwServiceType,
2088 dwStartType, dwErrorControl, wBinaryPathName,
2089 wLoadOrderGroup, lpdwTagId, wDependencies,
2090 wServiceStartName, wPassword, wDisplayName);
2092 HeapFree( GetProcessHeap(), 0, wBinaryPathName );
2093 HeapFree( GetProcessHeap(), 0, wLoadOrderGroup );
2094 HeapFree( GetProcessHeap(), 0, wDependencies );
2095 HeapFree( GetProcessHeap(), 0, wServiceStartName );
2096 HeapFree( GetProcessHeap(), 0, wPassword );
2097 HeapFree( GetProcessHeap(), 0, wDisplayName );
2099 return r;
2102 /******************************************************************************
2103 * ChangeServiceConfig2A [ADVAPI32.@]
2105 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
2106 LPVOID lpInfo)
2108 BOOL r = FALSE;
2110 TRACE("%p %d %p\n",hService, dwInfoLevel, lpInfo);
2112 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2114 LPSERVICE_DESCRIPTIONA sd = lpInfo;
2115 SERVICE_DESCRIPTIONW sdw;
2117 sdw.lpDescription = SERV_dup( sd->lpDescription );
2119 r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
2121 HeapFree( GetProcessHeap(), 0, sdw.lpDescription );
2123 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
2125 LPSERVICE_FAILURE_ACTIONSA fa = lpInfo;
2126 SERVICE_FAILURE_ACTIONSW faw;
2128 faw.dwResetPeriod = fa->dwResetPeriod;
2129 faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg );
2130 faw.lpCommand = SERV_dup( fa->lpCommand );
2131 faw.cActions = fa->cActions;
2132 faw.lpsaActions = fa->lpsaActions;
2134 r = ChangeServiceConfig2W( hService, dwInfoLevel, &faw );
2136 HeapFree( GetProcessHeap(), 0, faw.lpRebootMsg );
2137 HeapFree( GetProcessHeap(), 0, faw.lpCommand );
2139 else if (dwInfoLevel == SERVICE_CONFIG_PRESHUTDOWN_INFO)
2141 r = ChangeServiceConfig2W( hService, dwInfoLevel, lpInfo);
2143 else
2144 SetLastError( ERROR_INVALID_PARAMETER );
2146 return r;
2149 /******************************************************************************
2150 * ChangeServiceConfig2W [ADVAPI32.@]
2152 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
2153 LPVOID lpInfo)
2155 DWORD err;
2157 __TRY
2159 err = svcctl_ChangeServiceConfig2W( hService, dwInfoLevel, lpInfo );
2161 __EXCEPT(rpc_filter)
2163 err = map_exception_code(GetExceptionCode());
2165 __ENDTRY
2167 if (err != ERROR_SUCCESS)
2168 SetLastError(err);
2170 return err == ERROR_SUCCESS;
2173 NTSTATUS SERV_QueryServiceObjectSecurity(SC_HANDLE hService,
2174 SECURITY_INFORMATION dwSecurityInformation,
2175 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2176 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2178 SECURITY_DESCRIPTOR descriptor;
2179 NTSTATUS status;
2180 DWORD size;
2181 ACL acl;
2183 FIXME("%p %d %p %u %p - semi-stub\n", hService, dwSecurityInformation,
2184 lpSecurityDescriptor, cbBufSize, pcbBytesNeeded);
2186 if (dwSecurityInformation != DACL_SECURITY_INFORMATION)
2187 FIXME("information %d not supported\n", dwSecurityInformation);
2189 InitializeSecurityDescriptor(&descriptor, SECURITY_DESCRIPTOR_REVISION);
2191 InitializeAcl(&acl, sizeof(ACL), ACL_REVISION);
2192 SetSecurityDescriptorDacl(&descriptor, TRUE, &acl, TRUE);
2194 size = cbBufSize;
2195 status = RtlMakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
2196 *pcbBytesNeeded = size;
2197 return status;
2200 /******************************************************************************
2201 * QueryServiceObjectSecurity [ADVAPI32.@]
2203 BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
2204 SECURITY_INFORMATION dwSecurityInformation,
2205 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2206 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2208 NTSTATUS status = SERV_QueryServiceObjectSecurity(hService, dwSecurityInformation, lpSecurityDescriptor,
2209 cbBufSize, pcbBytesNeeded);
2210 if (status != STATUS_SUCCESS)
2212 SetLastError(RtlNtStatusToDosError(status));
2213 return FALSE;
2215 return TRUE;
2218 /******************************************************************************
2219 * SetServiceObjectSecurity [ADVAPI32.@]
2221 * NOTES
2222 * - SetSecurityInfo should be updated to call this function once it's implemented.
2224 BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService,
2225 SECURITY_INFORMATION dwSecurityInformation,
2226 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2228 FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
2229 return TRUE;
2232 /******************************************************************************
2233 * SetServiceBits [ADVAPI32.@]
2235 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
2236 DWORD dwServiceBits,
2237 BOOL bSetBitsOn,
2238 BOOL bUpdateImmediately)
2240 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
2241 bSetBitsOn, bUpdateImmediately);
2242 return TRUE;
2245 /* thunk for calling the RegisterServiceCtrlHandler handler function */
2246 static DWORD WINAPI ctrl_handler_thunk( DWORD control, DWORD type, void *data, void *context )
2248 LPHANDLER_FUNCTION func = context;
2250 func( control );
2251 return ERROR_SUCCESS;
2254 /******************************************************************************
2255 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
2257 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER_FUNCTION handler )
2259 return RegisterServiceCtrlHandlerExA( name, ctrl_handler_thunk, handler );
2262 /******************************************************************************
2263 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
2265 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLER_FUNCTION handler )
2267 return RegisterServiceCtrlHandlerExW( name, ctrl_handler_thunk, handler );
2270 /******************************************************************************
2271 * RegisterServiceCtrlHandlerExA [ADVAPI32.@]
2273 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDLER_FUNCTION_EX handler, LPVOID context )
2275 LPWSTR nameW;
2276 SERVICE_STATUS_HANDLE ret;
2278 nameW = SERV_dup(name);
2279 ret = RegisterServiceCtrlHandlerExW( nameW, handler, context );
2280 HeapFree( GetProcessHeap(), 0, nameW );
2281 return ret;
2284 /******************************************************************************
2285 * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
2287 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
2288 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2290 service_data *service;
2291 SC_HANDLE hService = 0;
2292 BOOL found = FALSE;
2294 TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
2296 EnterCriticalSection( &service_cs );
2297 if ((service = find_service_by_name( lpServiceName )))
2299 service->handler = lpHandlerProc;
2300 service->context = lpContext;
2301 hService = service->handle;
2302 found = TRUE;
2304 LeaveCriticalSection( &service_cs );
2306 if (!found) SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
2308 return (SERVICE_STATUS_HANDLE)hService;
2311 /******************************************************************************
2312 * EnumDependentServicesA [ADVAPI32.@]
2314 BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState,
2315 LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize,
2316 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2318 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2319 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2321 *lpServicesReturned = 0;
2322 return TRUE;
2325 /******************************************************************************
2326 * EnumDependentServicesW [ADVAPI32.@]
2328 BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
2329 LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize,
2330 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2332 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2333 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2335 *lpServicesReturned = 0;
2336 return TRUE;