/*
 * Unit test of the SHBrowseForFolder function.
 *
 * Copyright 2009-2010 Michael Mc Donnell
 * Copyright 2011 André Hentschel
 *
 * 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 <windows.h>
#include <shlobj.h>
#include <shobjidl.h>
#include <string.h>

#include "wine/test.h"
#define IDD_MAKENEWFOLDER 0x3746 /* From "../shresdef.h" */
#define TIMER_WAIT_MS 50 /* Should be long enough for slow systems */

static const char new_folder_name[] = "foo";
static LPITEMIDLIST selected_folder_pidl;

/*
 * 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);

    FindClose(find_handle);
    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);
}

/*
 * Timer callback used by test_click_make_new_folder_button. It simulates a user
 * making a new folder and calling it "foo".
 */
static void CALLBACK make_new_folder_timer_callback(HWND hwnd, UINT uMsg,
                                                    UINT_PTR idEvent, DWORD dwTime)
{
    static int step = 0;

    switch (step++)
    {
    case 0:
        /* Click "Make New Folder" button */
        PostMessage(hwnd, WM_COMMAND, IDD_MAKENEWFOLDER, 0);
        break;
    case 1:
        /* Set the new folder name to foo by replacing text in edit control */
        SendMessage(GetFocus(), EM_REPLACESEL, 0, (LPARAM) new_folder_name);
        SetFocus(hwnd);
        break;
    case 2:
        /*
         * The test does not trigger the correct state on Windows. This results
         * in the new folder pidl not being returned. The result is as
         * expected if the same steps are done manually.
         * Sending the down key selects the new folder again which sets the
         * correct state. This ensures that the correct pidl is returned.
         */
        keybd_event(VK_DOWN, 0, 0, 0);
        break;
    case 3:
        keybd_event(VK_DOWN, 0, KEYEVENTF_KEYUP, 0);
        break;
    case 4:
        KillTimer(hwnd, idEvent);
        /* Close dialog box */
        SendMessage(hwnd, WM_COMMAND, IDOK, 0);
        break;
    default:
        break;
    }
}

/*
 * Callback used by test_click_make_new_folder_button. It sets up a timer to
 * simulate user input.
 */
static int CALLBACK create_new_folder_callback(HWND hwnd, UINT uMsg,
                                               LPARAM lParam, LPARAM lpData)
{
    switch (uMsg)
    {
    case BFFM_INITIALIZED:
        /* User input is simulated in timer callback */
        SetTimer(hwnd, 0, TIMER_WAIT_MS, make_new_folder_timer_callback);
        return TRUE;
    default:
        return FALSE;
    }
}

/*
 * Tests if clicking the "Make New Folder" button in a SHBrowseForFolder
 * dialog box creates a new folder. (Bug 17986).
 *
 * Here follows a description of what happens on W2K,Vista, W2K8, W7:
 * When the "Make New Folder" button is clicked a new folder is created and
 * inserted into the tree. The folder is given a default name that depends on
 * the locale (e.g. "New Folder"). The folder name is selected and the dialog
 * waits for the user to type in a new name. The folder is renamed when the user
 * types in a name and presses enter.
 *
 * Note that XP and W2K3 do not select the folder name or wait for the user
 * to type in a new folder name. This behavior is considered broken as most
 * users would like to give the folder a name after creating it. The fact that
 * it originally waited for the user to type in a new folder name(W2K), and then
 * again was changed back wait for the new folder name(Vista, W2K8, W7),
 * indicates that MS also believes that it was broken in XP and W2K3.
 */
static void test_click_make_new_folder_button(void)
{
    HRESULT resCoInit, hr;
    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 new_folder_path[MAX_PATH];
    CHAR new_folder_pidl_path[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, -1,
        test_folder_pathW, MAX_PATH);
    hr = SHGetDesktopFolder(&test_folder_object);
    ok (SUCCEEDED(hr), "SHGetDesktopFolder failed with hr 0x%08x\n", hr);
    if (FAILED(hr)) {
        skip("SHGetDesktopFolder failed - skipping\n");
        return;
    }
    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);
    ok(number_of_folders == 1 || broken(number_of_folders == 0) /* W95, W98 */,
        "Clicking \"Make New Folder\" button did not result in a new folder.\n");

    /* There should be a new folder foo inside the test folder */
    strcpy(new_folder_path, test_folder_path);
    strcat(new_folder_path, new_folder_name);
    ok(does_folder_or_file_exist(new_folder_path)
        || broken(!does_folder_or_file_exist(new_folder_path)) /* W95, W98, XP, W2K3 */,
        "The new folder did not get the name %s\n", new_folder_name);

    /* Dialog should return a pidl pointing to the new folder */
    ok(SHGetPathFromIDListA(pidl, new_folder_pidl_path),
        "SHGetPathFromIDList failed for new folder.\n");
    ok(strcmp(new_folder_path, new_folder_pidl_path) == 0
        || broken(strcmp(new_folder_path, new_folder_pidl_path) != 0) /* earlier than Vista */,
        "SHBrowseForFolder did not return the pidl for the new folder. "
        "Expected '%s' got '%s'\n", new_folder_path, new_folder_pidl_path);

    /* 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);
    test_folder_object->lpVtbl->Release(test_folder_object);

    CoUninitialize();
}


/*
 * Callback used by test_selection.
 */
static int CALLBACK selection_callback(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
    DWORD ret;

    switch (uMsg)
    {
    case BFFM_INITIALIZED:
        /* test with zero values */
        ret = SendMessage(hwnd, BFFM_SETSELECTIONA, 0, 0);
        ok(!ret, "SendMessage returned: %u\n", ret);
        ret = SendMessage(hwnd, BFFM_SETSELECTIONW, 0, 0);
        ok(!ret, "SendMessage returned: %u\n", ret);

        ret = SendMessage(hwnd, BFFM_SETSELECTIONA, 1, 0);
        ok(!ret, "SendMessage returned: %u\n", ret);

        if(0)
        {
            /* Crashes on NT4 */
            ret = SendMessage(hwnd, BFFM_SETSELECTIONW, 1, 0);
            ok(!ret, "SendMessage returned: %u\n", ret);
        }

        ret = SendMessage(hwnd, BFFM_SETSELECTIONA, 0, (LPARAM)selected_folder_pidl);
        ok(!ret, "SendMessage returned: %u\n", ret);
        ret = SendMessage(hwnd, BFFM_SETSELECTIONW, 0, (LPARAM)selected_folder_pidl);
        ok(!ret, "SendMessage returned: %u\n", ret);

        ret = SendMessage(hwnd, BFFM_SETSELECTIONA, 1, (LPARAM)selected_folder_pidl);
        ok(!ret, "SendMessage returned: %u\n", ret);
        ret = SendMessage(hwnd, BFFM_SETSELECTIONW, 1, (LPARAM)selected_folder_pidl);
        ok(!ret, "SendMessage returned: %u\n", ret);

        ret = SendMessage(hwnd, BFFM_SETSELECTIONA, 1, (LPARAM)new_folder_name);
        ok(!ret, "SendMessage returned: %u\n", ret);
        ret = SendMessage(hwnd, BFFM_SETSELECTIONW, 1, (LPARAM)new_folder_name);
        ok(!ret, "SendMessage returned: %u\n", ret);

        SendMessage(hwnd, WM_COMMAND, IDOK, 0);
        return TRUE;
    default:
        return FALSE;
    }
}

static void test_selection(void)
{
    HRESULT resCoInit, hr;
    BROWSEINFO bi;
    LPITEMIDLIST pidl = NULL;
    IShellFolder *desktop_object;
    WCHAR selected_folderW[MAX_PATH];
    const CHAR title[] = "test_selection";

    resCoInit = CoInitialize(NULL);
    if(!(resCoInit == S_OK || resCoInit == S_FALSE))
    {
        skip("COM could not be initialized %u\n", GetLastError());
        return;
    }

    if (!GetCurrentDirectoryW(MAX_PATH, selected_folderW))
    {
        skip("GetCurrentDirectoryW failed %u\n", GetLastError());
    }

    /* Initialize browse info struct for SHBrowseForFolder */
    bi.hwndOwner = NULL;
    bi.pszDisplayName = NULL;
    bi.lpszTitle = (LPTSTR) title;
    bi.lpfn = selection_callback;

    hr = SHGetDesktopFolder(&desktop_object);
    ok (SUCCEEDED(hr), "SHGetDesktopFolder failed with hr 0x%08x\n", hr);
    if (FAILED(hr)) {
        skip("SHGetDesktopFolder failed - skipping\n");
        return;
    }
    desktop_object->lpVtbl->ParseDisplayName(desktop_object, NULL, NULL,
        selected_folderW, 0UL, &selected_folder_pidl, 0UL);
    bi.pidlRoot = selected_folder_pidl;

    /* test without flags */
    bi.ulFlags = 0;
    pidl = SHBrowseForFolder(&bi);

    if (pidl)
        CoTaskMemFree(pidl);

    /* test with flag */
    bi.ulFlags = BIF_NEWDIALOGSTYLE;
    pidl = SHBrowseForFolder(&bi);

    if (pidl)
        CoTaskMemFree(pidl);

    desktop_object->lpVtbl->Release(desktop_object);

    CoUninitialize();
}

START_TEST(brsfolder)
{
    test_click_make_new_folder_button();
    test_selection();
}
