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