3bed83dac3de37b59d8d0719cb6353c9b80b1212
[reactos.git] / reactos / dll / win32 / kernel32 / client / compname.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: dll/win32/kernel32/client/compname.c
24 * PROGRAMER: Eric Kohl
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 = NtOpenKey(&KeyHandle,
61 KEY_READ,
62 &ObjectAttributes);
63 if (!NT_SUCCESS(Status))
64 {
65 BaseSetLastNTError (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 NtClose(KeyHandle);
74 SetLastError(ERROR_OUTOFMEMORY);
75 return FALSE;
76 }
77
78 RtlInitUnicodeString(&ValueName, ValueNameStr);
79
80 Status = NtQueryValueKey(KeyHandle,
81 &ValueName,
82 KeyValuePartialInformation,
83 KeyInfo,
84 KeyInfoSize,
85 &ReturnSize);
86
87 NtClose(KeyHandle);
88
89 if (!NT_SUCCESS(Status))
90 {
91 *nSize = (ReturnSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data)) / sizeof(WCHAR);
92 goto failed;
93 }
94
95 if (KeyInfo->Type != REG_SZ)
96 {
97 Status = STATUS_UNSUCCESSFUL;
98 goto failed;
99 }
100
101 if (!lpBuffer || *nSize < (KeyInfo->DataLength / sizeof(WCHAR)))
102 {
103 *nSize = (ReturnSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data)) / sizeof(WCHAR);
104 Status = STATUS_BUFFER_OVERFLOW;
105 goto failed;
106 }
107
108 *nSize = KeyInfo->DataLength / sizeof(WCHAR) - 1;
109 RtlCopyMemory(lpBuffer, KeyInfo->Data, KeyInfo->DataLength);
110 lpBuffer[*nSize] = 0;
111
112 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
113
114 return TRUE;
115
116 failed:
117 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
118 BaseSetLastNTError(Status);
119 return FALSE;
120 }
121
122 /*
123 * @implemented
124 */
125 BOOL
126 WINAPI
127 GetComputerNameExW(COMPUTER_NAME_FORMAT NameType,
128 LPWSTR lpBuffer,
129 LPDWORD nSize)
130 {
131 UNICODE_STRING ResultString;
132 UNICODE_STRING DomainPart;
133 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
134 NTSTATUS Status;
135 BOOL ret = TRUE;
136 DWORD HostSize;
137
138 if ((nSize == NULL) ||
139 (lpBuffer == NULL && *nSize > 0))
140 {
141 SetLastError(ERROR_INVALID_PARAMETER);
142 return FALSE;
143 }
144
145 switch (NameType)
146 {
147 case ComputerNameNetBIOS:
148 return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
149 L"\\Control\\ComputerName\\ComputerName",
150 L"ComputerName",
151 lpBuffer,
152 nSize);
153
154 case ComputerNameDnsDomain:
155 return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
156 L"\\Services\\Tcpip\\Parameters",
157 L"Domain",
158 lpBuffer,
159 nSize);
160
161 case ComputerNameDnsFullyQualified:
162 ResultString.Length = 0;
163 ResultString.MaximumLength = (USHORT)*nSize * sizeof(WCHAR);
164 ResultString.Buffer = lpBuffer;
165
166 RtlZeroMemory(QueryTable, sizeof(QueryTable));
167 RtlInitUnicodeString(&DomainPart, NULL);
168
169 QueryTable[0].Name = L"HostName";
170 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
171 QueryTable[0].EntryContext = &DomainPart;
172
173 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
174 L"\\Registry\\Machine\\System"
175 L"\\CurrentControlSet\\Services\\Tcpip"
176 L"\\Parameters",
177 QueryTable,
178 NULL,
179 NULL);
180
181 if (NT_SUCCESS(Status))
182 {
183 Status = RtlAppendUnicodeStringToString(&ResultString, &DomainPart);
184 HostSize = DomainPart.Length;
185
186 if (!NT_SUCCESS(Status))
187 {
188 ret = FALSE;
189 }
190
191 RtlAppendUnicodeToString(&ResultString, L".");
192 RtlFreeUnicodeString(&DomainPart);
193
194 RtlInitUnicodeString(&DomainPart, NULL);
195 QueryTable[0].Name = L"Domain";
196 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
197 QueryTable[0].EntryContext = &DomainPart;
198
199 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
200 L"\\Registry\\Machine\\System"
201 L"\\CurrentControlSet\\Services\\Tcpip"
202 L"\\Parameters",
203 QueryTable,
204 NULL,
205 NULL);
206
207 if (NT_SUCCESS(Status))
208 {
209 Status = RtlAppendUnicodeStringToString(&ResultString, &DomainPart);
210 if ((!NT_SUCCESS(Status)) || (!ret))
211 {
212 *nSize = HostSize + DomainPart.Length;
213 SetLastError(ERROR_MORE_DATA);
214 RtlFreeUnicodeString(&DomainPart);
215 return FALSE;
216 }
217 RtlFreeUnicodeString(&DomainPart);
218 *nSize = ResultString.Length / sizeof(WCHAR) - 1;
219 return TRUE;
220 }
221 }
222 return FALSE;
223
224 case ComputerNameDnsHostname:
225 return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
226 L"\\Services\\Tcpip\\Parameters",
227 L"Hostname",
228 lpBuffer,
229 nSize);
230
231 case ComputerNamePhysicalDnsDomain:
232 return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
233 L"\\Services\\Tcpip\\Parameters",
234 L"Domain",
235 lpBuffer,
236 nSize);
237
238 /* XXX Redo these */
239 case ComputerNamePhysicalDnsFullyQualified:
240 return GetComputerNameExW(ComputerNameDnsFullyQualified,
241 lpBuffer,
242 nSize);
243
244 case ComputerNamePhysicalDnsHostname:
245 return GetComputerNameExW(ComputerNameDnsHostname,
246 lpBuffer,
247 nSize);
248
249 case ComputerNamePhysicalNetBIOS:
250 return GetComputerNameExW(ComputerNameNetBIOS,
251 lpBuffer,
252 nSize);
253
254 case ComputerNameMax:
255 return FALSE;
256 }
257
258 return FALSE;
259 }
260
261 /*
262 * @implemented
263 */
264 BOOL
265 WINAPI
266 GetComputerNameExA(COMPUTER_NAME_FORMAT NameType,
267 LPSTR lpBuffer,
268 LPDWORD nSize)
269 {
270 UNICODE_STRING UnicodeString;
271 ANSI_STRING AnsiString;
272 BOOL Result;
273 PWCHAR TempBuffer = NULL;
274
275 if ((nSize == NULL) ||
276 (lpBuffer == NULL && *nSize > 0))
277 {
278 SetLastError(ERROR_INVALID_PARAMETER);
279 return FALSE;
280 }
281
282 if (*nSize > 0)
283 {
284 TempBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *nSize * sizeof(WCHAR));
285 if (!TempBuffer)
286 {
287 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
288 return FALSE;
289 }
290 }
291
292 AnsiString.MaximumLength = (USHORT)*nSize;
293 AnsiString.Length = 0;
294 AnsiString.Buffer = lpBuffer;
295
296 Result = GetComputerNameExW(NameType, TempBuffer, nSize);
297
298 if (Result)
299 {
300 UnicodeString.MaximumLength = (USHORT)*nSize * sizeof(WCHAR) + sizeof(WCHAR);
301 UnicodeString.Length = (USHORT)*nSize * sizeof(WCHAR);
302 UnicodeString.Buffer = TempBuffer;
303
304 RtlUnicodeStringToAnsiString(&AnsiString,
305 &UnicodeString,
306 FALSE);
307 }
308
309 RtlFreeHeap(RtlGetProcessHeap(), 0, TempBuffer);
310
311 return Result;
312 }
313
314 /*
315 * @implemented
316 */
317 BOOL
318 WINAPI
319 GetComputerNameA(LPSTR lpBuffer, LPDWORD lpnSize)
320 {
321 BOOL ret;
322
323 ret = GetComputerNameExA(ComputerNameNetBIOS, lpBuffer, lpnSize);
324 if (!ret && GetLastError() == ERROR_MORE_DATA)
325 SetLastError(ERROR_BUFFER_OVERFLOW);
326
327 return ret;
328 }
329
330
331 /*
332 * @implemented
333 */
334 BOOL
335 WINAPI
336 GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
337 {
338 BOOL ret;
339 ret=GetComputerNameExW(ComputerNameNetBIOS, lpBuffer, lpnSize);
340 if(!ret && GetLastError() == ERROR_MORE_DATA)
341 SetLastError(ERROR_BUFFER_OVERFLOW);
342 return ret;
343 }
344
345
346 /*
347 * @implemented
348 */
349 static
350 BOOL
351 IsValidComputerName(COMPUTER_NAME_FORMAT NameType,
352 LPCWSTR lpComputerName)
353 {
354 PWCHAR p;
355 ULONG Length;
356
357 /* FIXME: do verification according to NameType */
358
359 Length = 0;
360 p = (PWCHAR)lpComputerName;
361
362 while (*p != 0)
363 {
364 if (!(iswctype(*p, _ALPHA | _DIGIT) || *p == L'!' || *p == L'@' || *p == L'#' ||
365 *p == L'$' || *p == L'%' || *p == L'^' || *p == L'&' || *p == L'\'' ||
366 *p == L')' || *p == L'(' || *p == L'.' || *p == L'-' || *p == L'_' ||
367 *p == L'{' || *p == L'}' || *p == L'~'))
368 return FALSE;
369
370 Length++;
371 p++;
372 }
373
374 if (Length == 0 || Length > MAX_COMPUTERNAME_LENGTH)
375 return FALSE;
376
377 return TRUE;
378 }
379
380
381 static
382 BOOL
383 SetComputerNameToRegistry(LPCWSTR RegistryKey,
384 LPCWSTR ValueNameStr,
385 LPCWSTR lpBuffer)
386 {
387 OBJECT_ATTRIBUTES ObjectAttributes;
388 UNICODE_STRING KeyName;
389 UNICODE_STRING ValueName;
390 HANDLE KeyHandle;
391 NTSTATUS Status;
392
393 RtlInitUnicodeString(&KeyName, RegistryKey);
394 InitializeObjectAttributes(&ObjectAttributes,
395 &KeyName,
396 OBJ_CASE_INSENSITIVE,
397 NULL,
398 NULL);
399
400 Status = NtOpenKey(&KeyHandle,
401 KEY_WRITE,
402 &ObjectAttributes);
403 if (!NT_SUCCESS(Status))
404 {
405 BaseSetLastNTError(Status);
406 return FALSE;
407 }
408
409 RtlInitUnicodeString(&ValueName, ValueNameStr);
410
411 Status = NtSetValueKey(KeyHandle,
412 &ValueName,
413 0,
414 REG_SZ,
415 (PVOID)lpBuffer,
416 (wcslen (lpBuffer) + 1) * sizeof(WCHAR));
417 if (!NT_SUCCESS(Status))
418 {
419 NtClose(KeyHandle);
420 BaseSetLastNTError(Status);
421 return FALSE;
422 }
423
424 NtFlushKey(KeyHandle);
425 NtClose(KeyHandle);
426
427 return TRUE;
428 }
429
430
431 /*
432 * @implemented
433 */
434 BOOL
435 WINAPI
436 SetComputerNameA(LPCSTR lpComputerName)
437 {
438 return SetComputerNameExA(ComputerNamePhysicalNetBIOS, lpComputerName);
439 }
440
441
442 /*
443 * @implemented
444 */
445 BOOL
446 WINAPI
447 SetComputerNameW(LPCWSTR lpComputerName)
448 {
449 return SetComputerNameExW(ComputerNamePhysicalNetBIOS, lpComputerName);
450 }
451
452
453 /*
454 * @implemented
455 */
456 BOOL
457 WINAPI
458 SetComputerNameExA(COMPUTER_NAME_FORMAT NameType,
459 LPCSTR lpBuffer)
460 {
461 UNICODE_STRING Buffer;
462 BOOL bResult;
463
464 RtlCreateUnicodeStringFromAsciiz(&Buffer, (LPSTR)lpBuffer);
465
466 bResult = SetComputerNameExW(NameType, Buffer.Buffer);
467
468 RtlFreeUnicodeString(&Buffer);
469
470 return bResult;
471 }
472
473
474 /*
475 * @implemented
476 */
477 BOOL
478 WINAPI
479 SetComputerNameExW(COMPUTER_NAME_FORMAT NameType,
480 LPCWSTR lpBuffer)
481 {
482 if (!IsValidComputerName(NameType, lpBuffer))
483 {
484 SetLastError(ERROR_INVALID_PARAMETER);
485 return FALSE;
486 }
487
488 switch( NameType )
489 {
490 case ComputerNamePhysicalDnsDomain:
491 return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
492 L"\\Services\\Tcpip\\Parameters",
493 L"Domain",
494 lpBuffer);
495
496 case ComputerNamePhysicalDnsHostname:
497 return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
498 L"\\Services\\Tcpip\\Parameters",
499 L"Hostname",
500 lpBuffer);
501
502 case ComputerNamePhysicalNetBIOS:
503 return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
504 L"\\Control\\ComputerName\\ComputerName",
505 L"ComputerName",
506 lpBuffer);
507
508 default:
509 SetLastError (ERROR_INVALID_PARAMETER);
510 return FALSE;
511 }
512 }
513
514
515 /*
516 * @implemented
517 */
518 BOOL
519 WINAPI
520 DnsHostnameToComputerNameA(LPCSTR Hostname,
521 LPSTR ComputerName,
522 LPDWORD nSize)
523 {
524 DWORD len;
525
526 DPRINT("(%s, %p, %p)\n", Hostname, ComputerName, nSize);
527
528 if (!Hostname || !nSize)
529 return FALSE;
530
531 len = lstrlenA(Hostname);
532
533 if (len > MAX_COMPUTERNAME_LENGTH)
534 len = MAX_COMPUTERNAME_LENGTH;
535
536 if (*nSize < len)
537 {
538 *nSize = len;
539 return FALSE;
540 }
541
542 if (!ComputerName) return FALSE;
543
544 memcpy(ComputerName, Hostname, len);
545 ComputerName[len + 1] = 0;
546 return TRUE;
547 }
548
549
550 /*
551 * @implemented
552 */
553 BOOL
554 WINAPI
555 DnsHostnameToComputerNameW(LPCWSTR hostname,
556 LPWSTR computername,
557 LPDWORD size)
558 {
559 DWORD len;
560
561 DPRINT("(%s, %p, %p): stub\n", hostname, computername, size);
562
563 if (!hostname || !size) return FALSE;
564 len = lstrlenW(hostname);
565
566 if (len > MAX_COMPUTERNAME_LENGTH)
567 len = MAX_COMPUTERNAME_LENGTH;
568
569 if (*size < len)
570 {
571 *size = len;
572 return FALSE;
573 }
574 if (!computername) return FALSE;
575
576 memcpy(computername, hostname, len * sizeof(WCHAR));
577 computername[len + 1] = 0;
578 return TRUE;
579 }
580
581 DWORD
582 WINAPI
583 AddLocalAlternateComputerNameA(LPSTR lpName, PNTSTATUS Status)
584 {
585 STUB;
586 return 0;
587 }
588
589 DWORD
590 WINAPI
591 AddLocalAlternateComputerNameW(LPWSTR lpName, PNTSTATUS Status)
592 {
593 STUB;
594 return 0;
595 }
596
597 DWORD
598 WINAPI
599 EnumerateLocalComputerNamesA(PVOID pUnknown, DWORD Size, LPSTR lpBuffer, LPDWORD lpnSize)
600 {
601 STUB;
602 return ERROR_CALL_NOT_IMPLEMENTED;
603 }
604
605 DWORD
606 WINAPI
607 EnumerateLocalComputerNamesW(PVOID pUnknown, DWORD Size, LPWSTR lpBuffer, LPDWORD lpnSize)
608 {
609 STUB;
610 return ERROR_CALL_NOT_IMPLEMENTED;
611 }
612
613 DWORD
614 WINAPI
615 RemoveLocalAlternateComputerNameA(LPSTR lpName, DWORD Unknown)
616 {
617 STUB;
618 return ERROR_CALL_NOT_IMPLEMENTED;
619 }
620
621 DWORD
622 WINAPI
623 RemoveLocalAlternateComputerNameW(LPWSTR lpName, DWORD Unknown)
624 {
625 STUB;
626 return ERROR_CALL_NOT_IMPLEMENTED;
627 }
628
629 /*
630 * @unimplemented
631 */
632 BOOL
633 WINAPI
634 SetLocalPrimaryComputerNameA(IN DWORD Unknown1,
635 IN DWORD Unknown2)
636 {
637 STUB;
638 return FALSE;
639 }
640
641 /*
642 * @unimplemented
643 */
644 BOOL
645 WINAPI
646 SetLocalPrimaryComputerNameW(IN DWORD Unknown1,
647 IN DWORD Unknown2)
648 {
649 STUB;
650 return FALSE;
651 }
652
653
654 /* EOF */