advapi32/tests: Expand tests for performance keys.
[wine.git] / dlls / advapi32 / service.c
blob8a1024ff8036deaa05d7ae80e33f98ff535196d2
1 /*
2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
5 * Copyright 2005 Mike McCormack
6 * Copyright 2007 Rolf Kalbermatter
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winsvc.h"
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 */
49 TRACE("%p\n", lock);
50 return TRUE;
53 /******************************************************************************
54 * EnumServicesStatusA [ADVAPI32.@]
56 BOOL WINAPI
57 EnumServicesStatusA( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSA
58 services, DWORD size, LPDWORD needed, LPDWORD returned,
59 LPDWORD resume_handle )
61 BOOL ret;
62 unsigned int i;
63 ENUM_SERVICE_STATUSW *servicesW = NULL;
64 DWORD sz, n;
65 char *p;
67 TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
68 returned, resume_handle);
70 if (!hmngr)
72 SetLastError( ERROR_INVALID_HANDLE );
73 return FALSE;
75 if (!needed || !returned)
77 SetLastError( ERROR_INVALID_ADDRESS );
78 return FALSE;
81 sz = max( 2 * size, sizeof(*servicesW) );
82 if (!(servicesW = heap_alloc( sz )))
84 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
85 return FALSE;
88 ret = EnumServicesStatusW( hmngr, type, state, servicesW, sz, needed, returned, resume_handle );
89 if (!ret) goto done;
91 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUSA);
92 n = size - (p - (char *)services);
93 ret = FALSE;
94 for (i = 0; i < *returned; i++)
96 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
97 if (!sz) goto done;
98 services[i].lpServiceName = p;
99 p += sz;
100 n -= sz;
101 if (servicesW[i].lpDisplayName)
103 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
104 if (!sz) goto done;
105 services[i].lpDisplayName = p;
106 p += sz;
107 n -= sz;
109 else services[i].lpDisplayName = NULL;
110 services[i].ServiceStatus = servicesW[i].ServiceStatus;
113 ret = TRUE;
115 done:
116 heap_free( servicesW );
117 return ret;
120 /******************************************************************************
121 * EnumServicesStatusW [ADVAPI32.@]
123 BOOL WINAPI
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;
129 WCHAR *p;
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);
134 if (!manager)
136 SetLastError( ERROR_INVALID_HANDLE );
137 return FALSE;
140 if (!ret_size || !ret_count)
142 SetLastError( ERROR_INVALID_PARAMETER );
143 return FALSE;
146 *ret_size = 0;
147 *ret_count = 0;
148 if (!EnumServicesStatusExW( manager, SC_ENUM_PROCESS_INFO, type, state,
149 NULL, 0, &alloc_size, &count, resume_handle, NULL )
150 && GetLastError() != ERROR_MORE_DATA)
151 return FALSE;
153 if (!(status_ex = heap_alloc( alloc_size )))
155 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
156 return FALSE;
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 );
164 return FALSE;
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)
175 ++*ret_count;
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 );
205 return FALSE;
208 *ret_size = 0;
209 return TRUE;
212 /******************************************************************************
213 * EnumServicesStatusExA [ADVAPI32.@]
215 BOOL WINAPI
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 )
220 BOOL ret;
221 unsigned int i;
222 ENUM_SERVICE_STATUS_PROCESSA *services = (ENUM_SERVICE_STATUS_PROCESSA *)buffer;
223 ENUM_SERVICE_STATUS_PROCESSW *servicesW = NULL;
224 WCHAR *groupW = NULL;
225 DWORD sz, n;
226 char *p;
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 );
235 return FALSE;
237 if (group)
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 );
244 return FALSE;
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 );
251 if (!ret) goto done;
253 p = (char *)services + *returned * sizeof(ENUM_SERVICE_STATUS_PROCESSA);
254 n = size - (p - (char *)services);
255 ret = FALSE;
256 for (i = 0; i < *returned; i++)
258 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpServiceName, -1, p, n, NULL, NULL );
259 if (!sz) goto done;
260 services[i].lpServiceName = p;
261 p += sz;
262 n -= sz;
263 if (servicesW[i].lpDisplayName)
265 sz = WideCharToMultiByte( CP_ACP, 0, servicesW[i].lpDisplayName, -1, p, n, NULL, NULL );
266 if (!sz) goto done;
267 services[i].lpDisplayName = p;
268 p += sz;
269 n -= sz;
271 else services[i].lpDisplayName = NULL;
272 services[i].ServiceStatusProcess = servicesW[i].ServiceStatusProcess;
275 ret = TRUE;
277 done:
278 heap_free( servicesW );
279 heap_free( groupW );
280 return ret;
283 /******************************************************************************
284 * GetServiceKeyNameA [ADVAPI32.@]
286 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
287 LPSTR lpServiceName, LPDWORD lpcchBuffer )
289 LPWSTR lpDisplayNameW, lpServiceNameW;
290 DWORD sizeW;
291 BOOL ret = FALSE;
293 TRACE("%p %s %p %p\n", hSCManager,
294 debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
296 lpDisplayNameW = strdupAW(lpDisplayName);
297 if (lpServiceName)
298 lpServiceNameW = heap_alloc(*lpcchBuffer * sizeof(WCHAR));
299 else
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 */
308 goto cleanup;
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);
317 goto cleanup;
320 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
321 ret = TRUE;
323 cleanup:
324 heap_free(lpServiceNameW);
325 heap_free(lpDisplayNameW);
326 return ret;
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);
338 return FALSE;
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);
350 return FALSE;
353 /******************************************************************************
354 * GetServiceDisplayNameA [ADVAPI32.@]
356 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
357 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
359 LPWSTR lpServiceNameW, lpDisplayNameW;
360 DWORD sizeW;
361 BOOL ret = FALSE;
363 TRACE("%p %s %p %p\n", hSCManager,
364 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
366 lpServiceNameW = strdupAW(lpServiceName);
367 if (lpDisplayName)
368 lpDisplayNameW = heap_alloc(*lpcchBuffer * sizeof(WCHAR));
369 else
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 */
378 goto cleanup;
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);
387 goto cleanup;
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) */
392 ret = TRUE;
394 cleanup:
395 heap_free(lpDisplayNameW);
396 heap_free(lpServiceNameW);
397 return ret;
400 /******************************************************************************
401 * SetServiceBits [ADVAPI32.@]
403 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
404 DWORD dwServiceBits,
405 BOOL bSetBitsOn,
406 BOOL bUpdateImmediately)
408 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
409 bSetBitsOn, bUpdateImmediately);
410 return TRUE;
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;
424 return TRUE;