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