Implementation of GetVolumeNameForVolumeMountPointW (depends on mount manager, so...
[reactos.git] / reactos / lib / 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 "../include/debug.h"
33
34
35 /* FUNCTIONS *****************************************************************/
36
37 static BOOL GetComputerNameFromRegistry( LPWSTR RegistryKey,
38 LPWSTR ValueNameStr,
39 LPWSTR lpBuffer,
40 LPDWORD nSize ) {
41 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
42 OBJECT_ATTRIBUTES ObjectAttributes;
43 UNICODE_STRING KeyName;
44 UNICODE_STRING ValueName;
45 HANDLE KeyHandle;
46 ULONG KeyInfoSize;
47 ULONG ReturnSize;
48 NTSTATUS Status;
49
50 RtlInitUnicodeString (&KeyName,RegistryKey);
51 InitializeObjectAttributes (&ObjectAttributes,
52 &KeyName,
53 OBJ_CASE_INSENSITIVE,
54 NULL,
55 NULL);
56 Status = ZwOpenKey (&KeyHandle,
57 KEY_READ,
58 &ObjectAttributes);
59 if (!NT_SUCCESS(Status))
60 {
61 SetLastErrorByStatus (Status);
62 return FALSE;
63 }
64
65 KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
66 *nSize * sizeof(WCHAR);
67 KeyInfo = RtlAllocateHeap (RtlGetProcessHeap (),
68 0,
69 KeyInfoSize);
70 if (KeyInfo == NULL)
71 {
72 ZwClose (KeyHandle);
73 SetLastError (ERROR_OUTOFMEMORY);
74 return FALSE;
75 }
76
77 RtlInitUnicodeString (&ValueName,ValueNameStr);
78
79 Status = ZwQueryValueKey (KeyHandle,
80 &ValueName,
81 KeyValuePartialInformation,
82 KeyInfo,
83 KeyInfoSize,
84 &ReturnSize);
85 if (!NT_SUCCESS(Status))
86 {
87 RtlFreeHeap (RtlGetProcessHeap (),
88 0,
89 KeyInfo);
90 ZwClose (KeyHandle);
91 SetLastErrorByStatus (Status);
92 return FALSE;
93 }
94
95 if( *nSize > (KeyInfo->DataLength / sizeof(WCHAR)) ) {
96 *nSize = KeyInfo->DataLength / sizeof(WCHAR);
97 lpBuffer[*nSize] = 0;
98 }
99
100 RtlCopyMemory (lpBuffer,
101 KeyInfo->Data,
102 *nSize * sizeof(WCHAR));
103
104 RtlFreeHeap (RtlGetProcessHeap (),
105 0,
106 KeyInfo)
107 ;
108 ZwClose (KeyHandle);
109
110 return TRUE;
111 }
112
113 /*
114 * @implemented
115 */
116 BOOL STDCALL
117 GetComputerNameExW (
118 COMPUTER_NAME_FORMAT NameType,
119 LPWSTR lpBuffer,
120 LPDWORD nSize
121 )
122 {
123 UNICODE_STRING ResultString;
124 UNICODE_STRING DomainPart;
125 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
126 NTSTATUS Status;
127
128 switch( NameType ) {
129 case ComputerNameNetBIOS:
130 return GetComputerNameFromRegistry
131 ( L"\\Registry\\Machine\\System\\CurrentControlSet"
132 L"\\Control\\ComputerName\\ComputerName",
133 L"ComputerName",
134 lpBuffer,
135 nSize );
136
137 case ComputerNameDnsDomain:
138 return GetComputerNameFromRegistry
139 ( L"\\Registry\\Machine\\System\\CurrentControlSet"
140 L"\\Services\\Tcpip\\Parameters",
141 L"Domain",
142 lpBuffer,
143 nSize );
144
145 case ComputerNameDnsFullyQualified:
146 ResultString.Length = 0;
147 ResultString.MaximumLength = *nSize * sizeof(WCHAR);
148 ResultString.Buffer = lpBuffer;
149
150 RtlZeroMemory(QueryTable, sizeof(QueryTable));
151 RtlInitUnicodeString(&DomainPart, NULL);
152 QueryTable[0].Name = L"HostName";
153 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
154 QueryTable[0].EntryContext = &DomainPart;
155
156 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
157 L"\\Registry\\Machine\\System"
158 L"\\CurrentControlSet\\Services\\Tcpip"
159 L"\\Parameters",
160 QueryTable, NULL, NULL);
161
162 if( NT_SUCCESS(Status) ) {
163 RtlAppendUnicodeStringToString(&ResultString, &DomainPart);
164 RtlAppendUnicodeToString(&ResultString, L".");
165 RtlFreeUnicodeString(&DomainPart);
166
167 RtlInitUnicodeString(&DomainPart, NULL);
168 QueryTable[0].Name = L"Domain";
169 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
170 QueryTable[0].EntryContext = &DomainPart;
171
172 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
173 L"\\Registry\\Machine\\System"
174 L"\\CurrentControlSet\\Services\\Tcpip"
175 L"\\Parameters",
176 QueryTable, NULL, NULL);
177
178 if( NT_SUCCESS(Status) ) {
179 RtlAppendUnicodeStringToString(&ResultString, &DomainPart);
180 RtlFreeUnicodeString(&DomainPart);
181 *nSize = ResultString.Length / sizeof(WCHAR);
182 return TRUE;
183 }
184 }
185 return FALSE;
186
187 case ComputerNameDnsHostname:
188 return GetComputerNameFromRegistry
189 ( L"\\Registry\\Machine\\System\\CurrentControlSet"
190 L"\\Services\\Tcpip\\Parameters",
191 L"Hostname",
192 lpBuffer,
193 nSize );
194
195 case ComputerNamePhysicalDnsDomain:
196 return GetComputerNameFromRegistry
197 ( L"\\Registry\\Machine\\System\\CurrentControlSet"
198 L"\\Services\\Tcpip\\Parameters",
199 L"Domain",
200 lpBuffer,
201 nSize );
202
203 /* XXX Redo these */
204 case ComputerNamePhysicalDnsFullyQualified:
205 return GetComputerNameExW( ComputerNameDnsFullyQualified,
206 lpBuffer, nSize );
207 case ComputerNamePhysicalDnsHostname:
208 return GetComputerNameExW( ComputerNameDnsHostname,
209 lpBuffer, nSize );
210 case ComputerNamePhysicalNetBIOS:
211 return GetComputerNameExW( ComputerNameNetBIOS,
212 lpBuffer, nSize );
213
214 case ComputerNameMax:
215 return FALSE;
216 }
217
218 return FALSE;
219 }
220
221 /*
222 * @implemented
223 */
224 BOOL
225 STDCALL
226 GetComputerNameExA (
227 COMPUTER_NAME_FORMAT NameType,
228 LPSTR lpBuffer,
229 LPDWORD nSize
230 )
231 {
232 UNICODE_STRING UnicodeString;
233 ANSI_STRING AnsiString;
234 BOOL Result;
235 PWCHAR TempBuffer = RtlAllocateHeap( GetProcessHeap(), 0, *nSize * sizeof(WCHAR) );
236
237 if( !TempBuffer ) {
238 return ERROR_OUTOFMEMORY;
239 }
240
241 AnsiString.MaximumLength = *nSize;
242 AnsiString.Length = 0;
243 AnsiString.Buffer = lpBuffer;
244
245 Result = GetComputerNameExW( NameType, TempBuffer, nSize );
246
247 if( Result ) {
248 UnicodeString.MaximumLength = *nSize * sizeof(WCHAR);
249 UnicodeString.Length = *nSize * sizeof(WCHAR);
250 UnicodeString.Buffer = TempBuffer;
251
252 RtlUnicodeStringToAnsiString (&AnsiString,
253 &UnicodeString,
254 FALSE);
255 }
256
257 HeapFree( GetProcessHeap(), 0, TempBuffer );
258
259 return Result;
260 }
261
262 /*
263 * @implemented
264 */
265 BOOL STDCALL
266 GetComputerNameA (LPSTR lpBuffer,
267 LPDWORD lpnSize)
268 {
269 return GetComputerNameExA( ComputerNameNetBIOS, lpBuffer, lpnSize );
270 }
271
272
273 /*
274 * @implemented
275 */
276 BOOL STDCALL
277 GetComputerNameW (LPWSTR lpBuffer,
278 LPDWORD lpnSize)
279 {
280 return GetComputerNameExW( ComputerNameNetBIOS, lpBuffer, lpnSize );
281 }
282
283
284 /*
285 * @implemented
286 */
287 static BOOL
288 IsValidComputerName (
289 COMPUTER_NAME_FORMAT NameType,
290 LPCWSTR lpComputerName)
291 {
292 PWCHAR p;
293 ULONG Length;
294
295 /* FIXME: do verification according to NameType */
296
297 Length = 0;
298 p = (PWCHAR)lpComputerName;
299 while (*p != 0)
300 {
301 if (!(iswctype (*p, _ALPHA || _DIGIT) ||
302 *p == L'!' ||
303 *p == L'@' ||
304 *p == L'#' ||
305 *p == L'$' ||
306 *p == L'%' ||
307 *p == L'^' ||
308 *p == L'&' ||
309 *p == L'\'' ||
310 *p == L')' ||
311 *p == L'(' ||
312 *p == L'.' ||
313 *p == L'-' ||
314 *p == L'_' ||
315 *p == L'{' ||
316 *p == L'}' ||
317 *p == L'~'))
318 return FALSE;
319
320 Length++;
321 p++;
322 }
323
324 if (Length == 0 ||
325 Length > MAX_COMPUTERNAME_LENGTH)
326 return FALSE;
327
328 return TRUE;
329 }
330
331
332 static BOOL SetComputerNameToRegistry(
333 LPCWSTR RegistryKey,
334 LPCWSTR ValueNameStr,
335 LPCWSTR lpBuffer)
336 {
337 OBJECT_ATTRIBUTES ObjectAttributes;
338 UNICODE_STRING KeyName;
339 UNICODE_STRING ValueName;
340 HANDLE KeyHandle;
341 NTSTATUS Status;
342
343 RtlInitUnicodeString (&KeyName, RegistryKey);
344 InitializeObjectAttributes (&ObjectAttributes,
345 &KeyName,
346 OBJ_CASE_INSENSITIVE,
347 NULL,
348 NULL );
349
350 Status = NtOpenKey (&KeyHandle,
351 KEY_WRITE,
352 &ObjectAttributes);
353 if (!NT_SUCCESS(Status))
354 {
355 SetLastErrorByStatus (Status);
356 return FALSE;
357 }
358
359 RtlInitUnicodeString (&ValueName, ValueNameStr);
360
361 Status = NtSetValueKey (KeyHandle,
362 &ValueName,
363 0,
364 REG_SZ,
365 (PVOID)lpBuffer,
366 (wcslen (lpBuffer) + 1) * sizeof(WCHAR));
367 if (!NT_SUCCESS(Status))
368 {
369 ZwClose (KeyHandle);
370 SetLastErrorByStatus (Status);
371 return FALSE;
372 }
373
374 NtFlushKey (KeyHandle);
375 ZwClose (KeyHandle);
376
377 return TRUE;
378 }
379
380
381 /*
382 * @implemented
383 */
384 BOOL STDCALL
385 SetComputerNameA (LPCSTR lpComputerName)
386 {
387 return SetComputerNameExA( ComputerNamePhysicalNetBIOS, lpComputerName );
388 }
389
390
391 /*
392 * @implemented
393 */
394 BOOL STDCALL
395 SetComputerNameW (LPCWSTR lpComputerName)
396 {
397 return SetComputerNameExW( ComputerNamePhysicalNetBIOS, lpComputerName );
398 }
399
400
401 /*
402 * @implemented
403 */
404 BOOL STDCALL
405 SetComputerNameExA (
406 COMPUTER_NAME_FORMAT NameType,
407 LPCSTR lpBuffer)
408 {
409 UNICODE_STRING Buffer;
410 BOOL bResult;
411
412 RtlCreateUnicodeStringFromAsciiz (&Buffer,
413 (LPSTR)lpBuffer);
414
415 bResult = SetComputerNameExW (NameType, Buffer.Buffer);
416
417 RtlFreeUnicodeString (&Buffer);
418
419 return bResult;
420 }
421
422
423 /*
424 * @implemented
425 */
426 BOOL STDCALL
427 SetComputerNameExW (
428 COMPUTER_NAME_FORMAT NameType,
429 LPCWSTR lpBuffer)
430 {
431 if (!IsValidComputerName (NameType, lpBuffer))
432 {
433 SetLastError (ERROR_INVALID_PARAMETER);
434 return FALSE;
435 }
436
437 switch( NameType ) {
438 case ComputerNamePhysicalDnsDomain:
439 return SetComputerNameToRegistry
440 ( L"\\Registry\\Machine\\System\\CurrentControlSet"
441 L"\\Services\\Tcpip\\Parameters",
442 L"Domain",
443 lpBuffer );
444
445 case ComputerNamePhysicalDnsHostname:
446 return SetComputerNameToRegistry
447 ( L"\\Registry\\Machine\\System\\CurrentControlSet"
448 L"\\Services\\Tcpip\\Parameters",
449 L"Hostname",
450 lpBuffer );
451
452 case ComputerNamePhysicalNetBIOS:
453 return SetComputerNameToRegistry
454 ( L"\\Registry\\Machine\\System\\CurrentControlSet"
455 L"\\Control\\ComputerName\\ComputerName",
456 L"ComputerName",
457 lpBuffer );
458
459 default:
460 SetLastError (ERROR_INVALID_PARAMETER);
461 return FALSE;
462 }
463 }
464
465 /* EOF */