#pragma comment(lib, "shlwapi.lib") #define _WIN32_WINNT _WIN32_WINNT_VISTA #include #include #include UINT32 TotalFiles = 0; UINT64 TotalSize = 0; UINT32 AliasedFiles = 0; UINT64 AliasedSize = 0; WCHAR Pattern[MAX_PATH]; void SearchRecursively(LPCWSTR Path) { WIN32_FIND_DATA FindData = { 0 }; HANDLE FindHandle = INVALID_HANDLE_VALUE; ::PathCombine(Pattern, Path, L"*"); FindHandle = ::FindFirstFile(Pattern, &FindData); do { if ((::lstrlenW(FindData.cFileName) == 0) || (::lstrcmpiW(FindData.cFileName, L".") == 0) || (::lstrcmpiW(FindData.cFileName, L"..") == 0)) { continue; } ::PathCombine(FindData.cFileName, Path, FindData.cFileName); if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { SearchRecursively(FindData.cFileName); } else { HANDLE File = ::CreateFile(FindData.cFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (File != INVALID_HANDLE_VALUE) { FILE_STANDARD_INFO FileInfo; if (::GetFileInformationByHandleEx(File, FileStandardInfo, &FileInfo, sizeof(FileInfo))) { if (FileInfo.NumberOfLinks > 1) { AliasedFiles += 1; AliasedSize += FileInfo.AllocationSize.QuadPart; } TotalFiles += 1; TotalSize += FileInfo.AllocationSize.QuadPart; } ::CloseHandle(File); } } } while (::FindNextFile(FindHandle, &FindData) ); } int wmain(int argc, wchar_t* argv[]) { SearchRecursively(L"C:\\Windows\\WinSxS"); std::cout << "Total count: " << TotalFiles << std::endl; std::cout << "Total size: " << TotalSize << std::endl; std::cout << std::endl; std::cout << "Hardlinked count: " << AliasedFiles << std::endl; std::cout << "Hardlinked size: " << AliasedSize << std::endl; std::cout << std::endl; std::cout << "Unique size: " << (TotalSize - AliasedSize) << std::endl; return 0; }