[SYSDM] Improvements to the user profile page
[reactos.git] / dll / cpl / sysdm / userprofile.c
index 203505c..e0868a8 100644 (file)
@@ -14,6 +14,7 @@
 
 typedef struct _PROFILEDATA
 {
+    BOOL bMyProfile;
     PWSTR pszFullName;
 } PROFILEDATA, *PPROFILEDATA;
 
@@ -34,43 +35,45 @@ SetListViewColumns(HWND hwndListView)
     column.fmt = LVCFMT_LEFT;
     column.cx = (INT)((rect.right - rect.left) * 0.40);
     column.iSubItem = 0;
-    LoadString(hApplet, IDS_USERPROFILE_NAME, szStr, 32);
+    LoadString(hApplet, IDS_USERPROFILE_NAME, szStr, ARRAYSIZE(szStr));
     column.pszText = szStr;
     (void)ListView_InsertColumn(hwndListView, 0, &column);
 
     column.fmt = LVCFMT_RIGHT;
     column.cx = (INT)((rect.right - rect.left) * 0.15);
     column.iSubItem = 1;
-    LoadString(hApplet, IDS_USERPROFILE_SIZE, szStr, 32);
+    LoadString(hApplet, IDS_USERPROFILE_SIZE, szStr, ARRAYSIZE(szStr));
     column.pszText = szStr;
     (void)ListView_InsertColumn(hwndListView, 1, &column);
 
     column.fmt = LVCFMT_LEFT;
     column.cx = (INT)((rect.right - rect.left) * 0.15);
     column.iSubItem = 2;
-    LoadString(hApplet, IDS_USERPROFILE_TYPE, szStr, 32);
+    LoadString(hApplet, IDS_USERPROFILE_TYPE, szStr, ARRAYSIZE(szStr));
     column.pszText = szStr;
     (void)ListView_InsertColumn(hwndListView, 2, &column);
 
     column.fmt = LVCFMT_LEFT;
     column.cx = (INT)((rect.right - rect.left) * 0.15);
     column.iSubItem = 3;
-    LoadString(hApplet, IDS_USERPROFILE_STATUS, szStr, 32);
+    LoadString(hApplet, IDS_USERPROFILE_STATUS, szStr, ARRAYSIZE(szStr));
     column.pszText = szStr;
     (void)ListView_InsertColumn(hwndListView, 3, &column);
 
     column.fmt = LVCFMT_LEFT;
     column.cx = (INT)((rect.right - rect.left) * 0.15) - GetSystemMetrics(SM_CYHSCROLL);
     column.iSubItem = 4;
-    LoadString(hApplet, IDS_USERPROFILE_MODIFIED, szStr, 32);
+    LoadString(hApplet, IDS_USERPROFILE_MODIFIED, szStr, ARRAYSIZE(szStr));
     column.pszText = szStr;
     (void)ListView_InsertColumn(hwndListView, 4, &column);
 }
 
 
 static VOID
-AddUserProfile(HWND hwndListView,
-               LPTSTR lpProfileSid)
+AddUserProfile(
+    _In_ HWND hwndListView,
+    _In_ LPTSTR lpProfileSid,
+    _In_ PSID pMySid)
 {
     PPROFILEDATA pProfileData = NULL;
     PWSTR pszAccountName = NULL;
@@ -129,25 +132,25 @@ AddUserProfile(HWND hwndListView,
     if (pProfileData == NULL)
         goto done;
 
+    pProfileData->bMyProfile = EqualSid(pMySid, pSid);
+
     ptr = (PWSTR)((ULONG_PTR)pProfileData + sizeof(PROFILEDATA));
     pProfileData->pszFullName = ptr;
 
     wsprintf(pProfileData->pszFullName, L"%s\\%s", pszDomainName, pszAccountName);
 
     memset(&lvi, 0x00, sizeof(lvi));
-    lvi.mask = LVIF_TEXT | LVIF_STATE;
+    lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
     lvi.pszText = pProfileData->pszFullName;
     lvi.state = 0;
+    lvi.lParam = (LPARAM)pProfileData;
     ListView_InsertItem(hwndListView, &lvi);
 
 done:
-    if (pProfileData == NULL)
-        HeapFree(GetProcessHeap(), 0, pProfileData);
-
-    if (pszDomainName == NULL)
+    if (pszDomainName != NULL)
         HeapFree(GetProcessHeap(), 0, pszDomainName);
 
-    if (pszAccountName == NULL)
+    if (pszAccountName != NULL)
         HeapFree(GetProcessHeap(), 0, pszAccountName);
 
     if (pSid != NULL)
@@ -158,36 +161,64 @@ done:
 static VOID
 AddUserProfiles(HWND hwndListView)
 {
-    HKEY hKeyUserProfiles;
+    HKEY hKeyUserProfiles = INVALID_HANDLE_VALUE;
     DWORD dwIndex;
-    TCHAR szProfileSid[64];
+    WCHAR szProfileSid[64];
     DWORD dwSidLength;
     FILETIME ftLastWrite;
+    DWORD dwSize;
+    HANDLE hToken = NULL;
+    PTOKEN_USER pTokenUser = NULL;
 
-    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                     _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"),
-                     0,
-                     KEY_READ,
-                     &hKeyUserProfiles))
+    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
         return;
 
+    GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
+    if (dwSize == 0)
+        goto done;
+
+    pTokenUser = HeapAlloc(GetProcessHeap(), 0, dwSize);
+    if (pTokenUser == NULL)
+        goto done;
+
+    if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize))
+        goto done;
+
+    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                      L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
+                      0,
+                      KEY_READ,
+                      &hKeyUserProfiles))
+        goto done;
+
     for (dwIndex = 0; ; dwIndex++)
     {
-        dwSidLength = 64;
-        if (RegEnumKeyEx(hKeyUserProfiles,
-                         dwIndex,
-                         szProfileSid,
-                         &dwSidLength,
-                         NULL,
-                         NULL,
-                         NULL,
-                         &ftLastWrite))
+        dwSidLength = ARRAYSIZE(szProfileSid);
+        if (RegEnumKeyExW(hKeyUserProfiles,
+                          dwIndex,
+                          szProfileSid,
+                          &dwSidLength,
+                          NULL,
+                          NULL,
+                          NULL,
+                          &ftLastWrite))
             break;
 
-        AddUserProfile(hwndListView, szProfileSid);
+        AddUserProfile(hwndListView, szProfileSid, pTokenUser->User.Sid);
     }
 
-    RegCloseKey(hKeyUserProfiles);
+    if (ListView_GetItemCount(hwndListView) != 0)
+        ListView_SetItemState(hwndListView, 0, LVIS_SELECTED, LVIS_SELECTED);
+
+done:
+    if (hKeyUserProfiles != INVALID_HANDLE_VALUE)
+        RegCloseKey(hKeyUserProfiles);
+
+    if (pTokenUser != NULL)
+        HeapFree(GetProcessHeap(), 0, pTokenUser);
+
+    if (hToken != NULL)
+        CloseHandle(hToken);
 }
 
 
@@ -208,6 +239,80 @@ OnInitUserProfileDialog(HWND hwndDlg)
 }
 
 
+static
+VOID
+OnDestroy(
+    _In_ HWND hwndDlg)
+{
+    HWND hwndList;
+    INT nItems, i;
+    LVITEM Item;
+
+    hwndList = GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST);
+
+    nItems = ListView_GetItemCount(hwndList);
+    for (i = 0; i < nItems; i++)
+    {
+        Item.iItem = i;
+        Item.iSubItem = 0;
+        if (ListView_GetItem(hwndList, &Item))
+        {
+            if (Item.lParam != 0)
+                HeapFree(GetProcessHeap(), 0, (PVOID)Item.lParam);
+        }
+    }
+}
+
+
+static
+VOID
+OnNotify(
+    _In_ HWND hwndDlg,
+    _In_ NMHDR *nmhdr)
+{
+    if (nmhdr->idFrom == IDC_USERACCOUNT_LINK && nmhdr->code == NM_CLICK)
+    {
+        ShellExecuteW(hwndDlg, NULL, L"usrmgr.cpl", NULL, NULL, 0);
+    }
+    else if (nmhdr->idFrom == IDC_USERPROFILE_LIST && nmhdr->code == LVN_ITEMCHANGED)
+    {
+        if (ListView_GetSelectedCount(nmhdr->hwndFrom) == 0)
+        {
+            EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_CHANGE), FALSE);
+            EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), FALSE);
+            EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), FALSE);
+        }
+        else
+        {
+            LVITEM Item;
+            INT iSelected;
+            BOOL bMyProfile = FALSE;
+
+            iSelected = ListView_GetNextItem(nmhdr->hwndFrom, -1, LVNI_SELECTED);
+            if (iSelected != -1)
+            {
+                Item.iItem = iSelected;
+                Item.iSubItem = 0;
+                if (ListView_GetItem(nmhdr->hwndFrom, &Item))
+                {
+                    if (Item.lParam != 0)
+                    {
+                        bMyProfile = ((PPROFILEDATA)Item.lParam)->bMyProfile;
+                    }
+                }
+            }
+
+            EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_CHANGE), TRUE);
+            if (IsUserAnAdmin() && !bMyProfile)
+            {
+                EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), TRUE);
+                EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), TRUE);
+            }
+        }
+    }
+}
+
+
 /* Property page dialog callback */
 INT_PTR CALLBACK
 UserProfileDlgProc(HWND hwndDlg,
@@ -221,25 +326,27 @@ UserProfileDlgProc(HWND hwndDlg,
             OnInitUserProfileDialog(hwndDlg);
             break;
 
+        case WM_DESTROY:
+            OnDestroy(hwndDlg);
+            break;
+
         case WM_COMMAND:
-            if ((LOWORD(wParam) == IDOK) || (LOWORD(wParam) == IDCANCEL))
+            switch (LOWORD(wParam))
             {
-                EndDialog(hwndDlg,
-                          LOWORD(wParam));
-                return TRUE;
+                case IDOK:
+                case IDCANCEL:
+                    EndDialog(hwndDlg,
+                              LOWORD(wParam));
+                    return TRUE;
+
+                case IDC_USERPROFILE_DELETE:
+                    break;
             }
             break;
 
         case WM_NOTIFY:
-        {
-            NMHDR *nmhdr = (NMHDR *)lParam;
-
-            if (nmhdr->idFrom == IDC_USERACCOUNT_LINK && nmhdr->code == NM_CLICK)
-            {
-                ShellExecuteW(hwndDlg, NULL, L"usrmgr.cpl", NULL, NULL, 0);
-            }
+            OnNotify(hwndDlg, (NMHDR *)lParam);
             break;
-        }
     }
 
     return FALSE;