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
24 #include "wine/port.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
44 #include "wine/exception.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(service
);
48 static const WCHAR szServiceManagerKey
[] = { 'S','y','s','t','e','m','\\',
49 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
50 'S','e','r','v','i','c','e','s',0 };
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 static const GENERIC_MAPPING scm_generic
= {
63 (STANDARD_RIGHTS_READ
| SC_MANAGER_ENUMERATE_SERVICE
| SC_MANAGER_QUERY_LOCK_STATUS
),
64 (STANDARD_RIGHTS_WRITE
| SC_MANAGER_CREATE_SERVICE
| SC_MANAGER_MODIFY_BOOT_CONFIG
),
65 (STANDARD_RIGHTS_EXECUTE
| SC_MANAGER_CONNECT
| SC_MANAGER_LOCK
),
69 static const GENERIC_MAPPING svc_generic
= {
70 (STANDARD_RIGHTS_READ
| SERVICE_QUERY_CONFIG
| SERVICE_QUERY_STATUS
| SERVICE_INTERROGATE
| SERVICE_ENUMERATE_DEPENDENTS
),
71 (STANDARD_RIGHTS_WRITE
| SERVICE_CHANGE_CONFIG
),
72 (STANDARD_RIGHTS_EXECUTE
| SERVICE_START
| SERVICE_STOP
| SERVICE_PAUSE_CONTINUE
| SERVICE_USER_DEFINED_CONTROL
),
76 typedef struct service_data_t
78 LPHANDLER_FUNCTION_EX handler
;
84 LPSERVICE_MAIN_FUNCTIONA a
;
85 LPSERVICE_MAIN_FUNCTIONW w
;
91 static CRITICAL_SECTION service_cs
;
92 static CRITICAL_SECTION_DEBUG service_cs_debug
=
95 { &service_cs_debug
.ProcessLocksList
,
96 &service_cs_debug
.ProcessLocksList
},
97 0, 0, { (DWORD_PTR
)(__FILE__
": service_cs") }
99 static CRITICAL_SECTION service_cs
= { &service_cs_debug
, -1, 0, 0, 0, 0 };
101 static service_data
**services
;
102 static unsigned int nb_services
;
103 static HANDLE service_event
;
105 extern HANDLE
__wine_make_process_system(void);
107 /******************************************************************************
111 #define MAX_SERVICE_NAME 256
113 typedef enum { SC_HTYPE_MANAGER
, SC_HTYPE_SERVICE
} SC_HANDLE_TYPE
;
116 typedef VOID (*sc_handle_destructor
)(struct sc_handle
*);
120 SC_HANDLE_TYPE htype
;
122 sc_handle_destructor destroy
;
123 SC_RPC_HANDLE server_handle
; /* server-side handle */
126 struct sc_manager
/* service control manager handle */
128 struct sc_handle hdr
;
129 HKEY hkey
; /* handle to services database in the registry */
133 struct sc_service
/* service handle */
135 struct sc_handle hdr
;
136 HKEY hkey
; /* handle to service entry in the registry (under hkey) */
138 struct sc_manager
*scm
; /* pointer to SCM handle */
142 static void *sc_handle_alloc(SC_HANDLE_TYPE htype
, DWORD size
,
143 sc_handle_destructor destroy
)
145 struct sc_handle
*hdr
;
147 hdr
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
152 hdr
->destroy
= destroy
;
154 TRACE("sc_handle type=%d -> %p\n", htype
, hdr
);
158 static void *sc_handle_get_handle_data(SC_HANDLE handle
, DWORD htype
)
160 struct sc_handle
*hdr
= (struct sc_handle
*) handle
;
164 if (hdr
->htype
!= htype
)
169 static void sc_handle_free(struct sc_handle
* hdr
)
173 if (--hdr
->ref_count
)
176 HeapFree(GetProcessHeap(), 0, hdr
);
179 static void sc_handle_destroy_manager(struct sc_handle
*handle
)
181 struct sc_manager
*mgr
= (struct sc_manager
*) handle
;
183 TRACE("destroying SC Manager %p\n", mgr
);
185 RegCloseKey(mgr
->hkey
);
188 static void sc_handle_destroy_service(struct sc_handle
*handle
)
190 struct sc_service
*svc
= (struct sc_service
*) handle
;
192 TRACE("destroying service %p\n", svc
);
194 RegCloseKey(svc
->hkey
);
196 sc_handle_free(&svc
->scm
->hdr
);
200 /******************************************************************************
201 * String management functions (same behaviour as strdup)
202 * NOTE: the caller of those functions is responsible for calling HeapFree
203 * in order to release the memory allocated by those functions.
205 static inline LPWSTR
SERV_dup( LPCSTR str
)
212 len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
213 wstr
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof (WCHAR
) );
214 MultiByteToWideChar( CP_ACP
, 0, str
, -1, wstr
, len
);
218 static inline LPWSTR
SERV_dupmulti(LPCSTR str
)
226 len
+= MultiByteToWideChar( CP_ACP
, 0, &str
[n
], -1, NULL
, 0 );
227 n
+= (strlen( &str
[n
] ) + 1);
232 wstr
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof (WCHAR
) );
233 MultiByteToWideChar( CP_ACP
, 0, str
, n
, wstr
, len
);
237 static inline DWORD
multisz_cb(LPCWSTR wmultisz
)
239 const WCHAR
*wptr
= wmultisz
;
241 if (wmultisz
== NULL
)
245 wptr
+= lstrlenW(wptr
)+1;
246 return (wptr
- wmultisz
+ 1)*sizeof(WCHAR
);
249 /******************************************************************************
250 * RPC connection with services.exe
253 handle_t __RPC_USER
MACHINE_HANDLEW_bind(MACHINE_HANDLEW MachineName
)
255 WCHAR transport
[] = SVCCTL_TRANSPORT
;
256 WCHAR endpoint
[] = SVCCTL_ENDPOINT
;
257 RPC_WSTR binding_str
;
261 status
= RpcStringBindingComposeW(NULL
, transport
, (RPC_WSTR
)MachineName
, endpoint
, NULL
, &binding_str
);
262 if (status
!= RPC_S_OK
)
264 ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD
)status
);
268 status
= RpcBindingFromStringBindingW(binding_str
, &rpc_handle
);
269 RpcStringFreeW(&binding_str
);
271 if (status
!= RPC_S_OK
)
273 ERR("Couldn't connect to services.exe: error code %u\n", (DWORD
)status
);
280 void __RPC_USER
MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName
, handle_t h
)
285 static LONG WINAPI
rpc_filter(EXCEPTION_POINTERS
*eptr
)
287 return I_RpcExceptionFilter(eptr
->ExceptionRecord
->ExceptionCode
);
290 static DWORD
map_exception_code(DWORD exception_code
)
292 switch (exception_code
)
294 case RPC_X_NULL_REF_POINTER
:
295 case RPC_X_ENUM_VALUE_OUT_OF_RANGE
:
296 case RPC_X_BYTE_COUNT_TOO_SMALL
:
297 return ERROR_INVALID_PARAMETER
;
299 return exception_code
;
303 /******************************************************************************
304 * Service IPC functions
306 static LPWSTR
service_get_pipe_name(void)
308 static const WCHAR format
[] = { '\\','\\','.','\\','p','i','p','e','\\',
309 'n','e','t','\\','N','t','C','o','n','t','r','o','l','P','i','p','e','%','u',0};
310 static const WCHAR service_current_key_str
[] = { 'S','Y','S','T','E','M','\\',
311 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
312 'C','o','n','t','r','o','l','\\',
313 'S','e','r','v','i','c','e','C','u','r','r','e','n','t',0};
316 HKEY service_current_key
;
317 DWORD service_current
;
321 ret
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, service_current_key_str
, 0,
322 KEY_QUERY_VALUE
, &service_current_key
);
323 if (ret
!= ERROR_SUCCESS
)
325 len
= sizeof(service_current
);
326 ret
= RegQueryValueExW(service_current_key
, NULL
, NULL
, &type
,
327 (BYTE
*)&service_current
, &len
);
328 RegCloseKey(service_current_key
);
329 if (ret
!= ERROR_SUCCESS
|| type
!= REG_DWORD
)
331 len
= sizeof(format
)/sizeof(WCHAR
) + 10 /* strlenW("4294967295") */;
332 name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
335 snprintfW(name
, len
, format
, service_current
);
339 static HANDLE
service_open_pipe(void)
341 LPWSTR szPipe
= service_get_pipe_name();
342 HANDLE handle
= INVALID_HANDLE_VALUE
;
345 handle
= CreateFileW(szPipe
, GENERIC_READ
|GENERIC_WRITE
,
346 0, NULL
, OPEN_ALWAYS
, 0, NULL
);
347 if (handle
!= INVALID_HANDLE_VALUE
)
349 if (GetLastError() != ERROR_PIPE_BUSY
)
351 } while (WaitNamedPipeW(szPipe
, NMPWAIT_WAIT_FOREVER
));
352 HeapFree(GetProcessHeap(), 0, szPipe
);
357 static service_data
*find_service_by_name( const WCHAR
*name
)
361 if (nb_services
== 1) /* only one service (FIXME: should depend on OWN_PROCESS etc.) */
363 for (i
= 0; i
< nb_services
; i
++)
364 if (!strcmpiW( name
, services
[i
]->name
)) return services
[i
];
368 /******************************************************************************
371 * Call into the main service routine provided by StartServiceCtrlDispatcher.
373 static DWORD WINAPI
service_thread(LPVOID arg
)
375 service_data
*info
= arg
;
376 LPWSTR str
= info
->args
;
377 DWORD argc
= 0, len
= 0;
383 len
+= strlenW(&str
[len
]) + 1;
390 info
->proc
.w(0, NULL
);
392 info
->proc
.a(0, NULL
);
400 argv
= HeapAlloc(GetProcessHeap(), 0, (argc
+1)*sizeof(LPWSTR
));
401 for (argc
=0, p
=str
; *p
; p
+= strlenW(p
) + 1)
405 info
->proc
.w(argc
, argv
);
406 HeapFree(GetProcessHeap(), 0, argv
);
410 LPSTR strA
, *argv
, p
;
413 lenA
= WideCharToMultiByte(CP_ACP
,0, str
, len
, NULL
, 0, NULL
, NULL
);
414 strA
= HeapAlloc(GetProcessHeap(), 0, lenA
);
415 WideCharToMultiByte(CP_ACP
,0, str
, len
, strA
, lenA
, NULL
, NULL
);
417 argv
= HeapAlloc(GetProcessHeap(), 0, (argc
+1)*sizeof(LPSTR
));
418 for (argc
=0, p
=strA
; *p
; p
+= strlen(p
) + 1)
422 info
->proc
.a(argc
, argv
);
423 HeapFree(GetProcessHeap(), 0, argv
);
424 HeapFree(GetProcessHeap(), 0, strA
);
429 /******************************************************************************
430 * service_handle_start
432 static DWORD
service_handle_start(service_data
*service
, const WCHAR
*data
, DWORD count
)
434 TRACE("%s argsize %u\n", debugstr_w(service
->name
), count
);
438 WARN("service is not stopped\n");
439 return ERROR_SERVICE_ALREADY_RUNNING
;
442 HeapFree(GetProcessHeap(), 0, service
->args
);
443 service
->args
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WCHAR
));
444 memcpy( service
->args
, data
, count
* sizeof(WCHAR
) );
445 service
->thread
= CreateThread( NULL
, 0, service_thread
,
447 SetEvent( service_event
); /* notify the main loop */
451 /******************************************************************************
452 * service_handle_control
454 static DWORD
service_handle_control(service_data
*service
, DWORD dwControl
)
456 DWORD ret
= ERROR_INVALID_SERVICE_CONTROL
;
458 TRACE("%s control %u\n", debugstr_w(service
->name
), dwControl
);
460 if (service
->handler
)
461 ret
= service
->handler(dwControl
, 0, NULL
, service
->context
);
465 /******************************************************************************
466 * service_control_dispatcher
468 static DWORD WINAPI
service_control_dispatcher(LPVOID arg
)
473 if (!(manager
= OpenSCManagerW( NULL
, NULL
, SC_MANAGER_CONNECT
)))
475 ERR("failed to open service manager error %u\n", GetLastError());
479 pipe
= service_open_pipe();
481 if (pipe
==INVALID_HANDLE_VALUE
)
483 ERR("failed to create control pipe error = %d\n", GetLastError());
487 /* dispatcher loop */
490 service_data
*service
;
491 service_start_info info
;
494 DWORD data_size
= 0, count
, result
;
496 r
= ReadFile( pipe
, &info
, FIELD_OFFSET(service_start_info
,data
), &count
, NULL
);
499 if (GetLastError() != ERROR_BROKEN_PIPE
)
500 ERR( "pipe read failed error %u\n", GetLastError() );
503 if (count
!= FIELD_OFFSET(service_start_info
,data
))
505 ERR( "partial pipe read %u\n", count
);
508 if (count
< info
.total_size
)
510 data_size
= info
.total_size
- FIELD_OFFSET(service_start_info
,data
);
511 data
= HeapAlloc( GetProcessHeap(), 0, data_size
);
512 r
= ReadFile( pipe
, data
, data_size
, &count
, NULL
);
515 if (GetLastError() != ERROR_BROKEN_PIPE
)
516 ERR( "pipe read failed error %u\n", GetLastError() );
519 if (count
!= data_size
)
521 ERR( "partial pipe read %u/%u\n", count
, data_size
);
526 /* find the service */
528 if (!(service
= find_service_by_name( data
)))
530 FIXME( "got request %u for unknown service %s\n", info
.cmd
, debugstr_w(data
));
531 result
= ERROR_INVALID_PARAMETER
;
535 TRACE( "got request %u for service %s\n", info
.cmd
, debugstr_w(data
) );
537 /* handle the request */
540 case WINESERV_STARTINFO
:
541 if (!service
->handle
)
543 if (!(service
->handle
= OpenServiceW( manager
, data
, SERVICE_SET_STATUS
)))
544 FIXME( "failed to open service %s\n", debugstr_w(data
) );
546 result
= service_handle_start(service
, data
+ info
.name_size
,
547 data_size
/ sizeof(WCHAR
) - info
.name_size
);
549 case WINESERV_SENDCONTROL
:
550 result
= service_handle_control(service
, info
.control
);
553 ERR("received invalid command %u\n", info
.cmd
);
554 result
= ERROR_INVALID_PARAMETER
;
559 WriteFile(pipe
, &result
, sizeof(result
), &count
, NULL
);
560 HeapFree( GetProcessHeap(), 0, data
);
564 CloseServiceHandle( manager
);
568 /******************************************************************************
569 * service_run_main_thread
571 static BOOL
service_run_main_thread(void)
574 HANDLE wait_handles
[MAXIMUM_WAIT_OBJECTS
];
575 UINT wait_services
[MAXIMUM_WAIT_OBJECTS
];
577 service_event
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
579 /* FIXME: service_control_dispatcher should be merged into the main thread */
580 wait_handles
[0] = __wine_make_process_system();
581 wait_handles
[1] = CreateThread( NULL
, 0, service_control_dispatcher
, NULL
, 0, NULL
);
582 wait_handles
[2] = service_event
;
584 TRACE("Starting %d services running as process %d\n",
585 nb_services
, GetCurrentProcessId());
587 /* wait for all the threads to pack up and exit */
590 EnterCriticalSection( &service_cs
);
591 for (i
= 0, n
= 3; i
< nb_services
&& n
< MAXIMUM_WAIT_OBJECTS
; i
++)
593 if (!services
[i
]->thread
) continue;
594 wait_services
[n
] = i
;
595 wait_handles
[n
++] = services
[i
]->thread
;
597 LeaveCriticalSection( &service_cs
);
599 ret
= WaitForMultipleObjects( n
, wait_handles
, FALSE
, INFINITE
);
600 if (!ret
) /* system process event */
602 TRACE( "last user process exited, shutting down\n" );
603 /* FIXME: we should maybe send a shutdown control to running services */
608 TRACE( "control dispatcher exited, shutting down\n" );
609 /* FIXME: we should maybe send a shutdown control to running services */
614 continue; /* rebuild the list */
618 services
[wait_services
[ret
]]->thread
= 0;
619 CloseHandle( wait_handles
[ret
] );
620 if (n
== 4) return TRUE
; /* it was the last running thread */
626 /******************************************************************************
627 * StartServiceCtrlDispatcherA [ADVAPI32.@]
629 * See StartServiceCtrlDispatcherW.
631 BOOL WINAPI
StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA
*servent
)
637 TRACE("%p\n", servent
);
641 SetLastError( ERROR_SERVICE_ALREADY_RUNNING
);
644 while (servent
[nb_services
].lpServiceName
) nb_services
++;
645 services
= HeapAlloc( GetProcessHeap(), 0, nb_services
* sizeof(*services
) );
647 for (i
= 0; i
< nb_services
; i
++)
649 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, servent
[i
].lpServiceName
, -1, NULL
, 0);
650 DWORD sz
= FIELD_OFFSET( service_data
, name
[len
] );
651 info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sz
);
652 MultiByteToWideChar(CP_ACP
, 0, servent
[i
].lpServiceName
, -1, info
->name
, len
);
653 info
->proc
.a
= servent
[i
].lpServiceProc
;
654 info
->unicode
= FALSE
;
658 service_run_main_thread();
663 /******************************************************************************
664 * StartServiceCtrlDispatcherW [ADVAPI32.@]
666 * Connects a process containing one or more services to the service control
670 * servent [I] A list of the service names and service procedures
676 BOOL WINAPI
StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW
*servent
)
682 TRACE("%p\n", servent
);
686 SetLastError( ERROR_SERVICE_ALREADY_RUNNING
);
689 while (servent
[nb_services
].lpServiceName
) nb_services
++;
690 services
= HeapAlloc( GetProcessHeap(), 0, nb_services
* sizeof(*services
) );
692 for (i
= 0; i
< nb_services
; i
++)
694 DWORD len
= strlenW(servent
[i
].lpServiceName
) + 1;
695 DWORD sz
= FIELD_OFFSET( service_data
, name
[len
] );
696 info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sz
);
697 strcpyW(info
->name
, servent
[i
].lpServiceName
);
698 info
->proc
.w
= servent
[i
].lpServiceProc
;
699 info
->unicode
= TRUE
;
703 service_run_main_thread();
708 /******************************************************************************
709 * LockServiceDatabase [ADVAPI32.@]
711 SC_LOCK WINAPI
LockServiceDatabase (SC_HANDLE hSCManager
)
713 struct sc_manager
*hscm
;
714 SC_RPC_LOCK hLock
= NULL
;
717 TRACE("%p\n",hSCManager
);
719 hscm
= sc_handle_get_handle_data( hSCManager
, SC_HTYPE_MANAGER
);
722 SetLastError( ERROR_INVALID_HANDLE
);
728 err
= svcctl_LockServiceDatabase(hscm
->hdr
.server_handle
, &hLock
);
732 err
= map_exception_code(GetExceptionCode());
735 if (err
!= ERROR_SUCCESS
)
743 /******************************************************************************
744 * UnlockServiceDatabase [ADVAPI32.@]
746 BOOL WINAPI
UnlockServiceDatabase (SC_LOCK ScLock
)
749 SC_RPC_LOCK hRpcLock
= ScLock
;
751 TRACE("%p\n",ScLock
);
755 err
= svcctl_UnlockServiceDatabase(&hRpcLock
);
759 err
= map_exception_code(GetExceptionCode());
762 if (err
!= ERROR_SUCCESS
)
770 /******************************************************************************
771 * SetServiceStatus [ADVAPI32.@]
778 SetServiceStatus( SERVICE_STATUS_HANDLE hService
, LPSERVICE_STATUS lpStatus
)
780 struct sc_service
*hsvc
;
783 TRACE("%p %x %x %x %x %x %x %x\n", hService
,
784 lpStatus
->dwServiceType
, lpStatus
->dwCurrentState
,
785 lpStatus
->dwControlsAccepted
, lpStatus
->dwWin32ExitCode
,
786 lpStatus
->dwServiceSpecificExitCode
, lpStatus
->dwCheckPoint
,
787 lpStatus
->dwWaitHint
);
789 hsvc
= sc_handle_get_handle_data((SC_HANDLE
)hService
, SC_HTYPE_SERVICE
);
792 SetLastError( ERROR_INVALID_HANDLE
);
798 err
= svcctl_SetServiceStatus( hsvc
->hdr
.server_handle
, lpStatus
);
802 err
= map_exception_code(GetExceptionCode());
805 if (err
!= ERROR_SUCCESS
)
811 if (lpStatus
->dwCurrentState
== SERVICE_STOPPED
)
812 CloseServiceHandle((SC_HANDLE
)hService
);
818 /******************************************************************************
819 * OpenSCManagerA [ADVAPI32.@]
821 * Establish a connection to the service control manager and open its database.
824 * lpMachineName [I] Pointer to machine name string
825 * lpDatabaseName [I] Pointer to database name string
826 * dwDesiredAccess [I] Type of access
829 * Success: A Handle to the service control manager database
832 SC_HANDLE WINAPI
OpenSCManagerA( LPCSTR lpMachineName
, LPCSTR lpDatabaseName
,
833 DWORD dwDesiredAccess
)
835 LPWSTR lpMachineNameW
, lpDatabaseNameW
;
838 lpMachineNameW
= SERV_dup(lpMachineName
);
839 lpDatabaseNameW
= SERV_dup(lpDatabaseName
);
840 ret
= OpenSCManagerW(lpMachineNameW
, lpDatabaseNameW
, dwDesiredAccess
);
841 HeapFree(GetProcessHeap(), 0, lpDatabaseNameW
);
842 HeapFree(GetProcessHeap(), 0, lpMachineNameW
);
846 /******************************************************************************
847 * OpenSCManagerW [ADVAPI32.@]
849 * See OpenSCManagerA.
851 SC_HANDLE WINAPI
OpenSCManagerW( LPCWSTR lpMachineName
, LPCWSTR lpDatabaseName
,
852 DWORD dwDesiredAccess
)
854 struct sc_manager
*manager
;
857 DWORD new_mask
= dwDesiredAccess
;
859 TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName
),
860 debugstr_w(lpDatabaseName
), dwDesiredAccess
);
862 manager
= sc_handle_alloc( SC_HTYPE_MANAGER
, sizeof (struct sc_manager
),
863 sc_handle_destroy_manager
);
869 r
= svcctl_OpenSCManagerW(lpMachineName
, lpDatabaseName
, dwDesiredAccess
, &manager
->hdr
.server_handle
);
873 r
= map_exception_code(GetExceptionCode());
876 if (r
!=ERROR_SUCCESS
)
879 r
= RegConnectRegistryW(lpMachineName
,HKEY_LOCAL_MACHINE
,&hReg
);
880 if (r
!=ERROR_SUCCESS
)
883 r
= RegCreateKeyW(hReg
, szServiceManagerKey
, &manager
->hkey
);
885 if (r
!=ERROR_SUCCESS
)
888 RtlMapGenericMask(&new_mask
, &scm_generic
);
889 manager
->dwAccess
= new_mask
;
890 TRACE("returning %p (access : 0x%08x)\n", manager
, manager
->dwAccess
);
892 return (SC_HANDLE
) &manager
->hdr
;
895 sc_handle_free( &manager
->hdr
);
900 /******************************************************************************
901 * ControlService [ADVAPI32.@]
903 * Send a control code to a service.
906 * hService [I] Handle of the service control manager database
907 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
908 * lpServiceStatus [O] Destination for the status of the service, if available
915 * Unlike M$' implementation, control requests are not serialized and may be
916 * processed asynchronously.
918 BOOL WINAPI
ControlService( SC_HANDLE hService
, DWORD dwControl
,
919 LPSERVICE_STATUS lpServiceStatus
)
921 struct sc_service
*hsvc
;
924 TRACE("%p %d %p\n", hService
, dwControl
, lpServiceStatus
);
926 hsvc
= sc_handle_get_handle_data(hService
, SC_HTYPE_SERVICE
);
929 SetLastError( ERROR_INVALID_HANDLE
);
935 err
= svcctl_ControlService(hsvc
->hdr
.server_handle
, dwControl
, lpServiceStatus
);
939 err
= map_exception_code(GetExceptionCode());
942 if (err
!= ERROR_SUCCESS
)
951 /******************************************************************************
952 * CloseServiceHandle [ADVAPI32.@]
954 * Close a handle to a service or the service control manager database.
957 * hSCObject [I] Handle to service or service control manager database
964 CloseServiceHandle( SC_HANDLE hSCObject
)
966 struct sc_handle
*obj
;
969 TRACE("%p\n", hSCObject
);
970 if (hSCObject
== NULL
)
972 SetLastError(ERROR_INVALID_HANDLE
);
976 obj
= (struct sc_handle
*)hSCObject
;
979 err
= svcctl_CloseServiceHandle(&obj
->server_handle
);
983 err
= map_exception_code(GetExceptionCode());
986 sc_handle_free( obj
);
988 if (err
!= ERROR_SUCCESS
)
997 /******************************************************************************
998 * OpenServiceA [ADVAPI32.@]
1000 * Open a handle to a service.
1003 * hSCManager [I] Handle of the service control manager database
1004 * lpServiceName [I] Name of the service to open
1005 * dwDesiredAccess [I] Access required to the service
1008 * Success: Handle to the service
1011 SC_HANDLE WINAPI
OpenServiceA( SC_HANDLE hSCManager
, LPCSTR lpServiceName
,
1012 DWORD dwDesiredAccess
)
1014 LPWSTR lpServiceNameW
;
1017 TRACE("%p %s %d\n", hSCManager
, debugstr_a(lpServiceName
), dwDesiredAccess
);
1019 lpServiceNameW
= SERV_dup(lpServiceName
);
1020 ret
= OpenServiceW( hSCManager
, lpServiceNameW
, dwDesiredAccess
);
1021 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
1026 /******************************************************************************
1027 * OpenServiceW [ADVAPI32.@]
1031 SC_HANDLE WINAPI
OpenServiceW( SC_HANDLE hSCManager
, LPCWSTR lpServiceName
,
1032 DWORD dwDesiredAccess
)
1034 struct sc_manager
*hscm
;
1035 struct sc_service
*hsvc
;
1038 DWORD new_mask
= dwDesiredAccess
;
1040 TRACE("%p %s %d\n", hSCManager
, debugstr_w(lpServiceName
), dwDesiredAccess
);
1042 hscm
= sc_handle_get_handle_data( hSCManager
, SC_HTYPE_MANAGER
);
1045 SetLastError( ERROR_INVALID_HANDLE
);
1051 SetLastError(ERROR_INVALID_ADDRESS
);
1055 len
= strlenW(lpServiceName
)+1;
1056 hsvc
= sc_handle_alloc( SC_HTYPE_SERVICE
,
1057 sizeof (struct sc_service
) + len
*sizeof(WCHAR
),
1058 sc_handle_destroy_service
);
1061 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1064 strcpyW( hsvc
->name
, lpServiceName
);
1066 /* add reference to SCM handle */
1067 hscm
->hdr
.ref_count
++;
1072 err
= svcctl_OpenServiceW(hscm
->hdr
.server_handle
, lpServiceName
, dwDesiredAccess
, &hsvc
->hdr
.server_handle
);
1074 __EXCEPT(rpc_filter
)
1076 err
= map_exception_code(GetExceptionCode());
1080 if (err
!= ERROR_SUCCESS
)
1082 sc_handle_free(&hsvc
->hdr
);
1087 /* for parts of advapi32 not using services.exe yet */
1088 RtlMapGenericMask(&new_mask
, &svc_generic
);
1089 hsvc
->dwAccess
= new_mask
;
1091 err
= RegOpenKeyExW( hscm
->hkey
, lpServiceName
, 0, KEY_ALL_ACCESS
, &hsvc
->hkey
);
1092 if (err
!= ERROR_SUCCESS
)
1093 ERR("Shouldn't hapen - service key for service validated by services.exe doesn't exist\n");
1095 TRACE("returning %p\n",hsvc
);
1097 return (SC_HANDLE
) &hsvc
->hdr
;
1100 /******************************************************************************
1101 * CreateServiceW [ADVAPI32.@]
1104 CreateServiceW( SC_HANDLE hSCManager
, LPCWSTR lpServiceName
,
1105 LPCWSTR lpDisplayName
, DWORD dwDesiredAccess
,
1106 DWORD dwServiceType
, DWORD dwStartType
,
1107 DWORD dwErrorControl
, LPCWSTR lpBinaryPathName
,
1108 LPCWSTR lpLoadOrderGroup
, LPDWORD lpdwTagId
,
1109 LPCWSTR lpDependencies
, LPCWSTR lpServiceStartName
,
1110 LPCWSTR lpPassword
)
1112 struct sc_manager
*hscm
;
1113 struct sc_service
*hsvc
= NULL
;
1114 DWORD new_mask
= dwDesiredAccess
;
1118 TRACE("%p %s %s\n", hSCManager
,
1119 debugstr_w(lpServiceName
), debugstr_w(lpDisplayName
));
1121 hscm
= sc_handle_get_handle_data( hSCManager
, SC_HTYPE_MANAGER
);
1124 SetLastError( ERROR_INVALID_HANDLE
);
1128 if (!lpServiceName
|| !lpBinaryPathName
)
1130 SetLastError(ERROR_INVALID_ADDRESS
);
1135 passwdlen
= (strlenW(lpPassword
) + 1) * sizeof(WCHAR
);
1139 len
= strlenW(lpServiceName
)+1;
1140 len
= sizeof (struct sc_service
) + len
*sizeof(WCHAR
);
1141 hsvc
= sc_handle_alloc( SC_HTYPE_SERVICE
, len
, sc_handle_destroy_service
);
1144 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1147 lstrcpyW( hsvc
->name
, lpServiceName
);
1150 hscm
->hdr
.ref_count
++;
1154 err
= svcctl_CreateServiceW(hscm
->hdr
.server_handle
, lpServiceName
,
1155 lpDisplayName
, dwDesiredAccess
, dwServiceType
, dwStartType
, dwErrorControl
,
1156 lpBinaryPathName
, lpLoadOrderGroup
, lpdwTagId
, (LPBYTE
)lpDependencies
,
1157 multisz_cb(lpDependencies
), lpServiceStartName
, (LPBYTE
)lpPassword
, passwdlen
,
1158 &hsvc
->hdr
.server_handle
);
1160 __EXCEPT(rpc_filter
)
1162 err
= map_exception_code(GetExceptionCode());
1166 if (err
!= ERROR_SUCCESS
)
1169 sc_handle_free(&hsvc
->hdr
);
1173 /* for parts of advapi32 not using services.exe yet */
1174 err
= RegOpenKeyW(hscm
->hkey
, lpServiceName
, &hsvc
->hkey
);
1175 if (err
!= ERROR_SUCCESS
)
1176 WINE_ERR("Couldn't open key that should have been created by services.exe\n");
1178 RtlMapGenericMask(&new_mask
, &svc_generic
);
1179 hsvc
->dwAccess
= new_mask
;
1181 return (SC_HANDLE
) &hsvc
->hdr
;
1185 /******************************************************************************
1186 * CreateServiceA [ADVAPI32.@]
1189 CreateServiceA( SC_HANDLE hSCManager
, LPCSTR lpServiceName
,
1190 LPCSTR lpDisplayName
, DWORD dwDesiredAccess
,
1191 DWORD dwServiceType
, DWORD dwStartType
,
1192 DWORD dwErrorControl
, LPCSTR lpBinaryPathName
,
1193 LPCSTR lpLoadOrderGroup
, LPDWORD lpdwTagId
,
1194 LPCSTR lpDependencies
, LPCSTR lpServiceStartName
,
1197 LPWSTR lpServiceNameW
, lpDisplayNameW
, lpBinaryPathNameW
,
1198 lpLoadOrderGroupW
, lpDependenciesW
, lpServiceStartNameW
, lpPasswordW
;
1201 TRACE("%p %s %s\n", hSCManager
,
1202 debugstr_a(lpServiceName
), debugstr_a(lpDisplayName
));
1204 lpServiceNameW
= SERV_dup( lpServiceName
);
1205 lpDisplayNameW
= SERV_dup( lpDisplayName
);
1206 lpBinaryPathNameW
= SERV_dup( lpBinaryPathName
);
1207 lpLoadOrderGroupW
= SERV_dup( lpLoadOrderGroup
);
1208 lpDependenciesW
= SERV_dupmulti( lpDependencies
);
1209 lpServiceStartNameW
= SERV_dup( lpServiceStartName
);
1210 lpPasswordW
= SERV_dup( lpPassword
);
1212 r
= CreateServiceW( hSCManager
, lpServiceNameW
, lpDisplayNameW
,
1213 dwDesiredAccess
, dwServiceType
, dwStartType
, dwErrorControl
,
1214 lpBinaryPathNameW
, lpLoadOrderGroupW
, lpdwTagId
,
1215 lpDependenciesW
, lpServiceStartNameW
, lpPasswordW
);
1217 HeapFree( GetProcessHeap(), 0, lpServiceNameW
);
1218 HeapFree( GetProcessHeap(), 0, lpDisplayNameW
);
1219 HeapFree( GetProcessHeap(), 0, lpBinaryPathNameW
);
1220 HeapFree( GetProcessHeap(), 0, lpLoadOrderGroupW
);
1221 HeapFree( GetProcessHeap(), 0, lpDependenciesW
);
1222 HeapFree( GetProcessHeap(), 0, lpServiceStartNameW
);
1223 HeapFree( GetProcessHeap(), 0, lpPasswordW
);
1229 /******************************************************************************
1230 * DeleteService [ADVAPI32.@]
1232 * Delete a service from the service control manager database.
1235 * hService [I] Handle of the service to delete
1241 BOOL WINAPI
DeleteService( SC_HANDLE hService
)
1243 struct sc_service
*hsvc
;
1246 hsvc
= sc_handle_get_handle_data(hService
, SC_HTYPE_SERVICE
);
1249 SetLastError( ERROR_INVALID_HANDLE
);
1255 err
= svcctl_DeleteService(hsvc
->hdr
.server_handle
);
1257 __EXCEPT(rpc_filter
)
1259 err
= map_exception_code(GetExceptionCode());
1268 /* Close the key to the service */
1269 RegCloseKey(hsvc
->hkey
);
1275 /******************************************************************************
1276 * StartServiceA [ADVAPI32.@]
1281 * hService [I] Handle of service
1282 * dwNumServiceArgs [I] Number of arguments
1283 * lpServiceArgVectors [I] Address of array of argument strings
1286 * - NT implements this function using an obscure RPC call.
1287 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1288 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
1289 * - This will only work for shared address space. How should the service
1290 * args be transferred when address spaces are separated?
1291 * - Can only start one service at a time.
1292 * - Has no concept of privilege.
1298 BOOL WINAPI
StartServiceA( SC_HANDLE hService
, DWORD dwNumServiceArgs
,
1299 LPCSTR
*lpServiceArgVectors
)
1301 LPWSTR
*lpwstr
=NULL
;
1305 TRACE("(%p,%d,%p)\n",hService
,dwNumServiceArgs
,lpServiceArgVectors
);
1307 if (dwNumServiceArgs
)
1308 lpwstr
= HeapAlloc( GetProcessHeap(), 0,
1309 dwNumServiceArgs
*sizeof(LPWSTR
) );
1311 for(i
=0; i
<dwNumServiceArgs
; i
++)
1312 lpwstr
[i
]=SERV_dup(lpServiceArgVectors
[i
]);
1314 r
= StartServiceW(hService
, dwNumServiceArgs
, (LPCWSTR
*)lpwstr
);
1316 if (dwNumServiceArgs
)
1318 for(i
=0; i
<dwNumServiceArgs
; i
++)
1319 HeapFree(GetProcessHeap(), 0, lpwstr
[i
]);
1320 HeapFree(GetProcessHeap(), 0, lpwstr
);
1327 /******************************************************************************
1328 * StartServiceW [ADVAPI32.@]
1330 * See StartServiceA.
1332 BOOL WINAPI
StartServiceW(SC_HANDLE hService
, DWORD dwNumServiceArgs
,
1333 LPCWSTR
*lpServiceArgVectors
)
1335 struct sc_service
*hsvc
;
1338 TRACE("%p %d %p\n", hService
, dwNumServiceArgs
, lpServiceArgVectors
);
1340 hsvc
= sc_handle_get_handle_data(hService
, SC_HTYPE_SERVICE
);
1343 SetLastError(ERROR_INVALID_HANDLE
);
1349 err
= svcctl_StartServiceW(hsvc
->hdr
.server_handle
, dwNumServiceArgs
, lpServiceArgVectors
);
1351 __EXCEPT(rpc_filter
)
1353 err
= map_exception_code(GetExceptionCode());
1356 if (err
!= ERROR_SUCCESS
)
1365 /******************************************************************************
1366 * QueryServiceStatus [ADVAPI32.@]
1369 * hService [I] Handle to service to get information about
1370 * lpservicestatus [O] buffer to receive the status information for the service
1373 BOOL WINAPI
QueryServiceStatus(SC_HANDLE hService
,
1374 LPSERVICE_STATUS lpservicestatus
)
1376 SERVICE_STATUS_PROCESS SvcStatusData
;
1380 TRACE("%p %p\n", hService
, lpservicestatus
);
1382 ret
= QueryServiceStatusEx(hService
, SC_STATUS_PROCESS_INFO
, (LPBYTE
)&SvcStatusData
,
1383 sizeof(SERVICE_STATUS_PROCESS
), &dummy
);
1384 if (ret
) memcpy(lpservicestatus
, &SvcStatusData
, sizeof(SERVICE_STATUS
)) ;
1389 /******************************************************************************
1390 * QueryServiceStatusEx [ADVAPI32.@]
1392 * Get information about a service.
1395 * hService [I] Handle to service to get information about
1396 * InfoLevel [I] Level of information to get
1397 * lpBuffer [O] Destination for requested information
1398 * cbBufSize [I] Size of lpBuffer in bytes
1399 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1405 BOOL WINAPI
QueryServiceStatusEx(SC_HANDLE hService
, SC_STATUS_TYPE InfoLevel
,
1406 LPBYTE lpBuffer
, DWORD cbBufSize
,
1407 LPDWORD pcbBytesNeeded
)
1409 struct sc_service
*hsvc
;
1412 TRACE("%p %d %p %d %p\n", hService
, InfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
1414 hsvc
= sc_handle_get_handle_data(hService
, SC_HTYPE_SERVICE
);
1417 SetLastError( ERROR_INVALID_HANDLE
);
1423 err
= svcctl_QueryServiceStatusEx(hsvc
->hdr
.server_handle
, InfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
1425 __EXCEPT(rpc_filter
)
1427 err
= map_exception_code(GetExceptionCode());
1430 if (err
!= ERROR_SUCCESS
)
1439 /******************************************************************************
1440 * QueryServiceConfigA [ADVAPI32.@]
1442 BOOL WINAPI
QueryServiceConfigA( SC_HANDLE hService
, LPQUERY_SERVICE_CONFIGA config
,
1443 DWORD size
, LPDWORD needed
)
1448 QUERY_SERVICE_CONFIGW
*configW
;
1450 TRACE("%p %p %d %p\n", hService
, config
, size
, needed
);
1452 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, 2 * size
)))
1454 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1457 configW
= (QUERY_SERVICE_CONFIGW
*)buffer
;
1458 ret
= QueryServiceConfigW( hService
, configW
, 2 * size
, needed
);
1459 if (!ret
) goto done
;
1461 config
->dwServiceType
= configW
->dwServiceType
;
1462 config
->dwStartType
= configW
->dwStartType
;
1463 config
->dwErrorControl
= configW
->dwErrorControl
;
1464 config
->lpBinaryPathName
= NULL
;
1465 config
->lpLoadOrderGroup
= NULL
;
1466 config
->dwTagId
= configW
->dwTagId
;
1467 config
->lpDependencies
= NULL
;
1468 config
->lpServiceStartName
= NULL
;
1469 config
->lpDisplayName
= NULL
;
1471 p
= (LPSTR
)(config
+ 1);
1472 n
= size
- sizeof(*config
);
1475 #define MAP_STR(str) \
1479 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1480 if (!sz) goto done; \
1487 MAP_STR( lpBinaryPathName
);
1488 MAP_STR( lpLoadOrderGroup
);
1489 MAP_STR( lpDependencies
);
1490 MAP_STR( lpServiceStartName
);
1491 MAP_STR( lpDisplayName
);
1494 *needed
= p
- (LPSTR
)config
;
1498 HeapFree( GetProcessHeap(), 0, buffer
);
1502 static DWORD
move_string_to_buffer(BYTE
**buf
, LPWSTR
*string_ptr
)
1509 memset(*buf
, 0, cb
);
1513 cb
= (strlenW(*string_ptr
) + 1)*sizeof(WCHAR
);
1514 memcpy(*buf
, *string_ptr
, cb
);
1515 MIDL_user_free(*string_ptr
);
1518 *string_ptr
= (LPWSTR
)*buf
;
1524 static DWORD
size_string(LPWSTR string
)
1526 return (string
? (strlenW(string
) + 1)*sizeof(WCHAR
) : sizeof(WCHAR
));
1529 /******************************************************************************
1530 * QueryServiceConfigW [ADVAPI32.@]
1533 QueryServiceConfigW( SC_HANDLE hService
,
1534 LPQUERY_SERVICE_CONFIGW lpServiceConfig
,
1535 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
)
1537 QUERY_SERVICE_CONFIGW config
;
1538 struct sc_service
*hsvc
;
1543 TRACE("%p %p %d %p\n", hService
, lpServiceConfig
,
1544 cbBufSize
, pcbBytesNeeded
);
1546 hsvc
= sc_handle_get_handle_data(hService
, SC_HTYPE_SERVICE
);
1549 SetLastError( ERROR_INVALID_HANDLE
);
1553 memset(&config
, 0, sizeof(config
));
1557 err
= svcctl_QueryServiceConfigW(hsvc
->hdr
.server_handle
, &config
);
1559 __EXCEPT(rpc_filter
)
1561 err
= map_exception_code(GetExceptionCode());
1565 if (err
!= ERROR_SUCCESS
)
1567 TRACE("services.exe: error %u\n", err
);
1572 /* calculate the size required first */
1573 total
= sizeof (QUERY_SERVICE_CONFIGW
);
1574 total
+= size_string(config
.lpBinaryPathName
);
1575 total
+= size_string(config
.lpLoadOrderGroup
);
1576 total
+= size_string(config
.lpDependencies
);
1577 total
+= size_string(config
.lpServiceStartName
);
1578 total
+= size_string(config
.lpDisplayName
);
1580 *pcbBytesNeeded
= total
;
1582 /* if there's not enough memory, return an error */
1583 if( total
> cbBufSize
)
1585 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1586 MIDL_user_free(config
.lpBinaryPathName
);
1587 MIDL_user_free(config
.lpLoadOrderGroup
);
1588 MIDL_user_free(config
.lpDependencies
);
1589 MIDL_user_free(config
.lpServiceStartName
);
1590 MIDL_user_free(config
.lpDisplayName
);
1594 *lpServiceConfig
= config
;
1595 bufpos
= ((BYTE
*)lpServiceConfig
) + sizeof(QUERY_SERVICE_CONFIGW
);
1596 move_string_to_buffer(&bufpos
, &lpServiceConfig
->lpBinaryPathName
);
1597 move_string_to_buffer(&bufpos
, &lpServiceConfig
->lpLoadOrderGroup
);
1598 move_string_to_buffer(&bufpos
, &lpServiceConfig
->lpDependencies
);
1599 move_string_to_buffer(&bufpos
, &lpServiceConfig
->lpServiceStartName
);
1600 move_string_to_buffer(&bufpos
, &lpServiceConfig
->lpDisplayName
);
1602 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig
->lpBinaryPathName
) );
1603 TRACE("Group = %s\n", debugstr_w(lpServiceConfig
->lpLoadOrderGroup
) );
1604 TRACE("Dependencies = %s\n", debugstr_w(lpServiceConfig
->lpDependencies
) );
1605 TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig
->lpServiceStartName
) );
1606 TRACE("Display name = %s\n", debugstr_w(lpServiceConfig
->lpDisplayName
) );
1611 /******************************************************************************
1612 * QueryServiceConfig2A [ADVAPI32.@]
1615 * observed under win2k:
1616 * The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
1617 * required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
1619 BOOL WINAPI
QueryServiceConfig2A(SC_HANDLE hService
, DWORD dwLevel
, LPBYTE buffer
,
1620 DWORD size
, LPDWORD needed
)
1623 LPBYTE bufferW
= NULL
;
1626 bufferW
= HeapAlloc( GetProcessHeap(), 0, size
);
1628 ret
= QueryServiceConfig2W(hService
, dwLevel
, bufferW
, size
, needed
);
1629 if(!ret
) goto cleanup
;
1632 case SERVICE_CONFIG_DESCRIPTION
:
1633 { LPSERVICE_DESCRIPTIONA configA
= (LPSERVICE_DESCRIPTIONA
) buffer
;
1634 LPSERVICE_DESCRIPTIONW configW
= (LPSERVICE_DESCRIPTIONW
) bufferW
;
1635 if (configW
->lpDescription
) {
1637 configA
->lpDescription
= (LPSTR
)(configA
+ 1);
1638 sz
= WideCharToMultiByte( CP_ACP
, 0, configW
->lpDescription
, -1,
1639 configA
->lpDescription
, size
- sizeof(SERVICE_DESCRIPTIONA
), NULL
, NULL
);
1641 FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1643 configA
->lpDescription
= NULL
;
1646 else configA
->lpDescription
= NULL
;
1650 FIXME("conversation W->A not implemented for level %d\n", dwLevel
);
1655 HeapFree( GetProcessHeap(), 0, bufferW
);
1659 /******************************************************************************
1660 * QueryServiceConfig2W [ADVAPI32.@]
1662 BOOL WINAPI
QueryServiceConfig2W(SC_HANDLE hService
, DWORD dwLevel
, LPBYTE buffer
,
1663 DWORD size
, LPDWORD needed
)
1668 struct sc_service
*hsvc
;
1670 if(dwLevel
!= SERVICE_CONFIG_DESCRIPTION
) {
1671 if((dwLevel
== SERVICE_CONFIG_DELAYED_AUTO_START_INFO
) ||
1672 (dwLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
) ||
1673 (dwLevel
== SERVICE_CONFIG_FAILURE_ACTIONS_FLAG
) ||
1674 (dwLevel
== SERVICE_CONFIG_PRESHUTDOWN_INFO
) ||
1675 (dwLevel
== SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO
) ||
1676 (dwLevel
== SERVICE_CONFIG_SERVICE_SID_INFO
))
1677 FIXME("Level %d not implemented\n", dwLevel
);
1678 SetLastError(ERROR_INVALID_LEVEL
);
1681 if(!needed
|| (!buffer
&& size
)) {
1682 SetLastError(ERROR_INVALID_ADDRESS
);
1686 TRACE("%p 0x%d %p 0x%d %p\n", hService
, dwLevel
, buffer
, size
, needed
);
1688 hsvc
= sc_handle_get_handle_data(hService
, SC_HTYPE_SERVICE
);
1691 SetLastError(ERROR_INVALID_HANDLE
);
1697 case SERVICE_CONFIG_DESCRIPTION
: {
1698 static const WCHAR szDescription
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1699 LPSERVICE_DESCRIPTIONW config
= (LPSERVICE_DESCRIPTIONW
) buffer
;
1700 LPBYTE strbuf
= NULL
;
1701 *needed
= sizeof (SERVICE_DESCRIPTIONW
);
1702 sz
= size
- *needed
;
1703 if(config
&& (*needed
<= size
))
1704 strbuf
= (LPBYTE
) (config
+ 1);
1705 r
= RegQueryValueExW( hKey
, szDescription
, 0, &type
, strbuf
, &sz
);
1706 if((r
== ERROR_SUCCESS
) && ( type
!= REG_SZ
)) {
1707 FIXME("SERVICE_CONFIG_DESCRIPTION: don't know how to handle type %d\n", type
);
1712 if(r
== ERROR_SUCCESS
)
1713 config
->lpDescription
= (LPWSTR
) (config
+ 1);
1715 config
->lpDescription
= NULL
;
1721 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1723 return (*needed
<= size
);
1726 /******************************************************************************
1727 * EnumServicesStatusA [ADVAPI32.@]
1730 EnumServicesStatusA( SC_HANDLE hSCManager
, DWORD dwServiceType
,
1731 DWORD dwServiceState
, LPENUM_SERVICE_STATUSA lpServices
,
1732 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
,
1733 LPDWORD lpServicesReturned
, LPDWORD lpResumeHandle
)
1735 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager
,
1736 dwServiceType
, dwServiceState
, lpServices
, cbBufSize
,
1737 pcbBytesNeeded
, lpServicesReturned
, lpResumeHandle
);
1738 SetLastError (ERROR_ACCESS_DENIED
);
1742 /******************************************************************************
1743 * EnumServicesStatusW [ADVAPI32.@]
1746 EnumServicesStatusW( SC_HANDLE hSCManager
, DWORD dwServiceType
,
1747 DWORD dwServiceState
, LPENUM_SERVICE_STATUSW lpServices
,
1748 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
,
1749 LPDWORD lpServicesReturned
, LPDWORD lpResumeHandle
)
1751 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager
,
1752 dwServiceType
, dwServiceState
, lpServices
, cbBufSize
,
1753 pcbBytesNeeded
, lpServicesReturned
, lpResumeHandle
);
1754 SetLastError (ERROR_ACCESS_DENIED
);
1758 /******************************************************************************
1759 * EnumServicesStatusExA [ADVAPI32.@]
1762 EnumServicesStatusExA(SC_HANDLE hSCManager
, SC_ENUM_TYPE InfoLevel
, DWORD dwServiceType
,
1763 DWORD dwServiceState
, LPBYTE lpServices
, DWORD cbBufSize
, LPDWORD pcbBytesNeeded
,
1764 LPDWORD lpServicesReturned
, LPDWORD lpResumeHandle
, LPCSTR pszGroupName
)
1766 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager
, InfoLevel
,
1767 dwServiceType
, dwServiceState
, lpServices
, cbBufSize
,
1768 pcbBytesNeeded
, lpServicesReturned
, lpResumeHandle
, debugstr_a(pszGroupName
));
1769 if (lpServicesReturned
) *lpServicesReturned
= 0;
1770 SetLastError (ERROR_ACCESS_DENIED
);
1774 /******************************************************************************
1775 * EnumServicesStatusExW [ADVAPI32.@]
1778 EnumServicesStatusExW(SC_HANDLE hSCManager
, SC_ENUM_TYPE InfoLevel
, DWORD dwServiceType
,
1779 DWORD dwServiceState
, LPBYTE lpServices
, DWORD cbBufSize
, LPDWORD pcbBytesNeeded
,
1780 LPDWORD lpServicesReturned
, LPDWORD lpResumeHandle
, LPCWSTR pszGroupName
)
1782 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager
, InfoLevel
,
1783 dwServiceType
, dwServiceState
, lpServices
, cbBufSize
,
1784 pcbBytesNeeded
, lpServicesReturned
, lpResumeHandle
, debugstr_w(pszGroupName
));
1785 SetLastError (ERROR_ACCESS_DENIED
);
1789 /******************************************************************************
1790 * GetServiceKeyNameA [ADVAPI32.@]
1792 BOOL WINAPI
GetServiceKeyNameA( SC_HANDLE hSCManager
, LPCSTR lpDisplayName
,
1793 LPSTR lpServiceName
, LPDWORD lpcchBuffer
)
1795 LPWSTR lpDisplayNameW
, lpServiceNameW
;
1799 TRACE("%p %s %p %p\n", hSCManager
,
1800 debugstr_a(lpDisplayName
), lpServiceName
, lpcchBuffer
);
1802 lpDisplayNameW
= SERV_dup(lpDisplayName
);
1804 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer
* sizeof(WCHAR
));
1806 lpServiceNameW
= NULL
;
1808 sizeW
= *lpcchBuffer
;
1809 if (!GetServiceKeyNameW(hSCManager
, lpDisplayNameW
, lpServiceNameW
, &sizeW
))
1811 if (lpServiceName
&& *lpcchBuffer
)
1812 lpServiceName
[0] = 0;
1813 *lpcchBuffer
= sizeW
*2; /* we can only provide an upper estimation of string length */
1817 if (!WideCharToMultiByte(CP_ACP
, 0, lpServiceNameW
, (sizeW
+ 1), lpServiceName
,
1818 *lpcchBuffer
, NULL
, NULL
))
1820 if (*lpcchBuffer
&& lpServiceName
)
1821 lpServiceName
[0] = 0;
1822 *lpcchBuffer
= WideCharToMultiByte(CP_ACP
, 0, lpServiceNameW
, -1, NULL
, 0, NULL
, NULL
);
1826 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1830 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
1831 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
1835 /******************************************************************************
1836 * GetServiceKeyNameW [ADVAPI32.@]
1838 BOOL WINAPI
GetServiceKeyNameW( SC_HANDLE hSCManager
, LPCWSTR lpDisplayName
,
1839 LPWSTR lpServiceName
, LPDWORD lpcchBuffer
)
1841 struct sc_manager
*hscm
;
1844 TRACE("%p %s %p %p\n", hSCManager
,
1845 debugstr_w(lpServiceName
), lpDisplayName
, lpcchBuffer
);
1847 hscm
= sc_handle_get_handle_data(hSCManager
, SC_HTYPE_MANAGER
);
1850 SetLastError(ERROR_INVALID_HANDLE
);
1856 SetLastError(ERROR_INVALID_ADDRESS
);
1862 err
= svcctl_GetServiceKeyNameW(hscm
->hdr
.server_handle
,
1863 lpDisplayName
, lpServiceName
, lpServiceName
? *lpcchBuffer
: 0, lpcchBuffer
);
1865 __EXCEPT(rpc_filter
)
1867 err
= map_exception_code(GetExceptionCode());
1873 return err
== ERROR_SUCCESS
;
1876 /******************************************************************************
1877 * QueryServiceLockStatusA [ADVAPI32.@]
1879 BOOL WINAPI
QueryServiceLockStatusA( SC_HANDLE hSCManager
,
1880 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
1881 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
)
1883 FIXME("%p %p %08x %p\n", hSCManager
, lpLockStatus
, cbBufSize
, pcbBytesNeeded
);
1888 /******************************************************************************
1889 * QueryServiceLockStatusW [ADVAPI32.@]
1891 BOOL WINAPI
QueryServiceLockStatusW( SC_HANDLE hSCManager
,
1892 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
1893 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
)
1895 FIXME("%p %p %08x %p\n", hSCManager
, lpLockStatus
, cbBufSize
, pcbBytesNeeded
);
1900 /******************************************************************************
1901 * GetServiceDisplayNameA [ADVAPI32.@]
1903 BOOL WINAPI
GetServiceDisplayNameA( SC_HANDLE hSCManager
, LPCSTR lpServiceName
,
1904 LPSTR lpDisplayName
, LPDWORD lpcchBuffer
)
1906 LPWSTR lpServiceNameW
, lpDisplayNameW
;
1910 TRACE("%p %s %p %p\n", hSCManager
,
1911 debugstr_a(lpServiceName
), lpDisplayName
, lpcchBuffer
);
1913 lpServiceNameW
= SERV_dup(lpServiceName
);
1915 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer
* sizeof(WCHAR
));
1917 lpDisplayNameW
= NULL
;
1919 sizeW
= *lpcchBuffer
;
1920 if (!GetServiceDisplayNameW(hSCManager
, lpServiceNameW
, lpDisplayNameW
, &sizeW
))
1922 if (lpDisplayName
&& *lpcchBuffer
)
1923 lpDisplayName
[0] = 0;
1924 *lpcchBuffer
= sizeW
*2; /* we can only provide an upper estimation of string length */
1928 if (!WideCharToMultiByte(CP_ACP
, 0, lpDisplayNameW
, (sizeW
+ 1), lpDisplayName
,
1929 *lpcchBuffer
, NULL
, NULL
))
1931 if (*lpcchBuffer
&& lpDisplayName
)
1932 lpDisplayName
[0] = 0;
1933 *lpcchBuffer
= WideCharToMultiByte(CP_ACP
, 0, lpDisplayNameW
, -1, NULL
, 0, NULL
, NULL
);
1937 /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
1938 * (but if the function succeeded it means that is a good upper estimation of the size) */
1942 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
1943 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
1947 /******************************************************************************
1948 * GetServiceDisplayNameW [ADVAPI32.@]
1950 BOOL WINAPI
GetServiceDisplayNameW( SC_HANDLE hSCManager
, LPCWSTR lpServiceName
,
1951 LPWSTR lpDisplayName
, LPDWORD lpcchBuffer
)
1953 struct sc_manager
*hscm
;
1956 TRACE("%p %s %p %p\n", hSCManager
,
1957 debugstr_w(lpServiceName
), lpDisplayName
, lpcchBuffer
);
1959 hscm
= sc_handle_get_handle_data(hSCManager
, SC_HTYPE_MANAGER
);
1962 SetLastError(ERROR_INVALID_HANDLE
);
1968 SetLastError(ERROR_INVALID_ADDRESS
);
1974 err
= svcctl_GetServiceDisplayNameW(hscm
->hdr
.server_handle
,
1975 lpServiceName
, lpDisplayName
, lpDisplayName
? *lpcchBuffer
: 0, lpcchBuffer
);
1977 __EXCEPT(rpc_filter
)
1979 err
= map_exception_code(GetExceptionCode());
1985 return err
== ERROR_SUCCESS
;
1988 /******************************************************************************
1989 * ChangeServiceConfigW [ADVAPI32.@]
1991 BOOL WINAPI
ChangeServiceConfigW( SC_HANDLE hService
, DWORD dwServiceType
,
1992 DWORD dwStartType
, DWORD dwErrorControl
, LPCWSTR lpBinaryPathName
,
1993 LPCWSTR lpLoadOrderGroup
, LPDWORD lpdwTagId
, LPCWSTR lpDependencies
,
1994 LPCWSTR lpServiceStartName
, LPCWSTR lpPassword
, LPCWSTR lpDisplayName
)
1996 struct sc_service
*hsvc
;
2000 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2001 hService
, dwServiceType
, dwStartType
, dwErrorControl
,
2002 debugstr_w(lpBinaryPathName
), debugstr_w(lpLoadOrderGroup
),
2003 lpdwTagId
, lpDependencies
, debugstr_w(lpServiceStartName
),
2004 debugstr_w(lpPassword
), debugstr_w(lpDisplayName
) );
2006 hsvc
= sc_handle_get_handle_data(hService
, SC_HTYPE_SERVICE
);
2009 SetLastError( ERROR_INVALID_HANDLE
);
2013 cb_pwd
= lpPassword
? (strlenW(lpPassword
) + 1)*sizeof(WCHAR
) : 0;
2017 err
= svcctl_ChangeServiceConfigW(hsvc
->hdr
.server_handle
, dwServiceType
,
2018 dwStartType
, dwErrorControl
, lpBinaryPathName
, lpLoadOrderGroup
, lpdwTagId
,
2019 (const BYTE
*)lpDependencies
, multisz_cb(lpDependencies
), lpServiceStartName
,
2020 (const BYTE
*)lpPassword
, cb_pwd
, lpDisplayName
);
2022 __EXCEPT(rpc_filter
)
2024 err
= map_exception_code(GetExceptionCode());
2028 if (err
!= ERROR_SUCCESS
)
2031 return err
== ERROR_SUCCESS
;
2034 /******************************************************************************
2035 * ChangeServiceConfigA [ADVAPI32.@]
2037 BOOL WINAPI
ChangeServiceConfigA( SC_HANDLE hService
, DWORD dwServiceType
,
2038 DWORD dwStartType
, DWORD dwErrorControl
, LPCSTR lpBinaryPathName
,
2039 LPCSTR lpLoadOrderGroup
, LPDWORD lpdwTagId
, LPCSTR lpDependencies
,
2040 LPCSTR lpServiceStartName
, LPCSTR lpPassword
, LPCSTR lpDisplayName
)
2042 LPWSTR wBinaryPathName
, wLoadOrderGroup
, wDependencies
;
2043 LPWSTR wServiceStartName
, wPassword
, wDisplayName
;
2046 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2047 hService
, dwServiceType
, dwStartType
, dwErrorControl
,
2048 debugstr_a(lpBinaryPathName
), debugstr_a(lpLoadOrderGroup
),
2049 lpdwTagId
, lpDependencies
, debugstr_a(lpServiceStartName
),
2050 debugstr_a(lpPassword
), debugstr_a(lpDisplayName
) );
2052 wBinaryPathName
= SERV_dup( lpBinaryPathName
);
2053 wLoadOrderGroup
= SERV_dup( lpLoadOrderGroup
);
2054 wDependencies
= SERV_dupmulti( lpDependencies
);
2055 wServiceStartName
= SERV_dup( lpServiceStartName
);
2056 wPassword
= SERV_dup( lpPassword
);
2057 wDisplayName
= SERV_dup( lpDisplayName
);
2059 r
= ChangeServiceConfigW( hService
, dwServiceType
,
2060 dwStartType
, dwErrorControl
, wBinaryPathName
,
2061 wLoadOrderGroup
, lpdwTagId
, wDependencies
,
2062 wServiceStartName
, wPassword
, wDisplayName
);
2064 HeapFree( GetProcessHeap(), 0, wBinaryPathName
);
2065 HeapFree( GetProcessHeap(), 0, wLoadOrderGroup
);
2066 HeapFree( GetProcessHeap(), 0, wDependencies
);
2067 HeapFree( GetProcessHeap(), 0, wServiceStartName
);
2068 HeapFree( GetProcessHeap(), 0, wPassword
);
2069 HeapFree( GetProcessHeap(), 0, wDisplayName
);
2074 /******************************************************************************
2075 * ChangeServiceConfig2A [ADVAPI32.@]
2077 BOOL WINAPI
ChangeServiceConfig2A( SC_HANDLE hService
, DWORD dwInfoLevel
,
2082 TRACE("%p %d %p\n",hService
, dwInfoLevel
, lpInfo
);
2084 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
2086 LPSERVICE_DESCRIPTIONA sd
= (LPSERVICE_DESCRIPTIONA
) lpInfo
;
2087 SERVICE_DESCRIPTIONW sdw
;
2089 sdw
.lpDescription
= SERV_dup( sd
->lpDescription
);
2091 r
= ChangeServiceConfig2W( hService
, dwInfoLevel
, &sdw
);
2093 HeapFree( GetProcessHeap(), 0, sdw
.lpDescription
);
2095 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
2097 LPSERVICE_FAILURE_ACTIONSA fa
= (LPSERVICE_FAILURE_ACTIONSA
) lpInfo
;
2098 SERVICE_FAILURE_ACTIONSW faw
;
2100 faw
.dwResetPeriod
= fa
->dwResetPeriod
;
2101 faw
.lpRebootMsg
= SERV_dup( fa
->lpRebootMsg
);
2102 faw
.lpCommand
= SERV_dup( fa
->lpCommand
);
2103 faw
.cActions
= fa
->cActions
;
2104 faw
.lpsaActions
= fa
->lpsaActions
;
2106 r
= ChangeServiceConfig2W( hService
, dwInfoLevel
, &faw
);
2108 HeapFree( GetProcessHeap(), 0, faw
.lpRebootMsg
);
2109 HeapFree( GetProcessHeap(), 0, faw
.lpCommand
);
2112 SetLastError( ERROR_INVALID_PARAMETER
);
2117 /******************************************************************************
2118 * ChangeServiceConfig2W [ADVAPI32.@]
2120 BOOL WINAPI
ChangeServiceConfig2W( SC_HANDLE hService
, DWORD dwInfoLevel
,
2124 struct sc_service
*hsvc
;
2126 hsvc
= sc_handle_get_handle_data(hService
, SC_HTYPE_SERVICE
);
2129 SetLastError( ERROR_INVALID_HANDLE
);
2134 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
2136 static const WCHAR szDescription
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
2137 LPSERVICE_DESCRIPTIONW sd
= (LPSERVICE_DESCRIPTIONW
)lpInfo
;
2138 if (sd
->lpDescription
)
2140 TRACE("Setting Description to %s\n",debugstr_w(sd
->lpDescription
));
2141 if (sd
->lpDescription
[0] == 0)
2142 RegDeleteValueW(hKey
,szDescription
);
2144 RegSetValueExW(hKey
, szDescription
, 0, REG_SZ
,
2145 (LPVOID
)sd
->lpDescription
,
2146 sizeof(WCHAR
)*(strlenW(sd
->lpDescription
)+1));
2150 FIXME("STUB: %p %d %p\n",hService
, dwInfoLevel
, lpInfo
);
2154 /******************************************************************************
2155 * QueryServiceObjectSecurity [ADVAPI32.@]
2157 BOOL WINAPI
QueryServiceObjectSecurity(SC_HANDLE hService
,
2158 SECURITY_INFORMATION dwSecurityInformation
,
2159 PSECURITY_DESCRIPTOR lpSecurityDescriptor
,
2160 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
)
2162 SECURITY_DESCRIPTOR descriptor
;
2167 FIXME("%p %d %p %u %p - semi-stub\n", hService
, dwSecurityInformation
,
2168 lpSecurityDescriptor
, cbBufSize
, pcbBytesNeeded
);
2170 if (dwSecurityInformation
!= DACL_SECURITY_INFORMATION
)
2171 FIXME("information %d not supported\n", dwSecurityInformation
);
2173 InitializeSecurityDescriptor(&descriptor
, SECURITY_DESCRIPTOR_REVISION
);
2175 InitializeAcl(&acl
, sizeof(ACL
), ACL_REVISION
);
2176 SetSecurityDescriptorDacl(&descriptor
, TRUE
, &acl
, TRUE
);
2179 succ
= MakeSelfRelativeSD(&descriptor
, lpSecurityDescriptor
, &size
);
2180 *pcbBytesNeeded
= size
;
2184 /******************************************************************************
2185 * SetServiceObjectSecurity [ADVAPI32.@]
2187 BOOL WINAPI
SetServiceObjectSecurity(SC_HANDLE hService
,
2188 SECURITY_INFORMATION dwSecurityInformation
,
2189 PSECURITY_DESCRIPTOR lpSecurityDescriptor
)
2191 FIXME("%p %d %p\n", hService
, dwSecurityInformation
, lpSecurityDescriptor
);
2195 /******************************************************************************
2196 * SetServiceBits [ADVAPI32.@]
2198 BOOL WINAPI
SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus
,
2199 DWORD dwServiceBits
,
2201 BOOL bUpdateImmediately
)
2203 FIXME("%p %08x %x %x\n", hServiceStatus
, dwServiceBits
,
2204 bSetBitsOn
, bUpdateImmediately
);
2208 /* thunk for calling the RegisterServiceCtrlHandler handler function */
2209 static DWORD WINAPI
ctrl_handler_thunk( DWORD control
, DWORD type
, void *data
, void *context
)
2211 LPHANDLER_FUNCTION func
= context
;
2214 return ERROR_SUCCESS
;
2217 /******************************************************************************
2218 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
2220 SERVICE_STATUS_HANDLE WINAPI
RegisterServiceCtrlHandlerA( LPCSTR name
, LPHANDLER_FUNCTION handler
)
2222 return RegisterServiceCtrlHandlerExA( name
, ctrl_handler_thunk
, handler
);
2225 /******************************************************************************
2226 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
2228 SERVICE_STATUS_HANDLE WINAPI
RegisterServiceCtrlHandlerW( LPCWSTR name
, LPHANDLER_FUNCTION handler
)
2230 return RegisterServiceCtrlHandlerExW( name
, ctrl_handler_thunk
, handler
);
2233 /******************************************************************************
2234 * RegisterServiceCtrlHandlerExA [ADVAPI32.@]
2236 SERVICE_STATUS_HANDLE WINAPI
RegisterServiceCtrlHandlerExA( LPCSTR name
, LPHANDLER_FUNCTION_EX handler
, LPVOID context
)
2239 SERVICE_STATUS_HANDLE ret
;
2241 nameW
= SERV_dup(name
);
2242 ret
= RegisterServiceCtrlHandlerExW( nameW
, handler
, context
);
2243 HeapFree( GetProcessHeap(), 0, nameW
);
2247 /******************************************************************************
2248 * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
2250 SERVICE_STATUS_HANDLE WINAPI
RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName
,
2251 LPHANDLER_FUNCTION_EX lpHandlerProc
, LPVOID lpContext
)
2253 service_data
*service
;
2254 SC_HANDLE hService
= 0;
2257 TRACE("%s %p %p\n", debugstr_w(lpServiceName
), lpHandlerProc
, lpContext
);
2259 EnterCriticalSection( &service_cs
);
2260 if ((service
= find_service_by_name( lpServiceName
)))
2262 service
->handler
= lpHandlerProc
;
2263 service
->context
= lpContext
;
2264 hService
= service
->handle
;
2267 LeaveCriticalSection( &service_cs
);
2269 if (!found
) SetLastError(ERROR_SERVICE_DOES_NOT_EXIST
);
2271 return (SERVICE_STATUS_HANDLE
)hService
;
2274 /******************************************************************************
2275 * EnumDependentServicesA [ADVAPI32.@]
2277 BOOL WINAPI
EnumDependentServicesA( SC_HANDLE hService
, DWORD dwServiceState
,
2278 LPENUM_SERVICE_STATUSA lpServices
, DWORD cbBufSize
,
2279 LPDWORD pcbBytesNeeded
, LPDWORD lpServicesReturned
)
2281 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService
, dwServiceState
,
2282 lpServices
, cbBufSize
, pcbBytesNeeded
, lpServicesReturned
);
2284 *lpServicesReturned
= 0;
2288 /******************************************************************************
2289 * EnumDependentServicesW [ADVAPI32.@]
2291 BOOL WINAPI
EnumDependentServicesW( SC_HANDLE hService
, DWORD dwServiceState
,
2292 LPENUM_SERVICE_STATUSW lpServices
, DWORD cbBufSize
,
2293 LPDWORD pcbBytesNeeded
, LPDWORD lpServicesReturned
)
2295 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService
, dwServiceState
,
2296 lpServices
, cbBufSize
, pcbBytesNeeded
, lpServicesReturned
);
2298 *lpServicesReturned
= 0;