quartz: Silence a fixme.
[wine/dcerpc.git] / dlls / advapi32 / service.c
blob29c1a09167452921a2a4feadfea2e1dccd936a87
1 /*
2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
5 * Copyright 2005 Mike McCormack
6 * Copyright 2007 Rolf Kalbermatter
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <string.h>
28 #include <time.h>
29 #include <assert.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winsvc.h"
34 #include "winerror.h"
35 #include "winreg.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
38 #include "winternl.h"
39 #include "lmcons.h"
40 #include "lmserver.h"
42 #include "svcctl.h"
44 #include "wine/exception.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(service);
48 static const WCHAR szLocalSystem[] = {'L','o','c','a','l','S','y','s','t','e','m',0};
49 static const WCHAR szServiceManagerKey[] = { 'S','y','s','t','e','m','\\',
50 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
51 'S','e','r','v','i','c','e','s',0 };
52 static const WCHAR szSCMLock[] = {'A','D','V','A','P','I','_','S','C','M',
53 'L','O','C','K',0};
55 void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len)
57 return HeapAlloc(GetProcessHeap(), 0, len);
60 void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
62 HeapFree(GetProcessHeap(), 0, ptr);
65 static const GENERIC_MAPPING scm_generic = {
66 (STANDARD_RIGHTS_READ | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS),
67 (STANDARD_RIGHTS_WRITE | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_MODIFY_BOOT_CONFIG),
68 (STANDARD_RIGHTS_EXECUTE | SC_MANAGER_CONNECT | SC_MANAGER_LOCK),
69 SC_MANAGER_ALL_ACCESS
72 static const GENERIC_MAPPING svc_generic = {
73 (STANDARD_RIGHTS_READ | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS),
74 (STANDARD_RIGHTS_WRITE | SERVICE_CHANGE_CONFIG),
75 (STANDARD_RIGHTS_EXECUTE | SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_USER_DEFINED_CONTROL),
76 SERVICE_ALL_ACCESS
79 typedef struct service_data_t
81 LPHANDLER_FUNCTION_EX handler;
82 LPVOID context;
83 HANDLE thread;
84 SC_HANDLE handle;
85 BOOL unicode : 1;
86 union {
87 LPSERVICE_MAIN_FUNCTIONA a;
88 LPSERVICE_MAIN_FUNCTIONW w;
89 } proc;
90 LPWSTR args;
91 WCHAR name[1];
92 } service_data;
94 static CRITICAL_SECTION service_cs;
95 static CRITICAL_SECTION_DEBUG service_cs_debug =
97 0, 0, &service_cs,
98 { &service_cs_debug.ProcessLocksList,
99 &service_cs_debug.ProcessLocksList },
100 0, 0, { (DWORD_PTR)(__FILE__ ": service_cs") }
102 static CRITICAL_SECTION service_cs = { &service_cs_debug, -1, 0, 0, 0, 0 };
104 static service_data **services;
105 static unsigned int nb_services;
106 static HANDLE service_event;
108 extern HANDLE __wine_make_process_system(void);
110 /******************************************************************************
111 * SC_HANDLEs
114 #define MAX_SERVICE_NAME 256
116 typedef enum { SC_HTYPE_MANAGER, SC_HTYPE_SERVICE } SC_HANDLE_TYPE;
118 struct sc_handle;
119 typedef VOID (*sc_handle_destructor)(struct sc_handle *);
121 struct sc_handle
123 SC_HANDLE_TYPE htype;
124 DWORD ref_count;
125 sc_handle_destructor destroy;
126 SC_RPC_HANDLE server_handle; /* server-side handle */
129 struct sc_manager /* service control manager handle */
131 struct sc_handle hdr;
132 HKEY hkey; /* handle to services database in the registry */
133 DWORD dwAccess;
136 struct sc_service /* service handle */
138 struct sc_handle hdr;
139 HKEY hkey; /* handle to service entry in the registry (under hkey) */
140 DWORD dwAccess;
141 struct sc_manager *scm; /* pointer to SCM handle */
142 WCHAR name[1];
145 static void *sc_handle_alloc(SC_HANDLE_TYPE htype, DWORD size,
146 sc_handle_destructor destroy)
148 struct sc_handle *hdr;
150 hdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
151 if (hdr)
153 hdr->htype = htype;
154 hdr->ref_count = 1;
155 hdr->destroy = destroy;
157 TRACE("sc_handle type=%d -> %p\n", htype, hdr);
158 return hdr;
161 static void *sc_handle_get_handle_data(SC_HANDLE handle, DWORD htype)
163 struct sc_handle *hdr = (struct sc_handle *) handle;
165 if (!hdr)
166 return NULL;
167 if (hdr->htype != htype)
168 return NULL;
169 return hdr;
172 static void sc_handle_free(struct sc_handle* hdr)
174 if (!hdr)
175 return;
176 if (--hdr->ref_count)
177 return;
178 hdr->destroy(hdr);
179 HeapFree(GetProcessHeap(), 0, hdr);
182 static void sc_handle_destroy_manager(struct sc_handle *handle)
184 struct sc_manager *mgr = (struct sc_manager*) handle;
186 TRACE("destroying SC Manager %p\n", mgr);
187 if (mgr->hkey)
188 RegCloseKey(mgr->hkey);
191 static void sc_handle_destroy_service(struct sc_handle *handle)
193 struct sc_service *svc = (struct sc_service*) handle;
195 TRACE("destroying service %p\n", svc);
196 if (svc->hkey)
197 RegCloseKey(svc->hkey);
198 svc->hkey = NULL;
199 sc_handle_free(&svc->scm->hdr);
200 svc->scm = NULL;
203 /******************************************************************************
204 * String management functions (same behaviour as strdup)
205 * NOTE: the caller of those functions is responsible for calling HeapFree
206 * in order to release the memory allocated by those functions.
208 static inline LPWSTR SERV_dup( LPCSTR str )
210 UINT len;
211 LPWSTR wstr;
213 if( !str )
214 return NULL;
215 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
216 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
217 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
218 return wstr;
221 static inline LPWSTR SERV_dupmulti(LPCSTR str)
223 UINT len = 0, n = 0;
224 LPWSTR wstr;
226 if( !str )
227 return NULL;
228 do {
229 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
230 n += (strlen( &str[n] ) + 1);
231 } while (str[n]);
232 len++;
233 n++;
235 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
236 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
237 return wstr;
240 static inline DWORD multisz_cb(LPCWSTR wmultisz)
242 const WCHAR *wptr = wmultisz;
244 if (wmultisz == NULL)
245 return 0;
247 while (*wptr)
248 wptr += lstrlenW(wptr)+1;
249 return (wptr - wmultisz + 1)*sizeof(WCHAR);
252 /******************************************************************************
253 * RPC connection with services.exe
256 handle_t __RPC_USER MACHINE_HANDLEW_bind(MACHINE_HANDLEW MachineName)
258 WCHAR transport[] = SVCCTL_TRANSPORT;
259 WCHAR endpoint[] = SVCCTL_ENDPOINT;
260 RPC_WSTR binding_str;
261 RPC_STATUS status;
262 handle_t rpc_handle;
264 status = RpcStringBindingComposeW(NULL, transport, (RPC_WSTR)MachineName, endpoint, NULL, &binding_str);
265 if (status != RPC_S_OK)
267 ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD)status);
268 return NULL;
271 status = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
272 RpcStringFreeW(&binding_str);
274 if (status != RPC_S_OK)
276 ERR("Couldn't connect to services.exe: error code %u\n", (DWORD)status);
277 return NULL;
280 return rpc_handle;
283 void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName, handle_t h)
285 RpcBindingFree(&h);
288 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr)
290 return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode);
293 static DWORD map_exception_code(DWORD exception_code)
295 switch (exception_code)
297 case RPC_X_NULL_REF_POINTER:
298 case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
299 case RPC_X_BYTE_COUNT_TOO_SMALL:
300 return ERROR_INVALID_PARAMETER;
301 default:
302 return exception_code;
306 /******************************************************************************
307 * Service IPC functions
309 static LPWSTR service_get_pipe_name(void)
311 static const WCHAR format[] = { '\\','\\','.','\\','p','i','p','e','\\',
312 'n','e','t','\\','N','t','C','o','n','t','r','o','l','P','i','p','e','%','u',0};
313 static const WCHAR service_current_key_str[] = { 'S','Y','S','T','E','M','\\',
314 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
315 'C','o','n','t','r','o','l','\\',
316 'S','e','r','v','i','c','e','C','u','r','r','e','n','t',0};
317 LPWSTR name;
318 DWORD len;
319 HKEY service_current_key;
320 DWORD service_current;
321 LONG ret;
322 DWORD type;
324 ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, service_current_key_str, 0,
325 KEY_QUERY_VALUE, &service_current_key);
326 if (ret != ERROR_SUCCESS)
327 return NULL;
328 len = sizeof(service_current);
329 ret = RegQueryValueExW(service_current_key, NULL, NULL, &type,
330 (BYTE *)&service_current, &len);
331 RegCloseKey(service_current_key);
332 if (ret != ERROR_SUCCESS || type != REG_DWORD)
333 return NULL;
334 len = sizeof(format)/sizeof(WCHAR) + 10 /* strlenW("4294967295") */;
335 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
336 if (!name)
337 return NULL;
338 snprintfW(name, len, format, service_current);
339 return name;
342 static HANDLE service_open_pipe(void)
344 LPWSTR szPipe = service_get_pipe_name();
345 HANDLE handle = INVALID_HANDLE_VALUE;
347 do {
348 handle = CreateFileW(szPipe, GENERIC_READ|GENERIC_WRITE,
349 0, NULL, OPEN_ALWAYS, 0, NULL);
350 if (handle != INVALID_HANDLE_VALUE)
351 break;
352 if (GetLastError() != ERROR_PIPE_BUSY)
353 break;
354 } while (WaitNamedPipeW(szPipe, NMPWAIT_WAIT_FOREVER));
355 HeapFree(GetProcessHeap(), 0, szPipe);
357 return handle;
360 static service_data *find_service_by_name( const WCHAR *name )
362 unsigned int i;
364 if (nb_services == 1) /* only one service (FIXME: should depend on OWN_PROCESS etc.) */
365 return services[0];
366 for (i = 0; i < nb_services; i++)
367 if (!strcmpiW( name, services[i]->name )) return services[i];
368 return NULL;
371 /******************************************************************************
372 * service_thread
374 * Call into the main service routine provided by StartServiceCtrlDispatcher.
376 static DWORD WINAPI service_thread(LPVOID arg)
378 service_data *info = arg;
379 LPWSTR str = info->args;
380 DWORD argc = 0, len = 0;
382 TRACE("%p\n", arg);
384 while (str[len])
386 len += strlenW(&str[len]) + 1;
387 argc++;
390 if (!argc)
392 if (info->unicode)
393 info->proc.w(0, NULL);
394 else
395 info->proc.a(0, NULL);
396 return 0;
399 if (info->unicode)
401 LPWSTR *argv, p;
403 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR));
404 for (argc=0, p=str; *p; p += strlenW(p) + 1)
405 argv[argc++] = p;
406 argv[argc] = NULL;
408 info->proc.w(argc, argv);
409 HeapFree(GetProcessHeap(), 0, argv);
411 else
413 LPSTR strA, *argv, p;
414 DWORD lenA;
416 lenA = WideCharToMultiByte(CP_ACP,0, str, len, NULL, 0, NULL, NULL);
417 strA = HeapAlloc(GetProcessHeap(), 0, lenA);
418 WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL);
420 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPSTR));
421 for (argc=0, p=strA; *p; p += strlen(p) + 1)
422 argv[argc++] = p;
423 argv[argc] = NULL;
425 info->proc.a(argc, argv);
426 HeapFree(GetProcessHeap(), 0, argv);
427 HeapFree(GetProcessHeap(), 0, strA);
429 return 0;
432 /******************************************************************************
433 * service_handle_start
435 static DWORD service_handle_start(service_data *service, const WCHAR *data, DWORD count)
437 TRACE("%s argsize %u\n", debugstr_w(service->name), count);
439 if (service->thread)
441 WARN("service is not stopped\n");
442 return ERROR_SERVICE_ALREADY_RUNNING;
445 HeapFree(GetProcessHeap(), 0, service->args);
446 service->args = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
447 memcpy( service->args, data, count * sizeof(WCHAR) );
448 service->thread = CreateThread( NULL, 0, service_thread,
449 service, 0, NULL );
450 SetEvent( service_event ); /* notify the main loop */
451 return 0;
454 /******************************************************************************
455 * service_handle_control
457 static DWORD service_handle_control(service_data *service, DWORD dwControl)
459 DWORD ret = ERROR_INVALID_SERVICE_CONTROL;
461 TRACE("%s control %u\n", debugstr_w(service->name), dwControl);
463 if (service->handler)
464 ret = service->handler(dwControl, 0, NULL, service->context);
465 return ret;
468 /******************************************************************************
469 * service_control_dispatcher
471 static DWORD WINAPI service_control_dispatcher(LPVOID arg)
473 SC_HANDLE manager;
474 HANDLE pipe;
476 if (!(manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
478 ERR("failed to open service manager error %u\n", GetLastError());
479 return 0;
482 pipe = service_open_pipe();
484 if (pipe==INVALID_HANDLE_VALUE)
486 ERR("failed to create control pipe error = %d\n", GetLastError());
487 return 0;
490 /* dispatcher loop */
491 while (1)
493 service_data *service;
494 service_start_info info;
495 WCHAR *data = NULL;
496 BOOL r;
497 DWORD data_size = 0, count, result;
499 r = ReadFile( pipe, &info, FIELD_OFFSET(service_start_info,data), &count, NULL );
500 if (!r)
502 if (GetLastError() != ERROR_BROKEN_PIPE)
503 ERR( "pipe read failed error %u\n", GetLastError() );
504 break;
506 if (count != FIELD_OFFSET(service_start_info,data))
508 ERR( "partial pipe read %u\n", count );
509 break;
511 if (count < info.total_size)
513 data_size = info.total_size - FIELD_OFFSET(service_start_info,data);
514 data = HeapAlloc( GetProcessHeap(), 0, data_size );
515 r = ReadFile( pipe, data, data_size, &count, NULL );
516 if (!r)
518 if (GetLastError() != ERROR_BROKEN_PIPE)
519 ERR( "pipe read failed error %u\n", GetLastError() );
520 break;
522 if (count != data_size)
524 ERR( "partial pipe read %u/%u\n", count, data_size );
525 break;
529 /* find the service */
531 if (!(service = find_service_by_name( data )))
533 FIXME( "got request %u for unknown service %s\n", info.cmd, debugstr_w(data));
534 result = ERROR_INVALID_PARAMETER;
535 goto done;
538 TRACE( "got request %u for service %s\n", info.cmd, debugstr_w(data) );
540 /* handle the request */
541 switch (info.cmd)
543 case WINESERV_STARTINFO:
544 if (!service->handle)
546 if (!(service->handle = OpenServiceW( manager, data, SERVICE_SET_STATUS )))
547 FIXME( "failed to open service %s\n", debugstr_w(data) );
549 result = service_handle_start(service, data + info.name_size,
550 data_size / sizeof(WCHAR) - info.name_size );
551 break;
552 case WINESERV_SENDCONTROL:
553 result = service_handle_control(service, info.control);
554 break;
555 default:
556 ERR("received invalid command %u\n", info.cmd);
557 result = ERROR_INVALID_PARAMETER;
558 break;
561 done:
562 WriteFile(pipe, &result, sizeof(result), &count, NULL);
563 HeapFree( GetProcessHeap(), 0, data );
566 CloseHandle(pipe);
567 CloseServiceHandle( manager );
568 return 1;
571 /******************************************************************************
572 * service_run_main_thread
574 static BOOL service_run_main_thread(void)
576 DWORD i, n, ret;
577 HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
578 UINT wait_services[MAXIMUM_WAIT_OBJECTS];
580 service_event = CreateEventW( NULL, FALSE, FALSE, NULL );
582 /* FIXME: service_control_dispatcher should be merged into the main thread */
583 wait_handles[0] = __wine_make_process_system();
584 wait_handles[1] = CreateThread( NULL, 0, service_control_dispatcher, NULL, 0, NULL );
585 wait_handles[2] = service_event;
587 TRACE("Starting %d services running as process %d\n",
588 nb_services, GetCurrentProcessId());
590 /* wait for all the threads to pack up and exit */
591 for (;;)
593 EnterCriticalSection( &service_cs );
594 for (i = 0, n = 3; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
596 if (!services[i]->thread) continue;
597 wait_services[n] = i;
598 wait_handles[n++] = services[i]->thread;
600 LeaveCriticalSection( &service_cs );
602 ret = WaitForMultipleObjects( n, wait_handles, FALSE, INFINITE );
603 if (!ret) /* system process event */
605 TRACE( "last user process exited, shutting down\n" );
606 /* FIXME: we should maybe send a shutdown control to running services */
607 ExitProcess(0);
609 else if (ret == 1)
611 TRACE( "control dispatcher exited, shutting down\n" );
612 /* FIXME: we should maybe send a shutdown control to running services */
613 ExitProcess(0);
615 else if (ret == 2)
617 continue; /* rebuild the list */
619 else if (ret < n)
621 services[wait_services[ret]]->thread = 0;
622 CloseHandle( wait_handles[ret] );
623 if (n == 4) return TRUE; /* it was the last running thread */
625 else return FALSE;
629 /******************************************************************************
630 * StartServiceCtrlDispatcherA [ADVAPI32.@]
632 * See StartServiceCtrlDispatcherW.
634 BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
636 service_data *info;
637 unsigned int i;
638 BOOL ret = TRUE;
640 TRACE("%p\n", servent);
642 if (nb_services)
644 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
645 return FALSE;
647 while (servent[nb_services].lpServiceName) nb_services++;
648 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
650 for (i = 0; i < nb_services; i++)
652 DWORD len = MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, NULL, 0);
653 DWORD sz = FIELD_OFFSET( service_data, name[len] );
654 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
655 MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, info->name, len);
656 info->proc.a = servent[i].lpServiceProc;
657 info->unicode = FALSE;
658 services[i] = info;
661 service_run_main_thread();
663 return ret;
666 /******************************************************************************
667 * StartServiceCtrlDispatcherW [ADVAPI32.@]
669 * Connects a process containing one or more services to the service control
670 * manager.
672 * PARAMS
673 * servent [I] A list of the service names and service procedures
675 * RETURNS
676 * Success: TRUE.
677 * Failure: FALSE.
679 BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
681 service_data *info;
682 unsigned int i;
683 BOOL ret = TRUE;
685 TRACE("%p\n", servent);
687 if (nb_services)
689 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
690 return FALSE;
692 while (servent[nb_services].lpServiceName) nb_services++;
693 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
695 for (i = 0; i < nb_services; i++)
697 DWORD len = strlenW(servent[i].lpServiceName) + 1;
698 DWORD sz = FIELD_OFFSET( service_data, name[len] );
699 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
700 strcpyW(info->name, servent[i].lpServiceName);
701 info->proc.w = servent[i].lpServiceProc;
702 info->unicode = TRUE;
703 services[i] = info;
706 service_run_main_thread();
708 return ret;
711 /******************************************************************************
712 * LockServiceDatabase [ADVAPI32.@]
714 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
716 struct sc_manager *hscm;
717 SC_RPC_LOCK hLock = NULL;
718 DWORD err;
720 TRACE("%p\n",hSCManager);
722 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
723 if (!hscm)
725 SetLastError( ERROR_INVALID_HANDLE );
726 return NULL;
729 __TRY
731 err = svcctl_LockServiceDatabase(hscm->hdr.server_handle, &hLock);
733 __EXCEPT(rpc_filter)
735 err = map_exception_code(GetExceptionCode());
737 __ENDTRY
738 if (err != ERROR_SUCCESS)
740 SetLastError(err);
741 return NULL;
743 return hLock;
746 /******************************************************************************
747 * UnlockServiceDatabase [ADVAPI32.@]
749 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
751 DWORD err;
752 SC_RPC_LOCK hRpcLock = ScLock;
754 TRACE("%p\n",ScLock);
756 __TRY
758 err = svcctl_UnlockServiceDatabase(&hRpcLock);
760 __EXCEPT(rpc_filter)
762 err = map_exception_code(GetExceptionCode());
764 __ENDTRY
765 if (err != ERROR_SUCCESS)
767 SetLastError(err);
768 return FALSE;
770 return TRUE;
773 /******************************************************************************
774 * SetServiceStatus [ADVAPI32.@]
776 * PARAMS
777 * hService []
778 * lpStatus []
780 BOOL WINAPI
781 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
783 struct sc_service *hsvc;
784 DWORD err;
786 TRACE("%p %x %x %x %x %x %x %x\n", hService,
787 lpStatus->dwServiceType, lpStatus->dwCurrentState,
788 lpStatus->dwControlsAccepted, lpStatus->dwWin32ExitCode,
789 lpStatus->dwServiceSpecificExitCode, lpStatus->dwCheckPoint,
790 lpStatus->dwWaitHint);
792 hsvc = sc_handle_get_handle_data((SC_HANDLE)hService, SC_HTYPE_SERVICE);
793 if (!hsvc)
795 SetLastError( ERROR_INVALID_HANDLE );
796 return FALSE;
799 __TRY
801 err = svcctl_SetServiceStatus( hsvc->hdr.server_handle, lpStatus );
803 __EXCEPT(rpc_filter)
805 err = map_exception_code(GetExceptionCode());
807 __ENDTRY
808 if (err != ERROR_SUCCESS)
810 SetLastError(err);
811 return FALSE;
814 if (lpStatus->dwCurrentState == SERVICE_STOPPED)
815 CloseServiceHandle((SC_HANDLE)hService);
817 return TRUE;
821 /******************************************************************************
822 * OpenSCManagerA [ADVAPI32.@]
824 * Establish a connection to the service control manager and open its database.
826 * PARAMS
827 * lpMachineName [I] Pointer to machine name string
828 * lpDatabaseName [I] Pointer to database name string
829 * dwDesiredAccess [I] Type of access
831 * RETURNS
832 * Success: A Handle to the service control manager database
833 * Failure: NULL
835 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
836 DWORD dwDesiredAccess )
838 LPWSTR lpMachineNameW, lpDatabaseNameW;
839 SC_HANDLE ret;
841 lpMachineNameW = SERV_dup(lpMachineName);
842 lpDatabaseNameW = SERV_dup(lpDatabaseName);
843 ret = OpenSCManagerW(lpMachineNameW, lpDatabaseNameW, dwDesiredAccess);
844 HeapFree(GetProcessHeap(), 0, lpDatabaseNameW);
845 HeapFree(GetProcessHeap(), 0, lpMachineNameW);
846 return ret;
849 /******************************************************************************
850 * OpenSCManagerW [ADVAPI32.@]
852 * See OpenSCManagerA.
854 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
855 DWORD dwDesiredAccess )
857 struct sc_manager *manager;
858 HKEY hReg;
859 LONG r;
860 DWORD new_mask = dwDesiredAccess;
862 TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
863 debugstr_w(lpDatabaseName), dwDesiredAccess);
865 manager = sc_handle_alloc( SC_HTYPE_MANAGER, sizeof (struct sc_manager),
866 sc_handle_destroy_manager );
867 if (!manager)
868 return NULL;
870 __TRY
872 r = svcctl_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, &manager->hdr.server_handle);
874 __EXCEPT(rpc_filter)
876 r = map_exception_code(GetExceptionCode());
878 __ENDTRY
879 if (r!=ERROR_SUCCESS)
880 goto error;
882 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
883 if (r!=ERROR_SUCCESS)
884 goto error;
886 r = RegCreateKeyW(hReg, szServiceManagerKey, &manager->hkey);
887 RegCloseKey( hReg );
888 if (r!=ERROR_SUCCESS)
889 goto error;
891 RtlMapGenericMask(&new_mask, &scm_generic);
892 manager->dwAccess = new_mask;
893 TRACE("returning %p (access : 0x%08x)\n", manager, manager->dwAccess);
895 return (SC_HANDLE) &manager->hdr;
897 error:
898 sc_handle_free( &manager->hdr );
899 SetLastError( r);
900 return NULL;
903 /******************************************************************************
904 * ControlService [ADVAPI32.@]
906 * Send a control code to a service.
908 * PARAMS
909 * hService [I] Handle of the service control manager database
910 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
911 * lpServiceStatus [O] Destination for the status of the service, if available
913 * RETURNS
914 * Success: TRUE.
915 * Failure: FALSE.
917 * BUGS
918 * Unlike M$' implementation, control requests are not serialized and may be
919 * processed asynchronously.
921 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
922 LPSERVICE_STATUS lpServiceStatus )
924 struct sc_service *hsvc;
925 DWORD err;
927 TRACE("%p %d %p\n", hService, dwControl, lpServiceStatus);
929 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
930 if (!hsvc)
932 SetLastError( ERROR_INVALID_HANDLE );
933 return FALSE;
936 __TRY
938 err = svcctl_ControlService(hsvc->hdr.server_handle, dwControl, lpServiceStatus);
940 __EXCEPT(rpc_filter)
942 err = map_exception_code(GetExceptionCode());
944 __ENDTRY
945 if (err != ERROR_SUCCESS)
947 SetLastError(err);
948 return FALSE;
951 return TRUE;
954 /******************************************************************************
955 * CloseServiceHandle [ADVAPI32.@]
957 * Close a handle to a service or the service control manager database.
959 * PARAMS
960 * hSCObject [I] Handle to service or service control manager database
962 * RETURNS
963 * Success: TRUE
964 * Failure: FALSE
966 BOOL WINAPI
967 CloseServiceHandle( SC_HANDLE hSCObject )
969 struct sc_handle *obj;
970 DWORD err;
972 TRACE("%p\n", hSCObject);
973 if (hSCObject == NULL)
975 SetLastError(ERROR_INVALID_HANDLE);
976 return FALSE;
979 obj = (struct sc_handle *)hSCObject;
980 __TRY
982 err = svcctl_CloseServiceHandle(&obj->server_handle);
984 __EXCEPT(rpc_filter)
986 err = map_exception_code(GetExceptionCode());
988 __ENDTRY
989 sc_handle_free( obj );
991 if (err != ERROR_SUCCESS)
993 SetLastError(err);
994 return FALSE;
996 return TRUE;
1000 /******************************************************************************
1001 * OpenServiceA [ADVAPI32.@]
1003 * Open a handle to a service.
1005 * PARAMS
1006 * hSCManager [I] Handle of the service control manager database
1007 * lpServiceName [I] Name of the service to open
1008 * dwDesiredAccess [I] Access required to the service
1010 * RETURNS
1011 * Success: Handle to the service
1012 * Failure: NULL
1014 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1015 DWORD dwDesiredAccess )
1017 LPWSTR lpServiceNameW;
1018 SC_HANDLE ret;
1020 TRACE("%p %s %d\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
1022 lpServiceNameW = SERV_dup(lpServiceName);
1023 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
1024 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1025 return ret;
1029 /******************************************************************************
1030 * OpenServiceW [ADVAPI32.@]
1032 * See OpenServiceA.
1034 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1035 DWORD dwDesiredAccess)
1037 struct sc_manager *hscm;
1038 struct sc_service *hsvc;
1039 DWORD err;
1040 DWORD len;
1041 DWORD new_mask = dwDesiredAccess;
1043 TRACE("%p %s %d\n", hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
1045 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
1046 if (!hscm)
1048 SetLastError( ERROR_INVALID_HANDLE );
1049 return FALSE;
1052 if (!lpServiceName)
1054 SetLastError(ERROR_INVALID_ADDRESS);
1055 return NULL;
1058 len = strlenW(lpServiceName)+1;
1059 hsvc = sc_handle_alloc( SC_HTYPE_SERVICE,
1060 sizeof (struct sc_service) + len*sizeof(WCHAR),
1061 sc_handle_destroy_service );
1062 if (!hsvc)
1064 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1065 return NULL;
1067 strcpyW( hsvc->name, lpServiceName );
1069 /* add reference to SCM handle */
1070 hscm->hdr.ref_count++;
1071 hsvc->scm = hscm;
1073 __TRY
1075 err = svcctl_OpenServiceW(hscm->hdr.server_handle, lpServiceName, dwDesiredAccess, &hsvc->hdr.server_handle);
1077 __EXCEPT(rpc_filter)
1079 err = map_exception_code(GetExceptionCode());
1081 __ENDTRY
1083 if (err != ERROR_SUCCESS)
1085 sc_handle_free(&hsvc->hdr);
1086 SetLastError(err);
1087 return NULL;
1090 /* for parts of advapi32 not using services.exe yet */
1091 RtlMapGenericMask(&new_mask, &svc_generic);
1092 hsvc->dwAccess = new_mask;
1094 err = RegOpenKeyExW( hscm->hkey, lpServiceName, 0, KEY_ALL_ACCESS, &hsvc->hkey );
1095 if (err != ERROR_SUCCESS)
1096 ERR("Shouldn't hapen - service key for service validated by services.exe doesn't exist\n");
1098 TRACE("returning %p\n",hsvc);
1100 return (SC_HANDLE) &hsvc->hdr;
1103 /******************************************************************************
1104 * CreateServiceW [ADVAPI32.@]
1106 SC_HANDLE WINAPI
1107 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1108 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
1109 DWORD dwServiceType, DWORD dwStartType,
1110 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1111 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1112 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
1113 LPCWSTR lpPassword )
1115 struct sc_manager *hscm;
1116 struct sc_service *hsvc = NULL;
1117 DWORD new_mask = dwDesiredAccess;
1118 DWORD len, err;
1119 SIZE_T passwdlen;
1121 TRACE("%p %s %s\n", hSCManager,
1122 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
1124 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
1125 if (!hscm)
1127 SetLastError( ERROR_INVALID_HANDLE );
1128 return NULL;
1131 if (!lpServiceName || !lpBinaryPathName)
1133 SetLastError(ERROR_INVALID_ADDRESS);
1134 return NULL;
1137 if (lpPassword)
1138 passwdlen = (strlenW(lpPassword) + 1) * sizeof(WCHAR);
1139 else
1140 passwdlen = 0;
1142 len = strlenW(lpServiceName)+1;
1143 len = sizeof (struct sc_service) + len*sizeof(WCHAR);
1144 hsvc = sc_handle_alloc( SC_HTYPE_SERVICE, len, sc_handle_destroy_service );
1145 if( !hsvc )
1147 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1148 return NULL;
1150 lstrcpyW( hsvc->name, lpServiceName );
1152 hsvc->scm = hscm;
1153 hscm->hdr.ref_count++;
1155 __TRY
1157 err = svcctl_CreateServiceW(hscm->hdr.server_handle, lpServiceName,
1158 lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1159 lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, (LPBYTE)lpDependencies,
1160 multisz_cb(lpDependencies), lpServiceStartName, (LPBYTE)lpPassword, passwdlen,
1161 &hsvc->hdr.server_handle);
1163 __EXCEPT(rpc_filter)
1165 err = map_exception_code(GetExceptionCode());
1167 __ENDTRY
1169 if (err != ERROR_SUCCESS)
1171 SetLastError(err);
1172 sc_handle_free(&hsvc->hdr);
1173 return NULL;
1176 /* for parts of advapi32 not using services.exe yet */
1177 err = RegOpenKeyW(hscm->hkey, lpServiceName, &hsvc->hkey);
1178 if (err != ERROR_SUCCESS)
1179 WINE_ERR("Couldn't open key that should have been created by services.exe\n");
1181 RtlMapGenericMask(&new_mask, &svc_generic);
1182 hsvc->dwAccess = new_mask;
1184 return (SC_HANDLE) &hsvc->hdr;
1188 /******************************************************************************
1189 * CreateServiceA [ADVAPI32.@]
1191 SC_HANDLE WINAPI
1192 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1193 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
1194 DWORD dwServiceType, DWORD dwStartType,
1195 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1196 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1197 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
1198 LPCSTR lpPassword )
1200 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
1201 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
1202 SC_HANDLE r;
1204 TRACE("%p %s %s\n", hSCManager,
1205 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
1207 lpServiceNameW = SERV_dup( lpServiceName );
1208 lpDisplayNameW = SERV_dup( lpDisplayName );
1209 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
1210 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
1211 lpDependenciesW = SERV_dupmulti( lpDependencies );
1212 lpServiceStartNameW = SERV_dup( lpServiceStartName );
1213 lpPasswordW = SERV_dup( lpPassword );
1215 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
1216 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1217 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
1218 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
1220 HeapFree( GetProcessHeap(), 0, lpServiceNameW );
1221 HeapFree( GetProcessHeap(), 0, lpDisplayNameW );
1222 HeapFree( GetProcessHeap(), 0, lpBinaryPathNameW );
1223 HeapFree( GetProcessHeap(), 0, lpLoadOrderGroupW );
1224 HeapFree( GetProcessHeap(), 0, lpDependenciesW );
1225 HeapFree( GetProcessHeap(), 0, lpServiceStartNameW );
1226 HeapFree( GetProcessHeap(), 0, lpPasswordW );
1228 return r;
1232 /******************************************************************************
1233 * DeleteService [ADVAPI32.@]
1235 * Delete a service from the service control manager database.
1237 * PARAMS
1238 * hService [I] Handle of the service to delete
1240 * RETURNS
1241 * Success: TRUE
1242 * Failure: FALSE
1244 BOOL WINAPI DeleteService( SC_HANDLE hService )
1246 struct sc_service *hsvc;
1247 DWORD err;
1249 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1250 if (!hsvc)
1252 SetLastError( ERROR_INVALID_HANDLE );
1253 return FALSE;
1256 __TRY
1258 err = svcctl_DeleteService(hsvc->hdr.server_handle);
1260 __EXCEPT(rpc_filter)
1262 err = map_exception_code(GetExceptionCode());
1264 __ENDTRY
1265 if (err != 0)
1267 SetLastError(err);
1268 return FALSE;
1271 /* Close the key to the service */
1272 RegCloseKey(hsvc->hkey);
1273 hsvc->hkey = NULL;
1274 return TRUE;
1278 /******************************************************************************
1279 * StartServiceA [ADVAPI32.@]
1281 * Start a service
1283 * PARAMS
1284 * hService [I] Handle of service
1285 * dwNumServiceArgs [I] Number of arguments
1286 * lpServiceArgVectors [I] Address of array of argument strings
1288 * NOTES
1289 * - NT implements this function using an obscure RPC call.
1290 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1291 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
1292 * - This will only work for shared address space. How should the service
1293 * args be transferred when address spaces are separated?
1294 * - Can only start one service at a time.
1295 * - Has no concept of privilege.
1297 * RETURNS
1298 * Success: TRUE.
1299 * Failure: FALSE
1301 BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
1302 LPCSTR *lpServiceArgVectors )
1304 LPWSTR *lpwstr=NULL;
1305 unsigned int i;
1306 BOOL r;
1308 TRACE("(%p,%d,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
1310 if (dwNumServiceArgs)
1311 lpwstr = HeapAlloc( GetProcessHeap(), 0,
1312 dwNumServiceArgs*sizeof(LPWSTR) );
1314 for(i=0; i<dwNumServiceArgs; i++)
1315 lpwstr[i]=SERV_dup(lpServiceArgVectors[i]);
1317 r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
1319 if (dwNumServiceArgs)
1321 for(i=0; i<dwNumServiceArgs; i++)
1322 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
1323 HeapFree(GetProcessHeap(), 0, lpwstr);
1326 return r;
1330 /******************************************************************************
1331 * StartServiceW [ADVAPI32.@]
1333 * See StartServiceA.
1335 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1336 LPCWSTR *lpServiceArgVectors)
1338 struct sc_service *hsvc;
1339 DWORD err;
1341 TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1343 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1344 if (!hsvc)
1346 SetLastError(ERROR_INVALID_HANDLE);
1347 return FALSE;
1350 __TRY
1352 err = svcctl_StartServiceW(hsvc->hdr.server_handle, dwNumServiceArgs, lpServiceArgVectors);
1354 __EXCEPT(rpc_filter)
1356 err = map_exception_code(GetExceptionCode());
1358 __ENDTRY
1359 if (err != ERROR_SUCCESS)
1361 SetLastError(err);
1362 return FALSE;
1365 return TRUE;
1368 /******************************************************************************
1369 * QueryServiceStatus [ADVAPI32.@]
1371 * PARAMS
1372 * hService [I] Handle to service to get information about
1373 * lpservicestatus [O] buffer to receive the status information for the service
1376 BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
1377 LPSERVICE_STATUS lpservicestatus)
1379 SERVICE_STATUS_PROCESS SvcStatusData;
1380 BOOL ret;
1381 DWORD dummy;
1383 TRACE("%p %p\n", hService, lpservicestatus);
1385 ret = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&SvcStatusData,
1386 sizeof(SERVICE_STATUS_PROCESS), &dummy);
1387 if (ret) memcpy(lpservicestatus, &SvcStatusData, sizeof(SERVICE_STATUS)) ;
1388 return ret;
1392 /******************************************************************************
1393 * QueryServiceStatusEx [ADVAPI32.@]
1395 * Get information about a service.
1397 * PARAMS
1398 * hService [I] Handle to service to get information about
1399 * InfoLevel [I] Level of information to get
1400 * lpBuffer [O] Destination for requested information
1401 * cbBufSize [I] Size of lpBuffer in bytes
1402 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1404 * RETURNS
1405 * Success: TRUE
1406 * FAILURE: FALSE
1408 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1409 LPBYTE lpBuffer, DWORD cbBufSize,
1410 LPDWORD pcbBytesNeeded)
1412 struct sc_service *hsvc;
1413 DWORD err;
1415 TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1417 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1418 if (!hsvc)
1420 SetLastError( ERROR_INVALID_HANDLE );
1421 return FALSE;
1424 __TRY
1426 err = svcctl_QueryServiceStatusEx(hsvc->hdr.server_handle, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1428 __EXCEPT(rpc_filter)
1430 err = map_exception_code(GetExceptionCode());
1432 __ENDTRY
1433 if (err != ERROR_SUCCESS)
1435 SetLastError(err);
1436 return FALSE;
1439 return TRUE;
1442 /******************************************************************************
1443 * QueryServiceConfigA [ADVAPI32.@]
1445 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1446 DWORD size, LPDWORD needed )
1448 DWORD n;
1449 LPSTR p, buffer;
1450 BOOL ret;
1451 QUERY_SERVICE_CONFIGW *configW;
1453 TRACE("%p %p %d %p\n", hService, config, size, needed);
1455 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, 2 * size )))
1457 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1458 return FALSE;
1460 configW = (QUERY_SERVICE_CONFIGW *)buffer;
1461 ret = QueryServiceConfigW( hService, configW, 2 * size, needed );
1462 if (!ret) goto done;
1464 config->dwServiceType = configW->dwServiceType;
1465 config->dwStartType = configW->dwStartType;
1466 config->dwErrorControl = configW->dwErrorControl;
1467 config->lpBinaryPathName = NULL;
1468 config->lpLoadOrderGroup = NULL;
1469 config->dwTagId = configW->dwTagId;
1470 config->lpDependencies = NULL;
1471 config->lpServiceStartName = NULL;
1472 config->lpDisplayName = NULL;
1474 p = (LPSTR)(config + 1);
1475 n = size - sizeof(*config);
1476 ret = FALSE;
1478 #define MAP_STR(str) \
1479 do { \
1480 if (configW->str) \
1482 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1483 if (!sz) goto done; \
1484 config->str = p; \
1485 p += sz; \
1486 n -= sz; \
1488 } while (0)
1490 MAP_STR( lpBinaryPathName );
1491 MAP_STR( lpLoadOrderGroup );
1492 MAP_STR( lpDependencies );
1493 MAP_STR( lpServiceStartName );
1494 MAP_STR( lpDisplayName );
1495 #undef MAP_STR
1497 *needed = p - (LPSTR)config;
1498 ret = TRUE;
1500 done:
1501 HeapFree( GetProcessHeap(), 0, buffer );
1502 return ret;
1505 static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
1507 DWORD cb;
1509 if (!*string_ptr)
1511 cb = sizeof(WCHAR);
1512 memset(*buf, 0, cb);
1514 else
1516 cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
1517 memcpy(*buf, *string_ptr, cb);
1518 MIDL_user_free(*string_ptr);
1521 *string_ptr = (LPWSTR)*buf;
1522 *buf += cb;
1524 return cb;
1527 static DWORD size_string(LPWSTR string)
1529 return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
1532 /******************************************************************************
1533 * QueryServiceConfigW [ADVAPI32.@]
1535 BOOL WINAPI
1536 QueryServiceConfigW( SC_HANDLE hService,
1537 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1538 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1540 QUERY_SERVICE_CONFIGW config;
1541 struct sc_service *hsvc;
1542 DWORD total;
1543 DWORD err;
1544 BYTE *bufpos;
1546 TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1547 cbBufSize, pcbBytesNeeded);
1549 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1550 if (!hsvc)
1552 SetLastError( ERROR_INVALID_HANDLE );
1553 return FALSE;
1556 memset(&config, 0, sizeof(config));
1558 __TRY
1560 err = svcctl_QueryServiceConfigW(hsvc->hdr.server_handle, &config);
1562 __EXCEPT(rpc_filter)
1564 err = map_exception_code(GetExceptionCode());
1566 __ENDTRY
1568 if (err != ERROR_SUCCESS)
1570 TRACE("services.exe: error %u\n", err);
1571 SetLastError(err);
1572 return FALSE;
1575 /* calculate the size required first */
1576 total = sizeof (QUERY_SERVICE_CONFIGW);
1577 total += size_string(config.lpBinaryPathName);
1578 total += size_string(config.lpLoadOrderGroup);
1579 total += size_string(config.lpDependencies);
1580 total += size_string(config.lpServiceStartName);
1581 total += size_string(config.lpDisplayName);
1583 *pcbBytesNeeded = total;
1585 /* if there's not enough memory, return an error */
1586 if( total > cbBufSize )
1588 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1589 MIDL_user_free(config.lpBinaryPathName);
1590 MIDL_user_free(config.lpLoadOrderGroup);
1591 MIDL_user_free(config.lpDependencies);
1592 MIDL_user_free(config.lpServiceStartName);
1593 MIDL_user_free(config.lpDisplayName);
1594 return FALSE;
1597 *lpServiceConfig = config;
1598 bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
1599 move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
1600 move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
1601 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
1602 move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
1603 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
1605 if (bufpos - (LPBYTE)lpServiceConfig > cbBufSize)
1606 ERR("Buffer overflow!\n");
1608 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1609 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1610 TRACE("Dependencies = %s\n", debugstr_w(lpServiceConfig->lpDependencies) );
1611 TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig->lpServiceStartName) );
1612 TRACE("Display name = %s\n", debugstr_w(lpServiceConfig->lpDisplayName) );
1614 return TRUE;
1617 /******************************************************************************
1618 * QueryServiceConfig2A [ADVAPI32.@]
1620 * Note
1621 * observed under win2k:
1622 * The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
1623 * required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
1625 BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1626 DWORD size, LPDWORD needed)
1628 BOOL ret;
1629 LPBYTE bufferW = NULL;
1631 if(buffer && size)
1632 bufferW = HeapAlloc( GetProcessHeap(), 0, size);
1634 ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
1635 if(!ret) goto cleanup;
1637 switch(dwLevel) {
1638 case SERVICE_CONFIG_DESCRIPTION:
1639 { LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
1640 LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
1641 if (configW->lpDescription) {
1642 DWORD sz;
1643 configA->lpDescription = (LPSTR)(configA + 1);
1644 sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
1645 configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
1646 if (!sz) {
1647 FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1648 ret = FALSE;
1649 configA->lpDescription = NULL;
1652 else configA->lpDescription = NULL;
1654 break;
1655 default:
1656 FIXME("conversation W->A not implemented for level %d\n", dwLevel);
1657 ret = FALSE;
1660 cleanup:
1661 HeapFree( GetProcessHeap(), 0, bufferW);
1662 return ret;
1665 /******************************************************************************
1666 * QueryServiceConfig2W [ADVAPI32.@]
1668 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1669 DWORD size, LPDWORD needed)
1671 DWORD sz, type;
1672 HKEY hKey;
1673 LONG r;
1674 struct sc_service *hsvc;
1676 if(dwLevel != SERVICE_CONFIG_DESCRIPTION) {
1677 if((dwLevel == SERVICE_CONFIG_DELAYED_AUTO_START_INFO) ||
1678 (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS) ||
1679 (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS_FLAG) ||
1680 (dwLevel == SERVICE_CONFIG_PRESHUTDOWN_INFO) ||
1681 (dwLevel == SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO) ||
1682 (dwLevel == SERVICE_CONFIG_SERVICE_SID_INFO))
1683 FIXME("Level %d not implemented\n", dwLevel);
1684 SetLastError(ERROR_INVALID_LEVEL);
1685 return FALSE;
1687 if(!needed || (!buffer && size)) {
1688 SetLastError(ERROR_INVALID_ADDRESS);
1689 return FALSE;
1692 TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
1694 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1695 if (!hsvc)
1697 SetLastError(ERROR_INVALID_HANDLE);
1698 return FALSE;
1700 hKey = hsvc->hkey;
1702 switch(dwLevel) {
1703 case SERVICE_CONFIG_DESCRIPTION: {
1704 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1705 LPSERVICE_DESCRIPTIONW config = (LPSERVICE_DESCRIPTIONW) buffer;
1706 LPBYTE strbuf = NULL;
1707 *needed = sizeof (SERVICE_DESCRIPTIONW);
1708 sz = size - *needed;
1709 if(config && (*needed <= size))
1710 strbuf = (LPBYTE) (config + 1);
1711 r = RegQueryValueExW( hKey, szDescription, 0, &type, strbuf, &sz );
1712 if((r == ERROR_SUCCESS) && ( type != REG_SZ)) {
1713 FIXME("SERVICE_CONFIG_DESCRIPTION: don't know how to handle type %d\n", type);
1714 return FALSE;
1716 *needed += sz;
1717 if(config) {
1718 if(r == ERROR_SUCCESS)
1719 config->lpDescription = (LPWSTR) (config + 1);
1720 else
1721 config->lpDescription = NULL;
1724 break;
1726 if(*needed > size)
1727 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1729 return (*needed <= size);
1732 /******************************************************************************
1733 * EnumServicesStatusA [ADVAPI32.@]
1735 BOOL WINAPI
1736 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
1737 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
1738 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1739 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1741 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1742 dwServiceType, dwServiceState, lpServices, cbBufSize,
1743 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1744 SetLastError (ERROR_ACCESS_DENIED);
1745 return FALSE;
1748 /******************************************************************************
1749 * EnumServicesStatusW [ADVAPI32.@]
1751 BOOL WINAPI
1752 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
1753 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
1754 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1755 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1757 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1758 dwServiceType, dwServiceState, lpServices, cbBufSize,
1759 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1760 SetLastError (ERROR_ACCESS_DENIED);
1761 return FALSE;
1764 /******************************************************************************
1765 * EnumServicesStatusExA [ADVAPI32.@]
1767 BOOL WINAPI
1768 EnumServicesStatusExA(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType,
1769 DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1770 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCSTR pszGroupName)
1772 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager, InfoLevel,
1773 dwServiceType, dwServiceState, lpServices, cbBufSize,
1774 pcbBytesNeeded, lpServicesReturned, lpResumeHandle, debugstr_a(pszGroupName));
1775 *lpServicesReturned = 0;
1776 SetLastError (ERROR_ACCESS_DENIED);
1777 return FALSE;
1780 /******************************************************************************
1781 * EnumServicesStatusExW [ADVAPI32.@]
1783 BOOL WINAPI
1784 EnumServicesStatusExW(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType,
1785 DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1786 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCWSTR pszGroupName)
1788 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager, InfoLevel,
1789 dwServiceType, dwServiceState, lpServices, cbBufSize,
1790 pcbBytesNeeded, lpServicesReturned, lpResumeHandle, debugstr_w(pszGroupName));
1791 SetLastError (ERROR_ACCESS_DENIED);
1792 return FALSE;
1795 /******************************************************************************
1796 * GetServiceKeyNameA [ADVAPI32.@]
1798 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1799 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1801 LPWSTR lpDisplayNameW, lpServiceNameW;
1802 DWORD sizeW;
1803 BOOL ret = FALSE;
1805 TRACE("%p %s %p %p\n", hSCManager,
1806 debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1808 lpDisplayNameW = SERV_dup(lpDisplayName);
1809 if (lpServiceName)
1810 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1811 else
1812 lpServiceNameW = NULL;
1814 sizeW = *lpcchBuffer;
1815 if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
1817 if (*lpcchBuffer && lpServiceName)
1818 lpServiceName[0] = 0;
1819 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1820 goto cleanup;
1823 if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
1824 *lpcchBuffer, NULL, NULL ))
1826 if (*lpcchBuffer && lpServiceName)
1827 lpServiceName[0] = 0;
1828 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
1829 goto cleanup;
1832 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1833 ret = TRUE;
1835 cleanup:
1836 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1837 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1838 return ret;
1841 /******************************************************************************
1842 * GetServiceKeyNameW [ADVAPI32.@]
1844 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1845 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1847 struct sc_manager *hscm;
1848 DWORD err;
1850 TRACE("%p %s %p %p\n", hSCManager,
1851 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1853 hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER);
1854 if (!hscm)
1856 SetLastError(ERROR_INVALID_HANDLE);
1857 return FALSE;
1860 if (!lpDisplayName)
1862 SetLastError(ERROR_INVALID_ADDRESS);
1863 return FALSE;
1866 __TRY
1868 err = svcctl_GetServiceKeyNameW(hscm->hdr.server_handle,
1869 lpDisplayName, lpServiceName, lpServiceName ? *lpcchBuffer : 0, lpcchBuffer);
1871 __EXCEPT(rpc_filter)
1873 err = map_exception_code(GetExceptionCode());
1875 __ENDTRY
1877 if (err)
1878 SetLastError(err);
1879 return err == ERROR_SUCCESS;
1882 /******************************************************************************
1883 * QueryServiceLockStatusA [ADVAPI32.@]
1885 BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
1886 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1887 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1889 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1891 return FALSE;
1894 /******************************************************************************
1895 * QueryServiceLockStatusW [ADVAPI32.@]
1897 BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
1898 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1899 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1901 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1903 return FALSE;
1906 /******************************************************************************
1907 * GetServiceDisplayNameA [ADVAPI32.@]
1909 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1910 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1912 LPWSTR lpServiceNameW, lpDisplayNameW;
1913 DWORD sizeW;
1914 BOOL ret = FALSE;
1916 TRACE("%p %s %p %p\n", hSCManager,
1917 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1919 lpServiceNameW = SERV_dup(lpServiceName);
1920 if (lpDisplayName)
1921 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1922 else
1923 lpDisplayNameW = NULL;
1925 sizeW = *lpcchBuffer;
1926 if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
1928 if (*lpcchBuffer && lpDisplayName)
1929 lpDisplayName[0] = 0;
1930 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1931 goto cleanup;
1934 if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
1935 *lpcchBuffer, NULL, NULL ))
1937 if (*lpcchBuffer && lpDisplayName)
1938 lpDisplayName[0] = 0;
1939 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
1940 goto cleanup;
1943 /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
1944 * (but if the function succeeded it means that is a good upper estimation of the size) */
1945 ret = TRUE;
1947 cleanup:
1948 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1949 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1950 return ret;
1953 /******************************************************************************
1954 * GetServiceDisplayNameW [ADVAPI32.@]
1956 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1957 LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1959 struct sc_manager *hscm;
1960 DWORD err;
1962 TRACE("%p %s %p %p\n", hSCManager,
1963 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1965 hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER);
1966 if (!hscm)
1968 SetLastError(ERROR_INVALID_HANDLE);
1969 return FALSE;
1972 if (!lpServiceName)
1974 SetLastError(ERROR_INVALID_ADDRESS);
1975 return FALSE;
1978 __TRY
1980 err = svcctl_GetServiceDisplayNameW(hscm->hdr.server_handle,
1981 lpServiceName, lpDisplayName, lpDisplayName ? *lpcchBuffer : 0, lpcchBuffer);
1983 __EXCEPT(rpc_filter)
1985 err = map_exception_code(GetExceptionCode());
1987 __ENDTRY
1989 if (err)
1990 SetLastError(err);
1991 return err == ERROR_SUCCESS;
1994 /******************************************************************************
1995 * ChangeServiceConfigW [ADVAPI32.@]
1997 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1998 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1999 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
2000 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
2002 struct sc_service *hsvc;
2003 DWORD cb_pwd;
2004 DWORD err;
2006 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2007 hService, dwServiceType, dwStartType, dwErrorControl,
2008 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
2009 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
2010 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
2012 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
2013 if (!hsvc)
2015 SetLastError( ERROR_INVALID_HANDLE );
2016 return FALSE;
2019 cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
2021 __TRY
2023 err = svcctl_ChangeServiceConfigW(hsvc->hdr.server_handle, dwServiceType,
2024 dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId,
2025 (const BYTE *)lpDependencies, multisz_cb(lpDependencies), lpServiceStartName,
2026 (const BYTE *)lpPassword, cb_pwd, lpDisplayName);
2028 __EXCEPT(rpc_filter)
2030 err = map_exception_code(GetExceptionCode());
2032 __ENDTRY
2034 if (err != ERROR_SUCCESS)
2035 SetLastError(err);
2037 return err == ERROR_SUCCESS;
2040 /******************************************************************************
2041 * ChangeServiceConfigA [ADVAPI32.@]
2043 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
2044 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
2045 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
2046 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
2048 LPWSTR wBinaryPathName, wLoadOrderGroup, wDependencies;
2049 LPWSTR wServiceStartName, wPassword, wDisplayName;
2050 BOOL r;
2052 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2053 hService, dwServiceType, dwStartType, dwErrorControl,
2054 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
2055 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
2056 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
2058 wBinaryPathName = SERV_dup( lpBinaryPathName );
2059 wLoadOrderGroup = SERV_dup( lpLoadOrderGroup );
2060 wDependencies = SERV_dupmulti( lpDependencies );
2061 wServiceStartName = SERV_dup( lpServiceStartName );
2062 wPassword = SERV_dup( lpPassword );
2063 wDisplayName = SERV_dup( lpDisplayName );
2065 r = ChangeServiceConfigW( hService, dwServiceType,
2066 dwStartType, dwErrorControl, wBinaryPathName,
2067 wLoadOrderGroup, lpdwTagId, wDependencies,
2068 wServiceStartName, wPassword, wDisplayName);
2070 HeapFree( GetProcessHeap(), 0, wBinaryPathName );
2071 HeapFree( GetProcessHeap(), 0, wLoadOrderGroup );
2072 HeapFree( GetProcessHeap(), 0, wDependencies );
2073 HeapFree( GetProcessHeap(), 0, wServiceStartName );
2074 HeapFree( GetProcessHeap(), 0, wPassword );
2075 HeapFree( GetProcessHeap(), 0, wDisplayName );
2077 return r;
2080 /******************************************************************************
2081 * ChangeServiceConfig2A [ADVAPI32.@]
2083 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
2084 LPVOID lpInfo)
2086 BOOL r = FALSE;
2088 TRACE("%p %d %p\n",hService, dwInfoLevel, lpInfo);
2090 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2092 LPSERVICE_DESCRIPTIONA sd = (LPSERVICE_DESCRIPTIONA) lpInfo;
2093 SERVICE_DESCRIPTIONW sdw;
2095 sdw.lpDescription = SERV_dup( sd->lpDescription );
2097 r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
2099 HeapFree( GetProcessHeap(), 0, sdw.lpDescription );
2101 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
2103 LPSERVICE_FAILURE_ACTIONSA fa = (LPSERVICE_FAILURE_ACTIONSA) lpInfo;
2104 SERVICE_FAILURE_ACTIONSW faw;
2106 faw.dwResetPeriod = fa->dwResetPeriod;
2107 faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg );
2108 faw.lpCommand = SERV_dup( fa->lpCommand );
2109 faw.cActions = fa->cActions;
2110 faw.lpsaActions = fa->lpsaActions;
2112 r = ChangeServiceConfig2W( hService, dwInfoLevel, &faw );
2114 HeapFree( GetProcessHeap(), 0, faw.lpRebootMsg );
2115 HeapFree( GetProcessHeap(), 0, faw.lpCommand );
2117 else
2118 SetLastError( ERROR_INVALID_PARAMETER );
2120 return r;
2123 /******************************************************************************
2124 * ChangeServiceConfig2W [ADVAPI32.@]
2126 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
2127 LPVOID lpInfo)
2129 HKEY hKey;
2130 struct sc_service *hsvc;
2132 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
2133 if (!hsvc)
2135 SetLastError( ERROR_INVALID_HANDLE );
2136 return FALSE;
2138 hKey = hsvc->hkey;
2140 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2142 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
2143 LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo;
2144 if (sd->lpDescription)
2146 TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription));
2147 if (sd->lpDescription[0] == 0)
2148 RegDeleteValueW(hKey,szDescription);
2149 else
2150 RegSetValueExW(hKey, szDescription, 0, REG_SZ,
2151 (LPVOID)sd->lpDescription,
2152 sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
2155 else
2156 FIXME("STUB: %p %d %p\n",hService, dwInfoLevel, lpInfo);
2157 return TRUE;
2160 /******************************************************************************
2161 * QueryServiceObjectSecurity [ADVAPI32.@]
2163 BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
2164 SECURITY_INFORMATION dwSecurityInformation,
2165 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2166 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2168 SECURITY_DESCRIPTOR descriptor;
2169 DWORD size;
2170 BOOL succ;
2171 ACL acl;
2173 FIXME("%p %d %p %u %p - semi-stub\n", hService, dwSecurityInformation,
2174 lpSecurityDescriptor, cbBufSize, pcbBytesNeeded);
2176 if (dwSecurityInformation != DACL_SECURITY_INFORMATION)
2177 FIXME("information %d not supported\n", dwSecurityInformation);
2179 InitializeSecurityDescriptor(&descriptor, SECURITY_DESCRIPTOR_REVISION);
2181 InitializeAcl(&acl, sizeof(ACL), ACL_REVISION);
2182 SetSecurityDescriptorDacl(&descriptor, TRUE, &acl, TRUE);
2184 size = cbBufSize;
2185 succ = MakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
2186 *pcbBytesNeeded = size;
2187 return succ;
2190 /******************************************************************************
2191 * SetServiceObjectSecurity [ADVAPI32.@]
2193 BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService,
2194 SECURITY_INFORMATION dwSecurityInformation,
2195 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2197 FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
2198 return TRUE;
2201 /******************************************************************************
2202 * SetServiceBits [ADVAPI32.@]
2204 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
2205 DWORD dwServiceBits,
2206 BOOL bSetBitsOn,
2207 BOOL bUpdateImmediately)
2209 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
2210 bSetBitsOn, bUpdateImmediately);
2211 return TRUE;
2214 /* thunk for calling the RegisterServiceCtrlHandler handler function */
2215 static DWORD WINAPI ctrl_handler_thunk( DWORD control, DWORD type, void *data, void *context )
2217 LPHANDLER_FUNCTION func = context;
2219 func( control );
2220 return ERROR_SUCCESS;
2223 /******************************************************************************
2224 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
2226 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER_FUNCTION handler )
2228 return RegisterServiceCtrlHandlerExA( name, ctrl_handler_thunk, handler );
2231 /******************************************************************************
2232 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
2234 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLER_FUNCTION handler )
2236 return RegisterServiceCtrlHandlerExW( name, ctrl_handler_thunk, handler );
2239 /******************************************************************************
2240 * RegisterServiceCtrlHandlerExA [ADVAPI32.@]
2242 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDLER_FUNCTION_EX handler, LPVOID context )
2244 LPWSTR nameW;
2245 SERVICE_STATUS_HANDLE ret;
2247 nameW = SERV_dup(name);
2248 ret = RegisterServiceCtrlHandlerExW( nameW, handler, context );
2249 HeapFree( GetProcessHeap(), 0, nameW );
2250 return ret;
2253 /******************************************************************************
2254 * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
2256 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
2257 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2259 service_data *service;
2260 SC_HANDLE hService = 0;
2261 BOOL found = FALSE;
2263 TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
2265 EnterCriticalSection( &service_cs );
2266 if ((service = find_service_by_name( lpServiceName )))
2268 service->handler = lpHandlerProc;
2269 service->context = lpContext;
2270 hService = service->handle;
2271 found = TRUE;
2273 LeaveCriticalSection( &service_cs );
2275 if (!found) SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
2277 return (SERVICE_STATUS_HANDLE)hService;
2280 /******************************************************************************
2281 * EnumDependentServicesA [ADVAPI32.@]
2283 BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState,
2284 LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize,
2285 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2287 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2288 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2290 *lpServicesReturned = 0;
2291 return TRUE;
2294 /******************************************************************************
2295 * EnumDependentServicesW [ADVAPI32.@]
2297 BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
2298 LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize,
2299 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2301 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2302 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2304 *lpServicesReturned = 0;
2305 return TRUE;