1 /*
2  * PROJECT:     ReactOS API Tests
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Tests for TCP connections owner functions
5  * COPYRIGHT:   Copyright 2018 Pierre Schweitzer
6  */
7 
8 #include <apitest.h>
9 
10 #define WIN32_NO_STATUS
11 #include <iphlpapi.h>
12 #include <winsock2.h>
13 
14 static DWORD GetExtendedTcpTableWithAlloc(PVOID *TcpTable, BOOL Order, DWORD Family, TCP_TABLE_CLASS Class)
15 {
16     DWORD ret;
17     DWORD Size = 0;
18 
19     *TcpTable = NULL;
20 
21     ret = GetExtendedTcpTable(*TcpTable, &Size, Order, Family, Class, 0);
22     if (ret == ERROR_INSUFFICIENT_BUFFER)
23     {
24         *TcpTable = HeapAlloc(GetProcessHeap(), 0, Size);
25         if (*TcpTable == NULL)
26         {
27             return ERROR_OUTOFMEMORY;
28         }
29 
30         ret = GetExtendedTcpTable(*TcpTable, &Size, Order, Family, Class, 0);
31         if (ret != NO_ERROR)
32         {
33             HeapFree(GetProcessHeap(), 0, *TcpTable);
34             *TcpTable = NULL;
35         }
36     }
37 
38     return ret;
39 }
40 
41 START_TEST(GetOwnerModuleFromTcpEntry)
42 {
43     WSADATA wsaData;
44     SOCKET sock;
45     SOCKADDR_IN server;
46     PMIB_TCPTABLE_OWNER_MODULE TcpTableOwnerMod;
47     DWORD i;
48     BOOLEAN Found;
49     FILETIME Creation;
50     LARGE_INTEGER CreationTime;
51     DWORD Pid = GetCurrentProcessId();
52 
53     if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
54     {
55         skip("Failed to init WS2\n");
56         return;
57     }
58 
59     GetSystemTimeAsFileTime(&Creation);
60     CreationTime.LowPart = Creation.dwLowDateTime;
61     CreationTime.HighPart = Creation.dwHighDateTime;
62 
63     sock = socket(AF_INET, SOCK_STREAM, 0);
64     if (sock == INVALID_SOCKET)
65     {
66         skip("Cannot create socket\n");
67         goto quit;
68     }
69 
70     ZeroMemory(&server, sizeof(SOCKADDR_IN));
71     server.sin_family = AF_INET;
72     server.sin_addr.s_addr = htonl(INADDR_ANY);
73     server.sin_port = htons(9876);
74 
75     if (bind(sock, (SOCKADDR*)&server, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
76     {
77         skip("Cannot bind socket\n");
78         goto quit2;
79     }
80 
81     if (listen(sock, SOMAXCONN) == SOCKET_ERROR)
82     {
83         skip("Cannot listen on socket\n");
84         goto quit2;
85     }
86 
87     if (GetExtendedTcpTableWithAlloc((PVOID *)&TcpTableOwnerMod, TRUE, AF_INET, TCP_TABLE_OWNER_MODULE_LISTENER) == ERROR_SUCCESS)
88     {
89         ok(TcpTableOwnerMod->dwNumEntries > 0, "No TCP connections?!\n");
90 
91         Found = FALSE;
92         for (i = 0; i < TcpTableOwnerMod->dwNumEntries; ++i)
93         {
94             if (TcpTableOwnerMod->table[i].dwState == MIB_TCP_STATE_LISTEN &&
95                 TcpTableOwnerMod->table[i].dwLocalAddr == 0 &&
96                 TcpTableOwnerMod->table[i].dwLocalPort == htons(9876) &&
97                 TcpTableOwnerMod->table[i].dwRemoteAddr == 0)
98             {
99                 Found = TRUE;
100                 break;
101             }
102         }
103 
104         if (!Found)
105         {
106             skip("Our socket wasn't found!\n");
107         }
108         else
109         {
110             DWORD Size = 0;
111             PTCPIP_OWNER_MODULE_BASIC_INFO BasicInfo = NULL;
112 
113             ok(TcpTableOwnerMod->table[i].dwOwningPid == Pid, "Invalid owner\n");
114 
115             ok(TcpTableOwnerMod->table[i].liCreateTimestamp.QuadPart >= CreationTime.QuadPart, "Invalid time\n");
116             ok(TcpTableOwnerMod->table[i].liCreateTimestamp.QuadPart <= CreationTime.QuadPart + 60000000000LL, "Invalid time\n");
117 
118             if (GetOwnerModuleFromTcpEntry(&TcpTableOwnerMod->table[i], TCPIP_OWNER_MODULE_INFO_BASIC, BasicInfo, &Size) == ERROR_INSUFFICIENT_BUFFER)
119             {
120                 BasicInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
121                 ok(BasicInfo != NULL, "HeapAlloc failed\n");
122 
123                 if (GetOwnerModuleFromTcpEntry(&TcpTableOwnerMod->table[i], TCPIP_OWNER_MODULE_INFO_BASIC, BasicInfo, &Size) == ERROR_SUCCESS)
124                 {
125                     WCHAR CurrentModule[MAX_PATH];
126                     PWSTR FileName;
127 
128                     if (GetModuleFileNameW(NULL, CurrentModule, MAX_PATH) != 0)
129                     {
130                         FileName = wcsrchr(CurrentModule, L'\\');
131                         ++FileName;
132 
133                         ok(_wcsicmp(CurrentModule, BasicInfo->pModulePath) == 0, "Mismatching names (%S, %S)\n", CurrentModule, BasicInfo->pModulePath);
134                         ok(_wcsicmp(FileName, BasicInfo->pModuleName) == 0, "Mismatching names (%S, %S)\n", FileName, BasicInfo->pModuleName);
135                     }
136                     else
137                     {
138                         skip("GetModuleFileNameW failed\n");
139                     }
140                 }
141                 else
142                 {
143                     skip("GetOwnerModuleFromTcpEntry failed\n");
144                 }
145             }
146             else
147             {
148                 skip("GetOwnerModuleFromTcpEntry failed\n");
149             }
150         }
151 
152         HeapFree(GetProcessHeap(), 0, TcpTableOwnerMod);
153     }
154     else
155     {
156         skip("GetExtendedTcpTableWithAlloc failure\n");
157     }
158 
159 quit2:
160     closesocket(sock);
161 quit:
162     WSACleanup();
163 }
164