diff --git a/dlls/shell32/tests/Makefile.in b/dlls/shell32/tests/Makefile.in index 2849a330a32..0799944bd32 100644 --- a/dlls/shell32/tests/Makefile.in +++ b/dlls/shell32/tests/Makefile.in @@ -8,6 +8,7 @@ IMPORTS = shell32 ole32 oleaut32 user32 advapi32 kernel32 C_SRCS = \ appbar.c \ autocomplete.c \ + brsfolder.c \ generated.c \ progman_dde.c \ shelllink.c \ diff --git a/dlls/shell32/tests/brsfolder.c b/dlls/shell32/tests/brsfolder.c new file mode 100644 index 00000000000..af2bc73dbe1 --- /dev/null +++ b/dlls/shell32/tests/brsfolder.c @@ -0,0 +1,189 @@ +/* + * Unit test of the SHBrowseForFolder function. + * + * Copyright 2009 Michael Mc Donnell + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#include +#include +#include +#include + +#include "wine/test.h" +#define IDD_MAKENEWFOLDER 0x3746 /* From "../shresdef.h" */ + +/* + * Returns the number of folders in a folder. + */ +static int get_number_of_folders(LPCSTR path) +{ + int number_of_folders = 0; + char path_search_string[MAX_PATH]; + WIN32_FIND_DATA find_data; + HANDLE find_handle; + + strncpy(path_search_string, path, MAX_PATH); + strncat(path_search_string, "*", 1); + + find_handle = FindFirstFile(path_search_string, &find_data); + if (find_handle == INVALID_HANDLE_VALUE) + return -1; + + do + { + if ((find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && + strcmp(find_data.cFileName, ".") != 0 && + strcmp(find_data.cFileName, "..") != 0) + { + number_of_folders++; + } + } + while (FindNextFile(find_handle, &find_data) != 0); + + return number_of_folders; +} + +static BOOL does_folder_or_file_exist(LPCSTR folder_path) +{ + DWORD file_attributes = GetFileAttributesA(folder_path); + return !(file_attributes == INVALID_FILE_ATTRIBUTES); +} + +/* + * Callback used by test_click_make_new_folder_button for SHBrowseForFolder + * dialog box. It clicks the "Make New Folder" button and then closes the dialog + * box. + */ +static int CALLBACK create_new_folder_callback(HWND hwnd, UINT uMsg, + LPARAM lParam, LPARAM lpData) +{ + switch (uMsg) + { + case BFFM_INITIALIZED: + /* Click "Make New Folder" button */ + SendMessage(hwnd, WM_COMMAND, IDD_MAKENEWFOLDER, 0); + /* Close dialog box */ + SendMessage(hwnd, WM_COMMAND, IDCANCEL, 0); + return TRUE; + default: + return FALSE; + } +} + +/* + * Tests if clicking the "Make New Folder" button in a SHBrowseForFolder + * dialog box creates a new folder. (Bug 17986). + * + * The algorithm is: + * 1. Check that there is no "test_click_make_new_folder_button" folder. + * 2. Create a test folder called "test_click_make_new_folder_button". + * 3. Use the test folder as root for SHBrowseForFolder dialog box. + * 3. Hook up SHBrowseForFolder dialog box with callback. + * 4. Display SHBrowseForFolder dialog box. + * 5. Callback clicks "Make New Folder" button (by sending a message). + * 6. Callback closes SHBrowseForFolder dialog box. + * 7. Check that there is a new folder inside the test folder. + * 8. Remove the test folder and any subfolders. + */ +static void test_click_make_new_folder_button(void) +{ + HRESULT resCoInit; + BROWSEINFO bi; + LPITEMIDLIST pidl = NULL; + LPITEMIDLIST test_folder_pidl; + IShellFolder *test_folder_object; + char test_folder_path[MAX_PATH]; + WCHAR test_folder_pathW[MAX_PATH]; + char selected_folder[MAX_PATH]; + const CHAR title[] = "test_click_make_new_folder_button"; + int number_of_folders = -1; + SHFILEOPSTRUCT shfileop; + + if (does_folder_or_file_exist(title)) + { + skip("The test folder already exists.\n"); + return; + } + + /* Must initialize COM if using the NEWDIAlOGSTYLE according to MSDN. */ + resCoInit = CoInitialize(NULL); + if(!(resCoInit == S_OK || resCoInit == S_FALSE)) + { + skip("COM could not be initialized %u\n", GetLastError()); + return; + } + + /* Leave room for concatenating title, two backslashes, and an extra NULL. */ + if (!GetCurrentDirectoryA(MAX_PATH-strlen(title)-3, test_folder_path)) + { + skip("GetCurrentDirectoryA failed %u\n", GetLastError()); + } + strncat(test_folder_path, "\\", 1); + strncat(test_folder_path, title, MAX_PATH-1); + strncat(test_folder_path, "\\", 1); + + /* Avoid conflicts by creating a test folder. */ + if (!CreateDirectoryA(title, NULL)) + { + skip("CreateDirectoryA failed %u\n", GetLastError()); + return; + } + + /* Initialize browse info struct for SHBrowseForFolder */ + bi.hwndOwner = NULL; + bi.pszDisplayName = (LPTSTR) &selected_folder; + bi.lpszTitle = (LPTSTR) title; + bi.ulFlags = BIF_NEWDIALOGSTYLE; + bi.lpfn = create_new_folder_callback; + /* Use test folder as the root folder for dialog box */ + MultiByteToWideChar(CP_UTF8, 0, test_folder_path, MAX_PATH, + test_folder_pathW, MAX_PATH*sizeof(WCHAR)); + SHGetDesktopFolder(&test_folder_object); + test_folder_object->lpVtbl->ParseDisplayName(test_folder_object, NULL, NULL, + test_folder_pathW, 0UL, &test_folder_pidl, 0UL); + bi.pidlRoot = test_folder_pidl; + + /* Display dialog box and let callback click the buttons */ + pidl = SHBrowseForFolder(&bi); + + number_of_folders = get_number_of_folders(test_folder_path); + todo_wine ok(number_of_folders == 1 || broken(number_of_folders == 0) /* W98, W2K */, + "Clicking \"Make New Folder\" button did not result in a new folder.\n"); + + /* Remove test folder and any subfolders created in this test */ + shfileop.hwnd = NULL; + shfileop.wFunc = FO_DELETE; + /* Path must be double NULL terminated */ + test_folder_path[strlen(test_folder_path)+1] = '\0'; + shfileop.pFrom = test_folder_path; + shfileop.pTo = NULL; + shfileop.fFlags = FOF_NOCONFIRMATION|FOF_NOERRORUI|FOF_SILENT; + SHFileOperation(&shfileop); + + if (pidl) + CoTaskMemFree(pidl); + if (test_folder_pidl) + CoTaskMemFree(test_folder_pidl); + if (test_folder_object) + test_folder_object->lpVtbl->Release(test_folder_object); + + CoUninitialize(); +} + +START_TEST(brsfolder) +{ + test_click_make_new_folder_button(); +}