1 /*
2  * PROJECT:     ReactOS api tests
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Tests for the SetComputerNameExW API
5  * COPYRIGHT:   Victor Martinez Calvo (victor.martinez@reactos.org)
6  *              Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
7  */
8 #include <apitest.h>
9 
10 #define WIN32_NO_STATUS
11 #include <stdio.h>
12 #include <ndk/rtltypes.h>
13 
14 #undef _WIN32_WINNT
15 #define _WIN32_WINNT 0x0600
16 #include <winreg.h>
17 
18 static HKEY OpenHostNameKey(void)
19 {
20     static const WCHAR
21         RegHostNameKey[] = L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters";
22     HKEY hKey = NULL;
23     LONG Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, RegHostNameKey, 0, KEY_ALL_ACCESS, &hKey);
24     if (!Error)
25         return hKey;
26     return NULL;
27 }
28 
29 static HKEY OpenComputerNameKey(void)
30 {
31     static const WCHAR
32         RegComputerNameKey[] = L"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName";
33     HKEY hKey = NULL;
34     LONG Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, RegComputerNameKey, 0, KEY_ALL_ACCESS, &hKey);
35     if (!Error)
36         return hKey;
37     return NULL;
38 }
39 
40 static void DoTestComputerName(HKEY hKeyHN, HKEY hKeyCN, LPCWSTR pszNewName, BOOL bValid)
41 {
42     LONG Error;
43     BOOL ret;
44     DWORD cbData;
45     WCHAR szNVHostNameOld[MAX_PATH], szNVHostNameNew[MAX_PATH];
46     WCHAR szHostNameOld[MAX_PATH], szHostNameNew[MAX_PATH];
47     WCHAR szComputerNameOld[MAX_PATH], szComputerNameNew[MAX_PATH];
48 
49     trace("Testing '%S':\n", pszNewName);
50 
51     /* Get Old NV Hostname */
52     szNVHostNameOld[0] = UNICODE_NULL;
53     cbData = sizeof(szNVHostNameOld);
54     Error = RegQueryValueExW(hKeyHN, L"NV Hostname", NULL, NULL, (LPBYTE)szNVHostNameOld, &cbData);
55     ok_long(Error, ERROR_SUCCESS);
56     ok(szNVHostNameOld[0], "szNVHostNameOld is empty\n");
57 
58     /* Get Old Hostname */
59     szHostNameOld[0] = UNICODE_NULL;
60     cbData = sizeof(szHostNameOld);
61     Error = RegQueryValueExW(hKeyHN, L"Hostname", NULL, NULL, (LPBYTE)szHostNameOld, &cbData);
62     ok_long(Error, ERROR_SUCCESS);
63     ok(szHostNameOld[0], "szHostNameOld is empty\n");
64 
65     /* Get Old Computer Name */
66     szComputerNameOld[0] = UNICODE_NULL;
67     cbData = sizeof(szComputerNameOld);
68     Error = RegQueryValueExW(hKeyCN, L"ComputerName", NULL, NULL, (LPBYTE)szComputerNameOld, &cbData);
69     ok_long(Error, ERROR_SUCCESS);
70     ok(szComputerNameOld[0], "szComputerNameOld is empty\n");
71 
72     /* Change the value */
73     SetLastError(0xDEADFACE);
74     ret = SetComputerNameExW(ComputerNamePhysicalDnsHostname, pszNewName);
75     ok_int(ret, bValid);
76     Error = GetLastError();
77     if (bValid)
78         ok_long(Error, ERROR_SUCCESS);
79     else
80         ok_long(Error, ERROR_INVALID_PARAMETER);
81 
82     /* Get New NV Hostname */
83     szNVHostNameNew[0] = UNICODE_NULL;
84     cbData = sizeof(szNVHostNameNew);
85     Error = RegQueryValueExW(hKeyHN, L"NV Hostname", NULL, NULL, (LPBYTE)szNVHostNameNew, &cbData);
86     ok_long(Error, ERROR_SUCCESS);
87     if (bValid)
88     {
89         ok(szNVHostNameNew[0], "szNVHostNameNew is empty\n");
90         ok(lstrcmpW(szNVHostNameNew, pszNewName) == 0,
91            "szNVHostNameNew '%S' should be pszNewName '%S'\n", szNVHostNameNew, pszNewName);
92     }
93 
94     /* Get New Hostname */
95     szHostNameNew[0] = UNICODE_NULL;
96     cbData = sizeof(szHostNameNew);
97     Error = RegQueryValueExW(hKeyHN, L"Hostname", NULL, NULL, (LPBYTE)szHostNameNew, &cbData);
98     ok_long(Error, ERROR_SUCCESS);
99     if (bValid)
100     {
101         ok(szHostNameNew[0], "szHostNameNew is empty\n");
102         ok(lstrcmpW(szHostNameNew, szHostNameOld) == 0,
103            "szHostNameNew '%S' should be szHostNameOld '%S'\n", szHostNameNew, szHostNameOld);
104     }
105 
106     /* Get New Computer Name */
107     szComputerNameNew[0] = UNICODE_NULL;
108     cbData = sizeof(szComputerNameNew);
109     Error = RegQueryValueExW(hKeyCN, L"ComputerName", NULL, NULL, (LPBYTE)szComputerNameNew, &cbData);
110     ok_long(Error, ERROR_SUCCESS);
111     if (bValid)
112     {
113         ok(szComputerNameNew[0], "szComputerNameNew is empty\n");
114         if (lstrlenW(pszNewName) > MAX_COMPUTERNAME_LENGTH)
115         {
116             WCHAR szTruncatedNewName[MAX_COMPUTERNAME_LENGTH + 1];
117             lstrcpynW(szTruncatedNewName, pszNewName, ARRAYSIZE(szTruncatedNewName));
118             ok(lstrcmpiW(szComputerNameNew, szTruncatedNewName) == 0,
119                "szComputerNameNew '%S' should be szTruncatedNewName '%S'\n",
120                szComputerNameNew, szTruncatedNewName);
121         }
122         else
123         {
124             ok(lstrcmpiW(szComputerNameNew, pszNewName) == 0,
125                "szComputerNameNew '%S' should be pszNewName '%S'\n",
126                szComputerNameNew, pszNewName);
127         }
128     }
129 
130     /* Restore the registry values */
131     cbData = (lstrlenW(szNVHostNameOld) + 1) * sizeof(WCHAR);
132     Error = RegSetValueExW(hKeyHN, L"NV Hostname", 0, REG_SZ, (LPBYTE)szNVHostNameOld, cbData);
133     ok_long(Error, ERROR_SUCCESS);
134 
135     cbData = (lstrlenW(szHostNameOld) + 1) * sizeof(WCHAR);
136     Error = RegSetValueExW(hKeyHN, L"Hostname", 0, REG_SZ, (LPBYTE)szHostNameOld, cbData);
137     ok_long(Error, ERROR_SUCCESS);
138 
139     cbData = (lstrlenW(szComputerNameOld) + 1) * sizeof(WCHAR);
140     Error = RegSetValueExW(hKeyCN, L"ComputerName", 0, REG_SZ, (LPBYTE)szComputerNameOld, cbData);
141     ok_long(Error, ERROR_SUCCESS);
142 }
143 
144 START_TEST(SetComputerNameExW)
145 {
146     HKEY hKeyHN, hKeyCN;
147     static const WCHAR ValidSymbols[] = L"-_";
148     static const WCHAR InvalidSymbols[] = L"\"/\\[]:|<>+=;,?";
149     WCHAR szName[32];
150     INT i, cchValidSymbols, cchInvalidSymbols;
151     LONG Error;
152 
153     /* Open keys */
154     hKeyHN = OpenHostNameKey();
155     ok(hKeyHN != NULL, "hKeyHN is NULL\n");
156     hKeyCN = OpenComputerNameKey();
157     ok(hKeyCN != NULL, "hKeyCN is NULL\n");
158     if (!hKeyHN || !hKeyCN)
159     {
160         if (hKeyHN)
161             RegCloseKey(hKeyHN);
162         if (hKeyCN)
163             RegCloseKey(hKeyCN);
164         skip("Unable to open keys. Missing Admin rights?\n");
165         return;
166     }
167 
168     cchValidSymbols = lstrlenW(ValidSymbols);
169     cchInvalidSymbols = lstrlenW(InvalidSymbols);
170 
171     /* Test names */
172 
173     DoTestComputerName(hKeyHN, hKeyCN, L"SRVROSTEST", TRUE);
174     DoTestComputerName(hKeyHN, hKeyCN, L"SrvRosTest", TRUE);
175 
176     DoTestComputerName(hKeyHN, hKeyCN, L"", FALSE);
177     DoTestComputerName(hKeyHN, hKeyCN, L"a", TRUE);
178     DoTestComputerName(hKeyHN, hKeyCN, L"A", TRUE);
179     DoTestComputerName(hKeyHN, hKeyCN, L"1", FALSE);   // numeric-only
180     DoTestComputerName(hKeyHN, hKeyCN, L"@", FALSE);
181     DoTestComputerName(hKeyHN, hKeyCN, L".", FALSE);
182 
183     DoTestComputerName(hKeyHN, hKeyCN, L" ", FALSE);
184     DoTestComputerName(hKeyHN, hKeyCN, L"\t", FALSE);
185     DoTestComputerName(hKeyHN, hKeyCN, L"\b", FALSE);
186 
187     DoTestComputerName(hKeyHN, hKeyCN, L" a", FALSE);
188     DoTestComputerName(hKeyHN, hKeyCN, L" A", FALSE);
189     DoTestComputerName(hKeyHN, hKeyCN, L" 1", FALSE);
190     DoTestComputerName(hKeyHN, hKeyCN, L"\ta", FALSE);
191     DoTestComputerName(hKeyHN, hKeyCN, L"\tA", FALSE);
192     DoTestComputerName(hKeyHN, hKeyCN, L"\t1", FALSE);
193     DoTestComputerName(hKeyHN, hKeyCN, L"\ba", FALSE);
194     DoTestComputerName(hKeyHN, hKeyCN, L"\bA", FALSE);
195     DoTestComputerName(hKeyHN, hKeyCN, L"\b1", FALSE);
196 
197     DoTestComputerName(hKeyHN, hKeyCN, L"a ", FALSE);
198     DoTestComputerName(hKeyHN, hKeyCN, L"A ", FALSE);
199     DoTestComputerName(hKeyHN, hKeyCN, L"1 ", FALSE);
200     DoTestComputerName(hKeyHN, hKeyCN, L"a\t", FALSE);
201     DoTestComputerName(hKeyHN, hKeyCN, L"A\t", FALSE);
202     DoTestComputerName(hKeyHN, hKeyCN, L"1\t", FALSE);
203     DoTestComputerName(hKeyHN, hKeyCN, L"a\b", FALSE);
204     DoTestComputerName(hKeyHN, hKeyCN, L"A\b", FALSE);
205     DoTestComputerName(hKeyHN, hKeyCN, L"1\b", FALSE);
206 
207     DoTestComputerName(hKeyHN, hKeyCN, L"a c", FALSE);
208     DoTestComputerName(hKeyHN, hKeyCN, L"A C", FALSE);
209     DoTestComputerName(hKeyHN, hKeyCN, L"1 c", FALSE);
210 
211     DoTestComputerName(hKeyHN, hKeyCN, L"a\tc", FALSE);
212     DoTestComputerName(hKeyHN, hKeyCN, L"A\tC", FALSE);
213     DoTestComputerName(hKeyHN, hKeyCN, L"1\tc", FALSE);
214 
215     DoTestComputerName(hKeyHN, hKeyCN, L"a\bc", FALSE);
216     DoTestComputerName(hKeyHN, hKeyCN, L"A\bC", FALSE);
217     DoTestComputerName(hKeyHN, hKeyCN, L"1\bc", FALSE);
218 
219     DoTestComputerName(hKeyHN, hKeyCN, ValidSymbols, TRUE);
220     DoTestComputerName(hKeyHN, hKeyCN, InvalidSymbols, FALSE);
221 
222     DoTestComputerName(hKeyHN, hKeyCN, L"123456", FALSE);   // numeric-only
223     DoTestComputerName(hKeyHN, hKeyCN, L"123.456", FALSE);
224     DoTestComputerName(hKeyHN, hKeyCN, L"123X456", TRUE);
225     DoTestComputerName(hKeyHN, hKeyCN, L"123X.456", FALSE);
226 
227     DoTestComputerName(hKeyHN, hKeyCN, L"ThisIsLongLongComputerName", TRUE);
228 
229     for (i = 0; i < cchValidSymbols; ++i)
230     {
231         szName[0] = ValidSymbols[i];
232         szName[1] = UNICODE_NULL;
233         DoTestComputerName(hKeyHN, hKeyCN, szName, TRUE);
234     }
235 
236     for (i = 0; i < cchValidSymbols; ++i)
237     {
238         szName[0] = L'a';
239         szName[1] = ValidSymbols[i];
240         szName[2] = UNICODE_NULL;
241         DoTestComputerName(hKeyHN, hKeyCN, szName, TRUE);
242     }
243 
244     for (i = 0; i < cchValidSymbols; ++i)
245     {
246         szName[0] = L'A';
247         szName[1] = ValidSymbols[i];
248         szName[2] = UNICODE_NULL;
249         DoTestComputerName(hKeyHN, hKeyCN, szName, TRUE);
250     }
251 
252     for (i = 0; i < cchValidSymbols; ++i)
253     {
254         szName[0] = L'1';
255         szName[1] = ValidSymbols[i];
256         szName[2] = UNICODE_NULL;
257         DoTestComputerName(hKeyHN, hKeyCN, szName, TRUE);
258     }
259 
260     for (i = 0; i < cchInvalidSymbols; ++i)
261     {
262         szName[0] = L'A';
263         szName[1] = InvalidSymbols[i];
264         szName[2] = UNICODE_NULL;
265         DoTestComputerName(hKeyHN, hKeyCN, szName, FALSE);
266     }
267 
268     for (i = 0; i < cchInvalidSymbols; ++i)
269     {
270         szName[0] = L'1';
271         szName[1] = InvalidSymbols[i];
272         szName[2] = UNICODE_NULL;
273         DoTestComputerName(hKeyHN, hKeyCN, szName, FALSE);
274     }
275 
276     /* Close keys */
277     Error = RegCloseKey(hKeyHN);
278     ok_long(Error, ERROR_SUCCESS);
279     Error = RegCloseKey(hKeyCN);
280     ok_long(Error, ERROR_SUCCESS);
281 }
282