1 /* 2 * PROJECT: ReactOS System Control Panel Applet 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: dll/cpl/sysdm/userprofile.c 5 * PURPOSE: Computer settings for networking 6 * COPYRIGHT: Copyright Thomas Weidenmueller <w3seek@reactos.org> 7 * Copyright 2006 Ged Murphy <gedmurphy@gmail.com> 8 * 9 */ 10 11 #include "precomp.h" 12 #include <sddl.h> 13 #include <winnls.h> 14 15 #include <debug.h> 16 17 typedef struct _PROFILEDATA 18 { 19 DWORD dwRefCount; 20 DWORD dwState; 21 PWSTR pszFullName; 22 PWSTR pszProfilePath; 23 } PROFILEDATA, *PPROFILEDATA; 24 25 26 static 27 BOOL 28 OnProfileTypeInit( 29 _In_ HWND hwndDlg, 30 _In_ PPROFILEDATA pProfileData) 31 { 32 PWSTR pszRawBuffer = NULL, pszCookedBuffer = NULL; 33 INT nLength; 34 35 nLength = LoadStringW(hApplet, IDS_USERPROFILE_TYPE_TEXT, (PWSTR)&pszRawBuffer, 0); 36 pszRawBuffer = NULL; 37 if (nLength == 0) 38 return FALSE; 39 40 pszRawBuffer = HeapAlloc(GetProcessHeap(), 0, (nLength + 1) * sizeof(WCHAR)); 41 if (pszRawBuffer == NULL) 42 return FALSE; 43 44 LoadStringW(hApplet, IDS_USERPROFILE_TYPE_TEXT, pszRawBuffer, nLength + 1); 45 46 pszCookedBuffer = HeapAlloc(GetProcessHeap(), 0, (nLength + wcslen(pProfileData->pszFullName) + 1) * sizeof(WCHAR)); 47 if (pszCookedBuffer == NULL) 48 goto done; 49 50 swprintf(pszCookedBuffer, pszRawBuffer, pProfileData->pszFullName); 51 52 /* Set the full text */ 53 SetDlgItemText(hwndDlg, IDC_USERPROFILE_TYPE_TEXT, pszCookedBuffer); 54 55 /* FIXME: Right now, we support local user profiles only! */ 56 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_TYPE_ROAMING), FALSE); 57 Button_SetCheck(GetDlgItem(hwndDlg, IDC_USERPROFILE_TYPE_LOCAL), BST_CHECKED); 58 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE); 59 60 done: 61 if (pszCookedBuffer != NULL) 62 HeapFree(GetProcessHeap(), 0, pszCookedBuffer); 63 64 if (pszRawBuffer != NULL) 65 HeapFree(GetProcessHeap(), 0, pszRawBuffer); 66 67 return TRUE; 68 } 69 70 71 static 72 INT_PTR 73 CALLBACK 74 UserProfileTypeDlgProc( 75 _In_ HWND hwndDlg, 76 _In_ UINT uMsg, 77 _In_ WPARAM wParam, 78 _In_ LPARAM lParam) 79 { 80 switch (uMsg) 81 { 82 case WM_INITDIALOG: 83 OnProfileTypeInit(hwndDlg, (PPROFILEDATA)lParam); 84 return TRUE; 85 86 case WM_DESTROY: 87 break; 88 89 case WM_COMMAND: 90 switch (LOWORD(wParam)) 91 { 92 case IDOK: 93 case IDCANCEL: 94 EndDialog(hwndDlg, 95 LOWORD(wParam)); 96 return TRUE; 97 } 98 break; 99 } 100 101 return FALSE; 102 } 103 104 105 static 106 BOOL 107 ChangeUserProfileType( 108 _In_ HWND hwndDlg) 109 { 110 HWND hwndListView; 111 LVITEM Item; 112 INT iSelected; 113 114 DPRINT("ChangeUserProfileType(%p)\n", hwndDlg); 115 116 hwndListView = GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST); 117 if (hwndListView == NULL) 118 return FALSE; 119 120 iSelected = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED); 121 if (iSelected == -1) 122 return FALSE; 123 124 ZeroMemory(&Item, sizeof(LVITEM)); 125 Item.mask = LVIF_PARAM; 126 Item.iItem = iSelected; 127 Item.iSubItem = 0; 128 if (!ListView_GetItem(hwndListView, &Item)) 129 return FALSE; 130 131 if (Item.lParam == 0) 132 return FALSE; 133 134 if (DialogBoxParam(hApplet, 135 MAKEINTRESOURCE(IDD_USERPROFILE_TYPE), 136 hwndDlg, 137 UserProfileTypeDlgProc, 138 (LPARAM)Item.lParam) == IDOK) 139 { 140 /* FIXME: Update the profile list view */ 141 return TRUE; 142 } 143 144 return FALSE; 145 } 146 147 148 static 149 BOOL 150 DeleteUserProfile( 151 _In_ HWND hwndDlg) 152 { 153 WCHAR szTitle[64], szRawText[128], szCookedText[256]; 154 HWND hwndListView; 155 LVITEM Item; 156 INT iSelected; 157 PPROFILEDATA pProfileData; 158 159 DPRINT("DeleteUserProfile()\n"); 160 161 hwndListView = GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST); 162 if (hwndListView == NULL) 163 return FALSE; 164 165 iSelected = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED); 166 if (iSelected == -1) 167 return FALSE; 168 169 ZeroMemory(&Item, sizeof(LVITEM)); 170 Item.mask = LVIF_PARAM; 171 Item.iItem = iSelected; 172 Item.iSubItem = 0; 173 if (!ListView_GetItem(hwndListView, &Item)) 174 return FALSE; 175 176 if (Item.lParam == 0) 177 return FALSE; 178 179 pProfileData = (PPROFILEDATA)Item.lParam; 180 if (pProfileData->dwRefCount != 0) 181 return FALSE; 182 183 LoadStringW(hApplet, IDS_USERPROFILE_CONFIRM_DELETE_TITLE, szTitle, ARRAYSIZE(szTitle)); 184 LoadStringW(hApplet, IDS_USERPROFILE_CONFIRM_DELETE, szRawText, ARRAYSIZE(szRawText)); 185 swprintf(szCookedText, szRawText, pProfileData->pszFullName); 186 187 if (MessageBoxW(hwndDlg, 188 szCookedText, 189 szTitle, 190 MB_ICONQUESTION | MB_YESNO) == IDYES) 191 { 192 /* FIXME: Delete the profile here! */ 193 return TRUE; 194 } 195 196 return FALSE; 197 } 198 199 200 static 201 INT_PTR 202 CALLBACK 203 CopyUserProfileDlgProc( 204 _In_ HWND hwndDlg, 205 _In_ UINT uMsg, 206 _In_ WPARAM wParam, 207 _In_ LPARAM lParam) 208 { 209 switch (uMsg) 210 { 211 case WM_INITDIALOG: 212 return TRUE; 213 214 case WM_DESTROY: 215 break; 216 217 case WM_COMMAND: 218 switch (LOWORD(wParam)) 219 { 220 case IDOK: 221 case IDCANCEL: 222 EndDialog(hwndDlg, 223 LOWORD(wParam)); 224 return TRUE; 225 } 226 break; 227 } 228 229 return FALSE; 230 } 231 232 233 static 234 BOOL 235 CopyUserProfile( 236 _In_ HWND hwndDlg) 237 { 238 HWND hwndListView; 239 LVITEM Item; 240 INT iSelected; 241 242 DPRINT("CopyUserProfile()\n"); 243 244 hwndListView = GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST); 245 if (hwndListView == NULL) 246 return FALSE; 247 248 iSelected = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED); 249 if (iSelected == -1) 250 return FALSE; 251 252 ZeroMemory(&Item, sizeof(LVITEM)); 253 Item.mask = LVIF_PARAM; 254 Item.iItem = iSelected; 255 Item.iSubItem = 0; 256 if (!ListView_GetItem(hwndListView, &Item)) 257 return FALSE; 258 259 if (Item.lParam == 0) 260 return FALSE; 261 262 if (DialogBoxParam(hApplet, 263 MAKEINTRESOURCE(IDD_USERPROFILE_COPY), 264 hwndDlg, 265 CopyUserProfileDlgProc, 266 (LPARAM)Item.lParam) == IDOK) 267 { 268 /* FIXME: Update the profile list view */ 269 return TRUE; 270 } 271 272 return FALSE; 273 } 274 275 276 static VOID 277 SetListViewColumns( 278 _In_ HWND hwndListView) 279 { 280 LV_COLUMN column; 281 RECT rect; 282 TCHAR szStr[32]; 283 284 GetClientRect(hwndListView, &rect); 285 286 SendMessage(hwndListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); 287 288 memset(&column, 0x00, sizeof(column)); 289 column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT; 290 column.fmt = LVCFMT_LEFT; 291 column.cx = (INT)((rect.right - rect.left) * 0.40); 292 column.iSubItem = 0; 293 LoadString(hApplet, IDS_USERPROFILE_NAME, szStr, ARRAYSIZE(szStr)); 294 column.pszText = szStr; 295 (void)ListView_InsertColumn(hwndListView, 0, &column); 296 297 column.fmt = LVCFMT_RIGHT; 298 column.cx = (INT)((rect.right - rect.left) * 0.15); 299 column.iSubItem = 1; 300 LoadString(hApplet, IDS_USERPROFILE_SIZE, szStr, ARRAYSIZE(szStr)); 301 column.pszText = szStr; 302 (void)ListView_InsertColumn(hwndListView, 1, &column); 303 304 column.fmt = LVCFMT_LEFT; 305 column.cx = (INT)((rect.right - rect.left) * 0.15); 306 column.iSubItem = 2; 307 LoadString(hApplet, IDS_USERPROFILE_TYPE, szStr, ARRAYSIZE(szStr)); 308 column.pszText = szStr; 309 (void)ListView_InsertColumn(hwndListView, 2, &column); 310 311 column.fmt = LVCFMT_LEFT; 312 column.cx = (INT)((rect.right - rect.left) * 0.15); 313 column.iSubItem = 3; 314 LoadString(hApplet, IDS_USERPROFILE_STATUS, szStr, ARRAYSIZE(szStr)); 315 column.pszText = szStr; 316 (void)ListView_InsertColumn(hwndListView, 3, &column); 317 318 column.fmt = LVCFMT_LEFT; 319 column.cx = (INT)((rect.right - rect.left) * 0.15) - GetSystemMetrics(SM_CYHSCROLL); 320 column.iSubItem = 4; 321 LoadString(hApplet, IDS_USERPROFILE_MODIFIED, szStr, ARRAYSIZE(szStr)); 322 column.pszText = szStr; 323 (void)ListView_InsertColumn(hwndListView, 4, &column); 324 } 325 326 327 static 328 BOOL 329 GetProfileSize( 330 _In_ PWSTR pszProfilePath, 331 _Inout_ PULONGLONG pullProfileSize) 332 { 333 HANDLE hFile = INVALID_HANDLE_VALUE; 334 WIN32_FIND_DATA FindData; 335 DWORD dwProfilePathLength; 336 ULARGE_INTEGER Size; 337 BOOL bResult = TRUE; 338 339 dwProfilePathLength = wcslen(pszProfilePath); 340 341 wcscat(pszProfilePath, L"\\*.*"); 342 343 hFile = FindFirstFileW(pszProfilePath, &FindData); 344 if (hFile == INVALID_HANDLE_VALUE) 345 { 346 if ((GetLastError() != ERROR_FILE_NOT_FOUND) && 347 (GetLastError() != ERROR_PATH_NOT_FOUND)) 348 bResult = FALSE; 349 350 goto done; 351 } 352 353 do 354 { 355 if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 356 { 357 if ((_wcsicmp(FindData.cFileName, L".") == 0) || 358 (_wcsicmp(FindData.cFileName, L"..") == 0)) 359 continue; 360 361 pszProfilePath[dwProfilePathLength + 1] = UNICODE_NULL; 362 wcscat(pszProfilePath, FindData.cFileName); 363 364 if (!GetProfileSize(pszProfilePath, pullProfileSize)) 365 { 366 bResult = FALSE; 367 goto done; 368 } 369 } 370 else 371 { 372 Size.u.LowPart = FindData.nFileSizeLow; 373 Size.u.HighPart = FindData.nFileSizeHigh; 374 *pullProfileSize += Size.QuadPart; 375 } 376 } 377 while (FindNextFile(hFile, &FindData)); 378 379 done: 380 pszProfilePath[dwProfilePathLength] = UNICODE_NULL; 381 382 if (hFile != INVALID_HANDLE_VALUE) 383 FindClose(hFile); 384 385 return bResult; 386 } 387 388 389 static 390 BOOL 391 GetProfileName( 392 _In_ PSID pProfileSid, 393 _In_ DWORD dwNameBufferSize, 394 _Out_ PWSTR pszNameBuffer) 395 { 396 WCHAR szAccountName[128], szDomainName[128]; 397 DWORD dwAccountNameSize, dwDomainNameSize; 398 SID_NAME_USE Use; 399 400 dwAccountNameSize = ARRAYSIZE(szAccountName); 401 dwDomainNameSize = ARRAYSIZE(szDomainName); 402 if (!LookupAccountSidW(NULL, 403 pProfileSid, 404 szAccountName, 405 &dwAccountNameSize, 406 szDomainName, 407 &dwDomainNameSize, 408 &Use)) 409 { 410 /* Unknown account */ 411 LoadStringW(hApplet, IDS_USERPROFILE_ACCOUNT_UNKNOWN, pszNameBuffer, dwNameBufferSize); 412 } 413 else 414 { 415 /* Show only the user accounts */ 416 if (Use != SidTypeUser) 417 return FALSE; 418 419 if (szAccountName[0] == UNICODE_NULL) 420 { 421 /* Deleted account */ 422 LoadStringW(hApplet, IDS_USERPROFILE_ACCOUNT_DELETED, pszNameBuffer, dwNameBufferSize); 423 } 424 else 425 { 426 /* Normal account */ 427 wsprintf(pszNameBuffer, L"%s\\%s", szDomainName, szAccountName); 428 } 429 } 430 431 return TRUE; 432 } 433 434 435 static 436 VOID 437 FormatProfileSize( 438 _Out_ LPWSTR Buffer, 439 _In_ double size) 440 { 441 const LPWSTR units[] = {L"MB", L"GB", L"TB"}; 442 int i = 0, j; 443 444 size /= 1024; 445 size /= 1024; 446 447 while (size >= 1024 && i < 3) 448 { 449 size /= 1024; 450 i++; 451 } 452 453 if (size < 10) 454 j = 2; 455 else if (size < 100) 456 j = 1; 457 else 458 j = 0; 459 460 swprintf(Buffer, L"%.*f %s", j, size, units[i]); 461 } 462 463 464 static VOID 465 AddUserProfile( 466 _In_ HWND hwndListView, 467 _In_ PSID pProfileSid, 468 _In_ HKEY hProfileKey) 469 { 470 WCHAR szTempProfilePath[MAX_PATH], szProfilePath[MAX_PATH]; 471 WCHAR szNameBuffer[256]; 472 PPROFILEDATA pProfileData = NULL; 473 DWORD dwProfileData, dwSize, dwType, dwState = 0, dwRefCount = 0; 474 DWORD dwProfilePathLength; 475 PWSTR ptr; 476 INT nId, iItem; 477 LV_ITEM lvi; 478 WIN32_FIND_DATA FindData; 479 HANDLE hFile; 480 SYSTEMTIME SystemTime; 481 ULONGLONG ullProfileSize; 482 DWORD dwError; 483 484 /* Get the profile path */ 485 dwSize = MAX_PATH * sizeof(WCHAR); 486 dwError = RegQueryValueExW(hProfileKey, 487 L"ProfileImagePath", 488 NULL, 489 &dwType, 490 (LPBYTE)szTempProfilePath, 491 &dwSize); 492 if (dwError != ERROR_SUCCESS) 493 return; 494 495 /* Expand it */ 496 ExpandEnvironmentStringsW(szTempProfilePath, 497 szProfilePath, 498 MAX_PATH); 499 500 /* Check if the profile path exists */ 501 hFile = FindFirstFileW(szProfilePath, &FindData); 502 if (hFile == INVALID_HANDLE_VALUE) 503 return; 504 505 FindClose(hFile); 506 507 /* Get the length of the profile path */ 508 dwProfilePathLength = wcslen(szProfilePath); 509 510 /* Check for the ntuser.dat file */ 511 wcscat(szProfilePath, L"\\ntuser.dat"); 512 hFile = FindFirstFileW(szProfilePath, &FindData); 513 if (hFile == INVALID_HANDLE_VALUE) 514 return; 515 516 FindClose(hFile); 517 szProfilePath[dwProfilePathLength] = UNICODE_NULL; 518 519 /* Get the profile size */ 520 ullProfileSize = 0ULL; 521 GetProfileSize(szProfilePath, &ullProfileSize); 522 523 /* Get the profile name */ 524 if (!GetProfileName(pProfileSid, ARRAYSIZE(szNameBuffer), szNameBuffer)) 525 return; 526 527 /* Get the profile state value */ 528 dwSize = sizeof(dwState); 529 if (RegQueryValueExW(hProfileKey, 530 L"State", 531 NULL, 532 &dwType, 533 (LPBYTE)&dwState, 534 &dwSize) != ERROR_SUCCESS) 535 { 536 dwState = 0; 537 } 538 539 /* Get the profile reference counter */ 540 dwSize = sizeof(dwRefCount); 541 if (RegQueryValueExW(hProfileKey, 542 L"RefCount", 543 NULL, 544 &dwType, 545 (LPBYTE)&dwRefCount, 546 &dwSize) != ERROR_SUCCESS) 547 { 548 dwRefCount = 0; 549 } 550 551 /* Create and fill the profile data entry */ 552 dwProfileData = sizeof(PROFILEDATA) + 553 ((wcslen(szNameBuffer) + 1) * sizeof(WCHAR)) + 554 ((wcslen(szProfilePath) + 1) * sizeof(WCHAR)); 555 pProfileData = HeapAlloc(GetProcessHeap(), 556 HEAP_ZERO_MEMORY, 557 dwProfileData); 558 if (pProfileData == NULL) 559 return; 560 561 pProfileData->dwRefCount = dwRefCount; 562 pProfileData->dwState = dwState; 563 564 ptr = (PWSTR)((ULONG_PTR)pProfileData + sizeof(PROFILEDATA)); 565 pProfileData->pszFullName = ptr; 566 567 wcscpy(pProfileData->pszFullName, szNameBuffer); 568 569 ptr = (PWSTR)((ULONG_PTR)ptr + ((wcslen(pProfileData->pszFullName) + 1) * sizeof(WCHAR))); 570 pProfileData->pszProfilePath = ptr; 571 wcscpy(pProfileData->pszProfilePath, szProfilePath); 572 573 /* Add the profile and set its name */ 574 memset(&lvi, 0x00, sizeof(lvi)); 575 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM; 576 lvi.pszText = pProfileData->pszFullName; 577 lvi.state = 0; 578 lvi.lParam = (LPARAM)pProfileData; 579 iItem = ListView_InsertItem(hwndListView, &lvi); 580 581 /* Set the profile size */ 582 FormatProfileSize(szNameBuffer, (double)ullProfileSize); 583 ListView_SetItemText(hwndListView, iItem, 1, szNameBuffer); 584 585 /* Set the profile type */ 586 if (dwState & 0x0010) // PROFILE_UPDATE_CENTRAL 587 nId = IDS_USERPROFILE_ROAMING; 588 else 589 nId = IDS_USERPROFILE_LOCAL; 590 591 LoadStringW(hApplet, nId, szNameBuffer, ARRAYSIZE(szNameBuffer)); 592 593 ListView_SetItemText(hwndListView, iItem, 2, szNameBuffer); 594 595 /* FIXME: Set the profile status */ 596 if (dwState & 0x0001) // PROFILE_MANDATORY 597 nId = IDS_USERPROFILE_MANDATORY; 598 else if (dwState & 0x0010) // PROFILE_UPDATE_CENTRAL 599 nId = IDS_USERPROFILE_ROAMING; 600 else 601 nId = IDS_USERPROFILE_LOCAL; 602 603 LoadStringW(hApplet, nId, szNameBuffer, ARRAYSIZE(szNameBuffer)); 604 605 ListView_SetItemText(hwndListView, iItem, 3, szNameBuffer); 606 607 /* Set the profile modified time */ 608 FileTimeToSystemTime(&FindData.ftLastWriteTime, 609 &SystemTime); 610 611 GetDateFormatW(LOCALE_USER_DEFAULT, 612 DATE_SHORTDATE, 613 &SystemTime, 614 NULL, 615 szNameBuffer, 616 ARRAYSIZE(szNameBuffer)); 617 618 ListView_SetItemText(hwndListView, iItem, 4, szNameBuffer); 619 } 620 621 622 static VOID 623 UpdateButtonState( 624 _In_ HWND hwndDlg, 625 _In_ HWND hwndListView) 626 { 627 LVITEM Item; 628 INT iSelected; 629 BOOL bChange = FALSE; 630 BOOL bCopy = FALSE; 631 BOOL bDelete = FALSE; 632 633 iSelected = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED); 634 if (iSelected != -1) 635 { 636 Item.mask = LVIF_PARAM; 637 Item.iItem = iSelected; 638 Item.iSubItem = 0; 639 if (ListView_GetItem(hwndListView, &Item)) 640 { 641 if (Item.lParam != 0) 642 { 643 bCopy = (((PPROFILEDATA)Item.lParam)->dwRefCount == 0); 644 bDelete = (((PPROFILEDATA)Item.lParam)->dwRefCount == 0); 645 } 646 } 647 648 bChange = TRUE; 649 } 650 else 651 { 652 bChange = FALSE; 653 bCopy = FALSE; 654 bDelete = FALSE; 655 } 656 657 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_CHANGE), bChange); 658 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), bDelete); 659 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), bCopy); 660 } 661 662 663 static VOID 664 AddUserProfiles( 665 _In_ HWND hwndDlg, 666 _In_ HWND hwndListView, 667 _In_ BOOL bAdmin) 668 { 669 HKEY hKeyUserProfiles = INVALID_HANDLE_VALUE; 670 HKEY hProfileKey; 671 DWORD dwIndex; 672 WCHAR szProfileSid[64]; 673 DWORD dwSidLength; 674 FILETIME ftLastWrite; 675 DWORD dwSize; 676 HANDLE hToken = NULL; 677 PTOKEN_USER pTokenUser = NULL; 678 PSID pProfileSid; 679 PWSTR pszProfileSid; 680 681 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) 682 return; 683 684 GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize); 685 if (dwSize == 0) 686 goto done; 687 688 pTokenUser = HeapAlloc(GetProcessHeap(), 0, dwSize); 689 if (pTokenUser == NULL) 690 goto done; 691 692 if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize)) 693 goto done; 694 695 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 696 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList", 697 0, 698 KEY_READ, 699 &hKeyUserProfiles)) 700 goto done; 701 702 if (bAdmin) 703 { 704 for (dwIndex = 0; ; dwIndex++) 705 { 706 dwSidLength = ARRAYSIZE(szProfileSid); 707 if (RegEnumKeyExW(hKeyUserProfiles, 708 dwIndex, 709 szProfileSid, 710 &dwSidLength, 711 NULL, 712 NULL, 713 NULL, 714 &ftLastWrite)) 715 break; 716 717 if (RegOpenKeyExW(hKeyUserProfiles, 718 szProfileSid, 719 0, 720 KEY_READ, 721 &hProfileKey) == ERROR_SUCCESS) 722 { 723 if (ConvertStringSidToSid(szProfileSid, &pProfileSid)) 724 { 725 AddUserProfile(hwndListView, 726 pProfileSid, 727 hProfileKey); 728 LocalFree(pProfileSid); 729 } 730 731 RegCloseKey(hProfileKey); 732 } 733 } 734 } 735 else 736 { 737 if (ConvertSidToStringSidW(pTokenUser->User.Sid, &pszProfileSid)) 738 { 739 if (RegOpenKeyExW(hKeyUserProfiles, 740 pszProfileSid, 741 0, 742 KEY_READ, 743 &hProfileKey) == ERROR_SUCCESS) 744 { 745 AddUserProfile(hwndListView, 746 pTokenUser->User.Sid, 747 hProfileKey); 748 RegCloseKey(hProfileKey); 749 } 750 751 LocalFree(pszProfileSid); 752 } 753 } 754 755 if (ListView_GetItemCount(hwndListView) != 0) 756 ListView_SetItemState(hwndListView, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); 757 758 UpdateButtonState(hwndDlg, hwndListView); 759 760 done: 761 if (hKeyUserProfiles != INVALID_HANDLE_VALUE) 762 RegCloseKey(hKeyUserProfiles); 763 764 if (pTokenUser != NULL) 765 HeapFree(GetProcessHeap(), 0, pTokenUser); 766 767 if (hToken != NULL) 768 CloseHandle(hToken); 769 } 770 771 772 static VOID 773 OnInitUserProfileDialog(HWND hwndDlg) 774 { 775 BOOL bAdmin; 776 777 bAdmin = IsUserAdmin(); 778 779 /* Initialize the list view control */ 780 SetListViewColumns(GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST)); 781 782 /* Hide the delete and copy buttons for non-admins */ 783 ShowWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), bAdmin ? SW_SHOW : SW_HIDE); 784 ShowWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), bAdmin ? SW_SHOW : SW_HIDE); 785 786 /* Add the profiles to the list view */ 787 AddUserProfiles(hwndDlg, GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST), bAdmin); 788 } 789 790 791 static 792 VOID 793 OnDestroy( 794 _In_ HWND hwndDlg) 795 { 796 HWND hwndList; 797 INT nItems, i; 798 LVITEM Item; 799 800 hwndList = GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST); 801 802 nItems = ListView_GetItemCount(hwndList); 803 for (i = 0; i < nItems; i++) 804 { 805 Item.iItem = i; 806 Item.iSubItem = 0; 807 if (ListView_GetItem(hwndList, &Item)) 808 { 809 if (Item.lParam != 0) 810 HeapFree(GetProcessHeap(), 0, (PVOID)Item.lParam); 811 } 812 } 813 } 814 815 816 static 817 VOID 818 OnNotify( 819 _In_ HWND hwndDlg, 820 _In_ NMHDR *nmhdr) 821 { 822 if (nmhdr->idFrom == IDC_USERACCOUNT_LINK && nmhdr->code == NM_CLICK) 823 { 824 ShellExecuteW(hwndDlg, NULL, L"usrmgr.cpl", NULL, NULL, 0); 825 } 826 else if (nmhdr->idFrom == IDC_USERPROFILE_LIST && nmhdr->code == LVN_ITEMCHANGED) 827 { 828 UpdateButtonState(hwndDlg, nmhdr->hwndFrom); 829 } 830 } 831 832 833 /* Property page dialog callback */ 834 INT_PTR CALLBACK 835 UserProfileDlgProc(HWND hwndDlg, 836 UINT uMsg, 837 WPARAM wParam, 838 LPARAM lParam) 839 { 840 switch (uMsg) 841 { 842 case WM_INITDIALOG: 843 OnInitUserProfileDialog(hwndDlg); 844 return TRUE; 845 846 case WM_DESTROY: 847 OnDestroy(hwndDlg); 848 break; 849 850 case WM_COMMAND: 851 switch (LOWORD(wParam)) 852 { 853 case IDOK: 854 case IDCANCEL: 855 EndDialog(hwndDlg, 856 LOWORD(wParam)); 857 return TRUE; 858 859 case IDC_USERPROFILE_CHANGE: 860 ChangeUserProfileType(hwndDlg); 861 break; 862 863 case IDC_USERPROFILE_DELETE: 864 DeleteUserProfile(hwndDlg); 865 break; 866 867 case IDC_USERPROFILE_COPY: 868 CopyUserProfile(hwndDlg); 869 break; 870 } 871 break; 872 873 case WM_NOTIFY: 874 OnNotify(hwndDlg, (NMHDR *)lParam); 875 break; 876 } 877 878 return FALSE; 879 } 880