* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include <precomp.h>
+#include "precomp.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
return pwszResult;
}
-
+
VS_FIXEDFILEINFO *CFileVersionInfo::GetFixedInfo()
{
if (!m_pInfo)
return m_wszLang;
}
-/*************************************************************************
- *
- * SH_FormatFileSizeWithBytes
- *
- * Format a size in bytes to string.
- *
- * lpQwSize = Pointer to 64bit large integer to format
- * pszBuf = Buffer to fill with output string
- * cchBuf = size of pszBuf in characters
- *
- */
-
-LPWSTR
-SH_FormatFileSizeWithBytes(PULARGE_INTEGER lpQwSize, LPWSTR pszBuf, UINT cchBuf)
+UINT
+SH_FormatInteger(LONGLONG Num, LPWSTR pwszResult, UINT cchResultMax)
{
- NUMBERFMTW nf;
- WCHAR szNumber[24];
- WCHAR szDecimalSep[8];
- WCHAR szThousandSep[8];
- WCHAR szGrouping[12];
- int Len, cchFormatted, i;
- size_t cchRemaining;
- LPWSTR Ptr;
-
- // Try to build first Format byte string
- if (StrFormatByteSizeW(lpQwSize->QuadPart, pszBuf, cchBuf) == NULL)
- return NULL;
-
- // If there is less bytes than 1KB, we have nothing to do
- if (lpQwSize->QuadPart < 1024)
- return pszBuf;
-
// Print the number in uniform mode
- swprintf(szNumber, L"%I64u", lpQwSize->QuadPart);
+ WCHAR wszNumber[24];
+ swprintf(wszNumber, L"%I64u", Num);
// Get system strings for decimal and thousand separators.
- GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, szDecimalSep, sizeof(szDecimalSep) / sizeof(*szDecimalSep));
- GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szThousandSep, sizeof(szThousandSep) / sizeof(*szThousandSep));
+ WCHAR wszDecimalSep[8], wszThousandSep[8];
+ GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, wszDecimalSep, _countof(wszDecimalSep));
+ GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, wszThousandSep, _countof(wszThousandSep));
// Initialize format for printing the number in bytes
+ NUMBERFMTW nf;
ZeroMemory(&nf, sizeof(nf));
- nf.NumDigits = 0;
- nf.LeadingZero = 0;
- nf.Grouping = 0;
- nf.lpDecimalSep = szDecimalSep;
- nf.lpThousandSep = szThousandSep;
- nf.NegativeOrder = 0;
+ nf.lpDecimalSep = wszDecimalSep;
+ nf.lpThousandSep = wszThousandSep;
// Get system string for groups separator
- Len = GetLocaleInfoW(LOCALE_USER_DEFAULT,
- LOCALE_SGROUPING,
- szGrouping,
- sizeof(szGrouping) / sizeof(*szGrouping));
+ WCHAR wszGrouping[12];
+ INT cchGrouping = GetLocaleInfoW(LOCALE_USER_DEFAULT,
+ LOCALE_SGROUPING,
+ wszGrouping,
+ _countof(wszGrouping));
// Convert grouping specs from string to integer
- for (i = 0; i < Len; i++)
+ for (INT i = 0; i < cchGrouping; i++)
{
- WCHAR wch = szGrouping[i];
+ WCHAR wch = wszGrouping[i];
if (wch >= L'0' && wch <= L'9')
nf.Grouping = nf.Grouping * 10 + (wch - L'0');
else
nf.Grouping *= 10;
- // Concate " (" at the end of buffer
- Len = wcslen(pszBuf);
- Ptr = pszBuf + Len;
- cchRemaining = cchBuf - Len;
- StringCchCopyExW(Ptr, cchRemaining, L" (", &Ptr, &cchRemaining, 0);
-
- // Save formatted number of bytes in buffer
- cchFormatted = GetNumberFormatW(LOCALE_USER_DEFAULT,
+ // Format the number
+ INT cchResult = GetNumberFormatW(LOCALE_USER_DEFAULT,
0,
- szNumber,
+ wszNumber,
&nf,
- Ptr,
- cchRemaining);
+ pwszResult,
+ cchResultMax);
+
+ if (!cchResult)
+ return 0;
- if (cchFormatted == 0)
+ // GetNumberFormatW returns number of characters including UNICODE_NULL
+ return cchResult - 1;
+}
+
+UINT
+SH_FormatByteSize(LONGLONG cbSize, LPWSTR pwszResult, UINT cchResultMax)
+{
+ /* Write formated bytes count */
+ INT cchWritten = SH_FormatInteger(cbSize, pwszResult, cchResultMax);
+ if (!cchWritten)
+ return 0;
+
+ /* Copy " bytes" to buffer */
+ LPWSTR pwszEnd = pwszResult + cchWritten;
+ size_t cchRemaining = cchResultMax - cchWritten;
+ StringCchCopyExW(pwszEnd, cchRemaining, L" ", &pwszEnd, &cchRemaining, NULL);
+ cchWritten = LoadStringW(shell32_hInstance, IDS_BYTES_FORMAT, pwszEnd, cchRemaining);
+ cchRemaining -= cchWritten;
+
+ return cchResultMax - cchRemaining;
+}
+
+/*************************************************************************
+ *
+ * SH_FormatFileSizeWithBytes
+ *
+ * Format a size in bytes to string.
+ *
+ * lpQwSize = Pointer to 64bit large integer to format
+ * pszBuf = Buffer to fill with output string
+ * cchBuf = size of pszBuf in characters
+ *
+ */
+
+LPWSTR
+SH_FormatFileSizeWithBytes(const PULARGE_INTEGER lpQwSize, LPWSTR pwszResult, UINT cchResultMax)
+{
+ /* Format bytes in KBs, MBs etc */
+ if (StrFormatByteSizeW(lpQwSize->QuadPart, pwszResult, cchResultMax) == NULL)
return NULL;
- // cchFormatted is number of characters including NULL - make it a real length
- --cchFormatted;
+ /* If there is less bytes than 1KB, we have nothing to do */
+ if (lpQwSize->QuadPart < 1024)
+ return pwszResult;
+
+ /* Concate " (" */
+ UINT cchWritten = wcslen(pwszResult);
+ LPWSTR pwszEnd = pwszResult + cchWritten;
+ size_t cchRemaining = cchResultMax - cchWritten;
+ StringCchCopyExW(pwszEnd, cchRemaining, L" (", &pwszEnd, &cchRemaining, 0);
- // Copy ' ' to buffer
- Ptr += cchFormatted;
- cchRemaining -= cchFormatted;
- StringCchCopyExW(Ptr, cchRemaining, L" ", &Ptr, &cchRemaining, 0);
+ /* Write formated bytes count */
+ cchWritten = SH_FormatByteSize(lpQwSize->QuadPart, pwszEnd, cchRemaining);
+ pwszEnd += cchWritten;
+ cchRemaining -= cchWritten;
- // Copy 'bytes' string and remaining ')'
- Len = LoadStringW(shell32_hInstance, IDS_BYTES_FORMAT, Ptr, cchRemaining);
- Ptr += Len;
- cchRemaining -= Len;
- StringCchCopy(Ptr, cchRemaining, L")");
+ /* Copy ")" to the buffer */
+ StringCchCopyW(pwszEnd, cchRemaining, L")");
- return pszBuf;
+ return pwszResult;
}
/*************************************************************************
*/
HPROPSHEETPAGE
-SH_CreatePropertySheetPage(LPCSTR pszResName, DLGPROC pfnDlgProc, LPARAM lParam, LPWSTR pwszTitle)
+SH_CreatePropertySheetPage(WORD wDialogId, DLGPROC pfnDlgProc, LPARAM lParam, LPCWSTR pwszTitle)
{
- if (pszResName == NULL)
- return NULL;
-
- HRSRC hRes = FindResourceA(shell32_hInstance, pszResName, (LPSTR)RT_DIALOG);
+ HRSRC hRes = FindResourceW(shell32_hInstance, MAKEINTRESOURCEW(wDialogId), (LPWSTR)RT_DIALOG);
if (hRes == NULL)
{
- ERR("failed to find resource name\n");
+ ERR("failed to find resource id\n");
return NULL;
}
ShowWindow(hIconCtrl, SW_SHOW);
RECT rcIcon, rcDescr;
GetWindowRect(hIconCtrl, &rcIcon);
+ if (rcIcon.left == rcIcon.right)
+ ERR("Icon control has invalid width: %d-%d\n", rcIcon.left, rcIcon.right);
MapWindowPoints(NULL, hwndDlg, (LPPOINT)&rcIcon, 2);
GetWindowRect(hDescrCtrl, &rcDescr);
MapWindowPoints(NULL, hwndDlg, (LPPOINT)&rcDescr, 2);
/*************************************************************************
*
- * SHFileGeneralGetFileTimeString [Internal]
- *
- * formats a given LPFILETIME struct into readable user format
- */
-
-BOOL
-CFileDefExt::GetFileTimeString(LPFILETIME lpFileTime, WCHAR *lpResult)
-{
- FILETIME ft;
- SYSTEMTIME st;
-
- if (lpFileTime == NULL || lpResult == NULL)
- return FALSE;
-
- if (!FileTimeToLocalFileTime(lpFileTime, &ft))
- return FALSE;
-
- FileTimeToSystemTime(&ft, &st);
-
- /* ddmmyy */
- swprintf(lpResult, L"%02hu/%02hu/%04hu %02hu:%02hu", st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute);
-
- TRACE("result %s\n", debugstr_w(lpResult));
- return TRUE;
-}
-
-/*************************************************************************
- *
- * SH_FileGeneralSetText [Internal]
+ * CFileDefExt::InitFilePath [Internal]
*
* sets file path string and filename string
*
/*************************************************************************
*
- * SH_FileGeneralSetFileSizeTime [Internal]
- *
- * retrieves file information from file and sets in dialog
+ * CFileDefExt::GetFileTimeString [Internal]
*
+ * formats a given LPFILETIME struct into readable user format
*/
BOOL
-CFileDefExt::InitFileSizeTime(HWND hwndDlg)
+CFileDefExt::GetFileTimeString(LPFILETIME lpFileTime, LPWSTR pwszResult, UINT cchResult)
{
- WCHAR wszBuf[MAX_PATH];
-
- TRACE("SH_FileGeneralSetFileSizeTime %ls\n", m_wszPath);
-
- HANDLE hFile = CreateFileW(m_wszPath,
- GENERIC_READ,
- FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
+ FILETIME ft;
+ SYSTEMTIME st;
- if (hFile == INVALID_HANDLE_VALUE)
- {
- WARN("failed to open file %s\n", debugstr_w(m_wszPath));
+ if (!FileTimeToLocalFileTime(lpFileTime, &ft) || !FileTimeToSystemTime(&ft, &st))
return FALSE;
- }
- FILETIME CreateTime, AccessedTime, WriteTime;
- if (!GetFileTime(hFile, &CreateTime, &AccessedTime, &WriteTime))
- {
- WARN("GetFileTime failed\n");
- CloseHandle(hFile);
- return FALSE;
- }
+ size_t cchRemaining = cchResult;
+ LPWSTR pwszEnd = pwszResult;
+ int cchWritten = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, pwszEnd, cchRemaining);
+ if (cchWritten)
+ --cchWritten; // GetDateFormatW returns count with terminating zero
+ else
+ ERR("GetDateFormatW failed\n");
+ cchRemaining -= cchWritten;
+ pwszEnd += cchWritten;
- LARGE_INTEGER FileSize;
- if (!GetFileSizeEx(hFile, &FileSize))
- {
- WARN("GetFileSize failed\n");
- CloseHandle(hFile);
- return FALSE;
- }
+ StringCchCopyExW(pwszEnd, cchRemaining, L", ", &pwszEnd, &cchRemaining, 0);
- CloseHandle(hFile);
+ cchWritten = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, pwszEnd, cchRemaining);
+ if (cchWritten)
+ --cchWritten; // GetTimeFormatW returns count with terminating zero
+ else
+ ERR("GetTimeFormatW failed\n");
+ TRACE("result %s\n", debugstr_w(pwszResult));
+ return TRUE;
+}
- if (GetFileTimeString(&CreateTime, wszBuf))
- SetDlgItemTextW(hwndDlg, 14015, wszBuf);
+/*************************************************************************
+ *
+ * CFileDefExt::InitFileAttr [Internal]
+ *
+ * retrieves file information from file and sets in dialog
+ *
+ */
- if (GetFileTimeString(&AccessedTime, wszBuf))
- SetDlgItemTextW(hwndDlg, 14019, wszBuf);
+BOOL
+CFileDefExt::InitFileAttr(HWND hwndDlg)
+{
+ WCHAR wszBuf[MAX_PATH];
- if (GetFileTimeString(&WriteTime, wszBuf))
- SetDlgItemTextW(hwndDlg, 14017, wszBuf);
+ TRACE("InitFileAttr %ls\n", m_wszPath);
- if (SH_FormatFileSizeWithBytes((PULARGE_INTEGER)&FileSize,
- wszBuf,
- sizeof(wszBuf) / sizeof(WCHAR)))
+ WIN32_FILE_ATTRIBUTE_DATA FileInfo;
+ if (GetFileAttributesExW(m_wszPath, GetFileExInfoStandard, &FileInfo))
{
- SetDlgItemTextW(hwndDlg, 14011, wszBuf);
+ /* Update attribute checkboxes */
+ if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+ SendDlgItemMessage(hwndDlg, 14021, BM_SETCHECK, BST_CHECKED, 0);
+ if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
+ SendDlgItemMessage(hwndDlg, 14022, BM_SETCHECK, BST_CHECKED, 0);
+ if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
+ SendDlgItemMessage(hwndDlg, 14023, BM_SETCHECK, BST_CHECKED, 0);
+
+ /* Update creation time */
+ if (GetFileTimeString(&FileInfo.ftCreationTime, wszBuf, _countof(wszBuf)))
+ SetDlgItemTextW(hwndDlg, 14015, wszBuf);
+
+ /* For files display last access and last write time */
+ if (!m_bDir)
+ {
+ if (GetFileTimeString(&FileInfo.ftLastAccessTime, wszBuf, _countof(wszBuf)))
+ SetDlgItemTextW(hwndDlg, 14019, wszBuf);
+
+ if (GetFileTimeString(&FileInfo.ftLastWriteTime, wszBuf, _countof(wszBuf)))
+ SetDlgItemTextW(hwndDlg, 14017, wszBuf);
+
+ /* Update size of file */
+ ULARGE_INTEGER FileSize;
+ FileSize.u.LowPart = FileInfo.nFileSizeLow;
+ FileSize.u.HighPart = FileInfo.nFileSizeHigh;
+ if (SH_FormatFileSizeWithBytes(&FileSize, wszBuf, _countof(wszBuf)))
+ SetDlgItemTextW(hwndDlg, 14011, wszBuf);
+ }
}
+ if (m_bDir)
+ {
+ /* For directories files have to be counted */
+
+ _CountFolderAndFilesData *data = static_cast<_CountFolderAndFilesData*>(HeapAlloc(GetProcessHeap(), 0, sizeof(_CountFolderAndFilesData)));
+ data->This = this;
+ data->pwszBuf = static_cast<LPWSTR>(HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * MAX_PATH));
+ data->cchBufMax = MAX_PATH;
+ data->hwndDlg = hwndDlg;
+ this->AddRef();
+ StringCchCopyW(data->pwszBuf, MAX_PATH, m_wszPath);
+
+ SHCreateThread(CFileDefExt::_CountFolderAndFilesThreadProc, data, NULL, NULL);
+
+ /* Update size field */
+ if (SH_FormatFileSizeWithBytes(&m_DirSize, wszBuf, _countof(wszBuf)))
+ SetDlgItemTextW(hwndDlg, 14011, wszBuf);
+
+ /* Display files and folders count */
+ WCHAR wszFormat[256];
+ LoadStringW(shell32_hInstance, IDS_FILE_FOLDER, wszFormat, _countof(wszFormat));
+ StringCchPrintfW(wszBuf, _countof(wszBuf), wszFormat, m_cFiles, m_cFolders);
+ SetDlgItemTextW(hwndDlg, 14027, wszBuf);
+ }
+
+ /* Hide Advanced button. TODO: Implement advanced dialog and enable this button if filesystem supports compression or encryption */
+ ShowWindow(GetDlgItem(hwndDlg, 14028), SW_HIDE);
+
return TRUE;
}
InitFileType(hwndDlg);
/* Set open with application */
- if (!PathIsExeW(m_wszPath))
- InitOpensWithField(hwndDlg);
- else
+ if (!m_bDir)
{
- WCHAR wszBuf[MAX_PATH];
- LoadStringW(shell32_hInstance, IDS_EXE_DESCRIPTION, wszBuf, _countof(wszBuf));
- SetDlgItemTextW(hwndDlg, 14006, wszBuf);
- ShowWindow(GetDlgItem(hwndDlg, 14024), SW_HIDE);
- LPCWSTR pwszDescr = m_VerInfo.GetString(L"FileDescription");
- if (pwszDescr)
- SetDlgItemTextW(hwndDlg, 14007, pwszDescr);
+ if (!PathIsExeW(m_wszPath))
+ InitOpensWithField(hwndDlg);
else
{
- StringCbCopyW(wszBuf, sizeof(wszBuf), PathFindFileNameW(m_wszPath));
- PathRemoveExtension(wszBuf);
- SetDlgItemTextW(hwndDlg, 14007, wszBuf);
+ WCHAR wszBuf[MAX_PATH];
+ LoadStringW(shell32_hInstance, IDS_EXE_DESCRIPTION, wszBuf, _countof(wszBuf));
+ SetDlgItemTextW(hwndDlg, 14006, wszBuf);
+ ShowWindow(GetDlgItem(hwndDlg, 14024), SW_HIDE);
+ LPCWSTR pwszDescr = m_VerInfo.GetString(L"FileDescription");
+ if (pwszDescr)
+ SetDlgItemTextW(hwndDlg, 14007, pwszDescr);
+ else
+ {
+ StringCbCopyW(wszBuf, sizeof(wszBuf), PathFindFileNameW(m_wszPath));
+ PathRemoveExtension(wszBuf);
+ SetDlgItemTextW(hwndDlg, 14007, wszBuf);
+ }
}
}
- /* Set file created/modfied/accessed time */
- InitFileSizeTime(hwndDlg);
+ /* Set file created/modfied/accessed time, size and attributes */
+ InitFileAttr(hwndDlg);
return TRUE;
}
oainfo.oaifInFlags = OAIF_REGISTER_EXT|OAIF_FORCE_REGISTRATION;
return SUCCEEDED(SHOpenWithDialog(hwndDlg, &oainfo));
}
+ else if (LOWORD(wParam) == 14021 || LOWORD(wParam) == 14022 || LOWORD(wParam) == 14023) /* checkboxes */
+ PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
+ else if (LOWORD(wParam) == 14001) /* Name */
+ {
+ if (HIWORD(wParam) == EN_CHANGE)
+ PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
+ }
break;
+ case WM_NOTIFY:
+ {
+ LPPSHNOTIFY lppsn = (LPPSHNOTIFY)lParam;
+ if (lppsn->hdr.code == PSN_APPLY)
+ {
+ CFileDefExt *pFileDefExt = (CFileDefExt*)GetWindowLongPtr(hwndDlg, DWLP_USER);
+
+ /* Update attributes first */
+ DWORD dwAttr = GetFileAttributesW(pFileDefExt->m_wszPath);
+ if (dwAttr)
+ {
+ dwAttr &= ~(FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_ARCHIVE);
+
+ if (BST_CHECKED == SendDlgItemMessageW(hwndDlg, 14021, BM_GETCHECK, 0, 0))
+ dwAttr |= FILE_ATTRIBUTE_READONLY;
+ if (BST_CHECKED == SendDlgItemMessageW(hwndDlg, 14022, BM_GETCHECK, 0, 0))
+ dwAttr |= FILE_ATTRIBUTE_HIDDEN;
+ if (BST_CHECKED == SendDlgItemMessageW(hwndDlg, 14023, BM_GETCHECK, 0, 0))
+ dwAttr |= FILE_ATTRIBUTE_ARCHIVE;
+
+ if (!SetFileAttributesW(pFileDefExt->m_wszPath, dwAttr))
+ ERR("SetFileAttributesW failed\n");
+ }
+
+ /* Update filename now */
+ WCHAR wszBuf[MAX_PATH];
+ StringCchCopyW(wszBuf, _countof(wszBuf), pFileDefExt->m_wszPath);
+ LPWSTR pwszFilename = PathFindFileNameW(wszBuf);
+ UINT cchFilenameMax = _countof(wszBuf) - (pwszFilename - wszBuf);
+ if (GetDlgItemTextW(hwndDlg, 14001, pwszFilename, cchFilenameMax))
+ {
+ if (!MoveFileW(pFileDefExt->m_wszPath, wszBuf))
+ ERR("MoveFileW failed\n");
+ }
+
+ SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR);
+ return TRUE;
+ }
+ break;
+ }
default:
break;
}
return FALSE;
}
-CFileDefExt::CFileDefExt()
+CFileDefExt::CFileDefExt():
+ m_bDir(FALSE), m_cFiles(0), m_cFolders(0)
{
m_wszPath[0] = L'\0';
+ m_DirSize.QuadPart = 0ull;
}
CFileDefExt::~CFileDefExt()
{
-
+
}
HRESULT WINAPI
}
ReleaseStgMedium(&stgm);
+
TRACE("File properties %ls\n", m_wszPath);
- m_VerInfo.Load(m_wszPath);
+ m_bDir = PathIsDirectoryW(m_wszPath) ? TRUE : FALSE;
+ if (!m_bDir)
+ m_VerInfo.Load(m_wszPath);
return S_OK;
}
CFileDefExt::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
{
HPROPSHEETPAGE hPage;
+ WORD wResId = m_bDir ? IDD_FOLDER_PROPERTIES : IDD_FILE_PROPERTIES;
- hPage = SH_CreatePropertySheetPage("SHELL_FILE_GENERAL_DLG",
- GeneralPageProc,
- (LPARAM)this,
- NULL);
+ hPage = SH_CreatePropertySheetPage(wResId,
+ GeneralPageProc,
+ (LPARAM)this,
+ NULL);
if (hPage)
pfnAddPage(hPage, lParam);
- if (GetFileVersionInfoSizeW(m_wszPath, NULL))
+ if (!m_bDir && GetFileVersionInfoSizeW(m_wszPath, NULL))
{
- hPage = SH_CreatePropertySheetPage("SHELL_FILE_VERSION_DLG",
+ hPage = SH_CreatePropertySheetPage(IDD_FILE_VERSION,
VersionPageProc,
(LPARAM)this,
NULL);
UNIMPLEMENTED;
return E_NOTIMPL;
}
+
+DWORD WINAPI
+CFileDefExt::_CountFolderAndFilesThreadProc(LPVOID lpParameter)
+{
+ _CountFolderAndFilesData *data = static_cast<_CountFolderAndFilesData*>(lpParameter);
+ DWORD ticks = 0;
+ data->This->CountFolderAndFiles(data->hwndDlg, data->pwszBuf, data->cchBufMax, &ticks);
+
+ //Release the CFileDefExt and data object holds in the copying thread.
+ data->This->Release();
+ HeapFree(GetProcessHeap(), 0, data->pwszBuf);
+ HeapFree(GetProcessHeap(), 0, data);
+
+ return 0;
+}
+
+BOOL
+CFileDefExt::CountFolderAndFiles(HWND hwndDlg, LPWSTR pwszBuf, UINT cchBufMax, DWORD *ticks)
+{
+ /* Find filename position */
+ UINT cchBuf = wcslen(pwszBuf);
+ WCHAR *pwszFilename = pwszBuf + cchBuf;
+ size_t cchFilenameMax = cchBufMax - cchBuf;
+ if (!cchFilenameMax)
+ return FALSE;
+ *(pwszFilename++) = '\\';
+ --cchFilenameMax;
+
+ /* Find all files, FIXME: shouldn't be "*"? */
+ StringCchCopyW(pwszFilename, cchFilenameMax, L"*");
+
+ WIN32_FIND_DATAW wfd;
+ HANDLE hFind = FindFirstFileW(pwszBuf, &wfd);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ ERR("FindFirstFileW %ls failed\n", pwszBuf);
+ return FALSE;
+ }
+
+ BOOL root = FALSE;
+ if (*ticks == 0) {
+ *ticks = GetTickCount();
+ root = TRUE;
+ }
+
+ do
+ {
+ if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ /* Don't process "." and ".." items */
+ if (!wcscmp(wfd.cFileName, L".") || !wcscmp(wfd.cFileName, L".."))
+ continue;
+
+ ++m_cFolders;
+
+ StringCchCopyW(pwszFilename, cchFilenameMax, wfd.cFileName);
+ CountFolderAndFiles(hwndDlg, pwszBuf, cchBufMax, ticks);
+ }
+ else
+ {
+ m_cFiles++;
+
+ ULARGE_INTEGER FileSize;
+ FileSize.u.LowPart = wfd.nFileSizeLow;
+ FileSize.u.HighPart = wfd.nFileSizeHigh;
+ m_DirSize.QuadPart += FileSize.QuadPart;
+ }
+ if (GetTickCount() - *ticks > (DWORD) 300)
+ {
+ /* FIXME Using IsWindow is generally ill advised */
+ if (IsWindow(hwndDlg))
+ {
+ WCHAR wszBuf[MAX_PATH];
+
+ if (SH_FormatFileSizeWithBytes(&m_DirSize, wszBuf, _countof(wszBuf)))
+ SetDlgItemTextW(hwndDlg, 14011, wszBuf);
+
+ /* Display files and folders count */
+ WCHAR wszFormat[256];
+ LoadStringW(shell32_hInstance, IDS_FILE_FOLDER, wszFormat, _countof(wszFormat));
+ StringCchPrintfW(wszBuf, _countof(wszBuf), wszFormat, m_cFiles, m_cFolders);
+ SetDlgItemTextW(hwndDlg, 14027, wszBuf);
+ *ticks = GetTickCount();
+ }
+ else
+ break;
+ }
+ } while(FindNextFileW(hFind, &wfd));
+
+ if (root && IsWindow(hwndDlg))
+ {
+ WCHAR wszBuf[MAX_PATH];
+
+ if (SH_FormatFileSizeWithBytes(&m_DirSize, wszBuf, _countof(wszBuf)))
+ SetDlgItemTextW(hwndDlg, 14011, wszBuf);
+
+ /* Display files and folders count */
+ WCHAR wszFormat[256];
+ LoadStringW(shell32_hInstance, IDS_FILE_FOLDER, wszFormat, _countof(wszFormat));
+ StringCchPrintfW(wszBuf, _countof(wszBuf), wszFormat, m_cFiles, m_cFolders);
+ SetDlgItemTextW(hwndDlg, 14027, wszBuf);
+ }
+
+ FindClose(hFind);
+ return TRUE;
+}