In particular: * Fix the resume handle comments. * Don't expect START_PENDING and STOP_PENDING services to have a process id. * Take into account service start / stop race conditions. * Enumerate the services using the Unicode API since the ANSI one is broken in some UTF-8 locales. * Skip some tests if the EventLog service crashed.
From: Francois Gouget fgouget@codeweavers.com
Fix the comments to not imply that the tests expect all services but one to be returned. Add a test of the needed buffer size to retrieve the remaining services and document the limits of the test. --- dlls/advapi32/tests/service.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-)
diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index fbb18b048a0..2527be27d5f 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -1300,7 +1300,10 @@ static void test_enum_svc(void) ok(returnedW != 0xdeadbeef && returnedW > 0, "Expected some returned services\n"); HeapFree(GetProcessHeap(), 0, servicesW);
- /* Allocate less than the needed bytes and don't specify a resume handle */ + /* Allocate less than the needed bytes and don't specify a resume handle. + * More than one service will be missing because of the space needed for + * the strings. + */ services = HeapAlloc(GetProcessHeap(), 0, tempneeded); bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA); needed = 0xdeadbeef; @@ -1309,7 +1312,11 @@ static void test_enum_svc(void) ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services, bufsize, &needed, &returned, NULL); ok(!ret, "Expected failure\n"); - ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n"); + ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n"); + todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n"); + /* Experiments show bufsize + needed < tempneeded which proves the needed + * buffer size is an approximation. So it's best not to probe more. + */ ok(returned < tempreturned, "Expected fewer services to be returned\n"); ok(GetLastError() == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %ld\n", GetLastError()); @@ -1323,7 +1330,8 @@ static void test_enum_svc(void) ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services, bufsize, &needed, &returned, &resume); ok(!ret, "Expected failure\n"); - ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n"); + ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for the missing services\n"); + todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n"); ok(returned < tempreturned, "Expected fewer services to be returned\n"); todo_wine ok(resume, "Expected a resume handle\n"); ok(GetLastError() == ERROR_MORE_DATA, @@ -1615,7 +1623,10 @@ static void test_enum_svc(void) /* Store the number of returned services */ tempreturned = returned;
- /* Allocate less than the needed bytes and don't specify a resume handle */ + /* Allocate less than the needed bytes and don't specify a resume handle. + * More than one service will be missing because of the space needed for + * the strings. + */ exservices = HeapAlloc(GetProcessHeap(), 0, tempneeded); bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA); needed = 0xdeadbeef; @@ -1624,7 +1635,11 @@ static void test_enum_svc(void) ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, (BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL); ok(!ret, "Expected failure\n"); - ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n"); + ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for the missing services\n"); + todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n"); + /* Experiments show bufsize + needed < tempneeded which proves the needed + * buffer size is an approximation. So it's best not to probe more. + */ ok(returned < tempreturned, "Expected fewer services to be returned\n"); ok(GetLastError() == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %ld\n", GetLastError()); @@ -1638,13 +1653,14 @@ static void test_enum_svc(void) ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, (BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL); ok(!ret, "Expected failure\n"); - ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n"); + ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for the missing services\n"); + todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n"); ok(returned < tempreturned, "Expected fewer services to be returned\n"); todo_wine ok(resume, "Expected a resume handle\n"); ok(GetLastError() == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
- /* Fetch that last service but pass a bigger buffer size */ + /* Fetch the missing services but pass a bigger buffer size */ missing = tempreturned - returned; bufsize = tempneeded; needed = 0xdeadbeef;
From: Francois Gouget fgouget@codeweavers.com
The START_PENDING and STOP_PENDING services don't always have a process id. Also trace unusual service states so we can identify which ones behave in unexpected ways.
Wine-Bug: https://bugs.winehq.org//show_bug.cgi?id=53460 --- dlls/advapi32/tests/service.c | 60 ++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 8 deletions(-)
diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index 2527be27d5f..8a4fdec05ab 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -1420,10 +1420,30 @@ static void test_enum_svc(void) */ if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS)) { - if (status.dwCurrentState == SERVICE_STOPPED) - servicecountinactive--; - else + switch (status.dwCurrentState) + { + case SERVICE_START_PENDING: + case SERVICE_STOP_PENDING: + case SERVICE_PAUSE_PENDING: + case SERVICE_PAUSED: + case SERVICE_CONTINUE_PENDING: + trace("Got state %lx for service %s\n", status.dwCurrentState, + services[i].lpServiceName); + /* fall through */ + + case SERVICE_RUNNING: servicecountactive--; + break; + + case SERVICE_STOPPED: + servicecountinactive--; + break; + + default: + ok(0, "Got unknown state %lx for service %s\n", + status.dwCurrentState, services[i].lpServiceName); + break; + } } } HeapFree(GetProcessHeap(), 0, services); @@ -1739,21 +1759,45 @@ static void test_enum_svc(void)
if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS)) { - if (status.dwCurrentState != SERVICE_STOPPED) + switch (status.dwCurrentState) { + case SERVICE_START_PENDING: + case SERVICE_STOP_PENDING: + trace("Got state %lx (pid=%04lx) for service %s\n", + status.dwCurrentState, status.dwProcessId, + exservices[i].lpServiceName); + /* There may or may not be a process id */ + servicecountactive--; + break; + + case SERVICE_PAUSE_PENDING: + case SERVICE_PAUSED: + case SERVICE_CONTINUE_PENDING: + trace("Got state %lx (pid=%04lx) for service %s\n", + status.dwCurrentState, status.dwProcessId, + exservices[i].lpServiceName); + /* fall through */ + + case SERVICE_RUNNING: /* We expect a process id for every running service */ ok(status.dwProcessId > 0, "Expected a process id for this running service (%s)\n", exservices[i].lpServiceName); - servicecountactive--; - } - else - { + break; + + case SERVICE_STOPPED: /* We shouldn't have a process id for inactive services */ ok(status.dwProcessId == 0, "Service %s state %lu shouldn't have an associated process id\n", exservices[i].lpServiceName, status.dwCurrentState);
servicecountinactive--; + break; + + default: + ok(0, "Got unknown state %lx (pid=%04lx) for service %s\n", + status.dwCurrentState, status.dwProcessId, + exservices[i].lpServiceName); + break; } } }
From: Francois Gouget fgouget@codeweavers.com
--- This avoids too much long range test dependencies. --- dlls/advapi32/tests/service.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-)
diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index 8a4fdec05ab..2d38f9e6a90 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -1072,7 +1072,6 @@ static void test_enum_svc(void) DWORD servicecountactive, servicecountinactive; ENUM_SERVICE_STATUSA *services; ENUM_SERVICE_STATUSW *servicesW; - ENUM_SERVICE_STATUS_PROCESSA *exservices; UINT i;
/* All NULL or wrong */ @@ -1452,6 +1451,19 @@ static void test_enum_svc(void) ok(servicecountinactive == 0, "Inactive services mismatch %lu\n", servicecountinactive);
CloseServiceHandle(scm_handle); +} + +static void test_enum_svc_ex(void) +{ + SC_HANDLE scm_handle; + BOOL ret; + DWORD bufsize, needed, returned, resume; + DWORD neededW, returnedW; + DWORD tempneeded, tempreturned, missing; + DWORD servicecountactive, servicecountinactive; + ENUM_SERVICE_STATUSA *services; + ENUM_SERVICE_STATUS_PROCESSA *exservices; + UINT i;
/* More or less the same for EnumServicesStatusExA */ if (!pEnumServicesStatusExA) @@ -1627,9 +1639,24 @@ static void test_enum_svc(void) /* Store the needed bytes */ tempneeded = needed;
+ /* Show the Ex call returns the same service count as the regular enum */ + EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, + NULL, 0, &needed, &returned, NULL); + services = HeapAlloc(GetProcessHeap(), 0, needed); + returned = 0xdeadbeef; + ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, + services, needed, &needed, &returned, NULL); + ok(ret, "Expected success, got error %lu\n", GetLastError()); + ok(needed == 0, "Expected needed buffer to be 0 as we are done\n"); + ok(returned != 0xdeadbeef && returned > 0, "Expected some returned services\n"); + HeapFree(GetProcessHeap(), 0, services); + + /* Store the number of returned services */ + tempreturned = returned; + /* Allocate the correct needed bytes */ - exservices = HeapAlloc(GetProcessHeap(), 0, needed); - bufsize = needed; + exservices = HeapAlloc(GetProcessHeap(), 0, tempneeded); + bufsize = tempneeded; needed = 0xdeadbeef; returned = 0xdeadbeef; SetLastError(0xdeadbeef); @@ -2913,6 +2940,7 @@ START_TEST(service) test_get_servicekeyname(); test_query_svc(); test_enum_svc(); + test_enum_svc_ex(); test_close(); test_wow64(); /* Test the creation, querying and deletion of a service */
From: Francois Gouget fgouget@codeweavers.com
It only has this one test. --- dlls/advapi32/tests/service.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index 2d38f9e6a90..8736aaab04c 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -1631,10 +1631,16 @@ static void test_enum_svc_ex(void)
/* Test to show we get the same needed buffer size for the W-call */ neededW = 0xdeadbeef; + returnedW = 0xdeadbeef; + SetLastError(0xdeadbeef); ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &neededW, &returnedW, NULL, NULL); ok(!ret, "Expected failure\n"); + ok(returnedW == 0, "Expected no service returned, got %ld\n", returned); + ok(neededW != 0xdeadbeef && neededW > 0, "Expected the needed buffer size\n"); ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n"); + ok(GetLastError() == ERROR_MORE_DATA, + "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
/* Store the needed bytes */ tempneeded = needed;
From: Francois Gouget fgouget@codeweavers.com
Services sometimes start or stop between two EnumServicesStatus() calls. Fortunately this is rare so the tests can just retry to get the expected result.
Wine-Bug: https://bugs.winehq.org//show_bug.cgi?id=53460 --- dlls/advapi32/tests/service.c | 149 ++++++++++++++++++++++++++-------- 1 file changed, 115 insertions(+), 34 deletions(-)
diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index 8736aaab04c..92b44101a03 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -1062,10 +1062,10 @@ static void test_query_svc(void) CloseServiceHandle(scm_handle); }
-static void test_enum_svc(void) +static BOOL test_enum_svc(int attempt) { SC_HANDLE scm_handle; - BOOL ret; + BOOL ret, alldone = FALSE; DWORD bufsize, needed, returned, resume; DWORD neededW, returnedW; DWORD tempneeded, tempreturned, missing; @@ -1262,11 +1262,13 @@ static void test_enum_svc(void) SetLastError(0xdeadbeef); ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &neededW, &returnedW, NULL); ok(!ret, "Expected failure\n"); - ok(neededW != 0xdeadbeef && neededW > 0, "Expected the needed buffer size for this one service\n"); - ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n"); - ok(returnedW == 0, "Expected no service returned, got %ld\n", returnedW); ok(GetLastError() == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %ld\n", GetLastError()); + ok(neededW != 0xdeadbeef && neededW > 0, "Expected the needed buffer size for this one service\n"); + ok(returnedW == 0, "Expected no service returned, got %ld\n", returnedW); + if (neededW != needed && attempt) + goto retry; /* service start|stop race condition */ + ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n");
/* Store the needed bytes */ tempneeded = needed; @@ -1279,10 +1281,12 @@ static void test_enum_svc(void) SetLastError(0xdeadbeef); ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services, bufsize, &needed, &returned, NULL); + HeapFree(GetProcessHeap(), 0, services); + if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) + goto retry; /* service start race condition */ ok(ret, "Expected success, got error %lu\n", GetLastError()); ok(needed == 0, "Expected needed buffer to be 0 as we are done\n"); ok(returned != 0xdeadbeef && returned > 0, "Expected some returned services\n"); - HeapFree(GetProcessHeap(), 0, services);
/* Store the number of returned services */ tempreturned = returned; @@ -1294,10 +1298,12 @@ static void test_enum_svc(void) SetLastError(0xdeadbeef); ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, servicesW, bufsize, &neededW, &returnedW, NULL); + HeapFree(GetProcessHeap(), 0, servicesW); + if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) + goto retry; /* service start race condition */ ok(ret, "Expected success, got error %lu\n", GetLastError()); ok(neededW == 0, "Expected needed buffer to be 0 as we are done\n"); ok(returnedW != 0xdeadbeef && returnedW > 0, "Expected some returned services\n"); - HeapFree(GetProcessHeap(), 0, servicesW);
/* Allocate less than the needed bytes and don't specify a resume handle. * More than one service will be missing because of the space needed for @@ -1310,6 +1316,11 @@ static void test_enum_svc(void) SetLastError(0xdeadbeef); ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services, bufsize, &needed, &returned, NULL); + if (ret && needed == 0 && attempt) + { + HeapFree(GetProcessHeap(), 0, services); + goto retry; /* service stop race condition */ + } ok(!ret, "Expected failure\n"); ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n"); todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n"); @@ -1328,6 +1339,11 @@ static void test_enum_svc(void) SetLastError(0xdeadbeef); ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services, bufsize, &needed, &returned, &resume); + if (ret && needed == 0 && attempt) + { + HeapFree(GetProcessHeap(), 0, services); + goto retry; /* service stop race condition */ + } ok(!ret, "Expected failure\n"); ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for the missing services\n"); todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n"); @@ -1344,11 +1360,13 @@ static void test_enum_svc(void) SetLastError(0xdeadbeef); ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services, bufsize, &needed, &returned, &resume); + HeapFree(GetProcessHeap(), 0, services); + if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) + goto retry; /* service start race condition */ ok(ret, "Expected success, got error %lu\n", GetLastError()); ok(needed == 0, "Expected needed buffer to be 0 as we are done\n"); todo_wine ok(returned == missing, "Expected %lu services to be returned\n", missing); ok(resume == 0, "Expected the resume handle to be 0\n"); - HeapFree(GetProcessHeap(), 0, services);
/* See if things add up */
@@ -1366,9 +1384,11 @@ static void test_enum_svc(void) EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0, &needed, &returned, NULL); services = HeapAlloc(GetProcessHeap(), 0, needed); - EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, services, - needed, &needed, &returned, NULL); + ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, + services, needed, &needed, &returned, NULL); HeapFree(GetProcessHeap(), 0, services); + if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) + goto retry; /* service start race condition */
servicecountactive = returned;
@@ -1376,9 +1396,11 @@ static void test_enum_svc(void) EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, NULL, 0, &needed, &returned, NULL); services = HeapAlloc(GetProcessHeap(), 0, needed); - EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, services, - needed, &needed, &returned, NULL); + ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, + services, needed, &needed, &returned, NULL); HeapFree(GetProcessHeap(), 0, services); + if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) + goto retry; /* service start race condition */
servicecountinactive = returned;
@@ -1386,13 +1408,18 @@ static void test_enum_svc(void) EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL); services = HeapAlloc(GetProcessHeap(), 0, needed); - EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services, - needed, &needed, &returned, NULL); + ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, + services, needed, &needed, &returned, NULL); HeapFree(GetProcessHeap(), 0, services); + if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) + goto retry; /* service start race condition */
/* Check if total is the same as active and inactive win32 services */ - ok(returned == (servicecountactive + servicecountinactive), - "Something wrong in the calculation\n"); + if (returned != servicecountactive + servicecountinactive && attempt) + goto retry; /* service start|stop race condition */ + ok(returned == servicecountactive + servicecountinactive, + "Expected service count %ld == %ld + %ld\n", + returned, servicecountactive, servicecountinactive);
/* Get all drivers and services * @@ -1404,6 +1431,9 @@ static void test_enum_svc(void) services = HeapAlloc(GetProcessHeap(), 0, needed); ret = EnumServicesStatusA(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, services, needed, &needed, &returned, NULL); + if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) + goto retry; /* service start race condition */ + ok(ret, "Expected success %lu\n", GetLastError());
/* Loop through all those returned drivers and services */ for (i = 0; ret && i < returned; i++) @@ -1447,16 +1477,22 @@ static void test_enum_svc(void) } HeapFree(GetProcessHeap(), 0, services);
+ if ((servicecountactive || servicecountinactive) && attempt) + goto retry; /* service start|stop race condition */ ok(servicecountactive == 0, "Active services mismatch %lu\n", servicecountactive); ok(servicecountinactive == 0, "Inactive services mismatch %lu\n", servicecountinactive);
+ alldone = TRUE; + +retry: CloseServiceHandle(scm_handle); + return alldone; }
-static void test_enum_svc_ex(void) +static BOOL test_enum_svc_ex(int attempt) { SC_HANDLE scm_handle; - BOOL ret; + BOOL ret, alldone = FALSE; DWORD bufsize, needed, returned, resume; DWORD neededW, returnedW; DWORD tempneeded, tempreturned, missing; @@ -1469,7 +1505,7 @@ static void test_enum_svc_ex(void) if (!pEnumServicesStatusExA) { win_skip( "EnumServicesStatusExA not available\n" ); - return; + return TRUE; }
/* All NULL or wrong */ @@ -1636,8 +1672,12 @@ static void test_enum_svc_ex(void) ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &neededW, &returnedW, NULL, NULL); ok(!ret, "Expected failure\n"); - ok(returnedW == 0, "Expected no service returned, got %ld\n", returned); - ok(neededW != 0xdeadbeef && neededW > 0, "Expected the needed buffer size\n"); + ok(GetLastError() == ERROR_MORE_DATA, + "Expected ERROR_MORE_DATA, got %ld\n", GetLastError()); + ok(neededW != 0xdeadbeef && neededW > 0, "Expected the needed buffer size for this one service\n"); + ok(returnedW == 0, "Expected no service returned, got %ld\n", returnedW); + if (neededW != needed && attempt) + goto retry; /* service start|stop race condition */ ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n"); ok(GetLastError() == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %ld\n", GetLastError()); @@ -1652,10 +1692,12 @@ static void test_enum_svc_ex(void) returned = 0xdeadbeef; ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services, needed, &needed, &returned, NULL); + HeapFree(GetProcessHeap(), 0, services); + if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) + goto retry; /* service start race condition */ ok(ret, "Expected success, got error %lu\n", GetLastError()); ok(needed == 0, "Expected needed buffer to be 0 as we are done\n"); ok(returned != 0xdeadbeef && returned > 0, "Expected some returned services\n"); - HeapFree(GetProcessHeap(), 0, services);
/* Store the number of returned services */ tempreturned = returned; @@ -1668,10 +1710,12 @@ static void test_enum_svc_ex(void) SetLastError(0xdeadbeef); ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, (BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL); + HeapFree(GetProcessHeap(), 0, exservices); + if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) + goto retry; /* service start race condition */ ok(ret, "Expected success, got error %lu\n", GetLastError()); ok(needed == 0, "Expected needed buffer to be 0 as we are done\n"); ok(returned == tempreturned, "Expected the same number of service from this function\n"); - HeapFree(GetProcessHeap(), 0, exservices);
/* Store the number of returned services */ tempreturned = returned; @@ -1687,6 +1731,11 @@ static void test_enum_svc_ex(void) SetLastError(0xdeadbeef); ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, (BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL); + if (ret && needed == 0 && attempt) + { + HeapFree(GetProcessHeap(), 0, exservices); + goto retry; /* service stop race condition */ + } ok(!ret, "Expected failure\n"); ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for the missing services\n"); todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n"); @@ -1705,6 +1754,11 @@ static void test_enum_svc_ex(void) SetLastError(0xdeadbeef); ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, (BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL); + if (ret && needed == 0 && attempt) + { + HeapFree(GetProcessHeap(), 0, exservices); + goto retry; /* service stop race condition */ + } ok(!ret, "Expected failure\n"); ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for the missing services\n"); todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n"); @@ -1721,11 +1775,13 @@ static void test_enum_svc_ex(void) SetLastError(0xdeadbeef); ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, (BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL); + HeapFree(GetProcessHeap(), 0, exservices); + if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) + goto retry; /* service start race condition */ ok(ret, "Expected success, got error %lu\n", GetLastError()); ok(needed == 0, "Expected needed buffer to be 0 as we are done\n"); ok(returned == missing, "Expected %lu services to be returned\n", missing); ok(resume == 0, "Expected the resume handle to be 0\n"); - HeapFree(GetProcessHeap(), 0, exservices);
/* See if things add up */
@@ -1733,9 +1789,11 @@ static void test_enum_svc_ex(void) pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0, &needed, &returned, NULL, NULL); exservices = HeapAlloc(GetProcessHeap(), 0, needed); - pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE, - (BYTE*)exservices, needed, &needed, &returned, NULL, NULL); + ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE, + (BYTE*)exservices, needed, &needed, &returned, NULL, NULL); HeapFree(GetProcessHeap(), 0, exservices); + if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) + goto retry; /* service start race condition */
servicecountactive = returned;
@@ -1743,9 +1801,11 @@ static void test_enum_svc_ex(void) pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE, NULL, 0, &needed, &returned, NULL, NULL); exservices = HeapAlloc(GetProcessHeap(), 0, needed); - pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE, - (BYTE*)exservices, needed, &needed, &returned, NULL, NULL); + ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE, + (BYTE*)exservices, needed, &needed, &returned, NULL, NULL); HeapFree(GetProcessHeap(), 0, exservices); + if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) + goto retry; /* service start race condition */
servicecountinactive = returned;
@@ -1753,13 +1813,18 @@ static void test_enum_svc_ex(void) pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL, NULL); exservices = HeapAlloc(GetProcessHeap(), 0, needed); - pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, - (BYTE*)exservices, needed, &needed, &returned, NULL, NULL); + ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, + (BYTE*)exservices, needed, &needed, &returned, NULL, NULL); HeapFree(GetProcessHeap(), 0, exservices); + if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) + goto retry; /* service start race condition */
/* Check if total is the same as active and inactive win32 services */ - ok(returned == (servicecountactive + servicecountinactive), - "Something wrong in the calculation\n"); + if (returned != servicecountactive + servicecountinactive && attempt) + goto retry; /* service start|stop race condition */ + ok(returned == servicecountactive + servicecountinactive, + "Expected service count %ld == %ld + %ld\n", + returned, servicecountactive, servicecountinactive);
/* Get all drivers and services */ ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER, @@ -1768,6 +1833,8 @@ static void test_enum_svc_ex(void) exservices = HeapAlloc(GetProcessHeap(), 0, needed); ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER, SERVICE_STATE_ALL, (BYTE*)exservices, needed, &needed, &returned, NULL, NULL); + if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) + goto retry; /* service start race condition */ ok(ret, "Expected success %lu\n", GetLastError());
/* Loop through all those returned drivers and services */ @@ -1836,10 +1903,16 @@ static void test_enum_svc_ex(void) } HeapFree(GetProcessHeap(), 0, exservices);
+ if ((servicecountactive || servicecountinactive) && attempt) + goto retry; /* service start|stop race condition */ ok(servicecountactive == 0, "Active services mismatch %lu\n", servicecountactive); ok(servicecountinactive == 0, "Inactive services mismatch %lu\n", servicecountinactive);
+ alldone = TRUE; + +retry: CloseServiceHandle(scm_handle); + return alldone; }
static void test_close(void) @@ -2915,6 +2988,7 @@ START_TEST(service) SC_HANDLE scm_handle; int myARGC; char** myARGV; + int attempt;
myARGC = winetest_get_mainargs(&myARGV); GetFullPathNameA(myARGV[0], sizeof(selfname), selfname, NULL); @@ -2945,8 +3019,15 @@ START_TEST(service) test_get_displayname(); test_get_servicekeyname(); test_query_svc(); - test_enum_svc(); - test_enum_svc_ex(); + + /* Services may start or stop between enumeration calls, leading to + * inconsistencies and failures. So we may need a couple attempts. + */ + for (attempt = 2; attempt >= 0; attempt--) + if (test_enum_svc(attempt)) break; + for (attempt = 2; attempt >= 0; attempt--) + if (test_enum_svc_ex(attempt)) break; + test_close(); test_wow64(); /* Test the creation, querying and deletion of a service */
From: Francois Gouget fgouget@codeweavers.com
The ANSI one is broken in some UTF-8 locales which prevents most of the tests from running. So use the Unicode API for most tests and just confirm that it is consistent with the ANSI one instead of doing the reverse.
Wine-Bug: https://bugs.winehq.org//show_bug.cgi?id=52895 --- dlls/advapi32/tests/service.c | 155 ++++++++++++++++++---------------- 1 file changed, 80 insertions(+), 75 deletions(-)
diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index 92b44101a03..c999255fbcc 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -1067,11 +1067,11 @@ static BOOL test_enum_svc(int attempt) SC_HANDLE scm_handle; BOOL ret, alldone = FALSE; DWORD bufsize, needed, returned, resume; - DWORD neededW, returnedW; + DWORD neededA, returnedA; DWORD tempneeded, tempreturned, missing; DWORD servicecountactive, servicecountinactive; - ENUM_SERVICE_STATUSA *services; - ENUM_SERVICE_STATUSW *servicesW; + ENUM_SERVICE_STATUSA *servicesA; + ENUM_SERVICE_STATUSW *services; UINT i;
/* All NULL or wrong */ @@ -1232,7 +1232,7 @@ static BOOL test_enum_svc(int attempt) needed = 0xdeadbeef; returned = 0xdeadbeef; SetLastError(0xdeadbeef); - ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL); + ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL); ok(!ret, "Expected failure\n"); ok(needed == 0 || broken(needed != 0), /* nt4 */ "Expected needed buffer size to be set to 0, got %ld\n", needed); @@ -1249,26 +1249,26 @@ static BOOL test_enum_svc(int attempt) needed = 0xdeadbeef; returned = 0xdeadbeef; SetLastError(0xdeadbeef); - ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL); + ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL); ok(!ret, "Expected failure\n"); ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n"); ok(returned == 0, "Expected no service returned, got %ld\n", returned); ok(GetLastError() == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
- /* Test to show we get the same needed buffer size for the W-call */ - neededW = 0xdeadbeef; - returnedW = 0xdeadbeef; + /* Test to show we get the same needed buffer size for the A-call */ + neededA = 0xdeadbeef; + returnedA = 0xdeadbeef; SetLastError(0xdeadbeef); - ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &neededW, &returnedW, NULL); + ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &neededA, &returnedA, NULL); ok(!ret, "Expected failure\n"); ok(GetLastError() == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %ld\n", GetLastError()); - ok(neededW != 0xdeadbeef && neededW > 0, "Expected the needed buffer size for this one service\n"); - ok(returnedW == 0, "Expected no service returned, got %ld\n", returnedW); - if (neededW != needed && attempt) + ok(neededA != 0xdeadbeef && neededA > 0, "Expected the needed buffer size for this one service\n"); + ok(returnedA == 0, "Expected no service returned, got %ld\n", returnedA); + if (neededA != needed && attempt) goto retry; /* service start|stop race condition */ - ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n"); + ok(neededA == needed, "Expected needed buffersize to be the same for A- and W-calls\n");
/* Store the needed bytes */ tempneeded = needed; @@ -1279,7 +1279,7 @@ static BOOL test_enum_svc(int attempt) needed = 0xdeadbeef; returned = 0xdeadbeef; SetLastError(0xdeadbeef); - ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, + ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services, bufsize, &needed, &returned, NULL); HeapFree(GetProcessHeap(), 0, services); if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) @@ -1291,30 +1291,35 @@ static BOOL test_enum_svc(int attempt) /* Store the number of returned services */ tempreturned = returned;
- servicesW = HeapAlloc(GetProcessHeap(), 0, neededW); - bufsize = neededW; - neededW = 0xdeadbeef; - returnedW = 0xdeadbeef; + servicesA = HeapAlloc(GetProcessHeap(), 0, neededA); + bufsize = neededA; + neededA = 0xdeadbeef; + returnedA = 0xdeadbeef; SetLastError(0xdeadbeef); - ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, - servicesW, bufsize, &neededW, &returnedW, NULL); - HeapFree(GetProcessHeap(), 0, servicesW); + ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, + servicesA, bufsize, &neededA, &returnedA, NULL); + HeapFree(GetProcessHeap(), 0, servicesA); if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) goto retry; /* service start race condition */ - ok(ret, "Expected success, got error %lu\n", GetLastError()); - ok(neededW == 0, "Expected needed buffer to be 0 as we are done\n"); - ok(returnedW != 0xdeadbeef && returnedW > 0, "Expected some returned services\n"); + if (!ret && GetLastError() == ERROR_NOT_ENOUGH_MEMORY && GetACP() == CP_UTF8) + win_skip("Skipping some tests due to EnumServicesStatusA()'s broken UTF-8 support\n"); + else + { + ok(ret, "Expected success, got error %lu\n", GetLastError()); + ok(neededA == 0, "Expected needed buffer to be 0 as we are done\n"); + ok(returnedA != 0xdeadbeef && returnedA > 0, "Expected some returned services\n"); + }
/* Allocate less than the needed bytes and don't specify a resume handle. * More than one service will be missing because of the space needed for * the strings. */ services = HeapAlloc(GetProcessHeap(), 0, tempneeded); - bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA); + bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW); needed = 0xdeadbeef; returned = 0xdeadbeef; SetLastError(0xdeadbeef); - ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, + ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services, bufsize, &needed, &returned, NULL); if (ret && needed == 0 && attempt) { @@ -1332,12 +1337,12 @@ static BOOL test_enum_svc(int attempt) "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
/* Allocate less than the needed bytes, this time with a correct resume handle */ - bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA); + bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW); needed = 0xdeadbeef; returned = 0xdeadbeef; resume = 0; SetLastError(0xdeadbeef); - ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, + ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services, bufsize, &needed, &returned, &resume); if (ret && needed == 0 && attempt) { @@ -1358,7 +1363,7 @@ static BOOL test_enum_svc(int attempt) needed = 0xdeadbeef; returned = 0xdeadbeef; SetLastError(0xdeadbeef); - ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, + ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services, bufsize, &needed, &returned, &resume); HeapFree(GetProcessHeap(), 0, services); if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) @@ -1381,10 +1386,10 @@ static BOOL test_enum_svc(int attempt) */
/* Get the number of active win32 services */ - EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0, + EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0, &needed, &returned, NULL); services = HeapAlloc(GetProcessHeap(), 0, needed); - ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, + ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, services, needed, &needed, &returned, NULL); HeapFree(GetProcessHeap(), 0, services); if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) @@ -1393,10 +1398,10 @@ static BOOL test_enum_svc(int attempt) servicecountactive = returned;
/* Get the number of inactive win32 services */ - EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, NULL, 0, + EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, NULL, 0, &needed, &returned, NULL); services = HeapAlloc(GetProcessHeap(), 0, needed); - ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, + ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, services, needed, &needed, &returned, NULL); HeapFree(GetProcessHeap(), 0, services); if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) @@ -1405,10 +1410,10 @@ static BOOL test_enum_svc(int attempt) servicecountinactive = returned;
/* Get the number of win32 services */ - EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, + EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL); services = HeapAlloc(GetProcessHeap(), 0, needed); - ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, + ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services, needed, &needed, &returned, NULL); HeapFree(GetProcessHeap(), 0, services); if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) @@ -1426,10 +1431,10 @@ static BOOL test_enum_svc(int attempt) * Fetch the status of the last call as failing could make the following tests crash * on Wine (we don't return anything yet). */ - EnumServicesStatusA(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, + EnumServicesStatusW(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL); services = HeapAlloc(GetProcessHeap(), 0, needed); - ret = EnumServicesStatusA(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, + ret = EnumServicesStatusW(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, services, needed, &needed, &returned, NULL); if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) goto retry; /* service start race condition */ @@ -1457,7 +1462,7 @@ static BOOL test_enum_svc(int attempt) case SERVICE_PAUSED: case SERVICE_CONTINUE_PENDING: trace("Got state %lx for service %s\n", status.dwCurrentState, - services[i].lpServiceName); + wine_dbgstr_w(services[i].lpServiceName)); /* fall through */
case SERVICE_RUNNING: @@ -1470,7 +1475,7 @@ static BOOL test_enum_svc(int attempt)
default: ok(0, "Got unknown state %lx for service %s\n", - status.dwCurrentState, services[i].lpServiceName); + status.dwCurrentState, wine_dbgstr_w(services[i].lpServiceName)); break; } } @@ -1494,11 +1499,11 @@ static BOOL test_enum_svc_ex(int attempt) SC_HANDLE scm_handle; BOOL ret, alldone = FALSE; DWORD bufsize, needed, returned, resume; - DWORD neededW, returnedW; + DWORD neededA, returnedA; DWORD tempneeded, tempreturned, missing; DWORD servicecountactive, servicecountinactive; - ENUM_SERVICE_STATUSA *services; - ENUM_SERVICE_STATUS_PROCESSA *exservices; + ENUM_SERVICE_STATUSW *services; + ENUM_SERVICE_STATUS_PROCESSW *exservices; UINT i;
/* More or less the same for EnumServicesStatusExA */ @@ -1641,8 +1646,8 @@ static BOOL test_enum_svc_ex(int attempt) needed = 0xdeadbeef; returned = 0xdeadbeef; SetLastError(0xdeadbeef); - ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, - NULL, 0, &needed, &returned, NULL, "deadbeef_group"); + ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, + NULL, 0, &needed, &returned, NULL, L"deadbeef_group"); ok(!ret, "Expected failure\n"); ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned); ok(needed == 0, "Expected needed buffer size to be set to 0, got %ld\n", needed); @@ -1657,7 +1662,7 @@ static BOOL test_enum_svc_ex(int attempt) needed = 0xdeadbeef; returned = 0xdeadbeef; SetLastError(0xdeadbeef); - ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, + ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL, NULL); ok(!ret, "Expected failure\n"); ok(returned == 0, "Expected no service returned, got %ld\n", returned); @@ -1665,20 +1670,20 @@ static BOOL test_enum_svc_ex(int attempt) ok(GetLastError() == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
- /* Test to show we get the same needed buffer size for the W-call */ - neededW = 0xdeadbeef; - returnedW = 0xdeadbeef; + /* Test to show we get the same needed buffer size for the A-call */ + neededA = 0xdeadbeef; + returnedA = 0xdeadbeef; SetLastError(0xdeadbeef); - ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, - NULL, 0, &neededW, &returnedW, NULL, NULL); + ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, + NULL, 0, &neededA, &returnedA, NULL, NULL); ok(!ret, "Expected failure\n"); ok(GetLastError() == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %ld\n", GetLastError()); - ok(neededW != 0xdeadbeef && neededW > 0, "Expected the needed buffer size for this one service\n"); - ok(returnedW == 0, "Expected no service returned, got %ld\n", returnedW); - if (neededW != needed && attempt) + ok(neededA != 0xdeadbeef && neededA > 0, "Expected the needed buffer size for this one service\n"); + ok(returnedA == 0, "Expected no service returned, got %ld\n", returnedA); + if (neededA != needed && attempt) goto retry; /* service start|stop race condition */ - ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n"); + ok(neededA == needed, "Expected needed buffersize to be the same for A- and W-calls\n"); ok(GetLastError() == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
@@ -1686,11 +1691,11 @@ static BOOL test_enum_svc_ex(int attempt) tempneeded = needed;
/* Show the Ex call returns the same service count as the regular enum */ - EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, + EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL); services = HeapAlloc(GetProcessHeap(), 0, needed); returned = 0xdeadbeef; - ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, + ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services, needed, &needed, &returned, NULL); HeapFree(GetProcessHeap(), 0, services); if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) @@ -1708,7 +1713,7 @@ static BOOL test_enum_svc_ex(int attempt) needed = 0xdeadbeef; returned = 0xdeadbeef; SetLastError(0xdeadbeef); - ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, + ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, (BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL); HeapFree(GetProcessHeap(), 0, exservices); if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) @@ -1725,11 +1730,11 @@ static BOOL test_enum_svc_ex(int attempt) * the strings. */ exservices = HeapAlloc(GetProcessHeap(), 0, tempneeded); - bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA); + bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW); needed = 0xdeadbeef; returned = 0xdeadbeef; SetLastError(0xdeadbeef); - ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, + ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, (BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL); if (ret && needed == 0 && attempt) { @@ -1747,12 +1752,12 @@ static BOOL test_enum_svc_ex(int attempt) "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
/* Allocate less than the needed bytes, this time with a correct resume handle */ - bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA); + bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW); needed = 0xdeadbeef; returned = 0xdeadbeef; resume = 0; SetLastError(0xdeadbeef); - ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, + ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, (BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL); if (ret && needed == 0 && attempt) { @@ -1773,7 +1778,7 @@ static BOOL test_enum_svc_ex(int attempt) needed = 0xdeadbeef; returned = 0xdeadbeef; SetLastError(0xdeadbeef); - ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, + ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, (BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL); HeapFree(GetProcessHeap(), 0, exservices); if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) @@ -1786,10 +1791,10 @@ static BOOL test_enum_svc_ex(int attempt) /* See if things add up */
/* Get the number of active win32 services */ - pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE, + pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0, &needed, &returned, NULL, NULL); exservices = HeapAlloc(GetProcessHeap(), 0, needed); - ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE, + ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE, (BYTE*)exservices, needed, &needed, &returned, NULL, NULL); HeapFree(GetProcessHeap(), 0, exservices); if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) @@ -1798,10 +1803,10 @@ static BOOL test_enum_svc_ex(int attempt) servicecountactive = returned;
/* Get the number of inactive win32 services */ - pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE, + pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE, NULL, 0, &needed, &returned, NULL, NULL); exservices = HeapAlloc(GetProcessHeap(), 0, needed); - ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE, + ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE, (BYTE*)exservices, needed, &needed, &returned, NULL, NULL); HeapFree(GetProcessHeap(), 0, exservices); if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) @@ -1810,10 +1815,10 @@ static BOOL test_enum_svc_ex(int attempt) servicecountinactive = returned;
/* Get the number of win32 services */ - pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, + pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL, NULL); exservices = HeapAlloc(GetProcessHeap(), 0, needed); - ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, + ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, (BYTE*)exservices, needed, &needed, &returned, NULL, NULL); HeapFree(GetProcessHeap(), 0, exservices); if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) @@ -1827,11 +1832,11 @@ static BOOL test_enum_svc_ex(int attempt) returned, servicecountactive, servicecountinactive);
/* Get all drivers and services */ - ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER, + ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL, NULL); ok(!ret, "Expected failure\n"); exservices = HeapAlloc(GetProcessHeap(), 0, needed); - ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER, + ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER, SERVICE_STATE_ALL, (BYTE*)exservices, needed, &needed, &returned, NULL, NULL); if (!ret && GetLastError() == ERROR_MORE_DATA && attempt) goto retry; /* service start race condition */ @@ -1865,7 +1870,7 @@ static BOOL test_enum_svc_ex(int attempt) case SERVICE_STOP_PENDING: trace("Got state %lx (pid=%04lx) for service %s\n", status.dwCurrentState, status.dwProcessId, - exservices[i].lpServiceName); + wine_dbgstr_w(exservices[i].lpServiceName)); /* There may or may not be a process id */ servicecountactive--; break; @@ -1875,20 +1880,20 @@ static BOOL test_enum_svc_ex(int attempt) case SERVICE_CONTINUE_PENDING: trace("Got state %lx (pid=%04lx) for service %s\n", status.dwCurrentState, status.dwProcessId, - exservices[i].lpServiceName); + wine_dbgstr_w(exservices[i].lpServiceName)); /* fall through */
case SERVICE_RUNNING: /* We expect a process id for every running service */ ok(status.dwProcessId > 0, "Expected a process id for this running service (%s)\n", - exservices[i].lpServiceName); + wine_dbgstr_w(exservices[i].lpServiceName)); servicecountactive--; break;
case SERVICE_STOPPED: /* We shouldn't have a process id for inactive services */ ok(status.dwProcessId == 0, "Service %s state %lu shouldn't have an associated process id\n", - exservices[i].lpServiceName, status.dwCurrentState); + wine_dbgstr_w(exservices[i].lpServiceName), status.dwCurrentState);
servicecountinactive--; break; @@ -1896,7 +1901,7 @@ static BOOL test_enum_svc_ex(int attempt) default: ok(0, "Got unknown state %lx (pid=%04lx) for service %s\n", status.dwCurrentState, status.dwProcessId, - exservices[i].lpServiceName); + wine_dbgstr_w(exservices[i].lpServiceName)); break; } }
From: Francois Gouget fgouget@codeweavers.com
advapi32:eventlog crashes the EventLog service in some Windows versions so defend against that condition.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53461 --- Eventually it would be better to modify advapi32:eventlog to avoid crashing the service but that may be hard (and essentially require skipping most of advapi32:eventlog). --- dlls/advapi32/tests/service.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index c999255fbcc..da8495da45f 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -2919,19 +2919,25 @@ static void test_EventLog(void) ok(status.dwServiceType == SERVICE_WIN32_SHARE_PROCESS || status.dwServiceType == (SERVICE_WIN32_SHARE_PROCESS | SERVICE_WIN32_OWN_PROCESS) /* Win10 */, "got %#lx\n", status.dwServiceType); - ok(status.dwCurrentState == SERVICE_RUNNING, "got %#lx\n", status.dwCurrentState); - todo_wine - ok(status.dwControlsAccepted == SERVICE_ACCEPT_SHUTDOWN /* XP */ || - status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN) /* 2008 */ || - status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_TIMECHANGE | SERVICE_ACCEPT_SHUTDOWN), - "got %#lx\n", status.dwControlsAccepted); - ok(status.dwWin32ExitCode == 0, "got %#lx\n", status.dwWin32ExitCode); ok(status.dwServiceSpecificExitCode == 0, "got %#lx\n", status.dwServiceSpecificExitCode); ok(status.dwCheckPoint == 0, "got %#lx\n", status.dwCheckPoint); ok(status.dwWaitHint == 0, "got %#lx\n", status.dwWaitHint); - ok(status.dwProcessId != 0, "got %#lx\n", status.dwProcessId); ok(status.dwServiceFlags == 0 || status.dwServiceFlags == SERVICE_RUNS_IN_SYSTEM_PROCESS /* XP */, "got %#lx\n", status.dwServiceFlags); + if (status.dwCurrentState == SERVICE_STOPPED && + status.dwWin32ExitCode == ERROR_PROCESS_ABORTED) + win_skip("EventLog crashed!\n"); + else + { + ok(status.dwCurrentState == SERVICE_RUNNING, "got %#lx\n", status.dwCurrentState); + todo_wine + ok(status.dwControlsAccepted == SERVICE_ACCEPT_SHUTDOWN /* XP */ || + status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN) /* 2008 */ || + status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_TIMECHANGE | SERVICE_ACCEPT_SHUTDOWN), + "got %#lx\n", status.dwControlsAccepted); + ok(status.dwWin32ExitCode == 0, "got %#lx\n", status.dwWin32ExitCode); + ok(status.dwProcessId != 0, "got %#lx\n", status.dwProcessId); + }
CloseServiceHandle(svc_handle); CloseServiceHandle(scm_handle);