shell32/tests: Test that basic renaming is supported.
[wine/multimedia.git] / dlls / shell32 / tests / brsfolder.c
blob0aebb746134023c6bbf0aec7ab38ae4674cd6690
1 /*
2 * Unit test of the SHBrowseForFolder function.
4 * Copyright 2009-2010 Michael Mc Donnell
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <windows.h>
21 #include <shlobj.h>
22 #include <shobjidl.h>
23 #include <string.h>
25 #include "wine/test.h"
26 #define IDD_MAKENEWFOLDER 0x3746 /* From "../shresdef.h" */
27 #define TIMER_WAIT_MS 50 /* Should be long enough for slow systems */
29 static const char new_folder_name[] = "foo";
32 * Returns the number of folders in a folder.
34 static int get_number_of_folders(LPCSTR path)
36 int number_of_folders = 0;
37 char path_search_string[MAX_PATH];
38 WIN32_FIND_DATA find_data;
39 HANDLE find_handle;
41 strncpy(path_search_string, path, MAX_PATH);
42 strncat(path_search_string, "*", 1);
44 find_handle = FindFirstFile(path_search_string, &find_data);
45 if (find_handle == INVALID_HANDLE_VALUE)
46 return -1;
50 if ((find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
51 strcmp(find_data.cFileName, ".") != 0 &&
52 strcmp(find_data.cFileName, "..") != 0)
54 number_of_folders++;
57 while (FindNextFile(find_handle, &find_data) != 0);
59 return number_of_folders;
62 static BOOL does_folder_or_file_exist(LPCSTR folder_path)
64 DWORD file_attributes = GetFileAttributesA(folder_path);
65 return !(file_attributes == INVALID_FILE_ATTRIBUTES);
69 * Timer callback used by test_click_make_new_folder_button. It simulates a user
70 * making a new folder and calling it "foo".
72 static void CALLBACK make_new_folder_timer_callback(HWND hwnd, UINT uMsg,
73 UINT_PTR idEvent, DWORD dwTime)
75 static int step = 0;
77 switch (step++)
79 case 0:
80 /* Click "Make New Folder" button */
81 PostMessage(hwnd, WM_COMMAND, IDD_MAKENEWFOLDER, 0);
82 break;
83 case 1:
84 /* Set the new folder name to foo by replacing text in edit control */
85 SendMessage(GetFocus(), EM_REPLACESEL, 0, (LPARAM) new_folder_name);
86 SetFocus(hwnd);
87 break;
88 case 2:
89 KillTimer(hwnd, idEvent);
90 /* Close dialog box */
91 SendMessage(hwnd, WM_COMMAND, IDOK, 0);
92 break;
93 default:
94 break;
99 * Callback used by test_click_make_new_folder_button. It sets up a timer to
100 * simulate user input.
102 static int CALLBACK create_new_folder_callback(HWND hwnd, UINT uMsg,
103 LPARAM lParam, LPARAM lpData)
105 switch (uMsg)
107 case BFFM_INITIALIZED:
108 /* User input is simulated in timer callback */
109 SetTimer(hwnd, 0, TIMER_WAIT_MS, make_new_folder_timer_callback);
110 return TRUE;
111 default:
112 return FALSE;
117 * Tests if clicking the "Make New Folder" button in a SHBrowseForFolder
118 * dialog box creates a new folder. (Bug 17986).
120 * Here follows a description of what happens on W2K,Vista, W2K8, W7:
121 * When the "Make New Folder" button is clicked a new folder is created and
122 * inserted into the tree. The folder is given a default name that depends on
123 * the locale (e.g. "New Folder"). The folder name is selected and the dialog
124 * waits for the user to type in a new name. The folder is renamed when the user
125 * types in a name and presses enter.
127 * Note that XP and W2K3 do not select the folder name or wait for the user
128 * to type in a new folder name. This behavior is considered broken as most
129 * users would like to give the folder a name after creating it. The fact that
130 * it originally waited for the user to type in a new folder name(W2K), and then
131 * again was changed back wait for the new folder name(Vista, W2K8, W7),
132 * indicates that MS also believes that it was broken in XP and W2K3.
134 static void test_click_make_new_folder_button(void)
136 HRESULT resCoInit;
137 BROWSEINFO bi;
138 LPITEMIDLIST pidl = NULL;
139 LPITEMIDLIST test_folder_pidl;
140 IShellFolder *test_folder_object;
141 char test_folder_path[MAX_PATH];
142 WCHAR test_folder_pathW[MAX_PATH];
143 CHAR new_folder_path[MAX_PATH];
144 char selected_folder[MAX_PATH];
145 const CHAR title[] = "test_click_make_new_folder_button";
146 int number_of_folders = -1;
147 SHFILEOPSTRUCT shfileop;
149 if (does_folder_or_file_exist(title))
151 skip("The test folder already exists.\n");
152 return;
155 /* Must initialize COM if using the NEWDIAlOGSTYLE according to MSDN. */
156 resCoInit = CoInitialize(NULL);
157 if(!(resCoInit == S_OK || resCoInit == S_FALSE))
159 skip("COM could not be initialized %u\n", GetLastError());
160 return;
163 /* Leave room for concatenating title, two backslashes, and an extra NULL. */
164 if (!GetCurrentDirectoryA(MAX_PATH-strlen(title)-3, test_folder_path))
166 skip("GetCurrentDirectoryA failed %u\n", GetLastError());
168 strncat(test_folder_path, "\\", 1);
169 strncat(test_folder_path, title, MAX_PATH-1);
170 strncat(test_folder_path, "\\", 1);
172 /* Avoid conflicts by creating a test folder. */
173 if (!CreateDirectoryA(title, NULL))
175 skip("CreateDirectoryA failed %u\n", GetLastError());
176 return;
179 /* Initialize browse info struct for SHBrowseForFolder */
180 bi.hwndOwner = NULL;
181 bi.pszDisplayName = (LPTSTR) &selected_folder;
182 bi.lpszTitle = (LPTSTR) title;
183 bi.ulFlags = BIF_NEWDIALOGSTYLE;
184 bi.lpfn = create_new_folder_callback;
185 /* Use test folder as the root folder for dialog box */
186 MultiByteToWideChar(CP_UTF8, 0, test_folder_path, MAX_PATH,
187 test_folder_pathW, MAX_PATH*sizeof(WCHAR));
188 SHGetDesktopFolder(&test_folder_object);
189 test_folder_object->lpVtbl->ParseDisplayName(test_folder_object, NULL, NULL,
190 test_folder_pathW, 0UL, &test_folder_pidl, 0UL);
191 bi.pidlRoot = test_folder_pidl;
193 /* Display dialog box and let callback click the buttons */
194 pidl = SHBrowseForFolder(&bi);
196 number_of_folders = get_number_of_folders(test_folder_path);
197 todo_wine ok(number_of_folders == 1 || broken(number_of_folders == 0) /* W95, W98 */,
198 "Clicking \"Make New Folder\" button did not result in a new folder.\n");
200 /* There should be a new folder foo inside the test folder */
201 strcpy(new_folder_path, test_folder_path);
202 strcat(new_folder_path, new_folder_name);
203 todo_wine ok(does_folder_or_file_exist(new_folder_path)
204 || broken(!does_folder_or_file_exist(new_folder_path)) /* W95, W98, XP, W2K3 */,
205 "The new folder did not get the name %s\n", new_folder_name);
207 /* Remove test folder and any subfolders created in this test */
208 shfileop.hwnd = NULL;
209 shfileop.wFunc = FO_DELETE;
210 /* Path must be double NULL terminated */
211 test_folder_path[strlen(test_folder_path)+1] = '\0';
212 shfileop.pFrom = test_folder_path;
213 shfileop.pTo = NULL;
214 shfileop.fFlags = FOF_NOCONFIRMATION|FOF_NOERRORUI|FOF_SILENT;
215 SHFileOperation(&shfileop);
217 if (pidl)
218 CoTaskMemFree(pidl);
219 if (test_folder_pidl)
220 CoTaskMemFree(test_folder_pidl);
221 if (test_folder_object)
222 test_folder_object->lpVtbl->Release(test_folder_object);
224 CoUninitialize();
227 START_TEST(brsfolder)
229 test_click_make_new_folder_button();