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