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