https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c6ed215eef9727d0bd061…
commit c6ed215eef9727d0bd0617f3cf21d7e255b19c6f
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Mon Feb 10 15:57:30 2020 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Mon Feb 10 15:57:30 2020 +0900
[SHELL32] Initial implement SHLimitInputEdit (#2323)
Popup balloon window is not implemented yet.
CORE-11701
---
dll/win32/shell32/stubs.cpp | 11 ---
dll/win32/shell32/wine/shellord.c | 180 +++++++++++++++++++++++++++++++++++++-
2 files changed, 179 insertions(+), 12 deletions(-)
diff --git a/dll/win32/shell32/stubs.cpp b/dll/win32/shell32/stubs.cpp
index 1c7996df8a9..3be6d2ec3b5 100644
--- a/dll/win32/shell32/stubs.cpp
+++ b/dll/win32/shell32/stubs.cpp
@@ -36,17 +36,6 @@ SHFindComputer(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
return FALSE;
}
-/*
- * Unimplemented
- */
-EXTERN_C HRESULT
-WINAPI
-SHLimitInputEdit(HWND hWnd, IShellFolder *psf)
-{
- FIXME("SHLimitInputEdit() stub\n");
- return S_FALSE;
-}
-
/*
* Unimplemented
*/
diff --git a/dll/win32/shell32/wine/shellord.c b/dll/win32/shell32/wine/shellord.c
index a8bdab0e62c..f63e0b1a59a 100644
--- a/dll/win32/shell32/wine/shellord.c
+++ b/dll/win32/shell32/wine/shellord.c
@@ -2147,4 +2147,182 @@ SHTestTokenMembership(HANDLE TokenHandle, ULONG ulRID)
BOOL WINAPI IsUserAnAdmin(VOID)
{
return SHTestTokenMembership(NULL, DOMAIN_ALIAS_RID_ADMINS);
-}
\ No newline at end of file
+}
+
+/*************************************************************************
+ * SHLimitInputEdit(SHELL32.@)
+ */
+
+/* TODO: Show baloon popup window using SetWindowRgn */
+
+typedef struct UxSubclassInfo
+{
+ HWND hwnd;
+ WNDPROC fnWndProc;
+ LPWSTR pwszValidChars;
+ LPWSTR pwszInvalidChars;
+} UxSubclassInfo;
+
+static void
+UxSubclassInfo_Destroy(UxSubclassInfo *pInfo)
+{
+ if (!pInfo)
+ return;
+
+ RemovePropW(pInfo->hwnd, L"UxSubclassInfo");
+
+ CoTaskMemFree(pInfo->pwszValidChars);
+ CoTaskMemFree(pInfo->pwszInvalidChars);
+
+ SetWindowLongPtr(pInfo->hwnd, GWLP_WNDPROC, (LONG_PTR)pInfo->fnWndProc);
+
+ HeapFree(GetProcessHeap(), 0, pInfo);
+}
+
+static LRESULT CALLBACK
+LimitEditWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ WNDPROC fnWndProc;
+ UxSubclassInfo *pInfo = GetPropW(hwnd, L"UxSubclassInfo");
+ if (!pInfo)
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+
+ fnWndProc = pInfo->fnWndProc;
+
+ switch (uMsg)
+ {
+ case WM_CHAR:
+ {
+ if (pInfo->pwszInvalidChars)
+ {
+ if (wcschr(pInfo->pwszInvalidChars, (WCHAR)wParam) != NULL)
+ {
+ MessageBeep(0xFFFFFFFF);
+ break;
+ }
+ }
+ else if (pInfo->pwszValidChars)
+ {
+ if (wcschr(pInfo->pwszValidChars, (WCHAR)wParam) == NULL)
+ {
+ MessageBeep(0xFFFFFFFF);
+ break;
+ }
+ }
+ return fnWndProc(hwnd, uMsg, wParam, lParam);
+ }
+
+ case WM_IME_CHAR:
+ {
+ WCHAR wch = (WCHAR)wParam;
+ if (!IsWindowUnicode(hwnd) && HIBYTE(wch) != 0)
+ {
+ CHAR data[] = {HIBYTE(wch), LOBYTE(wch)};
+ MultiByteToWideChar(CP_ACP, 0, data, 2, &wch, 1);
+ }
+
+ if (pInfo->pwszInvalidChars)
+ {
+ if (wcschr(pInfo->pwszInvalidChars, wch) != NULL)
+ {
+ MessageBeep(0xFFFFFFFF);
+ break;
+ }
+ }
+ else if (pInfo->pwszValidChars)
+ {
+ if (wcschr(pInfo->pwszValidChars, wch) == NULL)
+ {
+ MessageBeep(0xFFFFFFFF);
+ break;
+ }
+ }
+ return fnWndProc(hwnd, uMsg, wParam, lParam);
+ }
+
+ case WM_NCDESTROY:
+ {
+ UxSubclassInfo_Destroy(pInfo);
+ return fnWndProc(hwnd, uMsg, wParam, lParam);
+ }
+
+ default:
+ return fnWndProc(hwnd, uMsg, wParam, lParam);
+ }
+
+ return 0;
+}
+
+static UxSubclassInfo *
+UxSubclassInfo_Create(HWND hwnd, LPWSTR valid, LPWSTR invalid)
+{
+ UxSubclassInfo *pInfo;
+ pInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(UxSubclassInfo));
+ if (!pInfo)
+ {
+ ERR("HeapAlloc failed.\n");
+ CoTaskMemFree(valid);
+ CoTaskMemFree(invalid);
+ return NULL;
+ }
+
+ pInfo->fnWndProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC,
(LONG_PTR)LimitEditWindowProc);
+ if (!pInfo->fnWndProc)
+ {
+ ERR("SetWindowLongPtr failed\n");
+ CoTaskMemFree(valid);
+ CoTaskMemFree(invalid);
+ HeapFree(GetProcessHeap(), 0, pInfo);
+ return NULL;
+ }
+
+ pInfo->hwnd = hwnd;
+ pInfo->pwszValidChars = valid;
+ pInfo->pwszInvalidChars = invalid;
+ if (!SetPropW(hwnd, L"UxSubclassInfo", pInfo))
+ {
+ UxSubclassInfo_Destroy(pInfo);
+ pInfo = NULL;
+ }
+ return pInfo;
+}
+
+HRESULT WINAPI
+SHLimitInputEdit(HWND hWnd, IShellFolder *psf)
+{
+ IItemNameLimits *pLimits;
+ HRESULT hr;
+ LPWSTR pwszValidChars, pwszInvalidChars;
+ UxSubclassInfo *pInfo;
+
+ pInfo = GetPropW(hWnd, L"UxSubclassInfo");
+ if (pInfo)
+ {
+ UxSubclassInfo_Destroy(pInfo);
+ pInfo = NULL;
+ }
+
+ hr = psf->lpVtbl->QueryInterface(psf, &IID_IItemNameLimits, (LPVOID
*)&pLimits);
+ if (FAILED(hr))
+ {
+ ERR("hr: %x\n", hr);
+ return hr;
+ }
+
+ pwszValidChars = pwszInvalidChars = NULL;
+ hr = pLimits->lpVtbl->GetValidCharacters(pLimits, &pwszValidChars,
&pwszInvalidChars);
+ if (FAILED(hr))
+ {
+ ERR("hr: %x\n", hr);
+ pLimits->lpVtbl->Release(pLimits);
+ return hr;
+ }
+
+ pInfo = UxSubclassInfo_Create(hWnd, pwszValidChars, pwszInvalidChars);
+ if (!pInfo)
+ hr = E_FAIL;
+
+ pLimits->lpVtbl->Release(pLimits);
+
+ return hr;
+}