https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c6ed215eef9727d0bd0617f3cf21d7e255b19c6f

commit c6ed215eef9727d0bd0617f3cf21d7e255b19c6f
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Mon Feb 10 15:57:30 2020 +0900
Commit:     GitHub <[email protected]>
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;
+}

Reply via email to