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 DPRINT1("DeleteProfileW(%S %S %S) not implemented!\n", lpSidString, lpProfilePath, lpComputerName); 1181 return TRUE; //FALSE; 1182 } 1183 1184 1185 BOOL 1186 WINAPI 1187 GetAllUsersProfileDirectoryA( 1188 _Out_opt_ LPSTR lpProfileDir, 1189 _Inout_ LPDWORD lpcchSize) 1190 { 1191 LPWSTR lpBuffer; 1192 BOOL bResult; 1193 1194 if (!lpcchSize) 1195 { 1196 SetLastError(ERROR_INVALID_PARAMETER); 1197 return FALSE; 1198 } 1199 1200 lpBuffer = GlobalAlloc(GMEM_FIXED, 1201 *lpcchSize * sizeof(WCHAR)); 1202 if (lpBuffer == NULL) 1203 return FALSE; 1204 1205 bResult = GetAllUsersProfileDirectoryW(lpBuffer, 1206 lpcchSize); 1207 if (bResult && lpProfileDir) 1208 { 1209 bResult = WideCharToMultiByte(CP_ACP, 1210 0, 1211 lpBuffer, 1212 -1, 1213 lpProfileDir, 1214 *lpcchSize, 1215 NULL, 1216 NULL); 1217 } 1218 1219 GlobalFree(lpBuffer); 1220 1221 return bResult; 1222 } 1223 1224 1225 BOOL 1226 WINAPI 1227 GetAllUsersProfileDirectoryW( 1228 _Out_opt_ LPWSTR lpProfileDir, 1229 _Inout_ LPDWORD lpcchSize) 1230 { 1231 WCHAR szProfilePath[MAX_PATH]; 1232 WCHAR szBuffer[MAX_PATH]; 1233 DWORD dwType, dwLength; 1234 HKEY hKey; 1235 LONG Error; 1236 1237 if (!lpcchSize) 1238 { 1239 SetLastError(ERROR_INVALID_PARAMETER); 1240 return FALSE; 1241 } 1242 1243 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1244 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList", 1245 0, 1246 KEY_QUERY_VALUE, 1247 &hKey); 1248 if (Error != ERROR_SUCCESS) 1249 { 1250 DPRINT1("Error: %lu\n", Error); 1251 SetLastError((DWORD)Error); 1252 return FALSE; 1253 } 1254 1255 /* Get profiles path */ 1256 dwLength = sizeof(szBuffer); 1257 Error = RegQueryValueExW(hKey, 1258 L"ProfilesDirectory", 1259 NULL, 1260 &dwType, 1261 (LPBYTE)szBuffer, 1262 &dwLength); 1263 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ)) 1264 { 1265 DPRINT1("Error: %lu\n", Error); 1266 RegCloseKey(hKey); 1267 SetLastError((DWORD)Error); 1268 return FALSE; 1269 } 1270 1271 /* Expand it */ 1272 if (!ExpandEnvironmentStringsW(szBuffer, 1273 szProfilePath, 1274 ARRAYSIZE(szProfilePath))) 1275 { 1276 DPRINT1("Error: %lu\n", GetLastError()); 1277 RegCloseKey(hKey); 1278 return FALSE; 1279 } 1280 1281 /* Get 'AllUsersProfile' name */ 1282 dwLength = sizeof(szBuffer); 1283 Error = RegQueryValueExW(hKey, 1284 L"AllUsersProfile", 1285 NULL, 1286 &dwType, 1287 (LPBYTE)szBuffer, 1288 &dwLength); 1289 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ)) 1290 { 1291 DPRINT1("Error: %lu\n", Error); 1292 RegCloseKey(hKey); 1293 SetLastError((DWORD)Error); 1294 return FALSE; 1295 } 1296 1297 RegCloseKey(hKey); 1298 1299 StringCbCatW(szProfilePath, sizeof(szProfilePath), L"\\"); 1300 StringCbCatW(szProfilePath, sizeof(szProfilePath), szBuffer); 1301 1302 dwLength = wcslen(szProfilePath) + 1; 1303 if (lpProfileDir && (*lpcchSize >= dwLength)) 1304 { 1305 StringCchCopyW(lpProfileDir, *lpcchSize, szProfilePath); 1306 *lpcchSize = dwLength; 1307 return TRUE; 1308 } 1309 else // if (!lpProfileDir || (*lpcchSize < dwLength)) 1310 { 1311 *lpcchSize = dwLength; 1312 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1313 return FALSE; 1314 } 1315 } 1316 1317 1318 BOOL 1319 WINAPI 1320 GetDefaultUserProfileDirectoryA( 1321 _Out_opt_ LPSTR lpProfileDir, 1322 _Inout_ LPDWORD lpcchSize) 1323 { 1324 LPWSTR lpBuffer; 1325 BOOL bResult; 1326 1327 if (!lpcchSize) 1328 { 1329 SetLastError(ERROR_INVALID_PARAMETER); 1330 return FALSE; 1331 } 1332 1333 lpBuffer = GlobalAlloc(GMEM_FIXED, 1334 *lpcchSize * sizeof(WCHAR)); 1335 if (lpBuffer == NULL) 1336 return FALSE; 1337 1338 bResult = GetDefaultUserProfileDirectoryW(lpBuffer, 1339 lpcchSize); 1340 if (bResult && lpProfileDir) 1341 { 1342 bResult = WideCharToMultiByte(CP_ACP, 1343 0, 1344 lpBuffer, 1345 -1, 1346 lpProfileDir, 1347 *lpcchSize, 1348 NULL, 1349 NULL); 1350 } 1351 1352 GlobalFree(lpBuffer); 1353 1354 return bResult; 1355 } 1356 1357 1358 BOOL 1359 WINAPI 1360 GetDefaultUserProfileDirectoryW( 1361 _Out_opt_ LPWSTR lpProfileDir, 1362 _Inout_ LPDWORD lpcchSize) 1363 { 1364 WCHAR szProfilePath[MAX_PATH]; 1365 WCHAR szBuffer[MAX_PATH]; 1366 DWORD dwType, dwLength; 1367 HKEY hKey; 1368 LONG Error; 1369 1370 if (!lpcchSize) 1371 { 1372 SetLastError(ERROR_INVALID_PARAMETER); 1373 return FALSE; 1374 } 1375 1376 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1377 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList", 1378 0, 1379 KEY_QUERY_VALUE, 1380 &hKey); 1381 if (Error != ERROR_SUCCESS) 1382 { 1383 DPRINT1("Error: %lu\n", Error); 1384 SetLastError((DWORD)Error); 1385 return FALSE; 1386 } 1387 1388 /* Get profiles path */ 1389 dwLength = sizeof(szBuffer); 1390 Error = RegQueryValueExW(hKey, 1391 L"ProfilesDirectory", 1392 NULL, 1393 &dwType, 1394 (LPBYTE)szBuffer, 1395 &dwLength); 1396 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ)) 1397 { 1398 DPRINT1("Error: %lu\n", Error); 1399 RegCloseKey(hKey); 1400 SetLastError((DWORD)Error); 1401 return FALSE; 1402 } 1403 1404 /* Expand it */ 1405 if (!ExpandEnvironmentStringsW(szBuffer, 1406 szProfilePath, 1407 ARRAYSIZE(szProfilePath))) 1408 { 1409 DPRINT1("Error: %lu\n", GetLastError()); 1410 RegCloseKey(hKey); 1411 return FALSE; 1412 } 1413 1414 /* Get 'DefaultUserProfile' name */ 1415 dwLength = sizeof(szBuffer); 1416 Error = RegQueryValueExW(hKey, 1417 L"DefaultUserProfile", 1418 NULL, 1419 &dwType, 1420 (LPBYTE)szBuffer, 1421 &dwLength); 1422 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ)) 1423 { 1424 DPRINT1("Error: %lu\n", Error); 1425 RegCloseKey(hKey); 1426 SetLastError((DWORD)Error); 1427 return FALSE; 1428 } 1429 1430 RegCloseKey(hKey); 1431 1432 StringCbCatW(szProfilePath, sizeof(szProfilePath), L"\\"); 1433 StringCbCatW(szProfilePath, sizeof(szProfilePath), szBuffer); 1434 1435 dwLength = wcslen(szProfilePath) + 1; 1436 if (lpProfileDir && (*lpcchSize >= dwLength)) 1437 { 1438 StringCchCopyW(lpProfileDir, *lpcchSize, szProfilePath); 1439 *lpcchSize = dwLength; 1440 return TRUE; 1441 } 1442 else // if (!lpProfileDir || (*lpcchSize < dwLength)) 1443 { 1444 *lpcchSize = dwLength; 1445 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1446 return FALSE; 1447 } 1448 } 1449 1450 1451 BOOL 1452 WINAPI 1453 GetProfilesDirectoryA( 1454 _Out_ LPSTR lpProfileDir, // _Out_opt_ 1455 _Inout_ LPDWORD lpcchSize) 1456 { 1457 LPWSTR lpBuffer; 1458 BOOL bResult; 1459 1460 if (!lpcchSize || !lpProfileDir) 1461 { 1462 SetLastError(ERROR_INVALID_PARAMETER); 1463 return FALSE; 1464 } 1465 1466 lpBuffer = GlobalAlloc(GMEM_FIXED, 1467 *lpcchSize * sizeof(WCHAR)); 1468 if (lpBuffer == NULL) 1469 return FALSE; 1470 1471 bResult = GetProfilesDirectoryW(lpBuffer, 1472 lpcchSize); 1473 if (bResult && lpProfileDir) 1474 { 1475 bResult = WideCharToMultiByte(CP_ACP, 1476 0, 1477 lpBuffer, 1478 -1, 1479 lpProfileDir, 1480 *lpcchSize, 1481 NULL, 1482 NULL); 1483 } 1484 1485 GlobalFree(lpBuffer); 1486 1487 return bResult; 1488 } 1489 1490 1491 BOOL 1492 WINAPI 1493 GetProfilesDirectoryW( 1494 _Out_ LPWSTR lpProfilesDir, // _Out_opt_ 1495 _Inout_ LPDWORD lpcchSize) 1496 { 1497 WCHAR szProfilesPath[MAX_PATH]; 1498 WCHAR szBuffer[MAX_PATH]; 1499 DWORD dwType, dwLength; 1500 HKEY hKey; 1501 LONG Error; 1502 1503 if (!lpcchSize) 1504 { 1505 SetLastError(ERROR_INVALID_PARAMETER); 1506 return FALSE; 1507 } 1508 1509 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1510 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList", 1511 0, 1512 KEY_QUERY_VALUE, 1513 &hKey); 1514 if (Error != ERROR_SUCCESS) 1515 { 1516 DPRINT1("Error: %lu\n", Error); 1517 SetLastError((DWORD)Error); 1518 return FALSE; 1519 } 1520 1521 /* Get profiles path */ 1522 dwLength = sizeof(szBuffer); 1523 Error = RegQueryValueExW(hKey, 1524 L"ProfilesDirectory", 1525 NULL, 1526 &dwType, 1527 (LPBYTE)szBuffer, 1528 &dwLength); 1529 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ)) 1530 { 1531 DPRINT1("Error: %lu\n", Error); 1532 RegCloseKey(hKey); 1533 SetLastError((DWORD)Error); 1534 return FALSE; 1535 } 1536 1537 RegCloseKey(hKey); 1538 1539 /* Expand it */ 1540 if (!ExpandEnvironmentStringsW(szBuffer, 1541 szProfilesPath, 1542 ARRAYSIZE(szProfilesPath))) 1543 { 1544 DPRINT1("Error: %lu\n", GetLastError()); 1545 return FALSE; 1546 } 1547 1548 dwLength = wcslen(szProfilesPath) + 1; 1549 if (lpProfilesDir && (*lpcchSize >= dwLength)) 1550 { 1551 StringCchCopyW(lpProfilesDir, *lpcchSize, szProfilesPath); 1552 *lpcchSize = dwLength; 1553 return TRUE; 1554 } 1555 else // if (!lpProfilesDir || (*lpcchSize < dwLength)) 1556 { 1557 *lpcchSize = dwLength; 1558 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1559 return FALSE; 1560 } 1561 } 1562 1563 1564 BOOL 1565 WINAPI 1566 GetProfileType( 1567 _Out_ PDWORD pdwFlags) 1568 { 1569 UNICODE_STRING SidString = {0, 0, NULL}; 1570 HANDLE hToken; 1571 HKEY hProfilesKey = NULL, hProfileKey = NULL; 1572 DWORD dwType, dwLength, dwState = 0; 1573 DWORD dwError; 1574 BOOL bResult = FALSE; 1575 1576 DPRINT("GetProfileType(%p)\n", pdwFlags); 1577 1578 if (pdwFlags == NULL) 1579 { 1580 SetLastError(ERROR_INVALID_PARAMETER); 1581 return FALSE; 1582 } 1583 1584 if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken)) 1585 { 1586 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) 1587 { 1588 DPRINT1("Failed to open a token (Error %lu)\n", GetLastError()); 1589 return FALSE; 1590 } 1591 } 1592 1593 /* Get the user SID string */ 1594 if (!GetUserSidStringFromToken(hToken, &SidString)) 1595 { 1596 DPRINT1("GetUserSidStringFromToken() failed\n"); 1597 goto done; 1598 } 1599 1600 DPRINT("SID: %wZ\n", &SidString); 1601 1602 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1603 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList", 1604 0, 1605 KEY_QUERY_VALUE, 1606 &hProfilesKey); 1607 if (dwError != ERROR_SUCCESS) 1608 { 1609 DPRINT1("Error: %lu\n", dwError); 1610 SetLastError(dwError); 1611 goto done; 1612 } 1613 1614 dwError = RegOpenKeyExW(hProfilesKey, 1615 SidString.Buffer, 1616 0, 1617 KEY_QUERY_VALUE | KEY_SET_VALUE, 1618 &hProfileKey); 1619 if (dwError != ERROR_SUCCESS) 1620 { 1621 DPRINT1("Error: %lu\n", dwError); 1622 SetLastError(dwError); 1623 goto done; 1624 } 1625 1626 /* Get the State value */ 1627 dwLength = sizeof(dwState); 1628 dwError = RegQueryValueExW(hProfileKey, 1629 L"State", 1630 NULL, 1631 &dwType, 1632 (PBYTE)&dwState, 1633 &dwLength); 1634 if (dwError != ERROR_SUCCESS) 1635 { 1636 DPRINT1("Error: %lu\n", dwError); 1637 SetLastError(dwError); 1638 goto done; 1639 } 1640 1641 *pdwFlags = 0; 1642 1643 if (dwState & 0x80) /* PROFILE_GUEST_USER */ 1644 *pdwFlags |= PT_TEMPORARY; 1645 1646 /* FIXME: Add checks for PT_MANDATORY and PT_ROAMING */ 1647 1648 bResult = TRUE; 1649 1650 done: 1651 if (hProfileKey != NULL) 1652 RegCloseKey(hProfileKey); 1653 1654 if (hProfilesKey != NULL) 1655 RegCloseKey(hProfilesKey); 1656 1657 RtlFreeUnicodeString(&SidString); 1658 1659 CloseHandle(hToken); 1660 1661 return bResult; 1662 } 1663 1664 1665 BOOL 1666 WINAPI 1667 GetUserProfileDirectoryA( 1668 _In_ HANDLE hToken, 1669 _Out_opt_ LPSTR lpProfileDir, 1670 _Inout_ LPDWORD lpcchSize) 1671 { 1672 LPWSTR lpBuffer; 1673 BOOL bResult; 1674 1675 if (!lpcchSize || !lpProfileDir) 1676 { 1677 SetLastError(ERROR_INVALID_PARAMETER); 1678 return FALSE; 1679 } 1680 1681 lpBuffer = GlobalAlloc(GMEM_FIXED, 1682 *lpcchSize * sizeof(WCHAR)); 1683 if (lpBuffer == NULL) 1684 return FALSE; 1685 1686 bResult = GetUserProfileDirectoryW(hToken, 1687 lpBuffer, 1688 lpcchSize); 1689 if (bResult && lpProfileDir) 1690 { 1691 bResult = WideCharToMultiByte(CP_ACP, 1692 0, 1693 lpBuffer, 1694 -1, 1695 lpProfileDir, 1696 *lpcchSize, 1697 NULL, 1698 NULL); 1699 } 1700 1701 GlobalFree(lpBuffer); 1702 1703 return bResult; 1704 } 1705 1706 1707 BOOL 1708 WINAPI 1709 GetUserProfileDirectoryW( 1710 _In_ HANDLE hToken, 1711 _Out_opt_ LPWSTR lpProfileDir, 1712 _Inout_ LPDWORD lpcchSize) 1713 { 1714 UNICODE_STRING SidString; 1715 WCHAR szKeyName[MAX_PATH]; 1716 WCHAR szRawImagePath[MAX_PATH]; 1717 WCHAR szImagePath[MAX_PATH]; 1718 DWORD dwType, dwLength; 1719 HKEY hKey; 1720 LONG Error; 1721 1722 if (!hToken) 1723 { 1724 SetLastError(ERROR_INVALID_HANDLE); 1725 return FALSE; 1726 } 1727 1728 if (!lpcchSize) 1729 { 1730 SetLastError(ERROR_INVALID_PARAMETER); 1731 return FALSE; 1732 } 1733 1734 /* Get the user SID string */ 1735 if (!GetUserSidStringFromToken(hToken, &SidString)) 1736 { 1737 DPRINT1("GetUserSidStringFromToken() failed\n"); 1738 return FALSE; 1739 } 1740 1741 DPRINT("SidString: '%wZ'\n", &SidString); 1742 1743 StringCbCopyW(szKeyName, sizeof(szKeyName), 1744 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\"); 1745 StringCbCatW(szKeyName, sizeof(szKeyName), SidString.Buffer); 1746 1747 RtlFreeUnicodeString(&SidString); 1748 1749 DPRINT("KeyName: '%S'\n", szKeyName); 1750 1751 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1752 szKeyName, 1753 0, 1754 KEY_QUERY_VALUE, 1755 &hKey); 1756 if (Error != ERROR_SUCCESS) 1757 { 1758 DPRINT1("Error: %lu\n", Error); 1759 SetLastError((DWORD)Error); 1760 return FALSE; 1761 } 1762 1763 dwLength = sizeof(szRawImagePath); 1764 Error = RegQueryValueExW(hKey, 1765 L"ProfileImagePath", 1766 NULL, 1767 &dwType, 1768 (LPBYTE)szRawImagePath, 1769 &dwLength); 1770 if ((Error != ERROR_SUCCESS) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ)) 1771 { 1772 DPRINT1("Error: %lu\n", Error); 1773 RegCloseKey(hKey); 1774 SetLastError((DWORD)Error); 1775 return FALSE; 1776 } 1777 1778 RegCloseKey(hKey); 1779 1780 DPRINT("RawImagePath: '%S'\n", szRawImagePath); 1781 1782 /* Expand it */ 1783 if (!ExpandEnvironmentStringsW(szRawImagePath, 1784 szImagePath, 1785 ARRAYSIZE(szImagePath))) 1786 { 1787 DPRINT1("Error: %lu\n", GetLastError()); 1788 return FALSE; 1789 } 1790 1791 DPRINT("ImagePath: '%S'\n", szImagePath); 1792 1793 dwLength = wcslen(szImagePath) + 1; 1794 if (lpProfileDir && (*lpcchSize >= dwLength)) 1795 { 1796 StringCchCopyW(lpProfileDir, *lpcchSize, szImagePath); 1797 *lpcchSize = dwLength; 1798 return TRUE; 1799 } 1800 else // if (!lpProfileDir || (*lpcchSize < dwLength)) 1801 { 1802 *lpcchSize = dwLength; 1803 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1804 return FALSE; 1805 } 1806 } 1807 1808 1809 BOOL 1810 WINAPI 1811 LoadUserProfileA( 1812 _In_ HANDLE hToken, 1813 _Inout_ LPPROFILEINFOA lpProfileInfo) 1814 { 1815 BOOL bResult = FALSE; 1816 PROFILEINFOW ProfileInfoW = {0}; 1817 int len; 1818 1819 DPRINT("LoadUserProfileA() called\n"); 1820 1821 /* Check profile info */ 1822 if (!lpProfileInfo || (lpProfileInfo->dwSize != sizeof(PROFILEINFOA)) || 1823 (lpProfileInfo->lpUserName == NULL) || (lpProfileInfo->lpUserName[0] == 0)) 1824 { 1825 SetLastError(ERROR_INVALID_PARAMETER); 1826 return FALSE; 1827 } 1828 1829 /* Convert the structure to UNICODE... */ 1830 ProfileInfoW.dwSize = sizeof(ProfileInfoW); 1831 ProfileInfoW.dwFlags = lpProfileInfo->dwFlags; 1832 1833 if (lpProfileInfo->lpUserName) 1834 { 1835 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpUserName, -1, NULL, 0); 1836 ProfileInfoW.lpUserName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 1837 if (!ProfileInfoW.lpUserName) 1838 { 1839 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1840 goto cleanup; 1841 } 1842 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpUserName, -1, ProfileInfoW.lpUserName, len); 1843 } 1844 1845 if (lpProfileInfo->lpProfilePath) 1846 { 1847 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpProfilePath, -1, NULL, 0); 1848 ProfileInfoW.lpProfilePath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 1849 if (!ProfileInfoW.lpProfilePath) 1850 { 1851 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1852 goto cleanup; 1853 } 1854 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpProfilePath, -1, ProfileInfoW.lpProfilePath, len); 1855 } 1856 1857 if (lpProfileInfo->lpDefaultPath) 1858 { 1859 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpDefaultPath, -1, NULL, 0); 1860 ProfileInfoW.lpDefaultPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 1861 if (!ProfileInfoW.lpDefaultPath) 1862 { 1863 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1864 goto cleanup; 1865 } 1866 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpDefaultPath, -1, ProfileInfoW.lpDefaultPath, len); 1867 } 1868 1869 if (lpProfileInfo->lpServerName) 1870 { 1871 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpServerName, -1, NULL, 0); 1872 ProfileInfoW.lpServerName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 1873 if (!ProfileInfoW.lpServerName) 1874 { 1875 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1876 goto cleanup; 1877 } 1878 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpServerName, -1, ProfileInfoW.lpServerName, len); 1879 } 1880 1881 if ((ProfileInfoW.dwFlags & PI_APPLYPOLICY) != 0 && lpProfileInfo->lpPolicyPath) 1882 { 1883 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpPolicyPath, -1, NULL, 0); 1884 ProfileInfoW.lpPolicyPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 1885 if (!ProfileInfoW.lpPolicyPath) 1886 { 1887 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1888 goto cleanup; 1889 } 1890 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpPolicyPath, -1, ProfileInfoW.lpPolicyPath, len); 1891 } 1892 1893 /* ... and call the UNICODE function */ 1894 bResult = LoadUserProfileW(hToken, &ProfileInfoW); 1895 1896 /* Save the returned value */ 1897 lpProfileInfo->hProfile = ProfileInfoW.hProfile; 1898 1899 cleanup: 1900 /* Memory cleanup */ 1901 if (ProfileInfoW.lpUserName) 1902 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpUserName); 1903 1904 if (ProfileInfoW.lpProfilePath) 1905 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpProfilePath); 1906 1907 if (ProfileInfoW.lpDefaultPath) 1908 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpDefaultPath); 1909 1910 if (ProfileInfoW.lpServerName) 1911 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpServerName); 1912 1913 if ((ProfileInfoW.dwFlags & PI_APPLYPOLICY) != 0 && ProfileInfoW.lpPolicyPath) 1914 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpPolicyPath); 1915 1916 return bResult; 1917 } 1918 1919 1920 BOOL 1921 WINAPI 1922 LoadUserProfileW( 1923 _In_ HANDLE hToken, 1924 _Inout_ LPPROFILEINFOW lpProfileInfo) 1925 { 1926 WCHAR szUserHivePath[MAX_PATH]; 1927 PTOKEN_USER UserSid = NULL; 1928 UNICODE_STRING SidString = { 0, 0, NULL }; 1929 HANDLE hProfileMutex = NULL; 1930 LONG Error; 1931 BOOL ret = FALSE; 1932 DWORD dwLength = sizeof(szUserHivePath) / sizeof(szUserHivePath[0]); 1933 1934 DPRINT("LoadUserProfileW(%p %p)\n", hToken, lpProfileInfo); 1935 1936 /* Check profile info */ 1937 if (!lpProfileInfo || (lpProfileInfo->dwSize != sizeof(PROFILEINFOW)) || 1938 (lpProfileInfo->lpUserName == NULL) || (lpProfileInfo->lpUserName[0] == 0)) 1939 { 1940 SetLastError(ERROR_INVALID_PARAMETER); 1941 return FALSE; 1942 } 1943 1944 DPRINT("UserName: %S\n", lpProfileInfo->lpUserName); 1945 1946 /* Get the user SID string */ 1947 ret = GetUserSidStringFromToken(hToken, &SidString); 1948 if (!ret) 1949 { 1950 DPRINT1("GetUserSidStringFromToken() failed\n"); 1951 goto cleanup; 1952 } 1953 ret = FALSE; 1954 1955 /* Create the profile mutex */ 1956 hProfileMutex = CreateProfileMutex(SidString.Buffer); 1957 if (hProfileMutex == NULL) 1958 { 1959 DPRINT1("Failed to create the profile mutex\n"); 1960 goto cleanup; 1961 } 1962 1963 /* Wait for the profile mutex */ 1964 WaitForSingleObject(hProfileMutex, INFINITE); 1965 1966 /* Don't load a profile twice */ 1967 if (CheckForLoadedProfile(hToken)) 1968 { 1969 DPRINT1("Profile %S already loaded\n", SidString.Buffer); 1970 } 1971 else 1972 { 1973 DPRINT1("Loading profile %S\n", SidString.Buffer); 1974 1975 if (lpProfileInfo->lpProfilePath) 1976 { 1977 /* Use the caller's specified roaming user profile path */ 1978 StringCbCopyW(szUserHivePath, sizeof(szUserHivePath), lpProfileInfo->lpProfilePath); 1979 } 1980 else 1981 { 1982 /* FIXME: check if MS Windows allows lpProfileInfo->lpProfilePath to be NULL */ 1983 if (!GetProfilesDirectoryW(szUserHivePath, &dwLength)) 1984 { 1985 DPRINT1("GetProfilesDirectoryW() failed (error %ld)\n", GetLastError()); 1986 goto cleanup; 1987 } 1988 } 1989 1990 /* Create user hive name */ 1991 StringCbCatW(szUserHivePath, sizeof(szUserHivePath), L"\\"); 1992 StringCbCatW(szUserHivePath, sizeof(szUserHivePath), lpProfileInfo->lpUserName); 1993 StringCbCatW(szUserHivePath, sizeof(szUserHivePath), L"\\ntuser.dat"); 1994 DPRINT("szUserHivePath: %S\n", szUserHivePath); 1995 1996 /* Create user profile directory if needed */ 1997 if (GetFileAttributesW(szUserHivePath) == INVALID_FILE_ATTRIBUTES) 1998 { 1999 /* Get user sid */ 2000 if (GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength) || 2001 GetLastError() != ERROR_INSUFFICIENT_BUFFER) 2002 { 2003 DPRINT1 ("GetTokenInformation() failed\n"); 2004 goto cleanup; 2005 } 2006 2007 UserSid = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), 0, dwLength); 2008 if (!UserSid) 2009 { 2010 DPRINT1("HeapAlloc() failed\n"); 2011 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 2012 goto cleanup; 2013 } 2014 2015 if (!GetTokenInformation(hToken, TokenUser, UserSid, dwLength, &dwLength)) 2016 { 2017 DPRINT1("GetTokenInformation() failed\n"); 2018 goto cleanup; 2019 } 2020 2021 /* Create profile */ 2022 ret = CreateUserProfileW(UserSid->User.Sid, lpProfileInfo->lpUserName); 2023 if (!ret) 2024 { 2025 DPRINT1("CreateUserProfileW() failed\n"); 2026 goto cleanup; 2027 } 2028 } 2029 2030 /* Acquire restore privilege */ 2031 if (!AcquireRemoveRestorePrivilege(TRUE)) 2032 { 2033 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError()); 2034 goto cleanup; 2035 } 2036 2037 /* Load user registry hive */ 2038 Error = RegLoadKeyW(HKEY_USERS, 2039 SidString.Buffer, 2040 szUserHivePath); 2041 AcquireRemoveRestorePrivilege(FALSE); 2042 2043 /* HACK: Do not fail if the profile has already been loaded! */ 2044 if (Error == ERROR_SHARING_VIOLATION) 2045 Error = ERROR_SUCCESS; 2046 2047 if (Error != ERROR_SUCCESS) 2048 { 2049 DPRINT1("RegLoadKeyW() failed (Error %ld)\n", Error); 2050 SetLastError((DWORD)Error); 2051 goto cleanup; 2052 } 2053 2054 SetProfileData(SidString.Buffer, 2055 lpProfileInfo->dwFlags, 2056 hToken); 2057 } 2058 2059 /* Open future HKEY_CURRENT_USER */ 2060 Error = RegOpenKeyExW(HKEY_USERS, 2061 SidString.Buffer, 2062 0, 2063 MAXIMUM_ALLOWED, 2064 (PHKEY)&lpProfileInfo->hProfile); 2065 if (Error != ERROR_SUCCESS) 2066 { 2067 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error); 2068 SetLastError((DWORD)Error); 2069 goto cleanup; 2070 } 2071 2072 Error = IncrementRefCount(SidString.Buffer, NULL); 2073 if (Error != ERROR_SUCCESS) 2074 { 2075 DPRINT1("IncrementRefCount() failed (Error %ld)\n", Error); 2076 SetLastError((DWORD)Error); 2077 goto cleanup; 2078 } 2079 2080 ret = TRUE; 2081 2082 cleanup: 2083 if (UserSid != NULL) 2084 HeapFree(GetProcessHeap(), 0, UserSid); 2085 2086 if (hProfileMutex != NULL) 2087 { 2088 ReleaseMutex(hProfileMutex); 2089 CloseHandle(hProfileMutex); 2090 } 2091 2092 RtlFreeUnicodeString(&SidString); 2093 2094 DPRINT("LoadUserProfileW() done\n"); 2095 return ret; 2096 } 2097 2098 2099 BOOL 2100 WINAPI 2101 UnloadUserProfile( 2102 _In_ HANDLE hToken, 2103 _In_ HANDLE hProfile) 2104 { 2105 UNICODE_STRING SidString = {0, 0, NULL}; 2106 HANDLE hProfileMutex = NULL; 2107 HKEY hProfilesKey = NULL, hProfileKey = NULL; 2108 DWORD dwRefCount = 0, dwLength, dwType, dwState = 0; 2109 DWORD dwError; 2110 BOOL bRet = FALSE; 2111 2112 DPRINT("UnloadUserProfile() called\n"); 2113 2114 if (hProfile == NULL) 2115 { 2116 DPRINT1("Invalid profile handle\n"); 2117 SetLastError(ERROR_INVALID_PARAMETER); 2118 return FALSE; 2119 } 2120 2121 /* Get the user SID string */ 2122 if (!GetUserSidStringFromToken(hToken, &SidString)) 2123 { 2124 DPRINT1("GetUserSidStringFromToken() failed\n"); 2125 return FALSE; 2126 } 2127 2128 DPRINT("SidString: '%wZ'\n", &SidString); 2129 2130 /* Create the profile mutex */ 2131 hProfileMutex = CreateProfileMutex(SidString.Buffer); 2132 if (hProfileMutex == NULL) 2133 { 2134 DPRINT1("Failed to create the profile mutex\n"); 2135 goto cleanup; 2136 } 2137 2138 /* Wait for the profile mutex */ 2139 WaitForSingleObject(hProfileMutex, INFINITE); 2140 2141 /* Close the profile handle */ 2142 RegFlushKey(hProfile); 2143 RegCloseKey(hProfile); 2144 2145 dwError = DecrementRefCount(SidString.Buffer, &dwRefCount); 2146 if (dwError != ERROR_SUCCESS) 2147 { 2148 DPRINT1("DecrementRefCount() failed (Error %lu)\n", dwError); 2149 SetLastError(dwError); 2150 goto cleanup; 2151 } 2152 2153 if (dwRefCount == 0) 2154 { 2155 DPRINT("RefCount is 0: Unload the Hive!\n"); 2156 2157 /* Acquire restore privilege */ 2158 if (!AcquireRemoveRestorePrivilege(TRUE)) 2159 { 2160 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %lu)\n", GetLastError()); 2161 goto cleanup; 2162 } 2163 2164 /* HACK */ 2165 { 2166 HKEY hUserKey; 2167 2168 dwError = RegOpenKeyExW(HKEY_USERS, 2169 SidString.Buffer, 2170 0, 2171 KEY_WRITE, 2172 &hUserKey); 2173 if (dwError == ERROR_SUCCESS) 2174 { 2175 RegDeleteKeyW(hUserKey, 2176 L"Volatile Environment"); 2177 2178 RegCloseKey(hUserKey); 2179 } 2180 } 2181 /* End of HACK */ 2182 2183 /* Unload the hive */ 2184 dwError = RegUnLoadKeyW(HKEY_USERS, 2185 SidString.Buffer); 2186 2187 /* Remove restore privilege */ 2188 AcquireRemoveRestorePrivilege(FALSE); 2189 2190 if (dwError != ERROR_SUCCESS) 2191 { 2192 DPRINT1("RegUnLoadKeyW() failed (Error %lu)\n", dwError); 2193 SetLastError(dwError); 2194 goto cleanup; 2195 } 2196 2197 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 2198 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList", 2199 0, 2200 KEY_QUERY_VALUE, 2201 &hProfilesKey); 2202 if (dwError != ERROR_SUCCESS) 2203 { 2204 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError); 2205 SetLastError(dwError); 2206 goto cleanup; 2207 } 2208 2209 dwError = RegOpenKeyExW(hProfilesKey, 2210 SidString.Buffer, 2211 0, 2212 KEY_QUERY_VALUE, 2213 &hProfileKey); 2214 if (dwError != ERROR_SUCCESS) 2215 { 2216 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError); 2217 SetLastError(dwError); 2218 goto cleanup; 2219 } 2220 2221 /* Get the State value */ 2222 dwLength = sizeof(dwState); 2223 dwError = RegQueryValueExW(hProfileKey, 2224 L"State", 2225 NULL, 2226 &dwType, 2227 (PBYTE)&dwState, 2228 &dwLength); 2229 if (dwError != ERROR_SUCCESS) 2230 { 2231 DPRINT1("RegQueryValueExW() failed (Error %lu)\n", dwError); 2232 SetLastError(dwError); 2233 goto cleanup; 2234 } 2235 2236 /* Delete a guest profile */ 2237 if (dwState & 0x80) // PROFILE_GUEST_USER 2238 { 2239 if (!DeleteProfileW(SidString.Buffer, NULL, NULL)) 2240 { 2241 DPRINT1("DeleteProfile(%S, NULL, NULL) failed (Error %lu)\n", 2242 SidString.Buffer, GetLastError()); 2243 goto cleanup; 2244 } 2245 } 2246 } 2247 2248 bRet = TRUE; 2249 2250 cleanup: 2251 if (hProfileKey != NULL) 2252 RegCloseKey(hProfileKey); 2253 2254 if (hProfilesKey != NULL) 2255 RegCloseKey(hProfilesKey); 2256 2257 if (hProfileMutex != NULL) 2258 { 2259 ReleaseMutex(hProfileMutex); 2260 CloseHandle(hProfileMutex); 2261 } 2262 2263 RtlFreeUnicodeString(&SidString); 2264 2265 DPRINT("UnloadUserProfile() done\n"); 2266 2267 return bRet; 2268 } 2269 2270 /* EOF */ 2271