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