- Merge from trunk up to r45543
[reactos.git] / 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
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 (lpBuffer && *nSize > (KeyInfo->DataLength / sizeof(WCHAR)))
96 {
97 *nSize = KeyInfo->DataLength / sizeof(WCHAR) - 1;
98 lpBuffer[*nSize] = 0;
99 }
100 else
101 {
102 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
103 ZwClose(KeyHandle);
104 *nSize = ReturnSize;
105 SetLastErrorByStatus(STATUS_BUFFER_OVERFLOW);
106 return FALSE;
107 }
108
109 RtlCopyMemory(lpBuffer, KeyInfo->Data, *nSize * sizeof(WCHAR));
110
111 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
112 ZwClose(KeyHandle);
113
114 return TRUE;
115 }
116
117 /*
118 * @implemented
119 */
120 BOOL
121 WINAPI
122 GetComputerNameExW(COMPUTER_NAME_FORMAT NameType,
123 LPWSTR lpBuffer,
124 LPDWORD nSize)
125 {
126 UNICODE_STRING ResultString;
127 UNICODE_STRING DomainPart;
128 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
129 NTSTATUS Status;
130 BOOL ret = TRUE;
131 DWORD HostSize;
132
133 switch (NameType)
134 {
135 case ComputerNameNetBIOS:
136 return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
137 L"\\Control\\ComputerName\\ComputerName",
138 L"ComputerName",
139 lpBuffer,
140 nSize);
141
142 case ComputerNameDnsDomain:
143 return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
144 L"\\Services\\Tcpip\\Parameters",
145 L"Domain",
146 lpBuffer,
147 nSize);
148
149 case ComputerNameDnsFullyQualified:
150 ResultString.Length = 0;
151 ResultString.MaximumLength = (USHORT)*nSize * sizeof(WCHAR);
152 ResultString.Buffer = lpBuffer;
153
154 RtlZeroMemory(QueryTable, sizeof(QueryTable));
155 RtlInitUnicodeString(&DomainPart, NULL);
156
157 QueryTable[0].Name = L"HostName";
158 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
159 QueryTable[0].EntryContext = &DomainPart;
160
161 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
162 L"\\Registry\\Machine\\System"
163 L"\\CurrentControlSet\\Services\\Tcpip"
164 L"\\Parameters",
165 QueryTable,
166 NULL,
167 NULL);
168
169 if (NT_SUCCESS(Status))
170 {
171 Status = RtlAppendUnicodeStringToString(&ResultString, &DomainPart);
172 HostSize = DomainPart.Length;
173
174 if (!NT_SUCCESS(Status))
175 {
176 ret = FALSE;
177 }
178
179 RtlAppendUnicodeToString(&ResultString, L".");
180 RtlFreeUnicodeString(&DomainPart);
181
182 RtlInitUnicodeString(&DomainPart, NULL);
183 QueryTable[0].Name = L"Domain";
184 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
185 QueryTable[0].EntryContext = &DomainPart;
186
187 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
188 L"\\Registry\\Machine\\System"
189 L"\\CurrentControlSet\\Services\\Tcpip"
190 L"\\Parameters",
191 QueryTable,
192 NULL,
193 NULL);
194
195 if (NT_SUCCESS(Status))
196 {
197 Status = RtlAppendUnicodeStringToString(&ResultString, &DomainPart);
198 if ((!NT_SUCCESS(Status)) || (!ret))
199 {
200 *nSize = HostSize + DomainPart.Length;
201 SetLastError(ERROR_MORE_DATA);
202 RtlFreeUnicodeString(&DomainPart);
203 return FALSE;
204 }
205 RtlFreeUnicodeString(&DomainPart);
206 *nSize = ResultString.Length / sizeof(WCHAR) - 1;
207 return TRUE;
208 }
209 }
210 return FALSE;
211
212 case ComputerNameDnsHostname:
213 return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
214 L"\\Services\\Tcpip\\Parameters",
215 L"Hostname",
216 lpBuffer,
217 nSize);
218
219 case ComputerNamePhysicalDnsDomain:
220 return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
221 L"\\Services\\Tcpip\\Parameters",
222 L"Domain",
223 lpBuffer,
224 nSize);
225
226 /* XXX Redo these */
227 case ComputerNamePhysicalDnsFullyQualified:
228 return GetComputerNameExW(ComputerNameDnsFullyQualified,
229 lpBuffer,
230 nSize);
231
232 case ComputerNamePhysicalDnsHostname:
233 return GetComputerNameExW(ComputerNameDnsHostname,
234 lpBuffer,
235 nSize);
236
237 case ComputerNamePhysicalNetBIOS:
238 return GetComputerNameExW(ComputerNameNetBIOS,
239 lpBuffer,
240 nSize);
241
242 case ComputerNameMax:
243 return FALSE;
244 }
245
246 return FALSE;
247 }
248
249 /*
250 * @implemented
251 */
252 BOOL
253 WINAPI
254 GetComputerNameExA(COMPUTER_NAME_FORMAT NameType,
255 LPSTR lpBuffer,
256 LPDWORD nSize)
257 {
258 UNICODE_STRING UnicodeString;
259 ANSI_STRING AnsiString;
260 BOOL Result;
261 PWCHAR TempBuffer = RtlAllocateHeap( RtlGetProcessHeap(), 0, *nSize * sizeof(WCHAR) );
262
263 if (!TempBuffer)
264 {
265 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
266 return FALSE;
267 }
268
269 AnsiString.MaximumLength = (USHORT)*nSize;
270 AnsiString.Length = 0;
271 AnsiString.Buffer = lpBuffer;
272
273 Result = GetComputerNameExW(NameType, TempBuffer, nSize);
274
275 if (Result)
276 {
277 UnicodeString.MaximumLength = (USHORT)*nSize * sizeof(WCHAR) + sizeof(WCHAR);
278 UnicodeString.Length = (USHORT)*nSize * sizeof(WCHAR) + sizeof(WCHAR);
279 UnicodeString.Buffer = TempBuffer;
280
281 RtlUnicodeStringToAnsiString(&AnsiString,
282 &UnicodeString,
283 FALSE);
284 }
285
286 RtlFreeHeap(RtlGetProcessHeap(), 0, TempBuffer);
287
288 return Result;
289 }
290
291 /*
292 * @implemented
293 */
294 BOOL
295 WINAPI
296 GetComputerNameA(LPSTR lpBuffer, LPDWORD lpnSize)
297 {
298 BOOL ret;
299 ret = GetComputerNameExA(ComputerNameNetBIOS, lpBuffer, lpnSize);
300 if(!ret && GetLastError() == ERROR_MORE_DATA)
301 SetLastError(ERROR_BUFFER_OVERFLOW);
302 return ret;
303 }
304
305
306 /*
307 * @implemented
308 */
309 BOOL
310 WINAPI
311 GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
312 {
313 BOOL ret;
314 ret=GetComputerNameExW(ComputerNameNetBIOS, lpBuffer, lpnSize);
315 if(!ret && GetLastError() == ERROR_MORE_DATA)
316 SetLastError(ERROR_BUFFER_OVERFLOW);
317 return ret;
318 }
319
320
321 /*
322 * @implemented
323 */
324 static
325 BOOL
326 IsValidComputerName(COMPUTER_NAME_FORMAT NameType,
327 LPCWSTR lpComputerName)
328 {
329 PWCHAR p;
330 ULONG Length;
331
332 /* FIXME: do verification according to NameType */
333
334 Length = 0;
335 p = (PWCHAR)lpComputerName;
336
337 while (*p != 0)
338 {
339 if (!(iswctype(*p, _ALPHA | _DIGIT) || *p == L'!' || *p == L'@' || *p == L'#' ||
340 *p == L'$' || *p == L'%' || *p == L'^' || *p == L'&' || *p == L'\'' ||
341 *p == L')' || *p == L'(' || *p == L'.' || *p == L'-' || *p == L'_' ||
342 *p == L'{' || *p == L'}' || *p == L'~'))
343 return FALSE;
344
345 Length++;
346 p++;
347 }
348
349 if (Length == 0 || Length > MAX_COMPUTERNAME_LENGTH)
350 return FALSE;
351
352 return TRUE;
353 }
354
355
356 static
357 BOOL
358 SetComputerNameToRegistry(LPCWSTR RegistryKey,
359 LPCWSTR ValueNameStr,
360 LPCWSTR lpBuffer)
361 {
362 OBJECT_ATTRIBUTES ObjectAttributes;
363 UNICODE_STRING KeyName;
364 UNICODE_STRING ValueName;
365 HANDLE KeyHandle;
366 NTSTATUS Status;
367
368 RtlInitUnicodeString(&KeyName, RegistryKey);
369 InitializeObjectAttributes(&ObjectAttributes,
370 &KeyName,
371 OBJ_CASE_INSENSITIVE,
372 NULL,
373 NULL);
374
375 Status = NtOpenKey(&KeyHandle,
376 KEY_WRITE,
377 &ObjectAttributes);
378 if (!NT_SUCCESS(Status))
379 {
380 SetLastErrorByStatus(Status);
381 return FALSE;
382 }
383
384 RtlInitUnicodeString(&ValueName, ValueNameStr);
385
386 Status = NtSetValueKey(KeyHandle,
387 &ValueName,
388 0,
389 REG_SZ,
390 (PVOID)lpBuffer,
391 (wcslen (lpBuffer) + 1) * sizeof(WCHAR));
392 if (!NT_SUCCESS(Status))
393 {
394 ZwClose(KeyHandle);
395 SetLastErrorByStatus(Status);
396 return FALSE;
397 }
398
399 NtFlushKey(KeyHandle);
400 ZwClose(KeyHandle);
401
402 return TRUE;
403 }
404
405
406 /*
407 * @implemented
408 */
409 BOOL
410 WINAPI
411 SetComputerNameA(LPCSTR lpComputerName)
412 {
413 return SetComputerNameExA(ComputerNamePhysicalNetBIOS, lpComputerName);
414 }
415
416
417 /*
418 * @implemented
419 */
420 BOOL
421 WINAPI
422 SetComputerNameW(LPCWSTR lpComputerName)
423 {
424 return SetComputerNameExW(ComputerNamePhysicalNetBIOS, lpComputerName);
425 }
426
427
428 /*
429 * @implemented
430 */
431 BOOL
432 WINAPI
433 SetComputerNameExA(COMPUTER_NAME_FORMAT NameType,
434 LPCSTR lpBuffer)
435 {
436 UNICODE_STRING Buffer;
437 BOOL bResult;
438
439 RtlCreateUnicodeStringFromAsciiz(&Buffer, (LPSTR)lpBuffer);
440
441 bResult = SetComputerNameExW(NameType, Buffer.Buffer);
442
443 RtlFreeUnicodeString(&Buffer);
444
445 return bResult;
446 }
447
448
449 /*
450 * @implemented
451 */
452 BOOL
453 WINAPI
454 SetComputerNameExW(COMPUTER_NAME_FORMAT NameType,
455 LPCWSTR lpBuffer)
456 {
457 if (!IsValidComputerName(NameType, lpBuffer))
458 {
459 SetLastError(ERROR_INVALID_PARAMETER);
460 return FALSE;
461 }
462
463 switch( NameType )
464 {
465 case ComputerNamePhysicalDnsDomain:
466 return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
467 L"\\Services\\Tcpip\\Parameters",
468 L"Domain",
469 lpBuffer);
470
471 case ComputerNamePhysicalDnsHostname:
472 return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
473 L"\\Services\\Tcpip\\Parameters",
474 L"Hostname",
475 lpBuffer);
476
477 case ComputerNamePhysicalNetBIOS:
478 return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
479 L"\\Control\\ComputerName\\ComputerName",
480 L"ComputerName",
481 lpBuffer);
482
483 default:
484 SetLastError (ERROR_INVALID_PARAMETER);
485 return FALSE;
486 }
487 }
488
489
490 /*
491 * @implemented
492 */
493 BOOL
494 WINAPI
495 DnsHostnameToComputerNameA(LPCSTR Hostname,
496 LPSTR ComputerName,
497 LPDWORD nSize)
498 {
499 DWORD len;
500
501 DPRINT("(%s, %p, %p)\n", Hostname, ComputerName, nSize);
502
503 if (!Hostname || !nSize)
504 return FALSE;
505
506 len = lstrlenA(Hostname);
507
508 if (len > MAX_COMPUTERNAME_LENGTH)
509 len = MAX_COMPUTERNAME_LENGTH;
510
511 if (*nSize < len)
512 {
513 *nSize = len;
514 return FALSE;
515 }
516
517 if (!ComputerName) return FALSE;
518
519 memcpy(ComputerName, Hostname, len);
520 ComputerName[len + 1] = 0;
521 return TRUE;
522 }
523
524
525 /*
526 * @implemented
527 */
528 BOOL
529 WINAPI
530 DnsHostnameToComputerNameW(LPCWSTR hostname,
531 LPWSTR computername,
532 LPDWORD size)
533 {
534 DWORD len;
535
536 DPRINT("(%s, %p, %p): stub\n", hostname, computername, size);
537
538 if (!hostname || !size) return FALSE;
539 len = lstrlenW(hostname);
540
541 if (len > MAX_COMPUTERNAME_LENGTH)
542 len = MAX_COMPUTERNAME_LENGTH;
543
544 if (*size < len)
545 {
546 *size = len;
547 return FALSE;
548 }
549 if (!computername) return FALSE;
550
551 memcpy(computername, hostname, len * sizeof(WCHAR));
552 computername[len + 1] = 0;
553 return TRUE;
554 }
555
556 /* EOF */