1 /*
2  * PROJECT:     ReactOS API tests
3  * LICENSE:     LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
4  * PURPOSE:     Tests for Hostname command and Winsock gethostname() function.
5  * COPYRIGHT:   Copyright 2019 Doug Lyons <douglyons@douglyons.com>
6  *              Copyright 2019 Hermes Belusca-Maito
7  */
8 
9 #include "ws2_32.h"
10 
11 #include <winreg.h>
12 
13 #define REG_HOSTNAME_KEY        L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters"
14 #define REG_COMPUTERNAME_KEY    L"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName"
15 
16 HKEY
17 OpenRegKey(
18     IN HKEY   hRootKey,
19     IN PCWSTR pszSubKey,
20     IN DWORD  ulOptions)
21 {
22     HKEY hKey = NULL;
23     LONG Error = RegOpenKeyExW(hRootKey, pszSubKey, 0, ulOptions, &hKey);
24     if (Error == ERROR_SUCCESS)
25         return hKey;
26     return NULL;
27 }
28 
29 BOOL
30 GetHostnameFromCommand(
31     OUT PSTR pszHostnameBuffer,
32     IN ULONG ulBufferSize)
33 {
34     PCSTR file_name = "HostName123.txt";
35     CHAR cmdline[MAX_PATH] = "hostname > ";
36     FILE *fp;
37     INT iResult;
38     INT len;
39     PCSTR ptr;
40 
41     ZeroMemory(pszHostnameBuffer, ulBufferSize * sizeof(CHAR));
42 
43     /* Run the 'hostname' command, piping out its result to the temporary file */
44     strcat(cmdline, file_name);
45     system(cmdline);
46 
47     /* Open the temporary file in read mode */
48     fp = fopen(file_name, "r");
49     ok(fp != NULL, "An error occurred while opening the file.\n");
50     if (fp == NULL)
51         return FALSE;
52 
53     /* Read its contents */
54     ptr = fgets(pszHostnameBuffer, ulBufferSize * sizeof(CHAR), fp);
55     ok(ptr != NULL, "An error occurred while reading the file.\n");
56     if (ptr == NULL)
57         goto Cleanup;
58 
59     /* Delete the expected ending line feed character */
60     len = lstrlenA(pszHostnameBuffer);
61     if (pszHostnameBuffer[len-1] == '\r' || pszHostnameBuffer[len-1] == '\n')
62         pszHostnameBuffer[len-1] = ANSI_NULL;
63 
64 Cleanup:
65     /* Close and remove the file */
66     iResult = fclose(fp);
67     ok(iResult == 0, "An error occurred while closing the file: %i.\n", iResult);
68     iResult = remove(file_name);
69     ok(iResult == 0, "An error occurred while deleting the file: %i.\n", iResult);
70 
71     return (ptr ? TRUE : FALSE);
72 }
73 
74 START_TEST(gethostname)
75 {
76     INT pos;
77     HKEY hKeyHN;
78     DWORD cbData;
79     LONG Error;
80     INT hnError;
81     INT iResult;
82     WSADATA wsaData;
83     DWORD uApiHostNameSize;
84     CHAR szApiHostName[256] = "";
85     CHAR szHostNameOld[256] = "";
86     CHAR szHostNameNew[256] = "";
87     CHAR hostbuffer[256] = "";
88 
89 /*
90  * Notes about the retrieval of the computer name on Windows.
91  *
92  * - GetComputerName() (equivalently, GetComputerNameEx(ComputerNameNetBIOS))
93  *   retrieves the name cached in the registry value "ComputerName" under
94  *   "System\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName" .
95  *
96  * - GetComputerNameEx(ComputerNameDnsHostname) as well as the 'hostname' command
97      return the registry value "Hostname" under "System\\CurrentControlSet\\Services\\Tcpip\\Parameters" .
98  *
99  * - In case a new computer name is set, its value is cached in the registry value
100  *   "ComputerName" under "System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",
101  *   and also in the registry value "NV Hostname" under "System\\CurrentControlSet\\Services\\Tcpip\\Parameters" .
102  */
103 
104     /* Retrieve the current host name using API */
105     uApiHostNameSize = _countof(szApiHostName);
106     if (!GetComputerNameExA(ComputerNameDnsHostname, szApiHostName, &uApiHostNameSize))
107     {
108         /* Fail in case of error */
109         skip("GetComputerNameExA(ComputerNameDnsHostname) failed, error %lu\n", GetLastError());
110         return;
111     }
112     printf("The Hostname from API is '%s'.\n", szApiHostName);
113 
114     /* Retrieve the current host name using the 'hostname' command */
115     if (!GetHostnameFromCommand(hostbuffer, _countof(hostbuffer)))
116     {
117         /* Fail in case of error */
118         skip("Error while retrieving the host name using the 'hostname' command!\n");
119         return;
120     }
121     printf("The Hostname from command is '%s'.\n", hostbuffer);
122 
123     pos = strcmp(szApiHostName, hostbuffer);
124     printf("The test results were '%s'.\n", pos==0 ? "good" : "bad");
125     ok(pos == 0, "hostbuffer '%s' should have been szApiHostName '%s'.\n", hostbuffer, szApiHostName);
126 
127     hKeyHN = OpenRegKey(HKEY_LOCAL_MACHINE, REG_HOSTNAME_KEY, KEY_ALL_ACCESS);
128     ok(hKeyHN != NULL, "Error while opening hostname registry key.\n");
129     if (hKeyHN == NULL)
130         return;
131 
132     /* Get Old Hostname */
133     szHostNameOld[0] = ANSI_NULL;
134     cbData = sizeof(szHostNameOld);
135     Error = RegQueryValueExA(hKeyHN, "Hostname", NULL, NULL, (LPBYTE)szHostNameOld, &cbData);
136 
137     printf("Hostname from Registry is '%s'.\n", szHostNameOld);
138 
139     pos = strcmp(szHostNameOld, szApiHostName);
140     printf("The test results were '%s'.\n", pos==0 ? "good" : "bad");
141     ok(pos == 0, "szApiHostName '%s' should have been szHostNameOld '%s'.\n", szApiHostName, szHostNameOld);
142 
143     /* Change Hostname in the Registry */
144     szHostNameNew[0] = ANSI_NULL;
145     strcat(szHostNameNew, "ROSHOSTNAME1");
146     cbData = lstrlenA(szHostNameNew) + 1;
147 
148     Error = RegSetValueExA(hKeyHN, "Hostname", 0, REG_SZ, (LPBYTE)szHostNameNew, cbData);
149     ok(Error == ERROR_SUCCESS, "Error setting new registry value (%ld).\n", GetLastError());
150 
151     /* Retrieve the current host name using API */
152     uApiHostNameSize = _countof(szApiHostName);
153     if (!GetComputerNameExA(ComputerNameDnsHostname, szApiHostName, &uApiHostNameSize))
154     {
155         /* Fail in case of error */
156         skip("GetComputerNameExA(ComputerNameDnsHostname) failed, error %lu\n", GetLastError());
157         goto Cleanup;
158     }
159     printf("The Hostname from API is '%s'.\n", szApiHostName);
160 
161     /* Retrieve the current host name using the 'hostname' command */
162     if (!GetHostnameFromCommand(hostbuffer, _countof(hostbuffer)))
163     {
164         /* Fail in case of error */
165         skip("Error while retrieving the host name using the 'hostname' command!\n");
166         goto Cleanup;
167     }
168     printf("The Hostname from command is '%s'.\n", hostbuffer);
169 
170     pos = strcmp(szHostNameNew, szApiHostName);
171     printf("The test results were '%s'.\n", pos==0 ? "good" : "bad");
172     ok(pos == 0, "szApiHostName '%s' should be szHostNameNew '%s'.\n", szApiHostName, szHostNameNew);
173 
174     pos = strcmp(szHostNameNew, hostbuffer);
175     printf("The test results were '%s'.\n", pos==0 ? "good" : "bad");
176     ok(pos == 0, "hostbuffer '%s' should have been szHostNameNew '%s'.\n", hostbuffer, szHostNameNew);
177 
178     /* Reset the original registry entry */
179     cbData = lstrlenA(szHostNameOld) + 1;
180 
181     Error = RegSetValueExA(hKeyHN, "Hostname", 0, REG_SZ, (LPBYTE)szHostNameOld, cbData);
182     ok(Error == ERROR_SUCCESS, "Error resetting new registry value back (%ld).\n", GetLastError());
183 
184 /*============ Winsock Checks ===============*/
185 
186     /* Start up Winsock to use gethostname() */
187     iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
188     ok(iResult == 0, "Error occurred starting Winsock");
189     if (iResult != 0)
190         goto Cleanup;
191 
192     /* Retrieve gethostname() */
193     hnError = gethostname(hostbuffer, sizeof(hostbuffer));
194     ok(!hnError, "Winsock gethostname() Error is '%d'.\n", WSAGetLastError());
195 
196     /* Display results */
197     if (!hnError)
198         printf("Winsock gethostname() is '%s'.\n", hostbuffer);
199 
200     pos = strcmp(szHostNameOld, hostbuffer);
201     printf("The test results were '%s'.\n", pos==0 ? "good" : "bad");
202     ok(pos == 0, "szHostNameOld '%s' should be hostbuffer '%s'.\n", szHostNameOld, hostbuffer);
203 
204     /* Change Hostname in the Registry */
205     szHostNameNew[0] = ANSI_NULL;
206     strcat(szHostNameNew, "ROSHOSTNAME1");
207     cbData = lstrlenA(szHostNameNew) + 1;
208 
209     Error = RegSetValueExA(hKeyHN, "Hostname", 0, REG_SZ, (LPBYTE)szHostNameNew, cbData);
210     ok(Error == ERROR_SUCCESS, "Error setting new registry value (%ld).\n", GetLastError());
211 
212     /* Retrieve gethostname() */
213     hnError = gethostname(hostbuffer, sizeof(hostbuffer));
214     ok(!hnError, "Winsock gethostname() Error is '%d'.\n", WSAGetLastError());
215 
216     /* Display results */
217     if (!hnError)
218         printf("Winsock gethostname() is '%s'.\n", hostbuffer);
219 
220     pos = strcmp(szHostNameNew, hostbuffer);
221     printf("The test results were '%s'.\n", pos==0 ? "good" : "bad");
222     ok(pos == 0, "szHostNameNew '%s' should be hostbuffer '%s'.\n", szHostNameNew, hostbuffer);
223 
224     /* Reset the original registry entry */
225     cbData = lstrlenA(szHostNameOld) + 1;
226 
227     Error = RegSetValueExA(hKeyHN, "Hostname", 0, REG_SZ, (LPBYTE)szHostNameOld, cbData);
228     ok(Error == ERROR_SUCCESS, "Error resetting new registry value back (%ld).\n", GetLastError());
229 
230     /* Retrieve gethostname() */
231     hnError = gethostname(hostbuffer, sizeof(hostbuffer));
232     ok(!hnError, "Winsock gethostname() Error is '%d'.\n", WSAGetLastError());
233 
234     /* Display results */
235     if (!hnError)
236         printf("Winsock gethostname() is '%s'.\n", hostbuffer);
237 
238     pos = strcmp(szHostNameOld, hostbuffer);
239     printf("The test results were '%s'.\n", pos==0 ? "good" : "bad");
240     ok(pos == 0, "szHostNameOld '%s' should be hostbuffer '%s'.\n", szHostNameOld, hostbuffer);
241 
242 Cleanup:
243     iResult = WSACleanup();
244     ok(iResult == 0, "WSACleanup error occurred ending Winsock");
245 
246     Error = RegCloseKey(hKeyHN);
247     ok(Error == ERROR_SUCCESS, "Error closing registry key (%ld).\n", GetLastError());
248 
249     return;
250 }
251