advapi32: Pass service name as argv[0] to ServiceMain.
[wine/multimedia.git] / dlls / advapi32 / service.c
blob088de91de870cd1ecb2c16b75210fea1416cb796
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 "wine/exception.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(service);
48 void __RPC_FAR * __RPC_USER MIDL_user_allocate(SIZE_T len)
50 return HeapAlloc(GetProcessHeap(), 0, len);
53 void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
55 HeapFree(GetProcessHeap(), 0, ptr);
58 typedef struct service_data_t
60 LPHANDLER_FUNCTION_EX handler;
61 LPVOID context;
62 HANDLE thread;
63 SC_HANDLE handle;
64 SC_HANDLE full_access_handle;
65 BOOL unicode : 1;
66 union {
67 LPSERVICE_MAIN_FUNCTIONA a;
68 LPSERVICE_MAIN_FUNCTIONW w;
69 } proc;
70 LPWSTR args;
71 WCHAR name[1];
72 } service_data;
74 static CRITICAL_SECTION service_cs;
75 static CRITICAL_SECTION_DEBUG service_cs_debug =
77 0, 0, &service_cs,
78 { &service_cs_debug.ProcessLocksList,
79 &service_cs_debug.ProcessLocksList },
80 0, 0, { (DWORD_PTR)(__FILE__ ": service_cs") }
82 static CRITICAL_SECTION service_cs = { &service_cs_debug, -1, 0, 0, 0, 0 };
84 static service_data **services;
85 static unsigned int nb_services;
86 static HANDLE service_event;
88 extern HANDLE CDECL __wine_make_process_system(void);
90 /******************************************************************************
91 * String management functions (same behaviour as strdup)
92 * NOTE: the caller of those functions is responsible for calling HeapFree
93 * in order to release the memory allocated by those functions.
95 static inline LPWSTR SERV_dup( LPCSTR str )
97 UINT len;
98 LPWSTR wstr;
100 if( !str )
101 return NULL;
102 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
103 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
104 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
105 return wstr;
108 static inline LPWSTR SERV_dupmulti(LPCSTR str)
110 UINT len = 0, n = 0;
111 LPWSTR wstr;
113 if( !str )
114 return NULL;
115 do {
116 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
117 n += (strlen( &str[n] ) + 1);
118 } while (str[n]);
119 len++;
120 n++;
122 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
123 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
124 return wstr;
127 static inline DWORD multisz_cb(LPCWSTR wmultisz)
129 const WCHAR *wptr = wmultisz;
131 if (wmultisz == NULL)
132 return 0;
134 while (*wptr)
135 wptr += lstrlenW(wptr)+1;
136 return (wptr - wmultisz + 1)*sizeof(WCHAR);
139 /******************************************************************************
140 * RPC connection with services.exe
143 DECLSPEC_HIDDEN handle_t __RPC_USER MACHINE_HANDLEW_bind(MACHINE_HANDLEW MachineName)
145 WCHAR transport[] = SVCCTL_TRANSPORT;
146 WCHAR endpoint[] = SVCCTL_ENDPOINT;
147 RPC_WSTR binding_str;
148 RPC_STATUS status;
149 handle_t rpc_handle;
151 status = RpcStringBindingComposeW(NULL, transport, (RPC_WSTR)MachineName, endpoint, NULL, &binding_str);
152 if (status != RPC_S_OK)
154 ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD)status);
155 return NULL;
158 status = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
159 RpcStringFreeW(&binding_str);
161 if (status != RPC_S_OK)
163 ERR("Couldn't connect to services.exe: error code %u\n", (DWORD)status);
164 return NULL;
167 return rpc_handle;
170 DECLSPEC_HIDDEN void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName, handle_t h)
172 RpcBindingFree(&h);
175 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr)
177 return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode);
180 static DWORD map_exception_code(DWORD exception_code)
182 switch (exception_code)
184 case RPC_X_NULL_REF_POINTER:
185 return ERROR_INVALID_ADDRESS;
186 case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
187 case RPC_X_BYTE_COUNT_TOO_SMALL:
188 return ERROR_INVALID_PARAMETER;
189 case RPC_S_INVALID_BINDING:
190 case RPC_X_SS_IN_NULL_CONTEXT:
191 return ERROR_INVALID_HANDLE;
192 default:
193 return exception_code;
197 /******************************************************************************
198 * Service IPC functions
200 static LPWSTR service_get_pipe_name(void)
202 static const WCHAR format[] = { '\\','\\','.','\\','p','i','p','e','\\',
203 'n','e','t','\\','N','t','C','o','n','t','r','o','l','P','i','p','e','%','u',0};
204 static const WCHAR service_current_key_str[] = { 'S','Y','S','T','E','M','\\',
205 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
206 'C','o','n','t','r','o','l','\\',
207 'S','e','r','v','i','c','e','C','u','r','r','e','n','t',0};
208 LPWSTR name;
209 DWORD len;
210 HKEY service_current_key;
211 DWORD service_current;
212 LONG ret;
213 DWORD type;
215 ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, service_current_key_str, 0,
216 KEY_QUERY_VALUE, &service_current_key);
217 if (ret != ERROR_SUCCESS)
218 return NULL;
219 len = sizeof(service_current);
220 ret = RegQueryValueExW(service_current_key, NULL, NULL, &type,
221 (BYTE *)&service_current, &len);
222 RegCloseKey(service_current_key);
223 if (ret != ERROR_SUCCESS || type != REG_DWORD)
224 return NULL;
225 len = sizeof(format)/sizeof(WCHAR) + 10 /* strlenW("4294967295") */;
226 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
227 if (!name)
228 return NULL;
229 snprintfW(name, len, format, service_current);
230 return name;
233 static HANDLE service_open_pipe(void)
235 LPWSTR szPipe = service_get_pipe_name();
236 HANDLE handle = INVALID_HANDLE_VALUE;
238 do {
239 handle = CreateFileW(szPipe, GENERIC_READ|GENERIC_WRITE,
240 0, NULL, OPEN_ALWAYS, 0, NULL);
241 if (handle != INVALID_HANDLE_VALUE)
242 break;
243 if (GetLastError() != ERROR_PIPE_BUSY)
244 break;
245 } while (WaitNamedPipeW(szPipe, NMPWAIT_USE_DEFAULT_WAIT));
246 HeapFree(GetProcessHeap(), 0, szPipe);
248 return handle;
251 static service_data *find_service_by_name( const WCHAR *name )
253 unsigned int i;
255 if (nb_services == 1) /* only one service (FIXME: should depend on OWN_PROCESS etc.) */
256 return services[0];
257 for (i = 0; i < nb_services; i++)
258 if (!strcmpiW( name, services[i]->name )) return services[i];
259 return NULL;
262 /******************************************************************************
263 * service_thread
265 * Call into the main service routine provided by StartServiceCtrlDispatcher.
267 static DWORD WINAPI service_thread(LPVOID arg)
269 service_data *info = arg;
270 LPWSTR str = info->args;
271 DWORD argc = 0, len = 0;
273 TRACE("%p\n", arg);
275 while (str[len])
277 len += strlenW(&str[len]) + 1;
278 argc++;
280 len++;
282 if (info->unicode)
284 LPWSTR *argv, p;
286 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR));
287 for (argc=0, p=str; *p; p += strlenW(p) + 1)
288 argv[argc++] = p;
289 argv[argc] = NULL;
291 info->proc.w(argc, argv);
292 HeapFree(GetProcessHeap(), 0, argv);
294 else
296 LPSTR strA, *argv, p;
297 DWORD lenA;
299 lenA = WideCharToMultiByte(CP_ACP,0, str, len, NULL, 0, NULL, NULL);
300 strA = HeapAlloc(GetProcessHeap(), 0, lenA);
301 WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL);
303 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPSTR));
304 for (argc=0, p=strA; *p; p += strlen(p) + 1)
305 argv[argc++] = p;
306 argv[argc] = NULL;
308 info->proc.a(argc, argv);
309 HeapFree(GetProcessHeap(), 0, argv);
310 HeapFree(GetProcessHeap(), 0, strA);
312 return 0;
315 /******************************************************************************
316 * service_handle_start
318 static DWORD service_handle_start(service_data *service, const WCHAR *data, DWORD count)
320 TRACE("%s argsize %u\n", debugstr_w(service->name), count);
322 if (service->thread)
324 WARN("service is not stopped\n");
325 return ERROR_SERVICE_ALREADY_RUNNING;
328 HeapFree(GetProcessHeap(), 0, service->args);
329 service->args = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
330 memcpy( service->args, data, count * sizeof(WCHAR) );
331 service->thread = CreateThread( NULL, 0, service_thread,
332 service, 0, NULL );
333 SetEvent( service_event ); /* notify the main loop */
334 return 0;
337 /******************************************************************************
338 * service_handle_control
340 static DWORD service_handle_control(const service_data *service, DWORD dwControl)
342 DWORD ret = ERROR_INVALID_SERVICE_CONTROL;
344 TRACE("%s control %u\n", debugstr_w(service->name), dwControl);
346 if (service->handler)
347 ret = service->handler(dwControl, 0, NULL, service->context);
348 return ret;
351 /******************************************************************************
352 * service_control_dispatcher
354 static DWORD WINAPI service_control_dispatcher(LPVOID arg)
356 SC_HANDLE manager;
357 HANDLE pipe;
359 if (!(manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
361 ERR("failed to open service manager error %u\n", GetLastError());
362 return 0;
365 pipe = service_open_pipe();
367 if (pipe==INVALID_HANDLE_VALUE)
369 WARN("failed to create control pipe error = %d\n", GetLastError());
370 return 0;
373 /* dispatcher loop */
374 while (1)
376 service_data *service;
377 service_start_info info;
378 WCHAR *data = NULL;
379 BOOL r;
380 DWORD data_size = 0, count, result;
382 r = ReadFile( pipe, &info, FIELD_OFFSET(service_start_info,data), &count, NULL );
383 if (!r)
385 if (GetLastError() != ERROR_BROKEN_PIPE)
386 ERR( "pipe read failed error %u\n", GetLastError() );
387 break;
389 if (count != FIELD_OFFSET(service_start_info,data))
391 ERR( "partial pipe read %u\n", count );
392 break;
394 if (count < info.total_size)
396 data_size = info.total_size - FIELD_OFFSET(service_start_info,data);
397 data = HeapAlloc( GetProcessHeap(), 0, data_size );
398 r = ReadFile( pipe, data, data_size, &count, NULL );
399 if (!r)
401 if (GetLastError() != ERROR_BROKEN_PIPE)
402 ERR( "pipe read failed error %u\n", GetLastError() );
403 break;
405 if (count != data_size)
407 ERR( "partial pipe read %u/%u\n", count, data_size );
408 break;
412 /* find the service */
414 if (!(service = find_service_by_name( data )))
416 FIXME( "got request %u for unknown service %s\n", info.cmd, debugstr_w(data));
417 result = ERROR_INVALID_PARAMETER;
418 goto done;
421 TRACE( "got request %u for service %s\n", info.cmd, debugstr_w(data) );
423 /* handle the request */
424 switch (info.cmd)
426 case WINESERV_STARTINFO:
427 if (!service->handle)
429 if (!(service->handle = OpenServiceW( manager, data, SERVICE_SET_STATUS )) ||
430 !(service->full_access_handle = OpenServiceW( manager, data, GENERIC_READ|GENERIC_WRITE )))
431 FIXME( "failed to open service %s\n", debugstr_w(data) );
433 result = service_handle_start(service, data, data_size / sizeof(WCHAR));
434 break;
435 case WINESERV_SENDCONTROL:
436 result = service_handle_control(service, info.control);
437 break;
438 default:
439 ERR("received invalid command %u\n", info.cmd);
440 result = ERROR_INVALID_PARAMETER;
441 break;
444 done:
445 WriteFile(pipe, &result, sizeof(result), &count, NULL);
446 HeapFree( GetProcessHeap(), 0, data );
449 CloseHandle(pipe);
450 CloseServiceHandle( manager );
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];
463 service_event = CreateEventW( NULL, FALSE, FALSE, NULL );
465 /* FIXME: service_control_dispatcher should be merged into the main thread */
466 wait_handles[0] = __wine_make_process_system();
467 wait_handles[1] = CreateThread( NULL, 0, service_control_dispatcher, NULL, 0, NULL );
468 wait_handles[2] = service_event;
470 TRACE("Starting %d services running as process %d\n",
471 nb_services, GetCurrentProcessId());
473 /* wait for all the threads to pack up and exit */
474 for (;;)
476 EnterCriticalSection( &service_cs );
477 for (i = 0, n = 3; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
479 if (!services[i]->thread) continue;
480 wait_services[n] = i;
481 wait_handles[n++] = services[i]->thread;
483 LeaveCriticalSection( &service_cs );
485 ret = WaitForMultipleObjects( n, wait_handles, FALSE, INFINITE );
486 if (!ret) /* system process event */
488 SERVICE_STATUS st;
489 SERVICE_PRESHUTDOWN_INFO spi;
490 DWORD timeout = 5000;
491 BOOL res;
493 EnterCriticalSection( &service_cs );
494 n = 0;
495 for (i = 0; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
497 if (!services[i]->thread) continue;
499 res = QueryServiceStatus(services[i]->full_access_handle, &st);
500 ret = ERROR_SUCCESS;
501 if (res && (st.dwControlsAccepted & SERVICE_ACCEPT_PRESHUTDOWN))
503 res = QueryServiceConfig2W( services[i]->full_access_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
504 (LPBYTE)&spi, sizeof(spi), &i );
505 if (res)
507 FIXME("service should be able to delay shutdown\n");
508 timeout += spi.dwPreshutdownTimeout;
509 ret = service_handle_control( services[i], SERVICE_CONTROL_PRESHUTDOWN );
510 wait_handles[n++] = services[i]->thread;
513 else if (res && (st.dwControlsAccepted & SERVICE_ACCEPT_SHUTDOWN))
515 ret = service_handle_control( services[i], SERVICE_CONTROL_SHUTDOWN );
516 wait_handles[n++] = services[i]->thread;
519 LeaveCriticalSection( &service_cs );
521 TRACE("last user process exited, shutting down (timeout: %d)\n", timeout);
522 WaitForMultipleObjects( n, wait_handles, TRUE, timeout );
523 ExitProcess(0);
525 else if (ret == 1)
527 TRACE( "control dispatcher exited, shutting down\n" );
528 /* FIXME: we should maybe send a shutdown control to running services */
529 ExitProcess(0);
531 else if (ret == 2)
533 continue; /* rebuild the list */
535 else if (ret < n)
537 services[wait_services[ret]]->thread = 0;
538 CloseHandle( wait_handles[ret] );
539 if (n == 4) return TRUE; /* it was the last running thread */
541 else return FALSE;
545 /******************************************************************************
546 * StartServiceCtrlDispatcherA [ADVAPI32.@]
548 * See StartServiceCtrlDispatcherW.
550 BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
552 service_data *info;
553 unsigned int i;
554 BOOL ret = TRUE;
556 TRACE("%p\n", servent);
558 if (nb_services)
560 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
561 return FALSE;
563 while (servent[nb_services].lpServiceName) nb_services++;
564 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
566 for (i = 0; i < nb_services; i++)
568 DWORD len = MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, NULL, 0);
569 DWORD sz = FIELD_OFFSET( service_data, name[len] );
570 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
571 MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, info->name, len);
572 info->proc.a = servent[i].lpServiceProc;
573 info->unicode = FALSE;
574 services[i] = info;
577 service_run_main_thread();
579 return ret;
582 /******************************************************************************
583 * StartServiceCtrlDispatcherW [ADVAPI32.@]
585 * Connects a process containing one or more services to the service control
586 * manager.
588 * PARAMS
589 * servent [I] A list of the service names and service procedures
591 * RETURNS
592 * Success: TRUE.
593 * Failure: FALSE.
595 BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
597 service_data *info;
598 unsigned int i;
599 BOOL ret = TRUE;
601 TRACE("%p\n", servent);
603 if (nb_services)
605 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
606 return FALSE;
608 while (servent[nb_services].lpServiceName) nb_services++;
609 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
611 for (i = 0; i < nb_services; i++)
613 DWORD len = strlenW(servent[i].lpServiceName) + 1;
614 DWORD sz = FIELD_OFFSET( service_data, name[len] );
615 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
616 strcpyW(info->name, servent[i].lpServiceName);
617 info->proc.w = servent[i].lpServiceProc;
618 info->unicode = TRUE;
619 services[i] = info;
622 service_run_main_thread();
624 return ret;
627 /******************************************************************************
628 * LockServiceDatabase [ADVAPI32.@]
630 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
632 SC_RPC_LOCK hLock = NULL;
633 DWORD err;
635 TRACE("%p\n",hSCManager);
637 __TRY
639 err = svcctl_LockServiceDatabase(hSCManager, &hLock);
641 __EXCEPT(rpc_filter)
643 err = map_exception_code(GetExceptionCode());
645 __ENDTRY
646 if (err != ERROR_SUCCESS)
648 SetLastError(err);
649 return NULL;
651 return hLock;
654 /******************************************************************************
655 * UnlockServiceDatabase [ADVAPI32.@]
657 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
659 DWORD err;
660 SC_RPC_LOCK hRpcLock = ScLock;
662 TRACE("%p\n",ScLock);
664 __TRY
666 err = svcctl_UnlockServiceDatabase(&hRpcLock);
668 __EXCEPT(rpc_filter)
670 err = map_exception_code(GetExceptionCode());
672 __ENDTRY
673 if (err != ERROR_SUCCESS)
675 SetLastError(err);
676 return FALSE;
678 return TRUE;
681 /******************************************************************************
682 * SetServiceStatus [ADVAPI32.@]
684 * PARAMS
685 * hService []
686 * lpStatus []
688 BOOL WINAPI
689 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
691 DWORD err;
693 TRACE("%p %x %x %x %x %x %x %x\n", hService,
694 lpStatus->dwServiceType, lpStatus->dwCurrentState,
695 lpStatus->dwControlsAccepted, lpStatus->dwWin32ExitCode,
696 lpStatus->dwServiceSpecificExitCode, lpStatus->dwCheckPoint,
697 lpStatus->dwWaitHint);
699 __TRY
701 err = svcctl_SetServiceStatus( hService, lpStatus );
703 __EXCEPT(rpc_filter)
705 err = map_exception_code(GetExceptionCode());
707 __ENDTRY
708 if (err != ERROR_SUCCESS)
710 SetLastError(err);
711 return FALSE;
714 if (lpStatus->dwCurrentState == SERVICE_STOPPED)
715 CloseServiceHandle((SC_HANDLE)hService);
717 return TRUE;
721 /******************************************************************************
722 * OpenSCManagerA [ADVAPI32.@]
724 * Establish a connection to the service control manager and open its database.
726 * PARAMS
727 * lpMachineName [I] Pointer to machine name string
728 * lpDatabaseName [I] Pointer to database name string
729 * dwDesiredAccess [I] Type of access
731 * RETURNS
732 * Success: A Handle to the service control manager database
733 * Failure: NULL
735 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
736 DWORD dwDesiredAccess )
738 LPWSTR lpMachineNameW, lpDatabaseNameW;
739 SC_HANDLE ret;
741 lpMachineNameW = SERV_dup(lpMachineName);
742 lpDatabaseNameW = SERV_dup(lpDatabaseName);
743 ret = OpenSCManagerW(lpMachineNameW, lpDatabaseNameW, dwDesiredAccess);
744 HeapFree(GetProcessHeap(), 0, lpDatabaseNameW);
745 HeapFree(GetProcessHeap(), 0, lpMachineNameW);
746 return ret;
749 /******************************************************************************
750 * OpenSCManagerW [ADVAPI32.@]
752 * See OpenSCManagerA.
754 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
755 DWORD dwDesiredAccess )
757 SC_HANDLE handle = 0;
758 LONG r;
760 TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
761 debugstr_w(lpDatabaseName), dwDesiredAccess);
763 __TRY
765 r = svcctl_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, (SC_RPC_HANDLE *)&handle);
767 __EXCEPT(rpc_filter)
769 r = map_exception_code(GetExceptionCode());
771 __ENDTRY
773 if (r!=ERROR_SUCCESS)
775 SetLastError( r );
776 handle = 0;
779 TRACE("returning %p\n", handle);
780 return handle;
783 /******************************************************************************
784 * ControlService [ADVAPI32.@]
786 * Send a control code to a service.
788 * PARAMS
789 * hService [I] Handle of the service control manager database
790 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
791 * lpServiceStatus [O] Destination for the status of the service, if available
793 * RETURNS
794 * Success: TRUE.
795 * Failure: FALSE.
797 * BUGS
798 * Unlike M$' implementation, control requests are not serialized and may be
799 * processed asynchronously.
801 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
802 LPSERVICE_STATUS lpServiceStatus )
804 DWORD err;
806 TRACE("%p %d %p\n", hService, dwControl, lpServiceStatus);
808 __TRY
810 err = svcctl_ControlService(hService, dwControl, lpServiceStatus);
812 __EXCEPT(rpc_filter)
814 err = map_exception_code(GetExceptionCode());
816 __ENDTRY
817 if (err != ERROR_SUCCESS)
819 SetLastError(err);
820 return FALSE;
823 return TRUE;
826 /******************************************************************************
827 * CloseServiceHandle [ADVAPI32.@]
829 * Close a handle to a service or the service control manager database.
831 * PARAMS
832 * hSCObject [I] Handle to service or service control manager database
834 * RETURNS
835 * Success: TRUE
836 * Failure: FALSE
838 BOOL WINAPI
839 CloseServiceHandle( SC_HANDLE hSCObject )
841 DWORD err;
843 TRACE("%p\n", hSCObject);
845 __TRY
847 err = svcctl_CloseServiceHandle((SC_RPC_HANDLE *)&hSCObject);
849 __EXCEPT(rpc_filter)
851 err = map_exception_code(GetExceptionCode());
853 __ENDTRY
855 if (err != ERROR_SUCCESS)
857 SetLastError(err);
858 return FALSE;
860 return TRUE;
864 /******************************************************************************
865 * OpenServiceA [ADVAPI32.@]
867 * Open a handle to a service.
869 * PARAMS
870 * hSCManager [I] Handle of the service control manager database
871 * lpServiceName [I] Name of the service to open
872 * dwDesiredAccess [I] Access required to the service
874 * RETURNS
875 * Success: Handle to the service
876 * Failure: NULL
878 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
879 DWORD dwDesiredAccess )
881 LPWSTR lpServiceNameW;
882 SC_HANDLE ret;
884 TRACE("%p %s %d\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
886 lpServiceNameW = SERV_dup(lpServiceName);
887 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
888 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
889 return ret;
893 /******************************************************************************
894 * OpenServiceW [ADVAPI32.@]
896 * See OpenServiceA.
898 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
899 DWORD dwDesiredAccess)
901 SC_HANDLE handle = 0;
902 DWORD err;
904 TRACE("%p %s %d\n", hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
906 if (!hSCManager)
908 SetLastError( ERROR_INVALID_HANDLE );
909 return 0;
912 __TRY
914 err = svcctl_OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess, (SC_RPC_HANDLE *)&handle);
916 __EXCEPT(rpc_filter)
918 err = map_exception_code(GetExceptionCode());
920 __ENDTRY
922 if (err != ERROR_SUCCESS)
924 SetLastError(err);
925 handle = 0;
928 TRACE("returning %p\n",handle);
929 return handle;
932 /******************************************************************************
933 * CreateServiceW [ADVAPI32.@]
935 SC_HANDLE WINAPI
936 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
937 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
938 DWORD dwServiceType, DWORD dwStartType,
939 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
940 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
941 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
942 LPCWSTR lpPassword )
944 SC_HANDLE handle = 0;
945 DWORD err;
946 SIZE_T passwdlen;
948 TRACE("%p %s %s\n", hSCManager,
949 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
951 if (!hSCManager)
953 SetLastError( ERROR_INVALID_HANDLE );
954 return 0;
957 if (lpPassword)
958 passwdlen = (strlenW(lpPassword) + 1) * sizeof(WCHAR);
959 else
960 passwdlen = 0;
962 __TRY
964 err = svcctl_CreateServiceW(hSCManager, lpServiceName,
965 lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
966 lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, (const BYTE*)lpDependencies,
967 multisz_cb(lpDependencies), lpServiceStartName, (const BYTE*)lpPassword, passwdlen,
968 (SC_RPC_HANDLE *)&handle);
970 __EXCEPT(rpc_filter)
972 err = map_exception_code(GetExceptionCode());
974 __ENDTRY
976 if (err != ERROR_SUCCESS)
978 SetLastError(err);
979 handle = 0;
981 return handle;
985 /******************************************************************************
986 * CreateServiceA [ADVAPI32.@]
988 SC_HANDLE WINAPI
989 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
990 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
991 DWORD dwServiceType, DWORD dwStartType,
992 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
993 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
994 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
995 LPCSTR lpPassword )
997 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
998 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
999 SC_HANDLE r;
1001 TRACE("%p %s %s\n", hSCManager,
1002 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
1004 lpServiceNameW = SERV_dup( lpServiceName );
1005 lpDisplayNameW = SERV_dup( lpDisplayName );
1006 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
1007 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
1008 lpDependenciesW = SERV_dupmulti( lpDependencies );
1009 lpServiceStartNameW = SERV_dup( lpServiceStartName );
1010 lpPasswordW = SERV_dup( lpPassword );
1012 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
1013 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1014 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
1015 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
1017 HeapFree( GetProcessHeap(), 0, lpServiceNameW );
1018 HeapFree( GetProcessHeap(), 0, lpDisplayNameW );
1019 HeapFree( GetProcessHeap(), 0, lpBinaryPathNameW );
1020 HeapFree( GetProcessHeap(), 0, lpLoadOrderGroupW );
1021 HeapFree( GetProcessHeap(), 0, lpDependenciesW );
1022 HeapFree( GetProcessHeap(), 0, lpServiceStartNameW );
1023 HeapFree( GetProcessHeap(), 0, lpPasswordW );
1025 return r;
1029 /******************************************************************************
1030 * DeleteService [ADVAPI32.@]
1032 * Delete a service from the service control manager database.
1034 * PARAMS
1035 * hService [I] Handle of the service to delete
1037 * RETURNS
1038 * Success: TRUE
1039 * Failure: FALSE
1041 BOOL WINAPI DeleteService( SC_HANDLE hService )
1043 DWORD err;
1045 __TRY
1047 err = svcctl_DeleteService(hService);
1049 __EXCEPT(rpc_filter)
1051 err = map_exception_code(GetExceptionCode());
1053 __ENDTRY
1054 if (err != 0)
1056 SetLastError(err);
1057 return FALSE;
1060 return TRUE;
1064 /******************************************************************************
1065 * StartServiceA [ADVAPI32.@]
1067 * Start a service
1069 * PARAMS
1070 * hService [I] Handle of service
1071 * dwNumServiceArgs [I] Number of arguments
1072 * lpServiceArgVectors [I] Address of array of argument strings
1074 * NOTES
1075 * - NT implements this function using an obscure RPC call.
1076 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1077 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
1078 * - This will only work for shared address space. How should the service
1079 * args be transferred when address spaces are separated?
1080 * - Can only start one service at a time.
1081 * - Has no concept of privilege.
1083 * RETURNS
1084 * Success: TRUE.
1085 * Failure: FALSE
1087 BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
1088 LPCSTR *lpServiceArgVectors )
1090 LPWSTR *lpwstr=NULL;
1091 unsigned int i;
1092 BOOL r;
1094 TRACE("(%p,%d,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
1096 if (dwNumServiceArgs)
1097 lpwstr = HeapAlloc( GetProcessHeap(), 0,
1098 dwNumServiceArgs*sizeof(LPWSTR) );
1100 for(i=0; i<dwNumServiceArgs; i++)
1101 lpwstr[i]=SERV_dup(lpServiceArgVectors[i]);
1103 r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
1105 if (dwNumServiceArgs)
1107 for(i=0; i<dwNumServiceArgs; i++)
1108 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
1109 HeapFree(GetProcessHeap(), 0, lpwstr);
1112 return r;
1116 /******************************************************************************
1117 * StartServiceW [ADVAPI32.@]
1119 * See StartServiceA.
1121 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1122 LPCWSTR *lpServiceArgVectors)
1124 DWORD err;
1126 TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1128 __TRY
1130 err = svcctl_StartServiceW(hService, dwNumServiceArgs, lpServiceArgVectors);
1132 __EXCEPT(rpc_filter)
1134 err = map_exception_code(GetExceptionCode());
1136 __ENDTRY
1137 if (err != ERROR_SUCCESS)
1139 SetLastError(err);
1140 return FALSE;
1143 return TRUE;
1146 /******************************************************************************
1147 * QueryServiceStatus [ADVAPI32.@]
1149 * PARAMS
1150 * hService [I] Handle to service to get information about
1151 * lpservicestatus [O] buffer to receive the status information for the service
1154 BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
1155 LPSERVICE_STATUS lpservicestatus)
1157 SERVICE_STATUS_PROCESS SvcStatusData;
1158 BOOL ret;
1159 DWORD dummy;
1161 TRACE("%p %p\n", hService, lpservicestatus);
1163 if (!hService)
1165 SetLastError(ERROR_INVALID_HANDLE);
1166 return FALSE;
1168 if (!lpservicestatus)
1170 SetLastError(ERROR_INVALID_ADDRESS);
1171 return FALSE;
1174 ret = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&SvcStatusData,
1175 sizeof(SERVICE_STATUS_PROCESS), &dummy);
1176 if (ret) memcpy(lpservicestatus, &SvcStatusData, sizeof(SERVICE_STATUS)) ;
1177 return ret;
1181 /******************************************************************************
1182 * QueryServiceStatusEx [ADVAPI32.@]
1184 * Get information about a service.
1186 * PARAMS
1187 * hService [I] Handle to service to get information about
1188 * InfoLevel [I] Level of information to get
1189 * lpBuffer [O] Destination for requested information
1190 * cbBufSize [I] Size of lpBuffer in bytes
1191 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1193 * RETURNS
1194 * Success: TRUE
1195 * FAILURE: FALSE
1197 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1198 LPBYTE lpBuffer, DWORD cbBufSize,
1199 LPDWORD pcbBytesNeeded)
1201 DWORD err;
1203 TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1205 if (InfoLevel != SC_STATUS_PROCESS_INFO)
1207 err = ERROR_INVALID_LEVEL;
1209 else if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
1211 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
1212 err = ERROR_INSUFFICIENT_BUFFER;
1214 else
1216 __TRY
1218 err = svcctl_QueryServiceStatusEx(hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1220 __EXCEPT(rpc_filter)
1222 err = map_exception_code(GetExceptionCode());
1224 __ENDTRY
1226 if (err != ERROR_SUCCESS)
1228 SetLastError(err);
1229 return FALSE;
1231 return TRUE;
1234 /******************************************************************************
1235 * QueryServiceConfigA [ADVAPI32.@]
1237 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1238 DWORD size, LPDWORD needed )
1240 DWORD n;
1241 LPSTR p, buffer;
1242 BOOL ret;
1243 QUERY_SERVICE_CONFIGW *configW;
1245 TRACE("%p %p %d %p\n", hService, config, size, needed);
1247 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, 2 * size )))
1249 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1250 return FALSE;
1252 configW = (QUERY_SERVICE_CONFIGW *)buffer;
1253 ret = QueryServiceConfigW( hService, configW, 2 * size, needed );
1254 if (!ret) goto done;
1256 config->dwServiceType = configW->dwServiceType;
1257 config->dwStartType = configW->dwStartType;
1258 config->dwErrorControl = configW->dwErrorControl;
1259 config->lpBinaryPathName = NULL;
1260 config->lpLoadOrderGroup = NULL;
1261 config->dwTagId = configW->dwTagId;
1262 config->lpDependencies = NULL;
1263 config->lpServiceStartName = NULL;
1264 config->lpDisplayName = NULL;
1266 p = (LPSTR)(config + 1);
1267 n = size - sizeof(*config);
1268 ret = FALSE;
1270 #define MAP_STR(str) \
1271 do { \
1272 if (configW->str) \
1274 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1275 if (!sz) goto done; \
1276 config->str = p; \
1277 p += sz; \
1278 n -= sz; \
1280 } while (0)
1282 MAP_STR( lpBinaryPathName );
1283 MAP_STR( lpLoadOrderGroup );
1284 MAP_STR( lpDependencies );
1285 MAP_STR( lpServiceStartName );
1286 MAP_STR( lpDisplayName );
1287 #undef MAP_STR
1289 *needed = p - (LPSTR)config;
1290 ret = TRUE;
1292 done:
1293 HeapFree( GetProcessHeap(), 0, buffer );
1294 return ret;
1297 static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
1299 DWORD cb;
1301 if (!*string_ptr)
1303 cb = sizeof(WCHAR);
1304 memset(*buf, 0, cb);
1306 else
1308 cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
1309 memcpy(*buf, *string_ptr, cb);
1310 MIDL_user_free(*string_ptr);
1313 *string_ptr = (LPWSTR)*buf;
1314 *buf += cb;
1316 return cb;
1319 static DWORD size_string(LPCWSTR string)
1321 return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
1324 /******************************************************************************
1325 * QueryServiceConfigW [ADVAPI32.@]
1327 BOOL WINAPI
1328 QueryServiceConfigW( SC_HANDLE hService,
1329 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1330 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1332 QUERY_SERVICE_CONFIGW config;
1333 DWORD total;
1334 DWORD err;
1335 BYTE *bufpos;
1337 TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1338 cbBufSize, pcbBytesNeeded);
1340 memset(&config, 0, sizeof(config));
1342 __TRY
1344 err = svcctl_QueryServiceConfigW(hService, &config);
1346 __EXCEPT(rpc_filter)
1348 err = map_exception_code(GetExceptionCode());
1350 __ENDTRY
1352 if (err != ERROR_SUCCESS)
1354 TRACE("services.exe: error %u\n", err);
1355 SetLastError(err);
1356 return FALSE;
1359 /* calculate the size required first */
1360 total = sizeof (QUERY_SERVICE_CONFIGW);
1361 total += size_string(config.lpBinaryPathName);
1362 total += size_string(config.lpLoadOrderGroup);
1363 total += size_string(config.lpDependencies);
1364 total += size_string(config.lpServiceStartName);
1365 total += size_string(config.lpDisplayName);
1367 *pcbBytesNeeded = total;
1369 /* if there's not enough memory, return an error */
1370 if( total > cbBufSize )
1372 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1373 MIDL_user_free(config.lpBinaryPathName);
1374 MIDL_user_free(config.lpLoadOrderGroup);
1375 MIDL_user_free(config.lpDependencies);
1376 MIDL_user_free(config.lpServiceStartName);
1377 MIDL_user_free(config.lpDisplayName);
1378 return FALSE;
1381 *lpServiceConfig = config;
1382 bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
1383 move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
1384 move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
1385 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
1386 move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
1387 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
1389 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1390 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1391 TRACE("Dependencies = %s\n", debugstr_w(lpServiceConfig->lpDependencies) );
1392 TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig->lpServiceStartName) );
1393 TRACE("Display name = %s\n", debugstr_w(lpServiceConfig->lpDisplayName) );
1395 return TRUE;
1398 /******************************************************************************
1399 * QueryServiceConfig2A [ADVAPI32.@]
1401 * Note
1402 * observed under win2k:
1403 * The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
1404 * required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
1406 BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1407 DWORD size, LPDWORD needed)
1409 BOOL ret;
1410 LPBYTE bufferW = NULL;
1412 if(buffer && size)
1413 bufferW = HeapAlloc( GetProcessHeap(), 0, size);
1415 ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
1416 if(!ret) goto cleanup;
1418 switch(dwLevel) {
1419 case SERVICE_CONFIG_DESCRIPTION:
1420 if (buffer && bufferW) {
1421 LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
1422 LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
1423 if (configW->lpDescription && (size > sizeof(SERVICE_DESCRIPTIONA))) {
1424 DWORD sz;
1425 configA->lpDescription = (LPSTR)(configA + 1);
1426 sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
1427 configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
1428 if (!sz) {
1429 FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1430 ret = FALSE;
1431 configA->lpDescription = NULL;
1434 else configA->lpDescription = NULL;
1436 break;
1437 case SERVICE_CONFIG_PRESHUTDOWN_INFO:
1438 if (buffer && bufferW && *needed<=size)
1439 memcpy(buffer, bufferW, *needed);
1440 break;
1441 default:
1442 FIXME("conversation W->A not implemented for level %d\n", dwLevel);
1443 ret = FALSE;
1444 break;
1447 cleanup:
1448 HeapFree( GetProcessHeap(), 0, bufferW);
1449 return ret;
1452 /******************************************************************************
1453 * QueryServiceConfig2W [ADVAPI32.@]
1455 * See QueryServiceConfig2A.
1457 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1458 DWORD size, LPDWORD needed)
1460 DWORD err;
1462 if(dwLevel!=SERVICE_CONFIG_DESCRIPTION && dwLevel!=SERVICE_CONFIG_PRESHUTDOWN_INFO) {
1463 FIXME("Level %d not implemented\n", dwLevel);
1464 SetLastError(ERROR_INVALID_LEVEL);
1465 return FALSE;
1468 if(!buffer && size) {
1469 SetLastError(ERROR_INVALID_ADDRESS);
1470 return FALSE;
1473 TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
1475 __TRY
1477 err = svcctl_QueryServiceConfig2W(hService, dwLevel, buffer, size, needed);
1479 __EXCEPT(rpc_filter)
1481 err = map_exception_code(GetExceptionCode());
1483 __ENDTRY
1485 if (err != ERROR_SUCCESS)
1487 SetLastError( err );
1488 return FALSE;
1491 switch (dwLevel)
1493 case SERVICE_CONFIG_DESCRIPTION:
1494 if (buffer)
1496 SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
1497 if (descr->lpDescription) /* make it an absolute pointer */
1498 descr->lpDescription = (WCHAR *)(buffer + (ULONG_PTR)descr->lpDescription);
1499 break;
1503 return TRUE;
1506 /******************************************************************************
1507 * EnumServicesStatusA [ADVAPI32.@]
1509 BOOL WINAPI
1510 EnumServicesStatusA( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSA
1511 services, DWORD size, LPDWORD needed, LPDWORD returned,
1512 LPDWORD resume_handle )
1514 BOOL ret;
1515 unsigned int i;
1516 ENUM_SERVICE_STATUSW *servicesW = NULL;
1517 DWORD sz, n;
1518 char *p;
1520 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
1521 returned, resume_handle);
1523 sz = max( 2 * size, sizeof(*servicesW) );
1524 if (!(servicesW = HeapAlloc( GetProcessHeap(), 0, sz )))
1526 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1527 return FALSE;
1530 ret = EnumServicesStatusW( hmngr, type, state, servicesW, sz, needed, returned, resume_handle );
1531 if (!ret) goto done;
1533 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUSA);
1534 n = size - (p - (char *)services);
1535 ret = FALSE;
1536 for (i = 0; i < *returned; i++)
1538 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
1539 if (!sz) goto done;
1540 services[i].lpServiceName = p;
1541 p += sz;
1542 n -= sz;
1543 if (servicesW[i].lpDisplayName)
1545 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
1546 if (!sz) goto done;
1547 services[i].lpDisplayName = p;
1548 p += sz;
1549 n -= sz;
1551 else services[i].lpDisplayName = NULL;
1552 services[i].ServiceStatus = servicesW[i].ServiceStatus;
1555 ret = TRUE;
1557 done:
1558 HeapFree( GetProcessHeap(), 0, servicesW );
1559 return ret;
1562 /******************************************************************************
1563 * EnumServicesStatusW [ADVAPI32.@]
1565 BOOL WINAPI
1566 EnumServicesStatusW( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSW
1567 services, DWORD size, LPDWORD needed, LPDWORD returned,
1568 LPDWORD resume_handle )
1570 DWORD err, i;
1571 ENUM_SERVICE_STATUSW dummy_status;
1573 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
1574 returned, resume_handle);
1576 if (resume_handle)
1577 FIXME("resume handle not supported\n");
1579 if (!hmngr)
1581 SetLastError( ERROR_INVALID_HANDLE );
1582 return FALSE;
1585 /* make sure we pass a valid pointer */
1586 if (!services || size < sizeof(*services))
1588 services = &dummy_status;
1589 size = sizeof(dummy_status);
1592 __TRY
1594 err = svcctl_EnumServicesStatusW( hmngr, type, state, (BYTE *)services, size, needed, returned );
1596 __EXCEPT(rpc_filter)
1598 err = map_exception_code( GetExceptionCode() );
1600 __ENDTRY
1602 if (err != ERROR_SUCCESS)
1604 SetLastError( err );
1605 return FALSE;
1608 for (i = 0; i < *returned; i++)
1610 /* convert buffer offsets into pointers */
1611 services[i].lpServiceName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpServiceName);
1612 if (services[i].lpDisplayName)
1613 services[i].lpDisplayName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpDisplayName);
1616 return TRUE;
1619 /******************************************************************************
1620 * EnumServicesStatusExA [ADVAPI32.@]
1622 BOOL WINAPI
1623 EnumServicesStatusExA( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state,
1624 LPBYTE buffer, DWORD size, LPDWORD needed, LPDWORD returned,
1625 LPDWORD resume_handle, LPCSTR group )
1627 BOOL ret;
1628 unsigned int i;
1629 ENUM_SERVICE_STATUS_PROCESSA *services = (ENUM_SERVICE_STATUS_PROCESSA *)buffer;
1630 ENUM_SERVICE_STATUS_PROCESSW *servicesW = NULL;
1631 WCHAR *groupW = NULL;
1632 DWORD sz, n;
1633 char *p;
1635 TRACE("%p %u 0x%x 0x%x %p %u %p %p %p %s\n", hmngr, level, type, state, buffer,
1636 size, needed, returned, resume_handle, debugstr_a(group));
1638 sz = max( 2 * size, sizeof(*servicesW) );
1639 if (!(servicesW = HeapAlloc( GetProcessHeap(), 0, sz )))
1641 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1642 return FALSE;
1644 if (group)
1646 int len = MultiByteToWideChar( CP_ACP, 0, group, -1, NULL, 0 );
1647 if (!(groupW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1649 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1650 HeapFree( GetProcessHeap(), 0, servicesW );
1651 return FALSE;
1653 MultiByteToWideChar( CP_ACP, 0, group, -1, groupW, len * sizeof(WCHAR) );
1656 ret = EnumServicesStatusExW( hmngr, level, type, state, (BYTE *)servicesW, sz,
1657 needed, returned, resume_handle, groupW );
1658 if (!ret) goto done;
1660 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUS_PROCESSA);
1661 n = size - (p - (char *)services);
1662 ret = FALSE;
1663 for (i = 0; i < *returned; i++)
1665 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
1666 if (!sz) goto done;
1667 services[i].lpServiceName = p;
1668 p += sz;
1669 n -= sz;
1670 if (servicesW[i].lpDisplayName)
1672 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
1673 if (!sz) goto done;
1674 services[i].lpDisplayName = p;
1675 p += sz;
1676 n -= sz;
1678 else services[i].lpDisplayName = NULL;
1679 services[i].ServiceStatusProcess = servicesW[i].ServiceStatusProcess;
1682 ret = TRUE;
1684 done:
1685 HeapFree( GetProcessHeap(), 0, servicesW );
1686 HeapFree( GetProcessHeap(), 0, groupW );
1687 return ret;
1690 /******************************************************************************
1691 * EnumServicesStatusExW [ADVAPI32.@]
1693 BOOL WINAPI
1694 EnumServicesStatusExW( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state,
1695 LPBYTE buffer, DWORD size, LPDWORD needed, LPDWORD returned,
1696 LPDWORD resume_handle, LPCWSTR group )
1698 DWORD err, i;
1699 ENUM_SERVICE_STATUS_PROCESSW dummy_status;
1700 ENUM_SERVICE_STATUS_PROCESSW *services = (ENUM_SERVICE_STATUS_PROCESSW *)buffer;
1702 TRACE("%p %u 0x%x 0x%x %p %u %p %p %p %s\n", hmngr, level, type, state, buffer,
1703 size, needed, returned, resume_handle, debugstr_w(group));
1705 if (resume_handle)
1706 FIXME("resume handle not supported\n");
1708 if (level != SC_ENUM_PROCESS_INFO)
1710 SetLastError( ERROR_INVALID_LEVEL );
1711 return FALSE;
1713 if (!hmngr)
1715 SetLastError( ERROR_INVALID_HANDLE );
1716 return FALSE;
1719 /* make sure we pass a valid buffer pointer */
1720 if (!services || size < sizeof(*services))
1722 buffer = (BYTE *)&dummy_status;
1723 size = sizeof(dummy_status);
1726 __TRY
1728 err = svcctl_EnumServicesStatusExW( hmngr, type, state, buffer, size, needed,
1729 returned, group );
1731 __EXCEPT(rpc_filter)
1733 err = map_exception_code( GetExceptionCode() );
1735 __ENDTRY
1737 if (err != ERROR_SUCCESS)
1739 SetLastError( err );
1740 return FALSE;
1743 for (i = 0; i < *returned; i++)
1745 /* convert buffer offsets into pointers */
1746 services[i].lpServiceName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpServiceName);
1747 if (services[i].lpDisplayName)
1748 services[i].lpDisplayName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpDisplayName);
1751 return TRUE;
1754 /******************************************************************************
1755 * GetServiceKeyNameA [ADVAPI32.@]
1757 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1758 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1760 LPWSTR lpDisplayNameW, lpServiceNameW;
1761 DWORD sizeW;
1762 BOOL ret = FALSE;
1764 TRACE("%p %s %p %p\n", hSCManager,
1765 debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1767 lpDisplayNameW = SERV_dup(lpDisplayName);
1768 if (lpServiceName)
1769 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1770 else
1771 lpServiceNameW = NULL;
1773 sizeW = *lpcchBuffer;
1774 if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
1776 if (lpServiceName && *lpcchBuffer)
1777 lpServiceName[0] = 0;
1778 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1779 goto cleanup;
1782 if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
1783 *lpcchBuffer, NULL, NULL ))
1785 if (*lpcchBuffer && lpServiceName)
1786 lpServiceName[0] = 0;
1787 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
1788 goto cleanup;
1791 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1792 ret = TRUE;
1794 cleanup:
1795 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1796 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1797 return ret;
1800 /******************************************************************************
1801 * GetServiceKeyNameW [ADVAPI32.@]
1803 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1804 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1806 DWORD err;
1807 WCHAR buffer[2];
1808 DWORD size;
1810 TRACE("%p %s %p %p\n", hSCManager,
1811 debugstr_w(lpDisplayName), lpServiceName, lpcchBuffer);
1813 if (!hSCManager)
1815 SetLastError( ERROR_INVALID_HANDLE );
1816 return 0;
1819 /* provide a buffer if the caller didn't */
1820 if (!lpServiceName || *lpcchBuffer < 2)
1822 lpServiceName = buffer;
1823 /* A size of 1 would be enough, but tests show that Windows returns 2,
1824 * probably because of a WCHAR/bytes mismatch in their code.
1826 *lpcchBuffer = 2;
1829 /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
1830 * includes the nul-terminator on input. */
1831 size = *lpcchBuffer - 1;
1833 __TRY
1835 err = svcctl_GetServiceKeyNameW(hSCManager, lpDisplayName, lpServiceName,
1836 &size);
1838 __EXCEPT(rpc_filter)
1840 err = map_exception_code(GetExceptionCode());
1842 __ENDTRY
1844 /* The value of *lpcchBuffer excludes nul-terminator on output. */
1845 if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
1846 *lpcchBuffer = size;
1848 if (err)
1849 SetLastError(err);
1850 return err == ERROR_SUCCESS;
1853 /******************************************************************************
1854 * QueryServiceLockStatusA [ADVAPI32.@]
1856 BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
1857 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1858 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1860 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1862 return FALSE;
1865 /******************************************************************************
1866 * QueryServiceLockStatusW [ADVAPI32.@]
1868 BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
1869 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1870 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1872 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1874 return FALSE;
1877 /******************************************************************************
1878 * GetServiceDisplayNameA [ADVAPI32.@]
1880 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1881 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1883 LPWSTR lpServiceNameW, lpDisplayNameW;
1884 DWORD sizeW;
1885 BOOL ret = FALSE;
1887 TRACE("%p %s %p %p\n", hSCManager,
1888 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1890 lpServiceNameW = SERV_dup(lpServiceName);
1891 if (lpDisplayName)
1892 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1893 else
1894 lpDisplayNameW = NULL;
1896 sizeW = *lpcchBuffer;
1897 if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
1899 if (lpDisplayName && *lpcchBuffer)
1900 lpDisplayName[0] = 0;
1901 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1902 goto cleanup;
1905 if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
1906 *lpcchBuffer, NULL, NULL ))
1908 if (*lpcchBuffer && lpDisplayName)
1909 lpDisplayName[0] = 0;
1910 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
1911 goto cleanup;
1914 /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
1915 * (but if the function succeeded it means that is a good upper estimation of the size) */
1916 ret = TRUE;
1918 cleanup:
1919 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1920 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1921 return ret;
1924 /******************************************************************************
1925 * GetServiceDisplayNameW [ADVAPI32.@]
1927 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1928 LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1930 DWORD err;
1931 DWORD size;
1932 WCHAR buffer[2];
1934 TRACE("%p %s %p %p\n", hSCManager,
1935 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1937 if (!hSCManager)
1939 SetLastError( ERROR_INVALID_HANDLE );
1940 return 0;
1943 /* provide a buffer if the caller didn't */
1944 if (!lpDisplayName || *lpcchBuffer < 2)
1946 lpDisplayName = buffer;
1947 /* A size of 1 would be enough, but tests show that Windows returns 2,
1948 * probably because of a WCHAR/bytes mismatch in their code.
1950 *lpcchBuffer = 2;
1953 /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
1954 * includes the nul-terminator on input. */
1955 size = *lpcchBuffer - 1;
1957 __TRY
1959 err = svcctl_GetServiceDisplayNameW(hSCManager, lpServiceName, lpDisplayName,
1960 &size);
1962 __EXCEPT(rpc_filter)
1964 err = map_exception_code(GetExceptionCode());
1966 __ENDTRY
1968 /* The value of *lpcchBuffer excludes nul-terminator on output. */
1969 if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
1970 *lpcchBuffer = size;
1972 if (err)
1973 SetLastError(err);
1974 return err == ERROR_SUCCESS;
1977 /******************************************************************************
1978 * ChangeServiceConfigW [ADVAPI32.@]
1980 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1981 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1982 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
1983 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
1985 DWORD cb_pwd;
1986 DWORD err;
1988 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
1989 hService, dwServiceType, dwStartType, dwErrorControl,
1990 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
1991 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
1992 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
1994 cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
1996 __TRY
1998 err = svcctl_ChangeServiceConfigW(hService, dwServiceType,
1999 dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId,
2000 (const BYTE *)lpDependencies, multisz_cb(lpDependencies), lpServiceStartName,
2001 (const BYTE *)lpPassword, cb_pwd, lpDisplayName);
2003 __EXCEPT(rpc_filter)
2005 err = map_exception_code(GetExceptionCode());
2007 __ENDTRY
2009 if (err != ERROR_SUCCESS)
2010 SetLastError(err);
2012 return err == ERROR_SUCCESS;
2015 /******************************************************************************
2016 * ChangeServiceConfigA [ADVAPI32.@]
2018 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
2019 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
2020 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
2021 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
2023 LPWSTR wBinaryPathName, wLoadOrderGroup, wDependencies;
2024 LPWSTR wServiceStartName, wPassword, wDisplayName;
2025 BOOL r;
2027 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2028 hService, dwServiceType, dwStartType, dwErrorControl,
2029 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
2030 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
2031 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
2033 wBinaryPathName = SERV_dup( lpBinaryPathName );
2034 wLoadOrderGroup = SERV_dup( lpLoadOrderGroup );
2035 wDependencies = SERV_dupmulti( lpDependencies );
2036 wServiceStartName = SERV_dup( lpServiceStartName );
2037 wPassword = SERV_dup( lpPassword );
2038 wDisplayName = SERV_dup( lpDisplayName );
2040 r = ChangeServiceConfigW( hService, dwServiceType,
2041 dwStartType, dwErrorControl, wBinaryPathName,
2042 wLoadOrderGroup, lpdwTagId, wDependencies,
2043 wServiceStartName, wPassword, wDisplayName);
2045 HeapFree( GetProcessHeap(), 0, wBinaryPathName );
2046 HeapFree( GetProcessHeap(), 0, wLoadOrderGroup );
2047 HeapFree( GetProcessHeap(), 0, wDependencies );
2048 HeapFree( GetProcessHeap(), 0, wServiceStartName );
2049 HeapFree( GetProcessHeap(), 0, wPassword );
2050 HeapFree( GetProcessHeap(), 0, wDisplayName );
2052 return r;
2055 /******************************************************************************
2056 * ChangeServiceConfig2A [ADVAPI32.@]
2058 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
2059 LPVOID lpInfo)
2061 BOOL r = FALSE;
2063 TRACE("%p %d %p\n",hService, dwInfoLevel, lpInfo);
2065 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2067 LPSERVICE_DESCRIPTIONA sd = lpInfo;
2068 SERVICE_DESCRIPTIONW sdw;
2070 sdw.lpDescription = SERV_dup( sd->lpDescription );
2072 r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
2074 HeapFree( GetProcessHeap(), 0, sdw.lpDescription );
2076 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
2078 LPSERVICE_FAILURE_ACTIONSA fa = lpInfo;
2079 SERVICE_FAILURE_ACTIONSW faw;
2081 faw.dwResetPeriod = fa->dwResetPeriod;
2082 faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg );
2083 faw.lpCommand = SERV_dup( fa->lpCommand );
2084 faw.cActions = fa->cActions;
2085 faw.lpsaActions = fa->lpsaActions;
2087 r = ChangeServiceConfig2W( hService, dwInfoLevel, &faw );
2089 HeapFree( GetProcessHeap(), 0, faw.lpRebootMsg );
2090 HeapFree( GetProcessHeap(), 0, faw.lpCommand );
2092 else if (dwInfoLevel == SERVICE_CONFIG_PRESHUTDOWN_INFO)
2094 r = ChangeServiceConfig2W( hService, dwInfoLevel, lpInfo);
2096 else
2097 SetLastError( ERROR_INVALID_PARAMETER );
2099 return r;
2102 /******************************************************************************
2103 * ChangeServiceConfig2W [ADVAPI32.@]
2105 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
2106 LPVOID lpInfo)
2108 DWORD err;
2110 __TRY
2112 err = svcctl_ChangeServiceConfig2W( hService, dwInfoLevel, lpInfo );
2114 __EXCEPT(rpc_filter)
2116 err = map_exception_code(GetExceptionCode());
2118 __ENDTRY
2120 if (err != ERROR_SUCCESS)
2121 SetLastError(err);
2123 return err == ERROR_SUCCESS;
2126 /******************************************************************************
2127 * QueryServiceObjectSecurity [ADVAPI32.@]
2129 BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
2130 SECURITY_INFORMATION dwSecurityInformation,
2131 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2132 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2134 SECURITY_DESCRIPTOR descriptor;
2135 DWORD size;
2136 BOOL succ;
2137 ACL acl;
2139 FIXME("%p %d %p %u %p - semi-stub\n", hService, dwSecurityInformation,
2140 lpSecurityDescriptor, cbBufSize, pcbBytesNeeded);
2142 if (dwSecurityInformation != DACL_SECURITY_INFORMATION)
2143 FIXME("information %d not supported\n", dwSecurityInformation);
2145 InitializeSecurityDescriptor(&descriptor, SECURITY_DESCRIPTOR_REVISION);
2147 InitializeAcl(&acl, sizeof(ACL), ACL_REVISION);
2148 SetSecurityDescriptorDacl(&descriptor, TRUE, &acl, TRUE);
2150 size = cbBufSize;
2151 succ = MakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
2152 *pcbBytesNeeded = size;
2153 return succ;
2156 /******************************************************************************
2157 * SetServiceObjectSecurity [ADVAPI32.@]
2159 BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService,
2160 SECURITY_INFORMATION dwSecurityInformation,
2161 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2163 FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
2164 return TRUE;
2167 /******************************************************************************
2168 * SetServiceBits [ADVAPI32.@]
2170 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
2171 DWORD dwServiceBits,
2172 BOOL bSetBitsOn,
2173 BOOL bUpdateImmediately)
2175 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
2176 bSetBitsOn, bUpdateImmediately);
2177 return TRUE;
2180 /* thunk for calling the RegisterServiceCtrlHandler handler function */
2181 static DWORD WINAPI ctrl_handler_thunk( DWORD control, DWORD type, void *data, void *context )
2183 LPHANDLER_FUNCTION func = context;
2185 func( control );
2186 return ERROR_SUCCESS;
2189 /******************************************************************************
2190 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
2192 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER_FUNCTION handler )
2194 return RegisterServiceCtrlHandlerExA( name, ctrl_handler_thunk, handler );
2197 /******************************************************************************
2198 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
2200 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLER_FUNCTION handler )
2202 return RegisterServiceCtrlHandlerExW( name, ctrl_handler_thunk, handler );
2205 /******************************************************************************
2206 * RegisterServiceCtrlHandlerExA [ADVAPI32.@]
2208 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDLER_FUNCTION_EX handler, LPVOID context )
2210 LPWSTR nameW;
2211 SERVICE_STATUS_HANDLE ret;
2213 nameW = SERV_dup(name);
2214 ret = RegisterServiceCtrlHandlerExW( nameW, handler, context );
2215 HeapFree( GetProcessHeap(), 0, nameW );
2216 return ret;
2219 /******************************************************************************
2220 * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
2222 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
2223 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2225 service_data *service;
2226 SC_HANDLE hService = 0;
2227 BOOL found = FALSE;
2229 TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
2231 EnterCriticalSection( &service_cs );
2232 if ((service = find_service_by_name( lpServiceName )))
2234 service->handler = lpHandlerProc;
2235 service->context = lpContext;
2236 hService = service->handle;
2237 found = TRUE;
2239 LeaveCriticalSection( &service_cs );
2241 if (!found) SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
2243 return (SERVICE_STATUS_HANDLE)hService;
2246 /******************************************************************************
2247 * EnumDependentServicesA [ADVAPI32.@]
2249 BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState,
2250 LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize,
2251 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2253 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2254 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2256 *lpServicesReturned = 0;
2257 return TRUE;
2260 /******************************************************************************
2261 * EnumDependentServicesW [ADVAPI32.@]
2263 BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
2264 LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize,
2265 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2267 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2268 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2270 *lpServicesReturned = 0;
2271 return TRUE;