Recently, When I was responsible for data backup products, I encountered a problem: In win7, the user selected "C: \ Users" as the backup source, it is found that the folder size displayed on the product UI is inconsistent with the folder size in the service process responsible for backup.
At first, I suspect that the method for obtaining the folder size is incorrect, but after checking the code, I found that the Code is the same. Enumerate the folder and file size, and then accumulate. Later, I found that many directories cannot be accessed when the UI process obtains the folder size, while the service process can access all the folders in the directory, the size is much larger than that displayed on the UI. The two processes have different permissions.
The framework of this product is: the UI process runs in the current user State, so only the current user's permissions are available, while the background service process runs in the system state, therefore, you have the highest permission to access all directories.
Problem itself:
First, let's take a look at the C: \ Users contents in the win7 directory (set both hide and system to visible)
There is an "Application Data" directory under the c: \ Users \ All Users Directory, which cannot be accessed in the resource manager.
Because the resource manager is actually running under the current user permission, the directory size obtained by the UI process is the same as that seen by the method of viewing properties through the resource manager.
How to solve the problem:
Then, I further compared the attributes of these directories and found that the "Application Data" directory contains attributes such as file_attribute_directory, file_attribute_system, file_attribute_reparse_point, and file_attribute_not_content_indexed. However, we cannot determine by attributes that the current user has no access permission, because some directories are accessible to the current user, such as the user's own "Application Data" directory.
Therefore, the perfect solution is to reduce the service process permission from system to the current user permission. However, I checked a lot of information, but I still did not have the necessary information. In addition, the implementation risk was high, so I gave up.
In this case, as long as the directory size on both sides is always displayed, we finally try to pass the directory size to the service process through the UI process, instead of letting the service process obtain it again.
How to get the directory size:
The following is a common function for getting the folder size for your reference only.
Bool getfoldersize (lpcwstr szpath, uint64 * totalsize, uint64 * totalfiles, uint64 * totalfolders)
{
If (null = szpath)
{
Return false;
}
Static const int max_path_len = 512;
Wchar szfilefilter [max_path_len] = {0 };
Tchar szfilepath [max_path_len] = {0 };
Handle hfind = invalid_handle_value;
Win32_find_data fileinfo;
Wcsncpy_s (szfilepath, szpath, max_path_len );
Wcscat_s (szfilepath, l "\\");
Wcsncpy_s (szfilefilter, szfilepath, max_path_len );
Wcscat_s (szfilefilter, l "*.*");
Hfind = findfirstfile (szfilefilter, & fileinfo );
If (invalid_handle_value = hfind)
{
Return false;
}
Do
{
If (fileinfo. dwfileattributes & file_attribute_directory)
{
If (! Wcscmp (fileinfo. cfilename, l ".") |! Wcscmp (fileinfo. cfilename, l ".."))
{
// Do nothing for "." and "..." Folders
}
Else
{
Wchar sztmp [max_path_len];
Wcsncpy_s (sztmp, szfilepath, max_path_len );
Wcscat_s (sztmp, fileinfo. cfilename );
Getfoldersize (sztmp, totalsize, totalfiles, totalfolders );
If (totalfolders! = NULL)
{
++ (* Totalfolders );
}
}
}
Else
{
If (totalfiles! = NULL)
{
++ (* Totalfiles );
}
}
If (totalsize! = NULL)
{
(* Totalsize) + = (uint64) maxdword + 1) * fileinfo. nfilesizehigh + fileinfo. nfilesizelow;
}
} While (findnextfile (hfind, & fileinfo ));
Findclose (hfind );
Hfind = invalid_handle_value;
Return true;
}