1c2c66affSColin Finck /* 2c2c66affSColin Finck * Unit test suite for comdlg32 API functions: file dialogs 3c2c66affSColin Finck * 4c2c66affSColin Finck * Copyright 2007 Google (Lei Zhang) 5c2c66affSColin Finck * 6c2c66affSColin Finck * This library is free software; you can redistribute it and/or 7c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public 8c2c66affSColin Finck * License as published by the Free Software Foundation; either 9c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version. 10c2c66affSColin Finck * 11c2c66affSColin Finck * This library is distributed in the hope that it will be useful, 12c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 13c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14c2c66affSColin Finck * Lesser General Public License for more details. 15c2c66affSColin Finck * 16c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public 17c2c66affSColin Finck * License along with this library; if not, write to the Free Software 18c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19c2c66affSColin Finck * 20c2c66affSColin Finck */ 21c2c66affSColin Finck 22da5f10afSAmine Khaldi #include <windows.h> 23da5f10afSAmine Khaldi #include <wine/test.h> 24c2c66affSColin Finck 25da5f10afSAmine Khaldi #include "shlguid.h" 26da5f10afSAmine Khaldi #define COBJMACROS 27da5f10afSAmine Khaldi #include "shobjidl.h" 28da5f10afSAmine Khaldi #include "commdlg.h" 29da5f10afSAmine Khaldi #include "cderr.h" 30da5f10afSAmine Khaldi #include "dlgs.h" 31da5f10afSAmine Khaldi 32da5f10afSAmine Khaldi #ifdef __REACTOS__ 33c2c66affSColin Finck #include <reactos/undocuser.h> 34da5f10afSAmine Khaldi #endif 35c2c66affSColin Finck 36c2c66affSColin Finck /* ##### */ 37c2c66affSColin Finck 38c2c66affSColin Finck static BOOL resizesupported = TRUE; 39c2c66affSColin Finck 40c2c66affSColin Finck static void toolbarcheck( HWND hDlg) 41c2c66affSColin Finck { 42c2c66affSColin Finck /* test toolbar properties */ 43c2c66affSColin Finck /* bug #10532 */ 44c2c66affSColin Finck int maxtextrows; 45c2c66affSColin Finck HWND ctrl; 46c2c66affSColin Finck DWORD ret; 47c2c66affSColin Finck char classname[20]; 48c2c66affSColin Finck 49c2c66affSColin Finck for( ctrl = GetWindow( hDlg, GW_CHILD); 50c2c66affSColin Finck ctrl ; ctrl = GetWindow( ctrl, GW_HWNDNEXT)) { 51c2c66affSColin Finck GetClassNameA( ctrl, classname, 10); 52c2c66affSColin Finck classname[7] = '\0'; 53c2c66affSColin Finck if( !strcmp( classname, "Toolbar")) break; 54c2c66affSColin Finck } 55c2c66affSColin Finck ok( ctrl != NULL, "could not get the toolbar control\n"); 56c2c66affSColin Finck ret = SendMessageA( ctrl, TB_ADDSTRINGA, 0, (LPARAM)"winetestwinetest\0\0"); 57c2c66affSColin Finck ok( ret == 0, "addstring returned %d (expected 0)\n", ret); 58c2c66affSColin Finck maxtextrows = SendMessageA( ctrl, TB_GETTEXTROWS, 0, 0); 59c2c66affSColin Finck ok( maxtextrows == 0 || broken(maxtextrows == 1), /* Win2k and below */ 60c2c66affSColin Finck "Get(Max)TextRows returned %d (expected 0)\n", maxtextrows); 61c2c66affSColin Finck } 62c2c66affSColin Finck 63c2c66affSColin Finck 64c2c66affSColin Finck static UINT_PTR CALLBACK OFNHookProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) 65c2c66affSColin Finck { 66c2c66affSColin Finck LPNMHDR nmh; 67c2c66affSColin Finck 68c2c66affSColin Finck if( msg == WM_NOTIFY) 69c2c66affSColin Finck { 70c2c66affSColin Finck nmh = (LPNMHDR) lParam; 71c2c66affSColin Finck if( nmh->code == CDN_INITDONE) 72c2c66affSColin Finck { 73c2c66affSColin Finck PostMessageA( GetParent(hDlg), WM_COMMAND, IDCANCEL, FALSE); 74c2c66affSColin Finck } else if (nmh->code == CDN_FOLDERCHANGE ) 75c2c66affSColin Finck { 76c2c66affSColin Finck char buf[1024]; 77c2c66affSColin Finck int ret; 78c2c66affSColin Finck 79c2c66affSColin Finck memset(buf, 0x66, sizeof(buf)); 80c2c66affSColin Finck ret = SendMessageA( GetParent(hDlg), CDM_GETFOLDERIDLIST, 5, (LPARAM)buf); 81c2c66affSColin Finck ok(ret > 0, "CMD_GETFOLDERIDLIST not implemented\n"); 82c2c66affSColin Finck if (ret > 5) 83c2c66affSColin Finck ok(buf[0] == 0x66 && buf[1] == 0x66, "CMD_GETFOLDERIDLIST: The buffer was touched on failure\n"); 84c2c66affSColin Finck toolbarcheck( GetParent(hDlg)); 85c2c66affSColin Finck } 86c2c66affSColin Finck } 87c2c66affSColin Finck 88c2c66affSColin Finck return 0; 89c2c66affSColin Finck } 90c2c66affSColin Finck 91c2c66affSColin Finck /* bug 6829 */ 92c2c66affSColin Finck static void test_DialogCancel(void) 93c2c66affSColin Finck { 94c2c66affSColin Finck OPENFILENAMEA ofn; 95c2c66affSColin Finck BOOL result; 96c2c66affSColin Finck char szFileName[MAX_PATH] = ""; 97c2c66affSColin Finck char szInitialDir[MAX_PATH]; 98c2c66affSColin Finck 99c2c66affSColin Finck GetWindowsDirectoryA(szInitialDir, MAX_PATH); 100c2c66affSColin Finck 101c2c66affSColin Finck ZeroMemory(&ofn, sizeof(ofn)); 102c2c66affSColin Finck 103c2c66affSColin Finck ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400A; 104c2c66affSColin Finck ofn.hwndOwner = NULL; 105c2c66affSColin Finck ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0"; 106c2c66affSColin Finck ofn.lpstrFile = szFileName; 107c2c66affSColin Finck ofn.nMaxFile = MAX_PATH; 108c2c66affSColin Finck ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLEHOOK; 109c2c66affSColin Finck ofn.lpstrDefExt = "txt"; 110c2c66affSColin Finck ofn.lpfnHook = OFNHookProc; 111c2c66affSColin Finck ofn.lpstrInitialDir = szInitialDir; 112c2c66affSColin Finck 113c2c66affSColin Finck PrintDlgA(NULL); 114c2c66affSColin Finck ok(CDERR_INITIALIZATION == CommDlgExtendedError(), 115c2c66affSColin Finck "expected CDERR_INITIALIZATION, got %d\n", CommDlgExtendedError()); 116c2c66affSColin Finck 117c2c66affSColin Finck result = GetOpenFileNameA(&ofn); 118c2c66affSColin Finck ok(FALSE == result, "expected FALSE, got %d\n", result); 119c2c66affSColin Finck ok(0 == CommDlgExtendedError(), "expected 0, got %d\n", 120c2c66affSColin Finck CommDlgExtendedError()); 121c2c66affSColin Finck 122c2c66affSColin Finck PrintDlgA(NULL); 123c2c66affSColin Finck ok(CDERR_INITIALIZATION == CommDlgExtendedError(), 124c2c66affSColin Finck "expected CDERR_INITIALIZATION, got %d\n", CommDlgExtendedError()); 125c2c66affSColin Finck 126c2c66affSColin Finck result = GetSaveFileNameA(&ofn); 127c2c66affSColin Finck ok(FALSE == result, "expected FALSE, got %d\n", result); 128c2c66affSColin Finck ok(0 == CommDlgExtendedError(), "expected 0, got %d\n", 129c2c66affSColin Finck CommDlgExtendedError()); 130c2c66affSColin Finck 131c2c66affSColin Finck PrintDlgA(NULL); 132c2c66affSColin Finck ok(CDERR_INITIALIZATION == CommDlgExtendedError(), 133c2c66affSColin Finck "expected CDERR_INITIALIZATION, got %d\n", CommDlgExtendedError()); 134c2c66affSColin Finck 135c2c66affSColin Finck /* Before passing the ofn to Unicode functions, remove the ANSI strings */ 136c2c66affSColin Finck ofn.lpstrFilter = NULL; 137c2c66affSColin Finck ofn.lpstrInitialDir = NULL; 138c2c66affSColin Finck ofn.lpstrDefExt = NULL; 139c2c66affSColin Finck 140c2c66affSColin Finck PrintDlgA(NULL); 141c2c66affSColin Finck ok(CDERR_INITIALIZATION == CommDlgExtendedError(), 142c2c66affSColin Finck "expected CDERR_INITIALIZATION, got %d\n", CommDlgExtendedError()); 143c2c66affSColin Finck 144c2c66affSColin Finck SetLastError(0xdeadbeef); 145c2c66affSColin Finck result = GetOpenFileNameW((LPOPENFILENAMEW) &ofn); 146c2c66affSColin Finck if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 147c2c66affSColin Finck win_skip("GetOpenFileNameW is not implemented\n"); 148c2c66affSColin Finck else 149c2c66affSColin Finck { 150c2c66affSColin Finck ok(FALSE == result, "expected FALSE, got %d\n", result); 151c2c66affSColin Finck ok(0 == CommDlgExtendedError(), "expected 0, got %d\n", CommDlgExtendedError()); 152c2c66affSColin Finck } 153c2c66affSColin Finck 154c2c66affSColin Finck SetLastError(0xdeadbeef); 155c2c66affSColin Finck result = GetSaveFileNameW((LPOPENFILENAMEW) &ofn); 156c2c66affSColin Finck if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 157c2c66affSColin Finck win_skip("GetSaveFileNameW is not implemented\n"); 158c2c66affSColin Finck else 159c2c66affSColin Finck { 160c2c66affSColin Finck ok(FALSE == result, "expected FALSE, got %d\n", result); 161c2c66affSColin Finck ok(0 == CommDlgExtendedError(), "expected 0, got %d\n", CommDlgExtendedError()); 162c2c66affSColin Finck } 163c2c66affSColin Finck } 164c2c66affSColin Finck 165c2c66affSColin Finck static UINT_PTR CALLBACK create_view_window2_hook(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) 166c2c66affSColin Finck { 167c2c66affSColin Finck if (msg == WM_NOTIFY) 168c2c66affSColin Finck { 169c2c66affSColin Finck if (((LPNMHDR)lParam)->code == CDN_FOLDERCHANGE) 170c2c66affSColin Finck { 171c2c66affSColin Finck IShellBrowser *shell_browser = (IShellBrowser *)SendMessageA(GetParent(dlg), WM_USER + 7 /* WM_GETISHELLBROWSER */, 0, 0); 172c2c66affSColin Finck IShellView *shell_view = NULL; 173c2c66affSColin Finck IShellView2 *shell_view2 = NULL; 174c2c66affSColin Finck SV2CVW2_PARAMS view_params; 175c2c66affSColin Finck FOLDERSETTINGS folder_settings; 176c2c66affSColin Finck HRESULT hr; 177c2c66affSColin Finck RECT rect = {0, 0, 0, 0}; 178c2c66affSColin Finck 179c2c66affSColin Finck hr = IShellBrowser_QueryActiveShellView(shell_browser, &shell_view); 180c2c66affSColin Finck ok(SUCCEEDED(hr), "QueryActiveShellView returned %#x\n", hr); 181c2c66affSColin Finck if (FAILED(hr)) goto cleanup; 182c2c66affSColin Finck 183c2c66affSColin Finck hr = IShellView_QueryInterface(shell_view, &IID_IShellView2, (void **)&shell_view2); 184c2c66affSColin Finck if (hr == E_NOINTERFACE) 185c2c66affSColin Finck { 186c2c66affSColin Finck win_skip("IShellView2 not supported\n"); 187c2c66affSColin Finck goto cleanup; 188c2c66affSColin Finck } 189c2c66affSColin Finck ok(SUCCEEDED(hr), "QueryInterface returned %#x\n", hr); 190c2c66affSColin Finck if (FAILED(hr)) goto cleanup; 191c2c66affSColin Finck 192c2c66affSColin Finck hr = IShellView2_DestroyViewWindow(shell_view2); 193c2c66affSColin Finck ok(SUCCEEDED(hr), "DestroyViewWindow returned %#x\n", hr); 194c2c66affSColin Finck 195c2c66affSColin Finck folder_settings.ViewMode = FVM_LIST; 196c2c66affSColin Finck folder_settings.fFlags = 0; 197c2c66affSColin Finck 198c2c66affSColin Finck view_params.cbSize = sizeof(view_params); 199c2c66affSColin Finck view_params.psvPrev = NULL; 200c2c66affSColin Finck view_params.pfs = &folder_settings; 201c2c66affSColin Finck view_params.psbOwner = shell_browser; 202c2c66affSColin Finck view_params.prcView = ▭ 203c2c66affSColin Finck view_params.pvid = NULL; 204c2c66affSColin Finck view_params.hwndView = NULL; 205c2c66affSColin Finck 206c2c66affSColin Finck hr = IShellView2_CreateViewWindow2(shell_view2, &view_params); 207c2c66affSColin Finck if (hr == E_FAIL) 208c2c66affSColin Finck { 209c2c66affSColin Finck win_skip("CreateViewWindow2 is broken on Vista/W2K8\n"); 210c2c66affSColin Finck goto cleanup; 211c2c66affSColin Finck } 212c2c66affSColin Finck ok(SUCCEEDED(hr), "CreateViewWindow2 returned %#x\n", hr); 213c2c66affSColin Finck if (FAILED(hr)) goto cleanup; 214c2c66affSColin Finck 215c2c66affSColin Finck hr = IShellView2_GetCurrentInfo(shell_view2, &folder_settings); 216c2c66affSColin Finck ok(SUCCEEDED(hr), "GetCurrentInfo returned %#x\n", hr); 217c2c66affSColin Finck ok(folder_settings.ViewMode == FVM_LIST, 218c2c66affSColin Finck "view mode is %d, expected FVM_LIST\n", 219c2c66affSColin Finck folder_settings.ViewMode); 220c2c66affSColin Finck 221c2c66affSColin Finck hr = IShellView2_DestroyViewWindow(shell_view2); 222c2c66affSColin Finck ok(SUCCEEDED(hr), "DestroyViewWindow returned %#x\n", hr); 223c2c66affSColin Finck 224c2c66affSColin Finck /* XP and W2K3 need this. On W2K the call to DestroyWindow() fails and has 225c2c66affSColin Finck * no side effects. NT4 doesn't get here. (FIXME: Vista doesn't get here yet). 226c2c66affSColin Finck */ 227c2c66affSColin Finck DestroyWindow(view_params.hwndView); 228c2c66affSColin Finck 229c2c66affSColin Finck view_params.pvid = &VID_Details; 230c2c66affSColin Finck hr = IShellView2_CreateViewWindow2(shell_view2, &view_params); 231c2c66affSColin Finck ok(SUCCEEDED(hr), "CreateViewWindow2 returned %#x\n", hr); 232c2c66affSColin Finck if (FAILED(hr)) goto cleanup; 233c2c66affSColin Finck 234c2c66affSColin Finck hr = IShellView2_GetCurrentInfo(shell_view2, &folder_settings); 235c2c66affSColin Finck ok(SUCCEEDED(hr), "GetCurrentInfo returned %#x\n", hr); 236c2c66affSColin Finck ok(folder_settings.ViewMode == FVM_DETAILS || broken(folder_settings.ViewMode == FVM_LIST), /* nt4 */ 237c2c66affSColin Finck "view mode is %d, expected FVM_DETAILS\n", 238c2c66affSColin Finck folder_settings.ViewMode); 239c2c66affSColin Finck 240c2c66affSColin Finck cleanup: 241c2c66affSColin Finck if (shell_view2) IShellView2_Release(shell_view2); 242c2c66affSColin Finck if (shell_view) IShellView_Release(shell_view); 243c2c66affSColin Finck PostMessageA(GetParent(dlg), WM_COMMAND, IDCANCEL, 0); 244c2c66affSColin Finck } 245c2c66affSColin Finck } 246c2c66affSColin Finck return 0; 247c2c66affSColin Finck } 248c2c66affSColin Finck 249c2c66affSColin Finck static UINT_PTR WINAPI template_hook(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) 250c2c66affSColin Finck { 251c2c66affSColin Finck if (msg == WM_INITDIALOG) 252c2c66affSColin Finck { 253c2c66affSColin Finck HWND p,cb; 254c2c66affSColin Finck INT sel; 255c2c66affSColin Finck p = GetParent(dlg); 256c2c66affSColin Finck ok(p!=NULL, "Failed to get parent of template\n"); 257c2c66affSColin Finck cb = GetDlgItem(p,0x470); 258c2c66affSColin Finck ok(cb!=NULL, "Failed to get filter combobox\n"); 259c2c66affSColin Finck sel = SendMessageA(cb, CB_GETCURSEL, 0, 0); 260c2c66affSColin Finck ok (sel != -1, "Failed to get selection from filter listbox\n"); 261c2c66affSColin Finck } 262c2c66affSColin Finck if (msg == WM_NOTIFY) 263c2c66affSColin Finck { 264c2c66affSColin Finck if (((LPNMHDR)lParam)->code == CDN_FOLDERCHANGE) 265c2c66affSColin Finck PostMessageA(GetParent(dlg), WM_COMMAND, IDCANCEL, 0); 266c2c66affSColin Finck } 267c2c66affSColin Finck return 0; 268c2c66affSColin Finck } 269c2c66affSColin Finck 270c2c66affSColin Finck static void test_create_view_window2(void) 271c2c66affSColin Finck { 272c2c66affSColin Finck OPENFILENAMEA ofn = {0}; 273c2c66affSColin Finck char filename[1024] = {0}; 274c2c66affSColin Finck DWORD ret; 275c2c66affSColin Finck 276c2c66affSColin Finck ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400A; 277c2c66affSColin Finck ofn.lpstrFile = filename; 278c2c66affSColin Finck ofn.nMaxFile = 1024; 279c2c66affSColin Finck ofn.lpfnHook = create_view_window2_hook; 280c2c66affSColin Finck ofn.Flags = OFN_ENABLEHOOK | OFN_EXPLORER; 281c2c66affSColin Finck ret = GetOpenFileNameA(&ofn); 282c2c66affSColin Finck ok(!ret, "GetOpenFileNameA returned %#x\n", ret); 283c2c66affSColin Finck ret = CommDlgExtendedError(); 284c2c66affSColin Finck ok(!ret, "CommDlgExtendedError returned %#x\n", ret); 285c2c66affSColin Finck } 286c2c66affSColin Finck 287c2c66affSColin Finck static void test_create_view_template(void) 288c2c66affSColin Finck { 289c2c66affSColin Finck OPENFILENAMEA ofn = {0}; 290c2c66affSColin Finck char filename[1024] = {0}; 291c2c66affSColin Finck DWORD ret; 292c2c66affSColin Finck 293c2c66affSColin Finck ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400A; 294c2c66affSColin Finck ofn.lpstrFile = filename; 295c2c66affSColin Finck ofn.nMaxFile = 1024; 296c2c66affSColin Finck ofn.lpfnHook = template_hook; 297c2c66affSColin Finck ofn.Flags = OFN_ENABLEHOOK | OFN_EXPLORER| OFN_ENABLETEMPLATE; 298c2c66affSColin Finck ofn.hInstance = GetModuleHandleA(NULL); 299c2c66affSColin Finck ofn.lpTemplateName = "template1"; 300c2c66affSColin Finck ofn.lpstrFilter="text\0*.txt\0All\0*\0\0"; 301c2c66affSColin Finck ret = GetOpenFileNameA(&ofn); 302c2c66affSColin Finck ok(!ret, "GetOpenFileNameA returned %#x\n", ret); 303c2c66affSColin Finck ret = CommDlgExtendedError(); 304c2c66affSColin Finck ok(!ret, "CommDlgExtendedError returned %#x\n", ret); 305c2c66affSColin Finck } 306c2c66affSColin Finck 307c2c66affSColin Finck /* test cases for resizing of the file dialog */ 308c2c66affSColin Finck static const struct { 309c2c66affSColin Finck DWORD flags; 310c2c66affSColin Finck int resize_folderchange;/* change in CDN_FOLDERCHANGE handler */ 311c2c66affSColin Finck int resize_timer1; /* change in first WM_TIMER handler */ 312c2c66affSColin Finck int resize_check; /* expected change (in second WM_TIMER handler) */ 313c2c66affSColin Finck BOOL todo; /* mark that test todo_wine */ 314c2c66affSColin Finck BOOL testcontrols; /* test resizing and moving of the controls */ 315c2c66affSColin Finck } resize_testcases[] = { 316c2c66affSColin Finck { 0 , 10, 10, 20,FALSE,FALSE}, /* 0 */ 317c2c66affSColin Finck { 0 ,-10,-10,-20,FALSE,FALSE}, 318c2c66affSColin Finck { OFN_ENABLESIZING , 0, 0, 0,FALSE,FALSE}, 319c2c66affSColin Finck { OFN_ENABLESIZING , 0,-10, 0,FALSE,FALSE}, 320c2c66affSColin Finck { OFN_ENABLESIZING , 0, 10, 10,FALSE, TRUE}, 321c2c66affSColin Finck { OFN_ENABLESIZING ,-10, 0, 10,FALSE,FALSE}, /* 5 */ 322c2c66affSColin Finck { OFN_ENABLESIZING , 10, 0, 10,FALSE,FALSE}, 323c2c66affSColin Finck { OFN_ENABLESIZING , 0, 10, 20,FALSE,FALSE}, 324c2c66affSColin Finck /* mark the end */ 325c2c66affSColin Finck { 0xffffffff } 326c2c66affSColin Finck }; 327c2c66affSColin Finck 328c2c66affSColin Finck static UINT_PTR WINAPI resize_template_hook(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) 329c2c66affSColin Finck { 330c2c66affSColin Finck static RECT initrc, rc; 331c2c66affSColin Finck static int index, count; 332c2c66affSColin Finck static BOOL gotSWP_bottom, gotShowWindow; 333c2c66affSColin Finck HWND parent = GetParent( dlg); 334c2c66affSColin Finck int resize; 335c2c66affSColin Finck #define MAXNRCTRLS 30 336c2c66affSColin Finck static RECT ctrlrcs[MAXNRCTRLS]; 337c2c66affSColin Finck static int ctrlids[MAXNRCTRLS]; 338c2c66affSColin Finck static HWND ctrls[MAXNRCTRLS]; 339c2c66affSColin Finck static int nrctrls; 340c2c66affSColin Finck 341c2c66affSColin Finck switch( msg) 342c2c66affSColin Finck { 343c2c66affSColin Finck case WM_INITDIALOG: 344c2c66affSColin Finck { 345c2c66affSColin Finck DWORD style; 346c2c66affSColin Finck 347c2c66affSColin Finck index = ((OPENFILENAMEA*)lParam)->lCustData; 348c2c66affSColin Finck count = 0; 349c2c66affSColin Finck gotSWP_bottom = gotShowWindow = FALSE; 350c2c66affSColin Finck /* test style */ 351c2c66affSColin Finck style = GetWindowLongA( parent, GWL_STYLE); 352c2c66affSColin Finck if( resize_testcases[index].flags & OFN_ENABLESIZING) 353c2c66affSColin Finck if( !(style & WS_SIZEBOX)) { 354c2c66affSColin Finck win_skip( "OFN_ENABLESIZING flag not supported.\n"); 355c2c66affSColin Finck resizesupported = FALSE; 356c2c66affSColin Finck PostMessageA( parent, WM_COMMAND, IDCANCEL, 0); 357c2c66affSColin Finck } else 358c2c66affSColin Finck ok( style & WS_SIZEBOX, 359c2c66affSColin Finck "testid %d: dialog should have a WS_SIZEBOX style.\n", index); 360c2c66affSColin Finck else 361c2c66affSColin Finck ok( !(style & WS_SIZEBOX), 362c2c66affSColin Finck "testid %d: dialog should not have a WS_SIZEBOX style.\n", index); 363c2c66affSColin Finck break; 364c2c66affSColin Finck } 365c2c66affSColin Finck case WM_NOTIFY: 366c2c66affSColin Finck { 367c2c66affSColin Finck if(( (LPNMHDR)lParam)->code == CDN_FOLDERCHANGE){ 368c2c66affSColin Finck GetWindowRect( parent, &initrc); 369c2c66affSColin Finck if( (resize = resize_testcases[index].resize_folderchange)){ 370c2c66affSColin Finck MoveWindow( parent, initrc.left,initrc.top, initrc.right - initrc.left + resize, 371c2c66affSColin Finck initrc.bottom - initrc.top + resize, TRUE); 372c2c66affSColin Finck } 373c2c66affSColin Finck SetTimer( dlg, 0, 100, 0); 374c2c66affSColin Finck } 375c2c66affSColin Finck break; 376c2c66affSColin Finck } 377c2c66affSColin Finck case WM_TIMER: 378c2c66affSColin Finck { 379c2c66affSColin Finck if( count == 0){ 380c2c66affSColin Finck /* store the control rectangles */ 381c2c66affSColin Finck if( resize_testcases[index].testcontrols) { 382c2c66affSColin Finck HWND ctrl; 383c2c66affSColin Finck int i; 384c2c66affSColin Finck for( i = 0, ctrl = GetWindow( parent, GW_CHILD); 385c2c66affSColin Finck i < MAXNRCTRLS && ctrl; 386c2c66affSColin Finck i++, ctrl = GetWindow( ctrl, GW_HWNDNEXT)) { 387c2c66affSColin Finck ctrlids[i] = GetDlgCtrlID( ctrl); 388c2c66affSColin Finck GetWindowRect( ctrl, &ctrlrcs[i]); 389c2c66affSColin Finck MapWindowPoints( NULL, parent, (LPPOINT) &ctrlrcs[i], 2); 390c2c66affSColin Finck ctrls[i] = ctrl; 391c2c66affSColin Finck } 392c2c66affSColin Finck nrctrls = i; 393c2c66affSColin Finck } 394c2c66affSColin Finck if( (resize = resize_testcases[index].resize_timer1)){ 395c2c66affSColin Finck GetWindowRect( parent, &rc); 396c2c66affSColin Finck MoveWindow( parent, rc.left,rc.top, rc.right - rc.left + resize, 397c2c66affSColin Finck rc.bottom - rc.top + resize, TRUE); 398c2c66affSColin Finck } 399c2c66affSColin Finck } else if( count == 1){ 400c2c66affSColin Finck resize = resize_testcases[index].resize_check; 401c2c66affSColin Finck GetWindowRect( parent, &rc); 402c2c66affSColin Finck todo_wine_if( resize_testcases[index].todo){ 403c2c66affSColin Finck ok( resize == rc.right - rc.left - initrc.right + initrc.left, 404c2c66affSColin Finck "testid %d size-x change %d expected %d\n", index, 405c2c66affSColin Finck rc.right - rc.left - initrc.right + initrc.left, resize); 406c2c66affSColin Finck ok( resize == rc.bottom - rc.top - initrc.bottom + initrc.top, 407c2c66affSColin Finck "testid %d size-y change %d expected %d\n", index, 408c2c66affSColin Finck rc.bottom - rc.top - initrc.bottom + initrc.top, resize); 409c2c66affSColin Finck } 410c2c66affSColin Finck if( resize_testcases[index].testcontrols) { 411c2c66affSColin Finck int i; 412c2c66affSColin Finck RECT rc; 413c2c66affSColin Finck for( i = 0; i < nrctrls; i++) { 414c2c66affSColin Finck GetWindowRect( ctrls[i], &rc); 415c2c66affSColin Finck MapWindowPoints( NULL, parent, (LPPOINT) &rc, 2); 416c2c66affSColin Finck switch( ctrlids[i]){ 417c2c66affSColin Finck 418c2c66affSColin Finck /* test if RECT R1, moved and sized result in R2 */ 419c2c66affSColin Finck #define TESTRECTS( R1, R2, Mx, My, Sx, Sy) \ 420c2c66affSColin Finck ((R1).left + (Mx) ==(R2).left \ 421c2c66affSColin Finck &&(R1).top + (My) ==(R2).top \ 422c2c66affSColin Finck &&(R1).right + (Mx) + (Sx) == (R2).right \ 423c2c66affSColin Finck &&(R1).bottom + (My) + (Sy) ==(R2).bottom) 424c2c66affSColin Finck 425c2c66affSColin Finck /* sized horizontal and moved vertical */ 426c2c66affSColin Finck case cmb1: 427c2c66affSColin Finck case edt1: 428c2c66affSColin Finck ok( TESTRECTS( ctrlrcs[i], rc, 0, 10, 10, 0), 429c2c66affSColin Finck "control id %03x should have sized horizontally and moved vertically, before %s after %s\n", 430c2c66affSColin Finck ctrlids[i], wine_dbgstr_rect( &ctrlrcs[i] ), 431c2c66affSColin Finck wine_dbgstr_rect( &rc )); 432c2c66affSColin Finck break; 433c2c66affSColin Finck /* sized horizontal and vertical */ 434c2c66affSColin Finck case lst2: 435c2c66affSColin Finck ok( TESTRECTS( ctrlrcs[i], rc, 0, 0, 10, 10), 436c2c66affSColin Finck "control id %03x should have sized horizontally and vertically, before %s after %s\n", 437c2c66affSColin Finck ctrlids[i], wine_dbgstr_rect( &ctrlrcs[i] ), 438c2c66affSColin Finck wine_dbgstr_rect( &rc )); 439c2c66affSColin Finck break; 440c2c66affSColin Finck /* moved horizontal and vertical */ 441c2c66affSColin Finck case IDCANCEL: 442c2c66affSColin Finck case pshHelp: 443c2c66affSColin Finck ok( TESTRECTS( ctrlrcs[i], rc, 10, 10, 0, 0), 444c2c66affSColin Finck "control id %03x should have moved horizontally and vertically, before %s after %s\n", 445c2c66affSColin Finck ctrlids[i], wine_dbgstr_rect( &ctrlrcs[i] ), 446c2c66affSColin Finck wine_dbgstr_rect( &rc )); 447c2c66affSColin Finck break; 448c2c66affSColin Finck /* moved vertically */ 449c2c66affSColin Finck case chx1: 450c2c66affSColin Finck case stc2: 451c2c66affSColin Finck case stc3: 452c2c66affSColin Finck ok( TESTRECTS( ctrlrcs[i], rc, 0, 10, 0, 0), 453c2c66affSColin Finck "control id %03x should have moved vertically, before %s after %s\n", 454c2c66affSColin Finck ctrlids[i], wine_dbgstr_rect( &ctrlrcs[i] ), 455c2c66affSColin Finck wine_dbgstr_rect( &rc )); 456c2c66affSColin Finck break; 457c2c66affSColin Finck /* resized horizontal */ 458c2c66affSColin Finck case cmb2: /* aka IDC_LOOKIN */ 459c2c66affSColin Finck ok( TESTRECTS( ctrlrcs[i], rc, 0, 0, 10, 0)|| 460c2c66affSColin Finck TESTRECTS( ctrlrcs[i], rc, 0, 0, 0, 0), /* Vista and higher */ 461c2c66affSColin Finck "control id %03x should have resized horizontally, before %s after %s\n", 462c2c66affSColin Finck ctrlids[i], wine_dbgstr_rect( &ctrlrcs[i] ), 463c2c66affSColin Finck wine_dbgstr_rect( &rc )); 464c2c66affSColin Finck break; 465c2c66affSColin Finck /* non moving non sizing controls */ 466c2c66affSColin Finck case stc4: 467c2c66affSColin Finck ok( TESTRECTS( rc, ctrlrcs[i], 0, 0, 0, 0), 468c2c66affSColin Finck "control id %03x was moved/resized, before %s after %s\n", 469c2c66affSColin Finck ctrlids[i], wine_dbgstr_rect( &ctrlrcs[i] ), 470c2c66affSColin Finck wine_dbgstr_rect( &rc )); 471c2c66affSColin Finck break; 472c2c66affSColin Finck /* todo_wine: non moving non sizing controls */ 473c2c66affSColin Finck case lst1: 474c2c66affSColin Finck todo_wine 475c2c66affSColin Finck ok( TESTRECTS( rc, ctrlrcs[i], 0, 0, 0, 0), 476c2c66affSColin Finck "control id %03x was moved/resized, before %s after %s\n", 477c2c66affSColin Finck ctrlids[i], wine_dbgstr_rect( &ctrlrcs[i] ), 478c2c66affSColin Finck wine_dbgstr_rect( &rc )); 479c2c66affSColin Finck break; 480c2c66affSColin Finck /* don't test: id is not unique */ 481c2c66affSColin Finck case IDOK: 482c2c66affSColin Finck case stc1: 483c2c66affSColin Finck case 0: 484c2c66affSColin Finck case -1: 485c2c66affSColin Finck break; 486c2c66affSColin Finck default: 487c2c66affSColin Finck trace("untested control id %03x before %s after %s\n", 488c2c66affSColin Finck ctrlids[i], wine_dbgstr_rect( &ctrlrcs[i] ), 489c2c66affSColin Finck wine_dbgstr_rect( &rc )); 490c2c66affSColin Finck #undef TESTRECTS 491c2c66affSColin Finck #undef MAXNRCTRLS 492c2c66affSColin Finck } 493c2c66affSColin Finck } 494c2c66affSColin Finck } 495c2c66affSColin Finck KillTimer( dlg, 0); 496c2c66affSColin Finck PostMessageA( parent, WM_COMMAND, IDCANCEL, 0); 497c2c66affSColin Finck } 498c2c66affSColin Finck count++; 499c2c66affSColin Finck } 500c2c66affSColin Finck break; 501c2c66affSColin Finck case WM_WINDOWPOSCHANGING: 502c2c66affSColin Finck { 503c2c66affSColin Finck WINDOWPOS *pwp = (WINDOWPOS *)lParam; 504c2c66affSColin Finck if( !index && pwp->hwndInsertAfter == HWND_BOTTOM){ 505c2c66affSColin Finck gotSWP_bottom = TRUE; 506c2c66affSColin Finck ok(!gotShowWindow, "The WM_WINDOWPOSCHANGING message came after a WM_SHOWWINDOW message\n"); 507c2c66affSColin Finck } 508c2c66affSColin Finck } 509c2c66affSColin Finck break; 510c2c66affSColin Finck case WM_SHOWWINDOW: 511c2c66affSColin Finck { 512c2c66affSColin Finck if( !index){ 513c2c66affSColin Finck gotShowWindow = TRUE; 514c2c66affSColin Finck ok(gotSWP_bottom, "No WM_WINDOWPOSCHANGING message came before a WM_SHOWWINDOW message\n"); 515c2c66affSColin Finck } 516c2c66affSColin Finck } 517c2c66affSColin Finck break; 518c2c66affSColin Finck } 519c2c66affSColin Finck return 0; 520c2c66affSColin Finck } 521c2c66affSColin Finck 522c2c66affSColin Finck static void test_resize(void) 523c2c66affSColin Finck { 524c2c66affSColin Finck OPENFILENAMEA ofn = { OPENFILENAME_SIZE_VERSION_400A }; 525c2c66affSColin Finck char filename[1024] = {0}; 526c2c66affSColin Finck DWORD ret; 527c2c66affSColin Finck int i; 528c2c66affSColin Finck 529c2c66affSColin Finck ofn.lpstrFile = filename; 530c2c66affSColin Finck ofn.nMaxFile = 1024; 531c2c66affSColin Finck ofn.lpfnHook = resize_template_hook; 532c2c66affSColin Finck ofn.hInstance = GetModuleHandleA(NULL); 533c2c66affSColin Finck ofn.lpTemplateName = "template_sz"; 534c2c66affSColin Finck for( i = 0; resize_testcases[i].flags != 0xffffffff; i++) { 535c2c66affSColin Finck ofn.lCustData = i; 536c2c66affSColin Finck ofn.Flags = resize_testcases[i].flags | 537c2c66affSColin Finck OFN_ENABLEHOOK | OFN_EXPLORER| OFN_ENABLETEMPLATE | OFN_SHOWHELP ; 538c2c66affSColin Finck ret = GetOpenFileNameA(&ofn); 539c2c66affSColin Finck ok(!ret, "GetOpenFileName returned %#x\n", ret); 540c2c66affSColin Finck ret = CommDlgExtendedError(); 541c2c66affSColin Finck ok(!ret, "CommDlgExtendedError returned %#x\n", ret); 542c2c66affSColin Finck } 543c2c66affSColin Finck } 544c2c66affSColin Finck 545c2c66affSColin Finck /* test cases for control message IDOK */ 546c2c66affSColin Finck /* Show case for bug #19079 */ 547c2c66affSColin Finck typedef struct { 548c2c66affSColin Finck int retval; /* return code of the message handler */ 549c2c66affSColin Finck BOOL setmsgresult; /* set the result in the DWLP_MSGRESULT */ 550c2c66affSColin Finck BOOL usemsgokstr; /* use the FILEOKSTRING message instead of WM_NOTIFY:CDN_FILEOK */ 551c2c66affSColin Finck BOOL do_subclass; /* subclass the dialog hook procedure */ 552c2c66affSColin Finck BOOL expclose; /* is the dialog expected to close ? */ 553c2c66affSColin Finck BOOL actclose; /* has the dialog actually closed ? */ 554c2c66affSColin Finck } ok_wndproc_testcase; 555c2c66affSColin Finck 556c2c66affSColin Finck static ok_wndproc_testcase ok_testcases[] = { 557c2c66affSColin Finck { 0, FALSE, FALSE, FALSE, TRUE}, 558c2c66affSColin Finck { 0, TRUE, FALSE, FALSE, TRUE}, 559c2c66affSColin Finck { 0, FALSE, FALSE, TRUE, TRUE}, 560c2c66affSColin Finck { 0, TRUE, FALSE, TRUE, TRUE}, 561c2c66affSColin Finck { 1, FALSE, FALSE, FALSE, TRUE}, 562c2c66affSColin Finck { 1, TRUE, FALSE, FALSE, FALSE}, 563c2c66affSColin Finck { 1, FALSE, FALSE, TRUE, FALSE}, 564c2c66affSColin Finck { 1, TRUE, FALSE, TRUE, FALSE}, 565c2c66affSColin Finck /* FILEOKSTRING tests */ 566c2c66affSColin Finck { 1, TRUE, TRUE, FALSE, FALSE}, 567c2c66affSColin Finck { 1, FALSE, TRUE, TRUE, FALSE}, 568c2c66affSColin Finck /* mark the end */ 569c2c66affSColin Finck { -1 } 570c2c66affSColin Finck }; 571c2c66affSColin Finck 572c2c66affSColin Finck /* test_ok_wndproc can be used as hook procedure or a subclass 573c2c66affSColin Finck * window proc for the file dialog */ 574c2c66affSColin Finck static UINT_PTR WINAPI test_ok_wndproc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) 575c2c66affSColin Finck { 576c2c66affSColin Finck HWND parent = GetParent( dlg); 577c2c66affSColin Finck static ok_wndproc_testcase *testcase = NULL; 578c2c66affSColin Finck static UINT msgFILEOKSTRING; 579c2c66affSColin Finck if (msg == WM_INITDIALOG) 580c2c66affSColin Finck { 581c2c66affSColin Finck testcase = (ok_wndproc_testcase*)((OPENFILENAMEA*)lParam)->lCustData; 582c2c66affSColin Finck testcase->actclose = TRUE; 583c2c66affSColin Finck msgFILEOKSTRING = RegisterWindowMessageA( FILEOKSTRINGA); 584c2c66affSColin Finck } 585c2c66affSColin Finck if( msg == WM_NOTIFY) { 586c2c66affSColin Finck if(((LPNMHDR)lParam)->code == CDN_FOLDERCHANGE) { 587c2c66affSColin Finck SetTimer( dlg, 0, 100, 0); 588c2c66affSColin Finck PostMessageA( parent, WM_COMMAND, IDOK, 0); 589c2c66affSColin Finck return FALSE; 590c2c66affSColin Finck } else if(((LPNMHDR)lParam)->code == CDN_FILEOK) { 591c2c66affSColin Finck if( testcase->usemsgokstr) 592c2c66affSColin Finck return FALSE; 593c2c66affSColin Finck if( testcase->setmsgresult) 594c2c66affSColin Finck SetWindowLongPtrA( dlg, DWLP_MSGRESULT, testcase->retval); 595c2c66affSColin Finck return testcase->retval; 596c2c66affSColin Finck } 597c2c66affSColin Finck } 598c2c66affSColin Finck if( msg == msgFILEOKSTRING) { 599c2c66affSColin Finck if( !testcase->usemsgokstr) 600c2c66affSColin Finck return FALSE; 601c2c66affSColin Finck if( testcase->setmsgresult) 602c2c66affSColin Finck SetWindowLongPtrA( dlg, DWLP_MSGRESULT, testcase->retval); 603c2c66affSColin Finck return testcase->retval; 604c2c66affSColin Finck } 605c2c66affSColin Finck if( msg == WM_TIMER) { 606c2c66affSColin Finck /* the dialog did not close automatically */ 607c2c66affSColin Finck testcase->actclose = FALSE; 608c2c66affSColin Finck KillTimer( dlg, 0); 609c2c66affSColin Finck PostMessageA( parent, WM_COMMAND, IDCANCEL, 0); 610c2c66affSColin Finck return FALSE; 611c2c66affSColin Finck } 612c2c66affSColin Finck if( testcase && testcase->do_subclass) 613c2c66affSColin Finck return DefWindowProcA( dlg, msg, wParam, lParam); 614c2c66affSColin Finck return FALSE; 615c2c66affSColin Finck } 616c2c66affSColin Finck 617c2c66affSColin Finck static UINT_PTR WINAPI ok_template_hook(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) 618c2c66affSColin Finck { 619c2c66affSColin Finck if (msg == WM_SETFONT) 620c2c66affSColin Finck SetWindowLongPtrA( dlg, GWLP_WNDPROC, (LONG_PTR) test_ok_wndproc); 621c2c66affSColin Finck return FALSE; 622c2c66affSColin Finck } 623c2c66affSColin Finck 624c2c66affSColin Finck static void test_ok(void) 625c2c66affSColin Finck { 626c2c66affSColin Finck OPENFILENAMEA ofn = { OPENFILENAME_SIZE_VERSION_400A }; 627c2c66affSColin Finck char filename[1024] = {0}; 628c2c66affSColin Finck char tmpfilename[ MAX_PATH]; 629c2c66affSColin Finck char curdir[MAX_PATH]; 630c2c66affSColin Finck int i; 631c2c66affSColin Finck DWORD ret; 632c2c66affSColin Finck BOOL cdret; 633c2c66affSColin Finck 634c2c66affSColin Finck cdret = GetCurrentDirectoryA(sizeof(curdir), curdir); 635c2c66affSColin Finck ok(cdret, "Failed to get current dir err %d\n", GetLastError()); 636c2c66affSColin Finck if (!GetTempFileNameA(".", "txt", 0, tmpfilename)) { 637c2c66affSColin Finck skip("Failed to create a temporary file name\n"); 638c2c66affSColin Finck return; 639c2c66affSColin Finck } 640c2c66affSColin Finck ofn.lpstrFile = filename; 641c2c66affSColin Finck ofn.nMaxFile = 1024; 642c2c66affSColin Finck ofn.hInstance = GetModuleHandleA(NULL); 643c2c66affSColin Finck ofn.lpTemplateName = "template1"; 644c2c66affSColin Finck ofn.Flags = OFN_ENABLEHOOK | OFN_EXPLORER| OFN_ENABLETEMPLATE ; 645c2c66affSColin Finck for( i = 0; ok_testcases[i].retval != -1; i++) { 646c2c66affSColin Finck strcpy( filename, tmpfilename); 647c2c66affSColin Finck ofn.lCustData = (LPARAM)(ok_testcases + i); 648c2c66affSColin Finck ofn.lpfnHook = ok_testcases[i].do_subclass ? ok_template_hook : test_ok_wndproc; 649c2c66affSColin Finck ret = GetOpenFileNameA(&ofn); 650c2c66affSColin Finck ok( ok_testcases[i].expclose == ok_testcases[i].actclose, 651c2c66affSColin Finck "testid %d: Open File dialog should %shave closed.\n", i, 652c2c66affSColin Finck ok_testcases[i].expclose ? "" : "NOT "); 653c2c66affSColin Finck ok(ret == ok_testcases[i].expclose, "testid %d: GetOpenFileName returned %#x\n", i, ret); 654c2c66affSColin Finck ret = CommDlgExtendedError(); 655c2c66affSColin Finck ok(!ret, "CommDlgExtendedError returned %#x\n", ret); 656c2c66affSColin Finck cdret = SetCurrentDirectoryA(curdir); 657c2c66affSColin Finck ok(cdret, "Failed to restore current dir err %d\n", GetLastError()); 658c2c66affSColin Finck } 659c2c66affSColin Finck ret = DeleteFileA( tmpfilename); 660c2c66affSColin Finck ok( ret, "Failed to delete temporary file %s err %d\n", tmpfilename, GetLastError()); 661c2c66affSColin Finck } 662c2c66affSColin Finck 663c2c66affSColin Finck /* test arranging with a custom template */ 664c2c66affSColin Finck typedef struct { 665c2c66affSColin Finck int x, y; /* left, top coordinates */ 666c2c66affSColin Finck int cx, cy; /* width and height */ 667c2c66affSColin Finck } posz; 668c2c66affSColin Finck static struct { 669c2c66affSColin Finck int nrcontrols; /* 0: no controls, 1: just the stc32 control 2: with button */ 670c2c66affSColin Finck posz poszDlg; 671c2c66affSColin Finck posz poszStc32; 672c2c66affSColin Finck posz poszBtn; 673c2c66affSColin Finck DWORD ofnflags; 674c2c66affSColin Finck } arrange_tests[] = { 675c2c66affSColin Finck /* do not change the first two cases: used to get the uncustomized sizes */ 676c2c66affSColin Finck { 0, {0},{0},{0},0 }, 677c2c66affSColin Finck { 0, {0},{0},{0}, OFN_SHOWHELP}, 678c2c66affSColin Finck /* two tests with just a subdialog, no controls */ 679c2c66affSColin Finck { 0, {0, 0, 316, 76},{0},{0},0 }, 680c2c66affSColin Finck { 0, {0, 0, 100, 76},{0},{0}, OFN_SHOWHELP}, 681c2c66affSColin Finck /* now with a control with id stc32 */ 682c2c66affSColin Finck { 1, {0, 0, 316, 76} ,{0, 0, 204, 76,},{0},0 }, /* bug #17748*/ 683c2c66affSColin Finck { 1, {0, 0, 316, 76} ,{0, 0, 204, 76,},{0}, OFN_SHOWHELP}, /* bug #17748*/ 684c2c66affSColin Finck /* tests with size of the stc32 control higher or wider then the standard dialog */ 685c2c66affSColin Finck { 1, {0, 0, 316, 170} ,{0, 0, 204, 170,},{0},0 }, 686c2c66affSColin Finck { 1, {0, 0, 316, 165} ,{0, 0, 411, 165,},{0}, OFN_SHOWHELP }, 687c2c66affSColin Finck /* move the stc32 control around */ 688c2c66affSColin Finck { 1, {0, 0, 300, 100} ,{73, 17, 50, 50,},{0},0 }, 689c2c66affSColin Finck /* add control */ 690c2c66affSColin Finck { 2, {0, 0, 280, 100} ,{0, 0, 50, 50,},{300,20,30,30},0 }, 691c2c66affSColin Finck /* enable resizing should make the dialog bigger */ 692c2c66affSColin Finck { 0, {0},{0},{0}, OFN_SHOWHELP|OFN_ENABLESIZING}, 693c2c66affSColin Finck /* mark the end */ 694c2c66affSColin Finck { -1 } 695c2c66affSColin Finck }; 696c2c66affSColin Finck 697c2c66affSColin Finck static UINT_PTR WINAPI template_hook_arrange(HWND dlgChild, UINT msg, WPARAM wParam, LPARAM lParam) 698c2c66affSColin Finck { 699c2c66affSColin Finck static int index, fixhelp; 700c2c66affSColin Finck static posz posz0[2]; 701c2c66affSColin Finck static RECT clrcParent, clrcChild, rcStc32; 702c2c66affSColin Finck static HWND hwndStc32; 703c2c66affSColin Finck HWND dlgParent; 704c2c66affSColin Finck 705c2c66affSColin Finck dlgParent = GetParent( dlgChild); 706c2c66affSColin Finck if (msg == WM_INITDIALOG) { 707c2c66affSColin Finck index = ((OPENFILENAMEA*)lParam)->lCustData; 708c2c66affSColin Finck /* get the positions before rearrangement */ 709c2c66affSColin Finck GetClientRect( dlgParent, &clrcParent); 710c2c66affSColin Finck GetClientRect( dlgChild, &clrcChild); 711c2c66affSColin Finck hwndStc32 = GetDlgItem( dlgChild, stc32); 712c2c66affSColin Finck if( hwndStc32) GetWindowRect( hwndStc32, &rcStc32); 713c2c66affSColin Finck } 714c2c66affSColin Finck if (msg == WM_NOTIFY && ((LPNMHDR)lParam)->code == CDN_FOLDERCHANGE) { 715c2c66affSColin Finck RECT wrcParent; 716c2c66affSColin Finck 717c2c66affSColin Finck GetWindowRect( dlgParent, &wrcParent); 718c2c66affSColin Finck /* the fist two "tests" just save the dialogs position, with and without 719c2c66affSColin Finck * help button */ 720c2c66affSColin Finck if( index == 0) { 721c2c66affSColin Finck posz0[0].x = wrcParent.left; 722c2c66affSColin Finck posz0[0].y = wrcParent.top; 723c2c66affSColin Finck posz0[0].cx = wrcParent.right - wrcParent.left; 724c2c66affSColin Finck posz0[0].cy = wrcParent.bottom - wrcParent.top; 725c2c66affSColin Finck } else if( index == 1) { 726c2c66affSColin Finck posz0[1].x = wrcParent.left; 727c2c66affSColin Finck posz0[1].y = wrcParent.top; 728c2c66affSColin Finck posz0[1].cx = wrcParent.right - wrcParent.left; 729c2c66affSColin Finck posz0[1].cy = wrcParent.bottom - wrcParent.top; 730c2c66affSColin Finck fixhelp = posz0[1].cy - posz0[0].cy; 731c2c66affSColin Finck } else { 732c2c66affSColin Finck /* the real tests */ 733c2c66affSColin Finck int withhelp; 734c2c66affSColin Finck int expectx, expecty; 735c2c66affSColin Finck DWORD style; 736c2c66affSColin Finck 737c2c66affSColin Finck withhelp = (arrange_tests[index].ofnflags & OFN_SHOWHELP) != 0; 738c2c66affSColin Finck GetWindowRect( dlgParent, &wrcParent); 739c2c66affSColin Finck if( !hwndStc32) { 740c2c66affSColin Finck /* case with no custom subitem with stc32: 741c2c66affSColin Finck * default to all custom controls below the standard */ 742c2c66affSColin Finck expecty = posz0[withhelp].cy + clrcChild.bottom; 743c2c66affSColin Finck expectx = posz0[withhelp].cx; 744c2c66affSColin Finck } else { 745c2c66affSColin Finck /* special case: there is a control with id stc32 */ 746c2c66affSColin Finck /* expected height */ 747c2c66affSColin Finck expecty = posz0[withhelp].cy; 748c2c66affSColin Finck if( rcStc32.bottom - rcStc32.top + (withhelp ? 0 : fixhelp) > clrcParent.bottom) { 749c2c66affSColin Finck expecty += clrcChild.bottom - clrcParent.bottom; 750c2c66affSColin Finck if( !withhelp) expecty += fixhelp; 751c2c66affSColin Finck } 752c2c66affSColin Finck else 753c2c66affSColin Finck expecty += clrcChild.bottom - ( rcStc32.bottom - rcStc32.top) ; 754c2c66affSColin Finck /* expected width */ 755c2c66affSColin Finck expectx = posz0[withhelp].cx; 756c2c66affSColin Finck if( rcStc32.right - rcStc32.left > clrcParent.right) { 757c2c66affSColin Finck expectx += clrcChild.right - clrcParent.right; 758c2c66affSColin Finck } 759c2c66affSColin Finck else 760c2c66affSColin Finck expectx += clrcChild.right - ( rcStc32.right - rcStc32.left) ; 761c2c66affSColin Finck } 762c2c66affSColin Finck style = GetWindowLongA( dlgParent, GWL_STYLE); 763c2c66affSColin Finck if( !(style & WS_SIZEBOX)) { 764c2c66affSColin Finck /* without the OFN_ENABLESIZING flag */ 765c2c66affSColin Finck ok( wrcParent.bottom - wrcParent.top == expecty, 766c2c66affSColin Finck "Wrong height of dialog %d, expected %d\n", 767c2c66affSColin Finck wrcParent.bottom - wrcParent.top, expecty); 768c2c66affSColin Finck ok( wrcParent.right - wrcParent.left == expectx, 769c2c66affSColin Finck "Wrong width of dialog %d, expected %d\n", 770c2c66affSColin Finck wrcParent.right - wrcParent.left, expectx); 771c2c66affSColin Finck } else { 772c2c66affSColin Finck /* with the OFN_ENABLESIZING flag */ 773c2c66affSColin Finck ok( wrcParent.bottom - wrcParent.top > expecty, 774c2c66affSColin Finck "Wrong height of dialog %d, expected more than %d\n", 775c2c66affSColin Finck wrcParent.bottom - wrcParent.top, expecty); 776c2c66affSColin Finck ok( wrcParent.right - wrcParent.left > expectx, 777c2c66affSColin Finck "Wrong width of dialog %d, expected more than %d\n", 778c2c66affSColin Finck wrcParent.right - wrcParent.left, expectx); 779c2c66affSColin Finck } 780c2c66affSColin Finck 781c2c66affSColin Finck } 782c2c66affSColin Finck PostMessageA( dlgParent, WM_COMMAND, IDCANCEL, 0); 783c2c66affSColin Finck } 784c2c66affSColin Finck return 0; 785c2c66affSColin Finck } 786c2c66affSColin Finck 787c2c66affSColin Finck static void test_arrange(void) 788c2c66affSColin Finck { 789c2c66affSColin Finck OPENFILENAMEA ofn = {0}; 790c2c66affSColin Finck char filename[1024] = {0}; 791c2c66affSColin Finck DWORD ret; 792c2c66affSColin Finck HRSRC hRes; 793c2c66affSColin Finck HANDLE hDlgTmpl; 794c2c66affSColin Finck LPBYTE pv; 795c2c66affSColin Finck DLGTEMPLATE *template; 796c2c66affSColin Finck DLGITEMTEMPLATE *itemtemplateStc32, *itemtemplateBtn; 797c2c66affSColin Finck int i; 798c2c66affSColin Finck 799c2c66affSColin Finck /* load subdialog template into memory */ 800c2c66affSColin Finck hRes = FindResourceA( GetModuleHandleA(NULL), "template_stc32", (LPSTR)RT_DIALOG); 801c2c66affSColin Finck hDlgTmpl = LoadResource( GetModuleHandleA(NULL), hRes ); 802c2c66affSColin Finck /* get pointers to the structures for the dialog and the controls */ 803c2c66affSColin Finck pv = LockResource( hDlgTmpl ); 804c2c66affSColin Finck template = (DLGTEMPLATE*)pv; 805c2c66affSColin Finck if( template->x != 11111) { 806c2c66affSColin Finck win_skip("could not find the dialog template\n"); 807c2c66affSColin Finck return; 808c2c66affSColin Finck } 809c2c66affSColin Finck /* skip dialog template, menu, class and title */ 810c2c66affSColin Finck pv += sizeof(DLGTEMPLATE); 811c2c66affSColin Finck pv += 3 * sizeof(WORD); 812c2c66affSColin Finck /* skip font info */ 813c2c66affSColin Finck while( *(WORD*)pv) 814c2c66affSColin Finck pv += sizeof(WORD); 815c2c66affSColin Finck pv += sizeof(WORD); 816c2c66affSColin Finck /* align on 32 bit boundaries */ 817c2c66affSColin Finck pv = (LPBYTE)(((UINT_PTR)pv + 3 ) & ~3); 818c2c66affSColin Finck itemtemplateStc32 = (DLGITEMTEMPLATE*)pv; 819c2c66affSColin Finck if( itemtemplateStc32->x != 22222) { 820c2c66affSColin Finck win_skip("could not find the first item template\n"); 821c2c66affSColin Finck return; 822c2c66affSColin Finck } 823c2c66affSColin Finck /* skip itemtemplate, class, title and creation data */ 824c2c66affSColin Finck pv += sizeof(DLGITEMTEMPLATE); 825c2c66affSColin Finck pv += 4 * sizeof(WORD); 826c2c66affSColin Finck /* align on 32 bit boundaries */ 827c2c66affSColin Finck pv = (LPBYTE)(((UINT_PTR)pv + 3 ) & ~3); 828c2c66affSColin Finck itemtemplateBtn = (DLGITEMTEMPLATE*)pv; 829c2c66affSColin Finck if( itemtemplateBtn->x != 12345) { 830c2c66affSColin Finck win_skip("could not find the second item template\n"); 831c2c66affSColin Finck return; 832c2c66affSColin Finck } 833c2c66affSColin Finck 834c2c66affSColin Finck ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400A; 835c2c66affSColin Finck ofn.lpstrFile = filename; 836c2c66affSColin Finck ofn.nMaxFile = 1024; 837c2c66affSColin Finck ofn.lpfnHook = template_hook_arrange; 838c2c66affSColin Finck ofn.hInstance = hDlgTmpl; 839c2c66affSColin Finck ofn.lpstrFilter="text\0*.txt\0All\0*\0\0"; 840c2c66affSColin Finck for( i = 0; arrange_tests[i].nrcontrols != -1; i++) { 841c2c66affSColin Finck ofn.lCustData = i; 842c2c66affSColin Finck ofn.Flags = OFN_ENABLEHOOK | OFN_EXPLORER| OFN_ENABLETEMPLATEHANDLE | OFN_HIDEREADONLY | 843c2c66affSColin Finck arrange_tests[i].ofnflags; 844c2c66affSColin Finck template->cdit = arrange_tests[i].nrcontrols; 845c2c66affSColin Finck template->x = arrange_tests[i].poszDlg.x; 846c2c66affSColin Finck template->y = arrange_tests[i].poszDlg.y; 847c2c66affSColin Finck template->cx = arrange_tests[i].poszDlg.cx; 848c2c66affSColin Finck template->cy = arrange_tests[i].poszDlg.cy; 849c2c66affSColin Finck itemtemplateStc32->x = arrange_tests[i].poszStc32.x; 850c2c66affSColin Finck itemtemplateStc32->y = arrange_tests[i].poszStc32.y; 851c2c66affSColin Finck itemtemplateStc32->cx = arrange_tests[i].poszStc32.cx; 852c2c66affSColin Finck itemtemplateStc32->cy = arrange_tests[i].poszStc32.cy; 853c2c66affSColin Finck itemtemplateBtn->x = arrange_tests[i].poszBtn.x; 854c2c66affSColin Finck itemtemplateBtn->y = arrange_tests[i].poszBtn.y; 855c2c66affSColin Finck itemtemplateBtn->cx = arrange_tests[i].poszBtn.cx; 856c2c66affSColin Finck itemtemplateBtn->cy = arrange_tests[i].poszBtn.cy; 857c2c66affSColin Finck ret = GetOpenFileNameA(&ofn); 858c2c66affSColin Finck ok(!ret, "GetOpenFileNameA returned %#x\n", ret); 859c2c66affSColin Finck ret = CommDlgExtendedError(); 860c2c66affSColin Finck ok(!ret, "CommDlgExtendedError returned %#x\n", ret); 861c2c66affSColin Finck } 862c2c66affSColin Finck } 863c2c66affSColin Finck 864c2c66affSColin Finck static CHAR SYSDIR[MAX_PATH]; 865c2c66affSColin Finck 866c2c66affSColin Finck static UINT_PTR CALLBACK path_hook_proc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) 867c2c66affSColin Finck { 868c2c66affSColin Finck LPNMHDR nmh; 869c2c66affSColin Finck 870c2c66affSColin Finck if( msg == WM_NOTIFY) 871c2c66affSColin Finck { 872c2c66affSColin Finck nmh = (LPNMHDR) lParam; 873c2c66affSColin Finck if( nmh->code == CDN_INITDONE) 874c2c66affSColin Finck { 875c2c66affSColin Finck PostMessageA( GetParent(hDlg), WM_COMMAND, IDCANCEL, FALSE); 876c2c66affSColin Finck } 877c2c66affSColin Finck else if ( nmh->code == CDN_FOLDERCHANGE) 878c2c66affSColin Finck { 879c2c66affSColin Finck char buf[1024]; 880c2c66affSColin Finck int ret; 881c2c66affSColin Finck 882c2c66affSColin Finck memset(buf, 0x66, sizeof(buf)); 883c2c66affSColin Finck ret = SendMessageA( GetParent(hDlg), CDM_GETFOLDERPATH, sizeof(buf), (LPARAM)buf); 884c2c66affSColin Finck ok(!lstrcmpiA(SYSDIR, buf), "Expected '%s', got '%s'\n", SYSDIR, buf); 885c2c66affSColin Finck ok(lstrlenA(SYSDIR) + 1 == ret, "Expected %d, got %d\n", lstrlenA(SYSDIR) + 1, ret); 886c2c66affSColin Finck } 887c2c66affSColin Finck } 888c2c66affSColin Finck 889c2c66affSColin Finck return 0; 890c2c66affSColin Finck } 891c2c66affSColin Finck 892c2c66affSColin Finck static void test_getfolderpath(void) 893c2c66affSColin Finck { 894c2c66affSColin Finck OPENFILENAMEA ofn; 895c2c66affSColin Finck BOOL result; 896c2c66affSColin Finck char szFileName[MAX_PATH] = ""; 897c2c66affSColin Finck char szInitialDir[MAX_PATH]; 898c2c66affSColin Finck 899c2c66affSColin Finck /* We need to pick a different directory as the other tests because of new 900c2c66affSColin Finck * Windows 7 behavior. 901c2c66affSColin Finck */ 902c2c66affSColin Finck GetSystemDirectoryA(szInitialDir, MAX_PATH); 903c2c66affSColin Finck lstrcpyA(SYSDIR, szInitialDir); 904c2c66affSColin Finck 905c2c66affSColin Finck ZeroMemory(&ofn, sizeof(ofn)); 906c2c66affSColin Finck 907c2c66affSColin Finck ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400A; 908c2c66affSColin Finck ofn.hwndOwner = NULL; 909c2c66affSColin Finck ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0"; 910c2c66affSColin Finck ofn.lpstrFile = szFileName; 911c2c66affSColin Finck ofn.nMaxFile = MAX_PATH; 912c2c66affSColin Finck ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLEHOOK; 913c2c66affSColin Finck ofn.lpstrDefExt = "txt"; 914c2c66affSColin Finck ofn.lpfnHook = path_hook_proc; 915c2c66affSColin Finck ofn.lpstrInitialDir = szInitialDir; 916c2c66affSColin Finck 917c2c66affSColin Finck result = GetOpenFileNameA(&ofn); 918c2c66affSColin Finck ok(FALSE == result, "expected FALSE, got %d\n", result); 919c2c66affSColin Finck ok(0 == CommDlgExtendedError(), "expected 0, got %d\n", 920c2c66affSColin Finck CommDlgExtendedError()); 921c2c66affSColin Finck 922c2c66affSColin Finck result = GetSaveFileNameA(&ofn); 923c2c66affSColin Finck ok(FALSE == result, "expected FALSE, got %d\n", result); 924c2c66affSColin Finck ok(0 == CommDlgExtendedError(), "expected 0, got %d\n", 925c2c66affSColin Finck CommDlgExtendedError()); 926c2c66affSColin Finck } 927c2c66affSColin Finck 928c2c66affSColin Finck static void test_resizable2(void) 929c2c66affSColin Finck { 930c2c66affSColin Finck OPENFILENAMEA ofn = {0}; 931c2c66affSColin Finck char filename[1024] = "pls press Enter if sizable, Esc otherwise"; 932c2c66affSColin Finck DWORD ret; 933c2c66affSColin Finck 934c2c66affSColin Finck /* interactive because there is no hook function */ 935c2c66affSColin Finck if( !winetest_interactive) { 936c2c66affSColin Finck skip( "some interactive resizable dialog tests (set WINETEST_INTERACTIVE=1)\n"); 937c2c66affSColin Finck return; 938c2c66affSColin Finck } 939c2c66affSColin Finck ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400A; 940c2c66affSColin Finck ofn.lpstrFile = filename; 941c2c66affSColin Finck ofn.nMaxFile = 1024; 942c2c66affSColin Finck ofn.lpfnHook = NULL; 943c2c66affSColin Finck ofn.hInstance = GetModuleHandleA(NULL); 944c2c66affSColin Finck ofn.lpTemplateName = "template1"; 945c2c66affSColin Finck ofn.Flags = OFN_EXPLORER; 946c2c66affSColin Finck ret = GetOpenFileNameA(&ofn); 947*234f89c0SAmine Khaldi ok( ret == TRUE, "File Dialog should have been sizable\n"); 948c2c66affSColin Finck ret = CommDlgExtendedError(); 949c2c66affSColin Finck ok(!ret, "CommDlgExtendedError returned %#x\n", ret); 950c2c66affSColin Finck ofn.Flags = OFN_EXPLORER | OFN_ENABLETEMPLATE; 951c2c66affSColin Finck ret = GetOpenFileNameA(&ofn); 952*234f89c0SAmine Khaldi ok( !ret, "File Dialog should NOT have been sizable\n"); 953c2c66affSColin Finck ret = CommDlgExtendedError(); 954c2c66affSColin Finck ok(!ret, "CommDlgExtendedError returned %#x\n", ret); 955c2c66affSColin Finck ofn.Flags = OFN_EXPLORER | OFN_ENABLETEMPLATEHANDLE; 956c2c66affSColin Finck ofn.hInstance = LoadResource( GetModuleHandleA(NULL), FindResourceA( GetModuleHandleA(NULL), "template1", (LPSTR)RT_DIALOG)); 957c2c66affSColin Finck ofn.lpTemplateName = NULL; 958c2c66affSColin Finck ret = GetOpenFileNameA(&ofn); 959*234f89c0SAmine Khaldi ok( !ret, "File Dialog should NOT have been sizable\n"); 960c2c66affSColin Finck ret = CommDlgExtendedError(); 961c2c66affSColin Finck ok(!ret, "CommDlgExtendedError returned %#x\n", ret); 962c2c66affSColin Finck ofn.Flags = OFN_EXPLORER | OFN_ENABLEHOOK; 963c2c66affSColin Finck ret = GetOpenFileNameA(&ofn); 964*234f89c0SAmine Khaldi ok( !ret, "File Dialog should NOT have been sizable\n"); 965c2c66affSColin Finck ret = CommDlgExtendedError(); 966c2c66affSColin Finck ok(!ret, "CommDlgExtendedError returned %#x\n", ret); 967c2c66affSColin Finck } 968c2c66affSColin Finck 969c2c66affSColin Finck static void test_mru(void) 970c2c66affSColin Finck { 971c2c66affSColin Finck ok_wndproc_testcase testcase = {0}; 972c2c66affSColin Finck OPENFILENAMEA ofn = { OPENFILENAME_SIZE_VERSION_400A }; 973c2c66affSColin Finck const char *test_dir_name = "C:\\mru_test"; 974c2c66affSColin Finck const char *test_file_name = "test.txt"; 975c2c66affSColin Finck const char *test_full_path = "C:\\mru_test\\test.txt"; 976c2c66affSColin Finck char filename_buf[MAX_PATH]; 977c2c66affSColin Finck DWORD ret; 978c2c66affSColin Finck 979c2c66affSColin Finck ofn.lpstrFile = filename_buf; 980c2c66affSColin Finck ofn.nMaxFile = sizeof(filename_buf); 981c2c66affSColin Finck ofn.lpTemplateName = "template1"; 982c2c66affSColin Finck ofn.hInstance = GetModuleHandleA(NULL); 983c2c66affSColin Finck ofn.Flags = OFN_ENABLEHOOK | OFN_EXPLORER | OFN_ENABLETEMPLATE | OFN_NOCHANGEDIR; 984c2c66affSColin Finck ofn.lCustData = (LPARAM)&testcase; 985c2c66affSColin Finck ofn.lpfnHook = test_ok_wndproc; 986c2c66affSColin Finck 987c2c66affSColin Finck SetLastError(0xdeadbeef); 988c2c66affSColin Finck ret = CreateDirectoryA(test_dir_name, NULL); 989c2c66affSColin Finck ok(ret == TRUE, "CreateDirectoryA should have succeeded: %d\n", GetLastError()); 990c2c66affSColin Finck 991c2c66affSColin Finck /* "teach" comdlg32 about this directory */ 992c2c66affSColin Finck strcpy(filename_buf, test_full_path); 993c2c66affSColin Finck SetLastError(0xdeadbeef); 994c2c66affSColin Finck ret = GetOpenFileNameA(&ofn); 995c2c66affSColin Finck ok(ret, "GetOpenFileNameA should have succeeded: %d\n", GetLastError()); 996c2c66affSColin Finck ret = CommDlgExtendedError(); 997c2c66affSColin Finck ok(!ret, "CommDlgExtendedError returned %x\n", ret); 998c2c66affSColin Finck ok(testcase.actclose, "Open File dialog should have closed.\n"); 999c2c66affSColin Finck ok(!strcmp(ofn.lpstrFile, test_full_path), "Expected to get %s, got %s\n", test_full_path, ofn.lpstrFile); 1000c2c66affSColin Finck 1001c2c66affSColin Finck /* get a filename without a full path. it should return the file in 1002c2c66affSColin Finck * test_dir_name, not in the CWD */ 1003c2c66affSColin Finck strcpy(filename_buf, test_file_name); 1004c2c66affSColin Finck SetLastError(0xdeadbeef); 1005c2c66affSColin Finck ret = GetOpenFileNameA(&ofn); 1006c2c66affSColin Finck ok(ret, "GetOpenFileNameA should have succeeded: %d\n", GetLastError()); 1007c2c66affSColin Finck ret = CommDlgExtendedError(); 1008c2c66affSColin Finck ok(!ret, "CommDlgExtendedError returned %x\n", ret); 1009c2c66affSColin Finck ok(testcase.actclose, "Open File dialog should have closed.\n"); 1010c2c66affSColin Finck if(strcmp(ofn.lpstrFile, test_full_path) != 0) 1011c2c66affSColin Finck win_skip("Platform doesn't save MRU data\n"); 1012c2c66affSColin Finck 1013c2c66affSColin Finck SetLastError(0xdeadbeef); 1014c2c66affSColin Finck ret = RemoveDirectoryA(test_dir_name); 1015c2c66affSColin Finck ok(ret == TRUE, "RemoveDirectoryA should have succeeded: %d\n", GetLastError()); 1016c2c66affSColin Finck } 1017c2c66affSColin Finck 1018c2c66affSColin Finck static UINT_PTR WINAPI test_extension_wndproc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) 1019c2c66affSColin Finck { 1020c2c66affSColin Finck HWND parent = GetParent( dlg); 1021c2c66affSColin Finck if( msg == WM_NOTIFY) { 1022c2c66affSColin Finck SetTimer( dlg, 0, 1000, 0); 1023c2c66affSColin Finck PostMessageA( parent, WM_COMMAND, IDOK, 0); 1024c2c66affSColin Finck } 1025c2c66affSColin Finck if( msg == WM_TIMER) { 1026c2c66affSColin Finck /* the dialog did not close automatically */ 1027c2c66affSColin Finck KillTimer( dlg, 0); 1028c2c66affSColin Finck PostMessageA( parent, WM_COMMAND, IDCANCEL, 0); 1029c2c66affSColin Finck } 1030c2c66affSColin Finck return FALSE; 1031c2c66affSColin Finck } 1032c2c66affSColin Finck 1033c2c66affSColin Finck static void test_extension_helper(OPENFILENAMEA* ofn, const char *filter, 1034c2c66affSColin Finck const char *expected_filename) 1035c2c66affSColin Finck { 1036c2c66affSColin Finck char *filename_ptr; 1037c2c66affSColin Finck DWORD ret; 1038c2c66affSColin Finck BOOL boolret; 1039c2c66affSColin Finck 1040c2c66affSColin Finck strcpy(ofn->lpstrFile, "deadbeef"); 1041c2c66affSColin Finck ofn->lpstrFilter = filter; 1042c2c66affSColin Finck 1043c2c66affSColin Finck boolret = GetSaveFileNameA(ofn); 1044c2c66affSColin Finck ok(boolret, "%s: expected TRUE\n", filter); 1045c2c66affSColin Finck 1046c2c66affSColin Finck ret = CommDlgExtendedError(); 1047c2c66affSColin Finck ok(!ret, "%s: CommDlgExtendedError returned %#x\n", filter, ret); 1048c2c66affSColin Finck 1049c2c66affSColin Finck filename_ptr = ofn->lpstrFile + ofn->nFileOffset; 1050c2c66affSColin Finck ok(strcmp(filename_ptr, expected_filename) == 0, 1051c2c66affSColin Finck "%s: Filename is %s, expected %s\n", filter, filename_ptr, expected_filename); 1052c2c66affSColin Finck } 1053c2c66affSColin Finck 1054c2c66affSColin Finck static void test_extension(void) 1055c2c66affSColin Finck { 1056c2c66affSColin Finck OPENFILENAMEA ofn = { OPENFILENAME_SIZE_VERSION_400A }; 1057c2c66affSColin Finck char filename[1024] = {0}; 1058c2c66affSColin Finck char curdir[MAX_PATH]; 1059c2c66affSColin Finck unsigned int i; 1060c2c66affSColin Finck BOOL boolret; 1061c2c66affSColin Finck 1062c2c66affSColin Finck const char *defext_concrete_filters[] = { 1063c2c66affSColin Finck "TestFilter (*.abc)\0*.abc\0", 1064c2c66affSColin Finck "TestFilter (*.abc;)\0*.abc;\0", 1065c2c66affSColin Finck "TestFilter (*.abc;*.def)\0*.abc;*.def\0", 1066c2c66affSColin Finck }; 1067c2c66affSColin Finck 1068c2c66affSColin Finck const char *defext_wildcard_filters[] = { 1069c2c66affSColin Finck "TestFilter (*.pt*)\0*.pt*\0", 1070c2c66affSColin Finck "TestFilter (*.pt*;*.abc)\0*.pt*;*.abc\0", 1071c2c66affSColin Finck "TestFilter (*.ab?)\0*.ab?\0", 1072c2c66affSColin Finck "TestFilter (*.*)\0*.*\0", 1073c2c66affSColin Finck "TestFilter (*sav)\0*sav\0", 1074c2c66affSColin Finck NULL /* is a test, not an endmark! */ 1075c2c66affSColin Finck }; 1076c2c66affSColin Finck 1077c2c66affSColin Finck boolret = GetCurrentDirectoryA(sizeof(curdir), curdir); 1078c2c66affSColin Finck ok(boolret, "Failed to get current dir err %d\n", GetLastError()); 1079c2c66affSColin Finck 1080c2c66affSColin Finck ofn.hwndOwner = NULL; 1081c2c66affSColin Finck ofn.lpstrFile = filename; 1082c2c66affSColin Finck ofn.nMaxFile = MAX_PATH; 1083c2c66affSColin Finck ofn.Flags = OFN_EXPLORER | OFN_ENABLEHOOK; 1084c2c66affSColin Finck ofn.lpstrInitialDir = curdir; 1085c2c66affSColin Finck ofn.lpfnHook = test_extension_wndproc; 1086c2c66affSColin Finck ofn.nFileExtension = 0; 1087c2c66affSColin Finck 1088c2c66affSColin Finck ofn.lpstrDefExt = NULL; 1089c2c66affSColin Finck 1090c2c66affSColin Finck /* Without lpstrDefExt, append no extension */ 1091c2c66affSColin Finck test_extension_helper(&ofn, "TestFilter (*.abc) lpstrDefExt=NULL\0*.abc\0", "deadbeef"); 1092c2c66affSColin Finck test_extension_helper(&ofn, "TestFilter (*.ab?) lpstrDefExt=NULL\0*.ab?\0", "deadbeef"); 1093c2c66affSColin Finck 1094c2c66affSColin Finck ofn.lpstrDefExt = ""; 1095c2c66affSColin Finck 1096c2c66affSColin Finck /* If lpstrDefExt="" and the filter has a concrete extension, append it */ 1097c2c66affSColin Finck test_extension_helper(&ofn, "TestFilter (*.abc) lpstrDefExt=\"\"\0*.abc\0", "deadbeef.abc"); 1098c2c66affSColin Finck 1099c2c66affSColin Finck /* If lpstrDefExt="" and the filter has a wildcard extension, do nothing */ 1100c2c66affSColin Finck test_extension_helper(&ofn, "TestFilter (*.ab?) lpstrDefExt=\"\"\0*.ab?\0", "deadbeef"); 1101c2c66affSColin Finck 1102c2c66affSColin Finck ofn.lpstrDefExt = "xyz"; 1103c2c66affSColin Finck 1104c2c66affSColin Finck /* Append concrete extensions from filters */ 1105c2c66affSColin Finck for (i = 0; i < ARRAY_SIZE(defext_concrete_filters); i++) { 1106c2c66affSColin Finck test_extension_helper(&ofn, defext_concrete_filters[i], "deadbeef.abc"); 1107c2c66affSColin Finck } 1108c2c66affSColin Finck 1109c2c66affSColin Finck /* Append nothing from this filter */ 1110c2c66affSColin Finck test_extension_helper(&ofn, "TestFilter (*.)\0*.\0", "deadbeef"); 1111c2c66affSColin Finck 1112c2c66affSColin Finck /* Ignore wildcard extensions in filters */ 1113c2c66affSColin Finck for (i = 0; i < ARRAY_SIZE(defext_wildcard_filters); i++) { 1114c2c66affSColin Finck test_extension_helper(&ofn, defext_wildcard_filters[i], "deadbeef.xyz"); 1115c2c66affSColin Finck } 1116c2c66affSColin Finck 1117c2c66affSColin Finck /* Append valid extensions consisting of multiple parts */ 1118c2c66affSColin Finck test_extension_helper(&ofn, "TestFilter (*.abc.def)\0*.abc.def\0", "deadbeef.abc.def"); 1119c2c66affSColin Finck test_extension_helper(&ofn, "TestFilter (.abc.def)\0.abc.def\0", "deadbeef.abc.def"); 1120c2c66affSColin Finck test_extension_helper(&ofn, "TestFilter (*.*.def)\0*.*.def\0", "deadbeef.xyz"); 1121c2c66affSColin Finck } 1122c2c66affSColin Finck 1123c2c66affSColin Finck #undef ARRAY_SIZE 1124c2c66affSColin Finck 1125c2c66affSColin Finck 1126c2c66affSColin Finck static BOOL WINAPI test_null_enum(HWND hwnd, LPARAM lParam) 1127c2c66affSColin Finck { 1128c2c66affSColin Finck /* Find the textbox and send a filename so IDOK will work. 1129c2c66affSColin Finck If the file textbox is empty IDOK will be ignored */ 1130c2c66affSColin Finck CHAR className[20]; 1131c2c66affSColin Finck if(GetClassNameA(hwnd, className, sizeof(className)) > 0 && !strcmp("Edit",className)) 1132c2c66affSColin Finck { 1133c2c66affSColin Finck SetWindowTextA(hwnd, "testfile"); 1134c2c66affSColin Finck return FALSE; /* break window enumeration */ 1135c2c66affSColin Finck } 1136c2c66affSColin Finck return TRUE; 1137c2c66affSColin Finck } 1138c2c66affSColin Finck 1139c2c66affSColin Finck static UINT_PTR WINAPI test_null_wndproc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) 1140c2c66affSColin Finck { 1141c2c66affSColin Finck HWND parent = GetParent( dlg); 1142c2c66affSColin Finck if( msg == WM_NOTIFY) { 1143c2c66affSColin Finck SetTimer( dlg, 0, 100, 0); 1144c2c66affSColin Finck SetTimer( dlg, 1, 1000, 0); 1145c2c66affSColin Finck EnumChildWindows( parent, test_null_enum, 0); 1146c2c66affSColin Finck } 1147c2c66affSColin Finck if( msg == WM_TIMER) { 1148c2c66affSColin Finck if(!wParam) 1149c2c66affSColin Finck PostMessageA( parent, WM_COMMAND, IDOK, 0); 1150c2c66affSColin Finck else { 1151c2c66affSColin Finck /* the dialog did not close automatically */ 1152c2c66affSColin Finck KillTimer( dlg, 0); 1153c2c66affSColin Finck PostMessageA( parent, WM_COMMAND, IDCANCEL, 0); 1154c2c66affSColin Finck } 1155c2c66affSColin Finck } 1156c2c66affSColin Finck return FALSE; 1157c2c66affSColin Finck } 1158c2c66affSColin Finck 1159c2c66affSColin Finck static void test_null_filename(void) 1160c2c66affSColin Finck { 1161c2c66affSColin Finck OPENFILENAMEA ofnA = {0}; 1162c2c66affSColin Finck OPENFILENAMEW ofnW = {0}; 1163c2c66affSColin Finck WCHAR filterW[] = {'t','e','x','t','\0','*','.','t','x','t','\0', 1164c2c66affSColin Finck 'A','l','l','\0','*','\0','\0'}; 1165c2c66affSColin Finck DWORD ret; 1166c2c66affSColin Finck 1167c2c66affSColin Finck ofnA.lStructSize = OPENFILENAME_SIZE_VERSION_400A; 1168c2c66affSColin Finck ofnA.lpstrFile = NULL; 1169c2c66affSColin Finck ofnA.nMaxFile = 0; 1170c2c66affSColin Finck ofnA.nFileOffset = 0xdead; 1171c2c66affSColin Finck ofnA.nFileExtension = 0xbeef; 1172c2c66affSColin Finck ofnA.lpfnHook = test_null_wndproc; 1173c2c66affSColin Finck ofnA.Flags = OFN_ENABLEHOOK | OFN_EXPLORER; 1174c2c66affSColin Finck ofnA.hInstance = GetModuleHandleA(NULL); 1175c2c66affSColin Finck ofnA.lpstrFilter = "text\0*.txt\0All\0*\0\0"; 1176c2c66affSColin Finck ofnA.lpstrDefExt = NULL; 1177c2c66affSColin Finck ret = GetOpenFileNameA(&ofnA); 1178c2c66affSColin Finck todo_wine ok(ret, "GetOpenFileNameA returned %#x\n", ret); 1179c2c66affSColin Finck ret = CommDlgExtendedError(); 1180c2c66affSColin Finck todo_wine ok(!ret, "CommDlgExtendedError returned %#x, should be 0\n", ret); 1181c2c66affSColin Finck 1182c2c66affSColin Finck todo_wine ok(ofnA.nFileOffset != 0xdead, "ofnA.nFileOffset is 0xdead\n"); 1183c2c66affSColin Finck todo_wine ok(ofnA.nFileExtension != 0xbeef, "ofnA.nFileExtension is 0xbeef\n"); 1184c2c66affSColin Finck 1185c2c66affSColin Finck ofnA.lpstrFile = NULL; 1186c2c66affSColin Finck ofnA.nMaxFile = 1024; /* bogus input - lpstrFile = NULL but fake 1024 bytes available */ 1187c2c66affSColin Finck ofnA.nFileOffset = 0xdead; 1188c2c66affSColin Finck ofnA.nFileExtension = 0xbeef; 1189c2c66affSColin Finck ret = GetOpenFileNameA(&ofnA); 1190c2c66affSColin Finck ok(ret, "GetOpenFileNameA returned %#x\n", ret); 1191c2c66affSColin Finck ret = CommDlgExtendedError(); 1192c2c66affSColin Finck ok(!ret, "CommDlgExtendedError returned %#x\n", ret); 1193c2c66affSColin Finck 1194c2c66affSColin Finck ok(ofnA.nFileOffset != 0xdead, "ofnA.nFileOffset is 0xdead\n"); 1195c2c66affSColin Finck ok(ofnA.nFileExtension == 0, "ofnA.nFileExtension is 0x%x, should be 0\n", ofnA.nFileExtension); 1196c2c66affSColin Finck 1197c2c66affSColin Finck /* unicode tests */ 1198c2c66affSColin Finck ofnW.lStructSize = OPENFILENAME_SIZE_VERSION_400W; 1199c2c66affSColin Finck ofnW.lpstrFile = NULL; 1200c2c66affSColin Finck ofnW.nMaxFile = 0; 1201c2c66affSColin Finck ofnW.nFileOffset = 0xdead; 1202c2c66affSColin Finck ofnW.nFileExtension = 0xbeef; 1203c2c66affSColin Finck ofnW.lpfnHook = test_null_wndproc; 1204c2c66affSColin Finck ofnW.Flags = OFN_ENABLEHOOK | OFN_EXPLORER; 1205c2c66affSColin Finck ofnW.hInstance = GetModuleHandleW(NULL); 1206c2c66affSColin Finck ofnW.lpstrFilter = filterW; 1207c2c66affSColin Finck ofnW.lpstrDefExt = NULL; 1208c2c66affSColin Finck ret = GetOpenFileNameW(&ofnW); 1209c2c66affSColin Finck todo_wine ok(ret, "GetOpenFileNameW returned %#x\n", ret); 1210c2c66affSColin Finck ret = CommDlgExtendedError(); 1211c2c66affSColin Finck todo_wine ok(!ret, "CommDlgExtendedError returned %#x\n", ret); 1212c2c66affSColin Finck 1213c2c66affSColin Finck todo_wine ok(ofnW.nFileOffset != 0xdead, "ofnW.nFileOffset is 0xdead\n"); 1214c2c66affSColin Finck todo_wine ok(ofnW.nFileExtension != 0xbeef, "ofnW.nFileExtension is 0xbeef\n"); 1215c2c66affSColin Finck 1216c2c66affSColin Finck ofnW.lpstrFile = NULL; 1217c2c66affSColin Finck ofnW.nMaxFile = 1024; /* bogus input - lpstrFile = NULL but fake 1024 bytes available */ 1218c2c66affSColin Finck ofnW.nFileOffset = 0xdead; 1219c2c66affSColin Finck ofnW.nFileExtension = 0xbeef; 1220c2c66affSColin Finck ret = GetOpenFileNameW(&ofnW); 1221c2c66affSColin Finck ok(ret, "GetOpenFileNameA returned %#x\n", ret); 1222c2c66affSColin Finck ret = CommDlgExtendedError(); 1223c2c66affSColin Finck ok(!ret, "CommDlgExtendedError returned %#x\n", ret); 1224c2c66affSColin Finck 1225c2c66affSColin Finck ok(ofnW.nFileOffset != 0xdead, "ofnW.nFileOffset is 0xdead\n"); 1226c2c66affSColin Finck ok(ofnW.nFileExtension == 0, "ofnW.nFileExtension is 0x%x, should be 0\n", ofnW.nFileExtension); 1227c2c66affSColin Finck } 1228c2c66affSColin Finck 1229c2c66affSColin Finck static void test_directory_filename(void) 1230c2c66affSColin Finck { 1231c2c66affSColin Finck OPENFILENAMEA ofnA = {0}; 1232c2c66affSColin Finck OPENFILENAMEW ofnW = {0}; 1233c2c66affSColin Finck WCHAR filterW[] = {'t','e','x','t','\0','*','.','t','x','t','\0', 1234c2c66affSColin Finck 'A','l','l','\0','*','\0','\0'}; 1235c2c66affSColin Finck char szInitialDir[MAX_PATH] = {0}; 1236c2c66affSColin Finck WCHAR szInitialDirW[MAX_PATH] = {0}; 1237c2c66affSColin Finck DWORD ret; 1238c2c66affSColin Finck 1239c2c66affSColin Finck GetWindowsDirectoryA(szInitialDir, MAX_PATH); 1240c2c66affSColin Finck GetWindowsDirectoryW(szInitialDirW, MAX_PATH); 1241c2c66affSColin Finck 1242c2c66affSColin Finck szInitialDir[strlen(szInitialDir)] = '\\'; 1243c2c66affSColin Finck szInitialDirW[lstrlenW(szInitialDirW)] = '\\'; 1244c2c66affSColin Finck 1245c2c66affSColin Finck ofnA.lStructSize = OPENFILENAME_SIZE_VERSION_400A; 1246c2c66affSColin Finck ofnA.lpstrFile = szInitialDir; 1247c2c66affSColin Finck ofnA.nMaxFile = MAX_PATH; 1248c2c66affSColin Finck ofnA.lpfnHook = test_null_wndproc; 1249c2c66affSColin Finck ofnA.Flags = OFN_ENABLEHOOK | OFN_EXPLORER; 1250c2c66affSColin Finck ofnA.hInstance = GetModuleHandleA(NULL); 1251c2c66affSColin Finck ofnA.lpstrFilter = "text\0*.txt\0All\0*\0\0"; 1252c2c66affSColin Finck ofnA.lpstrDefExt = NULL; 1253c2c66affSColin Finck ret = GetOpenFileNameA(&ofnA); 1254c2c66affSColin Finck todo_wine ok(!ret, "GetOpenFileNameA returned %#x\n", ret); 1255c2c66affSColin Finck 1256c2c66affSColin Finck /* unicode tests */ 1257c2c66affSColin Finck ofnW.lStructSize = OPENFILENAME_SIZE_VERSION_400W; 1258c2c66affSColin Finck ofnW.lpstrFile = szInitialDirW; 1259c2c66affSColin Finck ofnW.nMaxFile = MAX_PATH; 1260c2c66affSColin Finck ofnW.lpfnHook = test_null_wndproc; 1261c2c66affSColin Finck ofnW.Flags = OFN_ENABLEHOOK | OFN_EXPLORER; 1262c2c66affSColin Finck ofnW.hInstance = GetModuleHandleW(NULL); 1263c2c66affSColin Finck ofnW.lpstrFilter = filterW; 1264c2c66affSColin Finck ofnW.lpstrDefExt = NULL; 1265c2c66affSColin Finck ret = GetOpenFileNameW(&ofnW); 1266c2c66affSColin Finck todo_wine ok(!ret, "GetOpenFileNameW returned %#x\n", ret); 1267c2c66affSColin Finck } 1268c2c66affSColin Finck 1269c2c66affSColin Finck static UINT_PTR WINAPI test_ole_init_wndproc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) 1270c2c66affSColin Finck { 1271c2c66affSColin Finck HRESULT hr; 1272c2c66affSColin Finck 1273c2c66affSColin Finck hr = OleInitialize(NULL); 1274c2c66affSColin Finck ok(hr == S_FALSE, "OleInitialize() returned %#x\n", hr); 1275c2c66affSColin Finck OleUninitialize(); 1276c2c66affSColin Finck 1277c2c66affSColin Finck if (msg == WM_NOTIFY) 1278c2c66affSColin Finck PostMessageA(GetParent(dlg), WM_COMMAND, IDCANCEL, 0); 1279c2c66affSColin Finck return FALSE; 1280c2c66affSColin Finck } 1281c2c66affSColin Finck 1282c2c66affSColin Finck static LRESULT CALLBACK hook_proc(int code, WPARAM wp, LPARAM lp) 1283c2c66affSColin Finck { 1284c2c66affSColin Finck static BOOL first_dlg = TRUE; 1285c2c66affSColin Finck HRESULT hr; 1286c2c66affSColin Finck 1287c2c66affSColin Finck if (code == HCBT_CREATEWND) 1288c2c66affSColin Finck { 1289c2c66affSColin Finck CBT_CREATEWNDW *c = (CBT_CREATEWNDW *)lp; 1290c2c66affSColin Finck 1291c2c66affSColin Finck if (c->lpcs->lpszClass == (LPWSTR)WC_DIALOG) 1292c2c66affSColin Finck { 1293c2c66affSColin Finck /* OleInitialize() creates a window for the main apartment. Since 1294c2c66affSColin Finck * Vista OleInitialize() is called before the file dialog is 1295c2c66affSColin Finck * created. SimCity 2000 expects that the first window created 1296c2c66affSColin Finck * after GetOpenFileA() is a file dialog window. Mark Vista+ 1297c2c66affSColin Finck * behavior as broken. */ 1298c2c66affSColin Finck hr = OleInitialize(NULL); 1299c2c66affSColin Finck ok((first_dlg ? hr == S_OK : hr == S_FALSE) 1300c2c66affSColin Finck || broken(first_dlg && hr == S_FALSE), 1301c2c66affSColin Finck "OleInitialize() returned %#x (first dialog %#x)\n", hr, first_dlg); 1302c2c66affSColin Finck OleUninitialize(); 1303c2c66affSColin Finck first_dlg = FALSE; 1304c2c66affSColin Finck } 1305c2c66affSColin Finck } 1306c2c66affSColin Finck 1307c2c66affSColin Finck return CallNextHookEx(NULL, code, wp, lp); 1308c2c66affSColin Finck } 1309c2c66affSColin Finck 1310c2c66affSColin Finck static void test_ole_initialization(void) 1311c2c66affSColin Finck { 1312c2c66affSColin Finck char file[MAX_PATH] = {0}; 1313c2c66affSColin Finck OPENFILENAMEA ofn = {0}; 1314c2c66affSColin Finck HRESULT hr; 1315c2c66affSColin Finck HHOOK hook; 1316c2c66affSColin Finck BOOL ret; 1317c2c66affSColin Finck 1318c2c66affSColin Finck hook = SetWindowsHookExW(WH_CBT, hook_proc, NULL, GetCurrentThreadId()); 1319c2c66affSColin Finck 1320c2c66affSColin Finck ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400A; 1321c2c66affSColin Finck ofn.lpstrFile = file; 1322c2c66affSColin Finck ofn.nMaxFile = MAX_PATH; 1323c2c66affSColin Finck ofn.lpfnHook = test_ole_init_wndproc; 1324c2c66affSColin Finck ofn.Flags = OFN_ENABLEHOOK | OFN_EXPLORER; 1325c2c66affSColin Finck ofn.hInstance = GetModuleHandleA(NULL); 1326c2c66affSColin Finck ret = GetOpenFileNameA(&ofn); 1327c2c66affSColin Finck ok(!ret, "GetOpenFileNameA returned %#x\n", ret); 1328c2c66affSColin Finck 1329c2c66affSColin Finck hr = OleInitialize(NULL); 1330c2c66affSColin Finck ok(hr == S_OK, "OleInitialize() returned %#x\n", hr); 1331c2c66affSColin Finck OleUninitialize(); 1332c2c66affSColin Finck 1333c2c66affSColin Finck UnhookWindowsHookEx(hook); 1334c2c66affSColin Finck } 1335c2c66affSColin Finck 1336c2c66affSColin Finck START_TEST(filedlg) 1337c2c66affSColin Finck { 1338c2c66affSColin Finck test_DialogCancel(); 1339c2c66affSColin Finck test_create_view_window2(); 1340c2c66affSColin Finck test_create_view_template(); 1341c2c66affSColin Finck test_arrange(); 1342c2c66affSColin Finck test_resize(); 1343c2c66affSColin Finck test_ok(); 1344c2c66affSColin Finck test_getfolderpath(); 1345c2c66affSColin Finck test_mru(); 1346c2c66affSColin Finck if( resizesupported) test_resizable2(); 1347c2c66affSColin Finck test_extension(); 1348c2c66affSColin Finck test_null_filename(); 1349c2c66affSColin Finck test_directory_filename(); 1350c2c66affSColin Finck test_ole_initialization(); 1351c2c66affSColin Finck } 1352