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