1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
4  * PURPOSE:         Test for SHLimitInputEdit
5  * PROGRAMMER:      Katayama Hirofumi MZ
6  */
7 
8 #include "shelltest.h"
9 #include <shobjidl.h>
10 #include <shlwapi.h>
11 
12 class CShellFolder
13     : public IShellFolder
14     , public IItemNameLimits
15 {
16 public:
17     LONG m_cRefs;
18 
CShellFolder(INT iMaxNameLen=0,BOOL bDisabled=FALSE)19     CShellFolder(INT iMaxNameLen = 0, BOOL bDisabled = FALSE)
20         : m_cRefs(1)
21         , m_iMaxNameLen(iMaxNameLen)
22         , m_bDisabled(bDisabled)
23     {
24         trace("CShellFolder\n");
25     }
26 
~CShellFolder()27     virtual ~CShellFolder()
28     {
29         trace("~CShellFolder\n");
30     }
31 
32     /*** IUnknown methods ***/
33 
34     STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
35     STDMETHODIMP_(ULONG) AddRef();
36     STDMETHODIMP_(ULONG) Release();
37 
38     /*** IShellFolder methods ***/
39 
ParseDisplayName(HWND hwnd,IBindCtx * pbc,LPWSTR pszDisplayName,ULONG * pchEaten,PIDLIST_RELATIVE * ppidl,ULONG * pdwAttributes)40     STDMETHODIMP ParseDisplayName(
41         HWND hwnd,
42         IBindCtx *pbc,
43         LPWSTR pszDisplayName,
44         ULONG *pchEaten,
45         PIDLIST_RELATIVE *ppidl,
46         ULONG *pdwAttributes)
47     {
48         trace("ParseDisplayName\n");
49         return E_NOTIMPL;
50     }
51 
EnumObjects(HWND hwnd,SHCONTF grfFlags,IEnumIDList ** ppenumIDList)52     STDMETHODIMP EnumObjects(
53         HWND hwnd,
54         SHCONTF grfFlags,
55         IEnumIDList **ppenumIDList)
56     {
57         trace("EnumObjects\n");
58         return E_NOTIMPL;
59     }
60 
BindToObject(PCUIDLIST_RELATIVE pidl,IBindCtx * pbc,REFIID riid,void ** ppv)61     STDMETHODIMP BindToObject(
62         PCUIDLIST_RELATIVE pidl,
63         IBindCtx *pbc,
64         REFIID riid,
65         void **ppv)
66     {
67         trace("BindToObject\n");
68         return E_NOTIMPL;
69     }
70 
BindToStorage(PCUIDLIST_RELATIVE pidl,IBindCtx * pbc,REFIID riid,void ** ppv)71     STDMETHODIMP BindToStorage(
72         PCUIDLIST_RELATIVE pidl,
73         IBindCtx *pbc,
74         REFIID riid,
75         void **ppv)
76     {
77         trace("BindToStorage\n");
78         return E_NOTIMPL;
79     }
80 
CompareIDs(LPARAM lParam,PCUIDLIST_RELATIVE pidl1,PCUIDLIST_RELATIVE pidl2)81     STDMETHODIMP CompareIDs(
82         LPARAM lParam,
83         PCUIDLIST_RELATIVE pidl1,
84         PCUIDLIST_RELATIVE pidl2)
85     {
86         trace("CompareIDs\n");
87         return E_NOTIMPL;
88     }
89 
CreateViewObject(HWND hwndOwner,REFIID riid,void ** ppv)90     STDMETHODIMP CreateViewObject(
91         HWND hwndOwner,
92         REFIID riid,
93         void **ppv)
94     {
95         trace("CreateViewObject\n");
96         return E_NOTIMPL;
97     }
98 
GetAttributesOf(UINT cidl,PCUITEMID_CHILD_ARRAY apidl,SFGAOF * rgfInOut)99     STDMETHODIMP GetAttributesOf(
100         UINT cidl,
101         PCUITEMID_CHILD_ARRAY apidl,
102         SFGAOF *rgfInOut)
103     {
104         trace("GetAttributesOf\n");
105         return E_NOTIMPL;
106     }
107 
GetUIObjectOf(HWND hwndOwner,UINT cidl,PCUITEMID_CHILD_ARRAY apidl,REFIID riid,UINT * rgfReserved,void ** ppv)108     STDMETHODIMP GetUIObjectOf(
109         HWND hwndOwner,
110         UINT cidl,
111         PCUITEMID_CHILD_ARRAY apidl,
112         REFIID riid,
113         UINT *rgfReserved,
114         void **ppv)
115     {
116         trace("GetUIObjectOf\n");
117         return E_NOTIMPL;
118     }
119 
GetDisplayNameOf(PCUITEMID_CHILD pidl,SHGDNF uFlags,STRRET * pName)120     STDMETHODIMP GetDisplayNameOf(
121         PCUITEMID_CHILD pidl,
122         SHGDNF uFlags,
123         STRRET *pName)
124     {
125         trace("GetDisplayNameOf\n");
126         return E_NOTIMPL;
127     }
128 
SetNameOf(HWND hwnd,PCUITEMID_CHILD pidl,LPCWSTR pszName,SHGDNF uFlags,PITEMID_CHILD * ppidlOut)129     STDMETHODIMP SetNameOf(
130         HWND hwnd,
131         PCUITEMID_CHILD pidl,
132         LPCWSTR pszName,
133         SHGDNF uFlags,
134         PITEMID_CHILD *ppidlOut)
135     {
136         trace("SetNameOf\n");
137         return E_NOTIMPL;
138     }
139 
140     /*** IItemNameLimits methods ***/
141 
142     STDMETHODIMP GetMaxLength(
143         LPCWSTR pszName,
144         int *piMaxNameLen);
145 
146     STDMETHODIMP GetValidCharacters(
147         LPWSTR *ppwszValidChars,
148         LPWSTR *ppwszInvalidChars);
149 
150 protected:
151     INT m_iMaxNameLen;
152     BOOL m_bDisabled;
153 };
154 
QueryInterface(REFIID riid,void ** ppvObject)155 STDMETHODIMP CShellFolder::QueryInterface(REFIID riid, void **ppvObject)
156 {
157     trace("QueryInterface\n");
158 
159     if (!ppvObject)
160         return E_POINTER;
161 
162     if (IsEqualIID(riid, IID_IShellFolder) || IsEqualIID(riid, IID_IUnknown))
163     {
164         trace("IID_IShellFolder\n");
165         *ppvObject = static_cast<IShellFolder *>(this);
166         AddRef();
167         return S_OK;
168     }
169     if (IsEqualIID(riid, IID_IItemNameLimits))
170     {
171         trace("IID_IItemNameLimits\n");
172         *ppvObject = static_cast<IItemNameLimits *>(this);
173         AddRef();
174         return S_OK;
175     }
176 
177     return E_NOINTERFACE;
178 }
179 
STDMETHODIMP_(ULONG)180 STDMETHODIMP_(ULONG) CShellFolder::AddRef()
181 {
182     trace("AddRef\n");
183     return ++m_cRefs;
184 }
185 
STDMETHODIMP_(ULONG)186 STDMETHODIMP_(ULONG) CShellFolder::Release()
187 {
188     trace("Release\n");
189 
190     if (--m_cRefs == 0)
191     {
192         //delete this;
193         return 0;
194     }
195     return m_cRefs;
196 }
197 
GetMaxLength(LPCWSTR pszName,int * piMaxNameLen)198 STDMETHODIMP CShellFolder::GetMaxLength(
199     LPCWSTR pszName,
200     int *piMaxNameLen)
201 {
202     trace("GetMaxLength('%S', %p (%d))\n", pszName, piMaxNameLen, *piMaxNameLen);
203 
204     if (!piMaxNameLen)
205         return E_POINTER;
206 
207     *piMaxNameLen = m_iMaxNameLen;
208     return S_OK;
209 }
210 
GetValidCharacters(LPWSTR * ppwszValidChars,LPWSTR * ppwszInvalidChars)211 STDMETHODIMP CShellFolder::GetValidCharacters(
212     LPWSTR *ppwszValidChars,
213     LPWSTR *ppwszInvalidChars)
214 {
215     trace("GetValidCharacters(%p, %p)\n", ppwszValidChars, ppwszInvalidChars);
216 
217     if (m_bDisabled)
218         return E_NOTIMPL;
219 
220     if (ppwszInvalidChars)
221     {
222         SHStrDupW(L"/:*?\"<>|", ppwszInvalidChars);
223     }
224     if (ppwszValidChars)
225     {
226         *ppwszValidChars = NULL;
227     }
228     return S_OK;
229 }
230 
231 static BOOL CALLBACK
PropEnumProc(HWND hwnd,LPCWSTR lpszString,HANDLE hData)232 PropEnumProc(
233     HWND hwnd,
234     LPCWSTR lpszString,
235     HANDLE hData)
236 {
237     trace("PropEnumProc: '%S' --> %p\n", lpszString, hData);
238     return TRUE;
239 }
240 
241 static void
DoNullFolderTest(HWND hEdt1)242 DoNullFolderTest(HWND hEdt1)
243 {
244     HRESULT hr;
245 
246     _SEH2_TRY
247     {
248         hr = SHLimitInputEdit(hEdt1, NULL);
249     }
250     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
251     {
252         hr = 0xDEAD;
253     }
254     _SEH2_END;
255 
256     ok_int(hr, 0xDEAD);
257 }
258 
259 static INT_PTR CALLBACK
DialogProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)260 DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
261 {
262     if (uMsg != WM_INITDIALOG)
263         return FALSE;
264 
265     HWND hEdt1 = GetDlgItem(hwnd, edt1);
266     INT n;
267     HRESULT hr;
268     WCHAR szText[64];
269 
270     DoNullFolderTest(hEdt1);
271 
272     {
273         CShellFolder sf(123, FALSE);
274 
275         ok_long(sf.m_cRefs, 1);
276 
277         SendMessageW(hEdt1, EM_LIMITTEXT, 234, 0);
278 
279         trace("GWLP_WNDPROC: %p\n", (void *)GetWindowLongPtr(hEdt1, GWLP_WNDPROC));
280 
281         hr = SHLimitInputEdit(hEdt1, &sf);
282         ok_int(hr, S_OK);
283 
284         ok_long(sf.m_cRefs, 1);
285 
286         trace("GWLP_WNDPROC: %p\n", (void *)GetWindowLongPtr(hEdt1, GWLP_WNDPROC));
287 
288         EnumPropsW(hEdt1, PropEnumProc);
289 
290         n = (INT)SendMessageW(hEdt1, EM_GETLIMITTEXT, 0, 0);
291         ok_int(n, 234);
292     }
293 
294     {
295         CShellFolder sf(345, TRUE);
296 
297         hr = SHLimitInputEdit(hEdt1, &sf);
298         ok_int(hr, E_NOTIMPL);
299 
300         n = (INT)SendMessageW(hEdt1, EM_GETLIMITTEXT, 0, 0);
301         ok_int(n, 234);
302     }
303 
304     {
305         CShellFolder sf(999, FALSE);
306 
307         ok_long(sf.m_cRefs, 1);
308 
309         SetWindowTextW(hEdt1, L"TEST/TEST");
310         hr = SHLimitInputEdit(hEdt1, &sf);
311         ok_int(hr, S_OK);
312         GetWindowTextW(hEdt1, szText, _countof(szText));
313         ok_wstr(szText, L"TEST/TEST");
314 
315         ok_long(sf.m_cRefs, 1);
316 
317         n = (INT)SendMessageW(hEdt1, EM_GETLIMITTEXT, 0, 0);
318         ok_int(n, 234);
319 
320         SetWindowTextW(hEdt1, L"");
321         SendMessageW(hEdt1, WM_CHAR, L'A', 1);
322         GetWindowTextW(hEdt1, szText, _countof(szText));
323         ok_wstr(szText, L"A");
324 
325         SendMessageW(hEdt1, WM_CHAR, L'/', 1);
326         GetWindowTextW(hEdt1, szText, _countof(szText));
327         ok_wstr(szText, L"A");
328 
329         SendMessageW(hEdt1, WM_CHAR, L'/', 1);
330         GetWindowTextW(hEdt1, szText, _countof(szText));
331         ok_wstr(szText, L"A");
332 
333         SendMessageW(hEdt1, WM_CHAR, L'A', 1);
334         GetWindowTextW(hEdt1, szText, _countof(szText));
335         ok_wstr(szText, L"AA");
336     }
337 
338     {
339         CShellFolder sf(4, FALSE);
340 
341         ok_long(sf.m_cRefs, 1);
342 
343         SetWindowTextW(hEdt1, L"ABC");
344         hr = SHLimitInputEdit(hEdt1, &sf);
345 
346         SendMessageW(hEdt1, WM_CHAR, L'D', 1);
347         GetWindowTextW(hEdt1, szText, _countof(szText));
348         ok_wstr(szText, L"DABC");
349 
350         SendMessageW(hEdt1, WM_CHAR, L'E', 1);
351         GetWindowTextW(hEdt1, szText, _countof(szText));
352         ok_wstr(szText, L"DEABC");
353 
354         ok_long(sf.m_cRefs, 1);
355     }
356 
357     EndDialog(hwnd, IDABORT);
358     return TRUE;
359 }
360 
START_TEST(SHLimitInputEdit)361 START_TEST(SHLimitInputEdit)
362 {
363     HRESULT hr;
364 
365     _SEH2_TRY
366     {
367         hr = SHLimitInputEdit(NULL, NULL);
368     }
369     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
370     {
371         hr = 0xDEAD;
372     }
373     _SEH2_END;
374     ok_int(hr, 0xDEAD);
375 
376     _SEH2_TRY
377     {
378         hr = SHLimitInputEdit((HWND)0xDEAD, NULL);
379     }
380     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
381     {
382         hr = 0xDEAD;
383     }
384     _SEH2_END;
385     ok_int(hr, 0xDEAD);
386 
387     DialogBoxW(GetModuleHandleW(NULL), L"SHLIMIT", NULL, DialogProc);
388 }
389