mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +00:00
Shell Folders: Reject invalid characters (#2328)
Reject invalid input filename characters by using shell32!SHLimitInputEdit function and IItemNameLimits interface. Improve SHLimitInputEdit to sanitize paste. CORE-11701
This commit is contained in:
parent
0a7a747d87
commit
bc1519dd87
7 changed files with 219 additions and 10 deletions
|
@ -1989,9 +1989,13 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
|
|||
m_pSFParent->GetAttributesOf(1, &pidl, &dwAttr);
|
||||
if (SFGAO_CANRENAME & dwAttr)
|
||||
{
|
||||
HWND hEdit = reinterpret_cast<HWND>(m_ListView.SendMessage(LVM_GETEDITCONTROL));
|
||||
SHLimitInputEdit(hEdit, m_pSFParent);
|
||||
|
||||
m_isEditing = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,8 @@ class CDesktopFolder :
|
|||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IShellFolder2,
|
||||
public IPersistFolder2,
|
||||
public IContextMenuCB
|
||||
public IContextMenuCB,
|
||||
public IItemNameLimits
|
||||
{
|
||||
private:
|
||||
/* both paths are parsible from the desktop */
|
||||
|
@ -79,6 +80,28 @@ class CDesktopFolder :
|
|||
// IContextMenuCB
|
||||
virtual HRESULT WINAPI CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
/*** IItemNameLimits methods ***/
|
||||
|
||||
STDMETHODIMP
|
||||
GetMaxLength(LPCWSTR pszName, int *piMaxNameLen)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
GetValidCharacters(LPWSTR *ppwszValidChars, LPWSTR *ppwszInvalidChars)
|
||||
{
|
||||
if (ppwszValidChars)
|
||||
{
|
||||
*ppwszValidChars = NULL;
|
||||
}
|
||||
if (ppwszInvalidChars)
|
||||
{
|
||||
SHStrDupW(INVALID_FILETITLE_CHARACTERSW, ppwszInvalidChars);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
DECLARE_REGISTRY_RESOURCEID(IDR_SHELLDESKTOP)
|
||||
DECLARE_CENTRAL_INSTANCE_NOT_AGGREGATABLE(CDesktopFolder)
|
||||
|
||||
|
@ -90,6 +113,7 @@ class CDesktopFolder :
|
|||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IItemNameLimits, IItemNameLimits)
|
||||
END_COM_MAP()
|
||||
};
|
||||
|
||||
|
|
|
@ -29,7 +29,8 @@ class CFSFolder :
|
|||
public IShellFolder2,
|
||||
public IPersistFolder3,
|
||||
public IContextMenuCB,
|
||||
public IShellFolderViewCB
|
||||
public IShellFolderViewCB,
|
||||
public IItemNameLimits
|
||||
{
|
||||
private:
|
||||
const CLSID *m_pclsid;
|
||||
|
@ -88,6 +89,28 @@ class CFSFolder :
|
|||
// IShellFolderViewCB
|
||||
virtual HRESULT WINAPI MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
/*** IItemNameLimits methods ***/
|
||||
|
||||
STDMETHODIMP
|
||||
GetMaxLength(LPCWSTR pszName, int *piMaxNameLen)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
GetValidCharacters(LPWSTR *ppwszValidChars, LPWSTR *ppwszInvalidChars)
|
||||
{
|
||||
if (ppwszValidChars)
|
||||
{
|
||||
*ppwszValidChars = NULL;
|
||||
}
|
||||
if (ppwszInvalidChars)
|
||||
{
|
||||
SHStrDupW(INVALID_FILETITLE_CHARACTERSW, ppwszInvalidChars);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
DECLARE_REGISTRY_RESOURCEID(IDR_SHELLFSFOLDER)
|
||||
DECLARE_NOT_AGGREGATABLE(CFSFolder)
|
||||
|
||||
|
@ -101,6 +124,7 @@ class CFSFolder :
|
|||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder3, IPersistFolder3)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IShellFolderViewCB, IShellFolderViewCB)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IItemNameLimits, IItemNameLimits)
|
||||
END_COM_MAP()
|
||||
|
||||
protected:
|
||||
|
|
|
@ -26,7 +26,8 @@ class CMyDocsFolder :
|
|||
public CComCoClass<CMyDocsFolder, &CLSID_MyDocuments>,
|
||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IShellFolder2,
|
||||
public IPersistFolder2
|
||||
public IPersistFolder2,
|
||||
public IItemNameLimits
|
||||
{
|
||||
private:
|
||||
CComPtr<IShellFolder2> m_pisfInner;
|
||||
|
@ -65,6 +66,28 @@ class CMyDocsFolder :
|
|||
// IPersistFolder2
|
||||
virtual HRESULT WINAPI GetCurFolder(PIDLIST_ABSOLUTE * pidl);
|
||||
|
||||
/*** IItemNameLimits methods ***/
|
||||
|
||||
STDMETHODIMP
|
||||
GetMaxLength(LPCWSTR pszName, int *piMaxNameLen)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
GetValidCharacters(LPWSTR *ppwszValidChars, LPWSTR *ppwszInvalidChars)
|
||||
{
|
||||
if (ppwszValidChars)
|
||||
{
|
||||
*ppwszValidChars = NULL;
|
||||
}
|
||||
if (ppwszInvalidChars)
|
||||
{
|
||||
SHStrDupW(INVALID_FILETITLE_CHARACTERSW, ppwszInvalidChars);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
DECLARE_REGISTRY_RESOURCEID(IDR_MYDOCUMENTS)
|
||||
DECLARE_NOT_AGGREGATABLE(CMyDocsFolder)
|
||||
|
||||
|
@ -76,6 +99,7 @@ class CMyDocsFolder :
|
|||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IItemNameLimits, IItemNameLimits)
|
||||
END_COM_MAP()
|
||||
};
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ class CMergedFolder :
|
|||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IShellFolder2,
|
||||
public IPersistFolder2,
|
||||
public IItemNameLimits,
|
||||
public IAugmentedShellFolder3 // -- undocumented
|
||||
//public IShellService, // DEPRECATED IE4 interface: https://msdn.microsoft.com/en-us/library/windows/desktop/bb774870%28v=vs.85%29.aspx
|
||||
//public ITranslateShellChangeNotify,// -- undocumented
|
||||
|
@ -84,6 +85,7 @@ public:
|
|||
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IItemNameLimits, IItemNameLimits)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IAugmentedShellFolder, IAugmentedShellFolder)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IAugmentedShellFolder2, IAugmentedShellFolder2)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IAugmentedShellFolder3, IAugmentedShellFolder3)
|
||||
|
@ -196,6 +198,28 @@ public:
|
|||
// IPersistFolder2
|
||||
virtual HRESULT STDMETHODCALLTYPE GetCurFolder(PIDLIST_ABSOLUTE * pidl);
|
||||
|
||||
/*** IItemNameLimits methods ***/
|
||||
|
||||
STDMETHODIMP
|
||||
GetMaxLength(LPCWSTR pszName, int *piMaxNameLen)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
GetValidCharacters(LPWSTR *ppwszValidChars, LPWSTR *ppwszInvalidChars)
|
||||
{
|
||||
if (ppwszValidChars)
|
||||
{
|
||||
*ppwszValidChars = NULL;
|
||||
}
|
||||
if (ppwszInvalidChars)
|
||||
{
|
||||
SHStrDupW(INVALID_FILETITLE_CHARACTERSW, ppwszInvalidChars);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// IAugmentedShellFolder2
|
||||
virtual HRESULT STDMETHODCALLTYPE AddNameSpace(LPGUID lpGuid, IShellFolder * psf, LPCITEMIDLIST pcidl, ULONG dwUnknown);
|
||||
virtual HRESULT STDMETHODCALLTYPE GetNameSpaceID(LPCITEMIDLIST pcidl, LPGUID lpGuid);
|
||||
|
|
|
@ -2179,10 +2179,88 @@ UxSubclassInfo_Destroy(UxSubclassInfo *pInfo)
|
|||
HeapFree(GetProcessHeap(), 0, pInfo);
|
||||
}
|
||||
|
||||
static BOOL
|
||||
DoSanitizeText(LPWSTR pszSanitized, LPCWSTR pszInvalidChars, LPCWSTR pszValidChars)
|
||||
{
|
||||
LPWSTR pch1, pch2;
|
||||
BOOL bFound = FALSE;
|
||||
|
||||
for (pch1 = pch2 = pszSanitized; *pch1; ++pch1)
|
||||
{
|
||||
if (pszInvalidChars)
|
||||
{
|
||||
if (wcschr(pszInvalidChars, *pch1) != NULL)
|
||||
{
|
||||
bFound = TRUE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (pszValidChars)
|
||||
{
|
||||
if (wcschr(pszValidChars, *pch1) == NULL)
|
||||
{
|
||||
bFound = TRUE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
*pch2 = *pch1;
|
||||
++pch2;
|
||||
}
|
||||
*pch2 = 0;
|
||||
|
||||
return bFound;
|
||||
}
|
||||
|
||||
static void
|
||||
DoSanitizeClipboard(HWND hwnd, UxSubclassInfo *pInfo)
|
||||
{
|
||||
HGLOBAL hData;
|
||||
LPWSTR pszText, pszSanitized;
|
||||
DWORD cbData;
|
||||
|
||||
if (GetWindowLongPtrW(hwnd, GWL_STYLE) & ES_READONLY)
|
||||
return;
|
||||
if (!OpenClipboard(hwnd))
|
||||
return;
|
||||
|
||||
hData = GetClipboardData(CF_UNICODETEXT);
|
||||
pszText = GlobalLock(hData);
|
||||
if (!pszText)
|
||||
{
|
||||
CloseClipboard();
|
||||
return;
|
||||
}
|
||||
SHStrDupW(pszText, &pszSanitized);
|
||||
GlobalUnlock(hData);
|
||||
|
||||
if (pszSanitized &&
|
||||
DoSanitizeText(pszSanitized, pInfo->pwszInvalidChars, pInfo->pwszValidChars))
|
||||
{
|
||||
MessageBeep(0xFFFFFFFF);
|
||||
|
||||
/* Update clipboard text */
|
||||
cbData = (lstrlenW(pszSanitized) + 1) * sizeof(WCHAR);
|
||||
hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, cbData);
|
||||
pszText = GlobalLock(hData);
|
||||
if (pszText)
|
||||
{
|
||||
CopyMemory(pszText, pszSanitized, cbData);
|
||||
GlobalUnlock(hData);
|
||||
|
||||
SetClipboardData(CF_UNICODETEXT, hData);
|
||||
}
|
||||
}
|
||||
|
||||
CoTaskMemFree(pszSanitized);
|
||||
CloseClipboard();
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK
|
||||
LimitEditWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
WNDPROC fnWndProc;
|
||||
WCHAR wch;
|
||||
UxSubclassInfo *pInfo = GetPropW(hwnd, L"UxSubclassInfo");
|
||||
if (!pInfo)
|
||||
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||||
|
@ -2191,8 +2269,22 @@ LimitEditWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_KEYDOWN:
|
||||
if (GetKeyState(VK_SHIFT) < 0 && wParam == VK_INSERT)
|
||||
DoSanitizeClipboard(hwnd, pInfo);
|
||||
else if (GetKeyState(VK_CONTROL) < 0 && wParam == L'V')
|
||||
DoSanitizeClipboard(hwnd, pInfo);
|
||||
|
||||
return CallWindowProcW(fnWndProc, hwnd, uMsg, wParam, lParam);
|
||||
|
||||
case WM_PASTE:
|
||||
DoSanitizeClipboard(hwnd, pInfo);
|
||||
return CallWindowProcW(fnWndProc, hwnd, uMsg, wParam, lParam);
|
||||
|
||||
case WM_CHAR:
|
||||
{
|
||||
if (GetKeyState(VK_CONTROL) < 0 && wParam == L'V')
|
||||
break;
|
||||
|
||||
if (pInfo->pwszInvalidChars)
|
||||
{
|
||||
if (wcschr(pInfo->pwszInvalidChars, (WCHAR)wParam) != NULL)
|
||||
|
@ -2210,11 +2302,18 @@ LimitEditWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
}
|
||||
return CallWindowProcW(fnWndProc, hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
case WM_UNICHAR:
|
||||
if (wParam == UNICODE_NOCHAR)
|
||||
return TRUE;
|
||||
|
||||
/* FALL THROUGH */
|
||||
|
||||
case WM_IME_CHAR:
|
||||
{
|
||||
WCHAR wch = (WCHAR)wParam;
|
||||
wch = (WCHAR)wParam;
|
||||
if (GetKeyState(VK_CONTROL) < 0 && wch == L'V')
|
||||
break;
|
||||
|
||||
if (!IsWindowUnicode(hwnd) && HIBYTE(wch) != 0)
|
||||
{
|
||||
CHAR data[] = {HIBYTE(wch), LOBYTE(wch)};
|
||||
|
@ -2238,13 +2337,10 @@ LimitEditWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
}
|
||||
return CallWindowProcW(fnWndProc, hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
case WM_NCDESTROY:
|
||||
{
|
||||
UxSubclassInfo_Destroy(pInfo);
|
||||
return CallWindowProcW(fnWndProc, hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
default:
|
||||
return CallWindowProcW(fnWndProc, hwnd, uMsg, wParam, lParam);
|
||||
|
|
|
@ -697,6 +697,19 @@ IStream* WINAPI SHGetViewStream(LPCITEMIDLIST, DWORD, LPCTSTR, LPCTSTR, LPCTSTR)
|
|||
|
||||
EXTERN_C HRESULT WINAPI SHCreateSessionKey(REGSAM samDesired, PHKEY phKey);
|
||||
|
||||
/*****************************************************************************
|
||||
* INVALID_FILETITLE_CHARACTERS
|
||||
*/
|
||||
|
||||
#define INVALID_FILETITLE_CHARACTERSA "\\/:*?\"<>|"
|
||||
#define INVALID_FILETITLE_CHARACTERSW L"\\/:*?\"<>|"
|
||||
|
||||
#ifdef UNICODE
|
||||
#define INVALID_FILETITLE_CHARACTERS INVALID_FILETITLE_CHARACTERSW
|
||||
#else
|
||||
#define INVALID_FILETITLE_CHARACTERS INVALID_FILETITLE_CHARACTERSA
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* Shell Link
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue