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 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 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 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 52 STDMETHODIMP EnumObjects( 53 HWND hwnd, 54 SHCONTF grfFlags, 55 IEnumIDList **ppenumIDList) 56 { 57 trace("EnumObjects\n"); 58 return E_NOTIMPL; 59 } 60 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 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 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 90 STDMETHODIMP CreateViewObject( 91 HWND hwndOwner, 92 REFIID riid, 93 void **ppv) 94 { 95 trace("CreateViewObject\n"); 96 return E_NOTIMPL; 97 } 98 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 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 120 STDMETHODIMP GetDisplayNameOf( 121 PCUITEMID_CHILD pidl, 122 SHGDNF uFlags, 123 STRRET *pName) 124 { 125 trace("GetDisplayNameOf\n"); 126 return E_NOTIMPL; 127 } 128 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 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 180 STDMETHODIMP_(ULONG) CShellFolder::AddRef() 181 { 182 trace("AddRef\n"); 183 return ++m_cRefs; 184 } 185 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 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 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 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 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 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 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