Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/advapi32/service.c
4387 views
1
/*
2
* Win32 advapi functions
3
*
4
* Copyright 1995 Sven Verdoolaege
5
* Copyright 2005 Mike McCormack
6
* Copyright 2007 Rolf Kalbermatter
7
*
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.
12
*
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.
17
*
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
21
*/
22
23
#include <stdarg.h>
24
#include "windef.h"
25
#include "winbase.h"
26
#include "winsvc.h"
27
#include "wine/debug.h"
28
29
#include "advapi32_misc.h"
30
31
WINE_DEFAULT_DEBUG_CHANNEL(service);
32
33
/******************************************************************************
34
* LockServiceDatabase [ADVAPI32.@]
35
*/
36
SC_LOCK WINAPI LockServiceDatabase( SC_HANDLE manager )
37
{
38
/* this function is a no-op in Vista and above */
39
TRACE("%p\n", manager);
40
return (SC_LOCK)0xdeadbeef;
41
}
42
43
/******************************************************************************
44
* UnlockServiceDatabase [ADVAPI32.@]
45
*/
46
BOOL WINAPI UnlockServiceDatabase( SC_LOCK lock )
47
{
48
/* this function is a no-op in Vista and above */
49
TRACE("%p\n", lock);
50
return TRUE;
51
}
52
53
/******************************************************************************
54
* EnumServicesStatusA [ADVAPI32.@]
55
*/
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 )
60
{
61
BOOL ret;
62
unsigned int i;
63
ENUM_SERVICE_STATUSW *servicesW = NULL;
64
DWORD sz, n;
65
char *p;
66
67
TRACE("%p 0x%lx 0x%lx %p %lu %p %p %p\n", hmngr, type, state, services, size, needed,
68
returned, resume_handle);
69
70
if (!hmngr)
71
{
72
SetLastError( ERROR_INVALID_HANDLE );
73
return FALSE;
74
}
75
if (!needed || !returned)
76
{
77
SetLastError( ERROR_INVALID_ADDRESS );
78
return FALSE;
79
}
80
81
sz = max( 2 * size, sizeof(*servicesW) );
82
if (!(servicesW = malloc( sz )))
83
{
84
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
85
return FALSE;
86
}
87
88
ret = EnumServicesStatusW( hmngr, type, state, servicesW, sz, needed, returned, resume_handle );
89
if (!ret) goto done;
90
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++)
95
{
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)
102
{
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;
108
}
109
else services[i].lpDisplayName = NULL;
110
services[i].ServiceStatus = servicesW[i].ServiceStatus;
111
}
112
113
ret = TRUE;
114
115
done:
116
free( servicesW );
117
return ret;
118
}
119
120
/******************************************************************************
121
* EnumServicesStatusW [ADVAPI32.@]
122
*/
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 )
126
{
127
ENUM_SERVICE_STATUS_PROCESSW *status_ex;
128
DWORD alloc_size, count, i;
129
WCHAR *p;
130
131
TRACE("%p 0x%lx 0x%lx %p %lu %p %p %p\n", manager, type, state, status, size,
132
ret_size, ret_count, resume_handle);
133
134
if (!manager)
135
{
136
SetLastError( ERROR_INVALID_HANDLE );
137
return FALSE;
138
}
139
140
if (!ret_size || !ret_count)
141
{
142
SetLastError( ERROR_INVALID_PARAMETER );
143
return FALSE;
144
}
145
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;
152
153
if (!(status_ex = malloc( alloc_size )))
154
{
155
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
156
return FALSE;
157
}
158
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)
162
{
163
free( status_ex );
164
return FALSE;
165
}
166
167
for (i = 0; i < count; i++)
168
{
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);
173
174
if (*ret_size <= size)
175
++*ret_count;
176
}
177
178
p = (WCHAR *)(status + *ret_count);
179
for (i = 0; i < *ret_count; i++)
180
{
181
lstrcpyW( p, status_ex[i].lpServiceName );
182
status[i].lpServiceName = p;
183
p += lstrlenW( p ) + 1;
184
if (status_ex[i].lpDisplayName)
185
{
186
lstrcpyW( p, status_ex[i].lpDisplayName );
187
status[i].lpDisplayName = p;
188
p += lstrlenW( p ) + 1;
189
}
190
else status[i].lpDisplayName = NULL;
191
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;
199
}
200
201
free( status_ex );
202
if (*ret_size > size)
203
{
204
SetLastError( ERROR_MORE_DATA );
205
return FALSE;
206
}
207
208
*ret_size = 0;
209
return TRUE;
210
}
211
212
/******************************************************************************
213
* EnumServicesStatusExA [ADVAPI32.@]
214
*/
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 )
219
{
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;
227
228
TRACE("%p %u 0x%lx 0x%lx %p %lu %p %p %p %s\n", hmngr, level, type, state, buffer,
229
size, needed, returned, resume_handle, debugstr_a(group));
230
231
sz = max( 2 * size, sizeof(*servicesW) );
232
if (!(servicesW = malloc( sz )))
233
{
234
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
235
return FALSE;
236
}
237
if (group)
238
{
239
int len = MultiByteToWideChar( CP_ACP, 0, group, -1, NULL, 0 );
240
if (!(groupW = malloc( len * sizeof(WCHAR) )))
241
{
242
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
243
free( servicesW );
244
return FALSE;
245
}
246
MultiByteToWideChar( CP_ACP, 0, group, -1, groupW, len * sizeof(WCHAR) );
247
}
248
249
ret = EnumServicesStatusExW( hmngr, level, type, state, (BYTE *)servicesW, sz,
250
needed, returned, resume_handle, groupW );
251
if (!ret) goto done;
252
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++)
257
{
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)
264
{
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;
270
}
271
else services[i].lpDisplayName = NULL;
272
services[i].ServiceStatusProcess = servicesW[i].ServiceStatusProcess;
273
}
274
275
ret = TRUE;
276
277
done:
278
free( servicesW );
279
free( groupW );
280
return ret;
281
}
282
283
/******************************************************************************
284
* GetServiceKeyNameA [ADVAPI32.@]
285
*/
286
BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
287
LPSTR lpServiceName, LPDWORD lpcchBuffer )
288
{
289
LPWSTR lpDisplayNameW, lpServiceNameW;
290
DWORD sizeW;
291
BOOL ret = FALSE;
292
293
TRACE("%p %s %p %p\n", hSCManager,
294
debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
295
296
lpDisplayNameW = strdupAW(lpDisplayName);
297
if (lpServiceName)
298
lpServiceNameW = malloc(*lpcchBuffer * sizeof(WCHAR));
299
else
300
lpServiceNameW = NULL;
301
302
sizeW = *lpcchBuffer;
303
if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
304
{
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;
309
}
310
311
if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
312
*lpcchBuffer, NULL, NULL ))
313
{
314
if (*lpcchBuffer && lpServiceName)
315
lpServiceName[0] = 0;
316
*lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
317
goto cleanup;
318
}
319
320
/* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
321
ret = TRUE;
322
323
cleanup:
324
free(lpServiceNameW);
325
free(lpDisplayNameW);
326
return ret;
327
}
328
329
/******************************************************************************
330
* QueryServiceLockStatusA [ADVAPI32.@]
331
*/
332
BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
333
LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
334
DWORD cbBufSize, LPDWORD pcbBytesNeeded)
335
{
336
FIXME("%p %p %08lx %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
337
338
return FALSE;
339
}
340
341
/******************************************************************************
342
* QueryServiceLockStatusW [ADVAPI32.@]
343
*/
344
BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
345
LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
346
DWORD cbBufSize, LPDWORD pcbBytesNeeded)
347
{
348
FIXME("%p %p %08lx %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
349
350
return FALSE;
351
}
352
353
/******************************************************************************
354
* GetServiceDisplayNameA [ADVAPI32.@]
355
*/
356
BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
357
LPSTR lpDisplayName, LPDWORD lpcchBuffer)
358
{
359
LPWSTR lpServiceNameW, lpDisplayNameW;
360
DWORD sizeW;
361
BOOL ret = FALSE;
362
363
TRACE("%p %s %p %p\n", hSCManager,
364
debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
365
366
lpServiceNameW = strdupAW(lpServiceName);
367
if (lpDisplayName)
368
lpDisplayNameW = malloc(*lpcchBuffer * sizeof(WCHAR));
369
else
370
lpDisplayNameW = NULL;
371
372
sizeW = *lpcchBuffer;
373
if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
374
{
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;
379
}
380
381
if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
382
*lpcchBuffer, NULL, NULL ))
383
{
384
if (*lpcchBuffer && lpDisplayName)
385
lpDisplayName[0] = 0;
386
*lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
387
goto cleanup;
388
}
389
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;
393
394
cleanup:
395
free(lpDisplayNameW);
396
free(lpServiceNameW);
397
return ret;
398
}
399
400
/******************************************************************************
401
* SetServiceBits [ADVAPI32.@]
402
*/
403
BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
404
DWORD dwServiceBits,
405
BOOL bSetBitsOn,
406
BOOL bUpdateImmediately)
407
{
408
FIXME("%p %08lx %x %x\n", hServiceStatus, dwServiceBits,
409
bSetBitsOn, bUpdateImmediately);
410
return TRUE;
411
}
412
413
/******************************************************************************
414
* EnumDependentServicesA [ADVAPI32.@]
415
*/
416
BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState,
417
LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize,
418
LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
419
{
420
FIXME("%p 0x%08lx %p 0x%08lx %p %p - stub\n", hService, dwServiceState,
421
lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
422
423
*lpServicesReturned = 0;
424
return TRUE;
425
}
426
427