hlink: Implement HlinkUpdateStackItem().
[wine.git] / dlls / advapi32 / service.c
blobb591449f1bb5eb97b78497355f44af64ff2b8c9c
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 static CRITICAL_SECTION service_cs;
79 static CRITICAL_SECTION_DEBUG service_cs_debug =
81 0, 0, &service_cs,
82 { &service_cs_debug.ProcessLocksList,
83 &service_cs_debug.ProcessLocksList },
84 0, 0, { (DWORD_PTR)(__FILE__ ": service_cs") }
86 static CRITICAL_SECTION service_cs = { &service_cs_debug, -1, 0, 0, 0, 0 };
88 static service_data **services;
89 static unsigned int nb_services;
90 static HANDLE service_event;
91 static HANDLE stop_event;
93 extern HANDLE CDECL __wine_make_process_system(void);
95 /******************************************************************************
96 * String management functions (same behaviour as strdup)
97 * NOTE: the caller of those functions is responsible for calling HeapFree
98 * in order to release the memory allocated by those functions.
100 LPWSTR SERV_dup( LPCSTR str )
102 UINT len;
103 LPWSTR wstr;
105 if( !str )
106 return NULL;
107 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
108 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
109 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
110 return wstr;
113 static inline LPWSTR SERV_dupmulti(LPCSTR str)
115 UINT len = 0, n = 0;
116 LPWSTR wstr;
118 if( !str )
119 return NULL;
120 do {
121 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
122 n += (strlen( &str[n] ) + 1);
123 } while (str[n]);
124 len++;
125 n++;
127 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
128 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
129 return wstr;
132 static inline DWORD multisz_cb(LPCWSTR wmultisz)
134 const WCHAR *wptr = wmultisz;
136 if (wmultisz == NULL)
137 return 0;
139 while (*wptr)
140 wptr += lstrlenW(wptr)+1;
141 return (wptr - wmultisz + 1)*sizeof(WCHAR);
144 /******************************************************************************
145 * RPC connection with services.exe
148 DECLSPEC_HIDDEN handle_t __RPC_USER MACHINE_HANDLEW_bind(MACHINE_HANDLEW MachineName)
150 WCHAR transport[] = SVCCTL_TRANSPORT;
151 WCHAR endpoint[] = SVCCTL_ENDPOINT;
152 RPC_WSTR binding_str;
153 RPC_STATUS status;
154 handle_t rpc_handle;
156 status = RpcStringBindingComposeW(NULL, transport, (RPC_WSTR)MachineName, endpoint, NULL, &binding_str);
157 if (status != RPC_S_OK)
159 ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD)status);
160 return NULL;
163 status = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
164 RpcStringFreeW(&binding_str);
166 if (status != RPC_S_OK)
168 ERR("Couldn't connect to services.exe: error code %u\n", (DWORD)status);
169 return NULL;
172 return rpc_handle;
175 DECLSPEC_HIDDEN void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName, handle_t h)
177 RpcBindingFree(&h);
180 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr)
182 return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode);
185 static DWORD map_exception_code(DWORD exception_code)
187 switch (exception_code)
189 case RPC_X_NULL_REF_POINTER:
190 return ERROR_INVALID_ADDRESS;
191 case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
192 case RPC_X_BYTE_COUNT_TOO_SMALL:
193 return ERROR_INVALID_PARAMETER;
194 case RPC_S_INVALID_BINDING:
195 case RPC_X_SS_IN_NULL_CONTEXT:
196 return ERROR_INVALID_HANDLE;
197 default:
198 return exception_code;
202 /******************************************************************************
203 * Service IPC functions
205 static LPWSTR service_get_pipe_name(void)
207 static const WCHAR format[] = { '\\','\\','.','\\','p','i','p','e','\\',
208 'n','e','t','\\','N','t','C','o','n','t','r','o','l','P','i','p','e','%','u',0};
209 static const WCHAR service_current_key_str[] = { 'S','Y','S','T','E','M','\\',
210 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
211 'C','o','n','t','r','o','l','\\',
212 'S','e','r','v','i','c','e','C','u','r','r','e','n','t',0};
213 LPWSTR name;
214 DWORD len;
215 HKEY service_current_key;
216 DWORD service_current;
217 LONG ret;
218 DWORD type;
220 ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, service_current_key_str, 0,
221 KEY_QUERY_VALUE, &service_current_key);
222 if (ret != ERROR_SUCCESS)
223 return NULL;
224 len = sizeof(service_current);
225 ret = RegQueryValueExW(service_current_key, NULL, NULL, &type,
226 (BYTE *)&service_current, &len);
227 RegCloseKey(service_current_key);
228 if (ret != ERROR_SUCCESS || type != REG_DWORD)
229 return NULL;
230 len = sizeof(format)/sizeof(WCHAR) + 10 /* strlenW("4294967295") */;
231 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
232 if (!name)
233 return NULL;
234 snprintfW(name, len, format, service_current);
235 return name;
238 static HANDLE service_open_pipe(void)
240 LPWSTR szPipe = service_get_pipe_name();
241 HANDLE handle = INVALID_HANDLE_VALUE;
243 do {
244 handle = CreateFileW(szPipe, GENERIC_READ|GENERIC_WRITE,
245 0, NULL, OPEN_ALWAYS, 0, NULL);
246 if (handle != INVALID_HANDLE_VALUE)
247 break;
248 if (GetLastError() != ERROR_PIPE_BUSY)
249 break;
250 } while (WaitNamedPipeW(szPipe, NMPWAIT_USE_DEFAULT_WAIT));
251 HeapFree(GetProcessHeap(), 0, szPipe);
253 return handle;
256 static service_data *find_service_by_name( const WCHAR *name )
258 unsigned int i;
260 if (nb_services == 1) /* only one service (FIXME: should depend on OWN_PROCESS etc.) */
261 return services[0];
262 for (i = 0; i < nb_services; i++)
263 if (!strcmpiW( name, services[i]->name )) return services[i];
264 return NULL;
267 /******************************************************************************
268 * service_thread
270 * Call into the main service routine provided by StartServiceCtrlDispatcher.
272 static DWORD WINAPI service_thread(LPVOID arg)
274 service_data *info = arg;
275 LPWSTR str = info->args;
276 DWORD argc = 0, len = 0;
278 TRACE("%p\n", arg);
280 while (str[len])
282 len += strlenW(&str[len]) + 1;
283 argc++;
285 len++;
287 if (info->unicode)
289 LPWSTR *argv, p;
291 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR));
292 for (argc=0, p=str; *p; p += strlenW(p) + 1)
293 argv[argc++] = p;
294 argv[argc] = NULL;
296 info->proc.w(argc, argv);
297 HeapFree(GetProcessHeap(), 0, argv);
299 else
301 LPSTR strA, *argv, p;
302 DWORD lenA;
304 lenA = WideCharToMultiByte(CP_ACP,0, str, len, NULL, 0, NULL, NULL);
305 strA = HeapAlloc(GetProcessHeap(), 0, lenA);
306 WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL);
308 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPSTR));
309 for (argc=0, p=strA; *p; p += strlen(p) + 1)
310 argv[argc++] = p;
311 argv[argc] = NULL;
313 info->proc.a(argc, argv);
314 HeapFree(GetProcessHeap(), 0, argv);
315 HeapFree(GetProcessHeap(), 0, strA);
317 return 0;
320 /******************************************************************************
321 * service_handle_start
323 static DWORD service_handle_start(service_data *service, const WCHAR *data, DWORD count)
325 TRACE("%s argsize %u\n", debugstr_w(service->name), count);
327 if (service->thread)
329 WARN("service is not stopped\n");
330 return ERROR_SERVICE_ALREADY_RUNNING;
333 HeapFree(GetProcessHeap(), 0, service->args);
334 service->args = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
335 memcpy( service->args, data, count * sizeof(WCHAR) );
336 service->thread = CreateThread( NULL, 0, service_thread,
337 service, 0, NULL );
338 SetEvent( service_event ); /* notify the main loop */
339 return 0;
342 /******************************************************************************
343 * service_handle_control
345 static DWORD service_handle_control(const service_data *service, DWORD dwControl)
347 DWORD ret = ERROR_INVALID_SERVICE_CONTROL;
349 TRACE("%s control %u\n", debugstr_w(service->name), dwControl);
351 if (service->handler)
352 ret = service->handler(dwControl, 0, NULL, service->context);
353 return ret;
356 /******************************************************************************
357 * service_control_dispatcher
359 static DWORD WINAPI service_control_dispatcher(LPVOID arg)
361 SC_HANDLE manager;
362 HANDLE pipe;
364 if (!(manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
366 ERR("failed to open service manager error %u\n", GetLastError());
367 return 0;
370 pipe = service_open_pipe();
372 if (pipe==INVALID_HANDLE_VALUE)
374 WARN("failed to create control pipe error = %d\n", GetLastError());
375 return 0;
378 /* dispatcher loop */
379 while (1)
381 service_data *service;
382 service_start_info info;
383 WCHAR *data = NULL;
384 BOOL r;
385 DWORD data_size = 0, count, result;
387 r = ReadFile( pipe, &info, FIELD_OFFSET(service_start_info,data), &count, NULL );
388 if (!r)
390 if (GetLastError() != ERROR_BROKEN_PIPE)
391 ERR( "pipe read failed error %u\n", GetLastError() );
392 break;
394 if (count != FIELD_OFFSET(service_start_info,data))
396 ERR( "partial pipe read %u\n", count );
397 break;
399 if (count < info.total_size)
401 data_size = info.total_size - FIELD_OFFSET(service_start_info,data);
402 data = HeapAlloc( GetProcessHeap(), 0, data_size );
403 r = ReadFile( pipe, data, data_size, &count, NULL );
404 if (!r)
406 if (GetLastError() != ERROR_BROKEN_PIPE)
407 ERR( "pipe read failed error %u\n", GetLastError() );
408 HeapFree( GetProcessHeap(), 0, data );
409 break;
411 if (count != data_size)
413 ERR( "partial pipe read %u/%u\n", count, data_size );
414 HeapFree( GetProcessHeap(), 0, data );
415 break;
419 /* find the service */
421 if (!(service = find_service_by_name( data )))
423 FIXME( "got request %u for unknown service %s\n", info.cmd, debugstr_w(data));
424 result = ERROR_INVALID_PARAMETER;
425 goto done;
428 TRACE( "got request %u for service %s\n", info.cmd, debugstr_w(data) );
430 /* handle the request */
431 switch (info.cmd)
433 case WINESERV_STARTINFO:
434 if (!service->handle)
436 if (!(service->handle = OpenServiceW( manager, data, SERVICE_SET_STATUS )) ||
437 !(service->full_access_handle = OpenServiceW( manager, data, GENERIC_READ|GENERIC_WRITE )))
438 FIXME( "failed to open service %s\n", debugstr_w(data) );
440 result = service_handle_start(service, data, data_size / sizeof(WCHAR));
441 break;
442 case WINESERV_SENDCONTROL:
443 result = service_handle_control(service, info.control);
444 break;
445 default:
446 ERR("received invalid command %u\n", info.cmd);
447 result = ERROR_INVALID_PARAMETER;
448 break;
451 done:
452 WriteFile(pipe, &result, sizeof(result), &count, NULL);
453 HeapFree( GetProcessHeap(), 0, data );
456 CloseHandle(pipe);
457 CloseServiceHandle( manager );
458 return 1;
461 /******************************************************************************
462 * service_run_main_thread
464 static BOOL service_run_main_thread(void)
466 DWORD i, n, ret;
467 HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
468 UINT wait_services[MAXIMUM_WAIT_OBJECTS];
470 service_event = CreateEventW( NULL, FALSE, FALSE, NULL );
471 stop_event = CreateEventW( NULL, FALSE, FALSE, NULL );
473 /* FIXME: service_control_dispatcher should be merged into the main thread */
474 wait_handles[0] = __wine_make_process_system();
475 wait_handles[1] = CreateThread( NULL, 0, service_control_dispatcher, NULL, 0, NULL );
476 wait_handles[2] = service_event;
477 wait_handles[3] = stop_event;
479 TRACE("Starting %d services running as process %d\n",
480 nb_services, GetCurrentProcessId());
482 /* wait for all the threads to pack up and exit */
483 for (;;)
485 EnterCriticalSection( &service_cs );
486 for (i = 0, n = 4; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
488 if (!services[i]->thread) continue;
489 wait_services[n] = i;
490 wait_handles[n++] = services[i]->thread;
492 LeaveCriticalSection( &service_cs );
494 ret = WaitForMultipleObjects( n, wait_handles, FALSE, INFINITE );
495 if (!ret) /* system process event */
497 SERVICE_STATUS st;
498 SERVICE_PRESHUTDOWN_INFO spi;
499 DWORD timeout = 5000;
500 BOOL res;
502 EnterCriticalSection( &service_cs );
503 n = 0;
504 for (i = 0; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
506 if (!services[i]->thread) continue;
508 res = QueryServiceStatus(services[i]->full_access_handle, &st);
509 ret = ERROR_SUCCESS;
510 if (res && (st.dwControlsAccepted & SERVICE_ACCEPT_PRESHUTDOWN))
512 res = QueryServiceConfig2W( services[i]->full_access_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
513 (LPBYTE)&spi, sizeof(spi), &i );
514 if (res)
516 FIXME("service should be able to delay shutdown\n");
517 timeout += spi.dwPreshutdownTimeout;
518 ret = service_handle_control( services[i], SERVICE_CONTROL_PRESHUTDOWN );
519 wait_handles[n++] = services[i]->thread;
522 else if (res && (st.dwControlsAccepted & SERVICE_ACCEPT_SHUTDOWN))
524 ret = service_handle_control( services[i], SERVICE_CONTROL_SHUTDOWN );
525 wait_handles[n++] = services[i]->thread;
528 LeaveCriticalSection( &service_cs );
530 TRACE("last user process exited, shutting down (timeout: %d)\n", timeout);
531 WaitForMultipleObjects( n, wait_handles, TRUE, timeout );
532 ExitProcess(0);
534 else if (ret == 1)
536 TRACE( "control dispatcher exited, shutting down\n" );
537 /* FIXME: we should maybe send a shutdown control to running services */
538 ExitProcess(0);
540 else if (ret == 2)
542 continue; /* rebuild the list */
544 else if (ret == 3)
546 return TRUE;
548 else if (ret < n)
550 services[wait_services[ret]]->thread = 0;
551 CloseHandle( wait_handles[ret] );
553 else return FALSE;
557 /******************************************************************************
558 * StartServiceCtrlDispatcherA [ADVAPI32.@]
560 * See StartServiceCtrlDispatcherW.
562 BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
564 service_data *info;
565 unsigned int i;
566 BOOL ret = TRUE;
568 TRACE("%p\n", servent);
570 if (nb_services)
572 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
573 return FALSE;
575 while (servent[nb_services].lpServiceName) nb_services++;
576 if (!nb_services)
578 SetLastError( ERROR_INVALID_PARAMETER );
579 return FALSE;
582 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
584 for (i = 0; i < nb_services; i++)
586 DWORD len = MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, NULL, 0);
587 DWORD sz = FIELD_OFFSET( service_data, name[len] );
588 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
589 MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, info->name, len);
590 info->proc.a = servent[i].lpServiceProc;
591 info->unicode = FALSE;
592 services[i] = info;
595 service_run_main_thread();
597 return ret;
600 /******************************************************************************
601 * StartServiceCtrlDispatcherW [ADVAPI32.@]
603 * Connects a process containing one or more services to the service control
604 * manager.
606 * PARAMS
607 * servent [I] A list of the service names and service procedures
609 * RETURNS
610 * Success: TRUE.
611 * Failure: FALSE.
613 BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
615 service_data *info;
616 unsigned int i;
617 BOOL ret = TRUE;
619 TRACE("%p\n", servent);
621 if (nb_services)
623 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
624 return FALSE;
626 while (servent[nb_services].lpServiceName) nb_services++;
627 if (!nb_services)
629 SetLastError( ERROR_INVALID_PARAMETER );
630 return FALSE;
633 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
635 for (i = 0; i < nb_services; i++)
637 DWORD len = strlenW(servent[i].lpServiceName) + 1;
638 DWORD sz = FIELD_OFFSET( service_data, name[len] );
639 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
640 strcpyW(info->name, servent[i].lpServiceName);
641 info->proc.w = servent[i].lpServiceProc;
642 info->unicode = TRUE;
643 services[i] = info;
646 service_run_main_thread();
648 return ret;
651 /******************************************************************************
652 * LockServiceDatabase [ADVAPI32.@]
654 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
656 SC_RPC_LOCK hLock = NULL;
657 DWORD err;
659 TRACE("%p\n",hSCManager);
661 __TRY
663 err = svcctl_LockServiceDatabase(hSCManager, &hLock);
665 __EXCEPT(rpc_filter)
667 err = map_exception_code(GetExceptionCode());
669 __ENDTRY
670 if (err != ERROR_SUCCESS)
672 SetLastError(err);
673 return NULL;
675 return hLock;
678 /******************************************************************************
679 * UnlockServiceDatabase [ADVAPI32.@]
681 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
683 DWORD err;
684 SC_RPC_LOCK hRpcLock = ScLock;
686 TRACE("%p\n",ScLock);
688 __TRY
690 err = svcctl_UnlockServiceDatabase(&hRpcLock);
692 __EXCEPT(rpc_filter)
694 err = map_exception_code(GetExceptionCode());
696 __ENDTRY
697 if (err != ERROR_SUCCESS)
699 SetLastError(err);
700 return FALSE;
702 return TRUE;
705 /******************************************************************************
706 * SetServiceStatus [ADVAPI32.@]
708 * PARAMS
709 * hService []
710 * lpStatus []
712 BOOL WINAPI
713 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
715 DWORD err;
717 TRACE("%p %x %x %x %x %x %x %x\n", hService,
718 lpStatus->dwServiceType, lpStatus->dwCurrentState,
719 lpStatus->dwControlsAccepted, lpStatus->dwWin32ExitCode,
720 lpStatus->dwServiceSpecificExitCode, lpStatus->dwCheckPoint,
721 lpStatus->dwWaitHint);
723 __TRY
725 err = svcctl_SetServiceStatus( hService, lpStatus );
727 __EXCEPT(rpc_filter)
729 err = map_exception_code(GetExceptionCode());
731 __ENDTRY
732 if (err != ERROR_SUCCESS)
734 SetLastError(err);
735 return FALSE;
738 if (lpStatus->dwCurrentState == SERVICE_STOPPED) {
739 SetEvent(stop_event);
740 CloseServiceHandle((SC_HANDLE)hService);
743 return TRUE;
747 /******************************************************************************
748 * OpenSCManagerA [ADVAPI32.@]
750 * Establish a connection to the service control manager and open its database.
752 * PARAMS
753 * lpMachineName [I] Pointer to machine name string
754 * lpDatabaseName [I] Pointer to database name string
755 * dwDesiredAccess [I] Type of access
757 * RETURNS
758 * Success: A Handle to the service control manager database
759 * Failure: NULL
761 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
762 DWORD dwDesiredAccess )
764 LPWSTR lpMachineNameW, lpDatabaseNameW;
765 SC_HANDLE ret;
767 lpMachineNameW = SERV_dup(lpMachineName);
768 lpDatabaseNameW = SERV_dup(lpDatabaseName);
769 ret = OpenSCManagerW(lpMachineNameW, lpDatabaseNameW, dwDesiredAccess);
770 HeapFree(GetProcessHeap(), 0, lpDatabaseNameW);
771 HeapFree(GetProcessHeap(), 0, lpMachineNameW);
772 return ret;
775 /******************************************************************************
776 * OpenSCManagerW [ADVAPI32.@]
778 * See OpenSCManagerA.
780 DWORD SERV_OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
781 DWORD dwDesiredAccess, SC_HANDLE *handle )
783 DWORD r;
785 TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
786 debugstr_w(lpDatabaseName), dwDesiredAccess);
788 __TRY
790 r = svcctl_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, (SC_RPC_HANDLE *)handle);
792 __EXCEPT(rpc_filter)
794 r = map_exception_code(GetExceptionCode());
796 __ENDTRY
798 if (r!=ERROR_SUCCESS)
799 *handle = 0;
801 TRACE("returning %p\n", *handle);
802 return r;
805 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
806 DWORD dwDesiredAccess )
808 SC_HANDLE handle = 0;
809 DWORD r;
811 r = SERV_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, &handle);
812 if (r!=ERROR_SUCCESS)
813 SetLastError(r);
814 return handle;
817 /******************************************************************************
818 * ControlService [ADVAPI32.@]
820 * Send a control code to a service.
822 * PARAMS
823 * hService [I] Handle of the service control manager database
824 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
825 * lpServiceStatus [O] Destination for the status of the service, if available
827 * RETURNS
828 * Success: TRUE.
829 * Failure: FALSE.
831 * BUGS
832 * Unlike M$' implementation, control requests are not serialized and may be
833 * processed asynchronously.
835 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
836 LPSERVICE_STATUS lpServiceStatus )
838 DWORD err;
840 TRACE("%p %d %p\n", hService, dwControl, lpServiceStatus);
842 __TRY
844 err = svcctl_ControlService(hService, dwControl, lpServiceStatus);
846 __EXCEPT(rpc_filter)
848 err = map_exception_code(GetExceptionCode());
850 __ENDTRY
851 if (err != ERROR_SUCCESS)
853 SetLastError(err);
854 return FALSE;
857 return TRUE;
860 /******************************************************************************
861 * CloseServiceHandle [ADVAPI32.@]
863 * Close a handle to a service or the service control manager database.
865 * PARAMS
866 * hSCObject [I] Handle to service or service control manager database
868 * RETURNS
869 * Success: TRUE
870 * Failure: FALSE
872 BOOL WINAPI
873 CloseServiceHandle( SC_HANDLE hSCObject )
875 DWORD err;
877 TRACE("%p\n", hSCObject);
879 __TRY
881 err = svcctl_CloseServiceHandle((SC_RPC_HANDLE *)&hSCObject);
883 __EXCEPT(rpc_filter)
885 err = map_exception_code(GetExceptionCode());
887 __ENDTRY
889 if (err != ERROR_SUCCESS)
891 SetLastError(err);
892 return FALSE;
894 return TRUE;
898 /******************************************************************************
899 * OpenServiceA [ADVAPI32.@]
901 * Open a handle to a service.
903 * PARAMS
904 * hSCManager [I] Handle of the service control manager database
905 * lpServiceName [I] Name of the service to open
906 * dwDesiredAccess [I] Access required to the service
908 * RETURNS
909 * Success: Handle to the service
910 * Failure: NULL
912 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
913 DWORD dwDesiredAccess )
915 LPWSTR lpServiceNameW;
916 SC_HANDLE ret;
918 TRACE("%p %s %d\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
920 lpServiceNameW = SERV_dup(lpServiceName);
921 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
922 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
923 return ret;
927 /******************************************************************************
928 * OpenServiceW [ADVAPI32.@]
930 * See OpenServiceA.
932 DWORD SERV_OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
933 DWORD dwDesiredAccess, SC_HANDLE *handle )
935 DWORD err;
937 TRACE("%p %s %d\n", hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
939 if (!hSCManager)
940 return ERROR_INVALID_HANDLE;
942 __TRY
944 err = svcctl_OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess, (SC_RPC_HANDLE *)handle);
946 __EXCEPT(rpc_filter)
948 err = map_exception_code(GetExceptionCode());
950 __ENDTRY
952 if (err != ERROR_SUCCESS)
953 *handle = 0;
955 TRACE("returning %p\n", *handle);
956 return err;
959 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
960 DWORD dwDesiredAccess)
962 SC_HANDLE handle = 0;
963 DWORD err;
965 err = SERV_OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess, &handle);
966 if (err != ERROR_SUCCESS)
967 SetLastError(err);
968 return handle;
971 /******************************************************************************
972 * CreateServiceW [ADVAPI32.@]
974 SC_HANDLE WINAPI
975 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
976 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
977 DWORD dwServiceType, DWORD dwStartType,
978 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
979 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
980 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
981 LPCWSTR lpPassword )
983 SC_HANDLE handle = 0;
984 DWORD err;
985 SIZE_T passwdlen;
987 TRACE("%p %s %s\n", hSCManager,
988 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
990 if (!hSCManager)
992 SetLastError( ERROR_INVALID_HANDLE );
993 return 0;
996 if (lpPassword)
997 passwdlen = (strlenW(lpPassword) + 1) * sizeof(WCHAR);
998 else
999 passwdlen = 0;
1001 __TRY
1003 err = svcctl_CreateServiceW(hSCManager, lpServiceName,
1004 lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1005 lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, (const BYTE*)lpDependencies,
1006 multisz_cb(lpDependencies), lpServiceStartName, (const BYTE*)lpPassword, passwdlen,
1007 (SC_RPC_HANDLE *)&handle);
1009 __EXCEPT(rpc_filter)
1011 err = map_exception_code(GetExceptionCode());
1013 __ENDTRY
1015 if (err != ERROR_SUCCESS)
1017 SetLastError(err);
1018 handle = 0;
1020 return handle;
1024 /******************************************************************************
1025 * CreateServiceA [ADVAPI32.@]
1027 SC_HANDLE WINAPI
1028 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1029 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
1030 DWORD dwServiceType, DWORD dwStartType,
1031 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1032 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1033 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
1034 LPCSTR lpPassword )
1036 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
1037 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
1038 SC_HANDLE r;
1040 TRACE("%p %s %s\n", hSCManager,
1041 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
1043 lpServiceNameW = SERV_dup( lpServiceName );
1044 lpDisplayNameW = SERV_dup( lpDisplayName );
1045 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
1046 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
1047 lpDependenciesW = SERV_dupmulti( lpDependencies );
1048 lpServiceStartNameW = SERV_dup( lpServiceStartName );
1049 lpPasswordW = SERV_dup( lpPassword );
1051 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
1052 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1053 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
1054 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
1056 HeapFree( GetProcessHeap(), 0, lpServiceNameW );
1057 HeapFree( GetProcessHeap(), 0, lpDisplayNameW );
1058 HeapFree( GetProcessHeap(), 0, lpBinaryPathNameW );
1059 HeapFree( GetProcessHeap(), 0, lpLoadOrderGroupW );
1060 HeapFree( GetProcessHeap(), 0, lpDependenciesW );
1061 HeapFree( GetProcessHeap(), 0, lpServiceStartNameW );
1062 HeapFree( GetProcessHeap(), 0, lpPasswordW );
1064 return r;
1068 /******************************************************************************
1069 * DeleteService [ADVAPI32.@]
1071 * Delete a service from the service control manager database.
1073 * PARAMS
1074 * hService [I] Handle of the service to delete
1076 * RETURNS
1077 * Success: TRUE
1078 * Failure: FALSE
1080 BOOL WINAPI DeleteService( SC_HANDLE hService )
1082 DWORD err;
1084 __TRY
1086 err = svcctl_DeleteService(hService);
1088 __EXCEPT(rpc_filter)
1090 err = map_exception_code(GetExceptionCode());
1092 __ENDTRY
1093 if (err != 0)
1095 SetLastError(err);
1096 return FALSE;
1099 return TRUE;
1103 /******************************************************************************
1104 * StartServiceA [ADVAPI32.@]
1106 * Start a service
1108 * PARAMS
1109 * hService [I] Handle of service
1110 * dwNumServiceArgs [I] Number of arguments
1111 * lpServiceArgVectors [I] Address of array of argument strings
1113 * NOTES
1114 * - NT implements this function using an obscure RPC call.
1115 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1116 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
1117 * - This will only work for shared address space. How should the service
1118 * args be transferred when address spaces are separated?
1119 * - Can only start one service at a time.
1120 * - Has no concept of privilege.
1122 * RETURNS
1123 * Success: TRUE.
1124 * Failure: FALSE
1126 BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
1127 LPCSTR *lpServiceArgVectors )
1129 LPWSTR *lpwstr=NULL;
1130 unsigned int i;
1131 BOOL r;
1133 TRACE("(%p,%d,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
1135 if (dwNumServiceArgs)
1136 lpwstr = HeapAlloc( GetProcessHeap(), 0,
1137 dwNumServiceArgs*sizeof(LPWSTR) );
1139 for(i=0; i<dwNumServiceArgs; i++)
1140 lpwstr[i]=SERV_dup(lpServiceArgVectors[i]);
1142 r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
1144 if (dwNumServiceArgs)
1146 for(i=0; i<dwNumServiceArgs; i++)
1147 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
1148 HeapFree(GetProcessHeap(), 0, lpwstr);
1151 return r;
1155 /******************************************************************************
1156 * StartServiceW [ADVAPI32.@]
1158 * See StartServiceA.
1160 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1161 LPCWSTR *lpServiceArgVectors)
1163 DWORD err;
1165 TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1167 __TRY
1169 err = svcctl_StartServiceW(hService, dwNumServiceArgs, lpServiceArgVectors);
1171 __EXCEPT(rpc_filter)
1173 err = map_exception_code(GetExceptionCode());
1175 __ENDTRY
1176 if (err != ERROR_SUCCESS)
1178 SetLastError(err);
1179 return FALSE;
1182 return TRUE;
1185 /******************************************************************************
1186 * QueryServiceStatus [ADVAPI32.@]
1188 * PARAMS
1189 * hService [I] Handle to service to get information about
1190 * lpservicestatus [O] buffer to receive the status information for the service
1193 BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
1194 LPSERVICE_STATUS lpservicestatus)
1196 SERVICE_STATUS_PROCESS SvcStatusData;
1197 BOOL ret;
1198 DWORD dummy;
1200 TRACE("%p %p\n", hService, lpservicestatus);
1202 if (!hService)
1204 SetLastError(ERROR_INVALID_HANDLE);
1205 return FALSE;
1207 if (!lpservicestatus)
1209 SetLastError(ERROR_INVALID_ADDRESS);
1210 return FALSE;
1213 ret = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&SvcStatusData,
1214 sizeof(SERVICE_STATUS_PROCESS), &dummy);
1215 if (ret) memcpy(lpservicestatus, &SvcStatusData, sizeof(SERVICE_STATUS)) ;
1216 return ret;
1220 /******************************************************************************
1221 * QueryServiceStatusEx [ADVAPI32.@]
1223 * Get information about a service.
1225 * PARAMS
1226 * hService [I] Handle to service to get information about
1227 * InfoLevel [I] Level of information to get
1228 * lpBuffer [O] Destination for requested information
1229 * cbBufSize [I] Size of lpBuffer in bytes
1230 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1232 * RETURNS
1233 * Success: TRUE
1234 * FAILURE: FALSE
1236 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1237 LPBYTE lpBuffer, DWORD cbBufSize,
1238 LPDWORD pcbBytesNeeded)
1240 DWORD err;
1242 TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1244 if (InfoLevel != SC_STATUS_PROCESS_INFO)
1246 err = ERROR_INVALID_LEVEL;
1248 else if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
1250 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
1251 err = ERROR_INSUFFICIENT_BUFFER;
1253 else
1255 __TRY
1257 err = svcctl_QueryServiceStatusEx(hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1259 __EXCEPT(rpc_filter)
1261 err = map_exception_code(GetExceptionCode());
1263 __ENDTRY
1265 if (err != ERROR_SUCCESS)
1267 SetLastError(err);
1268 return FALSE;
1270 return TRUE;
1273 /******************************************************************************
1274 * QueryServiceConfigA [ADVAPI32.@]
1276 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1277 DWORD size, LPDWORD needed )
1279 DWORD n;
1280 LPSTR p, buffer;
1281 BOOL ret;
1282 QUERY_SERVICE_CONFIGW *configW;
1284 TRACE("%p %p %d %p\n", hService, config, size, needed);
1286 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, 2 * size )))
1288 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1289 return FALSE;
1291 configW = (QUERY_SERVICE_CONFIGW *)buffer;
1292 ret = QueryServiceConfigW( hService, configW, 2 * size, needed );
1293 if (!ret) goto done;
1295 config->dwServiceType = configW->dwServiceType;
1296 config->dwStartType = configW->dwStartType;
1297 config->dwErrorControl = configW->dwErrorControl;
1298 config->lpBinaryPathName = NULL;
1299 config->lpLoadOrderGroup = NULL;
1300 config->dwTagId = configW->dwTagId;
1301 config->lpDependencies = NULL;
1302 config->lpServiceStartName = NULL;
1303 config->lpDisplayName = NULL;
1305 p = (LPSTR)(config + 1);
1306 n = size - sizeof(*config);
1307 ret = FALSE;
1309 #define MAP_STR(str) \
1310 do { \
1311 if (configW->str) \
1313 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1314 if (!sz) goto done; \
1315 config->str = p; \
1316 p += sz; \
1317 n -= sz; \
1319 } while (0)
1321 MAP_STR( lpBinaryPathName );
1322 MAP_STR( lpLoadOrderGroup );
1323 MAP_STR( lpDependencies );
1324 MAP_STR( lpServiceStartName );
1325 MAP_STR( lpDisplayName );
1326 #undef MAP_STR
1328 *needed = p - (LPSTR)config;
1329 ret = TRUE;
1331 done:
1332 HeapFree( GetProcessHeap(), 0, buffer );
1333 return ret;
1336 static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
1338 DWORD cb;
1340 if (!*string_ptr)
1342 cb = sizeof(WCHAR);
1343 memset(*buf, 0, cb);
1345 else
1347 cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
1348 memcpy(*buf, *string_ptr, cb);
1349 MIDL_user_free(*string_ptr);
1352 *string_ptr = (LPWSTR)*buf;
1353 *buf += cb;
1355 return cb;
1358 static DWORD size_string(LPCWSTR string)
1360 return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
1363 /******************************************************************************
1364 * QueryServiceConfigW [ADVAPI32.@]
1366 BOOL WINAPI
1367 QueryServiceConfigW( SC_HANDLE hService,
1368 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1369 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1371 QUERY_SERVICE_CONFIGW config;
1372 DWORD total;
1373 DWORD err;
1374 BYTE *bufpos;
1376 TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1377 cbBufSize, pcbBytesNeeded);
1379 memset(&config, 0, sizeof(config));
1381 __TRY
1383 err = svcctl_QueryServiceConfigW(hService, &config);
1385 __EXCEPT(rpc_filter)
1387 err = map_exception_code(GetExceptionCode());
1389 __ENDTRY
1391 if (err != ERROR_SUCCESS)
1393 TRACE("services.exe: error %u\n", err);
1394 SetLastError(err);
1395 return FALSE;
1398 /* calculate the size required first */
1399 total = sizeof (QUERY_SERVICE_CONFIGW);
1400 total += size_string(config.lpBinaryPathName);
1401 total += size_string(config.lpLoadOrderGroup);
1402 total += size_string(config.lpDependencies);
1403 total += size_string(config.lpServiceStartName);
1404 total += size_string(config.lpDisplayName);
1406 *pcbBytesNeeded = total;
1408 /* if there's not enough memory, return an error */
1409 if( total > cbBufSize )
1411 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1412 MIDL_user_free(config.lpBinaryPathName);
1413 MIDL_user_free(config.lpLoadOrderGroup);
1414 MIDL_user_free(config.lpDependencies);
1415 MIDL_user_free(config.lpServiceStartName);
1416 MIDL_user_free(config.lpDisplayName);
1417 return FALSE;
1420 *lpServiceConfig = config;
1421 bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
1422 move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
1423 move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
1424 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
1425 move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
1426 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
1428 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1429 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1430 TRACE("Dependencies = %s\n", debugstr_w(lpServiceConfig->lpDependencies) );
1431 TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig->lpServiceStartName) );
1432 TRACE("Display name = %s\n", debugstr_w(lpServiceConfig->lpDisplayName) );
1434 return TRUE;
1437 /******************************************************************************
1438 * QueryServiceConfig2A [ADVAPI32.@]
1440 * Note
1441 * observed under win2k:
1442 * The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
1443 * required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
1445 BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1446 DWORD size, LPDWORD needed)
1448 BOOL ret;
1449 LPBYTE bufferW = NULL;
1451 if(buffer && size)
1452 bufferW = HeapAlloc( GetProcessHeap(), 0, size);
1454 ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
1455 if(!ret) goto cleanup;
1457 switch(dwLevel) {
1458 case SERVICE_CONFIG_DESCRIPTION:
1459 if (buffer && bufferW) {
1460 LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
1461 LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
1462 if (configW->lpDescription && (size > sizeof(SERVICE_DESCRIPTIONA))) {
1463 DWORD sz;
1464 configA->lpDescription = (LPSTR)(configA + 1);
1465 sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
1466 configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
1467 if (!sz) {
1468 FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1469 ret = FALSE;
1470 configA->lpDescription = NULL;
1473 else configA->lpDescription = NULL;
1475 break;
1476 case SERVICE_CONFIG_PRESHUTDOWN_INFO:
1477 if (buffer && bufferW && *needed<=size)
1478 memcpy(buffer, bufferW, *needed);
1479 break;
1480 default:
1481 FIXME("conversation W->A not implemented for level %d\n", dwLevel);
1482 ret = FALSE;
1483 break;
1486 cleanup:
1487 HeapFree( GetProcessHeap(), 0, bufferW);
1488 return ret;
1491 /******************************************************************************
1492 * QueryServiceConfig2W [ADVAPI32.@]
1494 * See QueryServiceConfig2A.
1496 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1497 DWORD size, LPDWORD needed)
1499 DWORD err;
1501 if(dwLevel!=SERVICE_CONFIG_DESCRIPTION && dwLevel!=SERVICE_CONFIG_PRESHUTDOWN_INFO) {
1502 FIXME("Level %d not implemented\n", dwLevel);
1503 SetLastError(ERROR_INVALID_LEVEL);
1504 return FALSE;
1507 if(!buffer && size) {
1508 SetLastError(ERROR_INVALID_ADDRESS);
1509 return FALSE;
1512 TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
1514 __TRY
1516 err = svcctl_QueryServiceConfig2W(hService, dwLevel, buffer, size, needed);
1518 __EXCEPT(rpc_filter)
1520 err = map_exception_code(GetExceptionCode());
1522 __ENDTRY
1524 if (err != ERROR_SUCCESS)
1526 SetLastError( err );
1527 return FALSE;
1530 switch (dwLevel)
1532 case SERVICE_CONFIG_DESCRIPTION:
1533 if (buffer)
1535 SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
1536 if (descr->lpDescription) /* make it an absolute pointer */
1537 descr->lpDescription = (WCHAR *)(buffer + (ULONG_PTR)descr->lpDescription);
1538 break;
1542 return TRUE;
1545 /******************************************************************************
1546 * EnumServicesStatusA [ADVAPI32.@]
1548 BOOL WINAPI
1549 EnumServicesStatusA( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSA
1550 services, DWORD size, LPDWORD needed, LPDWORD returned,
1551 LPDWORD resume_handle )
1553 BOOL ret;
1554 unsigned int i;
1555 ENUM_SERVICE_STATUSW *servicesW = NULL;
1556 DWORD sz, n;
1557 char *p;
1559 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
1560 returned, resume_handle);
1562 sz = max( 2 * size, sizeof(*servicesW) );
1563 if (!(servicesW = HeapAlloc( GetProcessHeap(), 0, sz )))
1565 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1566 return FALSE;
1569 ret = EnumServicesStatusW( hmngr, type, state, servicesW, sz, needed, returned, resume_handle );
1570 if (!ret) goto done;
1572 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUSA);
1573 n = size - (p - (char *)services);
1574 ret = FALSE;
1575 for (i = 0; i < *returned; i++)
1577 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
1578 if (!sz) goto done;
1579 services[i].lpServiceName = p;
1580 p += sz;
1581 n -= sz;
1582 if (servicesW[i].lpDisplayName)
1584 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
1585 if (!sz) goto done;
1586 services[i].lpDisplayName = p;
1587 p += sz;
1588 n -= sz;
1590 else services[i].lpDisplayName = NULL;
1591 services[i].ServiceStatus = servicesW[i].ServiceStatus;
1594 ret = TRUE;
1596 done:
1597 HeapFree( GetProcessHeap(), 0, servicesW );
1598 return ret;
1601 /******************************************************************************
1602 * EnumServicesStatusW [ADVAPI32.@]
1604 BOOL WINAPI
1605 EnumServicesStatusW( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSW
1606 services, DWORD size, LPDWORD needed, LPDWORD returned,
1607 LPDWORD resume_handle )
1609 DWORD err, i;
1610 ENUM_SERVICE_STATUSW dummy_status;
1612 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
1613 returned, resume_handle);
1615 if (resume_handle)
1616 FIXME("resume handle not supported\n");
1618 if (!hmngr)
1620 SetLastError( ERROR_INVALID_HANDLE );
1621 return FALSE;
1624 /* make sure we pass a valid pointer */
1625 if (!services || size < sizeof(*services))
1627 services = &dummy_status;
1628 size = sizeof(dummy_status);
1631 __TRY
1633 err = svcctl_EnumServicesStatusW( hmngr, type, state, (BYTE *)services, size, needed, returned );
1635 __EXCEPT(rpc_filter)
1637 err = map_exception_code( GetExceptionCode() );
1639 __ENDTRY
1641 if (err != ERROR_SUCCESS)
1643 SetLastError( err );
1644 return FALSE;
1647 for (i = 0; i < *returned; i++)
1649 /* convert buffer offsets into pointers */
1650 services[i].lpServiceName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpServiceName);
1651 if (services[i].lpDisplayName)
1652 services[i].lpDisplayName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpDisplayName);
1655 return TRUE;
1658 /******************************************************************************
1659 * EnumServicesStatusExA [ADVAPI32.@]
1661 BOOL WINAPI
1662 EnumServicesStatusExA( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state,
1663 LPBYTE buffer, DWORD size, LPDWORD needed, LPDWORD returned,
1664 LPDWORD resume_handle, LPCSTR group )
1666 BOOL ret;
1667 unsigned int i;
1668 ENUM_SERVICE_STATUS_PROCESSA *services = (ENUM_SERVICE_STATUS_PROCESSA *)buffer;
1669 ENUM_SERVICE_STATUS_PROCESSW *servicesW = NULL;
1670 WCHAR *groupW = NULL;
1671 DWORD sz, n;
1672 char *p;
1674 TRACE("%p %u 0x%x 0x%x %p %u %p %p %p %s\n", hmngr, level, type, state, buffer,
1675 size, needed, returned, resume_handle, debugstr_a(group));
1677 sz = max( 2 * size, sizeof(*servicesW) );
1678 if (!(servicesW = HeapAlloc( GetProcessHeap(), 0, sz )))
1680 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1681 return FALSE;
1683 if (group)
1685 int len = MultiByteToWideChar( CP_ACP, 0, group, -1, NULL, 0 );
1686 if (!(groupW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1688 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1689 HeapFree( GetProcessHeap(), 0, servicesW );
1690 return FALSE;
1692 MultiByteToWideChar( CP_ACP, 0, group, -1, groupW, len * sizeof(WCHAR) );
1695 ret = EnumServicesStatusExW( hmngr, level, type, state, (BYTE *)servicesW, sz,
1696 needed, returned, resume_handle, groupW );
1697 if (!ret) goto done;
1699 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUS_PROCESSA);
1700 n = size - (p - (char *)services);
1701 ret = FALSE;
1702 for (i = 0; i < *returned; i++)
1704 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
1705 if (!sz) goto done;
1706 services[i].lpServiceName = p;
1707 p += sz;
1708 n -= sz;
1709 if (servicesW[i].lpDisplayName)
1711 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
1712 if (!sz) goto done;
1713 services[i].lpDisplayName = p;
1714 p += sz;
1715 n -= sz;
1717 else services[i].lpDisplayName = NULL;
1718 services[i].ServiceStatusProcess = servicesW[i].ServiceStatusProcess;
1721 ret = TRUE;
1723 done:
1724 HeapFree( GetProcessHeap(), 0, servicesW );
1725 HeapFree( GetProcessHeap(), 0, groupW );
1726 return ret;
1729 /******************************************************************************
1730 * EnumServicesStatusExW [ADVAPI32.@]
1732 BOOL WINAPI
1733 EnumServicesStatusExW( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state,
1734 LPBYTE buffer, DWORD size, LPDWORD needed, LPDWORD returned,
1735 LPDWORD resume_handle, LPCWSTR group )
1737 DWORD err, i;
1738 ENUM_SERVICE_STATUS_PROCESSW dummy_status;
1739 ENUM_SERVICE_STATUS_PROCESSW *services = (ENUM_SERVICE_STATUS_PROCESSW *)buffer;
1741 TRACE("%p %u 0x%x 0x%x %p %u %p %p %p %s\n", hmngr, level, type, state, buffer,
1742 size, needed, returned, resume_handle, debugstr_w(group));
1744 if (resume_handle)
1745 FIXME("resume handle not supported\n");
1747 if (level != SC_ENUM_PROCESS_INFO)
1749 SetLastError( ERROR_INVALID_LEVEL );
1750 return FALSE;
1752 if (!hmngr)
1754 SetLastError( ERROR_INVALID_HANDLE );
1755 return FALSE;
1758 /* make sure we pass a valid buffer pointer */
1759 if (!services || size < sizeof(*services))
1761 buffer = (BYTE *)&dummy_status;
1762 size = sizeof(dummy_status);
1765 __TRY
1767 err = svcctl_EnumServicesStatusExW( hmngr, type, state, buffer, size, needed,
1768 returned, group );
1770 __EXCEPT(rpc_filter)
1772 err = map_exception_code( GetExceptionCode() );
1774 __ENDTRY
1776 if (err != ERROR_SUCCESS)
1778 SetLastError( err );
1779 return FALSE;
1782 for (i = 0; i < *returned; i++)
1784 /* convert buffer offsets into pointers */
1785 services[i].lpServiceName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpServiceName);
1786 if (services[i].lpDisplayName)
1787 services[i].lpDisplayName = (WCHAR *)((char *)services + (DWORD_PTR)services[i].lpDisplayName);
1790 return TRUE;
1793 /******************************************************************************
1794 * GetServiceKeyNameA [ADVAPI32.@]
1796 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1797 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1799 LPWSTR lpDisplayNameW, lpServiceNameW;
1800 DWORD sizeW;
1801 BOOL ret = FALSE;
1803 TRACE("%p %s %p %p\n", hSCManager,
1804 debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1806 lpDisplayNameW = SERV_dup(lpDisplayName);
1807 if (lpServiceName)
1808 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1809 else
1810 lpServiceNameW = NULL;
1812 sizeW = *lpcchBuffer;
1813 if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
1815 if (lpServiceName && *lpcchBuffer)
1816 lpServiceName[0] = 0;
1817 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1818 goto cleanup;
1821 if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
1822 *lpcchBuffer, NULL, NULL ))
1824 if (*lpcchBuffer && lpServiceName)
1825 lpServiceName[0] = 0;
1826 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
1827 goto cleanup;
1830 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1831 ret = TRUE;
1833 cleanup:
1834 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1835 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1836 return ret;
1839 /******************************************************************************
1840 * GetServiceKeyNameW [ADVAPI32.@]
1842 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1843 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1845 DWORD err;
1846 WCHAR buffer[2];
1847 DWORD size;
1849 TRACE("%p %s %p %p\n", hSCManager,
1850 debugstr_w(lpDisplayName), lpServiceName, lpcchBuffer);
1852 if (!hSCManager)
1854 SetLastError( ERROR_INVALID_HANDLE );
1855 return 0;
1858 /* provide a buffer if the caller didn't */
1859 if (!lpServiceName || *lpcchBuffer < 2)
1861 lpServiceName = buffer;
1862 /* A size of 1 would be enough, but tests show that Windows returns 2,
1863 * probably because of a WCHAR/bytes mismatch in their code.
1865 *lpcchBuffer = 2;
1868 /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
1869 * includes the nul-terminator on input. */
1870 size = *lpcchBuffer - 1;
1872 __TRY
1874 err = svcctl_GetServiceKeyNameW(hSCManager, lpDisplayName, lpServiceName,
1875 &size);
1877 __EXCEPT(rpc_filter)
1879 err = map_exception_code(GetExceptionCode());
1881 __ENDTRY
1883 /* The value of *lpcchBuffer excludes nul-terminator on output. */
1884 if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
1885 *lpcchBuffer = size;
1887 if (err)
1888 SetLastError(err);
1889 return err == ERROR_SUCCESS;
1892 /******************************************************************************
1893 * QueryServiceLockStatusA [ADVAPI32.@]
1895 BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
1896 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1897 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1899 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1901 return FALSE;
1904 /******************************************************************************
1905 * QueryServiceLockStatusW [ADVAPI32.@]
1907 BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
1908 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1909 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1911 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1913 return FALSE;
1916 /******************************************************************************
1917 * GetServiceDisplayNameA [ADVAPI32.@]
1919 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1920 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1922 LPWSTR lpServiceNameW, lpDisplayNameW;
1923 DWORD sizeW;
1924 BOOL ret = FALSE;
1926 TRACE("%p %s %p %p\n", hSCManager,
1927 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1929 lpServiceNameW = SERV_dup(lpServiceName);
1930 if (lpDisplayName)
1931 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1932 else
1933 lpDisplayNameW = NULL;
1935 sizeW = *lpcchBuffer;
1936 if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
1938 if (lpDisplayName && *lpcchBuffer)
1939 lpDisplayName[0] = 0;
1940 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1941 goto cleanup;
1944 if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
1945 *lpcchBuffer, NULL, NULL ))
1947 if (*lpcchBuffer && lpDisplayName)
1948 lpDisplayName[0] = 0;
1949 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
1950 goto cleanup;
1953 /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
1954 * (but if the function succeeded it means that is a good upper estimation of the size) */
1955 ret = TRUE;
1957 cleanup:
1958 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1959 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1960 return ret;
1963 /******************************************************************************
1964 * GetServiceDisplayNameW [ADVAPI32.@]
1966 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1967 LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1969 DWORD err;
1970 DWORD size;
1971 WCHAR buffer[2];
1973 TRACE("%p %s %p %p\n", hSCManager,
1974 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1976 if (!hSCManager)
1978 SetLastError( ERROR_INVALID_HANDLE );
1979 return 0;
1982 /* provide a buffer if the caller didn't */
1983 if (!lpDisplayName || *lpcchBuffer < 2)
1985 lpDisplayName = buffer;
1986 /* A size of 1 would be enough, but tests show that Windows returns 2,
1987 * probably because of a WCHAR/bytes mismatch in their code.
1989 *lpcchBuffer = 2;
1992 /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
1993 * includes the nul-terminator on input. */
1994 size = *lpcchBuffer - 1;
1996 __TRY
1998 err = svcctl_GetServiceDisplayNameW(hSCManager, lpServiceName, lpDisplayName,
1999 &size);
2001 __EXCEPT(rpc_filter)
2003 err = map_exception_code(GetExceptionCode());
2005 __ENDTRY
2007 /* The value of *lpcchBuffer excludes nul-terminator on output. */
2008 if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
2009 *lpcchBuffer = size;
2011 if (err)
2012 SetLastError(err);
2013 return err == ERROR_SUCCESS;
2016 /******************************************************************************
2017 * ChangeServiceConfigW [ADVAPI32.@]
2019 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
2020 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
2021 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
2022 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
2024 DWORD cb_pwd;
2025 DWORD err;
2027 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2028 hService, dwServiceType, dwStartType, dwErrorControl,
2029 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
2030 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
2031 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
2033 cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
2035 __TRY
2037 err = svcctl_ChangeServiceConfigW(hService, dwServiceType,
2038 dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId,
2039 (const BYTE *)lpDependencies, multisz_cb(lpDependencies), lpServiceStartName,
2040 (const BYTE *)lpPassword, cb_pwd, lpDisplayName);
2042 __EXCEPT(rpc_filter)
2044 err = map_exception_code(GetExceptionCode());
2046 __ENDTRY
2048 if (err != ERROR_SUCCESS)
2049 SetLastError(err);
2051 return err == ERROR_SUCCESS;
2054 /******************************************************************************
2055 * ChangeServiceConfigA [ADVAPI32.@]
2057 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
2058 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
2059 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
2060 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
2062 LPWSTR wBinaryPathName, wLoadOrderGroup, wDependencies;
2063 LPWSTR wServiceStartName, wPassword, wDisplayName;
2064 BOOL r;
2066 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2067 hService, dwServiceType, dwStartType, dwErrorControl,
2068 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
2069 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
2070 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
2072 wBinaryPathName = SERV_dup( lpBinaryPathName );
2073 wLoadOrderGroup = SERV_dup( lpLoadOrderGroup );
2074 wDependencies = SERV_dupmulti( lpDependencies );
2075 wServiceStartName = SERV_dup( lpServiceStartName );
2076 wPassword = SERV_dup( lpPassword );
2077 wDisplayName = SERV_dup( lpDisplayName );
2079 r = ChangeServiceConfigW( hService, dwServiceType,
2080 dwStartType, dwErrorControl, wBinaryPathName,
2081 wLoadOrderGroup, lpdwTagId, wDependencies,
2082 wServiceStartName, wPassword, wDisplayName);
2084 HeapFree( GetProcessHeap(), 0, wBinaryPathName );
2085 HeapFree( GetProcessHeap(), 0, wLoadOrderGroup );
2086 HeapFree( GetProcessHeap(), 0, wDependencies );
2087 HeapFree( GetProcessHeap(), 0, wServiceStartName );
2088 HeapFree( GetProcessHeap(), 0, wPassword );
2089 HeapFree( GetProcessHeap(), 0, wDisplayName );
2091 return r;
2094 /******************************************************************************
2095 * ChangeServiceConfig2A [ADVAPI32.@]
2097 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
2098 LPVOID lpInfo)
2100 BOOL r = FALSE;
2102 TRACE("%p %d %p\n",hService, dwInfoLevel, lpInfo);
2104 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2106 LPSERVICE_DESCRIPTIONA sd = lpInfo;
2107 SERVICE_DESCRIPTIONW sdw;
2109 sdw.lpDescription = SERV_dup( sd->lpDescription );
2111 r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
2113 HeapFree( GetProcessHeap(), 0, sdw.lpDescription );
2115 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
2117 LPSERVICE_FAILURE_ACTIONSA fa = lpInfo;
2118 SERVICE_FAILURE_ACTIONSW faw;
2120 faw.dwResetPeriod = fa->dwResetPeriod;
2121 faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg );
2122 faw.lpCommand = SERV_dup( fa->lpCommand );
2123 faw.cActions = fa->cActions;
2124 faw.lpsaActions = fa->lpsaActions;
2126 r = ChangeServiceConfig2W( hService, dwInfoLevel, &faw );
2128 HeapFree( GetProcessHeap(), 0, faw.lpRebootMsg );
2129 HeapFree( GetProcessHeap(), 0, faw.lpCommand );
2131 else if (dwInfoLevel == SERVICE_CONFIG_PRESHUTDOWN_INFO)
2133 r = ChangeServiceConfig2W( hService, dwInfoLevel, lpInfo);
2135 else
2136 SetLastError( ERROR_INVALID_PARAMETER );
2138 return r;
2141 /******************************************************************************
2142 * ChangeServiceConfig2W [ADVAPI32.@]
2144 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
2145 LPVOID lpInfo)
2147 DWORD err;
2149 __TRY
2151 err = svcctl_ChangeServiceConfig2W( hService, dwInfoLevel, lpInfo );
2153 __EXCEPT(rpc_filter)
2155 err = map_exception_code(GetExceptionCode());
2157 __ENDTRY
2159 if (err != ERROR_SUCCESS)
2160 SetLastError(err);
2162 return err == ERROR_SUCCESS;
2165 NTSTATUS SERV_QueryServiceObjectSecurity(SC_HANDLE hService,
2166 SECURITY_INFORMATION dwSecurityInformation,
2167 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2168 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2170 SECURITY_DESCRIPTOR descriptor;
2171 NTSTATUS status;
2172 DWORD size;
2173 ACL acl;
2175 FIXME("%p %d %p %u %p - semi-stub\n", hService, dwSecurityInformation,
2176 lpSecurityDescriptor, cbBufSize, pcbBytesNeeded);
2178 if (dwSecurityInformation != DACL_SECURITY_INFORMATION)
2179 FIXME("information %d not supported\n", dwSecurityInformation);
2181 InitializeSecurityDescriptor(&descriptor, SECURITY_DESCRIPTOR_REVISION);
2183 InitializeAcl(&acl, sizeof(ACL), ACL_REVISION);
2184 SetSecurityDescriptorDacl(&descriptor, TRUE, &acl, TRUE);
2186 size = cbBufSize;
2187 status = RtlMakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
2188 *pcbBytesNeeded = size;
2189 return status;
2192 /******************************************************************************
2193 * QueryServiceObjectSecurity [ADVAPI32.@]
2195 BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
2196 SECURITY_INFORMATION dwSecurityInformation,
2197 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2198 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2200 NTSTATUS status = SERV_QueryServiceObjectSecurity(hService, dwSecurityInformation, lpSecurityDescriptor,
2201 cbBufSize, pcbBytesNeeded);
2202 if (status != STATUS_SUCCESS)
2204 SetLastError(RtlNtStatusToDosError(status));
2205 return FALSE;
2207 return TRUE;
2210 /******************************************************************************
2211 * SetServiceObjectSecurity [ADVAPI32.@]
2213 * NOTES
2214 * - SetSecurityInfo should be updated to call this function once it's implemented.
2216 BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService,
2217 SECURITY_INFORMATION dwSecurityInformation,
2218 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2220 FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
2221 return TRUE;
2224 /******************************************************************************
2225 * SetServiceBits [ADVAPI32.@]
2227 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
2228 DWORD dwServiceBits,
2229 BOOL bSetBitsOn,
2230 BOOL bUpdateImmediately)
2232 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
2233 bSetBitsOn, bUpdateImmediately);
2234 return TRUE;
2237 /* thunk for calling the RegisterServiceCtrlHandler handler function */
2238 static DWORD WINAPI ctrl_handler_thunk( DWORD control, DWORD type, void *data, void *context )
2240 LPHANDLER_FUNCTION func = context;
2242 func( control );
2243 return ERROR_SUCCESS;
2246 /******************************************************************************
2247 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
2249 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER_FUNCTION handler )
2251 return RegisterServiceCtrlHandlerExA( name, ctrl_handler_thunk, handler );
2254 /******************************************************************************
2255 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
2257 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLER_FUNCTION handler )
2259 return RegisterServiceCtrlHandlerExW( name, ctrl_handler_thunk, handler );
2262 /******************************************************************************
2263 * RegisterServiceCtrlHandlerExA [ADVAPI32.@]
2265 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDLER_FUNCTION_EX handler, LPVOID context )
2267 LPWSTR nameW;
2268 SERVICE_STATUS_HANDLE ret;
2270 nameW = SERV_dup(name);
2271 ret = RegisterServiceCtrlHandlerExW( nameW, handler, context );
2272 HeapFree( GetProcessHeap(), 0, nameW );
2273 return ret;
2276 /******************************************************************************
2277 * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
2279 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
2280 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2282 service_data *service;
2283 SC_HANDLE hService = 0;
2284 BOOL found = FALSE;
2286 TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
2288 EnterCriticalSection( &service_cs );
2289 if ((service = find_service_by_name( lpServiceName )))
2291 service->handler = lpHandlerProc;
2292 service->context = lpContext;
2293 hService = service->handle;
2294 found = TRUE;
2296 LeaveCriticalSection( &service_cs );
2298 if (!found) SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
2300 return (SERVICE_STATUS_HANDLE)hService;
2303 /******************************************************************************
2304 * EnumDependentServicesA [ADVAPI32.@]
2306 BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState,
2307 LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize,
2308 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2310 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2311 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2313 *lpServicesReturned = 0;
2314 return TRUE;
2317 /******************************************************************************
2318 * EnumDependentServicesW [ADVAPI32.@]
2320 BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
2321 LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize,
2322 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2324 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2325 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2327 *lpServicesReturned = 0;
2328 return TRUE;