6b4635ba062b9c960b49c1f435cd93140f798a8b
[reactos.git] / dll / win32 / userenv / profile.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/userenv/profile.c
5 * PURPOSE: User profile code
6 * PROGRAMMERS: Eric Kohl
7 * Hervé Poussineau
8 */
9
10 #include "precomp.h"
11
12 #include <sddl.h>
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* FUNCTIONS ***************************************************************/
18
19 BOOL
20 AppendSystemPostfix(LPWSTR lpName,
21 DWORD dwMaxLength)
22 {
23 WCHAR szSystemRoot[MAX_PATH];
24 LPWSTR lpszPostfix;
25 LPWSTR lpszPtr;
26
27 /* Build profile name postfix */
28 if (!ExpandEnvironmentStringsW(L"%SystemRoot%",
29 szSystemRoot,
30 ARRAYSIZE(szSystemRoot)))
31 {
32 DPRINT1("Error: %lu\n", GetLastError());
33 return FALSE;
34 }
35
36 _wcsupr(szSystemRoot);
37
38 /* Get name postfix */
39 szSystemRoot[2] = L'.';
40 lpszPostfix = &szSystemRoot[2];
41 lpszPtr = lpszPostfix;
42 while (*lpszPtr != (WCHAR)0)
43 {
44 if (*lpszPtr == L'\\')
45 *lpszPtr = L'_';
46 lpszPtr++;
47 }
48
49 if (wcslen(lpName) + wcslen(lpszPostfix) + 1 >= dwMaxLength)
50 {
51 DPRINT1("Error: buffer overflow\n");
52 SetLastError(ERROR_BUFFER_OVERFLOW);
53 return FALSE;
54 }
55
56 wcscat(lpName, lpszPostfix);
57
58 return TRUE;
59 }
60
61
62 static
63 BOOL
64 AcquireRemoveRestorePrivilege(IN BOOL bAcquire)
65 {
66 BOOL bRet = FALSE;
67 HANDLE Token;
68 TOKEN_PRIVILEGES TokenPriv;
69
70 DPRINT("AcquireRemoveRestorePrivilege(%d)\n", bAcquire);
71
72 if (OpenProcessToken(GetCurrentProcess(),
73 TOKEN_ADJUST_PRIVILEGES,
74 &Token))
75 {
76 TokenPriv.PrivilegeCount = 1;
77 TokenPriv.Privileges[0].Attributes = (bAcquire ? SE_PRIVILEGE_ENABLED : 0);
78
79 if (LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &TokenPriv.Privileges[0].Luid))
80 {
81 bRet = AdjustTokenPrivileges(Token, FALSE, &TokenPriv, 0, NULL, NULL);
82
83 if (!bRet)
84 {
85 DPRINT1("AdjustTokenPrivileges() failed with error %lu\n", GetLastError());
86 }
87 else if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
88 {
89 DPRINT1("AdjustTokenPrivileges() succeeded, but with not all privileges assigned\n");
90 bRet = FALSE;
91 }
92 }
93 else
94 {
95 DPRINT1("LookupPrivilegeValue() failed with error %lu\n", GetLastError());
96 }
97
98 CloseHandle(Token);
99 }
100 else
101 {
102 DPRINT1("OpenProcessToken() failed with error %lu\n", GetLastError());
103 }
104
105 return bRet;
106 }
107
108
109 static
110 BOOL
111 CheckForLoadedProfile(HANDLE hToken)
112 {
113 UNICODE_STRING SidString;
114 HKEY hKey;
115
116 DPRINT("CheckForLoadedProfile() called\n");
117
118 /* Get the user SID string */
119 if (!GetUserSidStringFromToken(hToken, &SidString))
120 {
121 DPRINT1("GetUserSidStringFromToken() failed\n");
122 return FALSE;
123 }
124
125 if (RegOpenKeyExW(HKEY_USERS,
126 SidString.Buffer,
127 0,
128 MAXIMUM_ALLOWED,
129 &hKey))
130 {
131 DPRINT("Profile not loaded\n");
132 RtlFreeUnicodeString(&SidString);
133 return FALSE;
134 }
135
136 RegCloseKey(hKey);
137
138 RtlFreeUnicodeString(&SidString);
139
140 DPRINT("Profile already loaded\n");
141
142 return TRUE;
143 }
144
145
146 static
147 HANDLE
148 CreateProfileMutex(
149 _In_ PWSTR pszSidString)
150 {
151 SECURITY_DESCRIPTOR SecurityDescriptor;
152 SECURITY_ATTRIBUTES SecurityAttributes;
153 PWSTR pszMutexName = NULL;
154 HANDLE hMutex = NULL;
155
156 pszMutexName = HeapAlloc(GetProcessHeap(),
157 0,
158 (wcslen(L"Global\\userenv: User Profile Mutex for ") + wcslen(pszSidString) + 1) * sizeof(WCHAR));
159 if (pszMutexName == NULL)
160 {
161 DPRINT("Failed to allocate the mutex name buffer!\n");
162 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
163 return NULL;
164 }
165
166 /* Build the profile mutex name */
167 wcscpy(pszMutexName, L"Global\\userenv: User Profile Mutex for ");
168 wcscat(pszMutexName, pszSidString);
169
170 /* Initialize the security descriptor */
171 InitializeSecurityDescriptor(&SecurityDescriptor,
172 SECURITY_DESCRIPTOR_REVISION);
173
174 /* Set a NULL-DACL (everyone has access) */
175 SetSecurityDescriptorDacl(&SecurityDescriptor,
176 TRUE,
177 NULL,
178 FALSE);
179
180 /* Initialize the security attributes */
181 SecurityAttributes.nLength = sizeof(SecurityAttributes);
182 SecurityAttributes.lpSecurityDescriptor = &SecurityDescriptor;
183 SecurityAttributes.bInheritHandle = FALSE;
184
185 /* Create the profile mutex */
186 hMutex = CreateMutexW(&SecurityAttributes,
187 FALSE,
188 pszMutexName);
189 if (hMutex == NULL)
190 {
191 DPRINT1("Failed to create the profile mutex (Error %lu)\n", GetLastError());
192 }
193
194 HeapFree(GetProcessHeap(), 0, pszMutexName);
195
196 return hMutex;
197 }
198
199
200 /* PUBLIC FUNCTIONS ********************************************************/
201
202 BOOL
203 WINAPI
204 CopySystemProfile(
205 _In_ ULONG Unused)
206 {
207 WCHAR szKeyName[MAX_PATH];
208 WCHAR szRawProfilePath[MAX_PATH];
209 WCHAR szProfilePath[MAX_PATH];
210 WCHAR szDefaultProfilePath[MAX_PATH];
211 UNICODE_STRING SidString = {0, 0, NULL};
212 HANDLE hToken = NULL;
213 PSID pUserSid = NULL;
214 HKEY hProfileKey = NULL;
215 DWORD dwDisposition;
216 BOOL bResult = FALSE;
217 DWORD cchSize;
218 DWORD dwError;
219
220 DPRINT1("CopySystemProfile()\n");
221
222 if (!OpenProcessToken(GetCurrentProcess(),
223 TOKEN_QUERY | TOKEN_IMPERSONATE,
224 &hToken))
225 {
226 DPRINT1("Failed to open the process token (Error %lu)\n", GetLastError());
227 return FALSE;
228 }
229
230 pUserSid = GetUserSid(hToken);
231 if (pUserSid == NULL)
232 {
233 DPRINT1("Failed to get the users SID (Error %lu)\n", GetLastError());
234 goto done;
235 }
236
237 /* Get the user SID string */
238 if (!GetUserSidStringFromToken(hToken, &SidString))
239 {
240 DPRINT1("GetUserSidStringFromToken() failed\n");
241 goto done;
242 }
243
244 StringCbCopyW(szKeyName, sizeof(szKeyName),
245 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
246 StringCbCatW(szKeyName, sizeof(szKeyName), SidString.Buffer);
247
248 RtlFreeUnicodeString(&SidString);
249
250 dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
251 szKeyName,
252 0, NULL, 0,
253 KEY_WRITE,
254 NULL,
255 &hProfileKey,
256 &dwDisposition);
257 if (dwError != ERROR_SUCCESS)
258 {
259 DPRINT1("Failed to create the profile key for the %s profile (Error %lu)\n",
260 SidString.Buffer, dwError);
261 goto done;
262 }
263
264 dwError = RegSetValueExW(hProfileKey,
265 L"Sid",
266 0,
267 REG_BINARY,
268 (PBYTE)pUserSid,
269 RtlLengthSid(pUserSid));
270 if (dwError != ERROR_SUCCESS)
271 {
272 DPRINT1("Failed to set the SID value (Error %lu)\n", dwError);
273 goto done;
274 }
275
276 wcscpy(szRawProfilePath,
277 L"%systemroot%\\system32\\config\\systemprofile");
278
279 dwError = RegSetValueExW(hProfileKey,
280 L"ProfileImagePath",
281 0,
282 REG_EXPAND_SZ,
283 (PBYTE)szRawProfilePath,
284 (wcslen(szRawProfilePath) + 1) * sizeof(WCHAR));
285 if (dwError != ERROR_SUCCESS)
286 {
287 DPRINT1("Failed to set the ProfileImagePath value (Error %lu)\n", dwError);
288 goto done;
289 }
290
291 /* Expand the raw profile path */
292 if (!ExpandEnvironmentStringsW(szRawProfilePath,
293 szProfilePath,
294 ARRAYSIZE(szProfilePath)))
295 {
296 DPRINT1("Failled to expand the raw profile path (Error %lu)\n", GetLastError());
297 goto done;
298 }
299
300 /* Create the profile directory if it does not exist yet */
301 // FIXME: Security!
302 if (!CreateDirectoryW(szProfilePath, NULL))
303 {
304 if (GetLastError() != ERROR_ALREADY_EXISTS)
305 {
306 DPRINT1("Failed to create the profile directory (Error %lu)\n", GetLastError());
307 goto done;
308 }
309 }
310
311 /* Get the path of the default profile */
312 cchSize = ARRAYSIZE(szDefaultProfilePath);
313 if (!GetDefaultUserProfileDirectoryW(szDefaultProfilePath, &cchSize))
314 {
315 DPRINT1("Failed to create the default profile path (Error %lu)\n", GetLastError());
316 goto done;
317 }
318
319 /* Copy the default profile into the new profile directory */
320 // FIXME: Security!
321 if (!CopyDirectory(szProfilePath, szDefaultProfilePath))
322 {
323 DPRINT1("Failed to copy the default profile directory (Error %lu)\n", GetLastError());
324 goto done;
325 }
326
327 bResult = TRUE;
328
329 done:
330 if (hProfileKey != NULL)
331 RegCloseKey(hProfileKey);
332
333 RtlFreeUnicodeString(&SidString);
334
335 if (pUserSid != NULL)
336 LocalFree(pUserSid);
337
338 if (hToken != NULL)
339 CloseHandle(hToken);
340
341 return bResult;
342 }
343
344
345 BOOL
346 WINAPI
347 CreateUserProfileA(
348 _In_ PSID pSid,
349 _In_ LPCSTR lpUserName)
350 {
351 LPWSTR pUserNameW = NULL;
352 INT nLength;
353 BOOL bResult;
354
355 DPRINT("CreateUserProfileA(%p %s)\n", pSid, lpUserName);
356
357 /* Convert lpUserName to Unicode */
358 nLength = MultiByteToWideChar(CP_ACP, 0, lpUserName, -1, NULL, 0);
359 pUserNameW = HeapAlloc(GetProcessHeap(), 0, nLength * sizeof(WCHAR));
360 if (pUserNameW == NULL)
361 {
362 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
363 return FALSE;
364 }
365 MultiByteToWideChar(CP_ACP, 0, lpUserName, -1, pUserNameW, nLength);
366
367 /* Call the Ex function */
368 bResult = CreateUserProfileExW(pSid,
369 pUserNameW,
370 NULL,
371 NULL,
372 0,
373 FALSE);
374
375 HeapFree(GetProcessHeap(), 0, pUserNameW);
376
377 return bResult;
378 }
379
380
381 BOOL
382 WINAPI
383 CreateUserProfileW(
384 _In_ PSID pSid,
385 _In_ LPCWSTR lpUserName)
386 {
387 DPRINT("CreateUserProfileW(%p %S)\n", pSid, lpUserName);
388
389 /* Call the Ex function */
390 return CreateUserProfileExW(pSid,
391 lpUserName,
392 NULL,
393 NULL,
394 0,
395 FALSE);
396 }
397
398
399 BOOL
400 WINAPI
401 CreateUserProfileExA(
402 _In_ PSID pSid,
403 _In_ LPCSTR lpUserName,
404 _In_opt_ LPCSTR lpUserHive,
405 _Out_opt_ LPSTR lpProfileDir,
406 _In_ DWORD dwDirSize,
407 _In_ BOOL bWin9xUpg)
408 {
409 LPWSTR pUserNameW = NULL;
410 LPWSTR pUserHiveW = NULL;
411 LPWSTR pProfileDirW = NULL;
412 INT nLength;
413 BOOL bResult = FALSE;
414
415 DPRINT("CreateUserProfileExA(%p %s %s %p %lu %d)\n",
416 pSid, lpUserName, lpUserHive, lpProfileDir, dwDirSize, bWin9xUpg);
417
418 /* Check the parameters */
419 if (lpProfileDir != NULL && dwDirSize == 0)
420 {
421 SetLastError(ERROR_INVALID_PARAMETER);
422 return FALSE;
423 }
424
425 /* Convert lpUserName to Unicode */
426 nLength = MultiByteToWideChar(CP_ACP, 0, lpUserName, -1, NULL, 0);
427 pUserNameW = HeapAlloc(GetProcessHeap(), 0, nLength * sizeof(WCHAR));
428 if (pUserNameW == NULL)
429 {
430 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
431 goto done;
432 }
433 MultiByteToWideChar(CP_ACP, 0, lpUserName, -1, pUserNameW, nLength);
434
435 /* Convert lpUserHive to Unicode */
436 if (lpUserHive != NULL)
437 {
438 nLength = MultiByteToWideChar(CP_ACP, 0, lpUserHive, -1, NULL, 0);
439 pUserHiveW = HeapAlloc(GetProcessHeap(), 0, nLength * sizeof(WCHAR));
440 if (pUserHiveW == NULL)
441 {
442 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
443 goto done;
444 }
445 MultiByteToWideChar(CP_ACP, 0, lpUserHive, -1, pUserHiveW, nLength);
446 }
447
448 /* Allocate a Unicode buffer for lpProfileDir */
449 if (lpProfileDir != NULL)
450 {
451 pProfileDirW = HeapAlloc(GetProcessHeap(), 0, dwDirSize * sizeof(WCHAR));
452 if (pProfileDirW == NULL)
453 {
454 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
455 goto done;
456 }
457 }
458
459 /* Call the Unicode function */
460 bResult = CreateUserProfileExW(pSid,
461 (LPCWSTR)pUserNameW,
462 (LPCWSTR)pUserHiveW,
463 pProfileDirW,
464 dwDirSize,
465 bWin9xUpg);
466
467 /* Convert the profile path to ANSI */
468 if (bResult && lpProfileDir != NULL)
469 {
470 WideCharToMultiByte(CP_ACP, 0, pProfileDirW, -1, lpProfileDir, dwDirSize, NULL, NULL);
471 }
472
473 done:
474 /* Free the buffers */
475 if (pProfileDirW != NULL)
476 HeapFree(GetProcessHeap(), 0, pProfileDirW);
477
478 if (pUserHiveW != NULL)
479 HeapFree(GetProcessHeap(), 0, pUserHiveW);
480
481 if (pUserNameW != NULL)
482 HeapFree(GetProcessHeap(), 0, pUserNameW);
483
484 return bResult;
485 }
486
487
488 BOOL
489 WINAPI
490 CreateUserProfileExW(
491 _In_ PSID pSid,
492 _In_ LPCWSTR lpUserName,
493 _In_opt_ LPCWSTR lpUserHive,
494 _Out_opt_ LPWSTR lpProfileDir,
495 _In_ DWORD dwDirSize,
496 _In_ BOOL bWin9xUpg)
497 {
498 WCHAR szRawProfilesPath[MAX_PATH];
499 WCHAR szProfilesPath[MAX_PATH];
500 WCHAR szUserProfilePath[MAX_PATH];
501 WCHAR szDefaultUserPath[MAX_PATH];
502 WCHAR szUserProfileName[MAX_PATH];
503 WCHAR szBuffer[MAX_PATH];
504 LPWSTR SidString;
505 DWORD dwType, dwLength;
506 DWORD dwDisposition;
507 UINT i;
508 HKEY hKey;
509 BOOL bRet = TRUE;
510 LONG Error;
511
512 DPRINT("CreateUserProfileExW(%p %S %S %p %lu %d)\n",
513 pSid, lpUserName, lpUserHive, lpProfileDir, dwDirSize, bWin9xUpg);
514
515 /* Parameters validation */
516 if (!pSid || !lpUserName)
517 {
518 SetLastError(ERROR_INVALID_PARAMETER);
519 return FALSE;
520 }
521
522 /*
523 * TODO:
524 * - Add support for lpUserHive.
525 * - bWin9xUpg is obsolete. Don't waste your time implementing this.
526 */
527
528 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
529 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
530 0,
531 KEY_QUERY_VALUE,
532 &hKey);
533 if (Error != ERROR_SUCCESS)
534 {
535 DPRINT1("Error: %lu\n", Error);
536 SetLastError((DWORD)Error);
537 return FALSE;
538 }
539
540 /* Get profiles path */
541 dwLength = sizeof(szRawProfilesPath);
542 Error = RegQueryValueExW(hKey,
543 L"ProfilesDirectory",
544 NULL,
545 &dwType,
546 (LPBYTE)szRawProfilesPath,
547 &dwLength);
548 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
549 {
550 DPRINT1("Error: %lu\n", Error);
551 RegCloseKey(hKey);
552 SetLastError((DWORD)Error);
553 return FALSE;
554 }
555
556 /* Expand it */
557 if (!ExpandEnvironmentStringsW(szRawProfilesPath,
558 szProfilesPath,
559 ARRAYSIZE(szProfilesPath)))
560 {
561 DPRINT1("Error: %lu\n", GetLastError());
562 RegCloseKey(hKey);
563 return FALSE;
564 }
565
566 /* Create the profiles directory if it does not exist yet */
567 // FIXME: Security!
568 if (!CreateDirectoryW(szProfilesPath, NULL))
569 {
570 if (GetLastError() != ERROR_ALREADY_EXISTS)
571 {
572 DPRINT1("Error: %lu\n", GetLastError());
573 return FALSE;
574 }
575 }
576
577 /* Get default user path */
578 dwLength = sizeof(szBuffer);
579 Error = RegQueryValueExW(hKey,
580 L"DefaultUserProfile",
581 NULL,
582 &dwType,
583 (LPBYTE)szBuffer,
584 &dwLength);
585 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
586 {
587 DPRINT1("Error: %lu\n", Error);
588 RegCloseKey(hKey);
589 SetLastError((DWORD)Error);
590 return FALSE;
591 }
592
593 RegCloseKey(hKey);
594
595 StringCbCopyW(szUserProfileName, sizeof(szUserProfileName), lpUserName);
596
597 /* Create user profile directory */
598
599 StringCbCopyW(szUserProfilePath, sizeof(szUserProfilePath), szProfilesPath);
600 StringCbCatW(szUserProfilePath, sizeof(szUserProfilePath), L"\\");
601 StringCbCatW(szUserProfilePath, sizeof(szUserProfilePath), szUserProfileName);
602
603 // FIXME: Security!
604 if (!CreateDirectoryW(szUserProfilePath, NULL))
605 {
606 if (GetLastError() != ERROR_ALREADY_EXISTS)
607 {
608 DPRINT1("Error: %lu\n", GetLastError());
609 return FALSE;
610 }
611
612 for (i = 0; i < 1000; i++)
613 {
614 swprintf(szUserProfileName, L"%s.%03u", lpUserName, i);
615
616 StringCbCopyW(szUserProfilePath, sizeof(szUserProfilePath), szProfilesPath);
617 StringCbCatW(szUserProfilePath, sizeof(szUserProfilePath), L"\\");
618 StringCbCatW(szUserProfilePath, sizeof(szUserProfilePath), szUserProfileName);
619
620 // FIXME: Security!
621 if (CreateDirectoryW(szUserProfilePath, NULL))
622 break;
623
624 if (GetLastError() != ERROR_ALREADY_EXISTS)
625 {
626 DPRINT1("Error: %lu\n", GetLastError());
627 return FALSE;
628 }
629 }
630 }
631
632 /* Copy default user directory */
633
634 StringCbCopyW(szDefaultUserPath, sizeof(szDefaultUserPath), szProfilesPath);
635 StringCbCatW(szDefaultUserPath, sizeof(szDefaultUserPath), L"\\");
636 StringCbCatW(szDefaultUserPath, sizeof(szDefaultUserPath), szBuffer);
637
638 // FIXME: Security!
639 if (!CopyDirectory(szUserProfilePath, szDefaultUserPath))
640 {
641 DPRINT1("Error: %lu\n", GetLastError());
642 return FALSE;
643 }
644
645 /* Add profile to profile list */
646 if (!ConvertSidToStringSidW(pSid,
647 &SidString))
648 {
649 DPRINT1("Error: %lu\n", GetLastError());
650 return FALSE;
651 }
652
653 StringCbCopyW(szBuffer, sizeof(szBuffer),
654 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
655 StringCbCatW(szBuffer, sizeof(szBuffer), SidString);
656
657 /* Create user profile key */
658 Error = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
659 szBuffer,
660 0,
661 NULL,
662 REG_OPTION_NON_VOLATILE,
663 KEY_ALL_ACCESS,
664 NULL,
665 &hKey,
666 &dwDisposition);
667 if (Error != ERROR_SUCCESS)
668 {
669 DPRINT1("Error: %lu\n", Error);
670 bRet = FALSE;
671 goto done;
672 }
673
674 /* Create non-expanded user profile path */
675 StringCbCopyW(szBuffer, sizeof(szBuffer), szRawProfilesPath);
676 StringCbCatW(szBuffer, sizeof(szBuffer), L"\\");
677 StringCbCatW(szBuffer, sizeof(szBuffer), szUserProfileName);
678
679 /* Set 'ProfileImagePath' value (non-expanded) */
680 Error = RegSetValueExW(hKey,
681 L"ProfileImagePath",
682 0,
683 REG_EXPAND_SZ,
684 (LPBYTE)szBuffer,
685 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
686 if (Error != ERROR_SUCCESS)
687 {
688 DPRINT1("Error: %lu\n", Error);
689 RegCloseKey(hKey);
690 bRet = FALSE;
691 goto done;
692 }
693
694 /* Set 'Sid' value */
695 Error = RegSetValueExW(hKey,
696 L"Sid",
697 0,
698 REG_BINARY,
699 pSid,
700 GetLengthSid(pSid));
701 if (Error != ERROR_SUCCESS)
702 {
703 DPRINT1("Error: %lu\n", Error);
704 RegCloseKey(hKey);
705 bRet = FALSE;
706 goto done;
707 }
708
709 RegCloseKey(hKey);
710
711 /* Create user hive file */
712
713 /* Use the default hive file name */
714 StringCbCopyW(szBuffer, sizeof(szBuffer), szUserProfilePath);
715 StringCbCatW(szBuffer, sizeof(szBuffer), L"\\ntuser.dat");
716
717 /* Acquire restore privilege */
718 if (!AcquireRemoveRestorePrivilege(TRUE))
719 {
720 Error = GetLastError();
721 DPRINT1("Error: %lu\n", Error);
722 bRet = FALSE;
723 goto done;
724 }
725
726 /* Load the user hive */
727 Error = RegLoadKeyW(HKEY_USERS,
728 SidString,
729 szBuffer);
730 AcquireRemoveRestorePrivilege(FALSE);
731 if (Error != ERROR_SUCCESS)
732 {
733 DPRINT1("Error: %lu\n", Error);
734 bRet = FALSE;
735 goto done;
736 }
737
738 /* Initialize user hive */
739 if (!CreateUserHive(SidString, szUserProfilePath))
740 {
741 Error = GetLastError();
742 DPRINT1("Error: %lu\n", Error);
743 bRet = FALSE;
744 }
745
746 /* Unload the hive */
747 AcquireRemoveRestorePrivilege(TRUE);
748 RegUnLoadKeyW(HKEY_USERS, SidString);
749 AcquireRemoveRestorePrivilege(FALSE);
750
751 /*
752 * If the caller wants to retrieve the user profile path,
753 * give it now. 'dwDirSize' is the number of characters.
754 */
755 if (lpProfileDir && dwDirSize)
756 StringCchCopyW(lpProfileDir, dwDirSize, szUserProfilePath);
757
758 done:
759 LocalFree((HLOCAL)SidString);
760 SetLastError((DWORD)Error);
761
762 DPRINT("CreateUserProfileExW() done\n");
763
764 return bRet;
765 }
766
767
768 BOOL
769 WINAPI
770 DeleteProfileA(
771 _In_ LPCSTR lpSidString,
772 _In_opt_ LPCSTR lpProfilePath,
773 _In_opt_ LPCSTR lpComputerName)
774 {
775 BOOL bResult;
776 UNICODE_STRING SidString, ProfilePath, ComputerName;
777
778 DPRINT("DeleteProfileA() called\n");
779
780 /* Conversion to UNICODE */
781 if (lpSidString)
782 RtlCreateUnicodeStringFromAsciiz(&SidString,
783 (LPSTR)lpSidString);
784
785 if (lpProfilePath)
786 RtlCreateUnicodeStringFromAsciiz(&ProfilePath,
787 (LPSTR)lpProfilePath);
788
789 if (lpComputerName)
790 RtlCreateUnicodeStringFromAsciiz(&ComputerName,
791 (LPSTR)lpComputerName);
792
793 /* Call the UNICODE function */
794 bResult = DeleteProfileW(SidString.Buffer,
795 ProfilePath.Buffer,
796 ComputerName.Buffer);
797
798 /* Memory cleanup */
799 if (lpSidString)
800 RtlFreeUnicodeString(&SidString);
801
802 if (lpProfilePath)
803 RtlFreeUnicodeString(&ProfilePath);
804
805 if (lpComputerName)
806 RtlFreeUnicodeString(&ComputerName);
807
808 return bResult;
809 }
810
811
812 BOOL
813 WINAPI
814 DeleteProfileW(
815 _In_ LPCWSTR lpSidString,
816 _In_opt_ LPCWSTR lpProfilePath,
817 _In_opt_ LPCWSTR lpComputerName)
818 {
819 DPRINT1("DeleteProfileW() not implemented!\n");
820 return FALSE;
821 }
822
823
824 BOOL
825 WINAPI
826 GetAllUsersProfileDirectoryA(
827 _Out_opt_ LPSTR lpProfileDir,
828 _Inout_ LPDWORD lpcchSize)
829 {
830 LPWSTR lpBuffer;
831 BOOL bResult;
832
833 if (!lpcchSize)
834 {
835 SetLastError(ERROR_INVALID_PARAMETER);
836 return FALSE;
837 }
838
839 lpBuffer = GlobalAlloc(GMEM_FIXED,
840 *lpcchSize * sizeof(WCHAR));
841 if (lpBuffer == NULL)
842 return FALSE;
843
844 bResult = GetAllUsersProfileDirectoryW(lpBuffer,
845 lpcchSize);
846 if (bResult && lpProfileDir)
847 {
848 bResult = WideCharToMultiByte(CP_ACP,
849 0,
850 lpBuffer,
851 -1,
852 lpProfileDir,
853 *lpcchSize,
854 NULL,
855 NULL);
856 }
857
858 GlobalFree(lpBuffer);
859
860 return bResult;
861 }
862
863
864 BOOL
865 WINAPI
866 GetAllUsersProfileDirectoryW(
867 _Out_opt_ LPWSTR lpProfileDir,
868 _Inout_ LPDWORD lpcchSize)
869 {
870 WCHAR szProfilePath[MAX_PATH];
871 WCHAR szBuffer[MAX_PATH];
872 DWORD dwType, dwLength;
873 HKEY hKey;
874 LONG Error;
875
876 if (!lpcchSize)
877 {
878 SetLastError(ERROR_INVALID_PARAMETER);
879 return FALSE;
880 }
881
882 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
883 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
884 0,
885 KEY_QUERY_VALUE,
886 &hKey);
887 if (Error != ERROR_SUCCESS)
888 {
889 DPRINT1("Error: %lu\n", Error);
890 SetLastError((DWORD)Error);
891 return FALSE;
892 }
893
894 /* Get profiles path */
895 dwLength = sizeof(szBuffer);
896 Error = RegQueryValueExW(hKey,
897 L"ProfilesDirectory",
898 NULL,
899 &dwType,
900 (LPBYTE)szBuffer,
901 &dwLength);
902 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
903 {
904 DPRINT1("Error: %lu\n", Error);
905 RegCloseKey(hKey);
906 SetLastError((DWORD)Error);
907 return FALSE;
908 }
909
910 /* Expand it */
911 if (!ExpandEnvironmentStringsW(szBuffer,
912 szProfilePath,
913 ARRAYSIZE(szProfilePath)))
914 {
915 DPRINT1("Error: %lu\n", GetLastError());
916 RegCloseKey(hKey);
917 return FALSE;
918 }
919
920 /* Get 'AllUsersProfile' name */
921 dwLength = sizeof(szBuffer);
922 Error = RegQueryValueExW(hKey,
923 L"AllUsersProfile",
924 NULL,
925 &dwType,
926 (LPBYTE)szBuffer,
927 &dwLength);
928 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
929 {
930 DPRINT1("Error: %lu\n", Error);
931 RegCloseKey(hKey);
932 SetLastError((DWORD)Error);
933 return FALSE;
934 }
935
936 RegCloseKey(hKey);
937
938 StringCbCatW(szProfilePath, sizeof(szProfilePath), L"\\");
939 StringCbCatW(szProfilePath, sizeof(szProfilePath), szBuffer);
940
941 dwLength = wcslen(szProfilePath) + 1;
942 if (lpProfileDir && (*lpcchSize >= dwLength))
943 {
944 StringCchCopyW(lpProfileDir, *lpcchSize, szProfilePath);
945 *lpcchSize = dwLength;
946 return TRUE;
947 }
948 else // if (!lpProfileDir || (*lpcchSize < dwLength))
949 {
950 *lpcchSize = dwLength;
951 SetLastError(ERROR_INSUFFICIENT_BUFFER);
952 return FALSE;
953 }
954 }
955
956
957 BOOL
958 WINAPI
959 GetDefaultUserProfileDirectoryA(
960 _Out_opt_ LPSTR lpProfileDir,
961 _Inout_ LPDWORD lpcchSize)
962 {
963 LPWSTR lpBuffer;
964 BOOL bResult;
965
966 if (!lpcchSize)
967 {
968 SetLastError(ERROR_INVALID_PARAMETER);
969 return FALSE;
970 }
971
972 lpBuffer = GlobalAlloc(GMEM_FIXED,
973 *lpcchSize * sizeof(WCHAR));
974 if (lpBuffer == NULL)
975 return FALSE;
976
977 bResult = GetDefaultUserProfileDirectoryW(lpBuffer,
978 lpcchSize);
979 if (bResult && lpProfileDir)
980 {
981 bResult = WideCharToMultiByte(CP_ACP,
982 0,
983 lpBuffer,
984 -1,
985 lpProfileDir,
986 *lpcchSize,
987 NULL,
988 NULL);
989 }
990
991 GlobalFree(lpBuffer);
992
993 return bResult;
994 }
995
996
997 BOOL
998 WINAPI
999 GetDefaultUserProfileDirectoryW(
1000 _Out_opt_ LPWSTR lpProfileDir,
1001 _Inout_ LPDWORD lpcchSize)
1002 {
1003 WCHAR szProfilePath[MAX_PATH];
1004 WCHAR szBuffer[MAX_PATH];
1005 DWORD dwType, dwLength;
1006 HKEY hKey;
1007 LONG Error;
1008
1009 if (!lpcchSize)
1010 {
1011 SetLastError(ERROR_INVALID_PARAMETER);
1012 return FALSE;
1013 }
1014
1015 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1016 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1017 0,
1018 KEY_QUERY_VALUE,
1019 &hKey);
1020 if (Error != ERROR_SUCCESS)
1021 {
1022 DPRINT1("Error: %lu\n", Error);
1023 SetLastError((DWORD)Error);
1024 return FALSE;
1025 }
1026
1027 /* Get profiles path */
1028 dwLength = sizeof(szBuffer);
1029 Error = RegQueryValueExW(hKey,
1030 L"ProfilesDirectory",
1031 NULL,
1032 &dwType,
1033 (LPBYTE)szBuffer,
1034 &dwLength);
1035 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
1036 {
1037 DPRINT1("Error: %lu\n", Error);
1038 RegCloseKey(hKey);
1039 SetLastError((DWORD)Error);
1040 return FALSE;
1041 }
1042
1043 /* Expand it */
1044 if (!ExpandEnvironmentStringsW(szBuffer,
1045 szProfilePath,
1046 ARRAYSIZE(szProfilePath)))
1047 {
1048 DPRINT1("Error: %lu\n", GetLastError());
1049 RegCloseKey(hKey);
1050 return FALSE;
1051 }
1052
1053 /* Get 'DefaultUserProfile' name */
1054 dwLength = sizeof(szBuffer);
1055 Error = RegQueryValueExW(hKey,
1056 L"DefaultUserProfile",
1057 NULL,
1058 &dwType,
1059 (LPBYTE)szBuffer,
1060 &dwLength);
1061 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
1062 {
1063 DPRINT1("Error: %lu\n", Error);
1064 RegCloseKey(hKey);
1065 SetLastError((DWORD)Error);
1066 return FALSE;
1067 }
1068
1069 RegCloseKey(hKey);
1070
1071 StringCbCatW(szProfilePath, sizeof(szProfilePath), L"\\");
1072 StringCbCatW(szProfilePath, sizeof(szProfilePath), szBuffer);
1073
1074 dwLength = wcslen(szProfilePath) + 1;
1075 if (lpProfileDir && (*lpcchSize >= dwLength))
1076 {
1077 StringCchCopyW(lpProfileDir, *lpcchSize, szProfilePath);
1078 *lpcchSize = dwLength;
1079 return TRUE;
1080 }
1081 else // if (!lpProfileDir || (*lpcchSize < dwLength))
1082 {
1083 *lpcchSize = dwLength;
1084 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1085 return FALSE;
1086 }
1087 }
1088
1089
1090 BOOL
1091 WINAPI
1092 GetProfilesDirectoryA(
1093 _Out_ LPSTR lpProfileDir, // _Out_opt_
1094 _Inout_ LPDWORD lpcchSize)
1095 {
1096 LPWSTR lpBuffer;
1097 BOOL bResult;
1098
1099 if (!lpcchSize)
1100 {
1101 SetLastError(ERROR_INVALID_PARAMETER);
1102 return FALSE;
1103 }
1104
1105 lpBuffer = GlobalAlloc(GMEM_FIXED,
1106 *lpcchSize * sizeof(WCHAR));
1107 if (lpBuffer == NULL)
1108 return FALSE;
1109
1110 bResult = GetProfilesDirectoryW(lpBuffer,
1111 lpcchSize);
1112 if (bResult && lpProfileDir)
1113 {
1114 bResult = WideCharToMultiByte(CP_ACP,
1115 0,
1116 lpBuffer,
1117 -1,
1118 lpProfileDir,
1119 *lpcchSize,
1120 NULL,
1121 NULL);
1122 }
1123
1124 GlobalFree(lpBuffer);
1125
1126 return bResult;
1127 }
1128
1129
1130 BOOL
1131 WINAPI
1132 GetProfilesDirectoryW(
1133 _Out_ LPWSTR lpProfilesDir, // _Out_opt_
1134 _Inout_ LPDWORD lpcchSize)
1135 {
1136 WCHAR szProfilesPath[MAX_PATH];
1137 WCHAR szBuffer[MAX_PATH];
1138 DWORD dwType, dwLength;
1139 HKEY hKey;
1140 LONG Error;
1141
1142 if (!lpcchSize)
1143 {
1144 SetLastError(ERROR_INVALID_PARAMETER);
1145 return FALSE;
1146 }
1147
1148 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1149 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1150 0,
1151 KEY_QUERY_VALUE,
1152 &hKey);
1153 if (Error != ERROR_SUCCESS)
1154 {
1155 DPRINT1("Error: %lu\n", Error);
1156 SetLastError((DWORD)Error);
1157 return FALSE;
1158 }
1159
1160 /* Get profiles path */
1161 dwLength = sizeof(szBuffer);
1162 Error = RegQueryValueExW(hKey,
1163 L"ProfilesDirectory",
1164 NULL,
1165 &dwType,
1166 (LPBYTE)szBuffer,
1167 &dwLength);
1168 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
1169 {
1170 DPRINT1("Error: %lu\n", Error);
1171 RegCloseKey(hKey);
1172 SetLastError((DWORD)Error);
1173 return FALSE;
1174 }
1175
1176 RegCloseKey(hKey);
1177
1178 /* Expand it */
1179 if (!ExpandEnvironmentStringsW(szBuffer,
1180 szProfilesPath,
1181 ARRAYSIZE(szProfilesPath)))
1182 {
1183 DPRINT1("Error: %lu\n", GetLastError());
1184 return FALSE;
1185 }
1186
1187 dwLength = wcslen(szProfilesPath) + 1;
1188 if (lpProfilesDir && (*lpcchSize >= dwLength))
1189 {
1190 StringCchCopyW(lpProfilesDir, *lpcchSize, szProfilesPath);
1191 *lpcchSize = dwLength;
1192 return TRUE;
1193 }
1194 else // if (!lpProfilesDir || (*lpcchSize < dwLength))
1195 {
1196 *lpcchSize = dwLength;
1197 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1198 return FALSE;
1199 }
1200 }
1201
1202
1203 BOOL
1204 WINAPI
1205 GetProfileType(
1206 _Out_ PDWORD pdwFlags)
1207 {
1208 DPRINT1("GetProfileType() not implemented!\n");
1209 return FALSE;
1210 }
1211
1212
1213 BOOL
1214 WINAPI
1215 GetUserProfileDirectoryA(
1216 _In_ HANDLE hToken,
1217 _Out_opt_ LPSTR lpProfileDir,
1218 _Inout_ LPDWORD lpcchSize)
1219 {
1220 LPWSTR lpBuffer;
1221 BOOL bResult;
1222
1223 if (!lpcchSize)
1224 {
1225 SetLastError(ERROR_INVALID_PARAMETER);
1226 return FALSE;
1227 }
1228
1229 lpBuffer = GlobalAlloc(GMEM_FIXED,
1230 *lpcchSize * sizeof(WCHAR));
1231 if (lpBuffer == NULL)
1232 return FALSE;
1233
1234 bResult = GetUserProfileDirectoryW(hToken,
1235 lpBuffer,
1236 lpcchSize);
1237 if (bResult && lpProfileDir)
1238 {
1239 bResult = WideCharToMultiByte(CP_ACP,
1240 0,
1241 lpBuffer,
1242 -1,
1243 lpProfileDir,
1244 *lpcchSize,
1245 NULL,
1246 NULL);
1247 }
1248
1249 GlobalFree(lpBuffer);
1250
1251 return bResult;
1252 }
1253
1254
1255 BOOL
1256 WINAPI
1257 GetUserProfileDirectoryW(
1258 _In_ HANDLE hToken,
1259 _Out_opt_ LPWSTR lpProfileDir,
1260 _Inout_ LPDWORD lpcchSize)
1261 {
1262 UNICODE_STRING SidString;
1263 WCHAR szKeyName[MAX_PATH];
1264 WCHAR szRawImagePath[MAX_PATH];
1265 WCHAR szImagePath[MAX_PATH];
1266 DWORD dwType, dwLength;
1267 HKEY hKey;
1268 LONG Error;
1269
1270 if (!hToken)
1271 {
1272 SetLastError(ERROR_INVALID_HANDLE);
1273 return FALSE;
1274 }
1275
1276 if (!lpcchSize)
1277 {
1278 SetLastError(ERROR_INVALID_PARAMETER);
1279 return FALSE;
1280 }
1281
1282 /* Get the user SID string */
1283 if (!GetUserSidStringFromToken(hToken, &SidString))
1284 {
1285 DPRINT1("GetUserSidStringFromToken() failed\n");
1286 return FALSE;
1287 }
1288
1289 DPRINT("SidString: '%wZ'\n", &SidString);
1290
1291 StringCbCopyW(szKeyName, sizeof(szKeyName),
1292 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
1293 StringCbCatW(szKeyName, sizeof(szKeyName), SidString.Buffer);
1294
1295 RtlFreeUnicodeString(&SidString);
1296
1297 DPRINT("KeyName: '%S'\n", szKeyName);
1298
1299 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1300 szKeyName,
1301 0,
1302 KEY_QUERY_VALUE,
1303 &hKey);
1304 if (Error != ERROR_SUCCESS)
1305 {
1306 DPRINT1("Error: %lu\n", Error);
1307 SetLastError((DWORD)Error);
1308 return FALSE;
1309 }
1310
1311 dwLength = sizeof(szRawImagePath);
1312 Error = RegQueryValueExW(hKey,
1313 L"ProfileImagePath",
1314 NULL,
1315 &dwType,
1316 (LPBYTE)szRawImagePath,
1317 &dwLength);
1318 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
1319 {
1320 DPRINT1("Error: %lu\n", Error);
1321 RegCloseKey(hKey);
1322 SetLastError((DWORD)Error);
1323 return FALSE;
1324 }
1325
1326 RegCloseKey(hKey);
1327
1328 DPRINT("RawImagePath: '%S'\n", szRawImagePath);
1329
1330 /* Expand it */
1331 if (!ExpandEnvironmentStringsW(szRawImagePath,
1332 szImagePath,
1333 ARRAYSIZE(szImagePath)))
1334 {
1335 DPRINT1("Error: %lu\n", GetLastError());
1336 return FALSE;
1337 }
1338
1339 DPRINT("ImagePath: '%S'\n", szImagePath);
1340
1341 dwLength = wcslen(szImagePath) + 1;
1342 if (lpProfileDir && (*lpcchSize >= dwLength))
1343 {
1344 StringCchCopyW(lpProfileDir, *lpcchSize, szImagePath);
1345 *lpcchSize = dwLength;
1346 return TRUE;
1347 }
1348 else // if (!lpProfileDir || (*lpcchSize < dwLength))
1349 {
1350 *lpcchSize = dwLength;
1351 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1352 return FALSE;
1353 }
1354 }
1355
1356
1357 BOOL
1358 WINAPI
1359 LoadUserProfileA(
1360 _In_ HANDLE hToken,
1361 _Inout_ LPPROFILEINFOA lpProfileInfo)
1362 {
1363 BOOL bResult = FALSE;
1364 PROFILEINFOW ProfileInfoW = {0};
1365 int len;
1366
1367 DPRINT("LoadUserProfileA() called\n");
1368
1369 /* Check profile info */
1370 if (!lpProfileInfo || (lpProfileInfo->dwSize != sizeof(PROFILEINFOA)) ||
1371 (lpProfileInfo->lpUserName == NULL) || (lpProfileInfo->lpUserName[0] == 0))
1372 {
1373 SetLastError(ERROR_INVALID_PARAMETER);
1374 return FALSE;
1375 }
1376
1377 /* Convert the structure to UNICODE... */
1378 ProfileInfoW.dwSize = sizeof(ProfileInfoW);
1379 ProfileInfoW.dwFlags = lpProfileInfo->dwFlags;
1380
1381 if (lpProfileInfo->lpUserName)
1382 {
1383 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpUserName, -1, NULL, 0);
1384 ProfileInfoW.lpUserName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1385 if (!ProfileInfoW.lpUserName)
1386 {
1387 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1388 goto cleanup;
1389 }
1390 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpUserName, -1, ProfileInfoW.lpUserName, len);
1391 }
1392
1393 if (lpProfileInfo->lpProfilePath)
1394 {
1395 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpProfilePath, -1, NULL, 0);
1396 ProfileInfoW.lpProfilePath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1397 if (!ProfileInfoW.lpProfilePath)
1398 {
1399 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1400 goto cleanup;
1401 }
1402 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpProfilePath, -1, ProfileInfoW.lpProfilePath, len);
1403 }
1404
1405 if (lpProfileInfo->lpDefaultPath)
1406 {
1407 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpDefaultPath, -1, NULL, 0);
1408 ProfileInfoW.lpDefaultPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1409 if (!ProfileInfoW.lpDefaultPath)
1410 {
1411 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1412 goto cleanup;
1413 }
1414 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpDefaultPath, -1, ProfileInfoW.lpDefaultPath, len);
1415 }
1416
1417 if (lpProfileInfo->lpServerName)
1418 {
1419 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpServerName, -1, NULL, 0);
1420 ProfileInfoW.lpServerName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1421 if (!ProfileInfoW.lpServerName)
1422 {
1423 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1424 goto cleanup;
1425 }
1426 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpServerName, -1, ProfileInfoW.lpServerName, len);
1427 }
1428
1429 if ((ProfileInfoW.dwFlags & PI_APPLYPOLICY) != 0 && lpProfileInfo->lpPolicyPath)
1430 {
1431 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpPolicyPath, -1, NULL, 0);
1432 ProfileInfoW.lpPolicyPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1433 if (!ProfileInfoW.lpPolicyPath)
1434 {
1435 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1436 goto cleanup;
1437 }
1438 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpPolicyPath, -1, ProfileInfoW.lpPolicyPath, len);
1439 }
1440
1441 /* ... and call the UNICODE function */
1442 bResult = LoadUserProfileW(hToken, &ProfileInfoW);
1443
1444 /* Save the returned value */
1445 lpProfileInfo->hProfile = ProfileInfoW.hProfile;
1446
1447 cleanup:
1448 /* Memory cleanup */
1449 if (ProfileInfoW.lpUserName)
1450 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpUserName);
1451
1452 if (ProfileInfoW.lpProfilePath)
1453 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpProfilePath);
1454
1455 if (ProfileInfoW.lpDefaultPath)
1456 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpDefaultPath);
1457
1458 if (ProfileInfoW.lpServerName)
1459 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpServerName);
1460
1461 if ((ProfileInfoW.dwFlags & PI_APPLYPOLICY) != 0 && ProfileInfoW.lpPolicyPath)
1462 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpPolicyPath);
1463
1464 return bResult;
1465 }
1466
1467
1468 BOOL
1469 WINAPI
1470 LoadUserProfileW(
1471 _In_ HANDLE hToken,
1472 _Inout_ LPPROFILEINFOW lpProfileInfo)
1473 {
1474 WCHAR szUserHivePath[MAX_PATH];
1475 PTOKEN_USER UserSid = NULL;
1476 UNICODE_STRING SidString = { 0, 0, NULL };
1477 HANDLE hProfileMutex = NULL;
1478 LONG Error;
1479 BOOL ret = FALSE;
1480 DWORD dwLength = sizeof(szUserHivePath) / sizeof(szUserHivePath[0]);
1481
1482 DPRINT("LoadUserProfileW(%p %p)\n", hToken, lpProfileInfo);
1483
1484 /* Check profile info */
1485 if (!lpProfileInfo || (lpProfileInfo->dwSize != sizeof(PROFILEINFOW)) ||
1486 (lpProfileInfo->lpUserName == NULL) || (lpProfileInfo->lpUserName[0] == 0))
1487 {
1488 SetLastError(ERROR_INVALID_PARAMETER);
1489 return FALSE;
1490 }
1491
1492 DPRINT("UserName: %S\n", lpProfileInfo->lpUserName);
1493
1494 /* Get the user SID string */
1495 ret = GetUserSidStringFromToken(hToken, &SidString);
1496 if (!ret)
1497 {
1498 DPRINT1("GetUserSidStringFromToken() failed\n");
1499 goto cleanup;
1500 }
1501 ret = FALSE;
1502
1503 /* Create the profile mutex */
1504 hProfileMutex = CreateProfileMutex(SidString.Buffer);
1505 if (hProfileMutex == NULL)
1506 {
1507 DPRINT1("Failed to create the profile mutex\n");
1508 goto cleanup;
1509 }
1510
1511 /* Wait for the profile mutex */
1512 WaitForSingleObject(hProfileMutex, INFINITE);
1513
1514 /* Don't load a profile twice */
1515 if (CheckForLoadedProfile(hToken))
1516 {
1517 DPRINT1("Profile %S already loaded\n", SidString.Buffer);
1518 }
1519 else
1520 {
1521 DPRINT1("Loading profile %S\n", SidString.Buffer);
1522
1523 if (lpProfileInfo->lpProfilePath)
1524 {
1525 /* Use the caller's specified roaming user profile path */
1526 StringCbCopyW(szUserHivePath, sizeof(szUserHivePath), lpProfileInfo->lpProfilePath);
1527 }
1528 else
1529 {
1530 /* FIXME: check if MS Windows allows lpProfileInfo->lpProfilePath to be NULL */
1531 if (!GetProfilesDirectoryW(szUserHivePath, &dwLength))
1532 {
1533 DPRINT1("GetProfilesDirectoryW() failed (error %ld)\n", GetLastError());
1534 goto cleanup;
1535 }
1536 }
1537
1538 /* Create user hive name */
1539 StringCbCatW(szUserHivePath, sizeof(szUserHivePath), L"\\");
1540 StringCbCatW(szUserHivePath, sizeof(szUserHivePath), lpProfileInfo->lpUserName);
1541 StringCbCatW(szUserHivePath, sizeof(szUserHivePath), L"\\ntuser.dat");
1542 DPRINT("szUserHivePath: %S\n", szUserHivePath);
1543
1544 /* Create user profile directory if needed */
1545 if (GetFileAttributesW(szUserHivePath) == INVALID_FILE_ATTRIBUTES)
1546 {
1547 /* Get user sid */
1548 if (GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength) ||
1549 GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1550 {
1551 DPRINT1 ("GetTokenInformation() failed\n");
1552 goto cleanup;
1553 }
1554
1555 UserSid = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), 0, dwLength);
1556 if (!UserSid)
1557 {
1558 DPRINT1("HeapAlloc() failed\n");
1559 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1560 goto cleanup;
1561 }
1562
1563 if (!GetTokenInformation(hToken, TokenUser, UserSid, dwLength, &dwLength))
1564 {
1565 DPRINT1("GetTokenInformation() failed\n");
1566 goto cleanup;
1567 }
1568
1569 /* Create profile */
1570 ret = CreateUserProfileW(UserSid->User.Sid, lpProfileInfo->lpUserName);
1571 if (!ret)
1572 {
1573 DPRINT1("CreateUserProfileW() failed\n");
1574 goto cleanup;
1575 }
1576 }
1577
1578 /* Acquire restore privilege */
1579 if (!AcquireRemoveRestorePrivilege(TRUE))
1580 {
1581 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
1582 goto cleanup;
1583 }
1584
1585 /* Load user registry hive */
1586 Error = RegLoadKeyW(HKEY_USERS,
1587 SidString.Buffer,
1588 szUserHivePath);
1589 AcquireRemoveRestorePrivilege(FALSE);
1590
1591 /* HACK: Do not fail if the profile has already been loaded! */
1592 if (Error == ERROR_SHARING_VIOLATION)
1593 Error = ERROR_SUCCESS;
1594
1595 if (Error != ERROR_SUCCESS)
1596 {
1597 DPRINT1("RegLoadKeyW() failed (Error %ld)\n", Error);
1598 SetLastError((DWORD)Error);
1599 goto cleanup;
1600 }
1601 }
1602
1603 /* Open future HKEY_CURRENT_USER */
1604 Error = RegOpenKeyExW(HKEY_USERS,
1605 SidString.Buffer,
1606 0,
1607 MAXIMUM_ALLOWED,
1608 (PHKEY)&lpProfileInfo->hProfile);
1609 if (Error != ERROR_SUCCESS)
1610 {
1611 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error);
1612 SetLastError((DWORD)Error);
1613 goto cleanup;
1614 }
1615
1616 ret = TRUE;
1617
1618 cleanup:
1619 if (UserSid != NULL)
1620 HeapFree(GetProcessHeap(), 0, UserSid);
1621
1622 if (hProfileMutex != NULL)
1623 {
1624 ReleaseMutex(hProfileMutex);
1625 CloseHandle(hProfileMutex);
1626 }
1627
1628 RtlFreeUnicodeString(&SidString);
1629
1630 DPRINT("LoadUserProfileW() done\n");
1631 return ret;
1632 }
1633
1634
1635 BOOL
1636 WINAPI
1637 UnloadUserProfile(
1638 _In_ HANDLE hToken,
1639 _In_ HANDLE hProfile)
1640 {
1641 UNICODE_STRING SidString = {0, 0, NULL};
1642 HANDLE hProfileMutex = NULL;
1643 LONG Error;
1644 BOOL bRet = FALSE;
1645
1646 DPRINT("UnloadUserProfile() called\n");
1647
1648 if (hProfile == NULL)
1649 {
1650 DPRINT1("Invalid profile handle\n");
1651 SetLastError(ERROR_INVALID_PARAMETER);
1652 return FALSE;
1653 }
1654
1655 /* Get the user SID string */
1656 if (!GetUserSidStringFromToken(hToken, &SidString))
1657 {
1658 DPRINT1("GetUserSidStringFromToken() failed\n");
1659 return FALSE;
1660 }
1661
1662 DPRINT("SidString: '%wZ'\n", &SidString);
1663
1664 /* Create the profile mutex */
1665 hProfileMutex = CreateProfileMutex(SidString.Buffer);
1666 if (hProfileMutex == NULL)
1667 {
1668 DPRINT1("Failed to create the profile mutex\n");
1669 goto cleanup;
1670 }
1671
1672 /* Wait for the profile mutex */
1673 WaitForSingleObject(hProfileMutex, INFINITE);
1674
1675 /* Close the profile handle */
1676 RegCloseKey(hProfile);
1677
1678 /* Acquire restore privilege */
1679 if (!AcquireRemoveRestorePrivilege(TRUE))
1680 {
1681 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
1682 goto cleanup;
1683 }
1684
1685 /* HACK */
1686 {
1687 HKEY hUserKey;
1688
1689 Error = RegOpenKeyExW(HKEY_USERS,
1690 SidString.Buffer,
1691 0,
1692 KEY_WRITE,
1693 &hUserKey);
1694 if (Error == ERROR_SUCCESS)
1695 {
1696 RegDeleteKeyW(hUserKey,
1697 L"Volatile Environment");
1698
1699 RegCloseKey(hUserKey);
1700 }
1701 }
1702 /* End of HACK */
1703
1704 /* Unload the hive */
1705 Error = RegUnLoadKeyW(HKEY_USERS,
1706 SidString.Buffer);
1707
1708 /* Remove restore privilege */
1709 AcquireRemoveRestorePrivilege(FALSE);
1710
1711 if (Error != ERROR_SUCCESS)
1712 {
1713 DPRINT1("RegUnLoadKeyW() failed (Error %ld)\n", Error);
1714 SetLastError((DWORD)Error);
1715 goto cleanup;
1716 }
1717
1718 bRet = TRUE;
1719
1720 cleanup:
1721 if (hProfileMutex != NULL)
1722 {
1723 ReleaseMutex(hProfileMutex);
1724 CloseHandle(hProfileMutex);
1725 }
1726
1727 RtlFreeUnicodeString(&SidString);
1728
1729 DPRINT("UnloadUserProfile() done\n");
1730
1731 return bRet;
1732 }
1733
1734 /* EOF */