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 */ 2354