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