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