Implement AddDesktopItem() and DeleteDesktopItem().
[reactos.git] / reactos / lib / userenv / profile.c
1 /* $Id: profile.c,v 1.10 2004/04/29 14:41:26 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 CreateUserProfileA (PSID Sid,
80 LPCSTR lpUserName)
81 {
82 UNICODE_STRING UserName;
83 BOOL bResult;
84 NTSTATUS Status;
85
86 Status = RtlCreateUnicodeStringFromAsciiz (&UserName,
87 (LPSTR)lpUserName);
88 if (!NT_SUCCESS(Status))
89 {
90 SetLastError (RtlNtStatusToDosError (Status));
91 return FALSE;
92 }
93
94 bResult = CreateUserProfileW (Sid,
95 UserName.Buffer);
96
97 RtlFreeUnicodeString (&UserName);
98
99 return bResult;
100 }
101
102
103 BOOL WINAPI
104 CreateUserProfileW (PSID Sid,
105 LPCWSTR lpUserName)
106 {
107 WCHAR szRawProfilesPath[MAX_PATH];
108 WCHAR szProfilesPath[MAX_PATH];
109 WCHAR szUserProfilePath[MAX_PATH];
110 WCHAR szDefaultUserPath[MAX_PATH];
111 WCHAR szBuffer[MAX_PATH];
112 UNICODE_STRING SidString;
113 DWORD dwLength;
114 DWORD dwDisposition;
115 HKEY hKey;
116 NTSTATUS Status;
117
118 DPRINT ("CreateUserProfileW() called\n");
119
120 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
121 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
122 0,
123 KEY_ALL_ACCESS,
124 &hKey))
125 {
126 DPRINT1("Error: %lu\n", GetLastError());
127 return FALSE;
128 }
129
130 /* Get profiles path */
131 dwLength = MAX_PATH * sizeof(WCHAR);
132 if (RegQueryValueExW (hKey,
133 L"ProfilesDirectory",
134 NULL,
135 NULL,
136 (LPBYTE)szRawProfilesPath,
137 &dwLength))
138 {
139 DPRINT1("Error: %lu\n", GetLastError());
140 RegCloseKey (hKey);
141 return FALSE;
142 }
143
144 /* Expand it */
145 if (!ExpandEnvironmentStringsW (szRawProfilesPath,
146 szProfilesPath,
147 MAX_PATH))
148 {
149 DPRINT1("Error: %lu\n", GetLastError());
150 RegCloseKey (hKey);
151 return FALSE;
152 }
153
154 /* Get default user path */
155 dwLength = MAX_PATH * sizeof(WCHAR);
156 if (RegQueryValueExW (hKey,
157 L"DefaultUserProfile",
158 NULL,
159 NULL,
160 (LPBYTE)szBuffer,
161 &dwLength))
162 {
163 DPRINT1("Error: %lu\n", GetLastError());
164 RegCloseKey (hKey);
165 return FALSE;
166 }
167
168 RegCloseKey (hKey);
169
170 wcscpy (szUserProfilePath, szProfilesPath);
171 wcscat (szUserProfilePath, L"\\");
172 wcscat (szUserProfilePath, lpUserName);
173 if (!AppendSystemPostfix (szUserProfilePath, MAX_PATH))
174 {
175 DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
176 RtlFreeUnicodeString (&SidString);
177 RegCloseKey (hKey);
178 return FALSE;
179 }
180
181 wcscpy (szDefaultUserPath, szProfilesPath);
182 wcscat (szDefaultUserPath, L"\\");
183 wcscat (szDefaultUserPath, szBuffer);
184
185 /* Create user profile directory */
186 if (!CreateDirectoryW (szUserProfilePath, NULL))
187 {
188 if (GetLastError () != ERROR_ALREADY_EXISTS)
189 {
190 DPRINT1("Error: %lu\n", GetLastError());
191 return FALSE;
192 }
193 }
194
195 /* Copy default user directory */
196 if (!CopyDirectory (szUserProfilePath, szDefaultUserPath))
197 {
198 DPRINT1("Error: %lu\n", GetLastError());
199 return FALSE;
200 }
201
202 /* Add profile to profile list */
203 Status = RtlConvertSidToUnicodeString (&SidString, Sid, TRUE);
204 if (!NT_SUCCESS(Status))
205 {
206 DPRINT1("Status: %lx\n", Status);
207 return FALSE;
208 }
209
210 wcscpy (szBuffer,
211 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
212 wcscat (szBuffer, SidString.Buffer);
213
214 /* Create user profile key */
215 if (RegCreateKeyExW (HKEY_LOCAL_MACHINE,
216 szBuffer,
217 0,
218 NULL,
219 REG_OPTION_NON_VOLATILE,
220 KEY_ALL_ACCESS,
221 NULL,
222 &hKey,
223 &dwDisposition))
224 {
225 DPRINT1("Error: %lu\n", GetLastError());
226 RtlFreeUnicodeString (&SidString);
227 return FALSE;
228 }
229
230 /* Create non-expanded user profile path */
231 wcscpy (szBuffer, szRawProfilesPath);
232 wcscat (szBuffer, L"\\");
233 wcscat (szBuffer, lpUserName);
234 if (!AppendSystemPostfix (szBuffer, MAX_PATH))
235 {
236 DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
237 RtlFreeUnicodeString (&SidString);
238 RegCloseKey (hKey);
239 return FALSE;
240 }
241
242 /* Set 'ProfileImagePath' value (non-expanded) */
243 if (RegSetValueExW (hKey,
244 L"ProfileImagePath",
245 0,
246 REG_EXPAND_SZ,
247 (LPBYTE)szBuffer,
248 (wcslen (szBuffer) + 1) * sizeof(WCHAR)))
249 {
250 DPRINT1("Error: %lu\n", GetLastError());
251 RtlFreeUnicodeString (&SidString);
252 RegCloseKey (hKey);
253 return FALSE;
254 }
255
256 /* Set 'Sid' value */
257 if (RegSetValueExW (hKey,
258 L"Sid",
259 0,
260 REG_BINARY,
261 Sid,
262 RtlLengthSid (Sid)))
263 {
264 DPRINT1("Error: %lu\n", GetLastError());
265 RtlFreeUnicodeString (&SidString);
266 RegCloseKey (hKey);
267 return FALSE;
268 }
269
270 RegCloseKey (hKey);
271
272 /* Create user hive name */
273 wcscat (szUserProfilePath, L"\\ntuser.dat");
274
275 /* Create new user hive */
276 if (RegLoadKeyW (HKEY_USERS,
277 SidString.Buffer,
278 szUserProfilePath))
279 {
280 DPRINT1("Error: %lu\n", GetLastError());
281 RtlFreeUnicodeString (&SidString);
282 return FALSE;
283 }
284
285 /* Initialize user hive */
286 if (!CreateUserHive (SidString.Buffer))
287 {
288 DPRINT1("Error: %lu\n", GetLastError());
289 RtlFreeUnicodeString (&SidString);
290 return FALSE;
291 }
292
293 RegUnLoadKeyW (HKEY_USERS,
294 SidString.Buffer);
295
296 RtlFreeUnicodeString (&SidString);
297
298 DPRINT ("CreateUserProfileW() done\n");
299
300 return TRUE;
301 }
302
303
304 BOOL WINAPI
305 GetAllUsersProfileDirectoryW (LPWSTR lpProfileDir,
306 LPDWORD lpcchSize)
307 {
308 WCHAR szProfilePath[MAX_PATH];
309 WCHAR szBuffer[MAX_PATH];
310 DWORD dwLength;
311 HKEY hKey;
312
313 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
314 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
315 0,
316 KEY_READ,
317 &hKey))
318 {
319 DPRINT1("Error: %lu\n", GetLastError());
320 return FALSE;
321 }
322
323 /* Get profiles path */
324 dwLength = MAX_PATH * sizeof(WCHAR);
325 if (RegQueryValueExW (hKey,
326 L"ProfilesDirectory",
327 NULL,
328 NULL,
329 (LPBYTE)szBuffer,
330 &dwLength))
331 {
332 DPRINT1("Error: %lu\n", GetLastError());
333 RegCloseKey (hKey);
334 return FALSE;
335 }
336
337 /* Expand it */
338 if (!ExpandEnvironmentStringsW (szBuffer,
339 szProfilePath,
340 MAX_PATH))
341 {
342 DPRINT1("Error: %lu\n", GetLastError());
343 RegCloseKey (hKey);
344 return FALSE;
345 }
346
347 /* Get 'AllUsersProfile' name */
348 dwLength = MAX_PATH * sizeof(WCHAR);
349 if (RegQueryValueExW (hKey,
350 L"AllUsersProfile",
351 NULL,
352 NULL,
353 (LPBYTE)szBuffer,
354 &dwLength))
355 {
356 DPRINT1("Error: %lu\n", GetLastError());
357 RegCloseKey (hKey);
358 return FALSE;
359 }
360
361 RegCloseKey (hKey);
362
363 wcscat (szProfilePath, L"\\");
364 wcscat (szProfilePath, szBuffer);
365
366 dwLength = wcslen (szProfilePath);
367 if (lpProfileDir != NULL)
368 {
369 if (*lpcchSize < dwLength)
370 {
371 *lpcchSize = dwLength;
372 SetLastError (ERROR_INSUFFICIENT_BUFFER);
373 return FALSE;
374 }
375
376 wcscpy (lpProfileDir, szProfilePath);
377 }
378
379 *lpcchSize = dwLength;
380
381 return TRUE;
382 }
383
384
385 BOOL WINAPI
386 GetDefaultUserProfileDirectoryW (LPWSTR lpProfileDir,
387 LPDWORD lpcchSize)
388 {
389 WCHAR szProfilePath[MAX_PATH];
390 WCHAR szBuffer[MAX_PATH];
391 DWORD dwLength;
392 HKEY hKey;
393
394 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
395 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
396 0,
397 KEY_READ,
398 &hKey))
399 {
400 DPRINT1("Error: %lu\n", GetLastError());
401 return FALSE;
402 }
403
404 /* Get profiles path */
405 dwLength = MAX_PATH * sizeof(WCHAR);
406 if (RegQueryValueExW (hKey,
407 L"ProfilesDirectory",
408 NULL,
409 NULL,
410 (LPBYTE)szBuffer,
411 &dwLength))
412 {
413 DPRINT1("Error: %lu\n", GetLastError());
414 RegCloseKey (hKey);
415 return FALSE;
416 }
417
418 /* Expand it */
419 if (!ExpandEnvironmentStringsW (szBuffer,
420 szProfilePath,
421 MAX_PATH))
422 {
423 DPRINT1("Error: %lu\n", GetLastError());
424 RegCloseKey (hKey);
425 return FALSE;
426 }
427
428 /* Get 'DefaultUserProfile' name */
429 dwLength = MAX_PATH * sizeof(WCHAR);
430 if (RegQueryValueExW (hKey,
431 L"DefaultUserProfile",
432 NULL,
433 NULL,
434 (LPBYTE)szBuffer,
435 &dwLength))
436 {
437 DPRINT1("Error: %lu\n", GetLastError());
438 RegCloseKey (hKey);
439 return FALSE;
440 }
441
442 RegCloseKey (hKey);
443
444 wcscat (szProfilePath, L"\\");
445 wcscat (szProfilePath, szBuffer);
446
447 dwLength = wcslen (szProfilePath);
448 if (lpProfileDir != NULL)
449 {
450 if (*lpcchSize < dwLength)
451 {
452 *lpcchSize = dwLength;
453 SetLastError (ERROR_INSUFFICIENT_BUFFER);
454 return FALSE;
455 }
456
457 wcscpy (lpProfileDir, szProfilePath);
458 }
459
460 *lpcchSize = dwLength;
461
462 return TRUE;
463 }
464
465
466 BOOL WINAPI
467 GetProfilesDirectoryW (LPWSTR lpProfilesDir,
468 LPDWORD lpcchSize)
469 {
470 WCHAR szProfilesPath[MAX_PATH];
471 WCHAR szBuffer[MAX_PATH];
472 DWORD dwLength;
473 HKEY hKey;
474
475 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
476 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
477 0,
478 KEY_READ,
479 &hKey))
480 {
481 DPRINT1("Error: %lu\n", GetLastError());
482 return FALSE;
483 }
484
485 /* Get profiles path */
486 dwLength = MAX_PATH * sizeof(WCHAR);
487 if (RegQueryValueExW (hKey,
488 L"ProfilesDirectory",
489 NULL,
490 NULL,
491 (LPBYTE)szBuffer,
492 &dwLength))
493 {
494 DPRINT1("Error: %lu\n", GetLastError());
495 RegCloseKey (hKey);
496 return FALSE;
497 }
498
499 RegCloseKey (hKey);
500
501 /* Expand it */
502 if (!ExpandEnvironmentStringsW (szBuffer,
503 szProfilesPath,
504 MAX_PATH))
505 {
506 DPRINT1("Error: %lu\n", GetLastError());
507 return FALSE;
508 }
509
510 dwLength = wcslen (szProfilesPath);
511 if (lpProfilesDir != NULL)
512 {
513 if (*lpcchSize < dwLength)
514 {
515 *lpcchSize = dwLength;
516 SetLastError (ERROR_INSUFFICIENT_BUFFER);
517 return FALSE;
518 }
519
520 wcscpy (lpProfilesDir, szProfilesPath);
521 }
522
523 *lpcchSize = dwLength;
524
525 return TRUE;
526 }
527
528
529 BOOL WINAPI
530 GetUserProfileDirectoryW (HANDLE hToken,
531 LPWSTR lpProfileDir,
532 LPDWORD lpcchSize)
533 {
534 UNICODE_STRING SidString;
535 WCHAR szKeyName[MAX_PATH];
536 WCHAR szRawImagePath[MAX_PATH];
537 WCHAR szImagePath[MAX_PATH];
538 DWORD dwLength;
539 HKEY hKey;
540
541 if (!GetUserSidFromToken (hToken,
542 &SidString))
543 {
544 DPRINT1 ("GetUserSidFromToken() failed\n");
545 return FALSE;
546 }
547
548 DPRINT ("SidString: '%wZ'\n", &SidString);
549
550 wcscpy (szKeyName,
551 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
552 wcscat (szKeyName,
553 SidString.Buffer);
554
555 RtlFreeUnicodeString (&SidString);
556
557 DPRINT ("KeyName: '%S'\n", szKeyName);
558
559 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
560 szKeyName,
561 0,
562 KEY_ALL_ACCESS,
563 &hKey))
564 {
565 DPRINT1 ("Error: %lu\n", GetLastError());
566 return FALSE;
567 }
568
569 dwLength = MAX_PATH * sizeof(WCHAR);
570 if (RegQueryValueExW (hKey,
571 L"ProfileImagePath",
572 NULL,
573 NULL,
574 (LPBYTE)szRawImagePath,
575 &dwLength))
576 {
577 DPRINT1 ("Error: %lu\n", GetLastError());
578 RegCloseKey (hKey);
579 return FALSE;
580 }
581
582 RegCloseKey (hKey);
583
584 DPRINT ("RawImagePath: '%S'\n", szRawImagePath);
585
586 /* Expand it */
587 if (!ExpandEnvironmentStringsW (szRawImagePath,
588 szImagePath,
589 MAX_PATH))
590 {
591 DPRINT1 ("Error: %lu\n", GetLastError());
592 return FALSE;
593 }
594
595 DPRINT ("ImagePath: '%S'\n", szImagePath);
596
597 dwLength = wcslen (szImagePath);
598 if (dwLength > *lpcchSize)
599 {
600 DPRINT1 ("Buffer too small\n");
601 SetLastError (ERROR_INSUFFICIENT_BUFFER);
602 return FALSE;
603 }
604
605 *lpcchSize = dwLength;
606 wcscpy (lpProfileDir,
607 szImagePath);
608
609 return TRUE;
610 }
611
612
613 static BOOL
614 CheckForLoadedProfile (HANDLE hToken)
615 {
616 UNICODE_STRING SidString;
617 HKEY hKey;
618
619 DPRINT ("CheckForLoadedProfile() called \n");
620
621 if (!GetUserSidFromToken (hToken,
622 &SidString))
623 {
624 DPRINT1 ("GetUserSidFromToken() failed\n");
625 return FALSE;
626 }
627
628 if (RegOpenKeyExW (HKEY_USERS,
629 SidString.Buffer,
630 0,
631 KEY_ALL_ACCESS,
632 &hKey))
633 {
634 DPRINT ("Profile not loaded\n");
635 RtlFreeUnicodeString (&SidString);
636 return FALSE;
637 }
638
639 RegCloseKey (hKey);
640
641 RtlFreeUnicodeString (&SidString);
642
643 DPRINT ("Profile already loaded\n");
644
645 return TRUE;
646 }
647
648
649 BOOL WINAPI
650 LoadUserProfileA (HANDLE hToken,
651 LPPROFILEINFOA lpProfileInfo)
652 {
653 DPRINT ("LoadUserProfileA() not implemented\n");
654 return FALSE;
655 }
656
657
658 BOOL WINAPI
659 LoadUserProfileW (HANDLE hToken,
660 LPPROFILEINFOW lpProfileInfo)
661 {
662 WCHAR szUserHivePath[MAX_PATH];
663 UNICODE_STRING SidString;
664 DWORD dwLength;
665
666 DPRINT ("LoadUserProfileW() called\n");
667
668 /* Check profile info */
669 if (lpProfileInfo->dwSize != sizeof(PROFILEINFOW) ||
670 lpProfileInfo->lpUserName == NULL ||
671 lpProfileInfo->lpUserName[0] == 0)
672 {
673 SetLastError (ERROR_INVALID_PARAMETER);
674 return FALSE;
675 }
676
677 /* Don't load a profile twice */
678 if (CheckForLoadedProfile (hToken))
679 {
680 DPRINT ("Profile already loaded\n");
681 lpProfileInfo->hProfile = NULL;
682 return TRUE;
683 }
684
685 if (!GetProfilesDirectoryW (szUserHivePath,
686 &dwLength))
687 {
688 DPRINT1("GetProfilesDirectoryW() failed\n", GetLastError());
689 return FALSE;
690 }
691
692 wcscat (szUserHivePath, L"\\");
693 wcscat (szUserHivePath, lpProfileInfo->lpUserName);
694 if (!AppendSystemPostfix (szUserHivePath, MAX_PATH))
695 {
696 DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
697 return FALSE;
698 }
699
700 /* Create user hive name */
701 wcscat (szUserHivePath, L"\\ntuser.dat");
702
703 DPRINT ("szUserHivePath: %S\n", szUserHivePath);
704
705 if (!GetUserSidFromToken (hToken,
706 &SidString))
707 {
708 DPRINT1 ("GetUserSidFromToken() failed\n");
709 return FALSE;
710 }
711
712 DPRINT ("SidString: '%wZ'\n", &SidString);
713
714 if (RegLoadKeyW (HKEY_USERS,
715 SidString.Buffer,
716 szUserHivePath))
717 {
718 DPRINT1 ("RegLoadKeyW() failed (Error %ld)\n", GetLastError());
719 RtlFreeUnicodeString (&SidString);
720 return FALSE;
721 }
722
723 if (RegOpenKeyExW (HKEY_USERS,
724 SidString.Buffer,
725 0,
726 KEY_ALL_ACCESS,
727 (PHKEY)&lpProfileInfo->hProfile))
728 {
729 DPRINT1 ("RegOpenKeyExW() failed (Error %ld)\n", GetLastError());
730 RtlFreeUnicodeString (&SidString);
731 return FALSE;
732 }
733
734 RtlFreeUnicodeString (&SidString);
735
736 DPRINT ("LoadUserProfileW() done\n");
737
738 return TRUE;
739 }
740
741
742 BOOL WINAPI
743 UnloadUserProfile (HANDLE hToken,
744 HANDLE hProfile)
745 {
746 UNICODE_STRING SidString;
747
748 DPRINT ("UnloadUserProfile() called\n");
749
750 if (hProfile == NULL)
751 {
752 DPRINT1 ("Invalide profile handle\n");
753 SetLastError (ERROR_INVALID_PARAMETER);
754 return FALSE;
755 }
756
757 RegCloseKey (hProfile);
758
759 if (!GetUserSidFromToken (hToken,
760 &SidString))
761 {
762 DPRINT1 ("GetUserSidFromToken() failed\n");
763 return FALSE;
764 }
765
766 DPRINT ("SidString: '%wZ'\n", &SidString);
767
768 if (RegUnLoadKeyW (HKEY_USERS,
769 SidString.Buffer))
770 {
771 DPRINT1 ("RegUnLoadKeyW() failed (Error %ld)\n", GetLastError());
772 RtlFreeUnicodeString (&SidString);
773 return FALSE;
774 }
775
776 RtlFreeUnicodeString (&SidString);
777
778 DPRINT ("UnloadUserProfile() done\n");
779
780 return TRUE;
781 }
782
783 /* EOF */