[SYSDM] Allow deleting and copying of user profiles only for profiles that are curren...
[reactos.git] / dll / cpl / sysdm / userprofile.c
index b266a97..0c9e1f9 100644 (file)
@@ -16,7 +16,7 @@
 
 typedef struct _PROFILEDATA
 {
-    BOOL bMyProfile;
+    DWORD dwRefCount;
     DWORD dwState;
     PWSTR pszFullName;
 } PROFILEDATA, *PPROFILEDATA;
@@ -176,7 +176,7 @@ DeleteUserProfile(
         return FALSE;
 
     pProfileData = (PPROFILEDATA)Item.lParam;
-    if (pProfileData->bMyProfile)
+    if (pProfileData->dwRefCount != 0)
         return FALSE;
 
     LoadStringW(hApplet, IDS_USERPROFILE_CONFIRM_DELETE_TITLE, szTitle, ARRAYSIZE(szTitle));
@@ -323,6 +323,68 @@ SetListViewColumns(
 }
 
 
+static
+BOOL
+GetProfileSize(
+    PWSTR pszProfilePath,
+    PULONGLONG pullProfileSize)
+{
+    HANDLE hFile = INVALID_HANDLE_VALUE;
+    WIN32_FIND_DATA FindData;
+    DWORD dwProfilePathLength;
+    ULARGE_INTEGER Size;
+    BOOL bResult = TRUE;
+
+    dwProfilePathLength = wcslen(pszProfilePath);
+
+    wcscat(pszProfilePath, L"\\*.*");
+
+    hFile = FindFirstFileW(pszProfilePath, &FindData);
+    if (hFile == INVALID_HANDLE_VALUE)
+    {
+        if ((GetLastError() != ERROR_FILE_NOT_FOUND) &&
+            (GetLastError() != ERROR_PATH_NOT_FOUND))
+            bResult = FALSE;
+
+        goto done;
+    }
+
+    do
+    {
+        if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+        {
+            if ((_wcsicmp(FindData.cFileName, L".") == 0) ||
+                (_wcsicmp(FindData.cFileName, L"..") == 0))
+                continue;
+
+            pszProfilePath[dwProfilePathLength + 1] = UNICODE_NULL;
+            wcscat(pszProfilePath, FindData.cFileName);
+
+            if (!GetProfileSize(pszProfilePath, pullProfileSize))
+            {
+                bResult = FALSE;
+                goto done;
+            }
+        }
+        else
+        {
+            Size.u.LowPart = FindData.nFileSizeLow;
+            Size.u.HighPart = FindData.nFileSizeHigh;
+            *pullProfileSize += Size.QuadPart;
+        }
+    }
+    while (FindNextFile(hFile, &FindData));
+
+done:
+    pszProfilePath[dwProfilePathLength] = UNICODE_NULL;
+
+    if (hFile != INVALID_HANDLE_VALUE)
+        FindClose(hFile);
+
+    return bResult;
+}
+
+
 static
 BOOL
 GetProfileName(
@@ -369,17 +431,43 @@ GetProfileName(
 }
 
 
+static
+VOID
+FormatProfileSize(LPWSTR Buffer, double size)
+{
+    const LPWSTR units[] = {L"MB", L"GB", L"TB"};
+    int i = 0, j;
+
+    size /= 1024;
+    size /= 1024;
+
+    while (size >= 1024 && i < 3)
+    {
+        size /= 1024;
+        i++;
+    }
+
+    if (size < 10)
+        j = 2;
+    else if (size < 100)
+        j = 1;
+    else
+        j = 0;
+
+    swprintf(Buffer, L"%.*f %s", j, size, units[i]);
+}
+
+
 static VOID
 AddUserProfile(
     _In_ HWND hwndListView,
     _In_ PSID pProfileSid,
-    _In_ BOOL bMyProfile,
     _In_ HKEY hProfileKey)
 {
     WCHAR szTempProfilePath[MAX_PATH], szProfilePath[MAX_PATH];
     WCHAR szNameBuffer[256];
     PPROFILEDATA pProfileData = NULL;
-    DWORD dwProfileData, dwSize, dwType, dwState = 0;
+    DWORD dwProfileData, dwSize, dwType, dwState = 0, dwRefCount = 0;
     DWORD dwProfilePathLength;
     PWSTR ptr;
     INT nId, iItem;
@@ -387,6 +475,7 @@ AddUserProfile(
     WIN32_FIND_DATA FindData;
     HANDLE hFile;
     SYSTEMTIME SystemTime;
+    ULONGLONG ullProfileSize;
     DWORD dwError;
 
     /* Get the profile path */
@@ -424,6 +513,10 @@ AddUserProfile(
     FindClose(hFile);
     szProfilePath[dwProfilePathLength] = UNICODE_NULL;
 
+    /* Get the profile size */
+    ullProfileSize = 0ULL;
+    GetProfileSize(szProfilePath, &ullProfileSize);
+
     /* Get the profile name */
     if (!GetProfileName(pProfileSid, ARRAYSIZE(szNameBuffer), szNameBuffer))
         return;
@@ -440,6 +533,18 @@ AddUserProfile(
         dwState = 0;
     }
 
+    /* Get the profile reference counter */
+    dwSize = sizeof(dwRefCount);
+    if (RegQueryValueExW(hProfileKey,
+                         L"RefCount",
+                         NULL,
+                         &dwType,
+                         (LPBYTE)&dwRefCount,
+                         &dwSize) != ERROR_SUCCESS)
+    {
+        dwRefCount = 0;
+    }
+
     /* Create and fill the profile data entry */
     dwProfileData = sizeof(PROFILEDATA) +
                     ((wcslen(szNameBuffer) + 1) * sizeof(WCHAR));
@@ -449,7 +554,7 @@ AddUserProfile(
     if (pProfileData == NULL)
         return;
 
-    pProfileData->bMyProfile = bMyProfile;
+    pProfileData->dwRefCount = dwRefCount;
     pProfileData->dwState = dwState;
 
     ptr = (PWSTR)((ULONG_PTR)pProfileData + sizeof(PROFILEDATA));
@@ -465,12 +570,12 @@ AddUserProfile(
     lvi.lParam = (LPARAM)pProfileData;
     iItem = ListView_InsertItem(hwndListView, &lvi);
 
-    /* FIXME: Set the profile size */
+    /* Set the profile size */
+    FormatProfileSize(szNameBuffer, (double)ullProfileSize);
+    ListView_SetItemText(hwndListView, iItem, 1, szNameBuffer);
 
     /* Set the profile type */
-    if (dwState & 0x0001) // PROFILE_MANDATORY
-        nId = IDS_USERPROFILE_MANDATORY;
-    else if (dwState & 0x0010) // PROFILE_UPDATE_CENTRAL
+    if (dwState & 0x0010) // PROFILE_UPDATE_CENTRAL
         nId = IDS_USERPROFILE_ROAMING;
     else
         nId = IDS_USERPROFILE_LOCAL;
@@ -480,6 +585,16 @@ AddUserProfile(
     ListView_SetItemText(hwndListView, iItem, 2, szNameBuffer);
 
     /* FIXME: Set the profile status */
+    if (dwState & 0x0001) // PROFILE_MANDATORY
+        nId = IDS_USERPROFILE_MANDATORY;
+    else if (dwState & 0x0010) // PROFILE_UPDATE_CENTRAL
+        nId = IDS_USERPROFILE_ROAMING;
+    else
+        nId = IDS_USERPROFILE_LOCAL;
+
+    LoadStringW(hApplet, nId, szNameBuffer, ARRAYSIZE(szNameBuffer));
+
+    ListView_SetItemText(hwndListView, iItem, 3, szNameBuffer);
 
     /* Set the profile modified time */
     FileTimeToSystemTime(&FindData.ftLastWriteTime,
@@ -503,7 +618,9 @@ UpdateButtonState(
 {
     LVITEM Item;
     INT iSelected;
-    BOOL bMyProfile;
+    BOOL bChange = FALSE;
+    BOOL bCopy = FALSE;
+    BOOL bDelete = FALSE;
 
     iSelected = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED);
     if (iSelected != -1)
@@ -515,22 +632,23 @@ UpdateButtonState(
         {
             if (Item.lParam != 0)
             {
-                bMyProfile = ((PPROFILEDATA)Item.lParam)->bMyProfile;
-                if (!bMyProfile)
-                {
-                    EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), TRUE);
-                    EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), TRUE);
-                }
+                bCopy = (((PPROFILEDATA)Item.lParam)->dwRefCount == 0);
+                bDelete = (((PPROFILEDATA)Item.lParam)->dwRefCount == 0);
             }
         }
-        EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_CHANGE), TRUE);
+
+        bChange = TRUE;
     }
     else
     {
-        EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_CHANGE), FALSE);
-        EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), FALSE);
-        EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), FALSE);
+        bChange = FALSE;
+        bCopy = FALSE;
+        bDelete = FALSE;
     }
+
+    EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_CHANGE), bChange);
+    EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), bDelete);
+    EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), bCopy);
 }
 
 
@@ -598,7 +716,6 @@ AddUserProfiles(
                 {
                     AddUserProfile(hwndListView,
                                    pProfileSid,
-                                   EqualSid(pProfileSid, pTokenUser->User.Sid),
                                    hProfileKey);
                     LocalFree(pProfileSid);
                 }
@@ -619,7 +736,6 @@ AddUserProfiles(
             {
                 AddUserProfile(hwndListView,
                                pTokenUser->User.Sid,
-                               TRUE,
                                hProfileKey);
                 RegCloseKey(hProfileKey);
             }