1abb6fd83SPierre Schweitzer /*
2abb6fd83SPierre Schweitzer * PROJECT: ReactOS api tests
3abb6fd83SPierre Schweitzer * LICENSE: GPLv2+ - See COPYING in the top level directory
4abb6fd83SPierre Schweitzer * PURPOSE: Test for service networking
5abb6fd83SPierre Schweitzer * PROGRAMMER: Pierre Schweitzer
6abb6fd83SPierre Schweitzer */
7abb6fd83SPierre Schweitzer
8abb6fd83SPierre Schweitzer #include "precomp.h"
9abb6fd83SPierre Schweitzer
10abb6fd83SPierre Schweitzer #include "svchlp.h"
11abb6fd83SPierre Schweitzer
12abb6fd83SPierre Schweitzer #define WIN32_NO_STATUS
13abb6fd83SPierre Schweitzer #include <iphlpapi.h>
14abb6fd83SPierre Schweitzer #include <winsock2.h>
15abb6fd83SPierre Schweitzer
16abb6fd83SPierre Schweitzer /*** Service part of the test ***/
17abb6fd83SPierre Schweitzer
18abb6fd83SPierre Schweitzer static SERVICE_STATUS_HANDLE status_handle;
19abb6fd83SPierre Schweitzer
20abb6fd83SPierre Schweitzer static void
report_service_status(DWORD dwCurrentState,DWORD dwWin32ExitCode,DWORD dwWaitHint)21abb6fd83SPierre Schweitzer report_service_status(DWORD dwCurrentState,
22abb6fd83SPierre Schweitzer DWORD dwWin32ExitCode,
23abb6fd83SPierre Schweitzer DWORD dwWaitHint)
24abb6fd83SPierre Schweitzer {
25abb6fd83SPierre Schweitzer BOOL res;
26abb6fd83SPierre Schweitzer SERVICE_STATUS status;
27abb6fd83SPierre Schweitzer
28abb6fd83SPierre Schweitzer status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
29abb6fd83SPierre Schweitzer status.dwCurrentState = dwCurrentState;
30abb6fd83SPierre Schweitzer status.dwWin32ExitCode = dwWin32ExitCode;
31abb6fd83SPierre Schweitzer status.dwWaitHint = dwWaitHint;
32abb6fd83SPierre Schweitzer
33abb6fd83SPierre Schweitzer status.dwServiceSpecificExitCode = 0;
34abb6fd83SPierre Schweitzer status.dwCheckPoint = 0;
35abb6fd83SPierre Schweitzer
36abb6fd83SPierre Schweitzer if ( (dwCurrentState == SERVICE_START_PENDING) ||
37abb6fd83SPierre Schweitzer (dwCurrentState == SERVICE_STOP_PENDING) ||
38abb6fd83SPierre Schweitzer (dwCurrentState == SERVICE_STOPPED) )
39abb6fd83SPierre Schweitzer {
40abb6fd83SPierre Schweitzer status.dwControlsAccepted = 0;
41abb6fd83SPierre Schweitzer }
42abb6fd83SPierre Schweitzer else
43abb6fd83SPierre Schweitzer {
44abb6fd83SPierre Schweitzer status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
45abb6fd83SPierre Schweitzer }
46abb6fd83SPierre Schweitzer
47abb6fd83SPierre Schweitzer #if 0
48abb6fd83SPierre Schweitzer if ( (dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED) )
49abb6fd83SPierre Schweitzer status.dwCheckPoint = 0;
50abb6fd83SPierre Schweitzer else
51abb6fd83SPierre Schweitzer status.dwCheckPoint = dwCheckPoint++;
52abb6fd83SPierre Schweitzer #endif
53abb6fd83SPierre Schweitzer
54abb6fd83SPierre Schweitzer res = SetServiceStatus(status_handle, &status);
55abb6fd83SPierre Schweitzer service_ok(res, "SetServiceStatus(%d) failed: %lu\n", dwCurrentState, GetLastError());
56abb6fd83SPierre Schweitzer }
57abb6fd83SPierre Schweitzer
service_handler(DWORD ctrl)58abb6fd83SPierre Schweitzer static VOID WINAPI service_handler(DWORD ctrl)
59abb6fd83SPierre Schweitzer {
60abb6fd83SPierre Schweitzer switch(ctrl)
61abb6fd83SPierre Schweitzer {
62abb6fd83SPierre Schweitzer case SERVICE_CONTROL_STOP:
63abb6fd83SPierre Schweitzer case SERVICE_CONTROL_SHUTDOWN:
64abb6fd83SPierre Schweitzer report_service_status(SERVICE_STOP_PENDING, NO_ERROR, 0);
65abb6fd83SPierre Schweitzer default:
66abb6fd83SPierre Schweitzer report_service_status(SERVICE_RUNNING, NO_ERROR, 0);
67abb6fd83SPierre Schweitzer }
68abb6fd83SPierre Schweitzer }
69abb6fd83SPierre Schweitzer
GetExtendedTcpTableWithAlloc(PVOID * TcpTable,BOOL Order,DWORD Family,TCP_TABLE_CLASS Class)70abb6fd83SPierre Schweitzer static DWORD GetExtendedTcpTableWithAlloc(PVOID *TcpTable, BOOL Order, DWORD Family, TCP_TABLE_CLASS Class)
71abb6fd83SPierre Schweitzer {
72abb6fd83SPierre Schweitzer DWORD ret;
73abb6fd83SPierre Schweitzer DWORD Size = 0;
74abb6fd83SPierre Schweitzer
75abb6fd83SPierre Schweitzer *TcpTable = NULL;
76abb6fd83SPierre Schweitzer
77abb6fd83SPierre Schweitzer ret = GetExtendedTcpTable(*TcpTable, &Size, Order, Family, Class, 0);
78abb6fd83SPierre Schweitzer if (ret == ERROR_INSUFFICIENT_BUFFER)
79abb6fd83SPierre Schweitzer {
80abb6fd83SPierre Schweitzer *TcpTable = HeapAlloc(GetProcessHeap(), 0, Size);
81abb6fd83SPierre Schweitzer if (*TcpTable == NULL)
82abb6fd83SPierre Schweitzer {
83abb6fd83SPierre Schweitzer return ERROR_OUTOFMEMORY;
84abb6fd83SPierre Schweitzer }
85abb6fd83SPierre Schweitzer
86abb6fd83SPierre Schweitzer ret = GetExtendedTcpTable(*TcpTable, &Size, Order, Family, Class, 0);
87abb6fd83SPierre Schweitzer if (ret != NO_ERROR)
88abb6fd83SPierre Schweitzer {
89abb6fd83SPierre Schweitzer HeapFree(GetProcessHeap(), 0, *TcpTable);
90abb6fd83SPierre Schweitzer *TcpTable = NULL;
91abb6fd83SPierre Schweitzer }
92abb6fd83SPierre Schweitzer }
93abb6fd83SPierre Schweitzer
94abb6fd83SPierre Schweitzer return ret;
95abb6fd83SPierre Schweitzer }
96abb6fd83SPierre Schweitzer
GetExtendedUdpTableWithAlloc(PVOID * UdpTable,BOOL Order,DWORD Family,UDP_TABLE_CLASS Class)97abb6fd83SPierre Schweitzer static DWORD GetExtendedUdpTableWithAlloc(PVOID *UdpTable, BOOL Order, DWORD Family, UDP_TABLE_CLASS Class)
98abb6fd83SPierre Schweitzer {
99abb6fd83SPierre Schweitzer DWORD ret;
100abb6fd83SPierre Schweitzer DWORD Size = 0;
101abb6fd83SPierre Schweitzer
102abb6fd83SPierre Schweitzer *UdpTable = NULL;
103abb6fd83SPierre Schweitzer
104abb6fd83SPierre Schweitzer ret = GetExtendedUdpTable(*UdpTable, &Size, Order, Family, Class, 0);
105abb6fd83SPierre Schweitzer if (ret == ERROR_INSUFFICIENT_BUFFER)
106abb6fd83SPierre Schweitzer {
107abb6fd83SPierre Schweitzer *UdpTable = HeapAlloc(GetProcessHeap(), 0, Size);
108abb6fd83SPierre Schweitzer if (*UdpTable == NULL)
109abb6fd83SPierre Schweitzer {
110abb6fd83SPierre Schweitzer return ERROR_OUTOFMEMORY;
111abb6fd83SPierre Schweitzer }
112abb6fd83SPierre Schweitzer
113abb6fd83SPierre Schweitzer ret = GetExtendedUdpTable(*UdpTable, &Size, Order, Family, Class, 0);
114abb6fd83SPierre Schweitzer if (ret != NO_ERROR)
115abb6fd83SPierre Schweitzer {
116abb6fd83SPierre Schweitzer HeapFree(GetProcessHeap(), 0, *UdpTable);
117abb6fd83SPierre Schweitzer *UdpTable = NULL;
118abb6fd83SPierre Schweitzer }
119abb6fd83SPierre Schweitzer }
120abb6fd83SPierre Schweitzer
121abb6fd83SPierre Schweitzer return ret;
122abb6fd83SPierre Schweitzer }
123abb6fd83SPierre Schweitzer
124abb6fd83SPierre Schweitzer static void
test_tcp(LPWSTR svc_name,DWORD service_tag)125abb6fd83SPierre Schweitzer test_tcp(LPWSTR svc_name, DWORD service_tag)
126abb6fd83SPierre Schweitzer {
127abb6fd83SPierre Schweitzer SOCKET sock;
128abb6fd83SPierre Schweitzer SOCKADDR_IN server;
129abb6fd83SPierre Schweitzer PMIB_TCPTABLE_OWNER_MODULE TcpTableOwnerMod;
130abb6fd83SPierre Schweitzer DWORD i, ret;
131abb6fd83SPierre Schweitzer BOOLEAN Found;
132abb6fd83SPierre Schweitzer DWORD Pid = GetCurrentProcessId();
133abb6fd83SPierre Schweitzer
134abb6fd83SPierre Schweitzer sock = socket(AF_INET, SOCK_STREAM, 0);
135abb6fd83SPierre Schweitzer service_ok(sock != INVALID_SOCKET, "Socket creation failed!\n");
136abb6fd83SPierre Schweitzer
137abb6fd83SPierre Schweitzer ZeroMemory(&server, sizeof(SOCKADDR_IN));
138abb6fd83SPierre Schweitzer server.sin_family = AF_INET;
139abb6fd83SPierre Schweitzer server.sin_addr.s_addr = htonl(INADDR_ANY);
140abb6fd83SPierre Schweitzer server.sin_port = htons(9876);
141abb6fd83SPierre Schweitzer
142abb6fd83SPierre Schweitzer ret = bind(sock, (SOCKADDR*)&server, sizeof(SOCKADDR_IN));
143abb6fd83SPierre Schweitzer service_ok(ret != SOCKET_ERROR, "binding failed\n");
144abb6fd83SPierre Schweitzer
145abb6fd83SPierre Schweitzer ret = listen(sock, SOMAXCONN);
146abb6fd83SPierre Schweitzer service_ok(ret != SOCKET_ERROR, "listening failed\n");
147abb6fd83SPierre Schweitzer
148abb6fd83SPierre Schweitzer ret = GetExtendedTcpTableWithAlloc((PVOID *)&TcpTableOwnerMod, TRUE, AF_INET, TCP_TABLE_OWNER_MODULE_LISTENER);
149abb6fd83SPierre Schweitzer service_ok(ret == ERROR_SUCCESS, "GetExtendedTcpTableWithAlloc failed: %x\n", ret);
150abb6fd83SPierre Schweitzer if (ret == ERROR_SUCCESS)
151abb6fd83SPierre Schweitzer {
152abb6fd83SPierre Schweitzer service_ok(TcpTableOwnerMod->dwNumEntries > 0, "No TCP connections?!\n");
153abb6fd83SPierre Schweitzer
154abb6fd83SPierre Schweitzer Found = FALSE;
155abb6fd83SPierre Schweitzer for (i = 0; i < TcpTableOwnerMod->dwNumEntries; ++i)
156abb6fd83SPierre Schweitzer {
157abb6fd83SPierre Schweitzer if (TcpTableOwnerMod->table[i].dwState == MIB_TCP_STATE_LISTEN &&
158abb6fd83SPierre Schweitzer TcpTableOwnerMod->table[i].dwLocalAddr == 0 &&
159abb6fd83SPierre Schweitzer TcpTableOwnerMod->table[i].dwLocalPort == htons(9876) &&
160abb6fd83SPierre Schweitzer TcpTableOwnerMod->table[i].dwRemoteAddr == 0)
161abb6fd83SPierre Schweitzer {
162abb6fd83SPierre Schweitzer Found = TRUE;
163abb6fd83SPierre Schweitzer break;
164abb6fd83SPierre Schweitzer }
165abb6fd83SPierre Schweitzer }
166abb6fd83SPierre Schweitzer
167abb6fd83SPierre Schweitzer service_ok(Found, "Our socket wasn't found!\n");
168abb6fd83SPierre Schweitzer if (Found)
169abb6fd83SPierre Schweitzer {
170abb6fd83SPierre Schweitzer DWORD Size = 0;
171abb6fd83SPierre Schweitzer PTCPIP_OWNER_MODULE_BASIC_INFO BasicInfo = NULL;
172abb6fd83SPierre Schweitzer
173abb6fd83SPierre Schweitzer service_ok(TcpTableOwnerMod->table[i].dwOwningPid == Pid, "Invalid owner\n");
174abb6fd83SPierre Schweitzer service_ok((DWORD)(TcpTableOwnerMod->table[i].OwningModuleInfo[0]) == service_tag, "Invalid tag: %x - %x\n", (DWORD)TcpTableOwnerMod->table[i].OwningModuleInfo[0], service_tag);
175abb6fd83SPierre Schweitzer
176abb6fd83SPierre Schweitzer ret = GetOwnerModuleFromTcpEntry(&TcpTableOwnerMod->table[i], TCPIP_OWNER_MODULE_INFO_BASIC, BasicInfo, &Size);
177abb6fd83SPierre Schweitzer service_ok(ret == ERROR_INSUFFICIENT_BUFFER, "GetOwnerModuleFromTcpEntry failed with: %x\n", ret);
178abb6fd83SPierre Schweitzer if (ERROR_INSUFFICIENT_BUFFER == ERROR_INSUFFICIENT_BUFFER)
179abb6fd83SPierre Schweitzer {
180abb6fd83SPierre Schweitzer BasicInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
181abb6fd83SPierre Schweitzer service_ok(BasicInfo != NULL, "HeapAlloc failed\n");
182abb6fd83SPierre Schweitzer
183abb6fd83SPierre Schweitzer ret = GetOwnerModuleFromTcpEntry(&TcpTableOwnerMod->table[i], TCPIP_OWNER_MODULE_INFO_BASIC, BasicInfo, &Size);
184abb6fd83SPierre Schweitzer service_ok(ret == ERROR_SUCCESS, "GetOwnerModuleFromTcpEntry failed with: %x\n", ret);
185abb6fd83SPierre Schweitzer service_ok(_wcsicmp(svc_name, BasicInfo->pModulePath) == 0, "Mismatching names (%S, %S)\n", svc_name, BasicInfo->pModulePath);
186abb6fd83SPierre Schweitzer service_ok(_wcsicmp(svc_name, BasicInfo->pModuleName) == 0, "Mismatching names (%S, %S)\n", svc_name, BasicInfo->pModuleName);
187abb6fd83SPierre Schweitzer }
188abb6fd83SPierre Schweitzer }
189abb6fd83SPierre Schweitzer
190abb6fd83SPierre Schweitzer HeapFree(GetProcessHeap(), 0, TcpTableOwnerMod);
191abb6fd83SPierre Schweitzer }
192abb6fd83SPierre Schweitzer
193abb6fd83SPierre Schweitzer closesocket(sock);
194abb6fd83SPierre Schweitzer }
195abb6fd83SPierre Schweitzer
196abb6fd83SPierre Schweitzer static void
test_udp(LPWSTR svc_name,DWORD service_tag)197abb6fd83SPierre Schweitzer test_udp(LPWSTR svc_name, DWORD service_tag)
198abb6fd83SPierre Schweitzer {
199abb6fd83SPierre Schweitzer SOCKET sock;
200abb6fd83SPierre Schweitzer SOCKADDR_IN server;
201abb6fd83SPierre Schweitzer PMIB_UDPTABLE_OWNER_MODULE UdpTableOwnerMod;
202abb6fd83SPierre Schweitzer DWORD i, ret;
203abb6fd83SPierre Schweitzer BOOLEAN Found;
204abb6fd83SPierre Schweitzer DWORD Pid = GetCurrentProcessId();
205abb6fd83SPierre Schweitzer
206abb6fd83SPierre Schweitzer sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
207abb6fd83SPierre Schweitzer service_ok(sock != INVALID_SOCKET, "Socket creation failed!\n");
208abb6fd83SPierre Schweitzer
209abb6fd83SPierre Schweitzer ZeroMemory(&server, sizeof(SOCKADDR_IN));
210abb6fd83SPierre Schweitzer server.sin_family = AF_INET;
211abb6fd83SPierre Schweitzer server.sin_addr.s_addr = htonl(INADDR_ANY);
212abb6fd83SPierre Schweitzer server.sin_port = htons(9876);
213abb6fd83SPierre Schweitzer
214abb6fd83SPierre Schweitzer ret = bind(sock, (SOCKADDR*)&server, sizeof(SOCKADDR_IN));
215abb6fd83SPierre Schweitzer service_ok(ret != SOCKET_ERROR, "binding failed\n");
216abb6fd83SPierre Schweitzer
217abb6fd83SPierre Schweitzer ret = GetExtendedUdpTableWithAlloc((PVOID *)&UdpTableOwnerMod, TRUE, AF_INET, UDP_TABLE_OWNER_MODULE);
218abb6fd83SPierre Schweitzer service_ok(ret == ERROR_SUCCESS, "GetExtendedUdpTableWithAlloc failed: %x\n", ret);
219abb6fd83SPierre Schweitzer if (ret == ERROR_SUCCESS)
220abb6fd83SPierre Schweitzer {
221abb6fd83SPierre Schweitzer service_ok(UdpTableOwnerMod->dwNumEntries > 0, "No TCP connections?!\n");
222abb6fd83SPierre Schweitzer
223abb6fd83SPierre Schweitzer Found = FALSE;
224abb6fd83SPierre Schweitzer for (i = 0; i < UdpTableOwnerMod->dwNumEntries; ++i)
225abb6fd83SPierre Schweitzer {
226abb6fd83SPierre Schweitzer if (UdpTableOwnerMod->table[i].dwLocalAddr == 0 &&
227abb6fd83SPierre Schweitzer UdpTableOwnerMod->table[i].dwLocalPort == htons(9876))
228abb6fd83SPierre Schweitzer {
229abb6fd83SPierre Schweitzer Found = TRUE;
230abb6fd83SPierre Schweitzer break;
231abb6fd83SPierre Schweitzer }
232abb6fd83SPierre Schweitzer }
233abb6fd83SPierre Schweitzer
234abb6fd83SPierre Schweitzer service_ok(Found, "Our socket wasn't found!\n");
235abb6fd83SPierre Schweitzer if (Found)
236abb6fd83SPierre Schweitzer {
237abb6fd83SPierre Schweitzer DWORD Size = 0;
238abb6fd83SPierre Schweitzer PTCPIP_OWNER_MODULE_BASIC_INFO BasicInfo = NULL;
239abb6fd83SPierre Schweitzer
240abb6fd83SPierre Schweitzer service_ok(UdpTableOwnerMod->table[i].dwOwningPid == Pid, "Invalid owner\n");
241abb6fd83SPierre Schweitzer service_ok((DWORD)(UdpTableOwnerMod->table[i].OwningModuleInfo[0]) == service_tag, "Invalid tag: %x - %x\n", (DWORD)UdpTableOwnerMod->table[i].OwningModuleInfo[0], service_tag);
242abb6fd83SPierre Schweitzer
243abb6fd83SPierre Schweitzer ret = GetOwnerModuleFromUdpEntry(&UdpTableOwnerMod->table[i], TCPIP_OWNER_MODULE_INFO_BASIC, BasicInfo, &Size);
244abb6fd83SPierre Schweitzer service_ok(ret == ERROR_INSUFFICIENT_BUFFER, "GetOwnerModuleFromUdpEntry failed with: %x\n", ret);
245abb6fd83SPierre Schweitzer if (ret == ERROR_INSUFFICIENT_BUFFER)
246abb6fd83SPierre Schweitzer {
247abb6fd83SPierre Schweitzer BasicInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
248abb6fd83SPierre Schweitzer service_ok(BasicInfo != NULL, "HeapAlloc failed\n");
249abb6fd83SPierre Schweitzer
250abb6fd83SPierre Schweitzer ret = GetOwnerModuleFromUdpEntry(&UdpTableOwnerMod->table[i], TCPIP_OWNER_MODULE_INFO_BASIC, BasicInfo, &Size);
251abb6fd83SPierre Schweitzer service_ok(ret == ERROR_SUCCESS, "GetOwnerModuleFromUdpEntry failed with: %x\n", ret);
252abb6fd83SPierre Schweitzer service_ok(_wcsicmp(svc_name, BasicInfo->pModulePath) == 0, "Mismatching names (%S, %S)\n", svc_name, BasicInfo->pModulePath);
253abb6fd83SPierre Schweitzer service_ok(_wcsicmp(svc_name, BasicInfo->pModuleName) == 0, "Mismatching names (%S, %S)\n", svc_name, BasicInfo->pModuleName);
254abb6fd83SPierre Schweitzer }
255abb6fd83SPierre Schweitzer }
256abb6fd83SPierre Schweitzer
257abb6fd83SPierre Schweitzer HeapFree(GetProcessHeap(), 0, UdpTableOwnerMod);
258abb6fd83SPierre Schweitzer }
259abb6fd83SPierre Schweitzer
260abb6fd83SPierre Schweitzer closesocket(sock);
261abb6fd83SPierre Schweitzer }
262abb6fd83SPierre Schweitzer
263abb6fd83SPierre Schweitzer static void WINAPI
service_main(DWORD dwArgc,LPWSTR * lpszArgv)264abb6fd83SPierre Schweitzer service_main(DWORD dwArgc, LPWSTR* lpszArgv)
265abb6fd83SPierre Schweitzer {
266abb6fd83SPierre Schweitzer // SERVICE_STATUS_HANDLE status_handle;
267abb6fd83SPierre Schweitzer PTEB Teb;
268abb6fd83SPierre Schweitzer WSADATA wsaData;
269abb6fd83SPierre Schweitzer
270abb6fd83SPierre Schweitzer UNREFERENCED_PARAMETER(dwArgc);
271abb6fd83SPierre Schweitzer
272abb6fd83SPierre Schweitzer /* Register our service for control (lpszArgv[0] holds the service name) */
273abb6fd83SPierre Schweitzer status_handle = RegisterServiceCtrlHandlerW(lpszArgv[0], service_handler);
274abb6fd83SPierre Schweitzer service_ok(status_handle != NULL, "RegisterServiceCtrlHandler failed: %lu\n", GetLastError());
275abb6fd83SPierre Schweitzer if (!status_handle)
276abb6fd83SPierre Schweitzer return;
277abb6fd83SPierre Schweitzer
278abb6fd83SPierre Schweitzer /* Report SERVICE_RUNNING status */
279abb6fd83SPierre Schweitzer report_service_status(SERVICE_RUNNING, NO_ERROR, 4000);
280abb6fd83SPierre Schweitzer
281abb6fd83SPierre Schweitzer /* Check our tag is not 0 */
282abb6fd83SPierre Schweitzer Teb = NtCurrentTeb();
283abb6fd83SPierre Schweitzer service_ok(Teb->SubProcessTag != 0, "SubProcessTag is not defined!\n");
284abb6fd83SPierre Schweitzer
285abb6fd83SPierre Schweitzer if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
286abb6fd83SPierre Schweitzer {
287abb6fd83SPierre Schweitzer skip("Failed to init WS2\n");
288abb6fd83SPierre Schweitzer goto quit;
289abb6fd83SPierre Schweitzer }
290abb6fd83SPierre Schweitzer
291*bb9a5f60STimo Kreuzer test_tcp(lpszArgv[0], PtrToUlong(Teb->SubProcessTag));
292*bb9a5f60STimo Kreuzer test_udp(lpszArgv[0], PtrToUlong(Teb->SubProcessTag));
293abb6fd83SPierre Schweitzer
294abb6fd83SPierre Schweitzer WSACleanup();
295abb6fd83SPierre Schweitzer quit:
296abb6fd83SPierre Schweitzer /* Work is done */
297abb6fd83SPierre Schweitzer report_service_status(SERVICE_STOPPED, NO_ERROR, 0);
298abb6fd83SPierre Schweitzer }
299abb6fd83SPierre Schweitzer
start_service(PCSTR service_nameA,PCWSTR service_nameW)300abb6fd83SPierre Schweitzer static BOOL start_service(PCSTR service_nameA, PCWSTR service_nameW)
301abb6fd83SPierre Schweitzer {
302abb6fd83SPierre Schweitzer BOOL res;
303abb6fd83SPierre Schweitzer
304abb6fd83SPierre Schweitzer SERVICE_TABLE_ENTRYW servtbl[] =
305abb6fd83SPierre Schweitzer {
306abb6fd83SPierre Schweitzer { (PWSTR)service_nameW, service_main },
307abb6fd83SPierre Schweitzer { NULL, NULL }
308abb6fd83SPierre Schweitzer };
309abb6fd83SPierre Schweitzer
310abb6fd83SPierre Schweitzer res = StartServiceCtrlDispatcherW(servtbl);
311abb6fd83SPierre Schweitzer service_ok(res, "StartServiceCtrlDispatcherW failed: %lu\n", GetLastError());
312abb6fd83SPierre Schweitzer return res;
313abb6fd83SPierre Schweitzer }
314abb6fd83SPierre Schweitzer
315abb6fd83SPierre Schweitzer
316abb6fd83SPierre Schweitzer /*** Tester part of the test ***/
317abb6fd83SPierre Schweitzer
318abb6fd83SPierre Schweitzer static void
my_test_server(PCSTR service_nameA,PCWSTR service_nameW,void * param)319abb6fd83SPierre Schweitzer my_test_server(PCSTR service_nameA,
320abb6fd83SPierre Schweitzer PCWSTR service_nameW,
321abb6fd83SPierre Schweitzer void *param)
322abb6fd83SPierre Schweitzer {
323abb6fd83SPierre Schweitzer BOOL res;
324abb6fd83SPierre Schweitzer SC_HANDLE hSC = NULL;
325abb6fd83SPierre Schweitzer SC_HANDLE hService = NULL;
326abb6fd83SPierre Schweitzer SERVICE_STATUS ServiceStatus;
327abb6fd83SPierre Schweitzer
328abb6fd83SPierre Schweitzer /* Open the SCM */
329abb6fd83SPierre Schweitzer hSC = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
330abb6fd83SPierre Schweitzer if (!hSC)
331abb6fd83SPierre Schweitzer {
332abb6fd83SPierre Schweitzer skip("OpenSCManagerW failed with error %lu!\n", GetLastError());
333abb6fd83SPierre Schweitzer return;
334abb6fd83SPierre Schweitzer }
335abb6fd83SPierre Schweitzer
336abb6fd83SPierre Schweitzer /* First create ourselves as a service running in the default LocalSystem account */
337abb6fd83SPierre Schweitzer hService = register_service_exW(hSC, L"ServiceNetwork", service_nameW, NULL,
338abb6fd83SPierre Schweitzer SERVICE_ALL_ACCESS,
339abb6fd83SPierre Schweitzer SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
340abb6fd83SPierre Schweitzer SERVICE_DEMAND_START,
341abb6fd83SPierre Schweitzer SERVICE_ERROR_IGNORE,
342abb6fd83SPierre Schweitzer NULL, NULL, NULL,
343abb6fd83SPierre Schweitzer NULL, NULL);
344abb6fd83SPierre Schweitzer if (!hService)
345abb6fd83SPierre Schweitzer {
346abb6fd83SPierre Schweitzer skip("CreateServiceW failed with error %lu!\n", GetLastError());
347abb6fd83SPierre Schweitzer goto Cleanup;
348abb6fd83SPierre Schweitzer }
349abb6fd83SPierre Schweitzer
350abb6fd83SPierre Schweitzer /* Start it */
351abb6fd83SPierre Schweitzer if (!StartServiceW(hService, 0, NULL))
352abb6fd83SPierre Schweitzer {
353abb6fd83SPierre Schweitzer skip("StartServiceW failed with error %lu!\n", GetLastError());
354abb6fd83SPierre Schweitzer goto Cleanup;
355abb6fd83SPierre Schweitzer }
356abb6fd83SPierre Schweitzer
357abb6fd83SPierre Schweitzer /* Wait for the service to stop by itself */
358abb6fd83SPierre Schweitzer do
359abb6fd83SPierre Schweitzer {
360abb6fd83SPierre Schweitzer Sleep(100);
361abb6fd83SPierre Schweitzer ZeroMemory(&ServiceStatus, sizeof(ServiceStatus));
362abb6fd83SPierre Schweitzer res = QueryServiceStatus(hService, &ServiceStatus);
363abb6fd83SPierre Schweitzer } while (res && ServiceStatus.dwCurrentState != SERVICE_STOPPED);
364abb6fd83SPierre Schweitzer ok(res, "QueryServiceStatus failed: %lu\n", GetLastError());
365abb6fd83SPierre Schweitzer ok(ServiceStatus.dwCurrentState == SERVICE_STOPPED, "ServiceStatus.dwCurrentState = %lx\n", ServiceStatus.dwCurrentState);
366abb6fd83SPierre Schweitzer
367abb6fd83SPierre Schweitzer /* Be sure the service is really stopped */
368abb6fd83SPierre Schweitzer res = ControlService(hService, SERVICE_CONTROL_STOP, &ServiceStatus);
369abb6fd83SPierre Schweitzer if (!res && ServiceStatus.dwCurrentState != SERVICE_STOPPED &&
370abb6fd83SPierre Schweitzer ServiceStatus.dwCurrentState != SERVICE_STOP_PENDING &&
371abb6fd83SPierre Schweitzer GetLastError() != ERROR_SERVICE_NOT_ACTIVE)
372abb6fd83SPierre Schweitzer {
373abb6fd83SPierre Schweitzer skip("ControlService failed with error %lu!\n", GetLastError());
374abb6fd83SPierre Schweitzer goto Cleanup;
375abb6fd83SPierre Schweitzer }
376abb6fd83SPierre Schweitzer
377abb6fd83SPierre Schweitzer #if 0
378abb6fd83SPierre Schweitzer trace("Service stopped. Going to restart it...\n");
379abb6fd83SPierre Schweitzer
380abb6fd83SPierre Schweitzer /* Now change the service configuration to make it start under the NetworkService account */
381abb6fd83SPierre Schweitzer if (!ChangeServiceConfigW(hService,
382abb6fd83SPierre Schweitzer SERVICE_NO_CHANGE,
383abb6fd83SPierre Schweitzer SERVICE_NO_CHANGE,
384abb6fd83SPierre Schweitzer SERVICE_NO_CHANGE,
385abb6fd83SPierre Schweitzer NULL, NULL, NULL, NULL,
386abb6fd83SPierre Schweitzer L"NT AUTHORITY\\NetworkService", L"",
387abb6fd83SPierre Schweitzer NULL))
388abb6fd83SPierre Schweitzer {
389abb6fd83SPierre Schweitzer skip("ChangeServiceConfigW failed with error %lu!\n", GetLastError());
390abb6fd83SPierre Schweitzer goto Cleanup;
391abb6fd83SPierre Schweitzer }
392abb6fd83SPierre Schweitzer
393abb6fd83SPierre Schweitzer /* Start it */
394abb6fd83SPierre Schweitzer if (!StartServiceW(hService, 0, NULL))
395abb6fd83SPierre Schweitzer {
396abb6fd83SPierre Schweitzer skip("StartServiceW failed with error %lu!\n", GetLastError());
397abb6fd83SPierre Schweitzer goto Cleanup;
398abb6fd83SPierre Schweitzer }
399abb6fd83SPierre Schweitzer
400abb6fd83SPierre Schweitzer /* Wait for the service to stop by itself */
401abb6fd83SPierre Schweitzer do
402abb6fd83SPierre Schweitzer {
403abb6fd83SPierre Schweitzer Sleep(100);
404abb6fd83SPierre Schweitzer ZeroMemory(&ServiceStatus, sizeof(ServiceStatus));
405abb6fd83SPierre Schweitzer res = QueryServiceStatus(hService, &ServiceStatus);
406abb6fd83SPierre Schweitzer } while (res && ServiceStatus.dwCurrentState != SERVICE_STOPPED);
407abb6fd83SPierre Schweitzer ok(res, "QueryServiceStatus failed: %lu\n", GetLastError());
408abb6fd83SPierre Schweitzer ok(ServiceStatus.dwCurrentState == SERVICE_STOPPED, "ServiceStatus.dwCurrentState = %lx\n", ServiceStatus.dwCurrentState);
409abb6fd83SPierre Schweitzer
410abb6fd83SPierre Schweitzer /* Be sure the service is really stopped */
411abb6fd83SPierre Schweitzer res = ControlService(hService, SERVICE_CONTROL_STOP, &ServiceStatus);
412abb6fd83SPierre Schweitzer if (!res && ServiceStatus.dwCurrentState != SERVICE_STOPPED &&
413abb6fd83SPierre Schweitzer ServiceStatus.dwCurrentState != SERVICE_STOP_PENDING &&
414abb6fd83SPierre Schweitzer GetLastError() != ERROR_SERVICE_NOT_ACTIVE)
415abb6fd83SPierre Schweitzer {
416abb6fd83SPierre Schweitzer skip("ControlService failed with error %lu!\n", GetLastError());
417abb6fd83SPierre Schweitzer goto Cleanup;
418abb6fd83SPierre Schweitzer }
419abb6fd83SPierre Schweitzer #endif
420abb6fd83SPierre Schweitzer
421abb6fd83SPierre Schweitzer Cleanup:
422abb6fd83SPierre Schweitzer if (hService)
423abb6fd83SPierre Schweitzer {
424abb6fd83SPierre Schweitzer res = DeleteService(hService);
425abb6fd83SPierre Schweitzer ok(res, "DeleteService failed: %lu\n", GetLastError());
426abb6fd83SPierre Schweitzer CloseServiceHandle(hService);
427abb6fd83SPierre Schweitzer }
428abb6fd83SPierre Schweitzer
429abb6fd83SPierre Schweitzer if (hSC)
430abb6fd83SPierre Schweitzer CloseServiceHandle(hSC);
431abb6fd83SPierre Schweitzer }
432abb6fd83SPierre Schweitzer
START_TEST(ServiceNetwork)433abb6fd83SPierre Schweitzer START_TEST(ServiceNetwork)
434abb6fd83SPierre Schweitzer {
435abb6fd83SPierre Schweitzer int argc;
436abb6fd83SPierre Schweitzer char** argv;
437abb6fd83SPierre Schweitzer
438abb6fd83SPierre Schweitzer /* Check whether this test is started as a separated service process */
439abb6fd83SPierre Schweitzer argc = winetest_get_mainargs(&argv);
440abb6fd83SPierre Schweitzer if (argc >= 3)
441abb6fd83SPierre Schweitzer {
442abb6fd83SPierre Schweitzer service_process(start_service, argc, argv);
443abb6fd83SPierre Schweitzer return;
444abb6fd83SPierre Schweitzer }
445abb6fd83SPierre Schweitzer
446abb6fd83SPierre Schweitzer /* We are started as the real test */
447abb6fd83SPierre Schweitzer test_runner(my_test_server, NULL);
448abb6fd83SPierre Schweitzer // trace("Returned from test_runner\n");
449abb6fd83SPierre Schweitzer }
450