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