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
27 #include "wine/debug.h"
29 #include "advapi32_misc.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(service
);
33 /******************************************************************************
34 * LockServiceDatabase [ADVAPI32.@]
36 SC_LOCK WINAPI
LockServiceDatabase( SC_HANDLE manager
)
38 /* this function is a no-op in Vista and above */
39 TRACE("%p\n", manager
);
40 return (SC_LOCK
)0xdeadbeef;
43 /******************************************************************************
44 * UnlockServiceDatabase [ADVAPI32.@]
46 BOOL WINAPI
UnlockServiceDatabase( SC_LOCK lock
)
48 /* this function is a no-op in Vista and above */
53 /******************************************************************************
54 * EnumServicesStatusA [ADVAPI32.@]
57 EnumServicesStatusA( SC_HANDLE hmngr
, DWORD type
, DWORD state
, LPENUM_SERVICE_STATUSA
58 services
, DWORD size
, LPDWORD needed
, LPDWORD returned
,
59 LPDWORD resume_handle
)
63 ENUM_SERVICE_STATUSW
*servicesW
= NULL
;
67 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr
, type
, state
, services
, size
, needed
,
68 returned
, resume_handle
);
72 SetLastError( ERROR_INVALID_HANDLE
);
75 if (!needed
|| !returned
)
77 SetLastError( ERROR_INVALID_ADDRESS
);
81 sz
= max( 2 * size
, sizeof(*servicesW
) );
82 if (!(servicesW
= heap_alloc( sz
)))
84 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
88 ret
= EnumServicesStatusW( hmngr
, type
, state
, servicesW
, sz
, needed
, returned
, resume_handle
);
91 p
= (char *)services
+ *returned
* sizeof(ENUM_SERVICE_STATUSA
);
92 n
= size
- (p
- (char *)services
);
94 for (i
= 0; i
< *returned
; i
++)
96 sz
= WideCharToMultiByte( CP_ACP
, 0, servicesW
[i
].lpServiceName
, -1, p
, n
, NULL
, NULL
);
98 services
[i
].lpServiceName
= p
;
101 if (servicesW
[i
].lpDisplayName
)
103 sz
= WideCharToMultiByte( CP_ACP
, 0, servicesW
[i
].lpDisplayName
, -1, p
, n
, NULL
, NULL
);
105 services
[i
].lpDisplayName
= p
;
109 else services
[i
].lpDisplayName
= NULL
;
110 services
[i
].ServiceStatus
= servicesW
[i
].ServiceStatus
;
116 heap_free( servicesW
);
120 /******************************************************************************
121 * EnumServicesStatusW [ADVAPI32.@]
124 EnumServicesStatusW( SC_HANDLE manager
, DWORD type
, DWORD state
, ENUM_SERVICE_STATUSW
*status
,
125 DWORD size
, DWORD
*ret_size
, DWORD
*ret_count
, DWORD
*resume_handle
)
127 ENUM_SERVICE_STATUS_PROCESSW
*status_ex
;
128 DWORD alloc_size
, count
, i
;
131 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", manager
, type
, state
, status
, size
,
132 ret_size
, ret_count
, resume_handle
);
136 SetLastError( ERROR_INVALID_HANDLE
);
140 if (!ret_size
|| !ret_count
)
142 SetLastError( ERROR_INVALID_PARAMETER
);
148 if (!EnumServicesStatusExW( manager
, SC_ENUM_PROCESS_INFO
, type
, state
,
149 NULL
, 0, &alloc_size
, &count
, resume_handle
, NULL
)
150 && GetLastError() != ERROR_MORE_DATA
)
153 if (!(status_ex
= heap_alloc( alloc_size
)))
155 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
159 if (!EnumServicesStatusExW( manager
, SC_ENUM_PROCESS_INFO
, type
, state
, (BYTE
*)status_ex
,
160 alloc_size
, &alloc_size
, &count
, resume_handle
, NULL
)
161 && GetLastError() != ERROR_MORE_DATA
)
163 heap_free( status_ex
);
167 for (i
= 0; i
< count
; i
++)
169 *ret_size
+= sizeof(ENUM_SERVICE_STATUSW
);
170 *ret_size
+= (lstrlenW( status_ex
[i
].lpServiceName
) + 1) * sizeof(WCHAR
);
171 if (status_ex
[i
].lpDisplayName
)
172 *ret_size
+= (lstrlenW( status_ex
[i
].lpDisplayName
) + 1) * sizeof(WCHAR
);
174 if (*ret_size
<= size
)
178 p
= (WCHAR
*)(status
+ *ret_count
);
179 for (i
= 0; i
< *ret_count
; i
++)
181 lstrcpyW( p
, status_ex
[i
].lpServiceName
);
182 status
[i
].lpServiceName
= p
;
183 p
+= lstrlenW( p
) + 1;
184 if (status_ex
[i
].lpDisplayName
)
186 lstrcpyW( p
, status_ex
[i
].lpDisplayName
);
187 status
[i
].lpDisplayName
= p
;
188 p
+= lstrlenW( p
) + 1;
190 else status
[i
].lpDisplayName
= NULL
;
192 status
[i
].ServiceStatus
.dwServiceType
= status_ex
[i
].ServiceStatusProcess
.dwServiceType
;
193 status
[i
].ServiceStatus
.dwCurrentState
= status_ex
[i
].ServiceStatusProcess
.dwCurrentState
;
194 status
[i
].ServiceStatus
.dwControlsAccepted
= status_ex
[i
].ServiceStatusProcess
.dwControlsAccepted
;
195 status
[i
].ServiceStatus
.dwWin32ExitCode
= status_ex
[i
].ServiceStatusProcess
.dwWin32ExitCode
;
196 status
[i
].ServiceStatus
.dwServiceSpecificExitCode
= status_ex
[i
].ServiceStatusProcess
.dwServiceSpecificExitCode
;
197 status
[i
].ServiceStatus
.dwCheckPoint
= status_ex
[i
].ServiceStatusProcess
.dwCheckPoint
;
198 status
[i
].ServiceStatus
.dwWaitHint
= status_ex
[i
].ServiceStatusProcess
.dwWaitHint
;
201 heap_free( status_ex
);
202 if (*ret_size
> size
)
204 SetLastError( ERROR_MORE_DATA
);
212 /******************************************************************************
213 * EnumServicesStatusExA [ADVAPI32.@]
216 EnumServicesStatusExA( SC_HANDLE hmngr
, SC_ENUM_TYPE level
, DWORD type
, DWORD state
,
217 LPBYTE buffer
, DWORD size
, LPDWORD needed
, LPDWORD returned
,
218 LPDWORD resume_handle
, LPCSTR group
)
222 ENUM_SERVICE_STATUS_PROCESSA
*services
= (ENUM_SERVICE_STATUS_PROCESSA
*)buffer
;
223 ENUM_SERVICE_STATUS_PROCESSW
*servicesW
= NULL
;
224 WCHAR
*groupW
= NULL
;
228 TRACE("%p %u 0x%x 0x%x %p %u %p %p %p %s\n", hmngr
, level
, type
, state
, buffer
,
229 size
, needed
, returned
, resume_handle
, debugstr_a(group
));
231 sz
= max( 2 * size
, sizeof(*servicesW
) );
232 if (!(servicesW
= heap_alloc( sz
)))
234 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
239 int len
= MultiByteToWideChar( CP_ACP
, 0, group
, -1, NULL
, 0 );
240 if (!(groupW
= heap_alloc( len
* sizeof(WCHAR
) )))
242 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
243 heap_free( servicesW
);
246 MultiByteToWideChar( CP_ACP
, 0, group
, -1, groupW
, len
* sizeof(WCHAR
) );
249 ret
= EnumServicesStatusExW( hmngr
, level
, type
, state
, (BYTE
*)servicesW
, sz
,
250 needed
, returned
, resume_handle
, groupW
);
253 p
= (char *)services
+ *returned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
);
254 n
= size
- (p
- (char *)services
);
256 for (i
= 0; i
< *returned
; i
++)
258 sz
= WideCharToMultiByte( CP_ACP
, 0, servicesW
[i
].lpServiceName
, -1, p
, n
, NULL
, NULL
);
260 services
[i
].lpServiceName
= p
;
263 if (servicesW
[i
].lpDisplayName
)
265 sz
= WideCharToMultiByte( CP_ACP
, 0, servicesW
[i
].lpDisplayName
, -1, p
, n
, NULL
, NULL
);
267 services
[i
].lpDisplayName
= p
;
271 else services
[i
].lpDisplayName
= NULL
;
272 services
[i
].ServiceStatusProcess
= servicesW
[i
].ServiceStatusProcess
;
278 heap_free( servicesW
);
283 /******************************************************************************
284 * GetServiceKeyNameA [ADVAPI32.@]
286 BOOL WINAPI
GetServiceKeyNameA( SC_HANDLE hSCManager
, LPCSTR lpDisplayName
,
287 LPSTR lpServiceName
, LPDWORD lpcchBuffer
)
289 LPWSTR lpDisplayNameW
, lpServiceNameW
;
293 TRACE("%p %s %p %p\n", hSCManager
,
294 debugstr_a(lpDisplayName
), lpServiceName
, lpcchBuffer
);
296 lpDisplayNameW
= strdupAW(lpDisplayName
);
298 lpServiceNameW
= heap_alloc(*lpcchBuffer
* sizeof(WCHAR
));
300 lpServiceNameW
= NULL
;
302 sizeW
= *lpcchBuffer
;
303 if (!GetServiceKeyNameW(hSCManager
, lpDisplayNameW
, lpServiceNameW
, &sizeW
))
305 if (lpServiceName
&& *lpcchBuffer
)
306 lpServiceName
[0] = 0;
307 *lpcchBuffer
= sizeW
*2; /* we can only provide an upper estimation of string length */
311 if (!WideCharToMultiByte(CP_ACP
, 0, lpServiceNameW
, (sizeW
+ 1), lpServiceName
,
312 *lpcchBuffer
, NULL
, NULL
))
314 if (*lpcchBuffer
&& lpServiceName
)
315 lpServiceName
[0] = 0;
316 *lpcchBuffer
= WideCharToMultiByte(CP_ACP
, 0, lpServiceNameW
, -1, NULL
, 0, NULL
, NULL
);
320 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
324 heap_free(lpServiceNameW
);
325 heap_free(lpDisplayNameW
);
329 /******************************************************************************
330 * QueryServiceLockStatusA [ADVAPI32.@]
332 BOOL WINAPI
QueryServiceLockStatusA( SC_HANDLE hSCManager
,
333 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
334 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
)
336 FIXME("%p %p %08x %p\n", hSCManager
, lpLockStatus
, cbBufSize
, pcbBytesNeeded
);
341 /******************************************************************************
342 * QueryServiceLockStatusW [ADVAPI32.@]
344 BOOL WINAPI
QueryServiceLockStatusW( SC_HANDLE hSCManager
,
345 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
346 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
)
348 FIXME("%p %p %08x %p\n", hSCManager
, lpLockStatus
, cbBufSize
, pcbBytesNeeded
);
353 /******************************************************************************
354 * GetServiceDisplayNameA [ADVAPI32.@]
356 BOOL WINAPI
GetServiceDisplayNameA( SC_HANDLE hSCManager
, LPCSTR lpServiceName
,
357 LPSTR lpDisplayName
, LPDWORD lpcchBuffer
)
359 LPWSTR lpServiceNameW
, lpDisplayNameW
;
363 TRACE("%p %s %p %p\n", hSCManager
,
364 debugstr_a(lpServiceName
), lpDisplayName
, lpcchBuffer
);
366 lpServiceNameW
= strdupAW(lpServiceName
);
368 lpDisplayNameW
= heap_alloc(*lpcchBuffer
* sizeof(WCHAR
));
370 lpDisplayNameW
= NULL
;
372 sizeW
= *lpcchBuffer
;
373 if (!GetServiceDisplayNameW(hSCManager
, lpServiceNameW
, lpDisplayNameW
, &sizeW
))
375 if (lpDisplayName
&& *lpcchBuffer
)
376 lpDisplayName
[0] = 0;
377 *lpcchBuffer
= sizeW
*2; /* we can only provide an upper estimation of string length */
381 if (!WideCharToMultiByte(CP_ACP
, 0, lpDisplayNameW
, (sizeW
+ 1), lpDisplayName
,
382 *lpcchBuffer
, NULL
, NULL
))
384 if (*lpcchBuffer
&& lpDisplayName
)
385 lpDisplayName
[0] = 0;
386 *lpcchBuffer
= WideCharToMultiByte(CP_ACP
, 0, lpDisplayNameW
, -1, NULL
, 0, NULL
, NULL
);
390 /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
391 * (but if the function succeeded it means that is a good upper estimation of the size) */
395 heap_free(lpDisplayNameW
);
396 heap_free(lpServiceNameW
);
400 /******************************************************************************
401 * SetServiceBits [ADVAPI32.@]
403 BOOL WINAPI
SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus
,
406 BOOL bUpdateImmediately
)
408 FIXME("%p %08x %x %x\n", hServiceStatus
, dwServiceBits
,
409 bSetBitsOn
, bUpdateImmediately
);
413 /******************************************************************************
414 * EnumDependentServicesA [ADVAPI32.@]
416 BOOL WINAPI
EnumDependentServicesA( SC_HANDLE hService
, DWORD dwServiceState
,
417 LPENUM_SERVICE_STATUSA lpServices
, DWORD cbBufSize
,
418 LPDWORD pcbBytesNeeded
, LPDWORD lpServicesReturned
)
420 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService
, dwServiceState
,
421 lpServices
, cbBufSize
, pcbBytesNeeded
, lpServicesReturned
);
423 *lpServicesReturned
= 0;