Complete user profile creation.
[reactos.git] / reactos / lib / userenv / profile.c
1 /* $Id: profile.c,v 1.5 2004/02/28 11:30:59 ekohl Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/userenv/profile.c
6 * PURPOSE: User profile code
7 * PROGRAMMER: Eric Kohl
8 */
9
10 #include <ntos.h>
11 #include <windows.h>
12 #include <string.h>
13
14 #include <userenv.h>
15
16 #include "internal.h"
17
18
19 /* FUNCTIONS ***************************************************************/
20
21 BOOL
22 AppendSystemPostfix (LPWSTR lpName,
23 DWORD dwMaxLength)
24 {
25 WCHAR szSystemRoot[MAX_PATH];
26 WCHAR szDrivePostfix[3];
27 LPWSTR lpszPostfix;
28 LPWSTR lpszPtr;
29 DWORD dwPostfixLength;
30
31 /* Build profile name postfix */
32 if (!ExpandEnvironmentStringsW (L"%SystemRoot%",
33 szSystemRoot,
34 MAX_PATH))
35 {
36 DPRINT1("Error: %lu\n", GetLastError());
37 return FALSE;
38 }
39
40 _wcsupr (szSystemRoot);
41
42 /* Get name postfix */
43 szSystemRoot[2] = L'.';
44 lpszPostfix = &szSystemRoot[2];
45 lpszPtr = lpszPostfix;
46 while (*lpszPtr != (WCHAR)0)
47 {
48 if (*lpszPtr == L'\\')
49 *lpszPtr = '_';
50 lpszPtr++;
51 }
52
53 dwPostfixLength = wcslen (lpszPostfix);
54 if (szSystemRoot[0] != L'C')
55 {
56 dwPostfixLength += 2;
57 szDrivePostfix[0] = L'_';
58 szDrivePostfix[1] = szSystemRoot[0];
59 szDrivePostfix[2] = (WCHAR)0;
60 }
61
62 if (wcslen (lpName) + dwPostfixLength >= dwMaxLength)
63 {
64 DPRINT1("Error: buffer overflow\n");
65 return FALSE;
66 }
67
68 wcscat (lpName, lpszPostfix);
69 if (szSystemRoot[0] != L'C')
70 {
71 wcscat (lpName, szDrivePostfix);
72 }
73
74 return TRUE;
75 }
76
77
78 BOOL WINAPI
79 CreateUserProfileW (PSID Sid,
80 LPCWSTR lpUserName)
81 {
82 WCHAR szRawProfilesPath[MAX_PATH];
83 WCHAR szProfilesPath[MAX_PATH];
84 WCHAR szUserProfilePath[MAX_PATH];
85 WCHAR szDefaultUserPath[MAX_PATH];
86 WCHAR szBuffer[MAX_PATH];
87 UNICODE_STRING SidString;
88 DWORD dwLength;
89 DWORD dwDisposition;
90 HKEY hKey;
91 NTSTATUS Status;
92
93 DPRINT ("CreateUserProfileW() called\n");
94
95 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
96 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
97 0,
98 KEY_ALL_ACCESS,
99 &hKey))
100 {
101 DPRINT1("Error: %lu\n", GetLastError());
102 return FALSE;
103 }
104
105 /* Get profiles path */
106 dwLength = MAX_PATH * sizeof(WCHAR);
107 if (RegQueryValueExW (hKey,
108 L"ProfilesDirectory",
109 NULL,
110 NULL,
111 (LPBYTE)szRawProfilesPath,
112 &dwLength))
113 {
114 DPRINT1("Error: %lu\n", GetLastError());
115 RegCloseKey (hKey);
116 return FALSE;
117 }
118
119 /* Expand it */
120 if (!ExpandEnvironmentStringsW (szRawProfilesPath,
121 szProfilesPath,
122 MAX_PATH))
123 {
124 DPRINT1("Error: %lu\n", GetLastError());
125 RegCloseKey (hKey);
126 return FALSE;
127 }
128
129 /* Get default user path */
130 dwLength = MAX_PATH * sizeof(WCHAR);
131 if (RegQueryValueExW (hKey,
132 L"DefaultUserProfile",
133 NULL,
134 NULL,
135 (LPBYTE)szBuffer,
136 &dwLength))
137 {
138 DPRINT1("Error: %lu\n", GetLastError());
139 RegCloseKey (hKey);
140 return FALSE;
141 }
142
143 RegCloseKey (hKey);
144
145 wcscpy (szUserProfilePath, szProfilesPath);
146 wcscat (szUserProfilePath, L"\\");
147 wcscat (szUserProfilePath, lpUserName);
148 if (!AppendSystemPostfix (szUserProfilePath, MAX_PATH))
149 {
150 DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
151 RtlFreeUnicodeString (&SidString);
152 RegCloseKey (hKey);
153 return FALSE;
154 }
155
156 wcscpy (szDefaultUserPath, szProfilesPath);
157 wcscat (szDefaultUserPath, L"\\");
158 wcscat (szDefaultUserPath, szBuffer);
159
160 /* Create user profile directory */
161 if (!CreateDirectoryW (szUserProfilePath, NULL))
162 {
163 if (GetLastError () != ERROR_ALREADY_EXISTS)
164 {
165 DPRINT1("Error: %lu\n", GetLastError());
166 return FALSE;
167 }
168 }
169
170 /* Copy default user directory */
171 if (!CopyDirectory (szUserProfilePath, szDefaultUserPath))
172 {
173 DPRINT1("Error: %lu\n", GetLastError());
174 return FALSE;
175 }
176
177 /* Add profile to profile list */
178 Status = RtlConvertSidToUnicodeString (&SidString, Sid, TRUE);
179 if (!NT_SUCCESS(Status))
180 {
181 DPRINT1("Status: %lx\n", Status);
182 return FALSE;
183 }
184
185 wcscpy (szBuffer,
186 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
187 wcscat (szBuffer, SidString.Buffer);
188
189 /* Create user profile key */
190 if (RegCreateKeyExW (HKEY_LOCAL_MACHINE,
191 szBuffer,
192 0,
193 NULL,
194 REG_OPTION_NON_VOLATILE,
195 KEY_ALL_ACCESS,
196 NULL,
197 &hKey,
198 &dwDisposition))
199 {
200 DPRINT1("Error: %lu\n", GetLastError());
201 RtlFreeUnicodeString (&SidString);
202 return FALSE;
203 }
204
205 /* Create non-expanded user profile path */
206 wcscpy (szBuffer, szRawProfilesPath);
207 wcscat (szBuffer, L"\\");
208 wcscat (szBuffer, lpUserName);
209 if (!AppendSystemPostfix (szBuffer, MAX_PATH))
210 {
211 DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
212 RtlFreeUnicodeString (&SidString);
213 RegCloseKey (hKey);
214 return FALSE;
215 }
216
217 /* Set 'ProfileImagePath' value (non-expanded) */
218 if (RegSetValueExW (hKey,
219 L"ProfileImagePath",
220 0,
221 REG_EXPAND_SZ,
222 (LPBYTE)szBuffer,
223 (wcslen (szBuffer) + 1) * sizeof(WCHAR)))
224 {
225 DPRINT1("Error: %lu\n", GetLastError());
226 RtlFreeUnicodeString (&SidString);
227 RegCloseKey (hKey);
228 return FALSE;
229 }
230
231 /* Set 'Sid' value */
232 if (RegSetValueExW (hKey,
233 L"Sid",
234 0,
235 REG_BINARY,
236 Sid,
237 RtlLengthSid (Sid)))
238 {
239 DPRINT1("Error: %lu\n", GetLastError());
240 RtlFreeUnicodeString (&SidString);
241 RegCloseKey (hKey);
242 return FALSE;
243 }
244
245 RegCloseKey (hKey);
246
247 /* Create user hive name */
248 wcscat (szUserProfilePath, L"\\ntuser.dat");
249
250 /* Create new user hive */
251 if (RegLoadKeyW (HKEY_USERS,
252 SidString.Buffer,
253 szUserProfilePath))
254 {
255 DPRINT1("Error: %lu\n", GetLastError());
256 RtlFreeUnicodeString (&SidString);
257 return FALSE;
258 }
259
260 /* Initialize user hive */
261 if (!CreateUserHive (SidString.Buffer))
262 {
263 DPRINT1("Error: %lu\n", GetLastError());
264 RtlFreeUnicodeString (&SidString);
265 return FALSE;
266 }
267
268 RegUnLoadKeyW (HKEY_USERS,
269 SidString.Buffer);
270
271 RtlFreeUnicodeString (&SidString);
272
273 DPRINT ("CreateUserProfileW() done\n");
274
275 return TRUE;
276 }
277
278
279 BOOL WINAPI
280 GetAllUsersProfileDirectoryW (LPWSTR lpProfileDir,
281 LPDWORD lpcchSize)
282 {
283 WCHAR szProfilePath[MAX_PATH];
284 WCHAR szBuffer[MAX_PATH];
285 DWORD dwLength;
286 HKEY hKey;
287
288 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
289 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
290 0,
291 KEY_READ,
292 &hKey))
293 {
294 DPRINT1("Error: %lu\n", GetLastError());
295 return FALSE;
296 }
297
298 /* Get profiles path */
299 dwLength = MAX_PATH * sizeof(WCHAR);
300 if (RegQueryValueExW (hKey,
301 L"ProfilesDirectory",
302 NULL,
303 NULL,
304 (LPBYTE)szBuffer,
305 &dwLength))
306 {
307 DPRINT1("Error: %lu\n", GetLastError());
308 RegCloseKey (hKey);
309 return FALSE;
310 }
311
312 /* Expand it */
313 if (!ExpandEnvironmentStringsW (szBuffer,
314 szProfilePath,
315 MAX_PATH))
316 {
317 DPRINT1("Error: %lu\n", GetLastError());
318 RegCloseKey (hKey);
319 return FALSE;
320 }
321
322 /* Get 'AllUsersProfile' name */
323 dwLength = MAX_PATH * sizeof(WCHAR);
324 if (RegQueryValueExW (hKey,
325 L"AllUsersProfile",
326 NULL,
327 NULL,
328 (LPBYTE)szBuffer,
329 &dwLength))
330 {
331 DPRINT1("Error: %lu\n", GetLastError());
332 RegCloseKey (hKey);
333 return FALSE;
334 }
335
336 RegCloseKey (hKey);
337
338 wcscat (szProfilePath, L"\\");
339 wcscat (szProfilePath, szBuffer);
340
341 dwLength = wcslen (szProfilePath);
342 if (lpProfileDir != NULL)
343 {
344 if (*lpcchSize < dwLength)
345 {
346 *lpcchSize = dwLength;
347 SetLastError (ERROR_INSUFFICIENT_BUFFER);
348 return FALSE;
349 }
350
351 wcscpy (lpProfileDir, szProfilePath);
352 }
353
354 *lpcchSize = dwLength;
355
356 return TRUE;
357 }
358
359
360 BOOL WINAPI
361 GetDefaultUserProfileDirectoryW (LPWSTR lpProfileDir,
362 LPDWORD lpcchSize)
363 {
364 WCHAR szProfilePath[MAX_PATH];
365 WCHAR szBuffer[MAX_PATH];
366 DWORD dwLength;
367 HKEY hKey;
368
369 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
370 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
371 0,
372 KEY_READ,
373 &hKey))
374 {
375 DPRINT1("Error: %lu\n", GetLastError());
376 return FALSE;
377 }
378
379 /* Get profiles path */
380 dwLength = MAX_PATH * sizeof(WCHAR);
381 if (RegQueryValueExW (hKey,
382 L"ProfilesDirectory",
383 NULL,
384 NULL,
385 (LPBYTE)szBuffer,
386 &dwLength))
387 {
388 DPRINT1("Error: %lu\n", GetLastError());
389 RegCloseKey (hKey);
390 return FALSE;
391 }
392
393 /* Expand it */
394 if (!ExpandEnvironmentStringsW (szBuffer,
395 szProfilePath,
396 MAX_PATH))
397 {
398 DPRINT1("Error: %lu\n", GetLastError());
399 RegCloseKey (hKey);
400 return FALSE;
401 }
402
403 /* Get 'DefaultUserProfile' name */
404 dwLength = MAX_PATH * sizeof(WCHAR);
405 if (RegQueryValueExW (hKey,
406 L"DefaultUserProfile",
407 NULL,
408 NULL,
409 (LPBYTE)szBuffer,
410 &dwLength))
411 {
412 DPRINT1("Error: %lu\n", GetLastError());
413 RegCloseKey (hKey);
414 return FALSE;
415 }
416
417 RegCloseKey (hKey);
418
419 wcscat (szProfilePath, L"\\");
420 wcscat (szProfilePath, szBuffer);
421
422 dwLength = wcslen (szProfilePath);
423 if (lpProfileDir != NULL)
424 {
425 if (*lpcchSize < dwLength)
426 {
427 *lpcchSize = dwLength;
428 SetLastError (ERROR_INSUFFICIENT_BUFFER);
429 return FALSE;
430 }
431
432 wcscpy (lpProfileDir, szProfilePath);
433 }
434
435 *lpcchSize = dwLength;
436
437 return TRUE;
438 }
439
440
441 BOOL WINAPI
442 GetProfilesDirectoryW (LPWSTR lpProfilesDir,
443 LPDWORD lpcchSize)
444 {
445 WCHAR szProfilesPath[MAX_PATH];
446 WCHAR szBuffer[MAX_PATH];
447 DWORD dwLength;
448 HKEY hKey;
449
450 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
451 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
452 0,
453 KEY_READ,
454 &hKey))
455 {
456 DPRINT1("Error: %lu\n", GetLastError());
457 return FALSE;
458 }
459
460 /* Get profiles path */
461 dwLength = MAX_PATH * sizeof(WCHAR);
462 if (RegQueryValueExW (hKey,
463 L"ProfilesDirectory",
464 NULL,
465 NULL,
466 (LPBYTE)szBuffer,
467 &dwLength))
468 {
469 DPRINT1("Error: %lu\n", GetLastError());
470 RegCloseKey (hKey);
471 return FALSE;
472 }
473
474 RegCloseKey (hKey);
475
476 /* Expand it */
477 if (!ExpandEnvironmentStringsW (szBuffer,
478 szProfilesPath,
479 MAX_PATH))
480 {
481 DPRINT1("Error: %lu\n", GetLastError());
482 return FALSE;
483 }
484
485 dwLength = wcslen (szProfilesPath);
486 if (lpProfilesDir != NULL)
487 {
488 if (*lpcchSize < dwLength)
489 {
490 *lpcchSize = dwLength;
491 SetLastError (ERROR_INSUFFICIENT_BUFFER);
492 return FALSE;
493 }
494
495 wcscpy (lpProfilesDir, szProfilesPath);
496 }
497
498 *lpcchSize = dwLength;
499
500 return TRUE;
501 }
502
503
504 BOOL WINAPI
505 GetUserProfileDirectoryW (HANDLE hToken,
506 LPWSTR lpProfileDir,
507 LPDWORD lpcchSize)
508 {
509 /* FIXME */
510 return GetDefaultUserProfileDirectoryW (lpProfileDir, lpcchSize);
511 }
512
513
514 BOOL WINAPI
515 LoadUserProfileW (HANDLE hToken,
516 LPPROFILEINFOW lpProfileInfo)
517 {
518
519 /* Check profile info */
520 if (lpProfileInfo->dwSize != sizeof(PROFILEINFOW) ||
521 lpProfileInfo->lpUserName == NULL ||
522 lpProfileInfo->lpUserName[0] == 0)
523 {
524 SetLastError (ERROR_INVALID_PARAMETER);
525 return FALSE;
526 }
527
528 /* FIXME: load the profile */
529
530 return TRUE;
531 }
532
533 /* EOF */