2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wine/unicode.h"
32 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(advapi
);
37 static const WCHAR szServiceManagerKey
[] = { 'S','y','s','t','e','m','\\',
38 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
39 'S','e','r','v','i','c','e','s','\\',0 };
40 static const WCHAR szSCMLock
[] = {'A','D','V','A','P','I','_','S','C','M',
42 static const WCHAR szServiceShmemNameFmtW
[] = {'A','D','V','A','P','I','_',
43 'S','E','B','_','%','s',0};
45 struct SEB
/* service environment block */
46 { /* resides in service's shared memory object */
48 /* variable part of SEB contains service arguments */
51 /******************************************************************************
55 #define MAX_SERVICE_NAME 256
57 typedef enum { SC_HTYPE_MANAGER
, SC_HTYPE_SERVICE
} SC_HANDLE_TYPE
;
61 struct sc_manager
/* SCM handle */
63 HKEY hkey_scm_db
; /* handle to services database in the registry */
64 LONG ref_count
; /* handle must remain alive until any related service */
65 /* handle exists because DeleteService requires it */
68 struct sc_service
/* service handle */
70 HKEY hkey
; /* handle to service entry in the registry (under hkey_scm_db) */
71 struct sc_handle
*sc_manager
; /* pointer to SCM handle */
72 WCHAR name
[ MAX_SERVICE_NAME
];
80 struct sc_manager manager
;
81 struct sc_service service
;
85 static struct sc_handle
* alloc_sc_handle( SC_HANDLE_TYPE htype
)
87 struct sc_handle
*retval
;
89 retval
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct sc_handle
) );
92 retval
->htype
= htype
;
94 TRACE("SC_HANDLE type=%d -> %p\n",htype
,retval
);
98 static void free_sc_handle( struct sc_handle
* handle
)
103 switch( handle
->htype
)
105 case SC_HTYPE_MANAGER
:
107 if( InterlockedDecrement( &handle
->u
.manager
.ref_count
) )
108 /* there are references to this handle */
111 if( handle
->u
.manager
.hkey_scm_db
)
112 RegCloseKey( handle
->u
.manager
.hkey_scm_db
);
116 case SC_HTYPE_SERVICE
:
118 struct sc_handle
*h
= handle
->u
.service
.sc_manager
;
122 /* release SCM handle */
123 if( 0 == InterlockedDecrement( &h
->u
.manager
.ref_count
) )
125 /* it's time to destroy SCM handle */
126 if( h
->u
.manager
.hkey_scm_db
)
127 RegCloseKey( h
->u
.manager
.hkey_scm_db
);
129 TRACE("SC_HANDLE (SCM) %p type=%d\n",h
,h
->htype
);
131 HeapFree( GetProcessHeap(), 0, h
);
134 if( handle
->u
.service
.hkey
)
135 RegCloseKey( handle
->u
.service
.hkey
);
140 TRACE("SC_HANDLE %p type=%d\n",handle
,handle
->htype
);
142 HeapFree( GetProcessHeap(), 0, handle
);
145 static void init_service_handle( struct sc_handle
* handle
,
146 struct sc_handle
* sc_manager
,
147 HKEY hKey
, LPCWSTR lpServiceName
)
149 /* init sc_service structure */
150 handle
->u
.service
.hkey
= hKey
;
151 lstrcpynW( handle
->u
.service
.name
, lpServiceName
, MAX_SERVICE_NAME
);
153 /* add reference to SCM handle */
154 InterlockedIncrement( &sc_manager
->u
.manager
.ref_count
);
155 handle
->u
.service
.sc_manager
= sc_manager
;
158 static inline LPWSTR
SERV_dup( LPCSTR str
)
165 len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
166 wstr
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof (WCHAR
) );
167 MultiByteToWideChar( CP_ACP
, 0, str
, -1, wstr
, len
);
171 static inline LPWSTR
SERV_dupmulti( LPCSTR str
)
179 len
+= MultiByteToWideChar( CP_ACP
, 0, &str
[n
], -1, NULL
, 0 );
180 n
+= (strlen( &str
[n
] ) + 1);
185 wstr
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof (WCHAR
) );
186 MultiByteToWideChar( CP_ACP
, 0, str
, n
, wstr
, len
);
190 static inline VOID
SERV_free( LPWSTR wstr
)
192 HeapFree( GetProcessHeap(), 0, wstr
);
195 /******************************************************************************
196 * EnumServicesStatusA [ADVAPI32.@]
199 EnumServicesStatusA( SC_HANDLE hSCManager
, DWORD dwServiceType
,
200 DWORD dwServiceState
, LPENUM_SERVICE_STATUSA lpServices
,
201 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
,
202 LPDWORD lpServicesReturned
, LPDWORD lpResumeHandle
)
203 { FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager
,
204 dwServiceType
, dwServiceState
, lpServices
, cbBufSize
,
205 pcbBytesNeeded
, lpServicesReturned
, lpResumeHandle
);
206 SetLastError (ERROR_ACCESS_DENIED
);
210 /******************************************************************************
211 * EnumServicesStatusW [ADVAPI32.@]
214 EnumServicesStatusW( SC_HANDLE hSCManager
, DWORD dwServiceType
,
215 DWORD dwServiceState
, LPENUM_SERVICE_STATUSW lpServices
,
216 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
,
217 LPDWORD lpServicesReturned
, LPDWORD lpResumeHandle
)
218 { FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager
,
219 dwServiceType
, dwServiceState
, lpServices
, cbBufSize
,
220 pcbBytesNeeded
, lpServicesReturned
, lpResumeHandle
);
221 SetLastError (ERROR_ACCESS_DENIED
);
225 /******************************************************************************
228 * helper function for StartServiceCtrlDispatcherA/W
230 * SCM database is locked by StartService;
231 * open global SCM lock object and read service name
233 static BOOL
read_scm_lock_data( LPWSTR buffer
)
238 hLock
= OpenFileMappingW( FILE_MAP_ALL_ACCESS
, FALSE
, szSCMLock
);
241 SetLastError( ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
);
244 argptr
= MapViewOfFile( hLock
, FILE_MAP_ALL_ACCESS
,
245 0, 0, MAX_SERVICE_NAME
* sizeof(WCHAR
) );
248 CloseHandle( hLock
);
251 strcpyW( buffer
, argptr
);
252 UnmapViewOfFile( argptr
);
253 CloseHandle( hLock
);
257 /******************************************************************************
260 * helper function for StartServiceCtrlDispatcherA/W
262 static struct SEB
* open_seb_shmem( LPWSTR service_name
, HANDLE
* hServiceShmem
)
264 WCHAR object_name
[ MAX_PATH
];
268 snprintfW( object_name
, MAX_PATH
, szServiceShmemNameFmtW
, service_name
);
269 hmem
= OpenFileMappingW( FILE_MAP_ALL_ACCESS
, FALSE
, object_name
);
273 ret
= MapViewOfFile( hmem
, FILE_MAP_ALL_ACCESS
, 0, 0, 0 );
277 *hServiceShmem
= hmem
;
281 /******************************************************************************
284 * helper function for StartServiceCtrlDispatcherA/W
286 * Allocate and initialize array of LPWSTRs to arguments in variable part
287 * of service environment block.
288 * First entry in the array is reserved for service name and not initialized.
290 static LPWSTR
* build_arg_vectors( struct SEB
* seb
)
296 ret
= HeapAlloc( GetProcessHeap(), 0, (1 + seb
->argc
) * sizeof(LPWSTR
) );
300 argptr
= (LPWSTR
) &seb
[1];
301 for( i
= 0; i
< seb
->argc
; i
++ )
303 ret
[ 1 + i
] = argptr
;
304 argptr
+= 1 + strlenW( argptr
);
309 /******************************************************************************
310 * StartServiceCtrlDispatcherA [ADVAPI32.@]
313 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent
)
315 LPSERVICE_MAIN_FUNCTIONA fpMain
;
316 WCHAR service_name
[ MAX_SERVICE_NAME
];
317 HANDLE hServiceShmem
= NULL
;
318 struct SEB
*seb
= NULL
;
319 DWORD dwNumServiceArgs
= 0;
320 LPWSTR
*lpArgVecW
= NULL
;
321 LPSTR
*lpArgVecA
= NULL
;
325 TRACE("(%p)\n", servent
);
327 if( ! read_scm_lock_data( service_name
) )
329 /* FIXME: Instead of exiting we allow
330 service to be executed as ordinary program.
331 This behaviour was specially introduced in the patch
332 submitted against revision 1.45 and so preserved here.
334 FIXME("should fail with ERROR_FAILED_SERVICE_CONTROLLER_CONNECT\n");
335 servent
->lpServiceProc( 0, NULL
);
339 seb
= open_seb_shmem( service_name
, &hServiceShmem
);
343 lpArgVecW
= build_arg_vectors( seb
);
344 if( NULL
== lpArgVecW
)
347 lpArgVecW
[0] = service_name
;
348 dwNumServiceArgs
= seb
->argc
+ 1;
350 /* Convert the Unicode arg vectors back to ASCII */
351 lpArgVecA
= (LPSTR
*) HeapAlloc( GetProcessHeap(), 0,
352 dwNumServiceArgs
*sizeof(LPSTR
) );
353 for(i
=0; i
<dwNumServiceArgs
; i
++)
354 lpArgVecA
[i
]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW
[i
]);
356 /* FIXME: find service entry by name if SERVICE_WIN32_SHARE_PROCESS */
357 TRACE("%s at %p)\n", debugstr_a(servent
->lpServiceName
),servent
);
358 fpMain
= servent
->lpServiceProc
;
360 /* try to start the service */
361 fpMain( dwNumServiceArgs
, lpArgVecA
);
366 /* free arg strings */
367 for(i
=0; i
<dwNumServiceArgs
; i
++)
368 HeapFree(GetProcessHeap(), 0, lpArgVecA
[i
]);
369 HeapFree(GetProcessHeap(), 0, lpArgVecA
);
372 if( lpArgVecW
) HeapFree( GetProcessHeap(), 0, lpArgVecW
);
373 if( seb
) UnmapViewOfFile( seb
);
374 if( hServiceShmem
) CloseHandle( hServiceShmem
);
378 /******************************************************************************
379 * StartServiceCtrlDispatcherW [ADVAPI32.@]
385 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent
)
387 LPSERVICE_MAIN_FUNCTIONW fpMain
;
388 WCHAR service_name
[ MAX_SERVICE_NAME
];
389 HANDLE hServiceShmem
= NULL
;
391 DWORD dwNumServiceArgs
;
392 LPWSTR
*lpServiceArgVectors
;
394 TRACE("(%p)\n", servent
);
396 if( ! read_scm_lock_data( service_name
) )
399 seb
= open_seb_shmem( service_name
, &hServiceShmem
);
403 lpServiceArgVectors
= build_arg_vectors( seb
);
404 if( NULL
== lpServiceArgVectors
)
406 UnmapViewOfFile( seb
);
407 CloseHandle( hServiceShmem
);
410 lpServiceArgVectors
[0] = service_name
;
411 dwNumServiceArgs
= seb
->argc
+ 1;
413 /* FIXME: find service entry by name if SERVICE_WIN32_SHARE_PROCESS */
414 TRACE("%s at %p)\n", debugstr_w(servent
->lpServiceName
),servent
);
415 fpMain
= servent
->lpServiceProc
;
417 /* try to start the service */
418 fpMain( dwNumServiceArgs
, lpServiceArgVectors
);
420 HeapFree( GetProcessHeap(), 0, lpServiceArgVectors
);
421 UnmapViewOfFile( seb
);
422 CloseHandle( hServiceShmem
);
426 /******************************************************************************
427 * LockServiceDatabase [ADVAPI32.@]
429 LPVOID WINAPI
LockServiceDatabase (SC_HANDLE hSCManager
)
433 TRACE("%p\n",hSCManager
);
435 ret
= CreateFileMappingW( INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
,
436 0, MAX_SERVICE_NAME
* sizeof(WCHAR
), szSCMLock
);
437 if( ret
&& GetLastError() == ERROR_ALREADY_EXISTS
)
441 SetLastError( ERROR_SERVICE_DATABASE_LOCKED
);
444 TRACE("returning %p\n", ret
);
449 /******************************************************************************
450 * UnlockServiceDatabase [ADVAPI32.@]
452 BOOL WINAPI
UnlockServiceDatabase (LPVOID ScLock
)
454 TRACE("%p\n",ScLock
);
456 return CloseHandle( (HANDLE
) ScLock
);
459 /******************************************************************************
460 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
462 SERVICE_STATUS_HANDLE WINAPI
463 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName
,
464 LPHANDLER_FUNCTION lpfHandler
)
465 { FIXME("%s %p\n", lpServiceName
, lpfHandler
);
469 /******************************************************************************
470 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
476 SERVICE_STATUS_HANDLE WINAPI
477 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName
,
478 LPHANDLER_FUNCTION lpfHandler
)
479 { FIXME("%s %p\n", debugstr_w(lpServiceName
), lpfHandler
);
483 /******************************************************************************
484 * SetServiceStatus [ADVAPI32.@]
491 SetServiceStatus( SERVICE_STATUS_HANDLE hService
, LPSERVICE_STATUS lpStatus
)
492 { FIXME("0x%lx %p\n",hService
, lpStatus
);
493 TRACE("\tType:%lx\n",lpStatus
->dwServiceType
);
494 TRACE("\tState:%lx\n",lpStatus
->dwCurrentState
);
495 TRACE("\tControlAccepted:%lx\n",lpStatus
->dwControlsAccepted
);
496 TRACE("\tExitCode:%lx\n",lpStatus
->dwWin32ExitCode
);
497 TRACE("\tServiceExitCode:%lx\n",lpStatus
->dwServiceSpecificExitCode
);
498 TRACE("\tCheckPoint:%lx\n",lpStatus
->dwCheckPoint
);
499 TRACE("\tWaitHint:%lx\n",lpStatus
->dwWaitHint
);
503 /******************************************************************************
504 * OpenSCManagerA [ADVAPI32.@]
506 * Establish a connection to the service control manager and open its database.
509 * lpMachineName [I] Pointer to machine name string
510 * lpDatabaseName [I] Pointer to database name string
511 * dwDesiredAccess [I] Type of access
514 * Success: A Handle to the service control manager database
517 SC_HANDLE WINAPI
OpenSCManagerA( LPCSTR lpMachineName
, LPCSTR lpDatabaseName
,
518 DWORD dwDesiredAccess
)
520 UNICODE_STRING lpMachineNameW
;
521 UNICODE_STRING lpDatabaseNameW
;
524 RtlCreateUnicodeStringFromAsciiz (&lpMachineNameW
,lpMachineName
);
525 RtlCreateUnicodeStringFromAsciiz (&lpDatabaseNameW
,lpDatabaseName
);
526 ret
= OpenSCManagerW(lpMachineNameW
.Buffer
,lpDatabaseNameW
.Buffer
, dwDesiredAccess
);
527 RtlFreeUnicodeString(&lpDatabaseNameW
);
528 RtlFreeUnicodeString(&lpMachineNameW
);
532 /******************************************************************************
533 * OpenSCManagerW [ADVAPI32.@]
535 * See OpenSCManagerA.
537 SC_HANDLE WINAPI
OpenSCManagerW( LPCWSTR lpMachineName
, LPCWSTR lpDatabaseName
,
538 DWORD dwDesiredAccess
)
540 struct sc_handle
*retval
;
544 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName
),
545 debugstr_w(lpDatabaseName
), dwDesiredAccess
);
548 * FIXME: what is lpDatabaseName?
549 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
550 * docs, but what if it isn't?
553 retval
= alloc_sc_handle( SC_HTYPE_MANAGER
);
554 if( NULL
== retval
) return NULL
;
556 retval
->u
.manager
.ref_count
= 1;
558 r
= RegConnectRegistryW(lpMachineName
,HKEY_LOCAL_MACHINE
,&hReg
);
559 if (r
!=ERROR_SUCCESS
)
562 r
= RegOpenKeyExW(hReg
, szServiceManagerKey
,
563 0, KEY_ALL_ACCESS
, &retval
->u
.manager
.hkey_scm_db
);
565 if (r
!=ERROR_SUCCESS
)
568 TRACE("returning %p\n", retval
);
570 return (SC_HANDLE
) retval
;
573 free_sc_handle( retval
);
577 /******************************************************************************
578 * ControlService [ADVAPI32.@]
580 * Send a control code to a service.
583 * hService [I] Handle of the service control manager database
584 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
585 * lpServiceStatus [O] Destination for the status of the service, if available
591 BOOL WINAPI
ControlService( SC_HANDLE hService
, DWORD dwControl
,
592 LPSERVICE_STATUS lpServiceStatus
)
594 FIXME("(%p,%ld,%p): stub\n",hService
,dwControl
,lpServiceStatus
);
599 /******************************************************************************
600 * CloseServiceHandle [ADVAPI32.@]
602 * Close a handle to a service or the service control manager database.
605 * hSCObject [I] Handle to service or service control manager database
612 CloseServiceHandle( SC_HANDLE hSCObject
)
614 TRACE("(%p)\n", hSCObject
);
616 free_sc_handle( (struct sc_handle
*) hSCObject
);
622 /******************************************************************************
623 * OpenServiceA [ADVAPI32.@]
625 * Open a handle to a service.
628 * hSCManager [I] Handle of the service control manager database
629 * lpServiceName [I] Name of the service to open
630 * dwDesiredAccess [I] Access required to the service
633 * Success: Handle to the service
636 SC_HANDLE WINAPI
OpenServiceA( SC_HANDLE hSCManager
, LPCSTR lpServiceName
,
637 DWORD dwDesiredAccess
)
639 UNICODE_STRING lpServiceNameW
;
641 RtlCreateUnicodeStringFromAsciiz (&lpServiceNameW
,lpServiceName
);
643 TRACE("Request for service %s\n",lpServiceName
);
646 ret
= OpenServiceW( hSCManager
, lpServiceNameW
.Buffer
, dwDesiredAccess
);
647 RtlFreeUnicodeString(&lpServiceNameW
);
652 /******************************************************************************
653 * OpenServiceW [ADVAPI32.@]
657 SC_HANDLE WINAPI
OpenServiceW( SC_HANDLE hSCManager
, LPCWSTR lpServiceName
,
658 DWORD dwDesiredAccess
)
660 struct sc_handle
*hscm
= hSCManager
;
661 struct sc_handle
*retval
;
665 TRACE("(%p,%p,%ld)\n",hSCManager
, lpServiceName
,
668 retval
= alloc_sc_handle( SC_HTYPE_SERVICE
);
672 r
= RegOpenKeyExW( hscm
->u
.manager
.hkey_scm_db
,
673 lpServiceName
, 0, KEY_ALL_ACCESS
, &hKey
);
674 if (r
!=ERROR_SUCCESS
)
676 free_sc_handle( retval
);
677 SetLastError( ERROR_SERVICE_DOES_NOT_EXIST
);
681 init_service_handle( retval
, hscm
, hKey
, lpServiceName
);
683 TRACE("returning %p\n",retval
);
685 return (SC_HANDLE
) retval
;
688 /******************************************************************************
689 * CreateServiceW [ADVAPI32.@]
692 CreateServiceW( SC_HANDLE hSCManager
, LPCWSTR lpServiceName
,
693 LPCWSTR lpDisplayName
, DWORD dwDesiredAccess
,
694 DWORD dwServiceType
, DWORD dwStartType
,
695 DWORD dwErrorControl
, LPCWSTR lpBinaryPathName
,
696 LPCWSTR lpLoadOrderGroup
, LPDWORD lpdwTagId
,
697 LPCWSTR lpDependencies
, LPCWSTR lpServiceStartName
,
700 struct sc_handle
*hscm
= hSCManager
;
701 struct sc_handle
*retval
;
705 static const WCHAR szDisplayName
[] = { 'D','i','s','p','l','a','y','N','a','m','e', 0 };
706 static const WCHAR szType
[] = {'T','y','p','e',0};
707 static const WCHAR szStart
[] = {'S','t','a','r','t',0};
708 static const WCHAR szError
[] = {'E','r','r','o','r','C','o','n','t','r','o','l', 0};
709 static const WCHAR szImagePath
[] = {'I','m','a','g','e','P','a','t','h',0};
710 static const WCHAR szGroup
[] = {'G','r','o','u','p',0};
711 static const WCHAR szDependencies
[] = { 'D','e','p','e','n','d','e','n','c','i','e','s',0};
713 FIXME("%p %s %s\n", hSCManager
,
714 debugstr_w(lpServiceName
), debugstr_w(lpDisplayName
));
716 retval
= alloc_sc_handle( SC_HTYPE_SERVICE
);
720 r
= RegCreateKeyExW(hscm
->u
.manager
.hkey_scm_db
, lpServiceName
, 0, NULL
,
721 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, &dp
);
722 if (r
!=ERROR_SUCCESS
)
725 init_service_handle( retval
, hscm
, hKey
, lpServiceName
);
727 if (dp
!= REG_CREATED_NEW_KEY
)
732 r
= RegSetValueExW(hKey
, szDisplayName
, 0, REG_SZ
, (LPBYTE
)lpDisplayName
,
733 (strlenW(lpDisplayName
)+1)*sizeof(WCHAR
) );
734 if (r
!=ERROR_SUCCESS
)
738 r
= RegSetValueExW(hKey
, szType
, 0, REG_DWORD
, (LPVOID
)&dwServiceType
, sizeof (DWORD
) );
739 if (r
!=ERROR_SUCCESS
)
742 r
= RegSetValueExW(hKey
, szStart
, 0, REG_DWORD
, (LPVOID
)&dwStartType
, sizeof (DWORD
) );
743 if (r
!=ERROR_SUCCESS
)
746 r
= RegSetValueExW(hKey
, szError
, 0, REG_DWORD
,
747 (LPVOID
)&dwErrorControl
, sizeof (DWORD
) );
748 if (r
!=ERROR_SUCCESS
)
753 r
= RegSetValueExW(hKey
, szImagePath
, 0, REG_SZ
, (LPBYTE
)lpBinaryPathName
,
754 (strlenW(lpBinaryPathName
)+1)*sizeof(WCHAR
) );
755 if (r
!=ERROR_SUCCESS
)
761 r
= RegSetValueExW(hKey
, szGroup
, 0, REG_SZ
, (LPBYTE
)lpLoadOrderGroup
,
762 (strlenW(lpLoadOrderGroup
)+1)*sizeof(WCHAR
) );
763 if (r
!=ERROR_SUCCESS
)
771 /* determine the length of a double null terminated multi string */
773 len
+= (strlenW(&lpDependencies
[len
])+1);
774 } while (lpDependencies
[len
++]);
776 r
= RegSetValueExW(hKey
, szDependencies
, 0, REG_MULTI_SZ
,
777 (LPBYTE
)lpDependencies
, len
);
778 if (r
!=ERROR_SUCCESS
)
784 FIXME("Don't know how to add a Password for a service.\n");
787 if(lpServiceStartName
)
789 FIXME("Don't know how to add a ServiceStartName for a service.\n");
792 return (SC_HANDLE
) retval
;
795 free_sc_handle( retval
);
800 /******************************************************************************
801 * CreateServiceA [ADVAPI32.@]
804 CreateServiceA( SC_HANDLE hSCManager
, LPCSTR lpServiceName
,
805 LPCSTR lpDisplayName
, DWORD dwDesiredAccess
,
806 DWORD dwServiceType
, DWORD dwStartType
,
807 DWORD dwErrorControl
, LPCSTR lpBinaryPathName
,
808 LPCSTR lpLoadOrderGroup
, LPDWORD lpdwTagId
,
809 LPCSTR lpDependencies
, LPCSTR lpServiceStartName
,
812 LPWSTR lpServiceNameW
, lpDisplayNameW
, lpBinaryPathNameW
,
813 lpLoadOrderGroupW
, lpDependenciesW
, lpServiceStartNameW
, lpPasswordW
;
816 TRACE("%p %s %s\n", hSCManager
,
817 debugstr_a(lpServiceName
), debugstr_a(lpDisplayName
));
819 lpServiceNameW
= SERV_dup( lpServiceName
);
820 lpDisplayNameW
= SERV_dup( lpDisplayName
);
821 lpBinaryPathNameW
= SERV_dup( lpBinaryPathName
);
822 lpLoadOrderGroupW
= SERV_dup( lpLoadOrderGroup
);
823 lpDependenciesW
= SERV_dupmulti( lpDependencies
);
824 lpServiceStartNameW
= SERV_dup( lpServiceStartName
);
825 lpPasswordW
= SERV_dup( lpPassword
);
827 r
= CreateServiceW( hSCManager
, lpServiceNameW
, lpDisplayNameW
,
828 dwDesiredAccess
, dwServiceType
, dwStartType
, dwErrorControl
,
829 lpBinaryPathNameW
, lpLoadOrderGroupW
, lpdwTagId
,
830 lpDependenciesW
, lpServiceStartNameW
, lpPasswordW
);
832 SERV_free( lpServiceNameW
);
833 SERV_free( lpDisplayNameW
);
834 SERV_free( lpBinaryPathNameW
);
835 SERV_free( lpLoadOrderGroupW
);
836 SERV_free( lpDependenciesW
);
837 SERV_free( lpServiceStartNameW
);
838 SERV_free( lpPasswordW
);
844 /******************************************************************************
845 * DeleteService [ADVAPI32.@]
847 * Delete a service from the service control manager database.
850 * hService [I] Handle of the service to delete
856 BOOL WINAPI
DeleteService( SC_HANDLE hService
)
858 struct sc_handle
*hsvc
= hService
;
859 HKEY hKey
= hsvc
->u
.service
.hkey
;
860 WCHAR valname
[MAX_PATH
+1];
866 /* Clean out the values */
867 rc
= RegEnumValueW(hKey
, index
, valname
,&size
,0,0,0,0);
868 while (rc
== ERROR_SUCCESS
)
870 RegDeleteValueW(hKey
,valname
);
873 rc
= RegEnumValueW(hKey
, index
, valname
, &size
,0,0,0,0);
877 hsvc
->u
.service
.hkey
= NULL
;
880 RegDeleteKeyW(hsvc
->u
.service
.sc_manager
->u
.manager
.hkey_scm_db
,
881 hsvc
->u
.service
.name
);
887 /******************************************************************************
888 * StartServiceA [ADVAPI32.@]
893 * hService [I] Handle of service
894 * dwNumServiceArgs [I] Number of arguments
895 * lpServiceArgVectors [I] Address of array of argument strings
898 * - NT implements this function using an obscure RPC call.
899 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
900 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
901 * - This will only work for shared address space. How should the service
902 * args be transferred when address spaces are separated?
903 * - Can only start one service at a time.
904 * - Has no concept of privilege.
911 StartServiceA( SC_HANDLE hService
, DWORD dwNumServiceArgs
,
912 LPCSTR
*lpServiceArgVectors
)
915 UNICODE_STRING usBuffer
;
918 TRACE("(%p,%ld,%p)\n",hService
,dwNumServiceArgs
,lpServiceArgVectors
);
921 lpwstr
= (LPWSTR
*) HeapAlloc( GetProcessHeap(), 0,
922 dwNumServiceArgs
*sizeof(LPWSTR
) );
926 for(i
=0; i
<dwNumServiceArgs
; i
++)
928 RtlCreateUnicodeStringFromAsciiz (&usBuffer
,lpServiceArgVectors
[i
]);
929 lpwstr
[i
]=usBuffer
.Buffer
;
932 StartServiceW(hService
, dwNumServiceArgs
, (LPCWSTR
*)lpwstr
);
936 for(i
=0; i
<dwNumServiceArgs
; i
++)
937 HeapFree(GetProcessHeap(), 0, lpwstr
[i
]);
938 HeapFree(GetProcessHeap(), 0, lpwstr
);
945 /******************************************************************************
946 * StartServiceW [ADVAPI32.@]
951 StartServiceW( SC_HANDLE hService
, DWORD dwNumServiceArgs
,
952 LPCWSTR
*lpServiceArgVectors
)
954 static const WCHAR _WaitServiceStartW
[] = {'A','D','V','A','P','I','_','W',
955 'a','i','t','S','e','r','v','i',
956 'c','e','S','t','a','r','t',0};
957 static const WCHAR _ImagePathW
[] = {'I','m','a','g','e','P','a','t','h',0};
959 struct sc_handle
*hsvc
= hService
;
960 WCHAR path
[MAX_PATH
],str
[MAX_PATH
];
965 HANDLE hServiceShmem
= NULL
;
967 LPWSTR shmem_lock
= NULL
;
968 struct SEB
*seb
= NULL
;
970 PROCESS_INFORMATION procinfo
;
971 STARTUPINFOW startupinfo
;
974 TRACE("(%p,%ld,%p)\n",hService
,dwNumServiceArgs
,
975 lpServiceArgVectors
);
978 r
= RegQueryValueExW(hsvc
->u
.service
.hkey
, _ImagePathW
, NULL
, &type
, (LPVOID
)str
, &size
);
979 if (r
!=ERROR_SUCCESS
)
981 ExpandEnvironmentStringsW(str
,path
,sizeof(path
));
983 TRACE("Starting service %s\n", debugstr_w(path
) );
985 hLock
= LockServiceDatabase( hsvc
->u
.service
.sc_manager
);
990 * FIXME: start dependent services
993 /* pass argv[0] (service name) to the service via global SCM lock object */
994 shmem_lock
= MapViewOfFile( hLock
, FILE_MAP_ALL_ACCESS
,
995 0, 0, MAX_SERVICE_NAME
* sizeof(WCHAR
) );
996 if( NULL
== shmem_lock
)
998 ERR("Couldn't map shared memory\n");
1001 strcpyW( shmem_lock
, hsvc
->u
.service
.name
);
1003 /* create service environment block */
1004 size
= sizeof(struct SEB
);
1005 for( i
= 0; i
< dwNumServiceArgs
; i
++ )
1006 size
+= sizeof(WCHAR
) * (1 + strlenW( lpServiceArgVectors
[ i
] ));
1008 snprintfW( str
, MAX_PATH
, szServiceShmemNameFmtW
, hsvc
->u
.service
.name
);
1009 hServiceShmem
= CreateFileMappingW( INVALID_HANDLE_VALUE
,
1010 NULL
, PAGE_READWRITE
, 0, size
, str
);
1011 if( NULL
== hServiceShmem
)
1013 ERR("Couldn't create shared memory object\n");
1016 if( GetLastError() == ERROR_ALREADY_EXISTS
)
1018 SetLastError( ERROR_SERVICE_ALREADY_RUNNING
);
1021 seb
= MapViewOfFile( hServiceShmem
, FILE_MAP_ALL_ACCESS
, 0, 0, 0 );
1024 ERR("Couldn't map shared memory\n");
1028 /* copy service args to SEB */
1029 seb
->argc
= dwNumServiceArgs
;
1030 argptr
= (LPWSTR
) &seb
[1];
1031 for( i
= 0; i
< dwNumServiceArgs
; i
++ )
1033 strcpyW( argptr
, lpServiceArgVectors
[ i
] );
1034 argptr
+= 1 + strlenW( argptr
);
1037 wait
= CreateSemaphoreW(NULL
,0,1,_WaitServiceStartW
);
1040 ERR("Couldn't create wait semaphore\n");
1044 ZeroMemory(&startupinfo
,sizeof(STARTUPINFOW
));
1045 startupinfo
.cb
= sizeof(STARTUPINFOW
);
1047 r
= CreateProcessW(NULL
,
1049 NULL
, /* process security attribs */
1050 NULL
, /* thread security attribs */
1051 FALSE
, /* inherit handles */
1052 0, /* creation flags */
1053 NULL
, /* environment */
1054 NULL
, /* current directory */
1055 &startupinfo
, /* startup info */
1056 &procinfo
); /* process info */
1060 ERR("Couldn't start process\n");
1063 CloseHandle( procinfo
.hThread
);
1065 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
1066 r
= WaitForSingleObject(wait
,30000);
1067 if( WAIT_FAILED
== r
)
1069 CloseHandle( procinfo
.hProcess
);
1074 CloseHandle( procinfo
.hProcess
);
1078 if( wait
) CloseHandle( wait
);
1079 if( seb
!= NULL
) UnmapViewOfFile( seb
);
1080 if( hServiceShmem
!= NULL
) CloseHandle( hServiceShmem
);
1081 if( shmem_lock
!= NULL
) UnmapViewOfFile( shmem_lock
);
1082 UnlockServiceDatabase( hLock
);
1086 /******************************************************************************
1087 * QueryServiceStatus [ADVAPI32.@]
1091 * lpservicestatus []
1095 QueryServiceStatus( SC_HANDLE hService
, LPSERVICE_STATUS lpservicestatus
)
1097 struct sc_handle
*hsvc
= hService
;
1099 DWORD type
, val
, size
;
1100 WCHAR str
[MAX_PATH
];
1101 HANDLE hServiceShmem
= NULL
;
1103 FIXME("(%p,%p) partial\n",hService
,lpservicestatus
);
1105 /* read the service type from the registry */
1107 r
= RegQueryValueExA(hsvc
->u
.service
.hkey
, "Type", NULL
, &type
, (LPBYTE
)&val
, &size
);
1110 ERR("invalid Type\n");
1113 lpservicestatus
->dwServiceType
= val
;
1114 /* FIXME: how are these determined or read from the registry? */
1115 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */
1117 /* Determine if currently running via named shared memory */
1118 snprintfW( str
, MAX_PATH
, szServiceShmemNameFmtW
, hsvc
->u
.service
.name
);
1119 hServiceShmem
= CreateFileMappingW( INVALID_HANDLE_VALUE
,
1120 NULL
, PAGE_READWRITE
, 0, size
, str
);
1121 if( NULL
== hServiceShmem
)
1123 lpservicestatus
->dwCurrentState
= 1;
1125 if( GetLastError() == ERROR_ALREADY_EXISTS
)
1127 lpservicestatus
->dwCurrentState
= 3;
1129 lpservicestatus
->dwCurrentState
= 1;
1131 CloseHandle( hServiceShmem
);
1134 lpservicestatus
->dwControlsAccepted
= 0;
1135 lpservicestatus
->dwWin32ExitCode
= NO_ERROR
;
1136 lpservicestatus
->dwServiceSpecificExitCode
= 0;
1137 lpservicestatus
->dwCheckPoint
= 0;
1138 lpservicestatus
->dwWaitHint
= 0;
1143 /******************************************************************************
1144 * QueryServiceStatusEx [ADVAPI32.@]
1146 * Get information about a service.
1149 * hService [I] Handle to service to get information about
1150 * InfoLevel [I] Level of information to get
1151 * lpBuffer [O] Destination for requested information
1152 * cbBufSize [I] Size of lpBuffer in bytes
1153 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1159 BOOL WINAPI
QueryServiceStatusEx(SC_HANDLE hService
, SC_STATUS_TYPE InfoLevel
,
1160 LPBYTE lpBuffer
, DWORD cbBufSize
,
1161 LPDWORD pcbBytesNeeded
)
1164 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1168 /******************************************************************************
1169 * QueryServiceConfigA [ADVAPI32.@]
1172 QueryServiceConfigA( SC_HANDLE hService
,
1173 LPQUERY_SERVICE_CONFIGA lpServiceConfig
,
1174 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
)
1176 static const CHAR szDisplayName
[] = "DisplayName";
1177 static const CHAR szType
[] = "Type";
1178 static const CHAR szStart
[] = "Start";
1179 static const CHAR szError
[] = "ErrorControl";
1180 static const CHAR szImagePath
[] = "ImagePath";
1181 static const CHAR szGroup
[] = "Group";
1182 static const CHAR szDependencies
[] = "Dependencies";
1183 HKEY hKey
= ((struct sc_handle
*) hService
)->u
.service
.hkey
;
1184 CHAR str_buffer
[ MAX_PATH
];
1186 DWORD type
, val
, sz
, total
, n
;
1189 TRACE("%p %p %ld %p\n", hService
, lpServiceConfig
,
1190 cbBufSize
, pcbBytesNeeded
);
1192 /* calculate the size required first */
1193 total
= sizeof (QUERY_SERVICE_CONFIGA
);
1195 sz
= sizeof(str_buffer
);
1196 r
= RegQueryValueExA( hKey
, szImagePath
, 0, &type
, str_buffer
, &sz
);
1197 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_SZ
|| type
== REG_EXPAND_SZ
) )
1199 sz
= ExpandEnvironmentStringsA(str_buffer
,NULL
,0);
1200 if( 0 == sz
) return FALSE
;
1206 /* FIXME: set last error */
1211 r
= RegQueryValueExA( hKey
, szGroup
, 0, &type
, NULL
, &sz
);
1212 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_SZ
) )
1216 r
= RegQueryValueExA( hKey
, szDependencies
, 0, &type
, NULL
, &sz
);
1217 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_MULTI_SZ
) )
1221 r
= RegQueryValueExA( hKey
, szStart
, 0, &type
, NULL
, &sz
);
1222 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_SZ
) )
1226 r
= RegQueryValueExA( hKey
, szDisplayName
, 0, &type
, NULL
, &sz
);
1227 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_SZ
) )
1230 /* if there's not enough memory, return an error */
1231 if( total
> *pcbBytesNeeded
)
1233 *pcbBytesNeeded
= total
;
1234 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1238 *pcbBytesNeeded
= total
;
1239 ZeroMemory( lpServiceConfig
, total
);
1242 r
= RegQueryValueExA( hKey
, szType
, 0, &type
, (LPBYTE
)&val
, &sz
);
1243 if( ( r
== ERROR_SUCCESS
) || ( type
== REG_DWORD
) )
1244 lpServiceConfig
->dwServiceType
= val
;
1247 r
= RegQueryValueExA( hKey
, szStart
, 0, &type
, (LPBYTE
)&val
, &sz
);
1248 if( ( r
== ERROR_SUCCESS
) || ( type
== REG_DWORD
) )
1249 lpServiceConfig
->dwStartType
= val
;
1252 r
= RegQueryValueExA( hKey
, szError
, 0, &type
, (LPBYTE
)&val
, &sz
);
1253 if( ( r
== ERROR_SUCCESS
) || ( type
== REG_DWORD
) )
1254 lpServiceConfig
->dwErrorControl
= val
;
1256 /* now do the strings */
1257 p
= (LPBYTE
) &lpServiceConfig
[1];
1258 n
= total
- sizeof (QUERY_SERVICE_CONFIGA
);
1260 sz
= sizeof(str_buffer
);
1261 r
= RegQueryValueExA( hKey
, szImagePath
, 0, &type
, str_buffer
, &sz
);
1262 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_SZ
|| type
== REG_EXPAND_SZ
) )
1264 sz
= ExpandEnvironmentStringsA(str_buffer
, p
, n
);
1265 if( 0 == sz
|| sz
> n
) return FALSE
;
1267 lpServiceConfig
->lpBinaryPathName
= (LPSTR
) p
;
1273 /* FIXME: set last error */
1278 r
= RegQueryValueExA( hKey
, szGroup
, 0, &type
, p
, &sz
);
1279 if( ( r
== ERROR_SUCCESS
) || ( type
== REG_SZ
) )
1281 lpServiceConfig
->lpLoadOrderGroup
= (LPSTR
) p
;
1287 r
= RegQueryValueExA( hKey
, szDependencies
, 0, &type
, p
, &sz
);
1288 if( ( r
== ERROR_SUCCESS
) || ( type
== REG_SZ
) )
1290 lpServiceConfig
->lpDependencies
= (LPSTR
) p
;
1296 ERR("Buffer overflow!\n");
1298 TRACE("Image path = %s\n", lpServiceConfig
->lpBinaryPathName
);
1299 TRACE("Group = %s\n", lpServiceConfig
->lpLoadOrderGroup
);
1304 /******************************************************************************
1305 * QueryServiceConfigW [ADVAPI32.@]
1308 QueryServiceConfigW( SC_HANDLE hService
,
1309 LPQUERY_SERVICE_CONFIGW lpServiceConfig
,
1310 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
)
1312 static const WCHAR szDisplayName
[] = {
1313 'D','i','s','p','l','a','y','N','a','m','e', 0 };
1314 static const WCHAR szType
[] = {'T','y','p','e',0};
1315 static const WCHAR szStart
[] = {'S','t','a','r','t',0};
1316 static const WCHAR szError
[] = {
1317 'E','r','r','o','r','C','o','n','t','r','o','l', 0};
1318 static const WCHAR szImagePath
[] = {'I','m','a','g','e','P','a','t','h',0};
1319 static const WCHAR szGroup
[] = {'G','r','o','u','p',0};
1320 static const WCHAR szDependencies
[] = {
1321 'D','e','p','e','n','d','e','n','c','i','e','s',0};
1322 HKEY hKey
= ((struct sc_handle
*) hService
)->u
.service
.hkey
;
1323 WCHAR str_buffer
[ MAX_PATH
];
1325 DWORD type
, val
, sz
, total
, n
;
1328 TRACE("%p %p %ld %p\n", hService
, lpServiceConfig
,
1329 cbBufSize
, pcbBytesNeeded
);
1331 /* calculate the size required first */
1332 total
= sizeof (QUERY_SERVICE_CONFIGW
);
1334 sz
= sizeof(str_buffer
);
1335 r
= RegQueryValueExW( hKey
, szImagePath
, 0, &type
, (LPBYTE
) str_buffer
, &sz
);
1336 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_SZ
|| type
== REG_EXPAND_SZ
) )
1338 sz
= ExpandEnvironmentStringsW(str_buffer
,NULL
,0);
1339 if( 0 == sz
) return FALSE
;
1341 total
+= sizeof(WCHAR
) * sz
;
1345 /* FIXME: set last error */
1350 r
= RegQueryValueExW( hKey
, szGroup
, 0, &type
, NULL
, &sz
);
1351 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_SZ
) )
1355 r
= RegQueryValueExW( hKey
, szDependencies
, 0, &type
, NULL
, &sz
);
1356 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_MULTI_SZ
) )
1360 r
= RegQueryValueExW( hKey
, szStart
, 0, &type
, NULL
, &sz
);
1361 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_SZ
) )
1365 r
= RegQueryValueExW( hKey
, szDisplayName
, 0, &type
, NULL
, &sz
);
1366 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_SZ
) )
1369 /* if there's not enough memory, return an error */
1370 if( total
> *pcbBytesNeeded
)
1372 *pcbBytesNeeded
= total
;
1373 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1377 *pcbBytesNeeded
= total
;
1378 ZeroMemory( lpServiceConfig
, total
);
1381 r
= RegQueryValueExW( hKey
, szType
, 0, &type
, (LPBYTE
)&val
, &sz
);
1382 if( ( r
== ERROR_SUCCESS
) || ( type
== REG_DWORD
) )
1383 lpServiceConfig
->dwServiceType
= val
;
1386 r
= RegQueryValueExW( hKey
, szStart
, 0, &type
, (LPBYTE
)&val
, &sz
);
1387 if( ( r
== ERROR_SUCCESS
) || ( type
== REG_DWORD
) )
1388 lpServiceConfig
->dwStartType
= val
;
1391 r
= RegQueryValueExW( hKey
, szError
, 0, &type
, (LPBYTE
)&val
, &sz
);
1392 if( ( r
== ERROR_SUCCESS
) || ( type
== REG_DWORD
) )
1393 lpServiceConfig
->dwErrorControl
= val
;
1395 /* now do the strings */
1396 p
= (LPBYTE
) &lpServiceConfig
[1];
1397 n
= total
- sizeof (QUERY_SERVICE_CONFIGW
);
1399 sz
= sizeof(str_buffer
);
1400 r
= RegQueryValueExW( hKey
, szImagePath
, 0, &type
, (LPBYTE
) str_buffer
, &sz
);
1401 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_SZ
|| type
== REG_EXPAND_SZ
) )
1403 sz
= ExpandEnvironmentStringsW(str_buffer
, (LPWSTR
) p
, n
);
1404 sz
*= sizeof(WCHAR
);
1405 if( 0 == sz
|| sz
> n
) return FALSE
;
1407 lpServiceConfig
->lpBinaryPathName
= (LPWSTR
) p
;
1413 /* FIXME: set last error */
1418 r
= RegQueryValueExW( hKey
, szGroup
, 0, &type
, p
, &sz
);
1419 if( ( r
== ERROR_SUCCESS
) || ( type
== REG_SZ
) )
1421 lpServiceConfig
->lpLoadOrderGroup
= (LPWSTR
) p
;
1427 r
= RegQueryValueExW( hKey
, szDependencies
, 0, &type
, p
, &sz
);
1428 if( ( r
== ERROR_SUCCESS
) || ( type
== REG_SZ
) )
1430 lpServiceConfig
->lpDependencies
= (LPWSTR
) p
;
1436 ERR("Buffer overflow!\n");
1438 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig
->lpBinaryPathName
) );
1439 TRACE("Group = %s\n", debugstr_w(lpServiceConfig
->lpLoadOrderGroup
) );
1444 /******************************************************************************
1445 * ChangeServiceConfigW [ADVAPI32.@]
1447 BOOL WINAPI
ChangeServiceConfigW( SC_HANDLE hService
, DWORD dwServiceType
,
1448 DWORD dwStartType
, DWORD dwErrorControl
, LPCWSTR lpBinaryPathName
,
1449 LPCWSTR lpLoadOrderGroup
, LPDWORD lpdwTagId
, LPCWSTR lpDependencies
,
1450 LPCWSTR lpServiceStartName
, LPCWSTR lpPassword
, LPCWSTR lpDisplayName
)
1452 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1453 hService
, dwServiceType
, dwStartType
, dwErrorControl
,
1454 debugstr_w(lpBinaryPathName
), debugstr_w(lpLoadOrderGroup
),
1455 lpdwTagId
, lpDependencies
, debugstr_w(lpServiceStartName
),
1456 debugstr_w(lpPassword
), debugstr_w(lpDisplayName
) );
1460 /******************************************************************************
1461 * ChangeServiceConfigA [ADVAPI32.@]
1463 BOOL WINAPI
ChangeServiceConfigA( SC_HANDLE hService
, DWORD dwServiceType
,
1464 DWORD dwStartType
, DWORD dwErrorControl
, LPCSTR lpBinaryPathName
,
1465 LPCSTR lpLoadOrderGroup
, LPDWORD lpdwTagId
, LPCSTR lpDependencies
,
1466 LPCSTR lpServiceStartName
, LPCSTR lpPassword
, LPCSTR lpDisplayName
)
1468 LPWSTR wBinaryPathName
, wLoadOrderGroup
, wDependencies
;
1469 LPWSTR wServiceStartName
, wPassword
, wDisplayName
;
1472 TRACE("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1473 hService
, dwServiceType
, dwStartType
, dwErrorControl
,
1474 debugstr_a(lpBinaryPathName
), debugstr_a(lpLoadOrderGroup
),
1475 lpdwTagId
, lpDependencies
, debugstr_a(lpServiceStartName
),
1476 debugstr_a(lpPassword
), debugstr_a(lpDisplayName
) );
1478 wBinaryPathName
= SERV_dup( lpBinaryPathName
);
1479 wLoadOrderGroup
= SERV_dup( lpLoadOrderGroup
);
1480 wDependencies
= SERV_dupmulti( lpDependencies
);
1481 wServiceStartName
= SERV_dup( lpServiceStartName
);
1482 wPassword
= SERV_dup( lpPassword
);
1483 wDisplayName
= SERV_dup( lpDisplayName
);
1485 r
= ChangeServiceConfigW( hService
, dwServiceType
,
1486 dwStartType
, dwErrorControl
, wBinaryPathName
,
1487 wLoadOrderGroup
, lpdwTagId
, wDependencies
,
1488 wServiceStartName
, wPassword
, wDisplayName
);
1490 SERV_free( wBinaryPathName
);
1491 SERV_free( wLoadOrderGroup
);
1492 SERV_free( wDependencies
);
1493 SERV_free( wServiceStartName
);
1494 SERV_free( wPassword
);
1495 SERV_free( wDisplayName
);
1500 /******************************************************************************
1501 * ChangeServiceConfig2A [ADVAPI32.@]
1503 BOOL WINAPI
ChangeServiceConfig2A( SC_HANDLE hService
, DWORD dwInfoLevel
,
1508 TRACE("%p %ld %p\n",hService
, dwInfoLevel
, lpInfo
);
1510 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
1512 LPSERVICE_DESCRIPTIONA sd
= (LPSERVICE_DESCRIPTIONA
) lpInfo
;
1513 SERVICE_DESCRIPTIONW sdw
;
1515 sdw
.lpDescription
= SERV_dup( sd
->lpDescription
);
1517 r
= ChangeServiceConfig2W( hService
, dwInfoLevel
, &sdw
);
1519 SERV_free( sdw
.lpDescription
);
1521 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
1523 LPSERVICE_FAILURE_ACTIONSA fa
= (LPSERVICE_FAILURE_ACTIONSA
) lpInfo
;
1524 SERVICE_FAILURE_ACTIONSW faw
;
1526 faw
.dwResetPeriod
= fa
->dwResetPeriod
;
1527 faw
.lpRebootMsg
= SERV_dup( fa
->lpRebootMsg
);
1528 faw
.lpCommand
= SERV_dup( fa
->lpCommand
);
1529 faw
.cActions
= fa
->cActions
;
1530 faw
.lpsaActions
= fa
->lpsaActions
;
1532 r
= ChangeServiceConfig2W( hService
, dwInfoLevel
, &faw
);
1534 SERV_free( faw
.lpRebootMsg
);
1535 SERV_free( faw
.lpCommand
);
1538 SetLastError( ERROR_INVALID_PARAMETER
);
1543 /******************************************************************************
1544 * ChangeServiceConfig2W [ADVAPI32.@]
1546 BOOL WINAPI
ChangeServiceConfig2W( SC_HANDLE hService
, DWORD dwInfoLevel
,
1549 HKEY hKey
= ((struct sc_handle
*) hService
)->u
.service
.hkey
;
1551 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
1553 static const WCHAR szDescription
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1554 LPSERVICE_DESCRIPTIONW sd
= (LPSERVICE_DESCRIPTIONW
)lpInfo
;
1555 if (sd
->lpDescription
)
1557 TRACE("Setting Description to %s\n",debugstr_w(sd
->lpDescription
));
1558 if (sd
->lpDescription
[0] == 0)
1559 RegDeleteValueW(hKey
,szDescription
);
1561 RegSetValueExW(hKey
, szDescription
, 0, REG_SZ
,
1562 (LPVOID
)sd
->lpDescription
,
1563 sizeof(WCHAR
)*(strlenW(sd
->lpDescription
)+1));
1567 FIXME("STUB: %p %ld %p\n",hService
, dwInfoLevel
, lpInfo
);
1571 /******************************************************************************
1572 * QueryServiceObjectSecurity [ADVAPI32.@]
1574 BOOL WINAPI
QueryServiceObjectSecurity(SC_HANDLE hService
,
1575 SECURITY_INFORMATION dwSecurityInformation
,
1576 PSECURITY_DESCRIPTOR lpSecurityDescriptor
,
1577 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
)
1580 FIXME("%p %ld %p %lu %p\n", hService
, dwSecurityInformation
,
1581 lpSecurityDescriptor
, cbBufSize
, pcbBytesNeeded
);
1584 InitializeSecurityDescriptor(lpSecurityDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
1586 pACL
= HeapAlloc( GetProcessHeap(), 0, sizeof(ACL
) );
1587 InitializeAcl(pACL
, sizeof(ACL
), ACL_REVISION
);
1588 SetSecurityDescriptorDacl(lpSecurityDescriptor
, TRUE
, pACL
, TRUE
);
1592 /******************************************************************************
1593 * SetServiceObjectSecurity [ADVAPI32.@]
1595 BOOL WINAPI
SetServiceObjectSecurity(SC_HANDLE hService
,
1596 SECURITY_INFORMATION dwSecurityInformation
,
1597 PSECURITY_DESCRIPTOR lpSecurityDescriptor
)
1599 FIXME("%p %ld %p\n", hService
, dwSecurityInformation
, lpSecurityDescriptor
);