2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for QueryServiceConfig2A/W
5 * PROGRAMMER: Hermès BÉLUSCA - MAÏTO
12 #define TESTING_SERVICEW L"Spooler"
13 #define TESTING_SERVICEA "Spooler"
16 * Taken from base/system/services/config.c and adapted.
19 RegReadStringW(HKEY hKey
,
30 dwError
= RegQueryValueExW(hKey
,
36 if (dwError
!= ERROR_SUCCESS
)
39 *lpValue
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
41 return ERROR_NOT_ENOUGH_MEMORY
;
43 dwError
= RegQueryValueExW(hKey
,
49 if (dwError
!= ERROR_SUCCESS
)
51 HeapFree(GetProcessHeap(), 0, *lpValue
);
59 RegReadStringA(HKEY hKey
,
70 dwError
= RegQueryValueExA(hKey
,
76 if (dwError
!= ERROR_SUCCESS
)
79 *lpValue
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
81 return ERROR_NOT_ENOUGH_MEMORY
;
83 dwError
= RegQueryValueExA(hKey
,
89 if (dwError
!= ERROR_SUCCESS
)
91 HeapFree(GetProcessHeap(), 0, *lpValue
);
99 static int QueryConfig2W(SC_HANDLE hService
, LPCWSTR serviceName
, DWORD dwInfoLevel
)
105 DWORD dwRequiredSize
= 0;
106 LPBYTE lpBuffer
= NULL
;
112 /* Get the needed size */
113 SetLastError(0xdeadbeef);
114 bError
= QueryServiceConfig2W(hService
,
119 ok(bError
== FALSE
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError
, GetLastError(), (DWORD
)ERROR_INSUFFICIENT_BUFFER
);
120 ok(dwRequiredSize
!= 0, "dwRequiredSize is zero, expected non-zero\n");
121 if (dwRequiredSize
== 0)
123 skip("Required size is null; cannot proceed with QueryConfig2W --> %lu test\n", dwInfoLevel
);
127 /* Allocate memory */
128 lpBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwRequiredSize
);
129 if (lpBuffer
== NULL
)
131 skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize
);
135 /* Get the actual value */
136 SetLastError(0xdeadbeef);
137 bError
= QueryServiceConfig2W(hService
,
142 ok(bError
, "bError = %u, expected TRUE\n", bError
);
145 skip("QueryServiceConfig2W returned an error; cannot proceed with QueryConfig2W --> %lu test\n", dwInfoLevel
);
146 HeapFree(GetProcessHeap(), 0, lpBuffer
);
150 /* Now we can compare the retrieved value with what it's actually stored in the registry */
151 StringCbPrintfW(keyName
, sizeof(keyName
), L
"System\\CurrentControlSet\\Services\\%s", serviceName
);
152 SetLastError(0xdeadbeef);
153 lRet
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, keyName
, 0, KEY_QUERY_VALUE
, &hKey
);
154 ok(lRet
== ERROR_SUCCESS
, "RegOpenKeyExW failed with 0x%08lx\n", lRet
);
155 if (lRet
!= ERROR_SUCCESS
)
157 skip("No regkey; cannot proceed with QueryConfig2W --> %lu test\n", dwInfoLevel
);
158 HeapFree(GetProcessHeap(), 0, lpBuffer
);
164 case SERVICE_CONFIG_DESCRIPTION
:
166 LPSERVICE_DESCRIPTIONW lpDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
167 LPWSTR lpszDescription
= NULL
;
169 /* Retrieve the description via the registry */
170 dwRet
= RegReadStringW(hKey
, L
"Description", &lpszDescription
);
171 ok(dwRet
== ERROR_SUCCESS
, "RegReadStringW returned 0x%08lx\n", dwRet
);
172 ok(lpszDescription
!= NULL
, "lpszDescription is null, expected non-null\n");
174 /* Compare it with the description retrieved via QueryServiceConfig2 */
176 iRet
= wcscmp(lpDescription
->lpDescription
, lpszDescription
);
180 ok(iRet
== 0, "Retrieved descriptions are different !\n");
184 HeapFree(GetProcessHeap(), 0, lpszDescription
);
189 case SERVICE_CONFIG_FAILURE_ACTIONS
:
191 LPSERVICE_FAILURE_ACTIONSW lpFailureActions1
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
192 LPSERVICE_FAILURE_ACTIONSW lpFailureActions2
= NULL
;
193 LPWSTR lpRebootMessage
= NULL
;
194 LPWSTR lpFailureCommand
= NULL
;
197 /* Retrieve the failure actions via the registry */
198 lRet
= RegQueryValueExW(hKey
,
204 ok(lRet
== ERROR_SUCCESS
, "RegQueryValueExW returned 0x%08lx\n", lRet
);
205 ok(dwType
== REG_BINARY
, "dwType = %lu, expected REG_BINARY\n", dwType
);
206 ok(dwRequiredSize
!= 0, "dwRequiredSize is zero, expected non-zero\n");
208 lpFailureActions2
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwRequiredSize
);
209 if (lpFailureActions2
== NULL
)
211 skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize
);
215 lRet
= RegQueryValueExW(hKey
,
219 (LPBYTE
)lpFailureActions2
,
221 ok(lRet
== ERROR_SUCCESS
, "RegQueryValueExW returned 0x%08lx\n", lRet
);
222 ok(dwRequiredSize
!= 0, "dwRequiredSize is zero, expected non-zero\n");
224 /* Get the strings */
225 RegReadStringW(hKey
, L
"FailureCommand", &lpFailureCommand
);
226 RegReadStringW(hKey
, L
"RebootMessage" , &lpRebootMessage
);
228 /* Check the values */
229 ok(lpFailureActions1
->dwResetPeriod
== lpFailureActions2
->dwResetPeriod
, "lpFailureActions1->dwResetPeriod != lpFailureActions2->dwResetPeriod\n");
230 ok(lpFailureActions1
->cActions
== lpFailureActions2
->cActions
, "lpFailureActions1->cActions != lpFailureActions2->cActions\n");
232 /* Compare the actions */
233 if (lpFailureActions1
->cActions
== lpFailureActions2
->cActions
)
235 lpFailureActions2
->lpsaActions
= (lpFailureActions2
->cActions
> 0 ? (LPSC_ACTION
)(lpFailureActions2
+ 1) : NULL
);
237 if (lpFailureActions1
->cActions
> 0 &&
238 lpFailureActions1
->lpsaActions
!= NULL
)
240 for (i
= 0; i
< lpFailureActions1
->cActions
; ++i
)
242 ok(lpFailureActions1
->lpsaActions
[i
].Type
== lpFailureActions2
->lpsaActions
[i
].Type
, "lpFailureActions1->lpsaActions[%lu].Type != lpFailureActions2->lpsaActions[%lu].Type\n" , i
, i
);
243 ok(lpFailureActions1
->lpsaActions
[i
].Delay
== lpFailureActions2
->lpsaActions
[i
].Delay
, "lpFailureActions1->lpsaActions[%lu].Delay != lpFailureActions2->lpsaActions[%lu].Delay\n", i
, i
);
248 /* TODO: retrieve the strings if they are in MUI format */
250 /* Compare RebootMsg */
251 if (lpFailureActions1
->lpRebootMsg
&& lpRebootMessage
)
252 iRet
= wcscmp(lpFailureActions1
->lpRebootMsg
, lpRebootMessage
);
256 ok(iRet
== 0, "Retrieved reboot messages are different !\n");
258 /* Compare Command */
259 if (lpFailureActions1
->lpCommand
&& lpFailureCommand
)
260 iRet
= wcscmp(lpFailureActions1
->lpCommand
, lpFailureCommand
);
264 ok(iRet
== 0, "Retrieved commands are different !\n");
269 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
271 if (lpFailureCommand
)
272 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
274 HeapFree(GetProcessHeap(), 0, lpFailureActions2
);
280 skip("Unknown dwInfoLevel %lu, cannot proceed with QueryConfig2W --> %lu test\n", dwInfoLevel
, dwInfoLevel
);
286 HeapFree(GetProcessHeap(), 0, lpBuffer
);
291 static int QueryConfig2A(SC_HANDLE hService
, LPCSTR serviceName
, DWORD dwInfoLevel
)
297 DWORD dwRequiredSize
= 0;
298 LPBYTE lpBuffer
= NULL
;
304 /* Get the needed size */
305 SetLastError(0xdeadbeef);
306 bError
= QueryServiceConfig2A(hService
,
311 ok(bError
== FALSE
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError
, GetLastError(), (DWORD
)ERROR_INSUFFICIENT_BUFFER
);
312 ok(dwRequiredSize
!= 0, "dwRequiredSize is zero, expected non-zero\n");
313 if (dwRequiredSize
== 0)
315 skip("Required size is null; cannot proceed with QueryConfig2A --> %lu test\n", dwInfoLevel
);
319 /* Allocate memory */
320 lpBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwRequiredSize
);
321 if (lpBuffer
== NULL
)
323 skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize
);
327 /* Get the actual value */
328 SetLastError(0xdeadbeef);
329 bError
= QueryServiceConfig2A(hService
,
334 ok(bError
, "bError = %u, expected TRUE\n", bError
);
337 skip("QueryServiceConfig2A returned an error; cannot proceed with QueryConfig2A --> %lu test\n", dwInfoLevel
);
338 HeapFree(GetProcessHeap(), 0, lpBuffer
);
342 /* Now we can compare the retrieved value with what it's actually stored in the registry */
343 StringCbPrintfA(keyName
, sizeof(keyName
), "System\\CurrentControlSet\\Services\\%s", serviceName
);
344 SetLastError(0xdeadbeef);
345 lRet
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
, keyName
, 0, KEY_QUERY_VALUE
, &hKey
);
346 ok(lRet
== ERROR_SUCCESS
, "RegOpenKeyExA failed with 0x%08lx\n", lRet
);
347 if (lRet
!= ERROR_SUCCESS
)
349 skip("No regkey; cannot proceed with QueryConfig2A --> %lu test\n", dwInfoLevel
);
350 HeapFree(GetProcessHeap(), 0, lpBuffer
);
356 case SERVICE_CONFIG_DESCRIPTION
:
358 LPSERVICE_DESCRIPTIONA lpDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
359 LPSTR lpszDescription
= NULL
;
361 /* Retrieve the description via the registry */
362 dwRet
= RegReadStringA(hKey
, "Description", &lpszDescription
);
363 ok(dwRet
== ERROR_SUCCESS
, "RegReadStringA returned 0x%08lx\n", dwRet
);
364 ok(lpszDescription
!= NULL
, "lpszDescription is null, expected non-null\n");
366 /* Compare it with the description retrieved via QueryServiceConfig2 */
368 iRet
= strcmp(lpDescription
->lpDescription
, lpszDescription
);
372 ok(iRet
== 0, "Retrieved descriptions are different !\n");
376 HeapFree(GetProcessHeap(), 0, lpszDescription
);
381 case SERVICE_CONFIG_FAILURE_ACTIONS
:
383 LPSERVICE_FAILURE_ACTIONSA lpFailureActions1
= (LPSERVICE_FAILURE_ACTIONSA
)lpBuffer
;
384 LPSERVICE_FAILURE_ACTIONSA lpFailureActions2
= NULL
;
385 LPSTR lpRebootMessage
= NULL
;
386 LPSTR lpFailureCommand
= NULL
;
389 /* Retrieve the failure actions via the registry */
390 lRet
= RegQueryValueExA(hKey
,
396 ok(lRet
== ERROR_SUCCESS
, "RegQueryValueExA returned 0x%08lx\n", lRet
);
397 ok(dwType
== REG_BINARY
, "dwType = %lu, expected REG_BINARY\n", dwType
);
398 ok(dwRequiredSize
!= 0, "dwRequiredSize is zero, expected non-zero\n");
400 lpFailureActions2
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwRequiredSize
);
401 if (lpFailureActions2
== NULL
)
403 skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize
);
407 lRet
= RegQueryValueExA(hKey
,
411 (LPBYTE
)lpFailureActions2
,
413 ok(lRet
== ERROR_SUCCESS
, "RegQueryValueExA returned 0x%08lx\n", lRet
);
414 ok(dwRequiredSize
!= 0, "dwRequiredSize is zero, expected non-zero\n");
416 /* Get the strings */
417 RegReadStringA(hKey
, "FailureCommand", &lpFailureCommand
);
418 RegReadStringA(hKey
, "RebootMessage" , &lpRebootMessage
);
420 /* Check the values */
421 ok(lpFailureActions1
->dwResetPeriod
== lpFailureActions2
->dwResetPeriod
, "lpFailureActions1->dwResetPeriod != lpFailureActions2->dwResetPeriod\n");
422 ok(lpFailureActions1
->cActions
== lpFailureActions2
->cActions
, "lpFailureActions1->cActions != lpFailureActions2->cActions\n");
424 /* Compare the actions */
425 if (lpFailureActions1
->cActions
== lpFailureActions2
->cActions
)
427 lpFailureActions2
->lpsaActions
= (lpFailureActions2
->cActions
> 0 ? (LPSC_ACTION
)(lpFailureActions2
+ 1) : NULL
);
429 if (lpFailureActions1
->cActions
> 0 &&
430 lpFailureActions1
->lpsaActions
!= NULL
)
432 for (i
= 0; i
< lpFailureActions1
->cActions
; ++i
)
434 ok(lpFailureActions1
->lpsaActions
[i
].Type
== lpFailureActions2
->lpsaActions
[i
].Type
, "lpFailureActions1->lpsaActions[%lu].Type != lpFailureActions2->lpsaActions[%lu].Type\n" , i
, i
);
435 ok(lpFailureActions1
->lpsaActions
[i
].Delay
== lpFailureActions2
->lpsaActions
[i
].Delay
, "lpFailureActions1->lpsaActions[%lu].Delay != lpFailureActions2->lpsaActions[%lu].Delay\n", i
, i
);
440 /* TODO: retrieve the strings if they are in MUI format */
442 /* Compare RebootMsg */
443 if (lpFailureActions1
->lpRebootMsg
&& lpRebootMessage
)
444 iRet
= strcmp(lpFailureActions1
->lpRebootMsg
, lpRebootMessage
);
448 ok(iRet
== 0, "Retrieved reboot messages are different !\n");
450 /* Compare Command */
451 if (lpFailureActions1
->lpCommand
&& lpFailureCommand
)
452 iRet
= strcmp(lpFailureActions1
->lpCommand
, lpFailureCommand
);
456 ok(iRet
== 0, "Retrieved commands are different !\n");
461 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
463 if (lpFailureCommand
)
464 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
466 HeapFree(GetProcessHeap(), 0, lpFailureActions2
);
472 skip("Unknown dwInfoLevel %lu, cannot proceed with QueryConfig2A --> %lu test\n", dwInfoLevel
, dwInfoLevel
);
478 HeapFree(GetProcessHeap(), 0, lpBuffer
);
484 static void Test_QueryServiceConfig2W(void)
486 SC_HANDLE hScm
= NULL
;
487 SC_HANDLE hService
= NULL
;
489 SetLastError(0xdeadbeef);
490 hScm
= OpenSCManagerW(NULL
, NULL
, SC_MANAGER_CONNECT
);
491 ok(hScm
!= NULL
, "Failed to open service manager, error=0x%08lx\n", GetLastError());
494 skip("No service control manager; cannot proceed with QueryServiceConfig2W test\n");
498 ok_err(ERROR_SUCCESS
);
500 SetLastError(0xdeadbeef);
501 hService
= OpenServiceW(hScm
, TESTING_SERVICEW
, SERVICE_QUERY_CONFIG
);
502 ok(hService
!= NULL
, "Failed to open service handle, error=0x%08lx\n", GetLastError());
505 skip("Service not found; cannot proceed with QueryServiceConfig2W test\n");
509 ok_err(ERROR_SUCCESS
);
511 if (QueryConfig2W(hService
, TESTING_SERVICEW
, SERVICE_CONFIG_DESCRIPTION
) != 0)
514 if (QueryConfig2W(hService
, TESTING_SERVICEW
, SERVICE_CONFIG_FAILURE_ACTIONS
) != 0)
519 CloseServiceHandle(hService
);
522 CloseServiceHandle(hScm
);
525 static void Test_QueryServiceConfig2A(void)
527 SC_HANDLE hScm
= NULL
;
528 SC_HANDLE hService
= NULL
;
530 SetLastError(0xdeadbeef);
531 hScm
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
532 ok(hScm
!= NULL
, "Failed to open service manager, error=0x%08lx\n", GetLastError());
535 skip("No service control manager; cannot proceed with QueryServiceConfig2A test\n");
539 ok_err(ERROR_SUCCESS
);
541 SetLastError(0xdeadbeef);
542 hService
= OpenServiceA(hScm
, TESTING_SERVICEA
, SERVICE_QUERY_CONFIG
);
543 ok(hService
!= NULL
, "Failed to open service handle, error=0x%08lx\n", GetLastError());
546 skip("Service not found; cannot proceed with QueryServiceConfig2A test\n");
550 ok_err(ERROR_SUCCESS
);
552 if (QueryConfig2A(hService
, TESTING_SERVICEA
, SERVICE_CONFIG_DESCRIPTION
) != 0)
555 if (QueryConfig2A(hService
, TESTING_SERVICEA
, SERVICE_CONFIG_FAILURE_ACTIONS
) != 0)
560 CloseServiceHandle(hService
);
563 CloseServiceHandle(hScm
);
567 START_TEST(QueryServiceConfig2
)
569 Test_QueryServiceConfig2W();
570 Test_QueryServiceConfig2A();