Skip to content

Commit ab243b8

Browse files
SergeGautherielearn-more
authored andcommitted
[ADVAPI32_WINETEST] Restore service.c changes from 3c1b783
This reverts commit a67df65. New failure was fixed by previous SERVICES commit. Thus new timeout is avoided. CORE-14521
1 parent e3a1c2c commit ab243b8

File tree

1 file changed

+172
-33
lines changed

1 file changed

+172
-33
lines changed

modules/rostests/winetests/advapi32/service.c

Lines changed: 172 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ static const CHAR spooler[] = "Spooler"; /* Should be available on all platforms
3636
static CHAR selfname[MAX_PATH];
3737

3838
static BOOL (WINAPI *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID);
39+
static BOOL (WINAPI *pChangeServiceConfig2W)(SC_HANDLE,DWORD,LPVOID);
3940
static BOOL (WINAPI *pEnumServicesStatusExA)(SC_HANDLE, SC_ENUM_TYPE, DWORD,
4041
DWORD, LPBYTE, DWORD, LPDWORD,
4142
LPDWORD, LPDWORD, LPCSTR);
@@ -57,6 +58,7 @@ static void init_function_pointers(void)
5758
HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
5859

5960
pChangeServiceConfig2A = (void*)GetProcAddress(hadvapi32, "ChangeServiceConfig2A");
61+
pChangeServiceConfig2W = (void*)GetProcAddress(hadvapi32, "ChangeServiceConfig2W");
6062
pEnumServicesStatusExA= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExA");
6163
pEnumServicesStatusExW= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExW");
6264
pGetSecurityInfo = (void *)GetProcAddress(hadvapi32, "GetSecurityInfo");
@@ -1954,13 +1956,17 @@ static void test_queryconfig2(void)
19541956
DWORD expected, needed;
19551957
BYTE buffer[MAX_PATH];
19561958
LPSERVICE_DESCRIPTIONA pConfig = (LPSERVICE_DESCRIPTIONA)buffer;
1959+
LPSERVICE_DESCRIPTIONW pConfigW = (LPSERVICE_DESCRIPTIONW)buffer;
19571960
SERVICE_PRESHUTDOWN_INFO preshutdown_info;
19581961
static const CHAR servicename [] = "Winetest";
19591962
static const CHAR displayname [] = "Winetest dummy service";
19601963
static const CHAR pathname [] = "we_dont_care.exe";
19611964
static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
19621965
static const CHAR password [] = "";
19631966
static const CHAR description [] = "Description";
1967+
static const CHAR description_empty[] = "";
1968+
static const WCHAR descriptionW [] = {'D','e','s','c','r','i','p','t','i','o','n','W',0};
1969+
static const WCHAR descriptionW_empty[] = {0};
19641970

19651971
if(!pQueryServiceConfig2A)
19661972
{
@@ -2121,6 +2127,66 @@ static void test_queryconfig2(void)
21212127
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed,&needed);
21222128
ok(ret, "expected QueryServiceConfig2W to succeed\n");
21232129

2130+
pConfig->lpDescription = (LPSTR)description;
2131+
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2132+
ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2133+
2134+
pConfig->lpDescription = NULL;
2135+
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2136+
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2137+
ok(pConfig->lpDescription && !strcmp(description, pConfig->lpDescription),
2138+
"expected lpDescription to be %s, got %s\n", description, pConfig->lpDescription);
2139+
2140+
pConfig->lpDescription = NULL;
2141+
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2142+
ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2143+
2144+
pConfig->lpDescription = NULL;
2145+
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2146+
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2147+
ok(pConfig->lpDescription && !strcmp(description, pConfig->lpDescription),
2148+
"expected lpDescription to be %s, got %s\n", description, pConfig->lpDescription);
2149+
2150+
pConfig->lpDescription = (LPSTR)description_empty;
2151+
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2152+
ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2153+
2154+
pConfig->lpDescription = (void*)0xdeadbeef;
2155+
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2156+
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2157+
ok(!pConfig->lpDescription,
2158+
"expected lpDescription to be null, got %s\n", pConfig->lpDescription);
2159+
2160+
pConfigW->lpDescription = (LPWSTR)descriptionW;
2161+
ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2162+
ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2163+
2164+
pConfigW->lpDescription = NULL;
2165+
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2166+
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2167+
ok(pConfigW->lpDescription && !lstrcmpW(descriptionW, pConfigW->lpDescription),
2168+
"expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW), wine_dbgstr_w(pConfigW->lpDescription));
2169+
2170+
pConfigW->lpDescription = NULL;
2171+
ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2172+
ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2173+
2174+
pConfigW->lpDescription = NULL;
2175+
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2176+
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2177+
ok(pConfigW->lpDescription && !lstrcmpW(descriptionW, pConfigW->lpDescription),
2178+
"expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW), wine_dbgstr_w(pConfigW->lpDescription));
2179+
2180+
pConfigW->lpDescription = (LPWSTR)descriptionW_empty;
2181+
ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2182+
ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2183+
2184+
pConfigW->lpDescription = (void*)0xdeadbeef;
2185+
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2186+
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2187+
ok(!pConfigW->lpDescription,
2188+
"expected lpDescription to be null, got %s\n", wine_dbgstr_w(pConfigW->lpDescription));
2189+
21242190
SetLastError(0xdeadbeef);
21252191
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
21262192
(LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed);
@@ -2200,73 +2266,146 @@ static DWORD try_start_stop(SC_HANDLE svc_handle, const char* name, DWORD is_nt4
22002266
return le1;
22012267
}
22022268

2269+
#define PHASE_STOPPED 1
2270+
#define PHASE_RUNNING 2
2271+
22032272
struct notify_data {
22042273
SERVICE_NOTIFYW notify;
22052274
SC_HANDLE svc;
2275+
BOOL was_called;
2276+
DWORD phase;
22062277
};
22072278

2208-
static void CALLBACK cb_stopped(void *user)
2279+
static void CALLBACK notify_cb(void *user)
22092280
{
22102281
struct notify_data *data = user;
2211-
BOOL br;
2282+
switch (data->phase)
2283+
{
2284+
case PHASE_STOPPED:
2285+
ok(data->notify.dwNotificationStatus == ERROR_SUCCESS,
2286+
"Got wrong notification status: %u\n", data->notify.dwNotificationStatus);
2287+
ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_STOPPED,
2288+
"Got wrong service state: 0x%x\n", data->notify.ServiceStatus.dwCurrentState);
2289+
ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_STOPPED,
2290+
"Got wrong notification triggered: 0x%x\n", data->notify.dwNotificationTriggered);
2291+
break;
22122292

2213-
ok(data->notify.dwNotificationStatus == ERROR_SUCCESS,
2214-
"Got wrong notification status: %u\n", data->notify.dwNotificationStatus);
2215-
ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_STOPPED,
2216-
"Got wrong service state: 0x%x\n", data->notify.ServiceStatus.dwCurrentState);
2217-
ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_STOPPED,
2218-
"Got wrong notification triggered: 0x%x\n", data->notify.dwNotificationTriggered);
2293+
case PHASE_RUNNING:
2294+
ok(data->notify.dwNotificationStatus == ERROR_SUCCESS,
2295+
"Got wrong notification status: %u\n", data->notify.dwNotificationStatus);
2296+
ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_RUNNING,
2297+
"Got wrong service state: 0x%x\n", data->notify.ServiceStatus.dwCurrentState);
2298+
ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_RUNNING,
2299+
"Got wrong notification triggered: 0x%x\n", data->notify.dwNotificationTriggered);
2300+
break;
2301+
}
22192302

2220-
br = StartServiceA(data->svc, 0, NULL);
2221-
ok(br, "StartService failed: %u\n", GetLastError());
2303+
data->was_called = TRUE;
22222304
}
22232305

2224-
static void CALLBACK cb_running(void *user)
2306+
static void test_servicenotify(SC_HANDLE scm_handle, const char *servicename)
22252307
{
2226-
struct notify_data *data = user;
2308+
DWORD dr, dr2;
2309+
struct notify_data data;
2310+
struct notify_data data2;
22272311
BOOL br;
22282312
SERVICE_STATUS status;
2229-
2230-
ok(data->notify.dwNotificationStatus == ERROR_SUCCESS,
2231-
"Got wrong notification status: %u\n", data->notify.dwNotificationStatus);
2232-
ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_RUNNING,
2233-
"Got wrong service state: 0x%x\n", data->notify.ServiceStatus.dwCurrentState);
2234-
ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_RUNNING,
2235-
"Got wrong notification triggered: 0x%x\n", data->notify.dwNotificationTriggered);
2236-
2237-
br = ControlService(data->svc, SERVICE_CONTROL_STOP, &status);
2238-
ok(br, "ControlService failed: %u\n", GetLastError());
2239-
}
2240-
2241-
static void test_servicenotify(SC_HANDLE svc)
2242-
{
2243-
DWORD dr;
2244-
struct notify_data data;
2313+
HANDLE svc, svc2;
22452314

22462315
if(!pNotifyServiceStatusChangeW){
22472316
win_skip("No NotifyServiceStatusChangeW\n");
22482317
return;
22492318
}
22502319

2320+
svc = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2321+
svc2 = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2322+
ok(svc != NULL && svc2 != NULL, "Failed to open service\n");
2323+
if(!svc || !svc2)
2324+
return;
2325+
2326+
/* receive stopped notification, then start service */
22512327
memset(&data.notify, 0, sizeof(data.notify));
22522328
data.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2253-
data.notify.pfnNotifyCallback = &cb_stopped;
2329+
data.notify.pfnNotifyCallback = &notify_cb;
22542330
data.notify.pContext = &data;
22552331
data.svc = svc;
2332+
data.phase = PHASE_STOPPED;
2333+
data.was_called = FALSE;
2334+
2335+
dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2336+
ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr);
2337+
2338+
dr = SleepEx(100, TRUE);
2339+
ok(dr == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %u\n", dr);
2340+
ok(data.was_called == TRUE, "APC wasn't called\n");
2341+
2342+
br = StartServiceA(svc, 0, NULL);
2343+
ok(br, "StartService failed: %u\n", GetLastError());
2344+
2345+
/* receive running notification */
2346+
data.phase = PHASE_RUNNING;
2347+
data.was_called = FALSE;
2348+
2349+
dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2350+
ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr);
2351+
2352+
dr = SleepEx(100, TRUE);
2353+
ok(dr == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %u\n", dr);
2354+
ok(data.was_called == TRUE, "APC wasn't called\n");
2355+
2356+
/* cannot register two notifications */
2357+
data.phase = PHASE_STOPPED;
2358+
data.was_called = FALSE;
22562359

22572360
dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
22582361
ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr);
22592362

2363+
memset(&data2.notify, 0, sizeof(data2.notify));
2364+
data2.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2365+
data2.notify.pfnNotifyCallback = &notify_cb;
2366+
data2.notify.pContext = &data2;
2367+
2368+
dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data2.notify);
2369+
ok(dr == ERROR_SUCCESS || /* win8+ */
2370+
dr == ERROR_ALREADY_REGISTERED, "NotifyServiceStatusChangeW gave wrong result: %u\n", dr);
2371+
2372+
/* should receive no notification because status has not changed.
2373+
* on win8+, SleepEx quits early but the callback is still not invoked. */
2374+
dr2 = SleepEx(100, TRUE);
2375+
ok((dr == ERROR_SUCCESS && dr2 == WAIT_IO_COMPLETION) || /* win8+ */
2376+
(dr == ERROR_ALREADY_REGISTERED && dr2 == 0), "Got wrong SleepEx result: %u\n", dr);
2377+
ok(data.was_called == FALSE, "APC should not have been called\n");
2378+
2379+
/* stop service and receive notifiction */
2380+
br = ControlService(svc, SERVICE_CONTROL_STOP, &status);
2381+
ok(br, "ControlService failed: %u\n", GetLastError());
2382+
22602383
dr = SleepEx(100, TRUE);
2261-
ok(dr == WAIT_IO_COMPLETION, "APC wasn't called\n");
2384+
ok(dr == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %u\n", dr);
2385+
ok(data.was_called == TRUE, "APC wasn't called\n");
22622386

2263-
data.notify.pfnNotifyCallback = &cb_running;
2387+
/* test cancelation: create notify on svc that will block until service
2388+
* start; close svc; start service on svc2; verify that notification does
2389+
* not happen */
22642390

2391+
data.phase = PHASE_RUNNING;
2392+
data.was_called = FALSE;
22652393
dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
22662394
ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr);
22672395

2396+
CloseServiceHandle(svc);
2397+
2398+
br = StartServiceA(svc2, 0, NULL);
2399+
ok(br, "StartService failed: %u\n", GetLastError());
2400+
22682401
dr = SleepEx(100, TRUE);
2269-
ok(dr == WAIT_IO_COMPLETION, "APC wasn't called\n");
2402+
ok(dr == 0, "Got wrong SleepEx result: %u\n", dr);
2403+
ok(data.was_called == FALSE, "APC should not have been called\n");
2404+
2405+
br = ControlService(svc2, SERVICE_CONTROL_STOP, &status);
2406+
ok(br, "ControlService failed: %u\n", GetLastError());
2407+
2408+
CloseServiceHandle(svc2);
22702409
}
22712410

22722411
static void test_start_stop(void)
@@ -2352,7 +2491,7 @@ static void test_start_stop(void)
23522491
displayname = "Winetest Service";
23532492
ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, cmd, NULL, NULL, NULL, NULL, NULL, displayname);
23542493
ok(ret, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2355-
test_servicenotify(svc_handle);
2494+
test_servicenotify(scm_handle, servicename);
23562495

23572496
cleanup:
23582497
if (svc_handle)

0 commit comments

Comments
 (0)