dplayx: Assimilate the IDirectPlayLobby3 methods.
[wine.git] / dlls / advapi32 / service.c
blob5f3f15fef315b9bb9811cdcd8f15f993f66f5706
1 /*
2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
5 * Copyright 2005 Mike McCormack
6 * Copyright 2007 Rolf Kalbermatter
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <string.h>
28 #include <time.h>
29 #include <assert.h>
31 #include "ntstatus.h"
32 #define WIN32_NO_STATUS
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winsvc.h"
36 #include "winerror.h"
37 #include "winreg.h"
38 #include "wine/unicode.h"
39 #include "wine/debug.h"
40 #include "winternl.h"
41 #include "lmcons.h"
42 #include "lmserver.h"
44 #include "svcctl.h"
46 #include "advapi32_misc.h"
48 #include "wine/exception.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(service);
52 void __RPC_FAR * __RPC_USER MIDL_user_allocate(SIZE_T len)
54 return HeapAlloc(GetProcessHeap(), 0, len);
57 void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
59 HeapFree(GetProcessHeap(), 0, ptr);
62 typedef struct service_data_t
64 LPHANDLER_FUNCTION_EX handler;
65 LPVOID context;
66 HANDLE thread;
67 SC_HANDLE handle;
68 SC_HANDLE full_access_handle;
69 BOOL unicode : 1;
70 union {
71 LPSERVICE_MAIN_FUNCTIONA a;
72 LPSERVICE_MAIN_FUNCTIONW w;
73 } proc;
74 LPWSTR args;
75 WCHAR name[1];
76 } service_data;
78 typedef struct dispatcher_data_t
80 SC_HANDLE manager;
81 HANDLE pipe;
82 } dispatcher_data;
84 static CRITICAL_SECTION service_cs;
85 static CRITICAL_SECTION_DEBUG service_cs_debug =
87 0, 0, &service_cs,
88 { &service_cs_debug.ProcessLocksList,
89 &service_cs_debug.ProcessLocksList },
90 0, 0, { (DWORD_PTR)(__FILE__ ": service_cs") }
92 static CRITICAL_SECTION service_cs = { &service_cs_debug, -1, 0, 0, 0, 0 };
94 static service_data **services;
95 static unsigned int nb_services;
96 static HANDLE service_event;
97 static HANDLE stop_event;
99 extern HANDLE CDECL __wine_make_process_system(void);
101 /******************************************************************************
102 * String management functions (same behaviour as strdup)
103 * NOTE: the caller of those functions is responsible for calling HeapFree
104 * in order to release the memory allocated by those functions.
106 LPWSTR SERV_dup( LPCSTR str )
108 UINT len;
109 LPWSTR wstr;
111 if( !str )
112 return NULL;
113 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
114 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
115 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
116 return wstr;
119 static inline LPWSTR SERV_dupmulti(LPCSTR str)
121 UINT len = 0, n = 0;
122 LPWSTR wstr;
124 if( !str )
125 return NULL;
126 do {
127 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
128 n += (strlen( &str[n] ) + 1);
129 } while (str[n]);
130 len++;
131 n++;
133 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
134 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
135 return wstr;
138 static inline DWORD multisz_cb(LPCWSTR wmultisz)
140 const WCHAR *wptr = wmultisz;
142 if (wmultisz == NULL)
143 return 0;
145 while (*wptr)
146 wptr += lstrlenW(wptr)+1;
147 return (wptr - wmultisz + 1)*sizeof(WCHAR);
150 /******************************************************************************
151 * RPC connection with services.exe
154 DECLSPEC_HIDDEN handle_t __RPC_USER MACHINE_HANDLEW_bind(MACHINE_HANDLEW MachineName)
156 WCHAR transport[] = SVCCTL_TRANSPORT;
157 WCHAR endpoint[] = SVCCTL_ENDPOINT;
158 RPC_WSTR binding_str;
159 RPC_STATUS status;
160 handle_t rpc_handle;
162 status = RpcStringBindingComposeW(NULL, transport, (RPC_WSTR)MachineName, endpoint, NULL, &binding_str);
163 if (status != RPC_S_OK)
165 ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD)status);
166 return NULL;
169 status = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
170 RpcStringFreeW(&binding_str);
172 if (status != RPC_S_OK)
174 ERR("Couldn't connect to services.exe: error code %u\n", (DWORD)status);
175 return NULL;
178 return rpc_handle;
181 DECLSPEC_HIDDEN void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName, handle_t h)
183 RpcBindingFree(&h);
186 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr)
188 return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode);
191 static DWORD map_exception_code(DWORD exception_code)
193 switch (exception_code)
195 case RPC_X_NULL_REF_POINTER:
196 return ERROR_INVALID_ADDRESS;
197 case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
198 case RPC_X_BYTE_COUNT_TOO_SMALL:
199 return ERROR_INVALID_PARAMETER;
200 case RPC_S_INVALID_BINDING:
201 case RPC_X_SS_IN_NULL_CONTEXT:
202 return ERROR_INVALID_HANDLE;
203 default:
204 return exception_code;
208 /******************************************************************************
209 * Service IPC functions
211 static LPWSTR service_get_pipe_name(void)
213 static const WCHAR format[] = { '\\','\\','.','\\','p','i','p','e','\\',
214 'n','e','t','\\','N','t','C','o','n','t','r','o','l','P','i','p','e','%','u',0};
215 static const WCHAR service_current_key_str[] = { 'S','Y','S','T','E','M','\\',
216 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
217 'C','o','n','t','r','o','l','\\',
218 'S','e','r','v','i','c','e','C','u','r','r','e','n','t',0};
219 LPWSTR name;
220 DWORD len;
221 HKEY service_current_key;
222 DWORD service_current;
223 LONG ret;
224 DWORD type;
226 ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, service_current_key_str, 0,
227 KEY_QUERY_VALUE, &service_current_key);
228 if (ret != ERROR_SUCCESS)
229 return NULL;
230 len = sizeof(service_current);
231 ret = RegQueryValueExW(service_current_key, NULL, NULL, &type,
232 (BYTE *)&service_current, &len);
233 RegCloseKey(service_current_key);
234 if (ret != ERROR_SUCCESS || type != REG_DWORD)
235 return NULL;
236 len = sizeof(format)/sizeof(WCHAR) + 10 /* strlenW("4294967295") */;
237 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
238 if (!name)
239 return NULL;
240 snprintfW(name, len, format, service_current);
241 return name;
244 static HANDLE service_open_pipe(void)
246 LPWSTR szPipe = service_get_pipe_name();
247 HANDLE handle = INVALID_HANDLE_VALUE;
249 do {
250 handle = CreateFileW(szPipe, GENERIC_READ|GENERIC_WRITE,
251 0, NULL, OPEN_ALWAYS, 0, NULL);
252 if (handle != INVALID_HANDLE_VALUE)
253 break;
254 if (GetLastError() != ERROR_PIPE_BUSY)
255 break;
256 } while (WaitNamedPipeW(szPipe, NMPWAIT_USE_DEFAULT_WAIT));
257 HeapFree(GetProcessHeap(), 0, szPipe);
259 return handle;
262 static service_data *find_service_by_name( const WCHAR *name )
264 unsigned int i;
266 if (nb_services == 1) /* only one service (FIXME: should depend on OWN_PROCESS etc.) */
267 return services[0];
268 for (i = 0; i < nb_services; i++)
269 if (!strcmpiW( name, services[i]->name )) return services[i];
270 return NULL;
273 /******************************************************************************
274 * service_thread
276 * Call into the main service routine provided by StartServiceCtrlDispatcher.
278 static DWORD WINAPI service_thread(LPVOID arg)
280 service_data *info = arg;
281 LPWSTR str = info->args;
282 DWORD argc = 0, len = 0;
284 TRACE("%p\n", arg);
286 while (str[len])
288 len += strlenW(&str[len]) + 1;
289 argc++;
291 len++;
293 if (info->unicode)
295 LPWSTR *argv, p;
297 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR));
298 for (argc=0, p=str; *p; p += strlenW(p) + 1)
299 argv[argc++] = p;
300 argv[argc] = NULL;
302 info->proc.w(argc, argv);
303 HeapFree(GetProcessHeap(), 0, argv);
305 else
307 LPSTR strA, *argv, p;
308 DWORD lenA;
310 lenA = WideCharToMultiByte(CP_ACP,0, str, len, NULL, 0, NULL, NULL);
311 strA = HeapAlloc(GetProcessHeap(), 0, lenA);
312 WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL);
314 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPSTR));
315 for (argc=0, p=strA; *p; p += strlen(p) + 1)
316 argv[argc++] = p;
317 argv[argc] = NULL;
319 info->proc.a(argc, argv);
320 HeapFree(GetProcessHeap(), 0, argv);
321 HeapFree(GetProcessHeap(), 0, strA);
323 return 0;
326 /******************************************************************************
327 * service_handle_start
329 static DWORD service_handle_start(service_data *service, const WCHAR *data, DWORD count)
331 TRACE("%s argsize %u\n", debugstr_w(service->name), count);
333 if (service->thread)
335 WARN("service is not stopped\n");
336 return ERROR_SERVICE_ALREADY_RUNNING;
339 HeapFree(GetProcessHeap(), 0, service->args);
340 service->args = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
341 memcpy( service->args, data, count * sizeof(WCHAR) );
342 service->thread = CreateThread( NULL, 0, service_thread,
343 service, 0, NULL );
344 SetEvent( service_event ); /* notify the main loop */
345 return 0;
348 /******************************************************************************
349 * service_handle_control
351 static DWORD service_handle_control(const service_data *service, DWORD dwControl)
353 DWORD ret = ERROR_INVALID_SERVICE_CONTROL;
355 TRACE("%s control %u\n", debugstr_w(service->name), dwControl);
357 if (service->handler)
358 ret = service->handler(dwControl, 0, NULL, service->context);
359 return ret;
362 /******************************************************************************
363 * service_control_dispatcher
365 static DWORD WINAPI service_control_dispatcher(LPVOID arg)
367 dispatcher_data *disp = arg;
369 /* dispatcher loop */
370 while (1)
372 service_data *service;
373 service_start_info info;
374 WCHAR *data = NULL;
375 BOOL r;
376 DWORD data_size = 0, count, result;
378 r = ReadFile( disp->pipe, &info, FIELD_OFFSET(service_start_info,data), &count, NULL );
379 if (!r)
381 if (GetLastError() != ERROR_BROKEN_PIPE)
382 ERR( "pipe read failed error %u\n", GetLastError() );
383 break;
385 if (count != FIELD_OFFSET(service_start_info,data))
387 ERR( "partial pipe read %u\n", count );
388 break;
390 if (count < info.total_size)
392 data_size = info.total_size - FIELD_OFFSET(service_start_info,data);
393 data = HeapAlloc( GetProcessHeap(), 0, data_size );
394 r = ReadFile( disp->pipe, data, data_size, &count, NULL );
395 if (!r)
397 if (GetLastError() != ERROR_BROKEN_PIPE)
398 ERR( "pipe read failed error %u\n", GetLastError() );
399 HeapFree( GetProcessHeap(), 0, data );
400 break;
402 if (count != data_size)
404 ERR( "partial pipe read %u/%u\n", count, data_size );
405 HeapFree( GetProcessHeap(), 0, data );
406 break;
410 /* find the service */
412 if (!(service = find_service_by_name( data )))
414 FIXME( "got request %u for unknown service %s\n", info.cmd, debugstr_w(data));
415 result = ERROR_INVALID_PARAMETER;
416 goto done;
419 TRACE( "got request %u for service %s\n", info.cmd, debugstr_w(data) );
421 /* handle the request */
422 switch (info.cmd)
424 case WINESERV_STARTINFO:
425 if (!service->handle)
427 if (!(service->handle = OpenServiceW( disp->manager, data, SERVICE_SET_STATUS )) ||
428 !(service->full_access_handle = OpenServiceW( disp->manager, data,
429 GENERIC_READ|GENERIC_WRITE )))
430 FIXME( "failed to open service %s\n", debugstr_w(data) );
432 result = service_handle_start(service, data, data_size / sizeof(WCHAR));
433 break;
434 case WINESERV_SENDCONTROL:
435 result = service_handle_control(service, info.control);
436 break;
437 default:
438 ERR("received invalid command %u\n", info.cmd);
439 result = ERROR_INVALID_PARAMETER;
440 break;
443 done:
444 WriteFile( disp->pipe, &result, sizeof(result), &count, NULL );
445 HeapFree( GetProcessHeap(), 0, data );
448 CloseHandle( disp->pipe );
449 CloseServiceHandle( disp->manager );
450 HeapFree( GetProcessHeap(), 0, disp );
451 return 1;
454 /******************************************************************************
455 * service_run_main_thread
457 static BOOL service_run_main_thread(void)
459 DWORD i, n, ret;
460 HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
461 UINT wait_services[MAXIMUM_WAIT_OBJECTS];
462 dispatcher_data *disp = HeapAlloc( GetProcessHeap(), 0, sizeof(*disp) );
464 disp->manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT );
465 if (!disp->manager)
467 ERR("failed to open service manager error %u\n", GetLastError());
468 HeapFree( GetProcessHeap(), 0, disp );
469 return FALSE;
472 disp->pipe = service_open_pipe();
473 if (disp->pipe == INVALID_HANDLE_VALUE)
475 WARN("failed to create control pipe error %u\n", GetLastError());
476 CloseServiceHandle( disp->manager );
477 HeapFree( GetProcessHeap(), 0, disp );
478 SetLastError( ERROR_FAILED_SERVICE_CONTROLLER_CONNECT );
479 return FALSE;
482 service_event = CreateEventW( NULL, FALSE, FALSE, NULL );
483 stop_event = CreateEventW( NULL, FALSE, FALSE, NULL );
485 /* FIXME: service_control_dispatcher should be merged into the main thread */
486 wait_handles[0] = __wine_make_process_system();
487 wait_handles[1] = CreateThread( NULL, 0, service_control_dispatcher, disp, 0, NULL );
488 wait_handles[2] = service_event;
489 wait_handles[3] = stop_event;
491 TRACE("Starting %d services running as process %d\n",
492 nb_services, GetCurrentProcessId());
494 /* wait for all the threads to pack up and exit */
495 for (;;)
497 EnterCriticalSection( &service_cs );
498 for (i = 0, n = 4; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
500 if (!services[i]->thread) continue;
501 wait_services[n] = i;
502 wait_handles[n++] = services[i]->thread;
504 LeaveCriticalSection( &service_cs );
506 ret = WaitForMultipleObjects( n, wait_handles, FALSE, INFINITE );
507 if (!ret) /* system process event */
509 SERVICE_STATUS st;
510 SERVICE_PRESHUTDOWN_INFO spi;
511 DWORD timeout = 5000;
512 BOOL res;
514 EnterCriticalSection( &service_cs );
515 n = 0;
516 for (i = 0; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
518 if (!services[i]->thread) continue;
520 res = QueryServiceStatus(services[i]->full_access_handle, &st);
521 ret = ERROR_SUCCESS;
522 if (res && (st.dwControlsAccepted & SERVICE_ACCEPT_PRESHUTDOWN))
524 res = QueryServiceConfig2W( services[i]->full_access_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
525 (LPBYTE)&spi, sizeof(spi), &i );
526 if (res)
528 FIXME("service should be able to delay shutdown\n");
529 timeout += spi.dwPreshutdownTimeout;
530 ret = service_handle_control( services[i], SERVICE_CONTROL_PRESHUTDOWN );
531 wait_handles[n++] = services[i]->thread;
534 else if (res && (st.dwControlsAccepted & SERVICE_ACCEPT_SHUTDOWN))
536 ret = service_handle_control( services[i], SERVICE_CONTROL_SHUTDOWN );
537 wait_handles[n++] = services[i]->thread;
540 LeaveCriticalSection( &service_cs );
542 TRACE("last user process exited, shutting down (timeout: %d)\n", timeout);
543 WaitForMultipleObjects( n, wait_handles, TRUE, timeout );
544 ExitProcess(0);
546 else if (ret == 1)
548 TRACE( "control dispatcher exited, shutting down\n" );
549 /* FIXME: we should maybe send a shutdown control to running services */
550 ExitProcess(0);
552 else if (ret == 2)
554 continue; /* rebuild the list */
556 else if (ret == 3)
558 return TRUE;
560 else if (ret < n)
562 services[wait_services[ret]]->thread = 0;
563 CloseHandle( wait_handles[ret] );
565 else return FALSE;
569 /******************************************************************************
570 * StartServiceCtrlDispatcherA [ADVAPI32.@]
572 * See StartServiceCtrlDispatcherW.
574 BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
576 service_data *info;
577 unsigned int i;
579 TRACE("%p\n", servent);
581 if (nb_services)
583 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
584 return FALSE;
586 while (servent[nb_services].lpServiceName) nb_services++;
587 if (!nb_services)
589 SetLastError( ERROR_INVALID_PARAMETER );
590 return FALSE;
593 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
595 for (i = 0; i < nb_services; i++)
597 DWORD len = MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, NULL, 0);
598 DWORD sz = FIELD_OFFSET( service_data, name[len] );
599 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
600 MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, info->name, len);
601 info->proc.a = servent[i].lpServiceProc;
602 info->unicode = FALSE;
603 services[i] = info;
606 return service_run_main_thread();
609 /******************************************************************************
610 * StartServiceCtrlDispatcherW [ADVAPI32.@]
612 * Connects a process containing one or more services to the service control
613 * manager.
615 * PARAMS
616 * servent [I] A list of the service names and service procedures
618 * RETURNS
619 * Success: TRUE.
620 * Failure: FALSE.
622 BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
624 service_data *info;
625 unsigned int i;
627 TRACE("%p\n", servent);
629 if (nb_services)
631 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
632 return FALSE;
634 while (servent[nb_services].lpServiceName) nb_services++;
635 if (!nb_services)
637 SetLastError( ERROR_INVALID_PARAMETER );
638 return FALSE;
641 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
643 for (i = 0; i < nb_services; i++)
645 DWORD len = strlenW(servent[i].lpServiceName) + 1;
646 DWORD sz = FIELD_OFFSET( service_data, name[len] );
647 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
648 strcpyW(info->name, servent[i].lpServiceName);
649 info->proc.w = servent[i].lpServiceProc;
650 info->unicode = TRUE;
651 services[i] = info;
654 return service_run_main_thread();
657 /******************************************************************************
658 * LockServiceDatabase [ADVAPI32.@]
660 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
662 SC_RPC_LOCK hLock = NULL;
663 DWORD err;
665 TRACE("%p\n",hSCManager);
667 __TRY
669 err = svcctl_LockServiceDatabase(hSCManager, &hLock);
671 __EXCEPT(rpc_filter)
673 err = map_exception_code(GetExceptionCode());
675 __ENDTRY
676 if (err != ERROR_SUCCESS)
678 SetLastError(err);
679 return NULL;
681 return hLock;
684 /******************************************************************************
685 * UnlockServiceDatabase [ADVAPI32.@]
687 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
689 DWORD err;
690 SC_RPC_LOCK hRpcLock = ScLock;
692 TRACE("%p\n",ScLock);
694 __TRY
696 err = svcctl_UnlockServiceDatabase(&hRpcLock);
698 __EXCEPT(rpc_filter)
700 err = map_exception_code(GetExceptionCode());
702 __ENDTRY
703 if (err != ERROR_SUCCESS)
705 SetLastError(err);
706 return FALSE;
708 return TRUE;
711 /******************************************************************************
712 * SetServiceStatus [ADVAPI32.@]
714 * PARAMS
715 * hService []
716 * lpStatus []
718 BOOL WINAPI
719 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
721 DWORD err;
723 TRACE("%p %x %x %x %x %x %x %x\n", hService,
724 lpStatus->dwServiceType, lpStatus->dwCurrentState,
725 lpStatus->dwControlsAccepted, lpStatus->dwWin32ExitCode,
726 lpStatus->dwServiceSpecificExitCode, lpStatus->dwCheckPoint,
727 lpStatus->dwWaitHint);
729 __TRY
731 err = svcctl_SetServiceStatus( hService, lpStatus );
733 __EXCEPT(rpc_filter)
735 err = map_exception_code(GetExceptionCode());
737 __ENDTRY
738 if (err != ERROR_SUCCESS)
740 SetLastError(err);
741 return FALSE;
744 if (lpStatus->dwCurrentState == SERVICE_STOPPED) {
745 SetEvent(stop_event);
746 CloseServiceHandle((SC_HANDLE)hService);
749 return TRUE;
753 /******************************************************************************
754 * OpenSCManagerA [ADVAPI32.@]
756 * Establish a connection to the service control manager and open its database.
758 * PARAMS
759 * lpMachineName [I] Pointer to machine name string
760 * lpDatabaseName [I] Pointer to database name string
761 * dwDesiredAccess [I] Type of access
763 * RETURNS
764 * Success: A Handle to the service control manager database
765 * Failure: NULL
767 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
768 DWORD dwDesiredAccess )
770 LPWSTR lpMachineNameW, lpDatabaseNameW;
771 SC_HANDLE ret;
773 lpMachineNameW = SERV_dup(lpMachineName);
774 lpDatabaseNameW = SERV_dup(lpDatabaseName);
775 ret = OpenSCManagerW(lpMachineNameW, lpDatabaseNameW, dwDesiredAccess);
776 HeapFree(GetProcessHeap(), 0, lpDatabaseNameW);
777 HeapFree(GetProcessHeap(), 0, lpMachineNameW);
778 return ret;
781 /******************************************************************************
782 * OpenSCManagerW [ADVAPI32.@]
784 * See OpenSCManagerA.
786 DWORD SERV_OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
787 DWORD dwDesiredAccess, SC_HANDLE *handle )
789 DWORD r;
791 TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
792 debugstr_w(lpDatabaseName), dwDesiredAccess);
794 __TRY
796 r = svcctl_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, (SC_RPC_HANDLE *)handle);
798 __EXCEPT(rpc_filter)
800 r = map_exception_code(GetExceptionCode());
802 __ENDTRY
804 if (r!=ERROR_SUCCESS)
805 *handle = 0;
807 TRACE("returning %p\n", *handle);
808 return r;
811 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
812 DWORD dwDesiredAccess )
814 SC_HANDLE handle = 0;
815 DWORD r;
817 r = SERV_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, &handle);
818 if (r!=ERROR_SUCCESS)
819 SetLastError(r);
820 return handle;
823 /******************************************************************************
824 * ControlService [ADVAPI32.@]
826 * Send a control code to a service.
828 * PARAMS
829 * hService [I] Handle of the service control manager database
830 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
831 * lpServiceStatus [O] Destination for the status of the service, if available
833 * RETURNS
834 * Success: TRUE.
835 * Failure: FALSE.
837 * BUGS
838 * Unlike M$' implementation, control requests are not serialized and may be
839 * processed asynchronously.
841 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
842 LPSERVICE_STATUS lpServiceStatus )
844 DWORD err;
846 TRACE("%p %d %p\n", hService, dwControl, lpServiceStatus);
848 __TRY
850 err = svcctl_ControlService(hService, dwControl, lpServiceStatus);
852 __EXCEPT(rpc_filter)
854 err = map_exception_code(GetExceptionCode());
856 __ENDTRY
857 if (err != ERROR_SUCCESS)
859 SetLastError(err);
860 return FALSE;
863 return TRUE;
866 /******************************************************************************
867 * CloseServiceHandle [ADVAPI32.@]
869 * Close a handle to a service or the service control manager database.
871 * PARAMS
872 * hSCObject [I] Handle to service or service control manager database
874 * RETURNS
875 * Success: TRUE
876 * Failure: FALSE
878 BOOL WINAPI
879 CloseServiceHandle( SC_HANDLE hSCObject )
881 DWORD err;
883 TRACE("%p\n", hSCObject);
885 __TRY
887 err = svcctl_CloseServiceHandle((SC_RPC_HANDLE *)&hSCObject);
889 __EXCEPT(rpc_filter)
891 err = map_exception_code(GetExceptionCode());
893 __ENDTRY
895 if (err != ERROR_SUCCESS)
897 SetLastError(err);
898 return FALSE;
900 return TRUE;
904 /******************************************************************************
905 * OpenServiceA [ADVAPI32.@]
907 * Open a handle to a service.
909 * PARAMS
910 * hSCManager [I] Handle of the service control manager database
911 * lpServiceName [I] Name of the service to open
912 * dwDesiredAccess [I] Access required to the service
914 * RETURNS
915 * Success: Handle to the service
916 * Failure: NULL
918 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
919 DWORD dwDesiredAccess )
921 LPWSTR lpServiceNameW;
922 SC_HANDLE ret;
924 TRACE("%p %s %d\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
926 lpServiceNameW = SERV_dup(lpServiceName);
927 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
928 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
929 return ret;
933 /******************************************************************************
934 * OpenServiceW [ADVAPI32.@]
936 * See OpenServiceA.
938 DWORD SERV_OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
939 DWORD dwDesiredAccess, SC_HANDLE *handle )
941 DWORD err;
943 TRACE("%p %s %d\n", hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
945 if (!hSCManager)
946 return ERROR_INVALID_HANDLE;
948 __TRY
950 err = svcctl_OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess, (SC_RPC_HANDLE *)handle);
952 __EXCEPT(rpc_filter)
954 err = map_exception_code(GetExceptionCode());
956 __ENDTRY
958 if (err != ERROR_SUCCESS)
959 *handle = 0;
961 TRACE("returning %p\n", *handle);
962 return err;
965 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
966 DWORD dwDesiredAccess)
968 SC_HANDLE handle = 0;
969 DWORD err;
971 err = SERV_OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess, &handle);
972 if (err != ERROR_SUCCESS)
973 SetLastError(err);
974 return handle;
977 /******************************************************************************
978 * CreateServiceW [ADVAPI32.@]
980 SC_HANDLE WINAPI
981 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
982 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
983 DWORD dwServiceType, DWORD dwStartType,
984 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
985 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
986 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
987 LPCWSTR lpPassword )
989 SC_HANDLE handle = 0;
990 DWORD err;
991 SIZE_T passwdlen;
993 TRACE("%p %s %s\n", hSCManager,
994 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
996 if (!hSCManager)
998 SetLastError( ERROR_INVALID_HANDLE );
999 return 0;
1002 if (lpPassword)
1003 passwdlen = (strlenW(lpPassword) + 1) * sizeof(WCHAR);
1004 else
1005 passwdlen = 0;
1007 __TRY
1009 err = svcctl_CreateServiceW(hSCManager, lpServiceName,
1010 lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1011 lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, (const BYTE*)lpDependencies,
1012 multisz_cb(lpDependencies), lpServiceStartName, (const BYTE*)lpPassword, passwdlen,
1013 (SC_RPC_HANDLE *)&handle);
1015 __EXCEPT(rpc_filter)
1017 err = map_exception_code(GetExceptionCode());
1019 __ENDTRY
1021 if (err != ERROR_SUCCESS)
1023 SetLastError(err);
1024 handle = 0;
1026 return handle;
1030 /******************************************************************************
1031 * CreateServiceA [ADVAPI32.@]
1033 SC_HANDLE WINAPI
1034 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1035 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
1036 DWORD dwServiceType, DWORD dwStartType,
1037 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1038 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1039 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
1040 LPCSTR lpPassword )
1042 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
1043 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
1044 SC_HANDLE r;
1046 TRACE("%p %s %s\n", hSCManager,
1047 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
1049 lpServiceNameW = SERV_dup( lpServiceName );
1050 lpDisplayNameW = SERV_dup( lpDisplayName );
1051 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
1052 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
1053 lpDependenciesW = SERV_dupmulti( lpDependencies );
1054 lpServiceStartNameW = SERV_dup( lpServiceStartName );
1055 lpPasswordW = SERV_dup( lpPassword );
1057 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
1058 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1059 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
1060 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
1062 HeapFree( GetProcessHeap(), 0, lpServiceNameW );
1063 HeapFree( GetProcessHeap(), 0, lpDisplayNameW );
1064 HeapFree( GetProcessHeap(), 0, lpBinaryPathNameW );
1065 HeapFree( GetProcessHeap(), 0, lpLoadOrderGroupW );
1066 HeapFree( GetProcessHeap(), 0, lpDependenciesW );
1067 HeapFree( GetProcessHeap(), 0, lpServiceStartNameW );
1068 HeapFree( GetProcessHeap(), 0, lpPasswordW );
1070 return r;
1074 /******************************************************************************
1075 * DeleteService [ADVAPI32.@]
1077 * Delete a service from the service control manager database.
1079 * PARAMS
1080 * hService [I] Handle of the service to delete
1082 * RETURNS
1083 * Success: TRUE
1084 * Failure: FALSE
1086 BOOL WINAPI DeleteService( SC_HANDLE hService )
1088 DWORD err;
1090 __TRY
1092 err = svcctl_DeleteService(hService);
1094 __EXCEPT(rpc_filter)
1096 err = map_exception_code(GetExceptionCode());
1098 __ENDTRY
1099 if (err != 0)
1101 SetLastError(err);
1102 return FALSE;
1105 return TRUE;
1109 /******************************************************************************
1110 * StartServiceA [ADVAPI32.@]
1112 * Start a service
1114 * PARAMS
1115 * hService [I] Handle of service
1116 * dwNumServiceArgs [I] Number of arguments
1117 * lpServiceArgVectors [I] Address of array of argument strings
1119 * NOTES
1120 * - NT implements this function using an obscure RPC call.
1121 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1122 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
1123 * - This will only work for shared address space. How should the service
1124 * args be transferred when address spaces are separated?
1125 * - Can only start one service at a time.
1126 * - Has no concept of privilege.
1128 * RETURNS
1129 * Success: TRUE.
1130 * Failure: FALSE
1132 BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
1133 LPCSTR *lpServiceArgVectors )
1135 LPWSTR *lpwstr=NULL;
1136 unsigned int i;
1137 BOOL r;
1139 TRACE("(%p,%d,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
1141 if (dwNumServiceArgs)
1142 lpwstr = HeapAlloc( GetProcessHeap(), 0,
1143 dwNumServiceArgs*sizeof(LPWSTR) );
1145 for(i=0; i<dwNumServiceArgs; i++)
1146 lpwstr[i]=SERV_dup(lpServiceArgVectors[i]);
1148 r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
1150 if (dwNumServiceArgs)
1152 for(i=0; i<dwNumServiceArgs; i++)
1153 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
1154 HeapFree(GetProcessHeap(), 0, lpwstr);
1157 return r;
1161 /******************************************************************************
1162 * StartServiceW [ADVAPI32.@]
1164 * See StartServiceA.
1166 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1167 LPCWSTR *lpServiceArgVectors)
1169 DWORD err;
1171 TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1173 __TRY
1175 err = svcctl_StartServiceW(hService, dwNumServiceArgs, lpServiceArgVectors);
1177 __EXCEPT(rpc_filter)
1179 err = map_exception_code(GetExceptionCode());
1181 __ENDTRY
1182 if (err != ERROR_SUCCESS)
1184 SetLastError(err);
1185 return FALSE;
1188 return TRUE;
1191 /******************************************************************************
1192 * QueryServiceStatus [ADVAPI32.@]
1194 * PARAMS
1195 * hService [I] Handle to service to get information about
1196 * lpservicestatus [O] buffer to receive the status information for the service
1199 BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
1200 LPSERVICE_STATUS lpservicestatus)
1202 SERVICE_STATUS_PROCESS SvcStatusData;
1203 BOOL ret;
1204 DWORD dummy;
1206 TRACE("%p %p\n", hService, lpservicestatus);
1208 if (!hService)
1210 SetLastError(ERROR_INVALID_HANDLE);
1211 return FALSE;
1213 if (!lpservicestatus)
1215 SetLastError(ERROR_INVALID_ADDRESS);
1216 return FALSE;
1219 ret = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&SvcStatusData,
1220 sizeof(SERVICE_STATUS_PROCESS), &dummy);
1221 if (ret) memcpy(lpservicestatus, &SvcStatusData, sizeof(SERVICE_STATUS)) ;
1222 return ret;
1226 /******************************************************************************
1227 * QueryServiceStatusEx [ADVAPI32.@]
1229 * Get information about a service.
1231 * PARAMS
1232 * hService [I] Handle to service to get information about
1233 * InfoLevel [I] Level of information to get
1234 * lpBuffer [O] Destination for requested information
1235 * cbBufSize [I] Size of lpBuffer in bytes
1236 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1238 * RETURNS
1239 * Success: TRUE
1240 * FAILURE: FALSE
1242 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1243 LPBYTE lpBuffer, DWORD cbBufSize,
1244 LPDWORD pcbBytesNeeded)
1246 DWORD err;
1248 TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1250 if (InfoLevel != SC_STATUS_PROCESS_INFO)
1252 err = ERROR_INVALID_LEVEL;
1254 else if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
1256 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
1257 err = ERROR_INSUFFICIENT_BUFFER;
1259 else
1261 __TRY
1263 err = svcctl_QueryServiceStatusEx(hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1265 __EXCEPT(rpc_filter)
1267 err = map_exception_code(GetExceptionCode());
1269 __ENDTRY
1271 if (err != ERROR_SUCCESS)
1273 SetLastError(err);
1274 return FALSE;
1276 return TRUE;
1279 /******************************************************************************
1280 * QueryServiceConfigA [ADVAPI32.@]
1282 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1283 DWORD size, LPDWORD needed )
1285 DWORD n;
1286 LPSTR p, buffer;
1287 BOOL ret;
1288 QUERY_SERVICE_CONFIGW *configW;
1290 TRACE("%p %p %d %p\n", hService, config, size, needed);
1292 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, 2 * size )))
1294 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1295 return FALSE;
1297 configW = (QUERY_SERVICE_CONFIGW *)buffer;
1298 ret = QueryServiceConfigW( hService, configW, 2 * size, needed );
1299 if (!ret) goto done;
1301 config->dwServiceType = configW->dwServiceType;
1302 config->dwStartType = configW->dwStartType;
1303 config->dwErrorControl = configW->dwErrorControl;
1304 config->lpBinaryPathName = NULL;
1305 config->lpLoadOrderGroup = NULL;
1306 config->dwTagId = configW->dwTagId;
1307 config->lpDependencies = NULL;
1308 config->lpServiceStartName = NULL;
1309 config->lpDisplayName = NULL;
1311 p = (LPSTR)(config + 1);
1312 n = size - sizeof(*config);
1313 ret = FALSE;
1315 #define MAP_STR(str) \
1316 do { \
1317 if (configW->str) \
1319 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1320 if (!sz) goto done; \
1321 config->str = p; \
1322 p += sz; \
1323 n -= sz; \
1325 } while (0)
1327 MAP_STR( lpBinaryPathName );
1328 MAP_STR( lpLoadOrderGroup );
1329 MAP_STR( lpDependencies );
1330 MAP_STR( lpServiceStartName );
1331 MAP_STR( lpDisplayName );
1332 #undef MAP_STR
1334 *needed = p - (LPSTR)config;
1335 ret = TRUE;
1337 done:
1338 HeapFree( GetProcessHeap(), 0, buffer );
1339 return ret;
1342 static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
1344 DWORD cb;
1346 if (!*string_ptr)
1348 cb = sizeof(WCHAR);
1349 memset(*buf, 0, cb);
1351 else
1353 cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
1354 memcpy(*buf, *string_ptr, cb);
1355 MIDL_user_free(*string_ptr);
1358 *string_ptr = (LPWSTR)*buf;
1359 *buf += cb;
1361 return cb;
1364 static DWORD size_string(LPCWSTR string)
1366 return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
1369 /******************************************************************************
1370 * QueryServiceConfigW [ADVAPI32.@]
1372 BOOL WINAPI
1373 QueryServiceConfigW( SC_HANDLE hService,
1374 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1375 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1377 QUERY_SERVICE_CONFIGW config;
1378 DWORD total;
1379 DWORD err;
1380 BYTE *bufpos;
1382 TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1383 cbBufSize, pcbBytesNeeded);
1385 memset(&config, 0, sizeof(config));
1387 __TRY
1389 err = svcctl_QueryServiceConfigW(hService, &config);
1391 __EXCEPT(rpc_filter)
1393 err = map_exception_code(GetExceptionCode());
1395 __ENDTRY
1397 if (err != ERROR_SUCCESS)
1399 TRACE("services.exe: error %u\n", err);
1400 SetLastError(err);
1401 return FALSE;
1404 /* calculate the size required first */
1405 total = sizeof (QUERY_SERVICE_CONFIGW);
1406 total += size_string(config.lpBinaryPathName);
1407 total += size_string(config.lpLoadOrderGroup);
1408 total += size_string(config.lpDependencies);
1409 total += size_string(config.lpServiceStartName);
1410 total += size_string(config.lpDisplayName);
1412 *pcbBytesNeeded = total;
1414 /* if there's not enough memory, return an error */
1415 if( total > cbBufSize )
1417 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1418 MIDL_user_free(config.lpBinaryPathName);
1419 MIDL_user_free(config.lpLoadOrderGroup);
1420 MIDL_user_free(config.lpDependencies);
1421 MIDL_user_free(config.lpServiceStartName);
1422 MIDL_user_free(config.lpDisplayName);
1423 return FALSE;
1426 *lpServiceConfig = config;
1427 bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
1428 move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
1429 move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
1430 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
1431 move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
1432 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
1434 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1435 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1436 TRACE("Dependencies = %s\n", debugstr_w(lpServiceConfig->lpDependencies) );
1437 TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig->lpServiceStartName) );
1438 TRACE("Display name = %s\n", debugstr_w(lpServiceConfig->lpDisplayName) );
1440 return TRUE;
1443 /******************************************************************************
1444 * QueryServiceConfig2A [ADVAPI32.@]
1446 * Note
1447 * observed under win2k:
1448 * The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
1449 * required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
1451 BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1452 DWORD size, LPDWORD needed)
1454 BOOL ret;
1455 LPBYTE bufferW = NULL;
1457 if(buffer && size)
1458 bufferW = HeapAlloc( GetProcessHeap(), 0, size);
1460 ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
1461 if(!ret) goto cleanup;
1463 switch(dwLevel) {
1464 case SERVICE_CONFIG_DESCRIPTION:
1465 if (buffer && bufferW) {
1466 LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
1467 LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
1468 if (configW->lpDescription && (size > sizeof(SERVICE_DESCRIPTIONA))) {
1469 DWORD sz;
1470 configA->lpDescription = (LPSTR)(configA + 1);
1471 sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
1472 configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
1473 if (!sz) {
1474 FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1475 ret = FALSE;
1476 configA->lpDescription = NULL;
1479 else configA->lpDescription = NULL;
1481 break;
1482 case SERVICE_CONFIG_PRESHUTDOWN_INFO:
1483 if (buffer && bufferW && *needed<=size)
1484 memcpy(buffer, bufferW, *needed);
1485 break;
1486 default:
1487 FIXME("conversation W->A not implemented for level %d\n", dwLevel);
1488 ret = FALSE;
1489 break;
1492 cleanup:
1493 HeapFree( GetProcessHeap(), 0, bufferW);
1494 return ret;
1497 /******************************************************************************
1498 * QueryServiceConfig2W [ADVAPI32.@]
1500 * See QueryServiceConfig2A.
1502 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1503 DWORD size, LPDWORD needed)
1505 DWORD err;
1507 if(dwLevel!=SERVICE_CONFIG_DESCRIPTION && dwLevel!=SERVICE_CONFIG_PRESHUTDOWN_INFO) {
1508 FIXME("Level %d not implemented\n", dwLevel);
1509 SetLastError(ERROR_INVALID_LEVEL);
1510 return FALSE;
1513 if(!buffer && size) {
1514 SetLastError(ERROR_INVALID_ADDRESS);
1515 return FALSE;
1518 TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
1520 __TRY
1522 err = svcctl_QueryServiceConfig2W(hService, dwLevel, buffer, size, needed);
1524 __EXCEPT(rpc_filter)
1526 err = map_exception_code(GetExceptionCode());
1528 __ENDTRY
1530 if (err != ERROR_SUCCESS)
1532 SetLastError( err );
1533 return FALSE;
1536 switch (dwLevel)
1538 case SERVICE_CONFIG_DESCRIPTION:
1539 if (buffer)
1541 SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
1542 if (descr->lpDescription) /* make it an absolute pointer */
1543 descr->lpDescription = (WCHAR *)(buffer + (ULONG_PTR)descr->lpDescription);
1544 break;
1548 return TRUE;
1551 /******************************************************************************
1552 * EnumServicesStatusA [ADVAPI32.@]
1554 BOOL WINAPI
1555 EnumServicesStatusA( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSA
1556 services, DWORD size, LPDWORD needed, LPDWORD returned,
1557 LPDWORD resume_handle )
1559 BOOL ret;
1560 unsigned int i;
1561 ENUM_SERVICE_STATUSW *servicesW = NULL;
1562 DWORD sz, n;
1563 char *p;
1565 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
1566 returned, resume_handle);
1568 sz = max( 2 * size, sizeof(*servicesW) );
1569 if (!(servicesW = HeapAlloc( GetProcessHeap(), 0, sz )))
1571 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1572 return FALSE;
1575 ret = EnumServicesStatusW( hmngr, type, state, servicesW, sz, needed, returned, resume_handle );
1576 if (!ret) goto done;
1578 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUSA);
1579 n = size - (p - (char *)services);
1580 ret = FALSE;
1581 for (i = 0; i < *returned; i++)
1583 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
1584 if (!sz) goto done;
1585 services[i].lpServiceName = p;
1586 p += sz;
1587 n -= sz;
1588 if (servicesW[i].lpDisplayName)
1590 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
1591 if (!sz) goto done;
1592 services[i].lpDisplayName = p;
1593 p += sz;
1594 n -= sz;
1596 else services[i].lpDisplayName = NULL;
1597 services[i].ServiceStatus = servicesW[i].ServiceStatus;
1600 ret = TRUE;
1602 done:
1603 HeapFree( GetProcessHeap(), 0, servicesW );
1604 return ret;
1607 /******************************************************************************
1608 * EnumServicesStatusW [ADVAPI32.@]
1610 BOOL WINAPI
1611 EnumServicesStatusW( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSW
1612 services, DWORD size, LPDWORD needed, LPDWORD returned,
1613 LPDWORD resume_handle )
1615 DWORD err, i;
1616 ENUM_SERVICE_STATUSW dummy_status;
1618 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
1619 returned, resume_handle);
1621 if (resume_handle)
1622 FIXME("resume handle not supported\n");
1624 if (!hmngr)
1626 SetLastError( ERROR_INVALID_HANDLE );
1627 return FALSE;
1630 /* make sure we pass a valid pointer */
1631 if (!services || size < sizeof(*services))
1633 services = &dummy_status;
1634 size = sizeof(dummy_status);
1637 __TRY
1639 err = svcctl_EnumServicesStatusW( hmngr, type, state, (BYTE *)services, size, needed, returned );
1641 __EXCEPT(rpc_filter)
1643 err = map_exception_code( GetExceptionCode() );
1645 __ENDTRY
1647 if (err != ERROR_SUCCESS)
1649 SetLastError( err );
1650 return FALSE;
1653 for (i = 0; i < *returned; i++)
1655 /* convert buffer offsets into pointers */
1656 services[i].lpServiceName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpServiceName);
1657 if (services[i].lpDisplayName)
1658 services[i].lpDisplayName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpDisplayName);
1661 return TRUE;
1664 /******************************************************************************
1665 * EnumServicesStatusExA [ADVAPI32.@]
1667 BOOL WINAPI
1668 EnumServicesStatusExA( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state,
1669 LPBYTE buffer, DWORD size, LPDWORD needed, LPDWORD returned,
1670 LPDWORD resume_handle, LPCSTR group )
1672 BOOL ret;
1673 unsigned int i;
1674 ENUM_SERVICE_STATUS_PROCESSA *services = (ENUM_SERVICE_STATUS_PROCESSA *)buffer;
1675 ENUM_SERVICE_STATUS_PROCESSW *servicesW = NULL;
1676 WCHAR *groupW = NULL;
1677 DWORD sz, n;
1678 char *p;
1680 TRACE("%p %u 0x%x 0x%x %p %u %p %p %p %s\n", hmngr, level, type, state, buffer,
1681 size, needed, returned, resume_handle, debugstr_a(group));
1683 sz = max( 2 * size, sizeof(*servicesW) );
1684 if (!(servicesW = HeapAlloc( GetProcessHeap(), 0, sz )))
1686 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1687 return FALSE;
1689 if (group)
1691 int len = MultiByteToWideChar( CP_ACP, 0, group, -1, NULL, 0 );
1692 if (!(groupW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1694 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1695 HeapFree( GetProcessHeap(), 0, servicesW );
1696 return FALSE;
1698 MultiByteToWideChar( CP_ACP, 0, group, -1, groupW, len * sizeof(WCHAR) );
1701 ret = EnumServicesStatusExW( hmngr, level, type, state, (BYTE *)servicesW, sz,
1702 needed, returned, resume_handle, groupW );
1703 if (!ret) goto done;
1705 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUS_PROCESSA);
1706 n = size - (p - (char *)services);
1707 ret = FALSE;
1708 for (i = 0; i < *returned; i++)
1710 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
1711 if (!sz) goto done;
1712 services[i].lpServiceName = p;
1713 p += sz;
1714 n -= sz;
1715 if (servicesW[i].lpDisplayName)
1717 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
1718 if (!sz) goto done;
1719 services[i].lpDisplayName = p;
1720 p += sz;
1721 n -= sz;
1723 else services[i].lpDisplayName = NULL;
1724 services[i].ServiceStatusProcess = servicesW[i].ServiceStatusProcess;
1727 ret = TRUE;
1729 done:
1730 HeapFree( GetProcessHeap(), 0, servicesW );
1731 HeapFree( GetProcessHeap(), 0, groupW );
1732 return ret;
1735 /******************************************************************************
1736 * EnumServicesStatusExW [ADVAPI32.@]
1738 BOOL WINAPI
1739 EnumServicesStatusExW( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state,
1740 LPBYTE buffer, DWORD size, LPDWORD needed, LPDWORD returned,
1741 LPDWORD resume_handle, LPCWSTR group )
1743 DWORD err, i;
1744 ENUM_SERVICE_STATUS_PROCESSW dummy_status;
1745 ENUM_SERVICE_STATUS_PROCESSW *services = (ENUM_SERVICE_STATUS_PROCESSW *)buffer;
1747 TRACE("%p %u 0x%x 0x%x %p %u %p %p %p %s\n", hmngr, level, type, state, buffer,
1748 size, needed, returned, resume_handle, debugstr_w(group));
1750 if (resume_handle)
1751 FIXME("resume handle not supported\n");
1753 if (level != SC_ENUM_PROCESS_INFO)
1755 SetLastError( ERROR_INVALID_LEVEL );
1756 return FALSE;
1758 if (!hmngr)
1760 SetLastError( ERROR_INVALID_HANDLE );
1761 return FALSE;
1764 /* make sure we pass a valid buffer pointer */
1765 if (!services || size < sizeof(*services))
1767 buffer = (BYTE *)&dummy_status;
1768 size = sizeof(dummy_status);
1771 __TRY
1773 err = svcctl_EnumServicesStatusExW( hmngr, type, state, buffer, size, needed,
1774 returned, group );
1776 __EXCEPT(rpc_filter)
1778 err = map_exception_code( GetExceptionCode() );
1780 __ENDTRY
1782 if (err != ERROR_SUCCESS)
1784 SetLastError( err );
1785 return FALSE;
1788 for (i = 0; i < *returned; i++)
1790 /* convert buffer offsets into pointers */
1791 services[i].lpServiceName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpServiceName);
1792 if (services[i].lpDisplayName)
1793 services[i].lpDisplayName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpDisplayName);
1796 return TRUE;
1799 /******************************************************************************
1800 * GetServiceKeyNameA [ADVAPI32.@]
1802 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1803 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1805 LPWSTR lpDisplayNameW, lpServiceNameW;
1806 DWORD sizeW;
1807 BOOL ret = FALSE;
1809 TRACE("%p %s %p %p\n", hSCManager,
1810 debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1812 lpDisplayNameW = SERV_dup(lpDisplayName);
1813 if (lpServiceName)
1814 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1815 else
1816 lpServiceNameW = NULL;
1818 sizeW = *lpcchBuffer;
1819 if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
1821 if (lpServiceName && *lpcchBuffer)
1822 lpServiceName[0] = 0;
1823 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1824 goto cleanup;
1827 if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
1828 *lpcchBuffer, NULL, NULL ))
1830 if (*lpcchBuffer && lpServiceName)
1831 lpServiceName[0] = 0;
1832 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
1833 goto cleanup;
1836 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1837 ret = TRUE;
1839 cleanup:
1840 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1841 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1842 return ret;
1845 /******************************************************************************
1846 * GetServiceKeyNameW [ADVAPI32.@]
1848 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1849 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1851 DWORD err;
1852 WCHAR buffer[2];
1853 DWORD size;
1855 TRACE("%p %s %p %p\n", hSCManager,
1856 debugstr_w(lpDisplayName), lpServiceName, lpcchBuffer);
1858 if (!hSCManager)
1860 SetLastError( ERROR_INVALID_HANDLE );
1861 return 0;
1864 /* provide a buffer if the caller didn't */
1865 if (!lpServiceName || *lpcchBuffer < 2)
1867 lpServiceName = buffer;
1868 /* A size of 1 would be enough, but tests show that Windows returns 2,
1869 * probably because of a WCHAR/bytes mismatch in their code.
1871 *lpcchBuffer = 2;
1874 /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
1875 * includes the nul-terminator on input. */
1876 size = *lpcchBuffer - 1;
1878 __TRY
1880 err = svcctl_GetServiceKeyNameW(hSCManager, lpDisplayName, lpServiceName,
1881 &size);
1883 __EXCEPT(rpc_filter)
1885 err = map_exception_code(GetExceptionCode());
1887 __ENDTRY
1889 /* The value of *lpcchBuffer excludes nul-terminator on output. */
1890 if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
1891 *lpcchBuffer = size;
1893 if (err)
1894 SetLastError(err);
1895 return err == ERROR_SUCCESS;
1898 /******************************************************************************
1899 * QueryServiceLockStatusA [ADVAPI32.@]
1901 BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
1902 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1903 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1905 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1907 return FALSE;
1910 /******************************************************************************
1911 * QueryServiceLockStatusW [ADVAPI32.@]
1913 BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
1914 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1915 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1917 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1919 return FALSE;
1922 /******************************************************************************
1923 * GetServiceDisplayNameA [ADVAPI32.@]
1925 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1926 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1928 LPWSTR lpServiceNameW, lpDisplayNameW;
1929 DWORD sizeW;
1930 BOOL ret = FALSE;
1932 TRACE("%p %s %p %p\n", hSCManager,
1933 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1935 lpServiceNameW = SERV_dup(lpServiceName);
1936 if (lpDisplayName)
1937 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1938 else
1939 lpDisplayNameW = NULL;
1941 sizeW = *lpcchBuffer;
1942 if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
1944 if (lpDisplayName && *lpcchBuffer)
1945 lpDisplayName[0] = 0;
1946 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1947 goto cleanup;
1950 if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
1951 *lpcchBuffer, NULL, NULL ))
1953 if (*lpcchBuffer && lpDisplayName)
1954 lpDisplayName[0] = 0;
1955 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
1956 goto cleanup;
1959 /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
1960 * (but if the function succeeded it means that is a good upper estimation of the size) */
1961 ret = TRUE;
1963 cleanup:
1964 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1965 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1966 return ret;
1969 /******************************************************************************
1970 * GetServiceDisplayNameW [ADVAPI32.@]
1972 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1973 LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1975 DWORD err;
1976 DWORD size;
1977 WCHAR buffer[2];
1979 TRACE("%p %s %p %p\n", hSCManager,
1980 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1982 if (!hSCManager)
1984 SetLastError( ERROR_INVALID_HANDLE );
1985 return 0;
1988 /* provide a buffer if the caller didn't */
1989 if (!lpDisplayName || *lpcchBuffer < 2)
1991 lpDisplayName = buffer;
1992 /* A size of 1 would be enough, but tests show that Windows returns 2,
1993 * probably because of a WCHAR/bytes mismatch in their code.
1995 *lpcchBuffer = 2;
1998 /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
1999 * includes the nul-terminator on input. */
2000 size = *lpcchBuffer - 1;
2002 __TRY
2004 err = svcctl_GetServiceDisplayNameW(hSCManager, lpServiceName, lpDisplayName,
2005 &size);
2007 __EXCEPT(rpc_filter)
2009 err = map_exception_code(GetExceptionCode());
2011 __ENDTRY
2013 /* The value of *lpcchBuffer excludes nul-terminator on output. */
2014 if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
2015 *lpcchBuffer = size;
2017 if (err)
2018 SetLastError(err);
2019 return err == ERROR_SUCCESS;
2022 /******************************************************************************
2023 * ChangeServiceConfigW [ADVAPI32.@]
2025 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
2026 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
2027 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
2028 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
2030 DWORD cb_pwd;
2031 DWORD err;
2033 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2034 hService, dwServiceType, dwStartType, dwErrorControl,
2035 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
2036 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
2037 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
2039 cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
2041 __TRY
2043 err = svcctl_ChangeServiceConfigW(hService, dwServiceType,
2044 dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId,
2045 (const BYTE *)lpDependencies, multisz_cb(lpDependencies), lpServiceStartName,
2046 (const BYTE *)lpPassword, cb_pwd, lpDisplayName);
2048 __EXCEPT(rpc_filter)
2050 err = map_exception_code(GetExceptionCode());
2052 __ENDTRY
2054 if (err != ERROR_SUCCESS)
2055 SetLastError(err);
2057 return err == ERROR_SUCCESS;
2060 /******************************************************************************
2061 * ChangeServiceConfigA [ADVAPI32.@]
2063 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
2064 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
2065 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
2066 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
2068 LPWSTR wBinaryPathName, wLoadOrderGroup, wDependencies;
2069 LPWSTR wServiceStartName, wPassword, wDisplayName;
2070 BOOL r;
2072 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2073 hService, dwServiceType, dwStartType, dwErrorControl,
2074 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
2075 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
2076 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
2078 wBinaryPathName = SERV_dup( lpBinaryPathName );
2079 wLoadOrderGroup = SERV_dup( lpLoadOrderGroup );
2080 wDependencies = SERV_dupmulti( lpDependencies );
2081 wServiceStartName = SERV_dup( lpServiceStartName );
2082 wPassword = SERV_dup( lpPassword );
2083 wDisplayName = SERV_dup( lpDisplayName );
2085 r = ChangeServiceConfigW( hService, dwServiceType,
2086 dwStartType, dwErrorControl, wBinaryPathName,
2087 wLoadOrderGroup, lpdwTagId, wDependencies,
2088 wServiceStartName, wPassword, wDisplayName);
2090 HeapFree( GetProcessHeap(), 0, wBinaryPathName );
2091 HeapFree( GetProcessHeap(), 0, wLoadOrderGroup );
2092 HeapFree( GetProcessHeap(), 0, wDependencies );
2093 HeapFree( GetProcessHeap(), 0, wServiceStartName );
2094 HeapFree( GetProcessHeap(), 0, wPassword );
2095 HeapFree( GetProcessHeap(), 0, wDisplayName );
2097 return r;
2100 /******************************************************************************
2101 * ChangeServiceConfig2A [ADVAPI32.@]
2103 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
2104 LPVOID lpInfo)
2106 BOOL r = FALSE;
2108 TRACE("%p %d %p\n",hService, dwInfoLevel, lpInfo);
2110 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2112 LPSERVICE_DESCRIPTIONA sd = lpInfo;
2113 SERVICE_DESCRIPTIONW sdw;
2115 sdw.lpDescription = SERV_dup( sd->lpDescription );
2117 r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
2119 HeapFree( GetProcessHeap(), 0, sdw.lpDescription );
2121 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
2123 LPSERVICE_FAILURE_ACTIONSA fa = lpInfo;
2124 SERVICE_FAILURE_ACTIONSW faw;
2126 faw.dwResetPeriod = fa->dwResetPeriod;
2127 faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg );
2128 faw.lpCommand = SERV_dup( fa->lpCommand );
2129 faw.cActions = fa->cActions;
2130 faw.lpsaActions = fa->lpsaActions;
2132 r = ChangeServiceConfig2W( hService, dwInfoLevel, &faw );
2134 HeapFree( GetProcessHeap(), 0, faw.lpRebootMsg );
2135 HeapFree( GetProcessHeap(), 0, faw.lpCommand );
2137 else if (dwInfoLevel == SERVICE_CONFIG_PRESHUTDOWN_INFO)
2139 r = ChangeServiceConfig2W( hService, dwInfoLevel, lpInfo);
2141 else
2142 SetLastError( ERROR_INVALID_PARAMETER );
2144 return r;
2147 /******************************************************************************
2148 * ChangeServiceConfig2W [ADVAPI32.@]
2150 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
2151 LPVOID lpInfo)
2153 DWORD err;
2155 __TRY
2157 err = svcctl_ChangeServiceConfig2W( hService, dwInfoLevel, lpInfo );
2159 __EXCEPT(rpc_filter)
2161 err = map_exception_code(GetExceptionCode());
2163 __ENDTRY
2165 if (err != ERROR_SUCCESS)
2166 SetLastError(err);
2168 return err == ERROR_SUCCESS;
2171 NTSTATUS SERV_QueryServiceObjectSecurity(SC_HANDLE hService,
2172 SECURITY_INFORMATION dwSecurityInformation,
2173 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2174 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2176 SECURITY_DESCRIPTOR descriptor;
2177 NTSTATUS status;
2178 DWORD size;
2179 ACL acl;
2181 FIXME("%p %d %p %u %p - semi-stub\n", hService, dwSecurityInformation,
2182 lpSecurityDescriptor, cbBufSize, pcbBytesNeeded);
2184 if (dwSecurityInformation != DACL_SECURITY_INFORMATION)
2185 FIXME("information %d not supported\n", dwSecurityInformation);
2187 InitializeSecurityDescriptor(&descriptor, SECURITY_DESCRIPTOR_REVISION);
2189 InitializeAcl(&acl, sizeof(ACL), ACL_REVISION);
2190 SetSecurityDescriptorDacl(&descriptor, TRUE, &acl, TRUE);
2192 size = cbBufSize;
2193 status = RtlMakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
2194 *pcbBytesNeeded = size;
2195 return status;
2198 /******************************************************************************
2199 * QueryServiceObjectSecurity [ADVAPI32.@]
2201 BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
2202 SECURITY_INFORMATION dwSecurityInformation,
2203 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2204 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2206 NTSTATUS status = SERV_QueryServiceObjectSecurity(hService, dwSecurityInformation, lpSecurityDescriptor,
2207 cbBufSize, pcbBytesNeeded);
2208 if (status != STATUS_SUCCESS)
2210 SetLastError(RtlNtStatusToDosError(status));
2211 return FALSE;
2213 return TRUE;
2216 /******************************************************************************
2217 * SetServiceObjectSecurity [ADVAPI32.@]
2219 * NOTES
2220 * - SetSecurityInfo should be updated to call this function once it's implemented.
2222 BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService,
2223 SECURITY_INFORMATION dwSecurityInformation,
2224 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2226 FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
2227 return TRUE;
2230 /******************************************************************************
2231 * SetServiceBits [ADVAPI32.@]
2233 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
2234 DWORD dwServiceBits,
2235 BOOL bSetBitsOn,
2236 BOOL bUpdateImmediately)
2238 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
2239 bSetBitsOn, bUpdateImmediately);
2240 return TRUE;
2243 /* thunk for calling the RegisterServiceCtrlHandler handler function */
2244 static DWORD WINAPI ctrl_handler_thunk( DWORD control, DWORD type, void *data, void *context )
2246 LPHANDLER_FUNCTION func = context;
2248 func( control );
2249 return ERROR_SUCCESS;
2252 /******************************************************************************
2253 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
2255 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER_FUNCTION handler )
2257 return RegisterServiceCtrlHandlerExA( name, ctrl_handler_thunk, handler );
2260 /******************************************************************************
2261 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
2263 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLER_FUNCTION handler )
2265 return RegisterServiceCtrlHandlerExW( name, ctrl_handler_thunk, handler );
2268 /******************************************************************************
2269 * RegisterServiceCtrlHandlerExA [ADVAPI32.@]
2271 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDLER_FUNCTION_EX handler, LPVOID context )
2273 LPWSTR nameW;
2274 SERVICE_STATUS_HANDLE ret;
2276 nameW = SERV_dup(name);
2277 ret = RegisterServiceCtrlHandlerExW( nameW, handler, context );
2278 HeapFree( GetProcessHeap(), 0, nameW );
2279 return ret;
2282 /******************************************************************************
2283 * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
2285 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
2286 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2288 service_data *service;
2289 SC_HANDLE hService = 0;
2290 BOOL found = FALSE;
2292 TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
2294 EnterCriticalSection( &service_cs );
2295 if ((service = find_service_by_name( lpServiceName )))
2297 service->handler = lpHandlerProc;
2298 service->context = lpContext;
2299 hService = service->handle;
2300 found = TRUE;
2302 LeaveCriticalSection( &service_cs );
2304 if (!found) SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
2306 return (SERVICE_STATUS_HANDLE)hService;
2309 /******************************************************************************
2310 * EnumDependentServicesA [ADVAPI32.@]
2312 BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState,
2313 LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize,
2314 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2316 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2317 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2319 *lpServicesReturned = 0;
2320 return TRUE;
2323 /******************************************************************************
2324 * EnumDependentServicesW [ADVAPI32.@]
2326 BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
2327 LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize,
2328 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2330 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2331 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2333 *lpServicesReturned = 0;
2334 return TRUE;