dpvoice: New stub dll.
[wine/multimedia.git] / dlls / advapi32 / service.c
blob23ff2f048a1ea3ba456635d9ed1a54693892d70d
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 heap_alloc(len);
57 void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
59 heap_free(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 = heap_alloc( 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 = heap_alloc( 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 = heap_alloc(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 heap_free(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 = heap_alloc((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 heap_free(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 = heap_alloc(lenA);
312 WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL);
314 argv = heap_alloc((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 heap_free(argv);
321 heap_free(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 heap_free(service->args);
340 service->args = heap_alloc(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 = heap_alloc( 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 heap_free( data );
400 break;
402 if (count != data_size)
404 ERR( "partial pipe read %u/%u\n", count, data_size );
405 heap_free( 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 heap_free( data );
448 CloseHandle( disp->pipe );
449 CloseServiceHandle( disp->manager );
450 heap_free( 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 = heap_alloc( 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 heap_free( 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 heap_free( 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 = heap_alloc( 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 = heap_alloc_zero( 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 = heap_alloc( 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 = heap_alloc_zero( 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 machineW, databaseW;
771 SC_HANDLE ret;
773 machineW = SERV_dup(lpMachineName);
774 databaseW = SERV_dup(lpDatabaseName);
775 ret = OpenSCManagerW(machineW, databaseW, dwDesiredAccess);
776 heap_free(databaseW);
777 heap_free(machineW);
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 heap_free(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 heap_free( lpServiceNameW );
1063 heap_free( lpDisplayNameW );
1064 heap_free( lpBinaryPathNameW );
1065 heap_free( lpLoadOrderGroupW );
1066 heap_free( lpDependenciesW );
1067 heap_free( lpServiceStartNameW );
1068 heap_free( 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 = heap_alloc( dwNumServiceArgs*sizeof(LPWSTR) );
1146 for(i=0; i<dwNumServiceArgs; i++)
1147 lpwstr[i]=SERV_dup(lpServiceArgVectors[i]);
1149 r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
1151 if (dwNumServiceArgs)
1153 for(i=0; i<dwNumServiceArgs; i++)
1154 heap_free(lpwstr[i]);
1155 heap_free(lpwstr);
1158 return r;
1162 /******************************************************************************
1163 * StartServiceW [ADVAPI32.@]
1165 * See StartServiceA.
1167 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1168 LPCWSTR *lpServiceArgVectors)
1170 DWORD err;
1172 TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1174 __TRY
1176 err = svcctl_StartServiceW(hService, dwNumServiceArgs, lpServiceArgVectors);
1178 __EXCEPT(rpc_filter)
1180 err = map_exception_code(GetExceptionCode());
1182 __ENDTRY
1183 if (err != ERROR_SUCCESS)
1185 SetLastError(err);
1186 return FALSE;
1189 return TRUE;
1192 /******************************************************************************
1193 * QueryServiceStatus [ADVAPI32.@]
1195 * PARAMS
1196 * hService [I] Handle to service to get information about
1197 * lpservicestatus [O] buffer to receive the status information for the service
1200 BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
1201 LPSERVICE_STATUS lpservicestatus)
1203 SERVICE_STATUS_PROCESS SvcStatusData;
1204 BOOL ret;
1205 DWORD dummy;
1207 TRACE("%p %p\n", hService, lpservicestatus);
1209 if (!hService)
1211 SetLastError(ERROR_INVALID_HANDLE);
1212 return FALSE;
1214 if (!lpservicestatus)
1216 SetLastError(ERROR_INVALID_ADDRESS);
1217 return FALSE;
1220 ret = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&SvcStatusData,
1221 sizeof(SERVICE_STATUS_PROCESS), &dummy);
1222 if (ret) memcpy(lpservicestatus, &SvcStatusData, sizeof(SERVICE_STATUS)) ;
1223 return ret;
1227 /******************************************************************************
1228 * QueryServiceStatusEx [ADVAPI32.@]
1230 * Get information about a service.
1232 * PARAMS
1233 * hService [I] Handle to service to get information about
1234 * InfoLevel [I] Level of information to get
1235 * lpBuffer [O] Destination for requested information
1236 * cbBufSize [I] Size of lpBuffer in bytes
1237 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1239 * RETURNS
1240 * Success: TRUE
1241 * FAILURE: FALSE
1243 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1244 LPBYTE lpBuffer, DWORD cbBufSize,
1245 LPDWORD pcbBytesNeeded)
1247 DWORD err;
1249 TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1251 if (InfoLevel != SC_STATUS_PROCESS_INFO)
1253 err = ERROR_INVALID_LEVEL;
1255 else if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
1257 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
1258 err = ERROR_INSUFFICIENT_BUFFER;
1260 else
1262 __TRY
1264 err = svcctl_QueryServiceStatusEx(hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1266 __EXCEPT(rpc_filter)
1268 err = map_exception_code(GetExceptionCode());
1270 __ENDTRY
1272 if (err != ERROR_SUCCESS)
1274 SetLastError(err);
1275 return FALSE;
1277 return TRUE;
1280 /******************************************************************************
1281 * QueryServiceConfigA [ADVAPI32.@]
1283 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1284 DWORD size, LPDWORD needed )
1286 DWORD n;
1287 LPSTR p, buffer;
1288 BOOL ret;
1289 QUERY_SERVICE_CONFIGW *configW;
1291 TRACE("%p %p %d %p\n", hService, config, size, needed);
1293 if (!(buffer = heap_alloc( 2 * size )))
1295 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1296 return FALSE;
1298 configW = (QUERY_SERVICE_CONFIGW *)buffer;
1299 ret = QueryServiceConfigW( hService, configW, 2 * size, needed );
1300 if (!ret) goto done;
1302 config->dwServiceType = configW->dwServiceType;
1303 config->dwStartType = configW->dwStartType;
1304 config->dwErrorControl = configW->dwErrorControl;
1305 config->lpBinaryPathName = NULL;
1306 config->lpLoadOrderGroup = NULL;
1307 config->dwTagId = configW->dwTagId;
1308 config->lpDependencies = NULL;
1309 config->lpServiceStartName = NULL;
1310 config->lpDisplayName = NULL;
1312 p = (LPSTR)(config + 1);
1313 n = size - sizeof(*config);
1314 ret = FALSE;
1316 #define MAP_STR(str) \
1317 do { \
1318 if (configW->str) \
1320 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1321 if (!sz) goto done; \
1322 config->str = p; \
1323 p += sz; \
1324 n -= sz; \
1326 } while (0)
1328 MAP_STR( lpBinaryPathName );
1329 MAP_STR( lpLoadOrderGroup );
1330 MAP_STR( lpDependencies );
1331 MAP_STR( lpServiceStartName );
1332 MAP_STR( lpDisplayName );
1333 #undef MAP_STR
1335 *needed = p - (LPSTR)config;
1336 ret = TRUE;
1338 done:
1339 heap_free( buffer );
1340 return ret;
1343 static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
1345 DWORD cb;
1347 if (!*string_ptr)
1349 cb = sizeof(WCHAR);
1350 memset(*buf, 0, cb);
1352 else
1354 cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
1355 memcpy(*buf, *string_ptr, cb);
1356 MIDL_user_free(*string_ptr);
1359 *string_ptr = (LPWSTR)*buf;
1360 *buf += cb;
1362 return cb;
1365 static DWORD size_string(LPCWSTR string)
1367 return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
1370 /******************************************************************************
1371 * QueryServiceConfigW [ADVAPI32.@]
1373 BOOL WINAPI
1374 QueryServiceConfigW( SC_HANDLE hService,
1375 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1376 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1378 QUERY_SERVICE_CONFIGW config;
1379 DWORD total;
1380 DWORD err;
1381 BYTE *bufpos;
1383 TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1384 cbBufSize, pcbBytesNeeded);
1386 memset(&config, 0, sizeof(config));
1388 __TRY
1390 err = svcctl_QueryServiceConfigW(hService, &config);
1392 __EXCEPT(rpc_filter)
1394 err = map_exception_code(GetExceptionCode());
1396 __ENDTRY
1398 if (err != ERROR_SUCCESS)
1400 TRACE("services.exe: error %u\n", err);
1401 SetLastError(err);
1402 return FALSE;
1405 /* calculate the size required first */
1406 total = sizeof (QUERY_SERVICE_CONFIGW);
1407 total += size_string(config.lpBinaryPathName);
1408 total += size_string(config.lpLoadOrderGroup);
1409 total += size_string(config.lpDependencies);
1410 total += size_string(config.lpServiceStartName);
1411 total += size_string(config.lpDisplayName);
1413 *pcbBytesNeeded = total;
1415 /* if there's not enough memory, return an error */
1416 if( total > cbBufSize )
1418 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1419 MIDL_user_free(config.lpBinaryPathName);
1420 MIDL_user_free(config.lpLoadOrderGroup);
1421 MIDL_user_free(config.lpDependencies);
1422 MIDL_user_free(config.lpServiceStartName);
1423 MIDL_user_free(config.lpDisplayName);
1424 return FALSE;
1427 *lpServiceConfig = config;
1428 bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
1429 move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
1430 move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
1431 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
1432 move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
1433 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
1435 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1436 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1437 TRACE("Dependencies = %s\n", debugstr_w(lpServiceConfig->lpDependencies) );
1438 TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig->lpServiceStartName) );
1439 TRACE("Display name = %s\n", debugstr_w(lpServiceConfig->lpDisplayName) );
1441 return TRUE;
1444 /******************************************************************************
1445 * QueryServiceConfig2A [ADVAPI32.@]
1447 * Note
1448 * observed under win2k:
1449 * The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
1450 * required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
1452 BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1453 DWORD size, LPDWORD needed)
1455 BOOL ret;
1456 LPBYTE bufferW = NULL;
1458 if(buffer && size)
1459 bufferW = heap_alloc(size);
1461 ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
1462 if(!ret) goto cleanup;
1464 switch(dwLevel) {
1465 case SERVICE_CONFIG_DESCRIPTION:
1466 if (buffer && bufferW) {
1467 LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
1468 LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
1469 if (configW->lpDescription && (size > sizeof(SERVICE_DESCRIPTIONA))) {
1470 DWORD sz;
1471 configA->lpDescription = (LPSTR)(configA + 1);
1472 sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
1473 configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
1474 if (!sz) {
1475 FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1476 ret = FALSE;
1477 configA->lpDescription = NULL;
1480 else configA->lpDescription = NULL;
1482 break;
1483 case SERVICE_CONFIG_PRESHUTDOWN_INFO:
1484 if (buffer && bufferW && *needed<=size)
1485 memcpy(buffer, bufferW, *needed);
1486 break;
1487 default:
1488 FIXME("conversation W->A not implemented for level %d\n", dwLevel);
1489 ret = FALSE;
1490 break;
1493 cleanup:
1494 heap_free( bufferW);
1495 return ret;
1498 /******************************************************************************
1499 * QueryServiceConfig2W [ADVAPI32.@]
1501 * See QueryServiceConfig2A.
1503 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1504 DWORD size, LPDWORD needed)
1506 DWORD err;
1508 if(dwLevel!=SERVICE_CONFIG_DESCRIPTION && dwLevel!=SERVICE_CONFIG_PRESHUTDOWN_INFO) {
1509 FIXME("Level %d not implemented\n", dwLevel);
1510 SetLastError(ERROR_INVALID_LEVEL);
1511 return FALSE;
1514 if(!buffer && size) {
1515 SetLastError(ERROR_INVALID_ADDRESS);
1516 return FALSE;
1519 TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
1521 __TRY
1523 err = svcctl_QueryServiceConfig2W(hService, dwLevel, buffer, size, needed);
1525 __EXCEPT(rpc_filter)
1527 err = map_exception_code(GetExceptionCode());
1529 __ENDTRY
1531 if (err != ERROR_SUCCESS)
1533 SetLastError( err );
1534 return FALSE;
1537 switch (dwLevel)
1539 case SERVICE_CONFIG_DESCRIPTION:
1540 if (buffer)
1542 SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
1543 if (descr->lpDescription) /* make it an absolute pointer */
1544 descr->lpDescription = (WCHAR *)(buffer + (ULONG_PTR)descr->lpDescription);
1545 break;
1549 return TRUE;
1552 /******************************************************************************
1553 * EnumServicesStatusA [ADVAPI32.@]
1555 BOOL WINAPI
1556 EnumServicesStatusA( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSA
1557 services, DWORD size, LPDWORD needed, LPDWORD returned,
1558 LPDWORD resume_handle )
1560 BOOL ret;
1561 unsigned int i;
1562 ENUM_SERVICE_STATUSW *servicesW = NULL;
1563 DWORD sz, n;
1564 char *p;
1566 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
1567 returned, resume_handle);
1569 sz = max( 2 * size, sizeof(*servicesW) );
1570 if (!(servicesW = heap_alloc( sz )))
1572 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1573 return FALSE;
1576 ret = EnumServicesStatusW( hmngr, type, state, servicesW, sz, needed, returned, resume_handle );
1577 if (!ret) goto done;
1579 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUSA);
1580 n = size - (p - (char *)services);
1581 ret = FALSE;
1582 for (i = 0; i < *returned; i++)
1584 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
1585 if (!sz) goto done;
1586 services[i].lpServiceName = p;
1587 p += sz;
1588 n -= sz;
1589 if (servicesW[i].lpDisplayName)
1591 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
1592 if (!sz) goto done;
1593 services[i].lpDisplayName = p;
1594 p += sz;
1595 n -= sz;
1597 else services[i].lpDisplayName = NULL;
1598 services[i].ServiceStatus = servicesW[i].ServiceStatus;
1601 ret = TRUE;
1603 done:
1604 heap_free( servicesW );
1605 return ret;
1608 /******************************************************************************
1609 * EnumServicesStatusW [ADVAPI32.@]
1611 BOOL WINAPI
1612 EnumServicesStatusW( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSW
1613 services, DWORD size, LPDWORD needed, LPDWORD returned,
1614 LPDWORD resume_handle )
1616 DWORD err, i;
1617 ENUM_SERVICE_STATUSW dummy_status;
1619 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
1620 returned, resume_handle);
1622 if (resume_handle)
1623 FIXME("resume handle not supported\n");
1625 if (!hmngr)
1627 SetLastError( ERROR_INVALID_HANDLE );
1628 return FALSE;
1631 /* make sure we pass a valid pointer */
1632 if (!services || size < sizeof(*services))
1634 services = &dummy_status;
1635 size = sizeof(dummy_status);
1638 __TRY
1640 err = svcctl_EnumServicesStatusW( hmngr, type, state, (BYTE *)services, size, needed, returned );
1642 __EXCEPT(rpc_filter)
1644 err = map_exception_code( GetExceptionCode() );
1646 __ENDTRY
1648 if (err != ERROR_SUCCESS)
1650 SetLastError( err );
1651 return FALSE;
1654 for (i = 0; i < *returned; i++)
1656 /* convert buffer offsets into pointers */
1657 services[i].lpServiceName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpServiceName);
1658 if (services[i].lpDisplayName)
1659 services[i].lpDisplayName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpDisplayName);
1662 return TRUE;
1665 /******************************************************************************
1666 * EnumServicesStatusExA [ADVAPI32.@]
1668 BOOL WINAPI
1669 EnumServicesStatusExA( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state,
1670 LPBYTE buffer, DWORD size, LPDWORD needed, LPDWORD returned,
1671 LPDWORD resume_handle, LPCSTR group )
1673 BOOL ret;
1674 unsigned int i;
1675 ENUM_SERVICE_STATUS_PROCESSA *services = (ENUM_SERVICE_STATUS_PROCESSA *)buffer;
1676 ENUM_SERVICE_STATUS_PROCESSW *servicesW = NULL;
1677 WCHAR *groupW = NULL;
1678 DWORD sz, n;
1679 char *p;
1681 TRACE("%p %u 0x%x 0x%x %p %u %p %p %p %s\n", hmngr, level, type, state, buffer,
1682 size, needed, returned, resume_handle, debugstr_a(group));
1684 sz = max( 2 * size, sizeof(*servicesW) );
1685 if (!(servicesW = heap_alloc( sz )))
1687 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1688 return FALSE;
1690 if (group)
1692 int len = MultiByteToWideChar( CP_ACP, 0, group, -1, NULL, 0 );
1693 if (!(groupW = heap_alloc( len * sizeof(WCHAR) )))
1695 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1696 heap_free( servicesW );
1697 return FALSE;
1699 MultiByteToWideChar( CP_ACP, 0, group, -1, groupW, len * sizeof(WCHAR) );
1702 ret = EnumServicesStatusExW( hmngr, level, type, state, (BYTE *)servicesW, sz,
1703 needed, returned, resume_handle, groupW );
1704 if (!ret) goto done;
1706 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUS_PROCESSA);
1707 n = size - (p - (char *)services);
1708 ret = FALSE;
1709 for (i = 0; i < *returned; i++)
1711 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
1712 if (!sz) goto done;
1713 services[i].lpServiceName = p;
1714 p += sz;
1715 n -= sz;
1716 if (servicesW[i].lpDisplayName)
1718 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
1719 if (!sz) goto done;
1720 services[i].lpDisplayName = p;
1721 p += sz;
1722 n -= sz;
1724 else services[i].lpDisplayName = NULL;
1725 services[i].ServiceStatusProcess = servicesW[i].ServiceStatusProcess;
1728 ret = TRUE;
1730 done:
1731 heap_free( servicesW );
1732 heap_free( groupW );
1733 return ret;
1736 /******************************************************************************
1737 * EnumServicesStatusExW [ADVAPI32.@]
1739 BOOL WINAPI
1740 EnumServicesStatusExW( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state,
1741 LPBYTE buffer, DWORD size, LPDWORD needed, LPDWORD returned,
1742 LPDWORD resume_handle, LPCWSTR group )
1744 DWORD err, i;
1745 ENUM_SERVICE_STATUS_PROCESSW dummy_status;
1746 ENUM_SERVICE_STATUS_PROCESSW *services = (ENUM_SERVICE_STATUS_PROCESSW *)buffer;
1748 TRACE("%p %u 0x%x 0x%x %p %u %p %p %p %s\n", hmngr, level, type, state, buffer,
1749 size, needed, returned, resume_handle, debugstr_w(group));
1751 if (resume_handle)
1752 FIXME("resume handle not supported\n");
1754 if (level != SC_ENUM_PROCESS_INFO)
1756 SetLastError( ERROR_INVALID_LEVEL );
1757 return FALSE;
1759 if (!hmngr)
1761 SetLastError( ERROR_INVALID_HANDLE );
1762 return FALSE;
1765 /* make sure we pass a valid buffer pointer */
1766 if (!services || size < sizeof(*services))
1768 buffer = (BYTE *)&dummy_status;
1769 size = sizeof(dummy_status);
1772 __TRY
1774 err = svcctl_EnumServicesStatusExW( hmngr, type, state, buffer, size, needed,
1775 returned, group );
1777 __EXCEPT(rpc_filter)
1779 err = map_exception_code( GetExceptionCode() );
1781 __ENDTRY
1783 if (err != ERROR_SUCCESS)
1785 SetLastError( err );
1786 return FALSE;
1789 for (i = 0; i < *returned; i++)
1791 /* convert buffer offsets into pointers */
1792 services[i].lpServiceName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpServiceName);
1793 if (services[i].lpDisplayName)
1794 services[i].lpDisplayName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpDisplayName);
1797 return TRUE;
1800 /******************************************************************************
1801 * GetServiceKeyNameA [ADVAPI32.@]
1803 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1804 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1806 LPWSTR lpDisplayNameW, lpServiceNameW;
1807 DWORD sizeW;
1808 BOOL ret = FALSE;
1810 TRACE("%p %s %p %p\n", hSCManager,
1811 debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1813 lpDisplayNameW = SERV_dup(lpDisplayName);
1814 if (lpServiceName)
1815 lpServiceNameW = heap_alloc(*lpcchBuffer * sizeof(WCHAR));
1816 else
1817 lpServiceNameW = NULL;
1819 sizeW = *lpcchBuffer;
1820 if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
1822 if (lpServiceName && *lpcchBuffer)
1823 lpServiceName[0] = 0;
1824 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1825 goto cleanup;
1828 if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
1829 *lpcchBuffer, NULL, NULL ))
1831 if (*lpcchBuffer && lpServiceName)
1832 lpServiceName[0] = 0;
1833 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
1834 goto cleanup;
1837 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1838 ret = TRUE;
1840 cleanup:
1841 heap_free(lpServiceNameW);
1842 heap_free(lpDisplayNameW);
1843 return ret;
1846 /******************************************************************************
1847 * GetServiceKeyNameW [ADVAPI32.@]
1849 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1850 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1852 DWORD err;
1853 WCHAR buffer[2];
1854 DWORD size;
1856 TRACE("%p %s %p %p\n", hSCManager,
1857 debugstr_w(lpDisplayName), lpServiceName, lpcchBuffer);
1859 if (!hSCManager)
1861 SetLastError( ERROR_INVALID_HANDLE );
1862 return FALSE;
1865 /* provide a buffer if the caller didn't */
1866 if (!lpServiceName || *lpcchBuffer < 2)
1868 lpServiceName = buffer;
1869 /* A size of 1 would be enough, but tests show that Windows returns 2,
1870 * probably because of a WCHAR/bytes mismatch in their code.
1872 *lpcchBuffer = 2;
1875 /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
1876 * includes the nul-terminator on input. */
1877 size = *lpcchBuffer - 1;
1879 __TRY
1881 err = svcctl_GetServiceKeyNameW(hSCManager, lpDisplayName, lpServiceName,
1882 &size);
1884 __EXCEPT(rpc_filter)
1886 err = map_exception_code(GetExceptionCode());
1888 __ENDTRY
1890 /* The value of *lpcchBuffer excludes nul-terminator on output. */
1891 if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
1892 *lpcchBuffer = size;
1894 if (err)
1895 SetLastError(err);
1896 return err == ERROR_SUCCESS;
1899 /******************************************************************************
1900 * QueryServiceLockStatusA [ADVAPI32.@]
1902 BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
1903 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1904 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1906 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1908 return FALSE;
1911 /******************************************************************************
1912 * QueryServiceLockStatusW [ADVAPI32.@]
1914 BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
1915 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1916 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1918 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1920 return FALSE;
1923 /******************************************************************************
1924 * GetServiceDisplayNameA [ADVAPI32.@]
1926 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1927 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1929 LPWSTR lpServiceNameW, lpDisplayNameW;
1930 DWORD sizeW;
1931 BOOL ret = FALSE;
1933 TRACE("%p %s %p %p\n", hSCManager,
1934 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1936 lpServiceNameW = SERV_dup(lpServiceName);
1937 if (lpDisplayName)
1938 lpDisplayNameW = heap_alloc(*lpcchBuffer * sizeof(WCHAR));
1939 else
1940 lpDisplayNameW = NULL;
1942 sizeW = *lpcchBuffer;
1943 if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
1945 if (lpDisplayName && *lpcchBuffer)
1946 lpDisplayName[0] = 0;
1947 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1948 goto cleanup;
1951 if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
1952 *lpcchBuffer, NULL, NULL ))
1954 if (*lpcchBuffer && lpDisplayName)
1955 lpDisplayName[0] = 0;
1956 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
1957 goto cleanup;
1960 /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
1961 * (but if the function succeeded it means that is a good upper estimation of the size) */
1962 ret = TRUE;
1964 cleanup:
1965 heap_free(lpDisplayNameW);
1966 heap_free(lpServiceNameW);
1967 return ret;
1970 /******************************************************************************
1971 * GetServiceDisplayNameW [ADVAPI32.@]
1973 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1974 LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1976 DWORD err;
1977 DWORD size;
1978 WCHAR buffer[2];
1980 TRACE("%p %s %p %p\n", hSCManager,
1981 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1983 if (!hSCManager)
1985 SetLastError( ERROR_INVALID_HANDLE );
1986 return FALSE;
1989 /* provide a buffer if the caller didn't */
1990 if (!lpDisplayName || *lpcchBuffer < 2)
1992 lpDisplayName = buffer;
1993 /* A size of 1 would be enough, but tests show that Windows returns 2,
1994 * probably because of a WCHAR/bytes mismatch in their code.
1996 *lpcchBuffer = 2;
1999 /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
2000 * includes the nul-terminator on input. */
2001 size = *lpcchBuffer - 1;
2003 __TRY
2005 err = svcctl_GetServiceDisplayNameW(hSCManager, lpServiceName, lpDisplayName,
2006 &size);
2008 __EXCEPT(rpc_filter)
2010 err = map_exception_code(GetExceptionCode());
2012 __ENDTRY
2014 /* The value of *lpcchBuffer excludes nul-terminator on output. */
2015 if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
2016 *lpcchBuffer = size;
2018 if (err)
2019 SetLastError(err);
2020 return err == ERROR_SUCCESS;
2023 /******************************************************************************
2024 * ChangeServiceConfigW [ADVAPI32.@]
2026 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
2027 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
2028 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
2029 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
2031 DWORD cb_pwd;
2032 DWORD err;
2034 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2035 hService, dwServiceType, dwStartType, dwErrorControl,
2036 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
2037 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
2038 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
2040 cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
2042 __TRY
2044 err = svcctl_ChangeServiceConfigW(hService, dwServiceType,
2045 dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId,
2046 (const BYTE *)lpDependencies, multisz_cb(lpDependencies), lpServiceStartName,
2047 (const BYTE *)lpPassword, cb_pwd, lpDisplayName);
2049 __EXCEPT(rpc_filter)
2051 err = map_exception_code(GetExceptionCode());
2053 __ENDTRY
2055 if (err != ERROR_SUCCESS)
2056 SetLastError(err);
2058 return err == ERROR_SUCCESS;
2061 /******************************************************************************
2062 * ChangeServiceConfigA [ADVAPI32.@]
2064 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
2065 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
2066 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
2067 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
2069 LPWSTR wBinaryPathName, wLoadOrderGroup, wDependencies;
2070 LPWSTR wServiceStartName, wPassword, wDisplayName;
2071 BOOL r;
2073 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2074 hService, dwServiceType, dwStartType, dwErrorControl,
2075 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
2076 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
2077 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
2079 wBinaryPathName = SERV_dup( lpBinaryPathName );
2080 wLoadOrderGroup = SERV_dup( lpLoadOrderGroup );
2081 wDependencies = SERV_dupmulti( lpDependencies );
2082 wServiceStartName = SERV_dup( lpServiceStartName );
2083 wPassword = SERV_dup( lpPassword );
2084 wDisplayName = SERV_dup( lpDisplayName );
2086 r = ChangeServiceConfigW( hService, dwServiceType,
2087 dwStartType, dwErrorControl, wBinaryPathName,
2088 wLoadOrderGroup, lpdwTagId, wDependencies,
2089 wServiceStartName, wPassword, wDisplayName);
2091 heap_free( wBinaryPathName );
2092 heap_free( wLoadOrderGroup );
2093 heap_free( wDependencies );
2094 heap_free( wServiceStartName );
2095 heap_free( wPassword );
2096 heap_free( wDisplayName );
2098 return r;
2101 /******************************************************************************
2102 * ChangeServiceConfig2A [ADVAPI32.@]
2104 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
2105 LPVOID lpInfo)
2107 BOOL r = FALSE;
2109 TRACE("%p %d %p\n",hService, dwInfoLevel, lpInfo);
2111 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2113 LPSERVICE_DESCRIPTIONA sd = lpInfo;
2114 SERVICE_DESCRIPTIONW sdw;
2116 sdw.lpDescription = SERV_dup( sd->lpDescription );
2118 r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
2120 heap_free( sdw.lpDescription );
2122 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
2124 LPSERVICE_FAILURE_ACTIONSA fa = lpInfo;
2125 SERVICE_FAILURE_ACTIONSW faw;
2127 faw.dwResetPeriod = fa->dwResetPeriod;
2128 faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg );
2129 faw.lpCommand = SERV_dup( fa->lpCommand );
2130 faw.cActions = fa->cActions;
2131 faw.lpsaActions = fa->lpsaActions;
2133 r = ChangeServiceConfig2W( hService, dwInfoLevel, &faw );
2135 heap_free( faw.lpRebootMsg );
2136 heap_free( faw.lpCommand );
2138 else if (dwInfoLevel == SERVICE_CONFIG_PRESHUTDOWN_INFO)
2140 r = ChangeServiceConfig2W( hService, dwInfoLevel, lpInfo);
2142 else
2143 SetLastError( ERROR_INVALID_PARAMETER );
2145 return r;
2148 /******************************************************************************
2149 * ChangeServiceConfig2W [ADVAPI32.@]
2151 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
2152 LPVOID lpInfo)
2154 DWORD err;
2156 __TRY
2158 err = svcctl_ChangeServiceConfig2W( hService, dwInfoLevel, lpInfo );
2160 __EXCEPT(rpc_filter)
2162 err = map_exception_code(GetExceptionCode());
2164 __ENDTRY
2166 if (err != ERROR_SUCCESS)
2167 SetLastError(err);
2169 return err == ERROR_SUCCESS;
2172 NTSTATUS SERV_QueryServiceObjectSecurity(SC_HANDLE hService,
2173 SECURITY_INFORMATION dwSecurityInformation,
2174 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2175 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2177 SECURITY_DESCRIPTOR descriptor;
2178 NTSTATUS status;
2179 DWORD size;
2180 ACL acl;
2182 FIXME("%p %d %p %u %p - semi-stub\n", hService, dwSecurityInformation,
2183 lpSecurityDescriptor, cbBufSize, pcbBytesNeeded);
2185 if (dwSecurityInformation != DACL_SECURITY_INFORMATION)
2186 FIXME("information %d not supported\n", dwSecurityInformation);
2188 InitializeSecurityDescriptor(&descriptor, SECURITY_DESCRIPTOR_REVISION);
2190 InitializeAcl(&acl, sizeof(ACL), ACL_REVISION);
2191 SetSecurityDescriptorDacl(&descriptor, TRUE, &acl, TRUE);
2193 size = cbBufSize;
2194 status = RtlMakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
2195 *pcbBytesNeeded = size;
2196 return status;
2199 /******************************************************************************
2200 * QueryServiceObjectSecurity [ADVAPI32.@]
2202 BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
2203 SECURITY_INFORMATION dwSecurityInformation,
2204 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2205 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2207 NTSTATUS status = SERV_QueryServiceObjectSecurity(hService, dwSecurityInformation, lpSecurityDescriptor,
2208 cbBufSize, pcbBytesNeeded);
2209 if (status != STATUS_SUCCESS)
2211 SetLastError(RtlNtStatusToDosError(status));
2212 return FALSE;
2214 return TRUE;
2217 /******************************************************************************
2218 * SetServiceObjectSecurity [ADVAPI32.@]
2220 * NOTES
2221 * - SetSecurityInfo should be updated to call this function once it's implemented.
2223 BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService,
2224 SECURITY_INFORMATION dwSecurityInformation,
2225 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2227 FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
2228 return TRUE;
2231 /******************************************************************************
2232 * SetServiceBits [ADVAPI32.@]
2234 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
2235 DWORD dwServiceBits,
2236 BOOL bSetBitsOn,
2237 BOOL bUpdateImmediately)
2239 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
2240 bSetBitsOn, bUpdateImmediately);
2241 return TRUE;
2244 /* thunk for calling the RegisterServiceCtrlHandler handler function */
2245 static DWORD WINAPI ctrl_handler_thunk( DWORD control, DWORD type, void *data, void *context )
2247 LPHANDLER_FUNCTION func = context;
2249 func( control );
2250 return ERROR_SUCCESS;
2253 /******************************************************************************
2254 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
2256 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER_FUNCTION handler )
2258 return RegisterServiceCtrlHandlerExA( name, ctrl_handler_thunk, handler );
2261 /******************************************************************************
2262 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
2264 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLER_FUNCTION handler )
2266 return RegisterServiceCtrlHandlerExW( name, ctrl_handler_thunk, handler );
2269 /******************************************************************************
2270 * RegisterServiceCtrlHandlerExA [ADVAPI32.@]
2272 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDLER_FUNCTION_EX handler, LPVOID context )
2274 LPWSTR nameW;
2275 SERVICE_STATUS_HANDLE ret;
2277 nameW = SERV_dup(name);
2278 ret = RegisterServiceCtrlHandlerExW( nameW, handler, context );
2279 heap_free( nameW );
2280 return ret;
2283 /******************************************************************************
2284 * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
2286 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
2287 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2289 service_data *service;
2290 SC_HANDLE hService = 0;
2291 BOOL found = FALSE;
2293 TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
2295 EnterCriticalSection( &service_cs );
2296 if ((service = find_service_by_name( lpServiceName )))
2298 service->handler = lpHandlerProc;
2299 service->context = lpContext;
2300 hService = service->handle;
2301 found = TRUE;
2303 LeaveCriticalSection( &service_cs );
2305 if (!found) SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
2307 return (SERVICE_STATUS_HANDLE)hService;
2310 /******************************************************************************
2311 * EnumDependentServicesA [ADVAPI32.@]
2313 BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState,
2314 LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize,
2315 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2317 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2318 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2320 *lpServicesReturned = 0;
2321 return TRUE;
2324 /******************************************************************************
2325 * EnumDependentServicesW [ADVAPI32.@]
2327 BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
2328 LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize,
2329 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2331 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2332 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2334 *lpServicesReturned = 0;
2335 return TRUE;