[USERENV] Implement DeleteProfileW()
[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 static
201 DWORD
202 IncrementRefCount(
203 PWSTR pszSidString,
204 PDWORD pdwRefCount)
205 {
206 HKEY hProfilesKey = NULL, hProfileKey = NULL;
207 DWORD dwRefCount = 0, dwLength, dwType;
208 DWORD dwError;
209
210 DPRINT1("IncrementRefCount(%S %p)\n",
211 pszSidString, pdwRefCount);
212
213 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
214 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
215 0,
216 KEY_QUERY_VALUE,
217 &hProfilesKey);
218 if (dwError != ERROR_SUCCESS)
219 {
220 DPRINT1("Error: %lu\n", dwError);
221 goto done;
222 }
223
224 dwError = RegOpenKeyExW(hProfilesKey,
225 pszSidString,
226 0,
227 KEY_QUERY_VALUE | KEY_SET_VALUE,
228 &hProfileKey);
229 if (dwError != ERROR_SUCCESS)
230 {
231 DPRINT1("Error: %lu\n", dwError);
232 goto done;
233 }
234
235 /* Get the reference counter */
236 dwLength = sizeof(dwRefCount);
237 RegQueryValueExW(hProfileKey,
238 L"RefCount",
239 NULL,
240 &dwType,
241 (PBYTE)&dwRefCount,
242 &dwLength);
243
244 dwRefCount++;
245
246 dwLength = sizeof(dwRefCount);
247 dwError = RegSetValueExW(hProfileKey,
248 L"RefCount",
249 0,
250 REG_DWORD,
251 (PBYTE)&dwRefCount,
252 dwLength);
253 if (dwError != ERROR_SUCCESS)
254 {
255 DPRINT1("Error: %lu\n", dwError);
256 goto done;
257 }
258
259 if (pdwRefCount != NULL)
260 *pdwRefCount = dwRefCount;
261
262 done:
263 if (hProfileKey != NULL)
264 RegCloseKey(hProfileKey);
265
266 if (hProfilesKey != NULL)
267 RegCloseKey(hProfilesKey);
268
269 return dwError;
270 }
271
272
273 static
274 DWORD
275 DecrementRefCount(
276 PWSTR pszSidString,
277 PDWORD pdwRefCount)
278 {
279 HKEY hProfilesKey = NULL, hProfileKey = NULL;
280 DWORD dwRefCount = 0, dwLength, dwType;
281 DWORD dwError;
282
283 DPRINT1("DecrementRefCount(%S %p)\n",
284 pszSidString, pdwRefCount);
285
286 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
287 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
288 0,
289 KEY_QUERY_VALUE,
290 &hProfilesKey);
291 if (dwError != ERROR_SUCCESS)
292 {
293 DPRINT1("Error: %lu\n", dwError);
294 goto done;
295 }
296
297 dwError = RegOpenKeyExW(hProfilesKey,
298 pszSidString,
299 0,
300 KEY_QUERY_VALUE | KEY_SET_VALUE,
301 &hProfileKey);
302 if (dwError != ERROR_SUCCESS)
303 {
304 DPRINT1("Error: %lu\n", dwError);
305 goto done;
306 }
307
308 /* Get the reference counter */
309 dwLength = sizeof(dwRefCount);
310 dwError = RegQueryValueExW(hProfileKey,
311 L"RefCount",
312 NULL,
313 &dwType,
314 (PBYTE)&dwRefCount,
315 &dwLength);
316 if (dwError != ERROR_SUCCESS)
317 {
318 DPRINT1("Error: %lu\n", dwError);
319 goto done;
320 }
321
322 dwRefCount--;
323
324 dwLength = sizeof(dwRefCount);
325 dwError = RegSetValueExW(hProfileKey,
326 L"RefCount",
327 0,
328 REG_DWORD,
329 (PBYTE)&dwRefCount,
330 dwLength);
331 if (dwError != ERROR_SUCCESS)
332 {
333 DPRINT1("Error: %lu\n", dwError);
334 goto done;
335 }
336
337 if (pdwRefCount != NULL)
338 *pdwRefCount = dwRefCount;
339
340 done:
341 if (hProfileKey != NULL)
342 RegCloseKey(hProfileKey);
343
344 if (hProfilesKey != NULL)
345 RegCloseKey(hProfilesKey);
346
347 return dwError;
348 }
349
350
351 static
352 DWORD
353 CheckForGuestsAndAdmins(
354 _In_ HANDLE hToken,
355 _Out_ PDWORD pdwState)
356 {
357 PTOKEN_GROUPS pGroupInfo = NULL;
358 PSID pAdministratorsSID = NULL;
359 PSID pGuestsSID = NULL;
360 DWORD i, dwSize = 0;
361 DWORD dwError = ERROR_SUCCESS;
362
363 DPRINT("CheckForGuestsAndAdmins(%p %p)\n", hToken, pdwState);
364
365 /* Get the buffer size */
366 if (!GetTokenInformation(hToken, TokenGroups, NULL, dwSize, &dwSize))
367 {
368 dwError = GetLastError();
369 if (dwError != ERROR_INSUFFICIENT_BUFFER)
370 {
371 DPRINT1("GetTokenInformation() failed (Error %lu)\n", dwError);
372 return dwError;
373 }
374
375 dwError = ERROR_SUCCESS;
376 }
377
378 /* Allocate the buffer */
379 pGroupInfo = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), 0, dwSize);
380 if (pGroupInfo == NULL)
381 {
382 dwError = ERROR_OUTOFMEMORY;
383 DPRINT1("HeapAlloc() failed (Error %lu)\n", dwError);
384 goto done;
385 }
386
387 /* Get the token groups */
388 if (!GetTokenInformation(hToken, TokenGroups, pGroupInfo, dwSize, &dwSize))
389 {
390 dwError = GetLastError();
391 DPRINT1("GetTokenInformation() failed (Error %lu)\n", dwError);
392 goto done;
393 }
394
395 /* Build the Administrators Group SID */
396 if(!AllocateAndInitializeSid(&LocalSystemAuthority,
397 2,
398 SECURITY_BUILTIN_DOMAIN_RID,
399 DOMAIN_ALIAS_RID_ADMINS,
400 0, 0, 0, 0, 0, 0,
401 &pAdministratorsSID))
402 {
403 dwError = GetLastError();
404 DPRINT1("AllocateAndInitializeSid() failed (Error %lu)\n", dwError);
405 goto done;
406 }
407
408 /* Build the Guests Group SID */
409 if(!AllocateAndInitializeSid(&LocalSystemAuthority,
410 2,
411 SECURITY_BUILTIN_DOMAIN_RID,
412 DOMAIN_ALIAS_RID_GUESTS,
413 0, 0, 0, 0, 0, 0,
414 &pGuestsSID))
415 {
416 dwError = GetLastError();
417 DPRINT1("AllocateAndInitializeSid() failed (Error %lu)\n", dwError);
418 goto done;
419 }
420
421 /* Check for Administratos or Guests group memberships */
422 for (i = 0; i < pGroupInfo->GroupCount; i++)
423 {
424 if (EqualSid(pAdministratorsSID, pGroupInfo->Groups[i].Sid))
425 {
426 *pdwState |= 0x0100; // PROFILE_ADMIN_USER
427 }
428
429 if (EqualSid(pGuestsSID, pGroupInfo->Groups[i].Sid))
430 {
431 *pdwState |= 0x0080; // PROFILE_GUESTS_USER
432 }
433 }
434
435 dwError = ERROR_SUCCESS;
436
437 done:
438 if (pGuestsSID != NULL)
439 FreeSid(pGuestsSID);
440
441 if (pAdministratorsSID != NULL)
442 FreeSid(pAdministratorsSID);
443
444 if (pGroupInfo != NULL)
445 HeapFree(GetProcessHeap(), 0, pGroupInfo);
446
447 return dwError;
448 }
449
450
451 static
452 DWORD
453 SetProfileData(
454 _In_ PWSTR pszSidString,
455 _In_ DWORD dwFlags,
456 _In_ HANDLE hToken)
457 {
458 HKEY hProfilesKey = NULL, hProfileKey = NULL;
459 FILETIME LoadTime;
460 DWORD dwLength, dwState = 0;
461 DWORD dwError;
462
463 DPRINT("SetProfileData(%S %p)\n", pszSidString, hToken);
464
465 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
466 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
467 0,
468 KEY_QUERY_VALUE,
469 &hProfilesKey);
470 if (dwError != ERROR_SUCCESS)
471 {
472 DPRINT1("Error: %lu\n", dwError);
473 goto done;
474 }
475
476 dwError = RegOpenKeyExW(hProfilesKey,
477 pszSidString,
478 0,
479 KEY_QUERY_VALUE | KEY_SET_VALUE,
480 &hProfileKey);
481 if (dwError != ERROR_SUCCESS)
482 {
483 DPRINT1("Error: %lu\n", dwError);
484 goto done;
485 }
486
487 /* Set the profile load time */
488 GetSystemTimeAsFileTime(&LoadTime);
489
490 dwLength = sizeof(LoadTime.dwLowDateTime);
491 dwError = RegSetValueExW(hProfileKey,
492 L"ProfileLoadTimeLow",
493 0,
494 REG_DWORD,
495 (PBYTE)&LoadTime.dwLowDateTime,
496 dwLength);
497 if (dwError != ERROR_SUCCESS)
498 {
499 DPRINT1("Error: %lu\n", dwError);
500 goto done;
501 }
502
503 dwLength = sizeof(LoadTime.dwHighDateTime);
504 dwError = RegSetValueExW(hProfileKey,
505 L"ProfileLoadTimeHigh",
506 0,
507 REG_DWORD,
508 (PBYTE)&LoadTime.dwHighDateTime,
509 dwLength);
510 if (dwError != ERROR_SUCCESS)
511 {
512 DPRINT1("Error: %lu\n", dwError);
513 goto done;
514 }
515
516 dwLength = sizeof(dwFlags);
517 dwError = RegSetValueExW(hProfileKey,
518 L"Flags",
519 0,
520 REG_DWORD,
521 (PBYTE)&dwFlags,
522 dwLength);
523 if (dwError != ERROR_SUCCESS)
524 {
525 DPRINT1("Error: %lu\n", dwError);
526 goto done;
527 }
528
529 dwError = CheckForGuestsAndAdmins(hToken,
530 &dwState);
531 if (dwError != ERROR_SUCCESS)
532 {
533 DPRINT1("Error: %lu\n", dwError);
534 goto done;
535 }
536
537 dwLength = sizeof(dwState);
538 dwError = RegSetValueExW(hProfileKey,
539 L"State",
540 0,
541 REG_DWORD,
542 (PBYTE)&dwState,
543 dwLength);
544 if (dwError != ERROR_SUCCESS)
545 {
546 DPRINT1("Error: %lu\n", dwError);
547 goto done;
548 }
549
550 done:
551 if (hProfileKey != NULL)
552 RegCloseKey(hProfileKey);
553
554 if (hProfilesKey != NULL)
555 RegCloseKey(hProfilesKey);
556
557 return dwError;
558 }
559
560
561 /* PUBLIC FUNCTIONS ********************************************************/
562
563 BOOL
564 WINAPI
565 CopySystemProfile(
566 _In_ ULONG Unused)
567 {
568 WCHAR szKeyName[MAX_PATH];
569 WCHAR szRawProfilePath[MAX_PATH];
570 WCHAR szProfilePath[MAX_PATH];
571 WCHAR szDefaultProfilePath[MAX_PATH];
572 UNICODE_STRING SidString = {0, 0, NULL};
573 HANDLE hToken = NULL;
574 PSID pUserSid = NULL;
575 HKEY hProfileKey = NULL;
576 DWORD dwDisposition;
577 BOOL bResult = FALSE;
578 DWORD cchSize;
579 DWORD dwError;
580
581 DPRINT1("CopySystemProfile()\n");
582
583 if (!OpenProcessToken(GetCurrentProcess(),
584 TOKEN_QUERY | TOKEN_IMPERSONATE,
585 &hToken))
586 {
587 DPRINT1("Failed to open the process token (Error %lu)\n", GetLastError());
588 return FALSE;
589 }
590
591 pUserSid = GetUserSid(hToken);
592 if (pUserSid == NULL)
593 {
594 DPRINT1("Failed to get the users SID (Error %lu)\n", GetLastError());
595 goto done;
596 }
597
598 /* Get the user SID string */
599 if (!GetUserSidStringFromToken(hToken, &SidString))
600 {
601 DPRINT1("GetUserSidStringFromToken() failed\n");
602 goto done;
603 }
604
605 StringCbCopyW(szKeyName, sizeof(szKeyName),
606 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
607 StringCbCatW(szKeyName, sizeof(szKeyName), SidString.Buffer);
608
609 RtlFreeUnicodeString(&SidString);
610
611 dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
612 szKeyName,
613 0, NULL, 0,
614 KEY_WRITE,
615 NULL,
616 &hProfileKey,
617 &dwDisposition);
618 if (dwError != ERROR_SUCCESS)
619 {
620 DPRINT1("Failed to create the profile key for the %s profile (Error %lu)\n",
621 SidString.Buffer, dwError);
622 goto done;
623 }
624
625 dwError = RegSetValueExW(hProfileKey,
626 L"Sid",
627 0,
628 REG_BINARY,
629 (PBYTE)pUserSid,
630 RtlLengthSid(pUserSid));
631 if (dwError != ERROR_SUCCESS)
632 {
633 DPRINT1("Failed to set the SID value (Error %lu)\n", dwError);
634 goto done;
635 }
636
637 wcscpy(szRawProfilePath,
638 L"%systemroot%\\system32\\config\\systemprofile");
639
640 dwError = RegSetValueExW(hProfileKey,
641 L"ProfileImagePath",
642 0,
643 REG_EXPAND_SZ,
644 (PBYTE)szRawProfilePath,
645 (wcslen(szRawProfilePath) + 1) * sizeof(WCHAR));
646 if (dwError != ERROR_SUCCESS)
647 {
648 DPRINT1("Failed to set the ProfileImagePath value (Error %lu)\n", dwError);
649 goto done;
650 }
651
652 /* Expand the raw profile path */
653 if (!ExpandEnvironmentStringsW(szRawProfilePath,
654 szProfilePath,
655 ARRAYSIZE(szProfilePath)))
656 {
657 DPRINT1("Failled to expand the raw profile path (Error %lu)\n", GetLastError());
658 goto done;
659 }
660
661 /* Create the profile directory if it does not exist yet */
662 // FIXME: Security!
663 if (!CreateDirectoryW(szProfilePath, NULL))
664 {
665 if (GetLastError() != ERROR_ALREADY_EXISTS)
666 {
667 DPRINT1("Failed to create the profile directory (Error %lu)\n", GetLastError());
668 goto done;
669 }
670 }
671
672 /* Get the path of the default profile */
673 cchSize = ARRAYSIZE(szDefaultProfilePath);
674 if (!GetDefaultUserProfileDirectoryW(szDefaultProfilePath, &cchSize))
675 {
676 DPRINT1("Failed to create the default profile path (Error %lu)\n", GetLastError());
677 goto done;
678 }
679
680 /* Copy the default profile into the new profile directory */
681 // FIXME: Security!
682 if (!CopyDirectory(szProfilePath, szDefaultProfilePath))
683 {
684 DPRINT1("Failed to copy the default profile directory (Error %lu)\n", GetLastError());
685 goto done;
686 }
687
688 bResult = TRUE;
689
690 done:
691 if (hProfileKey != NULL)
692 RegCloseKey(hProfileKey);
693
694 RtlFreeUnicodeString(&SidString);
695
696 if (pUserSid != NULL)
697 LocalFree(pUserSid);
698
699 if (hToken != NULL)
700 CloseHandle(hToken);
701
702 return bResult;
703 }
704
705
706 BOOL
707 WINAPI
708 CreateUserProfileA(
709 _In_ PSID pSid,
710 _In_ LPCSTR lpUserName)
711 {
712 LPWSTR pUserNameW = NULL;
713 INT nLength;
714 BOOL bResult;
715
716 DPRINT("CreateUserProfileA(%p %s)\n", pSid, lpUserName);
717
718 /* Convert lpUserName to Unicode */
719 nLength = MultiByteToWideChar(CP_ACP, 0, lpUserName, -1, NULL, 0);
720 pUserNameW = HeapAlloc(GetProcessHeap(), 0, nLength * sizeof(WCHAR));
721 if (pUserNameW == NULL)
722 {
723 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
724 return FALSE;
725 }
726 MultiByteToWideChar(CP_ACP, 0, lpUserName, -1, pUserNameW, nLength);
727
728 /* Call the Ex function */
729 bResult = CreateUserProfileExW(pSid,
730 pUserNameW,
731 NULL,
732 NULL,
733 0,
734 FALSE);
735
736 HeapFree(GetProcessHeap(), 0, pUserNameW);
737
738 return bResult;
739 }
740
741
742 BOOL
743 WINAPI
744 CreateUserProfileW(
745 _In_ PSID pSid,
746 _In_ LPCWSTR lpUserName)
747 {
748 DPRINT("CreateUserProfileW(%p %S)\n", pSid, lpUserName);
749
750 /* Call the Ex function */
751 return CreateUserProfileExW(pSid,
752 lpUserName,
753 NULL,
754 NULL,
755 0,
756 FALSE);
757 }
758
759
760 BOOL
761 WINAPI
762 CreateUserProfileExA(
763 _In_ PSID pSid,
764 _In_ LPCSTR lpUserName,
765 _In_opt_ LPCSTR lpUserHive,
766 _Out_opt_ LPSTR lpProfileDir,
767 _In_ DWORD dwDirSize,
768 _In_ BOOL bWin9xUpg)
769 {
770 LPWSTR pUserNameW = NULL;
771 LPWSTR pUserHiveW = NULL;
772 LPWSTR pProfileDirW = NULL;
773 INT nLength;
774 BOOL bResult = FALSE;
775
776 DPRINT("CreateUserProfileExA(%p %s %s %p %lu %d)\n",
777 pSid, lpUserName, lpUserHive, lpProfileDir, dwDirSize, bWin9xUpg);
778
779 /* Check the parameters */
780 if (lpProfileDir != NULL && dwDirSize == 0)
781 {
782 SetLastError(ERROR_INVALID_PARAMETER);
783 return FALSE;
784 }
785
786 /* Convert lpUserName to Unicode */
787 nLength = MultiByteToWideChar(CP_ACP, 0, lpUserName, -1, NULL, 0);
788 pUserNameW = HeapAlloc(GetProcessHeap(), 0, nLength * sizeof(WCHAR));
789 if (pUserNameW == NULL)
790 {
791 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
792 goto done;
793 }
794 MultiByteToWideChar(CP_ACP, 0, lpUserName, -1, pUserNameW, nLength);
795
796 /* Convert lpUserHive to Unicode */
797 if (lpUserHive != NULL)
798 {
799 nLength = MultiByteToWideChar(CP_ACP, 0, lpUserHive, -1, NULL, 0);
800 pUserHiveW = HeapAlloc(GetProcessHeap(), 0, nLength * sizeof(WCHAR));
801 if (pUserHiveW == NULL)
802 {
803 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
804 goto done;
805 }
806 MultiByteToWideChar(CP_ACP, 0, lpUserHive, -1, pUserHiveW, nLength);
807 }
808
809 /* Allocate a Unicode buffer for lpProfileDir */
810 if (lpProfileDir != NULL)
811 {
812 pProfileDirW = HeapAlloc(GetProcessHeap(), 0, dwDirSize * sizeof(WCHAR));
813 if (pProfileDirW == NULL)
814 {
815 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
816 goto done;
817 }
818 }
819
820 /* Call the Unicode function */
821 bResult = CreateUserProfileExW(pSid,
822 (LPCWSTR)pUserNameW,
823 (LPCWSTR)pUserHiveW,
824 pProfileDirW,
825 dwDirSize,
826 bWin9xUpg);
827
828 /* Convert the profile path to ANSI */
829 if (bResult && lpProfileDir != NULL)
830 {
831 WideCharToMultiByte(CP_ACP, 0, pProfileDirW, -1, lpProfileDir, dwDirSize, NULL, NULL);
832 }
833
834 done:
835 /* Free the buffers */
836 if (pProfileDirW != NULL)
837 HeapFree(GetProcessHeap(), 0, pProfileDirW);
838
839 if (pUserHiveW != NULL)
840 HeapFree(GetProcessHeap(), 0, pUserHiveW);
841
842 if (pUserNameW != NULL)
843 HeapFree(GetProcessHeap(), 0, pUserNameW);
844
845 return bResult;
846 }
847
848
849 BOOL
850 WINAPI
851 CreateUserProfileExW(
852 _In_ PSID pSid,
853 _In_ LPCWSTR lpUserName,
854 _In_opt_ LPCWSTR lpUserHive,
855 _Out_opt_ LPWSTR lpProfileDir,
856 _In_ DWORD dwDirSize,
857 _In_ BOOL bWin9xUpg)
858 {
859 WCHAR szRawProfilesPath[MAX_PATH];
860 WCHAR szProfilesPath[MAX_PATH];
861 WCHAR szUserProfilePath[MAX_PATH];
862 WCHAR szDefaultUserPath[MAX_PATH];
863 WCHAR szUserProfileName[MAX_PATH];
864 WCHAR szBuffer[MAX_PATH];
865 LPWSTR SidString;
866 DWORD dwType, dwLength;
867 DWORD dwDisposition;
868 UINT i;
869 HKEY hKey;
870 BOOL bRet = TRUE;
871 LONG Error;
872
873 DPRINT("CreateUserProfileExW(%p %S %S %p %lu %d)\n",
874 pSid, lpUserName, lpUserHive, lpProfileDir, dwDirSize, bWin9xUpg);
875
876 /* Parameters validation */
877 if (!pSid || !lpUserName)
878 {
879 SetLastError(ERROR_INVALID_PARAMETER);
880 return FALSE;
881 }
882
883 /*
884 * TODO:
885 * - Add support for lpUserHive.
886 * - bWin9xUpg is obsolete. Don't waste your time implementing this.
887 */
888
889 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
890 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
891 0,
892 KEY_QUERY_VALUE,
893 &hKey);
894 if (Error != ERROR_SUCCESS)
895 {
896 DPRINT1("Error: %lu\n", Error);
897 SetLastError((DWORD)Error);
898 return FALSE;
899 }
900
901 /* Get profiles path */
902 dwLength = sizeof(szRawProfilesPath);
903 Error = RegQueryValueExW(hKey,
904 L"ProfilesDirectory",
905 NULL,
906 &dwType,
907 (LPBYTE)szRawProfilesPath,
908 &dwLength);
909 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
910 {
911 DPRINT1("Error: %lu\n", Error);
912 RegCloseKey(hKey);
913 SetLastError((DWORD)Error);
914 return FALSE;
915 }
916
917 /* Expand it */
918 if (!ExpandEnvironmentStringsW(szRawProfilesPath,
919 szProfilesPath,
920 ARRAYSIZE(szProfilesPath)))
921 {
922 DPRINT1("Error: %lu\n", GetLastError());
923 RegCloseKey(hKey);
924 return FALSE;
925 }
926
927 /* Create the profiles directory if it does not exist yet */
928 // FIXME: Security!
929 if (!CreateDirectoryW(szProfilesPath, NULL))
930 {
931 if (GetLastError() != ERROR_ALREADY_EXISTS)
932 {
933 DPRINT1("Error: %lu\n", GetLastError());
934 return FALSE;
935 }
936 }
937
938 /* Get default user path */
939 dwLength = sizeof(szBuffer);
940 Error = RegQueryValueExW(hKey,
941 L"DefaultUserProfile",
942 NULL,
943 &dwType,
944 (LPBYTE)szBuffer,
945 &dwLength);
946 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
947 {
948 DPRINT1("Error: %lu\n", Error);
949 RegCloseKey(hKey);
950 SetLastError((DWORD)Error);
951 return FALSE;
952 }
953
954 RegCloseKey(hKey);
955
956 StringCbCopyW(szUserProfileName, sizeof(szUserProfileName), lpUserName);
957
958 /* Create user profile directory */
959
960 StringCbCopyW(szUserProfilePath, sizeof(szUserProfilePath), szProfilesPath);
961 StringCbCatW(szUserProfilePath, sizeof(szUserProfilePath), L"\\");
962 StringCbCatW(szUserProfilePath, sizeof(szUserProfilePath), szUserProfileName);
963
964 // FIXME: Security!
965 if (!CreateDirectoryW(szUserProfilePath, NULL))
966 {
967 if (GetLastError() != ERROR_ALREADY_EXISTS)
968 {
969 DPRINT1("Error: %lu\n", GetLastError());
970 return FALSE;
971 }
972
973 for (i = 0; i < 1000; i++)
974 {
975 swprintf(szUserProfileName, L"%s.%03u", lpUserName, i);
976
977 StringCbCopyW(szUserProfilePath, sizeof(szUserProfilePath), szProfilesPath);
978 StringCbCatW(szUserProfilePath, sizeof(szUserProfilePath), L"\\");
979 StringCbCatW(szUserProfilePath, sizeof(szUserProfilePath), szUserProfileName);
980
981 // FIXME: Security!
982 if (CreateDirectoryW(szUserProfilePath, NULL))
983 break;
984
985 if (GetLastError() != ERROR_ALREADY_EXISTS)
986 {
987 DPRINT1("Error: %lu\n", GetLastError());
988 return FALSE;
989 }
990 }
991 }
992
993 /* Copy default user directory */
994
995 StringCbCopyW(szDefaultUserPath, sizeof(szDefaultUserPath), szProfilesPath);
996 StringCbCatW(szDefaultUserPath, sizeof(szDefaultUserPath), L"\\");
997 StringCbCatW(szDefaultUserPath, sizeof(szDefaultUserPath), szBuffer);
998
999 // FIXME: Security!
1000 if (!CopyDirectory(szUserProfilePath, szDefaultUserPath))
1001 {
1002 DPRINT1("Error: %lu\n", GetLastError());
1003 return FALSE;
1004 }
1005
1006 /* Add profile to profile list */
1007 if (!ConvertSidToStringSidW(pSid,
1008 &SidString))
1009 {
1010 DPRINT1("Error: %lu\n", GetLastError());
1011 return FALSE;
1012 }
1013
1014 StringCbCopyW(szBuffer, sizeof(szBuffer),
1015 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
1016 StringCbCatW(szBuffer, sizeof(szBuffer), SidString);
1017
1018 /* Create user profile key */
1019 Error = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
1020 szBuffer,
1021 0,
1022 NULL,
1023 REG_OPTION_NON_VOLATILE,
1024 KEY_ALL_ACCESS,
1025 NULL,
1026 &hKey,
1027 &dwDisposition);
1028 if (Error != ERROR_SUCCESS)
1029 {
1030 DPRINT1("Error: %lu\n", Error);
1031 bRet = FALSE;
1032 goto done;
1033 }
1034
1035 /* Create non-expanded user profile path */
1036 StringCbCopyW(szBuffer, sizeof(szBuffer), szRawProfilesPath);
1037 StringCbCatW(szBuffer, sizeof(szBuffer), L"\\");
1038 StringCbCatW(szBuffer, sizeof(szBuffer), szUserProfileName);
1039
1040 /* Set 'ProfileImagePath' value (non-expanded) */
1041 Error = RegSetValueExW(hKey,
1042 L"ProfileImagePath",
1043 0,
1044 REG_EXPAND_SZ,
1045 (LPBYTE)szBuffer,
1046 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
1047 if (Error != ERROR_SUCCESS)
1048 {
1049 DPRINT1("Error: %lu\n", Error);
1050 RegCloseKey(hKey);
1051 bRet = FALSE;
1052 goto done;
1053 }
1054
1055 /* Set 'Sid' value */
1056 Error = RegSetValueExW(hKey,
1057 L"Sid",
1058 0,
1059 REG_BINARY,
1060 pSid,
1061 GetLengthSid(pSid));
1062 if (Error != ERROR_SUCCESS)
1063 {
1064 DPRINT1("Error: %lu\n", Error);
1065 RegCloseKey(hKey);
1066 bRet = FALSE;
1067 goto done;
1068 }
1069
1070 RegCloseKey(hKey);
1071
1072 /* Create user hive file */
1073
1074 /* Use the default hive file name */
1075 StringCbCopyW(szBuffer, sizeof(szBuffer), szUserProfilePath);
1076 StringCbCatW(szBuffer, sizeof(szBuffer), L"\\ntuser.dat");
1077
1078 /* Acquire restore privilege */
1079 if (!AcquireRemoveRestorePrivilege(TRUE))
1080 {
1081 Error = GetLastError();
1082 DPRINT1("Error: %lu\n", Error);
1083 bRet = FALSE;
1084 goto done;
1085 }
1086
1087 /* Load the user hive */
1088 Error = RegLoadKeyW(HKEY_USERS,
1089 SidString,
1090 szBuffer);
1091 AcquireRemoveRestorePrivilege(FALSE);
1092 if (Error != ERROR_SUCCESS)
1093 {
1094 DPRINT1("Error: %lu\n", Error);
1095 bRet = FALSE;
1096 goto done;
1097 }
1098
1099 /* Initialize user hive */
1100 if (!CreateUserHive(SidString, szUserProfilePath))
1101 {
1102 Error = GetLastError();
1103 DPRINT1("Error: %lu\n", Error);
1104 bRet = FALSE;
1105 }
1106
1107 /* Unload the hive */
1108 AcquireRemoveRestorePrivilege(TRUE);
1109 RegUnLoadKeyW(HKEY_USERS, SidString);
1110 AcquireRemoveRestorePrivilege(FALSE);
1111
1112 /*
1113 * If the caller wants to retrieve the user profile path,
1114 * give it now. 'dwDirSize' is the number of characters.
1115 */
1116 if (lpProfileDir && dwDirSize)
1117 StringCchCopyW(lpProfileDir, dwDirSize, szUserProfilePath);
1118
1119 done:
1120 LocalFree((HLOCAL)SidString);
1121 SetLastError((DWORD)Error);
1122
1123 DPRINT("CreateUserProfileExW() done\n");
1124
1125 return bRet;
1126 }
1127
1128
1129 BOOL
1130 WINAPI
1131 DeleteProfileA(
1132 _In_ LPCSTR lpSidString,
1133 _In_opt_ LPCSTR lpProfilePath,
1134 _In_opt_ LPCSTR lpComputerName)
1135 {
1136 BOOL bResult;
1137 UNICODE_STRING SidString = {0, 0, NULL}, ProfilePath = {0, 0, NULL}, ComputerName = {0, 0, NULL};
1138
1139 DPRINT("DeleteProfileA() called\n");
1140
1141 /* Conversion to UNICODE */
1142 if (lpSidString)
1143 RtlCreateUnicodeStringFromAsciiz(&SidString,
1144 (LPSTR)lpSidString);
1145
1146 if (lpProfilePath)
1147 RtlCreateUnicodeStringFromAsciiz(&ProfilePath,
1148 (LPSTR)lpProfilePath);
1149
1150 if (lpComputerName)
1151 RtlCreateUnicodeStringFromAsciiz(&ComputerName,
1152 (LPSTR)lpComputerName);
1153
1154 /* Call the UNICODE function */
1155 bResult = DeleteProfileW(SidString.Buffer,
1156 ProfilePath.Buffer,
1157 ComputerName.Buffer);
1158
1159 /* Memory cleanup */
1160 if (lpSidString)
1161 RtlFreeUnicodeString(&SidString);
1162
1163 if (lpProfilePath)
1164 RtlFreeUnicodeString(&ProfilePath);
1165
1166 if (lpComputerName)
1167 RtlFreeUnicodeString(&ComputerName);
1168
1169 return bResult;
1170 }
1171
1172
1173 BOOL
1174 WINAPI
1175 DeleteProfileW(
1176 _In_ LPCWSTR lpSidString,
1177 _In_opt_ LPCWSTR lpProfilePath,
1178 _In_opt_ LPCWSTR lpComputerName)
1179 {
1180 HKEY hProfilesKey = NULL, hProfileKey = NULL;
1181 WCHAR szRawProfilePath[MAX_PATH], szProfilePath[MAX_PATH];
1182 DWORD dwLength, dwType;
1183 DWORD dwError = ERROR_SUCCESS;
1184 BOOL bRet = FALSE;
1185
1186 DPRINT("DeleteProfileW(%S %S %S)\n", lpSidString, lpProfilePath, lpComputerName);
1187
1188 if (lpSidString == NULL)
1189 {
1190 SetLastError(ERROR_INVALID_PARAMETER);
1191 return FALSE;
1192 }
1193
1194 if (lpProfilePath != NULL)
1195 {
1196 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1197 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1198 0,
1199 KEY_QUERY_VALUE,
1200 &hProfilesKey);
1201 if (dwError != ERROR_SUCCESS)
1202 {
1203 DPRINT1("Error: %lu\n", dwError);
1204 goto done;
1205 }
1206
1207 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1208 lpSidString,
1209 0,
1210 KEY_QUERY_VALUE,
1211 &hProfileKey);
1212 if (dwError != ERROR_SUCCESS)
1213 {
1214 DPRINT1("Error: %lu\n", dwError);
1215 goto done;
1216 }
1217
1218 /* Get the profile image path */
1219 dwLength = sizeof(szRawProfilePath);
1220 dwError = RegQueryValueExW(hProfileKey,
1221 L"ProfileImagePath",
1222 NULL,
1223 &dwType,
1224 (PBYTE)szRawProfilePath,
1225 &dwLength);
1226 if (dwError != ERROR_SUCCESS)
1227 {
1228 DPRINT1("Error: %lu\n", dwError);
1229 goto done;
1230 }
1231
1232 if (!ExpandEnvironmentStringsW(szRawProfilePath,
1233 szProfilePath,
1234 ARRAYSIZE(szProfilePath)))
1235 {
1236 dwError = GetLastError();
1237 DPRINT1("Failled to expand the raw profile path (Error %lu)\n", dwError);
1238 goto done;
1239 }
1240 }
1241 else
1242 {
1243 StringCchCopyW(szProfilePath, ARRAYSIZE(szProfilePath), lpProfilePath);
1244 }
1245
1246 DPRINT("ProfilePath: %S\n", szProfilePath);
1247
1248 if (!RemoveDirectoryPath(szProfilePath))
1249 {
1250 dwError = GetLastError();
1251 DPRINT1("Error: %lu\n", dwError);
1252 goto done;
1253 }
1254
1255 bRet = TRUE;
1256
1257 done:
1258 if (hProfileKey != NULL)
1259 RegCloseKey(hProfileKey);
1260
1261 if (hProfilesKey != NULL)
1262 RegCloseKey(hProfilesKey);
1263
1264 return bRet;
1265 }
1266
1267
1268 BOOL
1269 WINAPI
1270 GetAllUsersProfileDirectoryA(
1271 _Out_opt_ LPSTR lpProfileDir,
1272 _Inout_ LPDWORD lpcchSize)
1273 {
1274 LPWSTR lpBuffer;
1275 BOOL bResult;
1276
1277 if (!lpcchSize)
1278 {
1279 SetLastError(ERROR_INVALID_PARAMETER);
1280 return FALSE;
1281 }
1282
1283 lpBuffer = GlobalAlloc(GMEM_FIXED,
1284 *lpcchSize * sizeof(WCHAR));
1285 if (lpBuffer == NULL)
1286 return FALSE;
1287
1288 bResult = GetAllUsersProfileDirectoryW(lpBuffer,
1289 lpcchSize);
1290 if (bResult && lpProfileDir)
1291 {
1292 bResult = WideCharToMultiByte(CP_ACP,
1293 0,
1294 lpBuffer,
1295 -1,
1296 lpProfileDir,
1297 *lpcchSize,
1298 NULL,
1299 NULL);
1300 }
1301
1302 GlobalFree(lpBuffer);
1303
1304 return bResult;
1305 }
1306
1307
1308 BOOL
1309 WINAPI
1310 GetAllUsersProfileDirectoryW(
1311 _Out_opt_ LPWSTR lpProfileDir,
1312 _Inout_ LPDWORD lpcchSize)
1313 {
1314 WCHAR szProfilePath[MAX_PATH];
1315 WCHAR szBuffer[MAX_PATH];
1316 DWORD dwType, dwLength;
1317 HKEY hKey;
1318 LONG Error;
1319
1320 if (!lpcchSize)
1321 {
1322 SetLastError(ERROR_INVALID_PARAMETER);
1323 return FALSE;
1324 }
1325
1326 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1327 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1328 0,
1329 KEY_QUERY_VALUE,
1330 &hKey);
1331 if (Error != ERROR_SUCCESS)
1332 {
1333 DPRINT1("Error: %lu\n", Error);
1334 SetLastError((DWORD)Error);
1335 return FALSE;
1336 }
1337
1338 /* Get profiles path */
1339 dwLength = sizeof(szBuffer);
1340 Error = RegQueryValueExW(hKey,
1341 L"ProfilesDirectory",
1342 NULL,
1343 &dwType,
1344 (LPBYTE)szBuffer,
1345 &dwLength);
1346 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
1347 {
1348 DPRINT1("Error: %lu\n", Error);
1349 RegCloseKey(hKey);
1350 SetLastError((DWORD)Error);
1351 return FALSE;
1352 }
1353
1354 /* Expand it */
1355 if (!ExpandEnvironmentStringsW(szBuffer,
1356 szProfilePath,
1357 ARRAYSIZE(szProfilePath)))
1358 {
1359 DPRINT1("Error: %lu\n", GetLastError());
1360 RegCloseKey(hKey);
1361 return FALSE;
1362 }
1363
1364 /* Get 'AllUsersProfile' name */
1365 dwLength = sizeof(szBuffer);
1366 Error = RegQueryValueExW(hKey,
1367 L"AllUsersProfile",
1368 NULL,
1369 &dwType,
1370 (LPBYTE)szBuffer,
1371 &dwLength);
1372 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
1373 {
1374 DPRINT1("Error: %lu\n", Error);
1375 RegCloseKey(hKey);
1376 SetLastError((DWORD)Error);
1377 return FALSE;
1378 }
1379
1380 RegCloseKey(hKey);
1381
1382 StringCbCatW(szProfilePath, sizeof(szProfilePath), L"\\");
1383 StringCbCatW(szProfilePath, sizeof(szProfilePath), szBuffer);
1384
1385 dwLength = wcslen(szProfilePath) + 1;
1386 if (lpProfileDir && (*lpcchSize >= dwLength))
1387 {
1388 StringCchCopyW(lpProfileDir, *lpcchSize, szProfilePath);
1389 *lpcchSize = dwLength;
1390 return TRUE;
1391 }
1392 else // if (!lpProfileDir || (*lpcchSize < dwLength))
1393 {
1394 *lpcchSize = dwLength;
1395 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1396 return FALSE;
1397 }
1398 }
1399
1400
1401 BOOL
1402 WINAPI
1403 GetDefaultUserProfileDirectoryA(
1404 _Out_opt_ LPSTR lpProfileDir,
1405 _Inout_ LPDWORD lpcchSize)
1406 {
1407 LPWSTR lpBuffer;
1408 BOOL bResult;
1409
1410 if (!lpcchSize)
1411 {
1412 SetLastError(ERROR_INVALID_PARAMETER);
1413 return FALSE;
1414 }
1415
1416 lpBuffer = GlobalAlloc(GMEM_FIXED,
1417 *lpcchSize * sizeof(WCHAR));
1418 if (lpBuffer == NULL)
1419 return FALSE;
1420
1421 bResult = GetDefaultUserProfileDirectoryW(lpBuffer,
1422 lpcchSize);
1423 if (bResult && lpProfileDir)
1424 {
1425 bResult = WideCharToMultiByte(CP_ACP,
1426 0,
1427 lpBuffer,
1428 -1,
1429 lpProfileDir,
1430 *lpcchSize,
1431 NULL,
1432 NULL);
1433 }
1434
1435 GlobalFree(lpBuffer);
1436
1437 return bResult;
1438 }
1439
1440
1441 BOOL
1442 WINAPI
1443 GetDefaultUserProfileDirectoryW(
1444 _Out_opt_ LPWSTR lpProfileDir,
1445 _Inout_ LPDWORD lpcchSize)
1446 {
1447 WCHAR szProfilePath[MAX_PATH];
1448 WCHAR szBuffer[MAX_PATH];
1449 DWORD dwType, dwLength;
1450 HKEY hKey;
1451 LONG Error;
1452
1453 if (!lpcchSize)
1454 {
1455 SetLastError(ERROR_INVALID_PARAMETER);
1456 return FALSE;
1457 }
1458
1459 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1460 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1461 0,
1462 KEY_QUERY_VALUE,
1463 &hKey);
1464 if (Error != ERROR_SUCCESS)
1465 {
1466 DPRINT1("Error: %lu\n", Error);
1467 SetLastError((DWORD)Error);
1468 return FALSE;
1469 }
1470
1471 /* Get profiles path */
1472 dwLength = sizeof(szBuffer);
1473 Error = RegQueryValueExW(hKey,
1474 L"ProfilesDirectory",
1475 NULL,
1476 &dwType,
1477 (LPBYTE)szBuffer,
1478 &dwLength);
1479 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
1480 {
1481 DPRINT1("Error: %lu\n", Error);
1482 RegCloseKey(hKey);
1483 SetLastError((DWORD)Error);
1484 return FALSE;
1485 }
1486
1487 /* Expand it */
1488 if (!ExpandEnvironmentStringsW(szBuffer,
1489 szProfilePath,
1490 ARRAYSIZE(szProfilePath)))
1491 {
1492 DPRINT1("Error: %lu\n", GetLastError());
1493 RegCloseKey(hKey);
1494 return FALSE;
1495 }
1496
1497 /* Get 'DefaultUserProfile' name */
1498 dwLength = sizeof(szBuffer);
1499 Error = RegQueryValueExW(hKey,
1500 L"DefaultUserProfile",
1501 NULL,
1502 &dwType,
1503 (LPBYTE)szBuffer,
1504 &dwLength);
1505 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
1506 {
1507 DPRINT1("Error: %lu\n", Error);
1508 RegCloseKey(hKey);
1509 SetLastError((DWORD)Error);
1510 return FALSE;
1511 }
1512
1513 RegCloseKey(hKey);
1514
1515 StringCbCatW(szProfilePath, sizeof(szProfilePath), L"\\");
1516 StringCbCatW(szProfilePath, sizeof(szProfilePath), szBuffer);
1517
1518 dwLength = wcslen(szProfilePath) + 1;
1519 if (lpProfileDir && (*lpcchSize >= dwLength))
1520 {
1521 StringCchCopyW(lpProfileDir, *lpcchSize, szProfilePath);
1522 *lpcchSize = dwLength;
1523 return TRUE;
1524 }
1525 else // if (!lpProfileDir || (*lpcchSize < dwLength))
1526 {
1527 *lpcchSize = dwLength;
1528 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1529 return FALSE;
1530 }
1531 }
1532
1533
1534 BOOL
1535 WINAPI
1536 GetProfilesDirectoryA(
1537 _Out_ LPSTR lpProfileDir, // _Out_opt_
1538 _Inout_ LPDWORD lpcchSize)
1539 {
1540 LPWSTR lpBuffer;
1541 BOOL bResult;
1542
1543 if (!lpcchSize || !lpProfileDir)
1544 {
1545 SetLastError(ERROR_INVALID_PARAMETER);
1546 return FALSE;
1547 }
1548
1549 lpBuffer = GlobalAlloc(GMEM_FIXED,
1550 *lpcchSize * sizeof(WCHAR));
1551 if (lpBuffer == NULL)
1552 return FALSE;
1553
1554 bResult = GetProfilesDirectoryW(lpBuffer,
1555 lpcchSize);
1556 if (bResult && lpProfileDir)
1557 {
1558 bResult = WideCharToMultiByte(CP_ACP,
1559 0,
1560 lpBuffer,
1561 -1,
1562 lpProfileDir,
1563 *lpcchSize,
1564 NULL,
1565 NULL);
1566 }
1567
1568 GlobalFree(lpBuffer);
1569
1570 return bResult;
1571 }
1572
1573
1574 BOOL
1575 WINAPI
1576 GetProfilesDirectoryW(
1577 _Out_ LPWSTR lpProfilesDir, // _Out_opt_
1578 _Inout_ LPDWORD lpcchSize)
1579 {
1580 WCHAR szProfilesPath[MAX_PATH];
1581 WCHAR szBuffer[MAX_PATH];
1582 DWORD dwType, dwLength;
1583 HKEY hKey;
1584 LONG Error;
1585
1586 if (!lpcchSize)
1587 {
1588 SetLastError(ERROR_INVALID_PARAMETER);
1589 return FALSE;
1590 }
1591
1592 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1593 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1594 0,
1595 KEY_QUERY_VALUE,
1596 &hKey);
1597 if (Error != ERROR_SUCCESS)
1598 {
1599 DPRINT1("Error: %lu\n", Error);
1600 SetLastError((DWORD)Error);
1601 return FALSE;
1602 }
1603
1604 /* Get profiles path */
1605 dwLength = sizeof(szBuffer);
1606 Error = RegQueryValueExW(hKey,
1607 L"ProfilesDirectory",
1608 NULL,
1609 &dwType,
1610 (LPBYTE)szBuffer,
1611 &dwLength);
1612 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
1613 {
1614 DPRINT1("Error: %lu\n", Error);
1615 RegCloseKey(hKey);
1616 SetLastError((DWORD)Error);
1617 return FALSE;
1618 }
1619
1620 RegCloseKey(hKey);
1621
1622 /* Expand it */
1623 if (!ExpandEnvironmentStringsW(szBuffer,
1624 szProfilesPath,
1625 ARRAYSIZE(szProfilesPath)))
1626 {
1627 DPRINT1("Error: %lu\n", GetLastError());
1628 return FALSE;
1629 }
1630
1631 dwLength = wcslen(szProfilesPath) + 1;
1632 if (lpProfilesDir && (*lpcchSize >= dwLength))
1633 {
1634 StringCchCopyW(lpProfilesDir, *lpcchSize, szProfilesPath);
1635 *lpcchSize = dwLength;
1636 return TRUE;
1637 }
1638 else // if (!lpProfilesDir || (*lpcchSize < dwLength))
1639 {
1640 *lpcchSize = dwLength;
1641 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1642 return FALSE;
1643 }
1644 }
1645
1646
1647 BOOL
1648 WINAPI
1649 GetProfileType(
1650 _Out_ PDWORD pdwFlags)
1651 {
1652 UNICODE_STRING SidString = {0, 0, NULL};
1653 HANDLE hToken;
1654 HKEY hProfilesKey = NULL, hProfileKey = NULL;
1655 DWORD dwType, dwLength, dwState = 0;
1656 DWORD dwError;
1657 BOOL bResult = FALSE;
1658
1659 DPRINT("GetProfileType(%p)\n", pdwFlags);
1660
1661 if (pdwFlags == NULL)
1662 {
1663 SetLastError(ERROR_INVALID_PARAMETER);
1664 return FALSE;
1665 }
1666
1667 if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken))
1668 {
1669 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
1670 {
1671 DPRINT1("Failed to open a token (Error %lu)\n", GetLastError());
1672 return FALSE;
1673 }
1674 }
1675
1676 /* Get the user SID string */
1677 if (!GetUserSidStringFromToken(hToken, &SidString))
1678 {
1679 DPRINT1("GetUserSidStringFromToken() failed\n");
1680 goto done;
1681 }
1682
1683 DPRINT("SID: %wZ\n", &SidString);
1684
1685 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1686 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1687 0,
1688 KEY_QUERY_VALUE,
1689 &hProfilesKey);
1690 if (dwError != ERROR_SUCCESS)
1691 {
1692 DPRINT1("Error: %lu\n", dwError);
1693 SetLastError(dwError);
1694 goto done;
1695 }
1696
1697 dwError = RegOpenKeyExW(hProfilesKey,
1698 SidString.Buffer,
1699 0,
1700 KEY_QUERY_VALUE | KEY_SET_VALUE,
1701 &hProfileKey);
1702 if (dwError != ERROR_SUCCESS)
1703 {
1704 DPRINT1("Error: %lu\n", dwError);
1705 SetLastError(dwError);
1706 goto done;
1707 }
1708
1709 /* Get the State value */
1710 dwLength = sizeof(dwState);
1711 dwError = RegQueryValueExW(hProfileKey,
1712 L"State",
1713 NULL,
1714 &dwType,
1715 (PBYTE)&dwState,
1716 &dwLength);
1717 if (dwError != ERROR_SUCCESS)
1718 {
1719 DPRINT1("Error: %lu\n", dwError);
1720 SetLastError(dwError);
1721 goto done;
1722 }
1723
1724 *pdwFlags = 0;
1725
1726 if (dwState & 0x80) /* PROFILE_GUEST_USER */
1727 *pdwFlags |= PT_TEMPORARY;
1728
1729 /* FIXME: Add checks for PT_MANDATORY and PT_ROAMING */
1730
1731 bResult = TRUE;
1732
1733 done:
1734 if (hProfileKey != NULL)
1735 RegCloseKey(hProfileKey);
1736
1737 if (hProfilesKey != NULL)
1738 RegCloseKey(hProfilesKey);
1739
1740 RtlFreeUnicodeString(&SidString);
1741
1742 CloseHandle(hToken);
1743
1744 return bResult;
1745 }
1746
1747
1748 BOOL
1749 WINAPI
1750 GetUserProfileDirectoryA(
1751 _In_ HANDLE hToken,
1752 _Out_opt_ LPSTR lpProfileDir,
1753 _Inout_ LPDWORD lpcchSize)
1754 {
1755 LPWSTR lpBuffer;
1756 BOOL bResult;
1757
1758 if (!lpcchSize || !lpProfileDir)
1759 {
1760 SetLastError(ERROR_INVALID_PARAMETER);
1761 return FALSE;
1762 }
1763
1764 lpBuffer = GlobalAlloc(GMEM_FIXED,
1765 *lpcchSize * sizeof(WCHAR));
1766 if (lpBuffer == NULL)
1767 return FALSE;
1768
1769 bResult = GetUserProfileDirectoryW(hToken,
1770 lpBuffer,
1771 lpcchSize);
1772 if (bResult && lpProfileDir)
1773 {
1774 bResult = WideCharToMultiByte(CP_ACP,
1775 0,
1776 lpBuffer,
1777 -1,
1778 lpProfileDir,
1779 *lpcchSize,
1780 NULL,
1781 NULL);
1782 }
1783
1784 GlobalFree(lpBuffer);
1785
1786 return bResult;
1787 }
1788
1789
1790 BOOL
1791 WINAPI
1792 GetUserProfileDirectoryW(
1793 _In_ HANDLE hToken,
1794 _Out_opt_ LPWSTR lpProfileDir,
1795 _Inout_ LPDWORD lpcchSize)
1796 {
1797 UNICODE_STRING SidString;
1798 WCHAR szKeyName[MAX_PATH];
1799 WCHAR szRawImagePath[MAX_PATH];
1800 WCHAR szImagePath[MAX_PATH];
1801 DWORD dwType, dwLength;
1802 HKEY hKey;
1803 LONG Error;
1804
1805 if (!hToken)
1806 {
1807 SetLastError(ERROR_INVALID_HANDLE);
1808 return FALSE;
1809 }
1810
1811 if (!lpcchSize)
1812 {
1813 SetLastError(ERROR_INVALID_PARAMETER);
1814 return FALSE;
1815 }
1816
1817 /* Get the user SID string */
1818 if (!GetUserSidStringFromToken(hToken, &SidString))
1819 {
1820 DPRINT1("GetUserSidStringFromToken() failed\n");
1821 return FALSE;
1822 }
1823
1824 DPRINT("SidString: '%wZ'\n", &SidString);
1825
1826 StringCbCopyW(szKeyName, sizeof(szKeyName),
1827 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
1828 StringCbCatW(szKeyName, sizeof(szKeyName), SidString.Buffer);
1829
1830 RtlFreeUnicodeString(&SidString);
1831
1832 DPRINT("KeyName: '%S'\n", szKeyName);
1833
1834 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1835 szKeyName,
1836 0,
1837 KEY_QUERY_VALUE,
1838 &hKey);
1839 if (Error != ERROR_SUCCESS)
1840 {
1841 DPRINT1("Error: %lu\n", Error);
1842 SetLastError((DWORD)Error);
1843 return FALSE;
1844 }
1845
1846 dwLength = sizeof(szRawImagePath);
1847 Error = RegQueryValueExW(hKey,
1848 L"ProfileImagePath",
1849 NULL,
1850 &dwType,
1851 (LPBYTE)szRawImagePath,
1852 &dwLength);
1853 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
1854 {
1855 DPRINT1("Error: %lu\n", Error);
1856 RegCloseKey(hKey);
1857 SetLastError((DWORD)Error);
1858 return FALSE;
1859 }
1860
1861 RegCloseKey(hKey);
1862
1863 DPRINT("RawImagePath: '%S'\n", szRawImagePath);
1864
1865 /* Expand it */
1866 if (!ExpandEnvironmentStringsW(szRawImagePath,
1867 szImagePath,
1868 ARRAYSIZE(szImagePath)))
1869 {
1870 DPRINT1("Error: %lu\n", GetLastError());
1871 return FALSE;
1872 }
1873
1874 DPRINT("ImagePath: '%S'\n", szImagePath);
1875
1876 dwLength = wcslen(szImagePath) + 1;
1877 if (lpProfileDir && (*lpcchSize >= dwLength))
1878 {
1879 StringCchCopyW(lpProfileDir, *lpcchSize, szImagePath);
1880 *lpcchSize = dwLength;
1881 return TRUE;
1882 }
1883 else // if (!lpProfileDir || (*lpcchSize < dwLength))
1884 {
1885 *lpcchSize = dwLength;
1886 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1887 return FALSE;
1888 }
1889 }
1890
1891
1892 BOOL
1893 WINAPI
1894 LoadUserProfileA(
1895 _In_ HANDLE hToken,
1896 _Inout_ LPPROFILEINFOA lpProfileInfo)
1897 {
1898 BOOL bResult = FALSE;
1899 PROFILEINFOW ProfileInfoW = {0};
1900 int len;
1901
1902 DPRINT("LoadUserProfileA() called\n");
1903
1904 /* Check profile info */
1905 if (!lpProfileInfo || (lpProfileInfo->dwSize != sizeof(PROFILEINFOA)) ||
1906 (lpProfileInfo->lpUserName == NULL) || (lpProfileInfo->lpUserName[0] == 0))
1907 {
1908 SetLastError(ERROR_INVALID_PARAMETER);
1909 return FALSE;
1910 }
1911
1912 /* Convert the structure to UNICODE... */
1913 ProfileInfoW.dwSize = sizeof(ProfileInfoW);
1914 ProfileInfoW.dwFlags = lpProfileInfo->dwFlags;
1915
1916 if (lpProfileInfo->lpUserName)
1917 {
1918 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpUserName, -1, NULL, 0);
1919 ProfileInfoW.lpUserName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1920 if (!ProfileInfoW.lpUserName)
1921 {
1922 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1923 goto cleanup;
1924 }
1925 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpUserName, -1, ProfileInfoW.lpUserName, len);
1926 }
1927
1928 if (lpProfileInfo->lpProfilePath)
1929 {
1930 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpProfilePath, -1, NULL, 0);
1931 ProfileInfoW.lpProfilePath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1932 if (!ProfileInfoW.lpProfilePath)
1933 {
1934 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1935 goto cleanup;
1936 }
1937 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpProfilePath, -1, ProfileInfoW.lpProfilePath, len);
1938 }
1939
1940 if (lpProfileInfo->lpDefaultPath)
1941 {
1942 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpDefaultPath, -1, NULL, 0);
1943 ProfileInfoW.lpDefaultPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1944 if (!ProfileInfoW.lpDefaultPath)
1945 {
1946 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1947 goto cleanup;
1948 }
1949 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpDefaultPath, -1, ProfileInfoW.lpDefaultPath, len);
1950 }
1951
1952 if (lpProfileInfo->lpServerName)
1953 {
1954 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpServerName, -1, NULL, 0);
1955 ProfileInfoW.lpServerName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1956 if (!ProfileInfoW.lpServerName)
1957 {
1958 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1959 goto cleanup;
1960 }
1961 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpServerName, -1, ProfileInfoW.lpServerName, len);
1962 }
1963
1964 if ((ProfileInfoW.dwFlags & PI_APPLYPOLICY) != 0 && lpProfileInfo->lpPolicyPath)
1965 {
1966 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpPolicyPath, -1, NULL, 0);
1967 ProfileInfoW.lpPolicyPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1968 if (!ProfileInfoW.lpPolicyPath)
1969 {
1970 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1971 goto cleanup;
1972 }
1973 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpPolicyPath, -1, ProfileInfoW.lpPolicyPath, len);
1974 }
1975
1976 /* ... and call the UNICODE function */
1977 bResult = LoadUserProfileW(hToken, &ProfileInfoW);
1978
1979 /* Save the returned value */
1980 lpProfileInfo->hProfile = ProfileInfoW.hProfile;
1981
1982 cleanup:
1983 /* Memory cleanup */
1984 if (ProfileInfoW.lpUserName)
1985 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpUserName);
1986
1987 if (ProfileInfoW.lpProfilePath)
1988 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpProfilePath);
1989
1990 if (ProfileInfoW.lpDefaultPath)
1991 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpDefaultPath);
1992
1993 if (ProfileInfoW.lpServerName)
1994 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpServerName);
1995
1996 if ((ProfileInfoW.dwFlags & PI_APPLYPOLICY) != 0 && ProfileInfoW.lpPolicyPath)
1997 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpPolicyPath);
1998
1999 return bResult;
2000 }
2001
2002
2003 BOOL
2004 WINAPI
2005 LoadUserProfileW(
2006 _In_ HANDLE hToken,
2007 _Inout_ LPPROFILEINFOW lpProfileInfo)
2008 {
2009 WCHAR szUserHivePath[MAX_PATH];
2010 PTOKEN_USER UserSid = NULL;
2011 UNICODE_STRING SidString = { 0, 0, NULL };
2012 HANDLE hProfileMutex = NULL;
2013 LONG Error;
2014 BOOL ret = FALSE;
2015 DWORD dwLength = sizeof(szUserHivePath) / sizeof(szUserHivePath[0]);
2016
2017 DPRINT("LoadUserProfileW(%p %p)\n", hToken, lpProfileInfo);
2018
2019 /* Check profile info */
2020 if (!lpProfileInfo || (lpProfileInfo->dwSize != sizeof(PROFILEINFOW)) ||
2021 (lpProfileInfo->lpUserName == NULL) || (lpProfileInfo->lpUserName[0] == 0))
2022 {
2023 SetLastError(ERROR_INVALID_PARAMETER);
2024 return FALSE;
2025 }
2026
2027 DPRINT("UserName: %S\n", lpProfileInfo->lpUserName);
2028
2029 /* Get the user SID string */
2030 ret = GetUserSidStringFromToken(hToken, &SidString);
2031 if (!ret)
2032 {
2033 DPRINT1("GetUserSidStringFromToken() failed\n");
2034 goto cleanup;
2035 }
2036 ret = FALSE;
2037
2038 /* Create the profile mutex */
2039 hProfileMutex = CreateProfileMutex(SidString.Buffer);
2040 if (hProfileMutex == NULL)
2041 {
2042 DPRINT1("Failed to create the profile mutex\n");
2043 goto cleanup;
2044 }
2045
2046 /* Wait for the profile mutex */
2047 WaitForSingleObject(hProfileMutex, INFINITE);
2048
2049 /* Don't load a profile twice */
2050 if (CheckForLoadedProfile(hToken))
2051 {
2052 DPRINT1("Profile %S already loaded\n", SidString.Buffer);
2053 }
2054 else
2055 {
2056 DPRINT1("Loading profile %S\n", SidString.Buffer);
2057
2058 if (lpProfileInfo->lpProfilePath)
2059 {
2060 /* Use the caller's specified roaming user profile path */
2061 StringCbCopyW(szUserHivePath, sizeof(szUserHivePath), lpProfileInfo->lpProfilePath);
2062 }
2063 else
2064 {
2065 /* FIXME: check if MS Windows allows lpProfileInfo->lpProfilePath to be NULL */
2066 if (!GetProfilesDirectoryW(szUserHivePath, &dwLength))
2067 {
2068 DPRINT1("GetProfilesDirectoryW() failed (error %ld)\n", GetLastError());
2069 goto cleanup;
2070 }
2071 }
2072
2073 /* Create user hive name */
2074 StringCbCatW(szUserHivePath, sizeof(szUserHivePath), L"\\");
2075 StringCbCatW(szUserHivePath, sizeof(szUserHivePath), lpProfileInfo->lpUserName);
2076 StringCbCatW(szUserHivePath, sizeof(szUserHivePath), L"\\ntuser.dat");
2077 DPRINT("szUserHivePath: %S\n", szUserHivePath);
2078
2079 /* Create user profile directory if needed */
2080 if (GetFileAttributesW(szUserHivePath) == INVALID_FILE_ATTRIBUTES)
2081 {
2082 /* Get user sid */
2083 if (GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength) ||
2084 GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2085 {
2086 DPRINT1 ("GetTokenInformation() failed\n");
2087 goto cleanup;
2088 }
2089
2090 UserSid = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), 0, dwLength);
2091 if (!UserSid)
2092 {
2093 DPRINT1("HeapAlloc() failed\n");
2094 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2095 goto cleanup;
2096 }
2097
2098 if (!GetTokenInformation(hToken, TokenUser, UserSid, dwLength, &dwLength))
2099 {
2100 DPRINT1("GetTokenInformation() failed\n");
2101 goto cleanup;
2102 }
2103
2104 /* Create profile */
2105 ret = CreateUserProfileW(UserSid->User.Sid, lpProfileInfo->lpUserName);
2106 if (!ret)
2107 {
2108 DPRINT1("CreateUserProfileW() failed\n");
2109 goto cleanup;
2110 }
2111 }
2112
2113 /* Acquire restore privilege */
2114 if (!AcquireRemoveRestorePrivilege(TRUE))
2115 {
2116 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
2117 goto cleanup;
2118 }
2119
2120 /* Load user registry hive */
2121 Error = RegLoadKeyW(HKEY_USERS,
2122 SidString.Buffer,
2123 szUserHivePath);
2124 AcquireRemoveRestorePrivilege(FALSE);
2125
2126 /* HACK: Do not fail if the profile has already been loaded! */
2127 if (Error == ERROR_SHARING_VIOLATION)
2128 Error = ERROR_SUCCESS;
2129
2130 if (Error != ERROR_SUCCESS)
2131 {
2132 DPRINT1("RegLoadKeyW() failed (Error %ld)\n", Error);
2133 SetLastError((DWORD)Error);
2134 goto cleanup;
2135 }
2136
2137 SetProfileData(SidString.Buffer,
2138 lpProfileInfo->dwFlags,
2139 hToken);
2140 }
2141
2142 /* Open future HKEY_CURRENT_USER */
2143 Error = RegOpenKeyExW(HKEY_USERS,
2144 SidString.Buffer,
2145 0,
2146 MAXIMUM_ALLOWED,
2147 (PHKEY)&lpProfileInfo->hProfile);
2148 if (Error != ERROR_SUCCESS)
2149 {
2150 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error);
2151 SetLastError((DWORD)Error);
2152 goto cleanup;
2153 }
2154
2155 Error = IncrementRefCount(SidString.Buffer, NULL);
2156 if (Error != ERROR_SUCCESS)
2157 {
2158 DPRINT1("IncrementRefCount() failed (Error %ld)\n", Error);
2159 SetLastError((DWORD)Error);
2160 goto cleanup;
2161 }
2162
2163 ret = TRUE;
2164
2165 cleanup:
2166 if (UserSid != NULL)
2167 HeapFree(GetProcessHeap(), 0, UserSid);
2168
2169 if (hProfileMutex != NULL)
2170 {
2171 ReleaseMutex(hProfileMutex);
2172 CloseHandle(hProfileMutex);
2173 }
2174
2175 RtlFreeUnicodeString(&SidString);
2176
2177 DPRINT("LoadUserProfileW() done\n");
2178 return ret;
2179 }
2180
2181
2182 BOOL
2183 WINAPI
2184 UnloadUserProfile(
2185 _In_ HANDLE hToken,
2186 _In_ HANDLE hProfile)
2187 {
2188 UNICODE_STRING SidString = {0, 0, NULL};
2189 HANDLE hProfileMutex = NULL;
2190 HKEY hProfilesKey = NULL, hProfileKey = NULL;
2191 DWORD dwRefCount = 0, dwLength, dwType, dwState = 0;
2192 DWORD dwError;
2193 BOOL bRet = FALSE;
2194
2195 DPRINT("UnloadUserProfile() called\n");
2196
2197 if (hProfile == NULL)
2198 {
2199 DPRINT1("Invalid profile handle\n");
2200 SetLastError(ERROR_INVALID_PARAMETER);
2201 return FALSE;
2202 }
2203
2204 /* Get the user SID string */
2205 if (!GetUserSidStringFromToken(hToken, &SidString))
2206 {
2207 DPRINT1("GetUserSidStringFromToken() failed\n");
2208 return FALSE;
2209 }
2210
2211 DPRINT("SidString: '%wZ'\n", &SidString);
2212
2213 /* Create the profile mutex */
2214 hProfileMutex = CreateProfileMutex(SidString.Buffer);
2215 if (hProfileMutex == NULL)
2216 {
2217 DPRINT1("Failed to create the profile mutex\n");
2218 goto cleanup;
2219 }
2220
2221 /* Wait for the profile mutex */
2222 WaitForSingleObject(hProfileMutex, INFINITE);
2223
2224 /* Close the profile handle */
2225 RegFlushKey(hProfile);
2226 RegCloseKey(hProfile);
2227
2228 dwError = DecrementRefCount(SidString.Buffer, &dwRefCount);
2229 if (dwError != ERROR_SUCCESS)
2230 {
2231 DPRINT1("DecrementRefCount() failed (Error %lu)\n", dwError);
2232 SetLastError(dwError);
2233 goto cleanup;
2234 }
2235
2236 if (dwRefCount == 0)
2237 {
2238 DPRINT("RefCount is 0: Unload the Hive!\n");
2239
2240 /* Acquire restore privilege */
2241 if (!AcquireRemoveRestorePrivilege(TRUE))
2242 {
2243 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %lu)\n", GetLastError());
2244 goto cleanup;
2245 }
2246
2247 /* HACK */
2248 {
2249 HKEY hUserKey;
2250
2251 dwError = RegOpenKeyExW(HKEY_USERS,
2252 SidString.Buffer,
2253 0,
2254 KEY_WRITE,
2255 &hUserKey);
2256 if (dwError == ERROR_SUCCESS)
2257 {
2258 RegDeleteKeyW(hUserKey,
2259 L"Volatile Environment");
2260
2261 RegCloseKey(hUserKey);
2262 }
2263 }
2264 /* End of HACK */
2265
2266 /* Unload the hive */
2267 dwError = RegUnLoadKeyW(HKEY_USERS,
2268 SidString.Buffer);
2269
2270 /* Remove restore privilege */
2271 AcquireRemoveRestorePrivilege(FALSE);
2272
2273 if (dwError != ERROR_SUCCESS)
2274 {
2275 DPRINT1("RegUnLoadKeyW() failed (Error %lu)\n", dwError);
2276 SetLastError(dwError);
2277 goto cleanup;
2278 }
2279
2280 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2281 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
2282 0,
2283 KEY_QUERY_VALUE,
2284 &hProfilesKey);
2285 if (dwError != ERROR_SUCCESS)
2286 {
2287 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError);
2288 SetLastError(dwError);
2289 goto cleanup;
2290 }
2291
2292 dwError = RegOpenKeyExW(hProfilesKey,
2293 SidString.Buffer,
2294 0,
2295 KEY_QUERY_VALUE,
2296 &hProfileKey);
2297 if (dwError != ERROR_SUCCESS)
2298 {
2299 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError);
2300 SetLastError(dwError);
2301 goto cleanup;
2302 }
2303
2304 /* Get the State value */
2305 dwLength = sizeof(dwState);
2306 dwError = RegQueryValueExW(hProfileKey,
2307 L"State",
2308 NULL,
2309 &dwType,
2310 (PBYTE)&dwState,
2311 &dwLength);
2312 if (dwError != ERROR_SUCCESS)
2313 {
2314 DPRINT1("RegQueryValueExW() failed (Error %lu)\n", dwError);
2315 SetLastError(dwError);
2316 goto cleanup;
2317 }
2318
2319 /* Delete a guest profile */
2320 if (dwState & 0x80) // PROFILE_GUEST_USER
2321 {
2322 if (!DeleteProfileW(SidString.Buffer, NULL, NULL))
2323 {
2324 DPRINT1("DeleteProfile(%S, NULL, NULL) failed (Error %lu)\n",
2325 SidString.Buffer, GetLastError());
2326 goto cleanup;
2327 }
2328 }
2329 }
2330
2331 bRet = TRUE;
2332
2333 cleanup:
2334 if (hProfileKey != NULL)
2335 RegCloseKey(hProfileKey);
2336
2337 if (hProfilesKey != NULL)
2338 RegCloseKey(hProfilesKey);
2339
2340 if (hProfileMutex != NULL)
2341 {
2342 ReleaseMutex(hProfileMutex);
2343 CloseHandle(hProfileMutex);
2344 }
2345
2346 RtlFreeUnicodeString(&SidString);
2347
2348 DPRINT("UnloadUserProfile() done\n");
2349
2350 return bRet;
2351 }
2352
2353 /* EOF */