https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c6ed215eef9727d0bd0617...
commit c6ed215eef9727d0bd0617f3cf21d7e255b19c6f Author: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com AuthorDate: Mon Feb 10 15:57:30 2020 +0900 Commit: GitHub noreply@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; +}