update for HEAD-2003091401
[reactos.git] / 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 /* $Id$
20  *
21  * COPYRIGHT:       See COPYING in the top level directory
22  * PROJECT:         ReactOS system libraries
23  * PURPOSE:         Computer name functions
24  * FILE:            lib/kernel32/misc/computername.c
25  * PROGRAMER:       Eric Kohl (ekohl@rz-online.de)
26  */
27
28 /* INCLUDES ******************************************************************/
29
30 #include <k32.h>
31
32 #define NDEBUG
33 #include <kernel32/kernel32.h>
34
35
36 /* FUNCTIONS *****************************************************************/
37
38 /*
39  * @implemented
40  */
41 BOOL STDCALL
42 GetComputerNameA (LPSTR lpBuffer,
43                   LPDWORD lpnSize)
44 {
45   UNICODE_STRING UnicodeString;
46   ANSI_STRING AnsiString;
47
48   AnsiString.MaximumLength = *lpnSize;
49   AnsiString.Length = 0;
50   AnsiString.Buffer = lpBuffer;
51
52   UnicodeString.MaximumLength = *lpnSize * sizeof(WCHAR);
53   UnicodeString.Length = 0;
54   UnicodeString.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
55                                           0,
56                                           UnicodeString.MaximumLength);
57   if (UnicodeString.Buffer == NULL)
58     {
59       SetLastError (ERROR_OUTOFMEMORY);
60       return FALSE;
61     }
62
63   if (!GetComputerNameW (UnicodeString.Buffer, lpnSize))
64     {
65       RtlFreeUnicodeString (&UnicodeString);
66       return FALSE;
67     }
68
69   UnicodeString.Length = *lpnSize * sizeof(WCHAR);
70
71   RtlUnicodeStringToAnsiString (&AnsiString,
72                                 &UnicodeString,
73                                 FALSE);
74
75   RtlFreeUnicodeString (&UnicodeString);
76
77   return TRUE;
78 }
79
80
81 /*
82  * @implemented
83  */
84 BOOL STDCALL
85 GetComputerNameW (LPWSTR lpBuffer,
86                   LPDWORD lpnSize)
87 {
88   PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
89   OBJECT_ATTRIBUTES ObjectAttributes;
90   UNICODE_STRING KeyName;
91   UNICODE_STRING ValueName;
92   HANDLE KeyHandle;
93   ULONG KeyInfoSize;
94   ULONG ReturnSize;
95   NTSTATUS Status;
96
97   RtlInitUnicodeString (&KeyName,
98                         L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName\\ComputerName");
99   InitializeObjectAttributes (&ObjectAttributes,
100                               &KeyName,
101                               OBJ_CASE_INSENSITIVE,
102                               NULL,
103                               NULL);
104   Status = NtOpenKey (&KeyHandle,
105                       KEY_READ,
106                       &ObjectAttributes);
107   if (!NT_SUCCESS(Status))
108     {
109       SetLastErrorByStatus (Status);
110       return FALSE;
111     }
112
113   KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
114                 *lpnSize * sizeof(WCHAR);
115   KeyInfo = RtlAllocateHeap (RtlGetProcessHeap (),
116                              0,
117                              KeyInfoSize);
118   if (KeyInfo == NULL)
119     {
120       NtClose (KeyHandle);
121       SetLastError (ERROR_OUTOFMEMORY);
122       return FALSE;
123     }
124
125   RtlInitUnicodeString (&ValueName,
126                         L"ComputerName");
127
128   Status = NtQueryValueKey (KeyHandle,
129                             &ValueName,
130                             KeyValuePartialInformation,
131                             KeyInfo,
132                             KeyInfoSize,
133                             &ReturnSize);
134   if (!NT_SUCCESS(Status))
135     {
136       RtlFreeHeap (RtlGetProcessHeap (),
137                    0,
138                    KeyInfo);
139       NtClose (KeyHandle);
140       SetLastErrorByStatus (Status);
141       return FALSE;
142     }
143
144   *lpnSize =
145     (KeyInfo->DataLength != 0) ? (KeyInfo->DataLength / sizeof(WCHAR)) - 1 : 0;
146
147   RtlCopyMemory (lpBuffer,
148                  KeyInfo->Data,
149                  KeyInfo->DataLength);
150   lpBuffer[*lpnSize] = 0;
151
152   RtlFreeHeap (RtlGetProcessHeap (),
153                0,
154                KeyInfo);
155   NtClose (KeyHandle);
156
157   return TRUE;
158 }
159
160
161 /*
162  * @implemented
163  */
164 BOOL STDCALL
165 SetComputerNameA (LPCSTR lpComputerName)
166 {
167   UNICODE_STRING ComputerName;
168   BOOL bResult;
169
170   RtlCreateUnicodeStringFromAsciiz (&ComputerName,
171                                     (LPSTR)lpComputerName);
172
173   bResult = SetComputerNameW (ComputerName.Buffer);
174
175   RtlFreeUnicodeString (&ComputerName);
176
177   return bResult;
178 }
179
180
181 /*
182  * @implemented
183  */
184 static BOOL
185 IsValidComputerName (LPCWSTR lpComputerName)
186 {
187   PWCHAR p;
188   ULONG Length;
189
190   Length = 0;
191   p = (PWCHAR)lpComputerName;
192   while (*p != 0)
193     {
194       if (!(iswctype (*p, _ALPHA || _DIGIT) ||
195             *p == L'!' ||
196             *p == L'@' ||
197             *p == L'#' ||
198             *p == L'$' ||
199             *p == L'%' ||
200             *p == L'^' ||
201             *p == L'&' ||
202             *p == L'\'' ||
203             *p == L')' ||
204             *p == L'(' ||
205             *p == L'.' ||
206             *p == L'-' ||
207             *p == L'_' ||
208             *p == L'{' ||
209             *p == L'}' ||
210             *p == L'~'))
211         return FALSE;
212
213       Length++;
214       p++;
215     }
216
217   if (Length == 0 ||
218       Length > MAX_COMPUTERNAME_LENGTH)
219     return FALSE;
220
221   return TRUE;
222 }
223
224
225 /*
226  * @implemented
227  */
228 BOOL STDCALL
229 SetComputerNameW (LPCWSTR lpComputerName)
230 {
231   OBJECT_ATTRIBUTES ObjectAttributes;
232   UNICODE_STRING KeyName;
233   UNICODE_STRING ValueName;
234   HANDLE KeyHandle;
235   NTSTATUS Status;
236
237   if (!IsValidComputerName (lpComputerName))
238     {
239       SetLastError (ERROR_INVALID_PARAMETER);
240       return FALSE;
241     }
242
243   RtlInitUnicodeString (&KeyName,
244                         L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName\\ComputerName");
245   InitializeObjectAttributes (&ObjectAttributes,
246                               &KeyName,
247                               OBJ_CASE_INSENSITIVE,
248                               NULL,
249                               NULL);
250   Status = NtOpenKey (&KeyHandle,
251                       KEY_WRITE,
252                       &ObjectAttributes);
253   if (!NT_SUCCESS(Status))
254     {
255       SetLastErrorByStatus (Status);
256       return FALSE;
257     }
258
259   RtlInitUnicodeString (&ValueName,
260                         L"ComputerName");
261
262   Status = NtSetValueKey (KeyHandle,
263                           &ValueName,
264                           0,
265                           REG_SZ,
266                           (PVOID)lpComputerName,
267                           (wcslen (lpComputerName) + 1) * sizeof(WCHAR));
268   if (!NT_SUCCESS(Status))
269     {
270       NtClose (KeyHandle);
271       SetLastErrorByStatus (Status);
272       return FALSE;
273     }
274
275   NtFlushKey (KeyHandle);
276   NtClose (KeyHandle);
277
278   return TRUE;
279 }
280
281 /* EOF */