mirror of
https://github.com/reactos/reactos.git
synced 2024-07-01 02:10:07 +00:00
[SHELL32] Optimize change notification (#3030)
- Keep the directory lists only. - Don't remember file sizes and normal file paths. CORE-13950
This commit is contained in:
parent
1c40070561
commit
1f31905ecd
122
dll/win32/shell32/shelldesktop/CDirectoryList.cpp
Normal file
122
dll/win32/shell32/shelldesktop/CDirectoryList.cpp
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: shell32
|
||||||
|
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
||||||
|
* PURPOSE: Shell change notification
|
||||||
|
* COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||||
|
*/
|
||||||
|
#include "shelldesktop.h"
|
||||||
|
#include "CDirectoryList.h"
|
||||||
|
#include <assert.h> // for assert
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(shcn);
|
||||||
|
|
||||||
|
BOOL CDirectoryList::ContainsPath(LPCWSTR pszPath) const
|
||||||
|
{
|
||||||
|
assert(!PathIsRelativeW(pszPath));
|
||||||
|
|
||||||
|
for (INT i = 0; i < m_items.GetSize(); ++i)
|
||||||
|
{
|
||||||
|
if (m_items[i].IsEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (m_items[i].EqualPath(pszPath))
|
||||||
|
return TRUE; // matched
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL CDirectoryList::AddPath(LPCWSTR pszPath)
|
||||||
|
{
|
||||||
|
assert(!PathIsRelativeW(pszPath));
|
||||||
|
return m_items.Add(pszPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL CDirectoryList::RenamePath(LPCWSTR pszPath1, LPCWSTR pszPath2)
|
||||||
|
{
|
||||||
|
assert(!PathIsRelativeW(pszPath1));
|
||||||
|
assert(!PathIsRelativeW(pszPath2));
|
||||||
|
|
||||||
|
for (INT i = 0; i < m_items.GetSize(); ++i)
|
||||||
|
{
|
||||||
|
if (m_items[i].EqualPath(pszPath1))
|
||||||
|
{
|
||||||
|
// matched
|
||||||
|
m_items[i].SetPath(pszPath2);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL CDirectoryList::DeletePath(LPCWSTR pszPath)
|
||||||
|
{
|
||||||
|
assert(!PathIsRelativeW(pszPath));
|
||||||
|
|
||||||
|
for (INT i = 0; i < m_items.GetSize(); ++i)
|
||||||
|
{
|
||||||
|
if (m_items[i].EqualPath(pszPath))
|
||||||
|
{
|
||||||
|
// matched
|
||||||
|
m_items[i].SetPath(NULL);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL CDirectoryList::AddPathsFromDirectory(LPCWSTR pszDirectoryPath)
|
||||||
|
{
|
||||||
|
// get the full path
|
||||||
|
WCHAR szPath[MAX_PATH];
|
||||||
|
lstrcpynW(szPath, pszDirectoryPath, _countof(szPath));
|
||||||
|
assert(!PathIsRelativeW(szPath));
|
||||||
|
|
||||||
|
// is it a directory?
|
||||||
|
if (!PathIsDirectoryW(szPath))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// add the path
|
||||||
|
if (!AddPath(szPath))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// enumerate the file items to remember
|
||||||
|
PathAppendW(szPath, L"*");
|
||||||
|
WIN32_FIND_DATAW find;
|
||||||
|
HANDLE hFind = FindFirstFileW(szPath, &find);
|
||||||
|
if (hFind == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
ERR("FindFirstFileW failed\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPWSTR pch;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// ignore "." and ".."
|
||||||
|
pch = find.cFileName;
|
||||||
|
if (pch[0] == L'.' && (pch[1] == 0 || (pch[1] == L'.' && pch[2] == 0)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// build a path
|
||||||
|
PathRemoveFileSpecW(szPath);
|
||||||
|
if (lstrlenW(szPath) + lstrlenW(find.cFileName) + 1 > MAX_PATH)
|
||||||
|
{
|
||||||
|
ERR("szPath is too long\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
PathAppendW(szPath, find.cFileName);
|
||||||
|
|
||||||
|
// add the path and do recurse
|
||||||
|
if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
{
|
||||||
|
if (m_fRecursive)
|
||||||
|
AddPathsFromDirectory(szPath);
|
||||||
|
else
|
||||||
|
AddPath(szPath);
|
||||||
|
}
|
||||||
|
} while (FindNextFileW(hFind, &find));
|
||||||
|
|
||||||
|
FindClose(hFind);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
93
dll/win32/shell32/shelldesktop/CDirectoryList.h
Normal file
93
dll/win32/shell32/shelldesktop/CDirectoryList.h
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <atlsimpcoll.h> // for CSimpleArray
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// A pathname with info
|
||||||
|
class CDirectoryItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CDirectoryItem() : m_pszPath(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CDirectoryItem(LPCWSTR pszPath)
|
||||||
|
{
|
||||||
|
m_pszPath = _wcsdup(pszPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
CDirectoryItem(const CDirectoryItem& item)
|
||||||
|
: m_pszPath(_wcsdup(item.m_pszPath))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CDirectoryItem& operator=(const CDirectoryItem& item)
|
||||||
|
{
|
||||||
|
if (this != &item)
|
||||||
|
{
|
||||||
|
free(m_pszPath);
|
||||||
|
m_pszPath = _wcsdup(item.m_pszPath);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~CDirectoryItem()
|
||||||
|
{
|
||||||
|
free(m_pszPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL IsEmpty() const
|
||||||
|
{
|
||||||
|
return m_pszPath == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPCWSTR GetPath() const
|
||||||
|
{
|
||||||
|
return m_pszPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPath(LPCWSTR pszPath)
|
||||||
|
{
|
||||||
|
free(m_pszPath);
|
||||||
|
m_pszPath = _wcsdup(pszPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL EqualPath(LPCWSTR pszPath) const
|
||||||
|
{
|
||||||
|
return m_pszPath != NULL && lstrcmpiW(m_pszPath, pszPath) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
LPWSTR m_pszPath; // A full path, malloc'ed
|
||||||
|
};
|
||||||
|
|
||||||
|
// the directory list
|
||||||
|
class CDirectoryList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CDirectoryList() : m_fRecursive(FALSE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CDirectoryList(LPCWSTR pszDirectoryPath, BOOL fRecursive)
|
||||||
|
: m_fRecursive(fRecursive)
|
||||||
|
{
|
||||||
|
AddPathsFromDirectory(pszDirectoryPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL ContainsPath(LPCWSTR pszPath) const;
|
||||||
|
BOOL AddPath(LPCWSTR pszPath);
|
||||||
|
BOOL AddPathsFromDirectory(LPCWSTR pszDirectoryPath);
|
||||||
|
BOOL RenamePath(LPCWSTR pszPath1, LPCWSTR pszPath2);
|
||||||
|
BOOL DeletePath(LPCWSTR pszPath);
|
||||||
|
|
||||||
|
void RemoveAll()
|
||||||
|
{
|
||||||
|
m_items.RemoveAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BOOL m_fRecursive;
|
||||||
|
CSimpleArray<CDirectoryItem> m_items;
|
||||||
|
};
|
|
@ -71,7 +71,7 @@ static void NTAPI _RequestAllTerminationAPC(ULONG_PTR Parameter)
|
||||||
CDirectoryWatcher::CDirectoryWatcher(LPCWSTR pszDirectoryPath, BOOL fSubTree)
|
CDirectoryWatcher::CDirectoryWatcher(LPCWSTR pszDirectoryPath, BOOL fSubTree)
|
||||||
: m_fDead(FALSE)
|
: m_fDead(FALSE)
|
||||||
, m_fRecursive(fSubTree)
|
, m_fRecursive(fSubTree)
|
||||||
, m_file_list(pszDirectoryPath, fSubTree)
|
, m_dir_list(pszDirectoryPath, fSubTree)
|
||||||
{
|
{
|
||||||
TRACE("CDirectoryWatcher::CDirectoryWatcher: %p, '%S'\n", this, pszDirectoryPath);
|
TRACE("CDirectoryWatcher::CDirectoryWatcher: %p, '%S'\n", this, pszDirectoryPath);
|
||||||
|
|
||||||
|
@ -139,24 +139,6 @@ void CDirectoryWatcher::ProcessNotification()
|
||||||
DWORD dwEvent, cbName;
|
DWORD dwEvent, cbName;
|
||||||
BOOL fDir;
|
BOOL fDir;
|
||||||
|
|
||||||
// if the watch is recursive
|
|
||||||
if (m_fRecursive)
|
|
||||||
{
|
|
||||||
// get the first change
|
|
||||||
if (!m_file_list.GetFirstChange(szPath))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// then, notify a SHCNE_UPDATEDIR
|
|
||||||
if (lstrcmpiW(m_szDirectoryPath, szPath) != 0)
|
|
||||||
PathRemoveFileSpecW(szPath);
|
|
||||||
NotifyFileSystemChange(SHCNE_UPDATEDIR, szPath, NULL);
|
|
||||||
|
|
||||||
// refresh directory list
|
|
||||||
m_file_list.RemoveAll();
|
|
||||||
m_file_list.AddPathsFromDirectory(m_szDirectoryPath, TRUE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// for each entry in s_buffer
|
// for each entry in s_buffer
|
||||||
szPath[0] = szTempPath[0] = 0;
|
szPath[0] = szTempPath[0] = 0;
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -188,37 +170,37 @@ void CDirectoryWatcher::ProcessNotification()
|
||||||
dwEvent = ConvertActionToEvent(pInfo->Action, fDir);
|
dwEvent = ConvertActionToEvent(pInfo->Action, fDir);
|
||||||
|
|
||||||
// convert SHCNE_DELETE to SHCNE_RMDIR if the path is a directory
|
// convert SHCNE_DELETE to SHCNE_RMDIR if the path is a directory
|
||||||
if (!fDir && (dwEvent == SHCNE_DELETE) && m_file_list.ContainsPath(szPath, TRUE))
|
if (!fDir && (dwEvent == SHCNE_DELETE) && m_dir_list.ContainsPath(szPath))
|
||||||
{
|
{
|
||||||
fDir = TRUE;
|
fDir = TRUE;
|
||||||
dwEvent = SHCNE_RMDIR;
|
dwEvent = SHCNE_RMDIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update m_file_list
|
// update m_dir_list
|
||||||
switch (dwEvent)
|
switch (dwEvent)
|
||||||
{
|
{
|
||||||
case SHCNE_MKDIR:
|
case SHCNE_MKDIR:
|
||||||
if (!m_file_list.AddPath(szPath, 0, TRUE))
|
if (!PathIsDirectoryW(szPath) || !m_dir_list.AddPath(szPath))
|
||||||
dwEvent = 0;
|
dwEvent = 0;
|
||||||
break;
|
break;
|
||||||
case SHCNE_CREATE:
|
case SHCNE_CREATE:
|
||||||
if (!m_file_list.AddPath(szPath, INVALID_FILE_SIZE, FALSE))
|
if (!PathFileExistsW(szPath) || PathIsDirectoryW(szPath))
|
||||||
dwEvent = 0;
|
dwEvent = 0;
|
||||||
break;
|
break;
|
||||||
case SHCNE_RENAMEFOLDER:
|
case SHCNE_RENAMEFOLDER:
|
||||||
if (!m_file_list.RenamePath(szTempPath, szPath, TRUE))
|
if (!PathIsDirectoryW(szPath) || !m_dir_list.RenamePath(szTempPath, szPath))
|
||||||
dwEvent = 0;
|
dwEvent = 0;
|
||||||
break;
|
break;
|
||||||
case SHCNE_RENAMEITEM:
|
case SHCNE_RENAMEITEM:
|
||||||
if (!m_file_list.RenamePath(szTempPath, szPath, FALSE))
|
if (!PathFileExistsW(szPath) || PathIsDirectoryW(szPath))
|
||||||
dwEvent = 0;
|
dwEvent = 0;
|
||||||
break;
|
break;
|
||||||
case SHCNE_RMDIR:
|
case SHCNE_RMDIR:
|
||||||
if (!m_file_list.DeletePath(szPath, TRUE))
|
if (PathIsDirectoryW(szPath) || !m_dir_list.DeletePath(szPath))
|
||||||
dwEvent = 0;
|
dwEvent = 0;
|
||||||
break;
|
break;
|
||||||
case SHCNE_DELETE:
|
case SHCNE_DELETE:
|
||||||
if (!m_file_list.DeletePath(szPath, FALSE))
|
if (PathFileExistsW(szPath))
|
||||||
dwEvent = 0;
|
dwEvent = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CFilePathList.h"
|
#include "CDirectoryList.h"
|
||||||
|
|
||||||
// NOTE: Regard to asynchronous procedure call (APC), please see:
|
// NOTE: Regard to asynchronous procedure call (APC), please see:
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleepex
|
// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleepex
|
||||||
|
@ -31,7 +31,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
BOOL m_fDead;
|
BOOL m_fDead;
|
||||||
BOOL m_fRecursive;
|
BOOL m_fRecursive;
|
||||||
CFilePathList m_file_list;
|
CDirectoryList m_dir_list;
|
||||||
OVERLAPPED m_overlapped;
|
OVERLAPPED m_overlapped;
|
||||||
|
|
||||||
BOOL CreateAPCThread();
|
BOOL CreateAPCThread();
|
||||||
|
|
|
@ -1,192 +0,0 @@
|
||||||
/*
|
|
||||||
* PROJECT: shell32
|
|
||||||
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
|
||||||
* PURPOSE: Shell change notification
|
|
||||||
* COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
|
||||||
*/
|
|
||||||
#include "shelldesktop.h"
|
|
||||||
#include "CFilePathList.h"
|
|
||||||
#include <assert.h> // for assert
|
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(shcn);
|
|
||||||
|
|
||||||
BOOL CFilePathList::ContainsPath(LPCWSTR pszPath, BOOL fIsDirectory) const
|
|
||||||
{
|
|
||||||
assert(!PathIsRelativeW(pszPath));
|
|
||||||
|
|
||||||
for (INT i = 0; i < m_items.GetSize(); ++i)
|
|
||||||
{
|
|
||||||
if (m_items[i].IsEmpty() || fIsDirectory != m_items[i].IsDirectory())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (m_items[i].EqualPath(pszPath))
|
|
||||||
return TRUE; // matched
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DWORD GetSizeOfFile(LPCWSTR pszPath)
|
|
||||||
{
|
|
||||||
WIN32_FIND_DATAW find;
|
|
||||||
HANDLE hFind = FindFirstFileW(pszPath, &find);
|
|
||||||
if (hFind == INVALID_HANDLE_VALUE)
|
|
||||||
return FALSE;
|
|
||||||
FindClose(hFind);
|
|
||||||
return find.nFileSizeLow;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL CFilePathList::AddPath(LPCWSTR pszPath, DWORD dwFileSize, BOOL fIsDirectory)
|
|
||||||
{
|
|
||||||
assert(!PathIsRelativeW(pszPath));
|
|
||||||
|
|
||||||
if (dwFileSize == INVALID_FILE_SIZE)
|
|
||||||
{
|
|
||||||
dwFileSize = GetSizeOfFile(pszPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
CFilePathItem item(pszPath, dwFileSize, fIsDirectory);
|
|
||||||
return m_items.Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL CFilePathList::RenamePath(LPCWSTR pszPath1, LPCWSTR pszPath2, BOOL fIsDirectory)
|
|
||||||
{
|
|
||||||
assert(!PathIsRelativeW(pszPath1));
|
|
||||||
assert(!PathIsRelativeW(pszPath2));
|
|
||||||
|
|
||||||
for (INT i = 0; i < m_items.GetSize(); ++i)
|
|
||||||
{
|
|
||||||
if (m_items[i].IsDirectory() == fIsDirectory && m_items[i].EqualPath(pszPath1))
|
|
||||||
{
|
|
||||||
// matched
|
|
||||||
m_items[i].SetPath(pszPath2);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL CFilePathList::DeletePath(LPCWSTR pszPath, BOOL fIsDirectory)
|
|
||||||
{
|
|
||||||
assert(!PathIsRelativeW(pszPath));
|
|
||||||
|
|
||||||
for (INT i = 0; i < m_items.GetSize(); ++i)
|
|
||||||
{
|
|
||||||
if (m_items[i].IsDirectory() == fIsDirectory && m_items[i].EqualPath(pszPath))
|
|
||||||
{
|
|
||||||
// matched
|
|
||||||
m_items[i].SetPath(NULL);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL CFilePathList::AddPathsFromDirectory(LPCWSTR pszDirectoryPath, BOOL fRecursive)
|
|
||||||
{
|
|
||||||
// get the full path
|
|
||||||
WCHAR szPath[MAX_PATH];
|
|
||||||
lstrcpynW(szPath, pszDirectoryPath, _countof(szPath));
|
|
||||||
assert(!PathIsRelativeW(szPath));
|
|
||||||
|
|
||||||
// is it a directory?
|
|
||||||
if (!PathIsDirectoryW(szPath))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
// add the path
|
|
||||||
if (!AddPath(szPath, 0, TRUE))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
// enumerate the file items to remember
|
|
||||||
PathAppendW(szPath, L"*");
|
|
||||||
WIN32_FIND_DATAW find;
|
|
||||||
HANDLE hFind = FindFirstFileW(szPath, &find);
|
|
||||||
if (hFind == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
ERR("FindFirstFileW failed\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// ignore "." and ".."
|
|
||||||
if (lstrcmpW(find.cFileName, L".") == 0 ||
|
|
||||||
lstrcmpW(find.cFileName, L"..") == 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// build a path
|
|
||||||
PathRemoveFileSpecW(szPath);
|
|
||||||
if (lstrlenW(szPath) + lstrlenW(find.cFileName) + 1 > MAX_PATH)
|
|
||||||
{
|
|
||||||
ERR("szPath is too long\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
PathAppendW(szPath, find.cFileName);
|
|
||||||
|
|
||||||
BOOL fIsDirectory = !!(find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
|
||||||
|
|
||||||
// add the path and do recurse
|
|
||||||
if (fRecursive && fIsDirectory)
|
|
||||||
AddPathsFromDirectory(szPath, fRecursive);
|
|
||||||
else
|
|
||||||
AddPath(szPath, find.nFileSizeLow, fIsDirectory);
|
|
||||||
} while (FindNextFileW(hFind, &find));
|
|
||||||
|
|
||||||
FindClose(hFind);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL CFilePathList::GetFirstChange(LPWSTR pszPath) const
|
|
||||||
{
|
|
||||||
// validate paths
|
|
||||||
for (INT i = 0; i < m_items.GetSize(); ++i)
|
|
||||||
{
|
|
||||||
if (m_items[i].IsEmpty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (m_items[i].IsDirectory()) // item is a directory
|
|
||||||
{
|
|
||||||
if (!PathIsDirectoryW(m_items[i].GetPath()))
|
|
||||||
{
|
|
||||||
// mismatched
|
|
||||||
lstrcpynW(pszPath, m_items[i].GetPath(), MAX_PATH);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // item is a normal file
|
|
||||||
{
|
|
||||||
if (!PathFileExistsW(m_items[i].GetPath()) ||
|
|
||||||
PathIsDirectoryW(m_items[i].GetPath()))
|
|
||||||
{
|
|
||||||
// mismatched
|
|
||||||
lstrcpynW(pszPath, m_items[i].GetPath(), MAX_PATH);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check sizes
|
|
||||||
HANDLE hFind;
|
|
||||||
WIN32_FIND_DATAW find;
|
|
||||||
for (INT i = 0; i < m_items.GetSize(); ++i)
|
|
||||||
{
|
|
||||||
if (m_items[i].IsEmpty() || m_items[i].IsDirectory())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// get size
|
|
||||||
hFind = FindFirstFileW(m_items[i].GetPath(), &find);
|
|
||||||
FindClose(hFind);
|
|
||||||
|
|
||||||
if (hFind == INVALID_HANDLE_VALUE ||
|
|
||||||
find.nFileSizeLow != m_items[i].GetSize())
|
|
||||||
{
|
|
||||||
// different size
|
|
||||||
lstrcpynW(pszPath, m_items[i].GetPath(), MAX_PATH);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
|
@ -1,108 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <atlsimpcoll.h> // for CSimpleArray
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// A pathname with info
|
|
||||||
class CFilePathItem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CFilePathItem() : m_pszPath(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CFilePathItem(LPCWSTR pszPath, DWORD dwFileSize, BOOL IsDirectory)
|
|
||||||
{
|
|
||||||
m_pszPath = _wcsdup(pszPath);
|
|
||||||
m_dwFileSize = dwFileSize;
|
|
||||||
m_fIsDirectory = IsDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
CFilePathItem(const CFilePathItem& item)
|
|
||||||
: m_pszPath(_wcsdup(item.m_pszPath))
|
|
||||||
, m_dwFileSize(item.m_dwFileSize)
|
|
||||||
, m_fIsDirectory(item.m_fIsDirectory)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CFilePathItem& operator=(const CFilePathItem& item)
|
|
||||||
{
|
|
||||||
free(m_pszPath);
|
|
||||||
m_pszPath = _wcsdup(item.m_pszPath);
|
|
||||||
m_dwFileSize = item.m_dwFileSize;
|
|
||||||
m_fIsDirectory = item.m_fIsDirectory;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
~CFilePathItem()
|
|
||||||
{
|
|
||||||
free(m_pszPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL IsEmpty() const
|
|
||||||
{
|
|
||||||
return m_pszPath == NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL IsDirectory() const
|
|
||||||
{
|
|
||||||
return m_fIsDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPCWSTR GetPath() const
|
|
||||||
{
|
|
||||||
return m_pszPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetPath(LPCWSTR pszPath)
|
|
||||||
{
|
|
||||||
free(m_pszPath);
|
|
||||||
m_pszPath = _wcsdup(pszPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL EqualPath(LPCWSTR pszPath) const
|
|
||||||
{
|
|
||||||
return m_pszPath != NULL && lstrcmpiW(m_pszPath, pszPath) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD GetSize() const
|
|
||||||
{
|
|
||||||
return m_dwFileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
LPWSTR m_pszPath; // A full path, malloc'ed
|
|
||||||
DWORD m_dwFileSize; // the size of a file
|
|
||||||
BOOL m_fIsDirectory; // is it a directory?
|
|
||||||
};
|
|
||||||
|
|
||||||
// the file list
|
|
||||||
class CFilePathList
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CFilePathList()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CFilePathList(LPCWSTR pszDirectoryPath, BOOL fRecursive)
|
|
||||||
{
|
|
||||||
AddPathsFromDirectory(pszDirectoryPath, fRecursive);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL ContainsPath(LPCWSTR pszPath, BOOL fIsDirectory) const;
|
|
||||||
BOOL GetFirstChange(LPWSTR pszPath) const;
|
|
||||||
|
|
||||||
BOOL AddPath(LPCWSTR pszPath, DWORD dwFileSize, BOOL fIsDirectory);
|
|
||||||
BOOL AddPathsFromDirectory(LPCWSTR pszDirectoryPath, BOOL fRecursive);
|
|
||||||
BOOL RenamePath(LPCWSTR pszPath1, LPCWSTR pszPath2, BOOL fIsDirectory);
|
|
||||||
BOOL DeletePath(LPCWSTR pszPath, BOOL fIsDirectory);
|
|
||||||
|
|
||||||
void RemoveAll()
|
|
||||||
{
|
|
||||||
m_items.RemoveAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
CSimpleArray<CFilePathItem> m_items;
|
|
||||||
};
|
|
|
@ -13,7 +13,7 @@ list(APPEND SOURCE
|
||||||
CChangeNotifyServer.cpp
|
CChangeNotifyServer.cpp
|
||||||
CDesktopBrowser.cpp
|
CDesktopBrowser.cpp
|
||||||
CDirectoryWatcher.cpp
|
CDirectoryWatcher.cpp
|
||||||
CFilePathList.cpp
|
CDirectoryList.cpp
|
||||||
dde.cpp)
|
dde.cpp)
|
||||||
|
|
||||||
add_library(shelldesktop ${SOURCE})
|
add_library(shelldesktop ${SOURCE})
|
||||||
|
|
Loading…
Reference in a new issue