79bcb3153aa4f73218732361200f53e585ad520d
[reactos.git] / reactos / dll / win32 / kernel32 / misc / computername.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS system libraries
22 * PURPOSE: Computer name functions
23 * FILE: lib/kernel32/misc/computername.c
24 * PROGRAMER: Eric Kohl (ekohl@rz-online.de)
25 */
26
27 /* INCLUDES ******************************************************************/
28
29 #include <k32.h>
30
31 #define NDEBUG
32 #include <debug.h>
33
34
35 /* FUNCTIONS *****************************************************************/
36
37 static
38 BOOL
39 GetComputerNameFromRegistry(LPWSTR RegistryKey,
40 LPWSTR ValueNameStr,
41 LPWSTR lpBuffer,
42 LPDWORD nSize )
43 {
44 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
45 OBJECT_ATTRIBUTES ObjectAttributes;
46 UNICODE_STRING KeyName;
47 UNICODE_STRING ValueName;
48 HANDLE KeyHandle;
49 ULONG KeyInfoSize;
50 ULONG ReturnSize;
51 NTSTATUS Status;
52
53 RtlInitUnicodeString(&KeyName,RegistryKey);
54 InitializeObjectAttributes(&ObjectAttributes,
55 &KeyName,
56 OBJ_CASE_INSENSITIVE,
57 NULL,
58 NULL);
59
60 Status = ZwOpenKey(&KeyHandle,
61 KEY_READ,
62 &ObjectAttributes);
63 if (!NT_SUCCESS(Status))
64 {
65 SetLastErrorByStatus (Status);
66 return FALSE;
67 }
68
69 KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + *nSize * sizeof(WCHAR);
70 KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, KeyInfoSize);
71 if (KeyInfo == NULL)
72 {
73 ZwClose(KeyHandle);
74 SetLastError(ERROR_OUTOFMEMORY);
75 return FALSE;
76 }
77
78 RtlInitUnicodeString(&ValueName,ValueNameStr);
79
80 Status = ZwQueryValueKey(KeyHandle,
81 &ValueName,
82 KeyValuePartialInformation,
83 KeyInfo,
84 KeyInfoSize,
85 &ReturnSize);
86 if (!NT_SUCCESS(Status))
87 {
88 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
89 ZwClose(KeyHandle);
90 *nSize = ReturnSize;
91 SetLastErrorByStatus(Status);
92 return FALSE;
93 }
94
95 if (*nSize > (KeyInfo->DataLength / sizeof(WCHAR)))
96 {
97 *nSize = KeyInfo->DataLength / sizeof(WCHAR) - 1;
98 lpBuffer[*nSize] = 0;
99 }
100
101 RtlCopyMemory(lpBuffer, KeyInfo->Data, *nSize * sizeof(WCHAR));
102
103 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
104 ZwClose(KeyHandle);
105
106 return TRUE;
107 }
108
109 /*
110 * @implemented
111 */
112 BOOL
113 WINAPI
114 GetComputerNameExW(COMPUTER_NAME_FORMAT NameType,
115 LPWSTR lpBuffer,
116 LPDWORD nSize)
117 {
118 UNICODE_STRING ResultString;
119 UNICODE_STRING DomainPart;
120 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
121 NTSTATUS Status;
122 BOOL ret = TRUE;
123 DWORD HostSize;
124
125 switch (NameType)
126 {
127 case ComputerNameNetBIOS:
128 return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
129 L"\\Control\\ComputerName\\ComputerName",
130 L"ComputerName",
131 lpBuffer,
132 nSize);
133
134 case ComputerNameDnsDomain:
135 return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
136 L"\\Services\\Tcpip\\Parameters",
137 L"Domain",
138 lpBuffer,
139 nSize);
140
141 case ComputerNameDnsFullyQualified:
142 ResultString.Length = 0;
143 ResultString.MaximumLength = (USHORT)*nSize * sizeof(WCHAR);
144 ResultString.Buffer = lpBuffer;
145
146 RtlZeroMemory(QueryTable, sizeof(QueryTable));
147 RtlInitUnicodeString(&DomainPart, NULL);
148
149 QueryTable[0].Name = L"HostName";
150 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
151 QueryTable[0].EntryContext = &DomainPart;
152
153 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
154 L"\\Registry\\Machine\\System"
155 L"\\CurrentControlSet\\Services\\Tcpip"
156 L"\\Parameters",
157 QueryTable,
158 NULL,
159 NULL);
160
161 if (NT_SUCCESS(Status))
162 {
163 Status = RtlAppendUnicodeStringToString(&ResultString, &DomainPart);
164 HostSize = DomainPart.Length;
165
166 if (!NT_SUCCESS(Status))
167 {
168 ret = FALSE;
169 }
170
171 RtlAppendUnicodeToString(&ResultString, L".");
172 RtlFreeUnicodeString(&DomainPart);
173
174 RtlInitUnicodeString(&DomainPart, NULL);
175 QueryTable[0].Name = L"Domain";
176 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
177 QueryTable[0].EntryContext = &DomainPart;
178
179 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
180 L"\\Registry\\Machine\\System"
181 L"\\CurrentControlSet\\Services\\Tcpip"
182 L"\\Parameters",
183 QueryTable,
184 NULL,
185 NULL);
186
187 if (NT_SUCCESS(Status))
188 {
189 Status = RtlAppendUnicodeStringToString(&ResultString, &DomainPart);
190 if ((!NT_SUCCESS(Status)) || (!ret))
191 {
192 *nSize = HostSize + DomainPart.Length;
193 SetLastError(ERROR_MORE_DATA);
194 RtlFreeUnicodeString(&DomainPart);
195 return FALSE;
196 }
197 RtlFreeUnicodeString(&DomainPart);
198 *nSize = ResultString.Length / sizeof(WCHAR) - 1;
199 return TRUE;
200 }
201 }
202 return FALSE;
203
204 case ComputerNameDnsHostname:
205 return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
206 L"\\Services\\Tcpip\\Parameters",
207 L"Hostname",
208 lpBuffer,
209 nSize);
210
211 case ComputerNamePhysicalDnsDomain:
212 return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
213 L"\\Services\\Tcpip\\Parameters",
214 L"Domain",
215 lpBuffer,
216 nSize);
217
218 /* XXX Redo these */
219 case ComputerNamePhysicalDnsFullyQualified:
220 return GetComputerNameExW(ComputerNameDnsFullyQualified,
221 lpBuffer,
222 nSize);
223
224 case ComputerNamePhysicalDnsHostname:
225 return GetComputerNameExW(ComputerNameDnsHostname,
226 lpBuffer,
227 nSize);
228
229 case ComputerNamePhysicalNetBIOS:
230 return GetComputerNameExW(ComputerNameNetBIOS,
231 lpBuffer,
232 nSize);
233
234 case ComputerNameMax:
235 return FALSE;
236 }
237
238 return FALSE;
239 }
240
241 /*
242 * @implemented
243 */
244 BOOL
245 WINAPI
246 GetComputerNameExA(COMPUTER_NAME_FORMAT NameType,
247 LPSTR lpBuffer,
248 LPDWORD nSize)
249 {
250 UNICODE_STRING UnicodeString;
251 ANSI_STRING AnsiString;
252 BOOL Result;
253 PWCHAR TempBuffer = RtlAllocateHeap( RtlGetProcessHeap(), 0, *nSize * sizeof(WCHAR) );
254
255 if (!TempBuffer)
256 {
257 return ERROR_OUTOFMEMORY;
258 }
259
260 AnsiString.MaximumLength = (USHORT)*nSize;
261 AnsiString.Length = 0;
262 AnsiString.Buffer = lpBuffer;
263
264 Result = GetComputerNameExW(NameType, TempBuffer, nSize);
265
266 if (Result)
267 {
268 UnicodeString.MaximumLength = (USHORT)*nSize * sizeof(WCHAR) + sizeof(WCHAR);
269 UnicodeString.Length = (USHORT)*nSize * sizeof(WCHAR) + sizeof(WCHAR);
270 UnicodeString.Buffer = TempBuffer;
271
272 RtlUnicodeStringToAnsiString(&AnsiString,
273 &UnicodeString,
274 FALSE);
275 }
276
277 RtlFreeHeap(RtlGetProcessHeap(), 0, TempBuffer);
278
279 return Result;
280 }
281
282 /*
283 * @implemented
284 */
285 BOOL
286 WINAPI
287 GetComputerNameA(LPSTR lpBuffer, LPDWORD lpnSize)
288 {
289 return GetComputerNameExA(ComputerNameNetBIOS, lpBuffer, lpnSize);
290 }
291
292
293 /*
294 * @implemented
295 */
296 BOOL
297 WINAPI
298 GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
299 {
300 return GetComputerNameExW(ComputerNameNetBIOS, lpBuffer, lpnSize);
301 }
302
303
304 /*
305 * @implemented
306 */
307 static
308 BOOL
309 IsValidComputerName(COMPUTER_NAME_FORMAT NameType,
310 LPCWSTR lpComputerName)
311 {
312 PWCHAR p;
313 ULONG Length;
314
315 /* FIXME: do verification according to NameType */
316
317 Length = 0;
318 p = (PWCHAR)lpComputerName;
319
320 while (*p != 0)
321 {
322 if (!(iswctype(*p, _ALPHA | _DIGIT) || *p == L'!' || *p == L'@' || *p == L'#' ||
323 *p == L'$' || *p == L'%' || *p == L'^' || *p == L'&' || *p == L'\'' ||
324 *p == L')' || *p == L'(' || *p == L'.' || *p == L'-' || *p == L'_' ||
325 *p == L'{' || *p == L'}' || *p == L'~'))
326 return FALSE;
327
328 Length++;
329 p++;
330 }
331
332 if (Length == 0 || Length > MAX_COMPUTERNAME_LENGTH)
333 return FALSE;
334
335 return TRUE;
336 }
337
338
339 static
340 BOOL
341 SetComputerNameToRegistry(LPCWSTR RegistryKey,
342 LPCWSTR ValueNameStr,
343 LPCWSTR lpBuffer)
344 {
345 OBJECT_ATTRIBUTES ObjectAttributes;
346 UNICODE_STRING KeyName;
347 UNICODE_STRING ValueName;
348 HANDLE KeyHandle;
349 NTSTATUS Status;
350
351 RtlInitUnicodeString(&KeyName, RegistryKey);
352 InitializeObjectAttributes(&ObjectAttributes,
353 &KeyName,
354 OBJ_CASE_INSENSITIVE,
355 NULL,
356 NULL);
357
358 Status = NtOpenKey(&KeyHandle,
359 KEY_WRITE,
360 &ObjectAttributes);
361 if (!NT_SUCCESS(Status))
362 {
363 SetLastErrorByStatus(Status);
364 return FALSE;
365 }
366
367 RtlInitUnicodeString(&ValueName, ValueNameStr);
368
369 Status = NtSetValueKey(KeyHandle,
370 &ValueName,
371 0,
372 REG_SZ,
373 (PVOID)lpBuffer,
374 (wcslen (lpBuffer) + 1) * sizeof(WCHAR));
375 if (!NT_SUCCESS(Status))
376 {
377 ZwClose(KeyHandle);
378 SetLastErrorByStatus(Status);
379 return FALSE;
380 }
381
382 NtFlushKey(KeyHandle);
383 ZwClose(KeyHandle);
384
385 return TRUE;
386 }
387
388
389 /*
390 * @implemented
391 */
392 BOOL
393 WINAPI
394 SetComputerNameA(LPCSTR lpComputerName)
395 {
396 return SetComputerNameExA(ComputerNamePhysicalNetBIOS, lpComputerName);
397 }
398
399
400 /*
401 * @implemented
402 */
403 BOOL
404 WINAPI
405 SetComputerNameW(LPCWSTR lpComputerName)
406 {
407 return SetComputerNameExW(ComputerNamePhysicalNetBIOS, lpComputerName);
408 }
409
410
411 /*
412 * @implemented
413 */
414 BOOL
415 WINAPI
416 SetComputerNameExA(COMPUTER_NAME_FORMAT NameType,
417 LPCSTR lpBuffer)
418 {
419 UNICODE_STRING Buffer;
420 BOOL bResult;
421
422 RtlCreateUnicodeStringFromAsciiz(&Buffer, (LPSTR)lpBuffer);
423
424 bResult = SetComputerNameExW(NameType, Buffer.Buffer);
425
426 RtlFreeUnicodeString(&Buffer);
427
428 return bResult;
429 }
430
431
432 /*
433 * @implemented
434 */
435 BOOL
436 WINAPI
437 SetComputerNameExW(COMPUTER_NAME_FORMAT NameType,
438 LPCWSTR lpBuffer)
439 {
440 if (!IsValidComputerName(NameType, lpBuffer))
441 {
442 SetLastError(ERROR_INVALID_PARAMETER);
443 return FALSE;
444 }
445
446 switch( NameType )
447 {
448 case ComputerNamePhysicalDnsDomain:
449 return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
450 L"\\Services\\Tcpip\\Parameters",
451 L"Domain",
452 lpBuffer);
453
454 case ComputerNamePhysicalDnsHostname:
455 return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
456 L"\\Services\\Tcpip\\Parameters",
457 L"Hostname",
458 lpBuffer);
459
460 case ComputerNamePhysicalNetBIOS:
461 return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
462 L"\\Control\\ComputerName\\ComputerName",
463 L"ComputerName",
464 lpBuffer);
465
466 default:
467 SetLastError (ERROR_INVALID_PARAMETER);
468 return FALSE;
469 }
470 }
471
472
473 /*
474 * @implemented
475 */
476 BOOL
477 WINAPI
478 DnsHostnameToComputerNameA(LPCSTR Hostname,
479 LPSTR ComputerName,
480 LPDWORD nSize)
481 {
482 DWORD len;
483
484 DPRINT("(%s, %p, %p)\n", Hostname, ComputerName, nSize);
485
486 if (!Hostname || !nSize)
487 return FALSE;
488
489 len = lstrlenA(Hostname);
490
491 if (len > MAX_COMPUTERNAME_LENGTH)
492 len = MAX_COMPUTERNAME_LENGTH;
493
494 if (*nSize < len)
495 {
496 *nSize = len;
497 return FALSE;
498 }
499
500 if (!ComputerName) return FALSE;
501
502 memcpy(ComputerName, Hostname, len);
503 ComputerName[len + 1] = 0;
504 return TRUE;
505 }
506
507
508 /*
509 * @implemented
510 */
511 BOOL
512 WINAPI
513 DnsHostnameToComputerNameW(LPCWSTR hostname,
514 LPWSTR computername,
515 LPDWORD size)
516 {
517 DWORD len;
518
519 DPRINT("(%s, %p, %p): stub\n", hostname, computername, size);
520
521 if (!hostname || !size) return FALSE;
522 len = lstrlenW(hostname);
523
524 if (len > MAX_COMPUTERNAME_LENGTH)
525 len = MAX_COMPUTERNAME_LENGTH;
526
527 if (*size < len)
528 {
529 *size = len;
530 return FALSE;
531 }
532 if (!computername) return FALSE;
533
534 memcpy(computername, hostname, len * sizeof(WCHAR));
535 computername[len + 1] = 0;
536 return TRUE;
537 }
538
539 /* EOF */