#include "windows.h"
#include "shobjidl.h"
#include "shlguid.h"
-#include "initguid.h"
#include "shldisp.h"
+#include "shlobj.h"
#include "wine/heap.h"
#include "wine/test.h"
static IAutoComplete *test_init(void)
{
HRESULT r;
- IAutoComplete *ac;
+ IAutoComplete *ac, *ac2;
IUnknown *acSource;
LONG_PTR user_data;
user_data = GetWindowLongPtrA(hEdit, GWLP_USERDATA);
ok(user_data == 0, "Expected the edit control user data to be zero\n");
+ /* bind a different object to the same edit control */
+ r = CoCreateInstance(&CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IAutoComplete, (LPVOID*)&ac2);
+ ok(r == S_OK, "no IID_IAutoComplete (0x%08x)\n", r);
+
+ r = IAutoComplete_Init(ac2, hEdit, acSource, NULL, NULL);
+ ok(r == S_OK, "Init returned 0x%08x\n", r);
+ IAutoComplete_Release(ac2);
+
IUnknown_Release(acSource);
return ac;
CW_USEDEFAULT, CW_USEDEFAULT, 130, 105, NULL, NULL, GetModuleHandleA(NULL), 0);
}
+static WNDPROC HijackerWndProc_prev;
+static const WCHAR HijackerWndProc_txt[] = {'H','i','j','a','c','k','e','d',0};
+static LRESULT CALLBACK HijackerWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_GETTEXT:
+ {
+ size_t len = min(wParam, ARRAY_SIZE(HijackerWndProc_txt));
+ memcpy((void*)lParam, HijackerWndProc_txt, len * sizeof(WCHAR));
+ return len;
+ }
+ case WM_GETTEXTLENGTH:
+ return ARRAY_SIZE(HijackerWndProc_txt) - 1;
+ }
+ return CallWindowProcW(HijackerWndProc_prev, hWnd, msg, wParam, lParam);
+}
+
+static LRESULT CALLBACK HijackerWndProc2(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case EM_SETSEL:
+ lParam = wParam;
+ break;
+ case WM_SETTEXT:
+ lParam = (LPARAM)HijackerWndProc_txt;
+ break;
+ }
+ return CallWindowProcW(HijackerWndProc_prev, hWnd, msg, wParam, lParam);
+}
+
struct string_enumerator
{
IEnumString IEnumString_iface;
+ IACList IACList_iface;
LONG ref;
WCHAR **data;
int data_len;
int cur;
+ UINT num_resets;
+ UINT num_expand;
+ WCHAR last_expand[32];
};
static struct string_enumerator *impl_from_IEnumString(IEnumString *iface)
static HRESULT WINAPI string_enumerator_QueryInterface(IEnumString *iface, REFIID riid, void **ppv)
{
+ struct string_enumerator *this = impl_from_IEnumString(iface);
if (IsEqualGUID(riid, &IID_IEnumString) || IsEqualGUID(riid, &IID_IUnknown))
+ *ppv = &this->IEnumString_iface;
+ else if (IsEqualGUID(riid, &IID_IACList))
+ *ppv = &this->IACList_iface;
+ else
{
- IUnknown_AddRef(iface);
- *ppv = iface;
- return S_OK;
+ *ppv = NULL;
+ return E_NOINTERFACE;
}
- *ppv = NULL;
- return E_NOINTERFACE;
+ IUnknown_AddRef(&this->IEnumString_iface);
+ return S_OK;
}
static ULONG WINAPI string_enumerator_AddRef(IEnumString *iface)
struct string_enumerator *this = impl_from_IEnumString(iface);
this->cur = 0;
+ this->num_resets++;
return S_OK;
}
return E_NOTIMPL;
}
-static IEnumStringVtbl string_enumerator_vtlb =
+static IEnumStringVtbl string_enumerator_vtbl =
{
string_enumerator_QueryInterface,
string_enumerator_AddRef,
string_enumerator_Clone
};
+static struct string_enumerator *impl_from_IACList(IACList *iface)
+{
+ return CONTAINING_RECORD(iface, struct string_enumerator, IACList_iface);
+}
+
+static HRESULT WINAPI aclist_QueryInterface(IACList *iface, REFIID riid, void **ppv)
+{
+ return string_enumerator_QueryInterface(&impl_from_IACList(iface)->IEnumString_iface, riid, ppv);
+}
+
+static ULONG WINAPI aclist_AddRef(IACList *iface)
+{
+ return string_enumerator_AddRef(&impl_from_IACList(iface)->IEnumString_iface);
+}
+
+static ULONG WINAPI aclist_Release(IACList *iface)
+{
+ return string_enumerator_Release(&impl_from_IACList(iface)->IEnumString_iface);
+}
+
+static HRESULT WINAPI aclist_Expand(IACList *iface, const WCHAR *expand)
+{
+ struct string_enumerator *this = impl_from_IACList(iface);
+
+ /* see what we get called with and how many times,
+ don't actually do any expansion of the strings */
+ memcpy(this->last_expand, expand, min((lstrlenW(expand) + 1)*sizeof(WCHAR), sizeof(this->last_expand)));
+ this->last_expand[ARRAY_SIZE(this->last_expand) - 1] = '\0';
+ this->num_expand++;
+
+ return S_OK;
+}
+
+static IACListVtbl aclist_vtbl =
+{
+ aclist_QueryInterface,
+ aclist_AddRef,
+ aclist_Release,
+ aclist_Expand
+};
+
static HRESULT string_enumerator_create(void **ppv, WCHAR **suggestions, int count)
{
struct string_enumerator *object;
object = heap_alloc_zero(sizeof(*object));
- object->IEnumString_iface.lpVtbl = &string_enumerator_vtlb;
+ object->IEnumString_iface.lpVtbl = &string_enumerator_vtbl;
+ object->IACList_iface.lpVtbl = &aclist_vtbl;
object->ref = 1;
object->data = suggestions;
object->data_len = count;
return S_OK;
}
+static void dispatch_messages(void)
+{
+ MSG msg;
+ Sleep(33);
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessageA(&msg);
+ }
+}
+
+#define check_dropdown(acdropdown, hwnd_edit, list, list_num) check_dropdown_(__FILE__, __LINE__, acdropdown, hwnd_edit, list, list_num)
+static void check_dropdown_(const char *file, UINT line, IAutoCompleteDropDown *acdropdown, HWND hwnd_edit, WCHAR **list, UINT list_num)
+{
+ UINT i;
+ DWORD flags = 0;
+ LPWSTR str;
+ HRESULT hr;
+
+ hr = IAutoCompleteDropDown_GetDropDownStatus(acdropdown, &flags, &str);
+ ok_(file, line)(hr == S_OK, "IAutoCompleteDropDown_GetDropDownStatus failed: %x\n", hr);
+ if (hr != S_OK) return;
+ if (list_num) ok_(file, line)(flags & ACDD_VISIBLE, "AutoComplete DropDown not visible\n");
+ else
+ {
+ ok_(file, line)(!(flags & ACDD_VISIBLE), "AutoComplete DropDown visible\n");
+ return;
+ }
+ ok_(file, line)(str == NULL, "Expected (null), got %s\n", wine_dbgstr_w(str));
+ if (str)
+ {
+ CoTaskMemFree(str);
+ return;
+ }
+
+ for (i = 0; i <= list_num; i++)
+ {
+ flags = 0;
+ SendMessageW(hwnd_edit, WM_KEYDOWN, VK_DOWN, 0);
+ SendMessageW(hwnd_edit, WM_KEYUP, VK_DOWN, 0xc0000000);
+ hr = IAutoCompleteDropDown_GetDropDownStatus(acdropdown, &flags, &str);
+ ok_(file, line)(hr == S_OK, "IAutoCompleteDropDown_GetDropDownStatus failed: %x\n", hr);
+ ok_(file, line)(flags & ACDD_VISIBLE, "AutoComplete DropDown not visible\n");
+ if (hr == S_OK)
+ {
+ if (i < list_num)
+ ok_(file, line)(str && !lstrcmpW(list[i], str), "Expected %s, got %s\n",
+ wine_dbgstr_w(list[i]), wine_dbgstr_w(str));
+ else
+ ok_(file, line)(str == NULL, "Expected (null), got %s\n", wine_dbgstr_w(str));
+ }
+ CoTaskMemFree(str);
+ }
+}
+
+static void test_aclist_expand(HWND hwnd_edit, void *enumerator)
+{
+ struct string_enumerator *obj = (struct string_enumerator*)enumerator;
+ static WCHAR str1[] = {'t','e','s','t',0};
+ static WCHAR str1a[] = {'t','e','s','t','\\',0};
+ static WCHAR str2[] = {'t','e','s','t','\\','f','o','o','\\','b','a','r','\\','b','a',0};
+ static WCHAR str2a[] = {'t','e','s','t','\\','f','o','o','\\','b','a','r','\\',0};
+ static WCHAR str2b[] = {'t','e','s','t','\\','f','o','o','\\','b','a','r','\\','b','a','z','_','b','b','q','\\',0};
+ obj->num_resets = 0;
+
+ ok(obj->num_expand == 0, "Expected 0 expansions, got %u\n", obj->num_expand);
+ SendMessageW(hwnd_edit, WM_SETTEXT, 0, (LPARAM)str1);
+ SendMessageW(hwnd_edit, EM_SETSEL, ARRAY_SIZE(str1) - 1, ARRAY_SIZE(str1) - 1);
+ SendMessageW(hwnd_edit, WM_CHAR, '\\', 1);
+ dispatch_messages();
+ ok(obj->num_expand == 1, "Expected 1 expansion, got %u\n", obj->num_expand);
+ ok(lstrcmpW(obj->last_expand, str1a) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str1a), wine_dbgstr_w(obj->last_expand));
+ ok(obj->num_resets == 1, "Expected 1 reset, got %u\n", obj->num_resets);
+ SendMessageW(hwnd_edit, WM_SETTEXT, 0, (LPARAM)str2);
+ SendMessageW(hwnd_edit, EM_SETSEL, ARRAY_SIZE(str2) - 1, ARRAY_SIZE(str2) - 1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'z', 1);
+ dispatch_messages();
+ ok(obj->num_expand == 2, "Expected 2 expansions, got %u\n", obj->num_expand);
+ ok(lstrcmpW(obj->last_expand, str2a) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str2a), wine_dbgstr_w(obj->last_expand));
+ ok(obj->num_resets == 2, "Expected 2 resets, got %u\n", obj->num_resets);
+ SetFocus(hwnd_edit);
+ SendMessageW(hwnd_edit, WM_CHAR, '_', 1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'b', 1);
+ SetFocus(0);
+ SetFocus(hwnd_edit);
+ SendMessageW(hwnd_edit, WM_CHAR, 'b', 1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'q', 1);
+ dispatch_messages();
+ ok(obj->num_expand == 2, "Expected 2 expansions, got %u\n", obj->num_expand);
+ ok(obj->num_resets == 2, "Expected 2 resets, got %u\n", obj->num_resets);
+ SendMessageW(hwnd_edit, WM_CHAR, '\\', 1);
+ dispatch_messages();
+ ok(obj->num_expand == 3, "Expected 3 expansions, got %u\n", obj->num_expand);
+ ok(lstrcmpW(obj->last_expand, str2b) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str2b), wine_dbgstr_w(obj->last_expand));
+ ok(obj->num_resets == 3, "Expected 3 resets, got %u\n", obj->num_resets);
+ SendMessageW(hwnd_edit, EM_SETSEL, ARRAY_SIZE(str1a) - 1, -1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'x', 1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'y', 1);
+ dispatch_messages();
+ ok(obj->num_expand == 4, "Expected 4 expansions, got %u\n", obj->num_expand);
+ ok(lstrcmpW(obj->last_expand, str1a) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str1a), wine_dbgstr_w(obj->last_expand));
+ ok(obj->num_resets == 4, "Expected 4 resets, got %u\n", obj->num_resets);
+ SendMessageW(hwnd_edit, EM_SETSEL, ARRAY_SIZE(str1) - 1, -1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'x', 1);
+ dispatch_messages();
+ ok(obj->num_expand == 4, "Expected 4 expansions, got %u\n", obj->num_expand);
+ ok(obj->num_resets == 5, "Expected 5 resets, got %u\n", obj->num_resets);
+}
+
+static void test_prefix_filtering(HWND hwnd_edit)
+{
+ static WCHAR htt[] = {'h','t','t',0};
+ static WCHAR www[] = {'w','w','w','.',0};
+ static WCHAR str0[] = {'w','w','w','.','a','x',0};
+ static WCHAR str1[] = {'h','t','t','p','s',':','/','/','w','w','w','.','a','c',0};
+ static WCHAR str2[] = {'a','a',0};
+ static WCHAR str3[] = {'a','b',0};
+ static WCHAR str4[] = {'h','t','t','p',':','/','/','a','0',0};
+ static WCHAR str5[] = {'h','t','t','p','s',':','/','/','h','t','a',0};
+ static WCHAR str6[] = {'h','f','o','o',0};
+ static WCHAR str7[] = {'h','t','t','p',':','/','/','w','w','w','.','a','d','d',0};
+ static WCHAR str8[] = {'w','w','w','.','w','w','w','.','?',0};
+ static WCHAR str9[] = {'h','t','t','p',':','/','/','a','b','c','.','a','a','.','c','o','m',0};
+ static WCHAR str10[]= {'f','t','p',':','/','/','a','b','c',0};
+ static WCHAR str11[]= {'f','i','l','e',':','/','/','a','a',0};
+ static WCHAR str12[]= {'f','t','p',':','/','/','w','w','w','.','a','a',0};
+ static WCHAR *suggestions[] = { str0, str1, str2, str3, str4, str5, str6, str7, str8, str9, str10, str11, str12 };
+ static WCHAR *sorted1[] = { str4, str2, str3, str9, str1, str7, str0 };
+ static WCHAR *sorted2[] = { str3, str9 };
+ static WCHAR *sorted3[] = { str1, str7, str0 };
+ static WCHAR *sorted4[] = { str6, str5 };
+ static WCHAR *sorted5[] = { str5 };
+ static WCHAR *sorted6[] = { str4, str9 };
+ static WCHAR *sorted7[] = { str11, str10, str12 };
+ IUnknown *enumerator;
+ IAutoComplete2 *autocomplete;
+ IAutoCompleteDropDown *acdropdown;
+ WCHAR buffer[20];
+ HRESULT hr;
+
+ hr = CoCreateInstance(&CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER, &IID_IAutoComplete2, (void**)&autocomplete);
+ ok(hr == S_OK, "CoCreateInstance failed: %x\n", hr);
+
+ hr = IAutoComplete2_QueryInterface(autocomplete, &IID_IAutoCompleteDropDown, (LPVOID*)&acdropdown);
+ ok(hr == S_OK, "No IAutoCompleteDropDown interface: %x\n", hr);
+
+ string_enumerator_create((void**)&enumerator, suggestions, ARRAY_SIZE(suggestions));
+
+ hr = IAutoComplete2_SetOptions(autocomplete, ACO_FILTERPREFIXES | ACO_AUTOSUGGEST | ACO_AUTOAPPEND);
+ ok(hr == S_OK, "IAutoComplete2_SetOptions failed: %x\n", hr);
+ hr = IAutoComplete2_Init(autocomplete, hwnd_edit, enumerator, NULL, NULL);
+ ok(hr == S_OK, "IAutoComplete_Init failed: %x\n", hr);
+
+ SendMessageW(hwnd_edit, EM_SETSEL, 0, -1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'a', 1);
+ dispatch_messages();
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(lstrcmpW(str4 + 7, buffer) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str4 + 7), wine_dbgstr_w(buffer));
+ check_dropdown(acdropdown, hwnd_edit, sorted1, ARRAY_SIZE(sorted1));
+
+ SendMessageW(hwnd_edit, EM_SETSEL, 0, -1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'a', 1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'b', 1);
+ dispatch_messages();
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(lstrcmpW(str3, buffer) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str3), wine_dbgstr_w(buffer));
+ check_dropdown(acdropdown, hwnd_edit, sorted2, ARRAY_SIZE(sorted2));
+ SendMessageW(hwnd_edit, EM_SETSEL, 0, -1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'a', 1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'b', 1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'c', 1);
+ dispatch_messages();
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(lstrcmpW(str9 + 7, buffer) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str9 + 7), wine_dbgstr_w(buffer));
+
+ SendMessageW(hwnd_edit, WM_SETTEXT, 0, (LPARAM)www);
+ SendMessageW(hwnd_edit, EM_SETSEL, ARRAY_SIZE(www) - 1, ARRAY_SIZE(www) - 1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'a', 1);
+ dispatch_messages();
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(lstrcmpW(str1 + 8, buffer) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str1 + 8), wine_dbgstr_w(buffer));
+ check_dropdown(acdropdown, hwnd_edit, sorted3, ARRAY_SIZE(sorted3));
+ SendMessageW(hwnd_edit, WM_SETTEXT, 0, (LPARAM)www);
+ SendMessageW(hwnd_edit, EM_SETSEL, ARRAY_SIZE(www) - 1, ARRAY_SIZE(www) - 1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'w', 1);
+ dispatch_messages();
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(lstrcmpW(str8, buffer) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str8), wine_dbgstr_w(buffer));
+
+ SendMessageW(hwnd_edit, EM_SETSEL, 0, -1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'h', 1);
+ dispatch_messages();
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(lstrcmpW(str6, buffer) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str6), wine_dbgstr_w(buffer));
+ check_dropdown(acdropdown, hwnd_edit, sorted4, ARRAY_SIZE(sorted4));
+ SendMessageW(hwnd_edit, WM_CHAR, 't', 1);
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(lstrcmpW(str5 + 8, buffer) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str5 + 8), wine_dbgstr_w(buffer));
+ check_dropdown(acdropdown, hwnd_edit, sorted5, ARRAY_SIZE(sorted5));
+ SendMessageW(hwnd_edit, WM_CHAR, 't', 1);
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(lstrcmpW(htt, buffer) == 0, "Expected %s, got %s\n", wine_dbgstr_w(htt), wine_dbgstr_w(buffer));
+ check_dropdown(acdropdown, hwnd_edit, NULL, 0);
+ SendMessageW(hwnd_edit, WM_CHAR, 'p', 1);
+ SendMessageW(hwnd_edit, WM_CHAR, ':', 1);
+ SendMessageW(hwnd_edit, WM_CHAR, '/', 1);
+ SendMessageW(hwnd_edit, WM_CHAR, '/', 1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'a', 1);
+ dispatch_messages();
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(lstrcmpW(str4, buffer) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str4), wine_dbgstr_w(buffer));
+ check_dropdown(acdropdown, hwnd_edit, sorted6, ARRAY_SIZE(sorted6));
+ SendMessageW(hwnd_edit, EM_SETSEL, 0, 2);
+ SendMessageW(hwnd_edit, WM_CHAR, 'H', 1);
+ dispatch_messages();
+ check_dropdown(acdropdown, hwnd_edit, NULL, 0);
+ SendMessageW(hwnd_edit, WM_CHAR, 't', 1);
+ dispatch_messages();
+ check_dropdown(acdropdown, hwnd_edit, sorted6, ARRAY_SIZE(sorted6));
+
+ SendMessageW(hwnd_edit, EM_SETSEL, 0, -1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'F', 1);
+ dispatch_messages();
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ check_dropdown(acdropdown, hwnd_edit, sorted7, ARRAY_SIZE(sorted7));
+ SendMessageW(hwnd_edit, WM_CHAR, 'i', 1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'L', 1);
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ check_dropdown(acdropdown, hwnd_edit, sorted7, 1);
+
+ IAutoCompleteDropDown_Release(acdropdown);
+ IAutoComplete2_Release(autocomplete);
+ IUnknown_Release(enumerator);
+}
+
static void test_custom_source(void)
{
static WCHAR str_alpha[] = {'t','e','s','t','1',0};
static WCHAR str_alpha2[] = {'t','e','s','t','2',0};
static WCHAR str_beta[] = {'a','u','t','o',' ','c','o','m','p','l','e','t','e',0};
+ static WCHAR str_au[] = {'a','u',0};
+ static WCHAR str_aut[] = {'a','u','t',0};
static WCHAR *suggestions[] = { str_alpha, str_alpha2, str_beta };
+ struct string_enumerator *obj;
IUnknown *enumerator;
IAutoComplete2 *autocomplete;
+ IAutoCompleteDropDown *acdropdown;
HWND hwnd_edit;
+ DWORD flags = 0;
WCHAR buffer[20];
HRESULT hr;
- MSG msg;
ShowWindow(hMainWnd, SW_SHOW);
hr = CoCreateInstance(&CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER, &IID_IAutoComplete2, (void**)&autocomplete);
ok(hr == S_OK, "CoCreateInstance failed: %x\n", hr);
- string_enumerator_create((void**)&enumerator, suggestions, sizeof(suggestions) / sizeof(*suggestions));
+ hr = IAutoComplete2_QueryInterface(autocomplete, &IID_IAutoCompleteDropDown, (LPVOID*)&acdropdown);
+ ok(hr == S_OK, "No IAutoCompleteDropDown interface: %x\n", hr);
+
+ string_enumerator_create((void**)&enumerator, suggestions, ARRAY_SIZE(suggestions));
+ obj = (struct string_enumerator*)enumerator;
hr = IAutoComplete2_SetOptions(autocomplete, ACO_AUTOSUGGEST | ACO_AUTOAPPEND);
ok(hr == S_OK, "IAutoComplete2_SetOptions failed: %x\n", hr);
+ hr = IAutoCompleteDropDown_ResetEnumerator(acdropdown);
+ ok(hr == S_OK, "IAutoCompleteDropDown_ResetEnumerator failed: %x\n", hr);
hr = IAutoComplete2_Init(autocomplete, hwnd_edit, enumerator, NULL, NULL);
ok(hr == S_OK, "IAutoComplete_Init failed: %x\n", hr);
+ SetFocus(hwnd_edit);
SendMessageW(hwnd_edit, WM_CHAR, 'a', 1);
- /* Send a keyup message since wine doesn't handle WM_CHAR yet */
- SendMessageW(hwnd_edit, WM_KEYUP, 'u', 1);
- Sleep(100);
- while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessageA(&msg);
- }
- SendMessageW(hwnd_edit, WM_GETTEXT, sizeof(buffer) / sizeof(*buffer), (LPARAM)buffer);
+ SendMessageW(hwnd_edit, WM_CHAR, 'u', 1);
+ dispatch_messages();
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(lstrcmpW(str_beta, buffer) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str_beta), wine_dbgstr_w(buffer));
+ ok(obj->num_resets == 1, "Expected 1 reset, got %u\n", obj->num_resets);
+ SendMessageW(hwnd_edit, EM_SETSEL, 0, -1);
+ SendMessageW(hwnd_edit, WM_CHAR, '\b', 1);
+ dispatch_messages();
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(buffer[0] == '\0', "Expected empty string, got %s\n", wine_dbgstr_w(buffer));
+ ok(obj->num_resets == 1, "Expected 1 reset, got %u\n", obj->num_resets);
+ hr = IAutoCompleteDropDown_ResetEnumerator(acdropdown);
+ ok(hr == S_OK, "IAutoCompleteDropDown_ResetEnumerator failed: %x\n", hr);
+ ok(obj->num_resets == 1, "Expected 1 reset, got %u\n", obj->num_resets);
+ obj->num_resets = 0;
+
+ /* hijack the window procedure */
+ HijackerWndProc_prev = (WNDPROC)SetWindowLongPtrW(hwnd_edit, GWLP_WNDPROC, (LONG_PTR)HijackerWndProc);
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(lstrcmpW(HijackerWndProc_txt, buffer) == 0, "Expected %s, got %s\n", wine_dbgstr_w(HijackerWndProc_txt), wine_dbgstr_w(buffer));
+
+ SendMessageW(hwnd_edit, WM_CHAR, 'a', 1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'u', 1);
+ SetWindowLongPtrW(hwnd_edit, GWLP_WNDPROC, (LONG_PTR)HijackerWndProc_prev);
+ dispatch_messages();
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(lstrcmpW(str_au, buffer) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str_au), wine_dbgstr_w(buffer));
+ ok(obj->num_resets == 1, "Expected 1 reset, got %u\n", obj->num_resets);
+ SendMessageW(hwnd_edit, EM_SETSEL, 0, -1);
+ SendMessageW(hwnd_edit, WM_CHAR, '\b', 1);
+ dispatch_messages();
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(buffer[0] == '\0', "Expected empty string, got %s\n", wine_dbgstr_w(buffer));
+ hr = IAutoCompleteDropDown_ResetEnumerator(acdropdown);
+ ok(hr == S_OK, "IAutoCompleteDropDown_ResetEnumerator failed: %x\n", hr);
+
+ HijackerWndProc_prev = (WNDPROC)SetWindowLongPtrW(hwnd_edit, GWLP_WNDPROC, (LONG_PTR)HijackerWndProc2);
+ SendMessageW(hwnd_edit, WM_CHAR, 'a', 1);
+ SendMessageW(hwnd_edit, WM_CHAR, 'u', 1);
+ SetWindowLongPtrW(hwnd_edit, GWLP_WNDPROC, (LONG_PTR)HijackerWndProc_prev);
+ dispatch_messages();
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
ok(lstrcmpW(str_beta, buffer) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str_beta), wine_dbgstr_w(buffer));
+ ok(obj->num_resets == 2, "Expected 2 resets, got %u\n", obj->num_resets);
+ /* end of hijacks */
+
+ hr = IAutoCompleteDropDown_GetDropDownStatus(acdropdown, &flags, NULL);
+ ok(hr == S_OK, "IAutoCompleteDropDown_GetDropDownStatus failed: %x\n", hr);
+ ok(flags & ACDD_VISIBLE, "AutoComplete DropDown should be visible\n");
+ SendMessageW(hwnd_edit, WM_SETTEXT, 0, (LPARAM)str_au);
+ dispatch_messages();
+ hr = IAutoCompleteDropDown_GetDropDownStatus(acdropdown, &flags, NULL);
+ ok(hr == S_OK, "IAutoCompleteDropDown_GetDropDownStatus failed: %x\n", hr);
+ ok(!(flags & ACDD_VISIBLE), "AutoComplete DropDown should have been hidden\n");
+ SendMessageW(hwnd_edit, WM_SETTEXT, 0, (LPARAM)str_aut);
+ dispatch_messages();
+ hr = IAutoCompleteDropDown_GetDropDownStatus(acdropdown, &flags, NULL);
+ ok(hr == S_OK, "IAutoCompleteDropDown_GetDropDownStatus failed: %x\n", hr);
+ ok(!(flags & ACDD_VISIBLE), "AutoComplete DropDown should be hidden\n");
+ SendMessageW(hwnd_edit, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(lstrcmpW(str_aut, buffer) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str_aut), wine_dbgstr_w(buffer));
+
+ test_aclist_expand(hwnd_edit, enumerator);
+ obj->num_resets = 0;
+
+ hr = IAutoCompleteDropDown_ResetEnumerator(acdropdown);
+ ok(hr == S_OK, "IAutoCompleteDropDown_ResetEnumerator failed: %x\n", hr);
+ SendMessageW(hwnd_edit, WM_CHAR, 'x', 1);
+ dispatch_messages();
+ ok(obj->num_resets == 1, "Expected 1 reset, got %u\n", obj->num_resets);
+ SendMessageW(hwnd_edit, WM_CHAR, 'x', 1);
+ dispatch_messages();
+ ok(obj->num_resets == 1, "Expected 1 reset, got %u\n", obj->num_resets);
+
+ IAutoCompleteDropDown_Release(acdropdown);
+ IAutoComplete2_Release(autocomplete);
+ IUnknown_Release(enumerator);
+
+ test_prefix_filtering(hwnd_edit);
ShowWindow(hMainWnd, SW_HIDE);
DestroyWindow(hwnd_edit);
HRESULT r;
MSG msg;
IAutoComplete* ac;
+ RECT win_rect;
+ POINT orig_pos;
r = CoInitialize(NULL);
ok(r == S_OK, "CoInitialize failed (0x%08x). Tests aborted.\n", r);
ok(hMainWnd != NULL, "Failed to create parent window. Tests aborted.\n");
if (!hMainWnd) return;
+ /* Move the cursor away from the dropdown listbox */
+ GetWindowRect(hMainWnd, &win_rect);
+ GetCursorPos(&orig_pos);
+ SetCursorPos(win_rect.left, win_rect.top);
+
test_invalid_init();
ac = test_init();
if (!ac)
IAutoComplete_Release(ac);
cleanup:
+ SetCursorPos(orig_pos.x, orig_pos.y);
DestroyWindow(hEdit);
DestroyWindow(hMainWnd);
WIN32_FIND_DATAA find_data;
HANDLE find_handle;
- lstrcpynA(path_search_string, path, MAX_PATH);
- strncat(path_search_string, "*", 1);
+ lstrcpynA(path_search_string, path, MAX_PATH - 1);
+ strcat(path_search_string, "*");
find_handle = FindFirstFileA(path_search_string, &find_data);
if (find_handle == INVALID_HANDLE_VALUE)
{
skip("GetCurrentDirectoryA failed %u\n", GetLastError());
}
- strncat(test_folder_path, "\\", 1);
- strncat(test_folder_path, title, MAX_PATH-1);
- strncat(test_folder_path, "\\", 1);
+ strcat(test_folder_path, "\\");
+ strcat(test_folder_path, title);
+ strcat(test_folder_path, "\\");
/* Avoid conflicts by creating a test folder. */
if (!CreateDirectoryA(title, NULL))
for (i = 0; i < 20; i++)
{
- Sleep(100);
+ Sleep(100 * i);
if ((window = FindWindowA("ExplorerWClass", title)) ||
(window = FindWindowA("CabinetWClass", title)))
{
ok(folder == NULL, "expected NULL, got %p\n", folder);
/* test valid folder ids */
- for (i = 0; i < sizeof(special_folders)/sizeof(special_folders[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(special_folders); i++)
{
V_VT(&var) = VT_I4;
V_I4(&var) = special_folders[i];
FolderItems3 *items3 = NULL;
FolderItem *item = (FolderItem*)0xdeadbeef, *item2;
FolderItemVerbs *verbs = (FolderItemVerbs*)0xdeadbeef;
- VARIANT var, int_index, str_index, str_index2;
+ VARIANT var, var2, int_index, str_index, str_index2;
IDispatch *disp, *disp2;
LONG count = -1;
IUnknown *unk;
ok(!item, "item is not null\n");
/* create test files */
- for (i = 0; i < sizeof(file_defs)/sizeof(file_defs[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(file_defs); i++)
{
switch (file_defs[i].type)
{
count = -1;
r = FolderItems_get_Count(items, &count);
ok(r == S_OK, "FolderItems::get_Count failed: %08x\n", r);
- ok(count == sizeof(file_defs)/sizeof(file_defs[0]),
- "expected %d files, got %d\n", (LONG)(sizeof(file_defs)/sizeof(file_defs[0])), count);
+ ok(count == ARRAY_SIZE(file_defs), "got %d files\n", count);
+ /* VT_EMPTY */
V_VT(&var) = VT_EMPTY;
item = (FolderItem*)0xdeadbeef;
r = FolderItems_Item(items, var, &item);
ok(r == E_NOTIMPL, "expected E_NOTIMPL, got %08x\n", r);
ok(!item, "item is not null\n");
+ /* VT_I2 */
V_VT(&var) = VT_I2;
V_I2(&var) = 0;
FolderItem_Release(item);
+ /* VT_VARIANT | VT_BYREF */
+ V_VT(&var2) = VT_I2;
+ V_I2(&var2) = 0;
+
+ V_VT(&var) = VT_BYREF | VT_VARIANT;
+ V_VARIANTREF(&var) = &var2;
+
+ item = NULL;
+ r = FolderItems_Item(items, var, &item);
+ ok(r == S_OK, "FolderItems::Item failed: %08x\n", r);
+ ok(!!item, "item is null\n");
+ FolderItem_Release(item);
+
+ /* VT_I4 */
V_VT(&var) = VT_I4;
V_I4(&var) = 0;
item = NULL;
V_VT(&int_index) = VT_I4;
/* test the folder item corresponding to each file */
- for (i = 0; i < sizeof(file_defs)/sizeof(file_defs[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(file_defs); i++)
{
VARIANT_BOOL b;
BSTR name;
}
/* test that there are only as many folder items as there were files */
- V_I4(&int_index) = sizeof(file_defs)/sizeof(file_defs[0]);
+ V_I4(&int_index) = ARRAY_SIZE(file_defs);
item = (FolderItem*)0xdeadbeef;
r = FolderItems_Item(items, int_index, &item);
ok(r == S_FALSE, "expected S_FALSE, got %08x\n", r);
IShellView_Release(view);
/* Try with some other folder, that's not a desktop */
- GetTempPathW(sizeof(pathW)/sizeof(pathW[0]), pathW);
+ GetTempPathW(ARRAY_SIZE(pathW), pathW);
hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, pathW, NULL, &pidl, NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr != S_OK)
return;
-if (0) /* NULL out argument - currently crashes on Wine */ {
hr = IShellWindows_Register(shellwindows, NULL, 0, SWC_EXPLORER, NULL);
ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "got 0x%08x\n", hr);
-}
+
hr = IShellWindows_Register(shellwindows, NULL, 0, SWC_EXPLORER, &cookie);
todo_wine
ok(hr == E_POINTER, "got 0x%08x\n", hr);
IUnknown *unk;
ok(disp != NULL, "got %p\n", disp);
-
- if (disp == NULL) goto skip_disp_tests;
-
ok(ret != HandleToUlong(hwnd), "got %d\n", ret);
/* IDispatch-related tests */
IServiceProvider_Release(sp);
IDispatch_Release(disp);
}
-skip_disp_tests:
disp = (void*)0xdeadbeef;
ret = 0xdead;
&IID_IShellDispatch, (void**)&sd);
ok(hr == S_OK, "got 0x%08x\n", hr);
- GetTempPathW(sizeof(pathW)/sizeof(pathW[0]), pathW);
+ GetTempPathW(ARRAY_SIZE(pathW), pathW);
V_VT(&v) = VT_BSTR;
V_BSTR(&v) = SysAllocString(pathW);
hr = IShellDispatch_NameSpace(sd, v, &folder);
&IID_IShellDispatch, (void**)&sd);
ok(hr == S_OK, "got 0x%08x\n", hr);
- GetTempPathW(sizeof(pathW)/sizeof(pathW[0]), pathW);
+ GetTempPathW(ARRAY_SIZE(pathW), pathW);
V_VT(&v) = VT_BSTR;
V_BSTR(&v) = SysAllocString(pathW);
hr = IShellDispatch_NameSpace(sd, v, &folder);
static void test_GetIconLocation(void)
{
+ IShellLinkW *slW;
IShellLinkA *sl;
const char *str;
char buffer[INFOTIPSIZE], mypath[MAX_PATH];
r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
ok(lstrcmpiA(buffer,str) == 0, "GetIconLocation returned '%s'\n", buffer);
- ok(i == 0xbabecafe, "GetIconLocation returned %d'\n", i);
+ ok(i == 0xbabecafe, "GetIconLocation returned %#x.\n", i);
+ r = IShellLinkA_SetIconLocation(sl, NULL, 0xcafefe);
+ ok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r);
+
+ i = 0xdeadbeef;
+ r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
+ ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
+ ok(!*buffer, "GetIconLocation returned '%s'\n", buffer);
+ ok(i == 0xcafefe, "GetIconLocation returned %#x.\n", i);
+
+ r = IShellLinkA_QueryInterface(sl, &IID_IShellLinkW, (void **)&slW);
+ ok(SUCCEEDED(r), "Failed to get IShellLinkW, hr %#x.\n", r);
+
+ str = "c:\\nonexistent\\file";
+ r = IShellLinkA_SetIconLocation(sl, str, 0xbabecafe);
+ ok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r);
+
+ r = IShellLinkA_SetIconLocation(sl, NULL, 0xcafefe);
+ ok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r);
+
+ i = 0xdeadbeef;
+ r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
+ ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
+ ok(!*buffer, "GetIconLocation returned '%s'\n", buffer);
+ ok(i == 0xcafefe, "GetIconLocation returned %#x.\n", i);
+
+ IShellLinkW_Release(slW);
IShellLinkA_Release(sl);
}
/* there is a NULL check for the struct */
hr = pSHGetStockIconInfo(SIID_FOLDER, SHGSI_ICONLOCATION, NULL);
ok(hr == E_INVALIDARG, "NULL: got 0x%x\n", hr);
+
+ for(i = 0; i < 140; i++) /* highest on wvista, i > 140 gives E_INVALIDARG, win7 can go higher */
+ {
+ memset(buffer, 0, sizeof(buffer));
+ sii->cbSize = sizeof(SHSTOCKICONINFO);
+ hr = pSHGetStockIconInfo(i, SHGSI_ICON | SHGSI_SMALLICON, sii);
+ ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
+ ok(sii->hIcon != NULL, "got NULL, expected an icon handle\n");
+ ok(sii->iIcon != 0, "got unexpected 0 for SIID %d\n", i); /* howto find out exact sii->iIcon value??? */
+ ok(sii->iSysImageIndex == -1, "got %d (expected -1)\n", sii->iSysImageIndex);
+ ok(DestroyIcon(sii->hIcon), "DestroyIcon failed\n");
+ if (winetest_debug > 1)
+ trace("%3d: got iSysImageIndex %3d, iIcon %3d and %s\n", i, sii->iSysImageIndex,
+ sii->iIcon, wine_dbgstr_w(sii->szPath));
+ }
}
static void test_SHExtractIcons(void)
ok(hicon == NULL, "Got icon %p\n", hicon);
/* Create a temporary non-executable file */
- GetTempPathW(sizeof(pathW)/sizeof(pathW[0]), pathW);
+ GetTempPathW(ARRAY_SIZE(pathW), pathW);
lstrcatW(pathW, nameW);
file = CreateFileW(pathW, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
ok(file != INVALID_HANDLE_VALUE, "Failed to create a test file\n");
for (i = 0; i <= SHIL_LAST; i++)
{
hr = SHGetImageList( i, &IID_IImageList, (void **)&list );
- ok( hr == S_OK ||
- broken( i == SHIL_JUMBO && hr == E_INVALIDARG ), /* XP and 2003 */
- "%d: got %08x\n", i, hr );
+ ok( hr == S_OK || broken( i == SHIL_JUMBO && hr == E_INVALIDARG ), /* XP and 2003 */
+ "%d: got %08x\n", i, hr );
if (FAILED(hr)) continue;
IImageList_GetIconSize( list, &width, &height );
switch (i)
static void test_SHCreateSessionKey(void)
{
+ static const WCHAR session_format[] = {
+ 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
+ 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+ 'E','x','p','l','o','r','e','r','\\','S','e','s','s','i','o','n','I','n','f','o','\\','%','u',0};
HKEY hkey, hkey2;
HRESULT hr;
+ DWORD session;
+ WCHAR sessionW[ARRAY_SIZE(session_format) + 16];
+ LONG ret;
if (!pSHCreateSessionKey)
{
hkey = (HKEY)0xdeadbeef;
hr = pSHCreateSessionKey(0, &hkey);
- todo_wine ok(hr == E_ACCESSDENIED, "got 0x%08x\n", hr);
- todo_wine ok(hkey == NULL, "got %p\n", hkey);
+ ok(hr == E_ACCESSDENIED, "got 0x%08x\n", hr);
+ ok(hkey == NULL, "got %p\n", hkey);
hr = pSHCreateSessionKey(KEY_READ, &hkey);
ok(hr == S_OK, "got 0x%08x\n", hr);
RegCloseKey(hkey);
RegCloseKey(hkey2);
+
+ /* check the registry */
+ ProcessIdToSessionId( GetCurrentProcessId(), &session);
+ if (session)
+ {
+ wsprintfW(sessionW, session_format, session);
+ ret = RegOpenKeyW(HKEY_CURRENT_USER, sessionW, &hkey);
+ ok(!ret, "key not found\n");
+ RegCloseKey(hkey);
+ }
}
static void test_dragdrophelper(void)
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(x) ( sizeof(x) / sizeof((x)[0]) )
-#endif
-
/* from pidl.h, not included here: */
#ifndef PT_CPL /* Guess, Win7 uses this for CSIDL_CONTROLS */
#define PT_CPL 0x01 /* no path */
static const BYTE ieSpecialType[] = { PT_IESPECIAL2 };
static const BYTE shellExtType[] = { PT_SHELLEXT };
static const BYTE workgroupType[] = { PT_WORKGRP };
-#define DECLARE_TYPE(x, y) { x, sizeof(y) / sizeof(y[0]), y }
+#define DECLARE_TYPE(x, y) { x, ARRAY_SIZE(y), y }
static const struct shellExpectedValues requiredShellValues[] = {
DECLARE_TYPE(CSIDL_BITBUCKET, guidType),
DECLARE_TYPE(CSIDL_CONTROLS, controlPanelType),
}
}
-static void test_parameters(void)
-{
- LPITEMIDLIST pidl = NULL;
- char path[MAX_PATH];
- HRESULT hr;
-
- if (pSHGetFolderLocation)
- {
- /* check a bogus CSIDL: */
- pidl = NULL;
- hr = pSHGetFolderLocation(NULL, 0xeeee, NULL, 0, &pidl);
- ok(hr == E_INVALIDARG, "got 0x%08x, expected E_INVALIDARG\n", hr);
- if (hr == S_OK) IMalloc_Free(pMalloc, pidl);
-
- /* check a bogus user token: */
- pidl = NULL;
- hr = pSHGetFolderLocation(NULL, CSIDL_FAVORITES, (HANDLE)2, 0, &pidl);
- ok(hr == E_FAIL || hr == E_HANDLE, "got 0x%08x, expected E_FAIL or E_HANDLE\n", hr);
- if (hr == S_OK) IMalloc_Free(pMalloc, pidl);
-
- /* a NULL pidl pointer crashes, so don't test it */
- }
-
- if (pSHGetSpecialFolderLocation)
- {
- if (0)
- /* crashes */
- SHGetSpecialFolderLocation(NULL, 0, NULL);
-
- hr = pSHGetSpecialFolderLocation(NULL, 0xeeee, &pidl);
- ok(hr == E_INVALIDARG, "got returned 0x%08x\n", hr);
- }
-
- if (pSHGetFolderPathA)
- {
- /* expect 2's a bogus handle, especially since we didn't open it */
- hr = pSHGetFolderPathA(NULL, CSIDL_DESKTOP, (HANDLE)2, SHGFP_TYPE_DEFAULT, path);
- ok(hr == E_FAIL || hr == E_HANDLE || /* Vista and 2k8 */
- broken(hr == S_OK), /* W2k and Me */ "got 0x%08x, expected E_FAIL\n", hr);
-
- hr = pSHGetFolderPathA(NULL, 0xeeee, NULL, SHGFP_TYPE_DEFAULT, path);
- ok(hr == E_INVALIDARG, "got 0x%08x, expected E_INVALIDARG\n", hr);
- }
-
- if (pSHGetSpecialFolderPathA)
- {
- BOOL ret;
-
- if (0)
- pSHGetSpecialFolderPathA(NULL, NULL, CSIDL_BITBUCKET, FALSE);
-
- /* odd but true: calling with a NULL path still succeeds if it's a real
- * dir (on some windows platform). on winME it generates exception.
- */
- ret = pSHGetSpecialFolderPathA(NULL, path, CSIDL_PROGRAMS, FALSE);
- ok(ret, "got %d\n", ret);
-
- ret = pSHGetSpecialFolderPathA(NULL, path, 0xeeee, FALSE);
- ok(!ret, "got %d\n", ret);
- }
-}
-
-/* Returns the folder's PIDL type, or 0xff if one can't be found. */
-static BYTE testSHGetFolderLocation(int folder)
-{
- LPITEMIDLIST pidl;
- HRESULT hr;
- BYTE ret = 0xff;
-
- /* treat absence of function as success */
- if (!pSHGetFolderLocation) return TRUE;
-
- pidl = NULL;
- hr = pSHGetFolderLocation(NULL, folder, NULL, 0, &pidl);
- if (hr == S_OK)
- {
- if (pidl)
- {
- LPITEMIDLIST pidlLast = pILFindLastID(pidl);
-
- ok(pidlLast != NULL, "%s: ILFindLastID failed\n",
- getFolderName(folder));
- if (pidlLast)
- ret = pidlLast->mkid.abID[0];
- IMalloc_Free(pMalloc, pidl);
- }
- }
- return ret;
-}
-
-/* Returns the folder's PIDL type, or 0xff if one can't be found. */
-static BYTE testSHGetSpecialFolderLocation(int folder)
-{
- LPITEMIDLIST pidl;
- HRESULT hr;
- BYTE ret = 0xff;
-
- /* treat absence of function as success */
- if (!pSHGetSpecialFolderLocation) return TRUE;
-
- pidl = NULL;
- hr = pSHGetSpecialFolderLocation(NULL, folder, &pidl);
- if (hr == S_OK)
- {
- if (pidl)
- {
- LPITEMIDLIST pidlLast = pILFindLastID(pidl);
-
- ok(pidlLast != NULL,
- "%s: ILFindLastID failed\n", getFolderName(folder));
- if (pidlLast)
- ret = pidlLast->mkid.abID[0];
- IMalloc_Free(pMalloc, pidl);
- }
- }
- return ret;
-}
-
-static void test_SHGetFolderPath(BOOL optional, int folder)
-{
- char path[MAX_PATH];
- HRESULT hr;
-
- if (!pSHGetFolderPathA) return;
-
- hr = pSHGetFolderPathA(NULL, folder, NULL, SHGFP_TYPE_CURRENT, path);
- ok(hr == S_OK || optional,
- "SHGetFolderPathA(NULL, %s, NULL, SHGFP_TYPE_CURRENT, path) failed: 0x%08x\n", getFolderName(folder), hr);
-}
-
-static void test_SHGetSpecialFolderPath(BOOL optional, int folder)
-{
- char path[MAX_PATH];
- BOOL ret;
-
- if (!pSHGetSpecialFolderPathA) return;
-
- ret = pSHGetSpecialFolderPathA(NULL, path, folder, FALSE);
- if (ret && winetest_interactive)
- printf("%s: %s\n", getFolderName(folder), path);
- ok(ret || optional,
- "SHGetSpecialFolderPathA(NULL, path, %s, FALSE) failed\n",
- getFolderName(folder));
-}
-
-static void test_ShellValues(const struct shellExpectedValues testEntries[],
- int numEntries, BOOL optional)
-{
- int i;
-
- for (i = 0; i < numEntries; i++)
- {
- BYTE type;
- int j;
- BOOL foundTypeMatch = FALSE;
-
- if (pSHGetFolderLocation)
- {
- type = testSHGetFolderLocation(testEntries[i].folder);
- for (j = 0; !foundTypeMatch && j < testEntries[i].numTypes; j++)
- if (testEntries[i].types[j] == type)
- foundTypeMatch = TRUE;
- ok(foundTypeMatch || optional || broken(type == 0xff) /* Win9x */,
- "%s has unexpected type %d (0x%02x)\n",
- getFolderName(testEntries[i].folder), type, type);
- }
- type = testSHGetSpecialFolderLocation(testEntries[i].folder);
- for (j = 0, foundTypeMatch = FALSE; !foundTypeMatch &&
- j < testEntries[i].numTypes; j++)
- if (testEntries[i].types[j] == type)
- foundTypeMatch = TRUE;
- ok(foundTypeMatch || optional || broken(type == 0xff) /* Win9x */,
- "%s has unexpected type %d (0x%02x)\n",
- getFolderName(testEntries[i].folder), type, type);
- switch (type)
- {
- case PT_FOLDER:
- case PT_DRIVE:
- case PT_DRIVE2:
- case PT_IESPECIAL2:
- test_SHGetFolderPath(optional, testEntries[i].folder);
- test_SHGetSpecialFolderPath(optional, testEntries[i].folder);
- break;
- }
- }
-}
-
-/* Attempts to verify that the folder path corresponding to the folder CSIDL
- * value has the same value as the environment variable with name envVar.
- * Doesn't mind if SHGetSpecialFolderPath fails for folder or if envVar isn't
- * set in this environment; different OS and shell version behave differently.
- * However, if both are present, fails if envVar's value is not the same
- * (byte-for-byte) as what SHGetSpecialFolderPath returns.
- */
-static void matchSpecialFolderPathToEnv(int folder, const char *envVar)
-{
- char path[MAX_PATH];
-
- if (!pSHGetSpecialFolderPathA) return;
+/* Standard CSIDL values (and their flags) uses only two less-significant bytes */
+#define NO_CSIDL 0x10000
+#define WINE_ATTRIBUTES_OPTIONAL 0x20000
+#define KNOWN_FOLDER(id, csidl, name, category, parent1, parent2, relative_path, parsing_name, attributes, definitionFlags) \
+ { &id, # id, csidl, # csidl, name, category, {&parent1, &parent2}, relative_path, parsing_name, attributes, definitionFlags, __LINE__ }
- if (pSHGetSpecialFolderPathA(NULL, path, folder, FALSE))
- {
- char *envVal = getenv(envVar);
+/* non-published known folders test */
+static const GUID _FOLDERID_CryptoKeys = {0xB88F4DAA, 0xE7BD, 0x49A9, {0xB7, 0x4D, 0x02, 0x88, 0x5A, 0x5D, 0xC7, 0x65} };
+static const GUID _FOLDERID_DpapiKeys = {0x10C07CD0, 0xEF91, 0x4567, {0xB8, 0x50, 0x44, 0x8B, 0x77, 0xCB, 0x37, 0xF9} };
+static const GUID _FOLDERID_SystemCertificates = {0x54EED2E0, 0xE7CA, 0x4FDB, {0x91, 0x48, 0x0F, 0x42, 0x47, 0x29, 0x1C, 0xFA} };
+static const GUID _FOLDERID_CredentialManager = {0x915221FB, 0x9EFE, 0x4BDA, {0x8F, 0xD7, 0xF7, 0x8D, 0xCA, 0x77, 0x4F, 0x87} };
- ok(!envVal || !lstrcmpiA(envVal, path),
- "%%%s%% does not match SHGetSpecialFolderPath:\n"
- "%%%s%% is %s\nSHGetSpecialFolderPath returns %s\n",
- envVar, envVar, envVal, path);
- }
-}
+struct knownFolderDef {
+ const KNOWNFOLDERID *folderId;
+ const char *sFolderId;
+ const int csidl;
+ const char *sCsidl;
+ const char *sName;
+ const KF_CATEGORY category;
+ const KNOWNFOLDERID *fidParents[2];
+ const char *sRelativePath;
+ const char *sParsingName;
+ const DWORD attributes;
+ const KF_DEFINITION_FLAGS definitionFlags;
+ const int line;
+};
-/* Attempts to match the GUID returned by SHGetFolderLocation for folder with
- * GUID. Assumes the type of the returned PIDL is in fact a GUID, but doesn't
- * fail if it isn't--that check should already have been done.
- * Fails if the returned PIDL is a GUID whose value does not match guid.
- */
-static void matchGUID(int folder, const GUID *guid, const GUID *guid_alt)
-{
- LPITEMIDLIST pidl;
- HRESULT hr;
-
- if (!pSHGetFolderLocation) return;
- if (!guid) return;
-
- pidl = NULL;
- hr = pSHGetFolderLocation(NULL, folder, NULL, 0, &pidl);
- if (hr == S_OK)
- {
- LPITEMIDLIST pidlLast = pILFindLastID(pidl);
-
- if (pidlLast && (pidlLast->mkid.abID[0] == PT_SHELLEXT ||
- pidlLast->mkid.abID[0] == PT_GUID))
- {
- GUID *shellGuid = (GUID *)(pidlLast->mkid.abID + 2);
-
- if (!guid_alt)
- ok(IsEqualIID(shellGuid, guid),
- "%s: got GUID %s, expected %s\n", getFolderName(folder),
- wine_dbgstr_guid(shellGuid), wine_dbgstr_guid(guid));
- else
- ok(IsEqualIID(shellGuid, guid) ||
- IsEqualIID(shellGuid, guid_alt),
- "%s: got GUID %s, expected %s or %s\n", getFolderName(folder),
- wine_dbgstr_guid(shellGuid), wine_dbgstr_guid(guid), wine_dbgstr_guid(guid_alt));
- }
- IMalloc_Free(pMalloc, pidl);
- }
-}
-
-/* Checks the PIDL type of all the known values. */
-static void test_PidlTypes(void)
-{
- /* Desktop */
- test_SHGetFolderPath(FALSE, CSIDL_DESKTOP);
- test_SHGetSpecialFolderPath(FALSE, CSIDL_DESKTOP);
-
- test_ShellValues(requiredShellValues, ARRAY_SIZE(requiredShellValues), FALSE);
- test_ShellValues(optionalShellValues, ARRAY_SIZE(optionalShellValues), TRUE);
-}
-
-/* FIXME: Should be in shobjidl.idl */
-DEFINE_GUID(CLSID_NetworkExplorerFolder, 0xF02C1A0D, 0xBE21, 0x4350, 0x88, 0xB0, 0x73, 0x67, 0xFC, 0x96, 0xEF, 0x3C);
-DEFINE_GUID(_CLSID_Documents, 0xA8CDFF1C, 0x4878, 0x43be, 0xB5, 0xFD, 0xF8, 0x09, 0x1C, 0x1C, 0x60, 0xD0);
-
-/* Verifies various shell virtual folders have the correct well-known GUIDs. */
-static void test_GUIDs(void)
-{
- matchGUID(CSIDL_BITBUCKET, &CLSID_RecycleBin, NULL);
- matchGUID(CSIDL_CONTROLS, &CLSID_ControlPanel, NULL);
- matchGUID(CSIDL_DRIVES, &CLSID_MyComputer, NULL);
- matchGUID(CSIDL_INTERNET, &CLSID_Internet, NULL);
- matchGUID(CSIDL_NETWORK, &CLSID_NetworkPlaces, &CLSID_NetworkExplorerFolder); /* Vista and higher */
- matchGUID(CSIDL_PERSONAL, &CLSID_MyDocuments, &_CLSID_Documents /* win8 */);
- matchGUID(CSIDL_COMMON_DOCUMENTS, &CLSID_CommonDocuments, NULL);
- matchGUID(CSIDL_PRINTERS, &CLSID_Printers, NULL);
-}
-
-/* Verifies various shell paths match the environment variables to which they
- * correspond.
- */
-static void test_EnvVars(void)
-{
- matchSpecialFolderPathToEnv(CSIDL_PROGRAM_FILES, "ProgramFiles");
- matchSpecialFolderPathToEnv(CSIDL_APPDATA, "APPDATA");
- matchSpecialFolderPathToEnv(CSIDL_PROFILE, "USERPROFILE");
- matchSpecialFolderPathToEnv(CSIDL_WINDOWS, "SystemRoot");
- matchSpecialFolderPathToEnv(CSIDL_WINDOWS, "windir");
- matchSpecialFolderPathToEnv(CSIDL_PROGRAM_FILES_COMMON, "CommonProgramFiles");
- /* this is only set on Wine, but can't hurt to verify it: */
- matchSpecialFolderPathToEnv(CSIDL_SYSTEM, "winsysdir");
-}
-
-/* Loosely based on PathRemoveBackslashA from dlls/shlwapi/path.c */
-static BOOL myPathIsRootA(LPCSTR lpszPath)
-{
- if (lpszPath && *lpszPath &&
- lpszPath[1] == ':' && lpszPath[2] == '\\' && lpszPath[3] == '\0')
- return TRUE; /* X:\ */
- return FALSE;
-}
-static LPSTR myPathRemoveBackslashA( LPSTR lpszPath )
-{
- LPSTR szTemp = NULL;
-
- if(lpszPath)
- {
- szTemp = CharPrevA(lpszPath, lpszPath + strlen(lpszPath));
- if (!myPathIsRootA(lpszPath) && *szTemp == '\\')
- *szTemp = '\0';
- }
- return szTemp;
-}
-
-/* Verifies the shell path for CSIDL_WINDOWS matches the return from
- * GetWindowsDirectory. If SHGetSpecialFolderPath fails, no harm, no foul--not
- * every shell32 version supports CSIDL_WINDOWS.
- */
-static void testWinDir(void)
-{
- char windowsShellPath[MAX_PATH], windowsDir[MAX_PATH] = { 0 };
-
- if (!pSHGetSpecialFolderPathA) return;
-
- if (pSHGetSpecialFolderPathA(NULL, windowsShellPath, CSIDL_WINDOWS, FALSE))
- {
- myPathRemoveBackslashA(windowsShellPath);
- GetWindowsDirectoryA(windowsDir, sizeof(windowsDir));
- myPathRemoveBackslashA(windowsDir);
- ok(!lstrcmpiA(windowsDir, windowsShellPath),
- "GetWindowsDirectory returns %s SHGetSpecialFolderPath returns %s\n",
- windowsDir, windowsShellPath);
- }
-}
-
-/* Verifies the shell path for CSIDL_SYSTEM matches the return from
- * GetSystemDirectory. If SHGetSpecialFolderPath fails, no harm,
- * no foul--not every shell32 version supports CSIDL_SYSTEM.
- */
-static void testSystemDir(void)
-{
- char systemShellPath[MAX_PATH], systemDir[MAX_PATH], systemDirx86[MAX_PATH];
-
- if (!pSHGetSpecialFolderPathA) return;
-
- GetSystemDirectoryA(systemDir, sizeof(systemDir));
- myPathRemoveBackslashA(systemDir);
- if (pSHGetSpecialFolderPathA(NULL, systemShellPath, CSIDL_SYSTEM, FALSE))
- {
- myPathRemoveBackslashA(systemShellPath);
- ok(!lstrcmpiA(systemDir, systemShellPath),
- "GetSystemDirectory returns %s SHGetSpecialFolderPath returns %s\n",
- systemDir, systemShellPath);
- }
-
- if (!pGetSystemWow64DirectoryA || !pGetSystemWow64DirectoryA(systemDirx86, sizeof(systemDirx86)))
- GetSystemDirectoryA(systemDirx86, sizeof(systemDirx86));
- myPathRemoveBackslashA(systemDirx86);
- if (pSHGetSpecialFolderPathA(NULL, systemShellPath, CSIDL_SYSTEMX86, FALSE))
- {
- myPathRemoveBackslashA(systemShellPath);
- ok(!lstrcmpiA(systemDirx86, systemShellPath) || broken(!lstrcmpiA(systemDir, systemShellPath)),
- "GetSystemDirectory returns %s SHGetSpecialFolderPath returns %s\n",
- systemDir, systemShellPath);
- }
-}
-
-/* Globals used by subprocesses */
-static int myARGC;
-static char **myARGV;
-static char base[MAX_PATH];
-static char selfname[MAX_PATH];
-
-static BOOL init(void)
-{
- myARGC = winetest_get_mainargs(&myARGV);
- if (!GetCurrentDirectoryA(sizeof(base), base)) return FALSE;
- strcpy(selfname, myARGV[0]);
- return TRUE;
-}
-
-static void doChild(const char *arg)
-{
- char path[MAX_PATH];
- HRESULT hr;
-
- if (arg[0] == '1')
- {
- LPITEMIDLIST pidl;
- char *p;
-
- /* test what happens when CSIDL_FAVORITES is set to a nonexistent directory */
-
- /* test some failure cases first: */
- hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES, NULL, SHGFP_TYPE_CURRENT, path);
- ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
- "SHGetFolderPath returned 0x%08x, expected 0x80070002\n", hr);
-
- pidl = NULL;
- hr = pSHGetFolderLocation(NULL, CSIDL_FAVORITES, NULL, 0, &pidl);
- ok(hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
- "SHGetFolderLocation returned 0x%08x\n", hr);
- if (hr == S_OK && pidl) IMalloc_Free(pMalloc, pidl);
-
- ok(!pSHGetSpecialFolderPathA(NULL, path, CSIDL_FAVORITES, FALSE),
- "SHGetSpecialFolderPath succeeded, expected failure\n");
-
- pidl = NULL;
- hr = pSHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidl);
- ok(hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
- "SHGetFolderLocation returned 0x%08x\n", hr);
-
- if (hr == S_OK && pidl) IMalloc_Free(pMalloc, pidl);
-
- /* now test success: */
- hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES | CSIDL_FLAG_CREATE, NULL,
- SHGFP_TYPE_CURRENT, path);
- ok (hr == S_OK, "got 0x%08x\n", hr);
- if (hr == S_OK)
- {
- BOOL ret;
-
- trace("CSIDL_FAVORITES was changed to %s\n", path);
- ret = CreateDirectoryA(path, NULL);
- ok(!ret, "expected failure with ERROR_ALREADY_EXISTS\n");
- if (!ret)
- ok(GetLastError() == ERROR_ALREADY_EXISTS,
- "got %d, expected ERROR_ALREADY_EXISTS\n", GetLastError());
-
- p = path + strlen(path);
- strcpy(p, "\\desktop.ini");
- DeleteFileA(path);
- *p = 0;
- SetFileAttributesA( path, FILE_ATTRIBUTE_NORMAL );
- ret = RemoveDirectoryA(path);
- ok( ret, "failed to remove %s error %u\n", path, GetLastError() );
- }
- }
- else if (arg[0] == '2')
- {
- /* make sure SHGetFolderPath still succeeds when the
- original value of CSIDL_FAVORITES is restored. */
- hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES | CSIDL_FLAG_CREATE, NULL,
- SHGFP_TYPE_CURRENT, path);
- ok(hr == S_OK, "SHGetFolderPath failed: 0x%08x\n", hr);
- }
-}
-
-/* Tests the return values from the various shell functions both with and
- * without the use of the CSIDL_FLAG_CREATE flag. This flag only appeared in
- * version 5 of the shell, so don't test unless it's at least version 5.
- * The test reads a value from the registry, modifies it, calls
- * SHGetFolderPath once with the CSIDL_FLAG_CREATE flag, and immediately
- * afterward without it. Then it restores the registry and deletes the folder
- * that was created.
- * One oddity with respect to restoration: shell32 caches somehow, so it needs
- * to be reloaded in order to see the correct (restored) value.
- * Some APIs unrelated to the ones under test may fail, but I expect they're
- * covered by other unit tests; I just print out something about failure to
- * help trace what's going on.
- */
-static void test_NonExistentPath(void)
-{
- static const char userShellFolders[] =
- "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders";
- char originalPath[MAX_PATH], modifiedPath[MAX_PATH];
- HKEY key;
-
- if (!pSHGetFolderPathA) return;
- if (!pSHGetFolderLocation) return;
- if (!pSHGetSpecialFolderPathA) return;
- if (!pSHGetSpecialFolderLocation) return;
- if (!pSHFileOperationA) return;
- if (shellVersion.dwMajorVersion < 5) return;
-
- if (!RegOpenKeyExA(HKEY_CURRENT_USER, userShellFolders, 0, KEY_ALL_ACCESS,
- &key))
- {
- DWORD len, type;
-
- len = sizeof(originalPath);
- if (!RegQueryValueExA(key, "Favorites", NULL, &type,
- (LPBYTE)&originalPath, &len))
- {
- size_t len = strlen(originalPath);
-
- memcpy(modifiedPath, originalPath, len);
- modifiedPath[len++] = '2';
- modifiedPath[len++] = '\0';
- trace("Changing CSIDL_FAVORITES to %s\n", modifiedPath);
- if (!RegSetValueExA(key, "Favorites", 0, type,
- (LPBYTE)modifiedPath, len))
- {
- char buffer[MAX_PATH+20];
- STARTUPINFOA startup;
- PROCESS_INFORMATION info;
-
- sprintf(buffer, "%s tests/shellpath.c 1", selfname);
- memset(&startup, 0, sizeof(startup));
- startup.cb = sizeof(startup);
- startup.dwFlags = STARTF_USESHOWWINDOW;
- startup.wShowWindow = SW_SHOWNORMAL;
- CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL,
- &startup, &info);
- winetest_wait_child_process( info.hProcess );
-
- /* restore original values: */
- trace("Restoring CSIDL_FAVORITES to %s\n", originalPath);
- RegSetValueExA(key, "Favorites", 0, type, (LPBYTE) originalPath,
- strlen(originalPath) + 1);
- RegFlushKey(key);
-
- sprintf(buffer, "%s tests/shellpath.c 2", selfname);
- memset(&startup, 0, sizeof(startup));
- startup.cb = sizeof(startup);
- startup.dwFlags = STARTF_USESHOWWINDOW;
- startup.wShowWindow = SW_SHOWNORMAL;
- CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL,
- &startup, &info);
- ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0,
- "child process termination\n");
- }
- }
- else skip("RegQueryValueExA(key, Favorites, ...) failed\n");
- if (key)
- RegCloseKey(key);
- }
- else skip("RegOpenKeyExA(HKEY_CURRENT_USER, %s, ...) failed\n", userShellFolders);
-}
-
-static void test_SHGetFolderPathEx(void)
-{
- HRESULT hr;
- WCHAR buffer[MAX_PATH], *path;
- DWORD len;
-
- if (!pSHGetKnownFolderPath || !pSHGetFolderPathEx)
- {
- win_skip("SHGetKnownFolderPath or SHGetFolderPathEx not available\n");
- return;
- }
-
-if (0) { /* crashes */
- hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, NULL);
- ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
-}
- /* non-existent folder id */
- path = (void *)0xdeadbeef;
- hr = pSHGetKnownFolderPath(&IID_IOleObject, 0, NULL, &path);
- ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr);
- ok(path == NULL, "got %p\n", path);
-
- path = NULL;
- hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, KF_FLAG_DEFAULT_PATH, NULL, &path);
- ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
- ok(path != NULL, "expected path != NULL\n");
- CoTaskMemFree(path);
-
- path = NULL;
- hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &path);
- ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
- ok(path != NULL, "expected path != NULL\n");
-
- hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, MAX_PATH);
- ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
- ok(!lstrcmpiW(path, buffer), "expected equal paths\n");
- len = lstrlenW(buffer);
- CoTaskMemFree(path);
-
- hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, 0);
- ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
-
-if (0) { /* crashes */
- hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, NULL, len + 1);
- ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
-
- hr = pSHGetFolderPathEx(NULL, 0, NULL, buffer, MAX_PATH);
- ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
-}
- hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, len);
- ok(hr == E_NOT_SUFFICIENT_BUFFER, "expected E_NOT_SUFFICIENT_BUFFER, got 0x%08x\n", hr);
-
- hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, len + 1);
- ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
-}
-
-/* Standard CSIDL values (and their flags) uses only two less-significant bytes */
-#define NO_CSIDL 0x10000
-#define WINE_ATTRIBUTES_OPTIONAL 0x20000
-#define KNOWN_FOLDER(id, csidl, name, category, parent1, parent2, relative_path, parsing_name, attributes, definitionFlags) \
- { &id, # id, csidl, # csidl, name, category, {&parent1, &parent2}, relative_path, parsing_name, attributes, definitionFlags, __LINE__ }
-
-/* non-published known folders test */
-static const GUID _FOLDERID_CryptoKeys = {0xB88F4DAA, 0xE7BD, 0x49A9, {0xB7, 0x4D, 0x02, 0x88, 0x5A, 0x5D, 0xC7, 0x65} };
-static const GUID _FOLDERID_DpapiKeys = {0x10C07CD0, 0xEF91, 0x4567, {0xB8, 0x50, 0x44, 0x8B, 0x77, 0xCB, 0x37, 0xF9} };
-static const GUID _FOLDERID_SystemCertificates = {0x54EED2E0, 0xE7CA, 0x4FDB, {0x91, 0x48, 0x0F, 0x42, 0x47, 0x29, 0x1C, 0xFA} };
-static const GUID _FOLDERID_CredentialManager = {0x915221FB, 0x9EFE, 0x4BDA, {0x8F, 0xD7, 0xF7, 0x8D, 0xCA, 0x77, 0x4F, 0x87} };
-
-struct knownFolderDef {
- const KNOWNFOLDERID *folderId;
- const char *sFolderId;
- const int csidl;
- const char *sCsidl;
- const char *sName;
- const KF_CATEGORY category;
- const KNOWNFOLDERID *fidParents[2];
- const char *sRelativePath;
- const char *sParsingName;
- const DWORD attributes;
- const KF_DEFINITION_FLAGS definitionFlags;
- const int line;
-};
-
-/* Note: content of parsing name may vary between Windows versions.
- * As a base, values from 6.0 (Vista) were used. Some entries may contain
- * alternative values. In that case, Windows version where the value was
- * found is noted.
- *
- * The list of values for parsing name was encoded as a number of null-
- * terminated strings placed one by one (separated by null byte only).
- * End of list is marked by two consecutive null bytes.
+/* Note: content of parsing name may vary between Windows versions.
+ * As a base, values from 6.0 (Vista) were used. Some entries may contain
+ * alternative values. In that case, Windows version where the value was
+ * found is noted.
+ *
+ * The list of values for parsing name was encoded as a number of null-
+ * terminated strings placed one by one (separated by null byte only).
+ * End of list is marked by two consecutive null bytes.
*/
static const struct knownFolderDef known_folders[] = {
KNOWN_FOLDER(FOLDERID_AddNewPrograms,
NULL,
0,
0),
- { 0 }
};
#undef KNOWN_FOLDER
-BOOL known_folder_found[ARRAY_SIZE(known_folders)-1];
+BOOL known_folder_found[ARRAY_SIZE(known_folders)];
+
+static void test_parameters(void)
+{
+ LPITEMIDLIST pidl = NULL;
+ char path[MAX_PATH];
+ HRESULT hr;
+
+ if (pSHGetFolderLocation)
+ {
+ /* check a bogus CSIDL: */
+ pidl = NULL;
+ hr = pSHGetFolderLocation(NULL, 0xeeee, NULL, 0, &pidl);
+ ok(hr == E_INVALIDARG, "got 0x%08x, expected E_INVALIDARG\n", hr);
+ if (hr == S_OK) IMalloc_Free(pMalloc, pidl);
+
+ /* check a bogus user token: */
+ pidl = NULL;
+ hr = pSHGetFolderLocation(NULL, CSIDL_FAVORITES, (HANDLE)2, 0, &pidl);
+ ok(hr == E_FAIL || hr == E_HANDLE, "got 0x%08x, expected E_FAIL or E_HANDLE\n", hr);
+ if (hr == S_OK) IMalloc_Free(pMalloc, pidl);
+
+ /* a NULL pidl pointer crashes, so don't test it */
+ }
+
+ if (pSHGetSpecialFolderLocation)
+ {
+ if (0)
+ /* crashes */
+ SHGetSpecialFolderLocation(NULL, 0, NULL);
+
+ hr = pSHGetSpecialFolderLocation(NULL, 0xeeee, &pidl);
+ ok(hr == E_INVALIDARG, "got returned 0x%08x\n", hr);
+ }
+
+ if (pSHGetFolderPathA)
+ {
+ /* expect 2's a bogus handle, especially since we didn't open it */
+ hr = pSHGetFolderPathA(NULL, CSIDL_DESKTOP, (HANDLE)2, SHGFP_TYPE_DEFAULT, path);
+ ok(hr == E_FAIL || hr == E_HANDLE || /* Vista and 2k8 */
+ broken(hr == S_OK), /* W2k and Me */ "got 0x%08x, expected E_FAIL\n", hr);
+
+ hr = pSHGetFolderPathA(NULL, 0xeeee, NULL, SHGFP_TYPE_DEFAULT, path);
+ ok(hr == E_INVALIDARG, "got 0x%08x, expected E_INVALIDARG\n", hr);
+ }
+
+ if (pSHGetSpecialFolderPathA)
+ {
+ BOOL ret;
+
+ if (0)
+ pSHGetSpecialFolderPathA(NULL, NULL, CSIDL_BITBUCKET, FALSE);
+
+ /* odd but true: calling with a NULL path still succeeds if it's a real
+ * dir (on some windows platform). on winME it generates exception.
+ */
+ ret = pSHGetSpecialFolderPathA(NULL, path, CSIDL_PROGRAMS, FALSE);
+ ok(ret, "got %d\n", ret);
+
+ ret = pSHGetSpecialFolderPathA(NULL, path, 0xeeee, FALSE);
+ ok(!ret, "got %d\n", ret);
+ }
+}
+
+/* Returns the folder's PIDL type, or 0xff if one can't be found. */
+static BYTE testSHGetFolderLocation(int folder)
+{
+ LPITEMIDLIST pidl;
+ HRESULT hr;
+ BYTE ret = 0xff;
+
+ /* treat absence of function as success */
+ if (!pSHGetFolderLocation) return TRUE;
+
+ pidl = NULL;
+ hr = pSHGetFolderLocation(NULL, folder, NULL, 0, &pidl);
+ if (hr == S_OK)
+ {
+ if (pidl)
+ {
+ LPITEMIDLIST pidlLast = pILFindLastID(pidl);
+
+ ok(pidlLast != NULL, "%s: ILFindLastID failed\n",
+ getFolderName(folder));
+ if (pidlLast)
+ ret = pidlLast->mkid.abID[0];
+ IMalloc_Free(pMalloc, pidl);
+ }
+ }
+ return ret;
+}
+
+/* Returns the folder's PIDL type, or 0xff if one can't be found. */
+static BYTE testSHGetSpecialFolderLocation(int folder)
+{
+ LPITEMIDLIST pidl;
+ HRESULT hr;
+ BYTE ret = 0xff;
+
+ /* treat absence of function as success */
+ if (!pSHGetSpecialFolderLocation) return TRUE;
+
+ pidl = NULL;
+ hr = pSHGetSpecialFolderLocation(NULL, folder, &pidl);
+ if (hr == S_OK)
+ {
+ if (pidl)
+ {
+ LPITEMIDLIST pidlLast = pILFindLastID(pidl);
+
+ ok(pidlLast != NULL,
+ "%s: ILFindLastID failed\n", getFolderName(folder));
+ if (pidlLast)
+ ret = pidlLast->mkid.abID[0];
+ IMalloc_Free(pMalloc, pidl);
+ }
+ }
+ return ret;
+}
+
+static void test_SHGetFolderPath(BOOL optional, int folder)
+{
+ char path[MAX_PATH];
+ HRESULT hr;
+
+ if (!pSHGetFolderPathA) return;
+
+ hr = pSHGetFolderPathA(NULL, folder, NULL, SHGFP_TYPE_CURRENT, path);
+ ok(hr == S_OK || optional,
+ "SHGetFolderPathA(NULL, %s, NULL, SHGFP_TYPE_CURRENT, path) failed: 0x%08x\n", getFolderName(folder), hr);
+}
+
+static void test_SHGetSpecialFolderPath(BOOL optional, int folder)
+{
+ char path[MAX_PATH];
+ BOOL ret;
+
+ if (!pSHGetSpecialFolderPathA) return;
+
+ ret = pSHGetSpecialFolderPathA(NULL, path, folder, FALSE);
+ if (ret && winetest_interactive)
+ printf("%s: %s\n", getFolderName(folder), path);
+ ok(ret || optional,
+ "SHGetSpecialFolderPathA(NULL, path, %s, FALSE) failed\n",
+ getFolderName(folder));
+}
+
+static void test_ShellValues(const struct shellExpectedValues testEntries[],
+ int numEntries, BOOL optional)
+{
+ int i;
+
+ for (i = 0; i < numEntries; i++)
+ {
+ BYTE type;
+ int j;
+ BOOL foundTypeMatch = FALSE;
+
+ if (pSHGetFolderLocation)
+ {
+ type = testSHGetFolderLocation(testEntries[i].folder);
+ for (j = 0; !foundTypeMatch && j < testEntries[i].numTypes; j++)
+ if (testEntries[i].types[j] == type)
+ foundTypeMatch = TRUE;
+ ok(foundTypeMatch || optional || broken(type == 0xff) /* Win9x */,
+ "%s has unexpected type %d (0x%02x)\n",
+ getFolderName(testEntries[i].folder), type, type);
+ }
+ type = testSHGetSpecialFolderLocation(testEntries[i].folder);
+ for (j = 0, foundTypeMatch = FALSE; !foundTypeMatch &&
+ j < testEntries[i].numTypes; j++)
+ if (testEntries[i].types[j] == type)
+ foundTypeMatch = TRUE;
+ ok(foundTypeMatch || optional || broken(type == 0xff) /* Win9x */,
+ "%s has unexpected type %d (0x%02x)\n",
+ getFolderName(testEntries[i].folder), type, type);
+ switch (type)
+ {
+ case PT_FOLDER:
+ case PT_DRIVE:
+ case PT_DRIVE2:
+ case PT_IESPECIAL2:
+ test_SHGetFolderPath(optional, testEntries[i].folder);
+ test_SHGetSpecialFolderPath(optional, testEntries[i].folder);
+ break;
+ }
+ }
+}
+
+/* Attempts to verify that the folder path corresponding to the folder CSIDL
+ * value has the same value as the environment variable with name envVar.
+ * Doesn't mind if SHGetSpecialFolderPath fails for folder or if envVar isn't
+ * set in this environment; different OS and shell version behave differently.
+ * However, if both are present, fails if envVar's value is not the same
+ * (byte-for-byte) as what SHGetSpecialFolderPath returns.
+ */
+static void matchSpecialFolderPathToEnv(int folder, const char *envVar)
+{
+ char path[MAX_PATH];
+
+ if (!pSHGetSpecialFolderPathA) return;
+
+ if (pSHGetSpecialFolderPathA(NULL, path, folder, FALSE))
+ {
+ char *envVal = getenv(envVar);
+
+ ok(!envVal || !lstrcmpiA(envVal, path),
+ "%%%s%% does not match SHGetSpecialFolderPath:\n"
+ "%%%s%% is %s\nSHGetSpecialFolderPath returns %s\n",
+ envVar, envVar, envVal, path);
+ }
+}
+
+/* Attempts to match the GUID returned by SHGetFolderLocation for folder with
+ * GUID. Assumes the type of the returned PIDL is in fact a GUID, but doesn't
+ * fail if it isn't--that check should already have been done.
+ * Fails if the returned PIDL is a GUID whose value does not match guid.
+ */
+static void matchGUID(int folder, const GUID *guid, const GUID *guid_alt)
+{
+ LPITEMIDLIST pidl;
+ HRESULT hr;
+
+ if (!pSHGetFolderLocation) return;
+ if (!guid) return;
+
+ pidl = NULL;
+ hr = pSHGetFolderLocation(NULL, folder, NULL, 0, &pidl);
+ if (hr == S_OK)
+ {
+ LPITEMIDLIST pidlLast = pILFindLastID(pidl);
+
+ if (pidlLast && (pidlLast->mkid.abID[0] == PT_SHELLEXT ||
+ pidlLast->mkid.abID[0] == PT_GUID))
+ {
+ GUID *shellGuid = (GUID *)(pidlLast->mkid.abID + 2);
+
+ if (!guid_alt)
+ ok(IsEqualIID(shellGuid, guid),
+ "%s: got GUID %s, expected %s\n", getFolderName(folder),
+ wine_dbgstr_guid(shellGuid), wine_dbgstr_guid(guid));
+ else
+ ok(IsEqualIID(shellGuid, guid) ||
+ IsEqualIID(shellGuid, guid_alt),
+ "%s: got GUID %s, expected %s or %s\n", getFolderName(folder),
+ wine_dbgstr_guid(shellGuid), wine_dbgstr_guid(guid), wine_dbgstr_guid(guid_alt));
+ }
+ IMalloc_Free(pMalloc, pidl);
+ }
+}
+
+/* Checks the PIDL type of all the known values. */
+static void test_PidlTypes(void)
+{
+ /* Desktop */
+ test_SHGetFolderPath(FALSE, CSIDL_DESKTOP);
+ test_SHGetSpecialFolderPath(FALSE, CSIDL_DESKTOP);
+
+ test_ShellValues(requiredShellValues, ARRAY_SIZE(requiredShellValues), FALSE);
+ test_ShellValues(optionalShellValues, ARRAY_SIZE(optionalShellValues), TRUE);
+}
+
+/* FIXME: Should be in shobjidl.idl */
+DEFINE_GUID(CLSID_NetworkExplorerFolder, 0xF02C1A0D, 0xBE21, 0x4350, 0x88, 0xB0, 0x73, 0x67, 0xFC, 0x96, 0xEF, 0x3C);
+DEFINE_GUID(_CLSID_Documents, 0xA8CDFF1C, 0x4878, 0x43be, 0xB5, 0xFD, 0xF8, 0x09, 0x1C, 0x1C, 0x60, 0xD0);
+
+/* Verifies various shell virtual folders have the correct well-known GUIDs. */
+static void test_GUIDs(void)
+{
+ matchGUID(CSIDL_BITBUCKET, &CLSID_RecycleBin, NULL);
+ matchGUID(CSIDL_CONTROLS, &CLSID_ControlPanel, NULL);
+ matchGUID(CSIDL_DRIVES, &CLSID_MyComputer, NULL);
+ matchGUID(CSIDL_INTERNET, &CLSID_Internet, NULL);
+ matchGUID(CSIDL_NETWORK, &CLSID_NetworkPlaces, &CLSID_NetworkExplorerFolder); /* Vista and higher */
+ matchGUID(CSIDL_PERSONAL, &CLSID_MyDocuments, &_CLSID_Documents /* win8 */);
+ matchGUID(CSIDL_COMMON_DOCUMENTS, &CLSID_CommonDocuments, NULL);
+ matchGUID(CSIDL_PRINTERS, &CLSID_Printers, NULL);
+}
+
+/* Verifies various shell paths match the environment variables to which they
+ * correspond.
+ */
+static void test_EnvVars(void)
+{
+ matchSpecialFolderPathToEnv(CSIDL_PROGRAM_FILES, "ProgramFiles");
+ matchSpecialFolderPathToEnv(CSIDL_APPDATA, "APPDATA");
+ matchSpecialFolderPathToEnv(CSIDL_PROFILE, "USERPROFILE");
+ matchSpecialFolderPathToEnv(CSIDL_WINDOWS, "SystemRoot");
+ matchSpecialFolderPathToEnv(CSIDL_WINDOWS, "windir");
+ matchSpecialFolderPathToEnv(CSIDL_PROGRAM_FILES_COMMON, "CommonProgramFiles");
+ /* this is only set on Wine, but can't hurt to verify it: */
+ matchSpecialFolderPathToEnv(CSIDL_SYSTEM, "winsysdir");
+}
+
+/* Loosely based on PathRemoveBackslashA from dlls/shlwapi/path.c */
+static BOOL myPathIsRootA(LPCSTR lpszPath)
+{
+ if (lpszPath && *lpszPath &&
+ lpszPath[1] == ':' && lpszPath[2] == '\\' && lpszPath[3] == '\0')
+ return TRUE; /* X:\ */
+ return FALSE;
+}
+static LPSTR myPathRemoveBackslashA( LPSTR lpszPath )
+{
+ LPSTR szTemp = NULL;
+
+ if(lpszPath)
+ {
+ szTemp = CharPrevA(lpszPath, lpszPath + strlen(lpszPath));
+ if (!myPathIsRootA(lpszPath) && *szTemp == '\\')
+ *szTemp = '\0';
+ }
+ return szTemp;
+}
+
+/* Verifies the shell path for CSIDL_WINDOWS matches the return from
+ * GetWindowsDirectory. If SHGetSpecialFolderPath fails, no harm, no foul--not
+ * every shell32 version supports CSIDL_WINDOWS.
+ */
+static void testWinDir(void)
+{
+ char windowsShellPath[MAX_PATH], windowsDir[MAX_PATH] = { 0 };
+
+ if (!pSHGetSpecialFolderPathA) return;
+
+ if (pSHGetSpecialFolderPathA(NULL, windowsShellPath, CSIDL_WINDOWS, FALSE))
+ {
+ myPathRemoveBackslashA(windowsShellPath);
+ GetWindowsDirectoryA(windowsDir, sizeof(windowsDir));
+ myPathRemoveBackslashA(windowsDir);
+ ok(!lstrcmpiA(windowsDir, windowsShellPath),
+ "GetWindowsDirectory returns %s SHGetSpecialFolderPath returns %s\n",
+ windowsDir, windowsShellPath);
+ }
+}
+
+/* Verifies the shell path for CSIDL_SYSTEM matches the return from
+ * GetSystemDirectory. If SHGetSpecialFolderPath fails, no harm,
+ * no foul--not every shell32 version supports CSIDL_SYSTEM.
+ */
+static void testSystemDir(void)
+{
+ char systemShellPath[MAX_PATH], systemDir[MAX_PATH], systemDirx86[MAX_PATH];
+
+ if (!pSHGetSpecialFolderPathA) return;
+
+ GetSystemDirectoryA(systemDir, sizeof(systemDir));
+ myPathRemoveBackslashA(systemDir);
+ if (pSHGetSpecialFolderPathA(NULL, systemShellPath, CSIDL_SYSTEM, FALSE))
+ {
+ myPathRemoveBackslashA(systemShellPath);
+ ok(!lstrcmpiA(systemDir, systemShellPath),
+ "GetSystemDirectory returns %s SHGetSpecialFolderPath returns %s\n",
+ systemDir, systemShellPath);
+ }
+
+ if (!pGetSystemWow64DirectoryA || !pGetSystemWow64DirectoryA(systemDirx86, sizeof(systemDirx86)))
+ GetSystemDirectoryA(systemDirx86, sizeof(systemDirx86));
+ myPathRemoveBackslashA(systemDirx86);
+ if (pSHGetSpecialFolderPathA(NULL, systemShellPath, CSIDL_SYSTEMX86, FALSE))
+ {
+ myPathRemoveBackslashA(systemShellPath);
+ ok(!lstrcmpiA(systemDirx86, systemShellPath) || broken(!lstrcmpiA(systemDir, systemShellPath)),
+ "GetSystemDirectory returns %s SHGetSpecialFolderPath returns %s\n",
+ systemDir, systemShellPath);
+ }
+}
+
+/* Globals used by subprocesses */
+static int myARGC;
+static char **myARGV;
+static char base[MAX_PATH];
+static char selfname[MAX_PATH];
+
+static BOOL init(void)
+{
+ myARGC = winetest_get_mainargs(&myARGV);
+ if (!GetCurrentDirectoryA(sizeof(base), base)) return FALSE;
+ strcpy(selfname, myARGV[0]);
+ return TRUE;
+}
+
+static void doChild(const char *arg)
+{
+ char path[MAX_PATH];
+ HRESULT hr;
+
+ if (arg[0] == '1')
+ {
+ LPITEMIDLIST pidl;
+ char *p;
+
+ /* test what happens when CSIDL_FAVORITES is set to a nonexistent directory */
+
+ /* test some failure cases first: */
+ hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES, NULL, SHGFP_TYPE_CURRENT, path);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
+ "SHGetFolderPath returned 0x%08x, expected 0x80070002\n", hr);
+
+ pidl = NULL;
+ hr = pSHGetFolderLocation(NULL, CSIDL_FAVORITES, NULL, 0, &pidl);
+ ok(hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
+ "SHGetFolderLocation returned 0x%08x\n", hr);
+ if (hr == S_OK && pidl) IMalloc_Free(pMalloc, pidl);
+
+ ok(!pSHGetSpecialFolderPathA(NULL, path, CSIDL_FAVORITES, FALSE),
+ "SHGetSpecialFolderPath succeeded, expected failure\n");
+
+ pidl = NULL;
+ hr = pSHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidl);
+ ok(hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
+ "SHGetFolderLocation returned 0x%08x\n", hr);
+
+ if (hr == S_OK && pidl) IMalloc_Free(pMalloc, pidl);
+
+ /* now test success: */
+ hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES | CSIDL_FLAG_CREATE, NULL,
+ SHGFP_TYPE_CURRENT, path);
+ ok (hr == S_OK, "got 0x%08x\n", hr);
+ if (hr == S_OK)
+ {
+ BOOL ret;
+
+ trace("CSIDL_FAVORITES was changed to %s\n", path);
+ ret = CreateDirectoryA(path, NULL);
+ ok(!ret, "expected failure with ERROR_ALREADY_EXISTS\n");
+ if (!ret)
+ ok(GetLastError() == ERROR_ALREADY_EXISTS,
+ "got %d, expected ERROR_ALREADY_EXISTS\n", GetLastError());
+
+ p = path + strlen(path);
+ strcpy(p, "\\desktop.ini");
+ DeleteFileA(path);
+ *p = 0;
+ SetFileAttributesA( path, FILE_ATTRIBUTE_NORMAL );
+ ret = RemoveDirectoryA(path);
+ ok( ret, "failed to remove %s error %u\n", path, GetLastError() );
+ }
+ }
+ else if (arg[0] == '2')
+ {
+ /* make sure SHGetFolderPath still succeeds when the
+ original value of CSIDL_FAVORITES is restored. */
+ hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES | CSIDL_FLAG_CREATE, NULL,
+ SHGFP_TYPE_CURRENT, path);
+ ok(hr == S_OK, "SHGetFolderPath failed: 0x%08x\n", hr);
+ }
+}
+
+/* Tests the return values from the various shell functions both with and
+ * without the use of the CSIDL_FLAG_CREATE flag. This flag only appeared in
+ * version 5 of the shell, so don't test unless it's at least version 5.
+ * The test reads a value from the registry, modifies it, calls
+ * SHGetFolderPath once with the CSIDL_FLAG_CREATE flag, and immediately
+ * afterward without it. Then it restores the registry and deletes the folder
+ * that was created.
+ * One oddity with respect to restoration: shell32 caches somehow, so it needs
+ * to be reloaded in order to see the correct (restored) value.
+ * Some APIs unrelated to the ones under test may fail, but I expect they're
+ * covered by other unit tests; I just print out something about failure to
+ * help trace what's going on.
+ */
+static void test_NonExistentPath(void)
+{
+ static const char userShellFolders[] =
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders";
+ char originalPath[MAX_PATH], modifiedPath[MAX_PATH];
+ HKEY key;
+
+ if (!pSHGetFolderPathA) return;
+ if (!pSHGetFolderLocation) return;
+ if (!pSHGetSpecialFolderPathA) return;
+ if (!pSHGetSpecialFolderLocation) return;
+ if (!pSHFileOperationA) return;
+ if (shellVersion.dwMajorVersion < 5) return;
+
+ if (!RegOpenKeyExA(HKEY_CURRENT_USER, userShellFolders, 0, KEY_ALL_ACCESS,
+ &key))
+ {
+ DWORD len, type;
+
+ len = sizeof(originalPath);
+ if (!RegQueryValueExA(key, "Favorites", NULL, &type,
+ (LPBYTE)&originalPath, &len))
+ {
+ size_t len = strlen(originalPath);
+
+ memcpy(modifiedPath, originalPath, len);
+ modifiedPath[len++] = '2';
+ modifiedPath[len++] = '\0';
+ trace("Changing CSIDL_FAVORITES to %s\n", modifiedPath);
+ if (!RegSetValueExA(key, "Favorites", 0, type,
+ (LPBYTE)modifiedPath, len))
+ {
+ char buffer[MAX_PATH+20];
+ STARTUPINFOA startup;
+ PROCESS_INFORMATION info;
+
+ sprintf(buffer, "%s tests/shellpath.c 1", selfname);
+ memset(&startup, 0, sizeof(startup));
+ startup.cb = sizeof(startup);
+ startup.dwFlags = STARTF_USESHOWWINDOW;
+ startup.wShowWindow = SW_SHOWNORMAL;
+ CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL,
+ &startup, &info);
+ winetest_wait_child_process( info.hProcess );
+
+ /* restore original values: */
+ trace("Restoring CSIDL_FAVORITES to %s\n", originalPath);
+ RegSetValueExA(key, "Favorites", 0, type, (LPBYTE) originalPath,
+ strlen(originalPath) + 1);
+ RegFlushKey(key);
+
+ sprintf(buffer, "%s tests/shellpath.c 2", selfname);
+ memset(&startup, 0, sizeof(startup));
+ startup.cb = sizeof(startup);
+ startup.dwFlags = STARTF_USESHOWWINDOW;
+ startup.wShowWindow = SW_SHOWNORMAL;
+ CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL,
+ &startup, &info);
+ ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0,
+ "child process termination\n");
+ }
+ }
+ else skip("RegQueryValueExA(key, Favorites, ...) failed\n");
+ if (key)
+ RegCloseKey(key);
+ }
+ else skip("RegOpenKeyExA(HKEY_CURRENT_USER, %s, ...) failed\n", userShellFolders);
+}
+
+static void test_SHGetFolderPathEx(void)
+{
+ WCHAR buffer[MAX_PATH], *path, *path2;
+ unsigned int i;
+ HRESULT hr;
+ DWORD len;
+
+ if (!pSHGetKnownFolderPath || !pSHGetFolderPathEx)
+ {
+ win_skip("SHGetKnownFolderPath or SHGetFolderPathEx not available\n");
+ return;
+ }
+
+if (0) { /* crashes */
+ hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, NULL);
+ ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
+}
+ /* non-existent folder id */
+ path = (void *)0xdeadbeef;
+ hr = pSHGetKnownFolderPath(&IID_IOleObject, 0, NULL, &path);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr);
+ ok(path == NULL, "got %p\n", path);
+
+ path = NULL;
+ hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, KF_FLAG_DEFAULT_PATH, NULL, &path);
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+ ok(path != NULL, "expected path != NULL\n");
+ CoTaskMemFree(path);
+
+ for (i = 0; i < ARRAY_SIZE(known_folders); ++i)
+ {
+ const KNOWNFOLDERID *folder_id = known_folders[i].folderId;
+
+ path = NULL;
+ hr = pSHGetKnownFolderPath(folder_id, KF_FLAG_DEFAULT, NULL, &path);
+ if (FAILED(hr))
+ continue;
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+ ok(path != NULL, "expected path != NULL\n");
+
+ path2 = NULL;
+ hr = pSHGetKnownFolderPath(folder_id, KF_FLAG_SIMPLE_IDLIST, NULL, &path2);
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+ ok(path2 != NULL, "expected path != NULL\n");
+ ok(!lstrcmpiW(path, path2), "expected equal paths: %s, %s\n", wine_dbgstr_w(path), wine_dbgstr_w(path2));
+ CoTaskMemFree(path2);
+
+ path2 = NULL;
+ hr = pSHGetKnownFolderPath(folder_id, KF_FLAG_DONT_UNEXPAND, NULL, &path2);
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+ ok(path2 != NULL, "expected path != NULL\n");
+ ok(!lstrcmpiW(path, path2), "expected equal paths: %s, %s\n", wine_dbgstr_w(path), wine_dbgstr_w(path2));
+ CoTaskMemFree(path2);
+
+ path2 = NULL;
+ hr = pSHGetKnownFolderPath(folder_id, KF_FLAG_SIMPLE_IDLIST | KF_FLAG_DONT_UNEXPAND, NULL, &path2);
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+ ok(path2 != NULL, "expected path != NULL\n");
+ ok(!lstrcmpiW(path, path2), "expected equal paths: %s, %s\n", wine_dbgstr_w(path), wine_dbgstr_w(path2));
+ CoTaskMemFree(path2);
+
+ CoTaskMemFree(path);
+ }
+
+ path = NULL;
+ hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &path);
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+ ok(path != NULL, "expected path != NULL\n");
+
+ hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, MAX_PATH);
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+ ok(!lstrcmpiW(path, buffer), "expected equal paths\n");
+ len = lstrlenW(buffer);
+ CoTaskMemFree(path);
+
+ hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, 0);
+ ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
+
+if (0) { /* crashes */
+ hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, NULL, len + 1);
+ ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
+
+ hr = pSHGetFolderPathEx(NULL, 0, NULL, buffer, MAX_PATH);
+ ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
+}
+ hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, len);
+ ok(hr == E_NOT_SUFFICIENT_BUFFER, "expected E_NOT_SUFFICIENT_BUFFER, got 0x%08x\n", hr);
+
+ hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, len + 1);
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+}
static BOOL is_in_strarray(const WCHAR *needle, const char *hay)
{
static void check_known_folder(IKnownFolderManager *mgr, KNOWNFOLDERID *folderId)
{
HRESULT hr;
- const struct knownFolderDef *known_folder = &known_folders[0];
int csidl, expectedCsidl, ret;
KNOWNFOLDER_DEFINITION kfd;
IKnownFolder *folder;
WCHAR sName[1024];
- BOOL *current_known_folder_found = &known_folder_found[0];
BOOL found = FALSE;
+ unsigned int i;
- while(known_folder->folderId != NULL)
+ for (i = 0; i < ARRAY_SIZE(known_folders); ++i)
{
+ const struct knownFolderDef *known_folder = &known_folders[i];
+
if(IsEqualGUID(known_folder->folderId, folderId))
{
- *current_known_folder_found = TRUE;
+ known_folder_found[i] = TRUE;
found = TRUE;
/* verify CSIDL */
if(!(known_folder->csidl & NO_CSIDL))
break;
}
- known_folder++;
- current_known_folder_found++;
}
if(!found)
"%HOMEDRIVE%%HOMEPATH%",
"%OS% %windir%"}; /* always the last entry in the table */
- for (i = 0; i < (sizeof(names)/sizeof(LPSTR)); i++)
+ for (i = 0; i < (ARRAY_SIZE(names)); i++)
{
memset(bufferA, '#', MAX_PATH - 1);
bufferA[MAX_PATH - 1] = 0;
dwMaxSubkeyLen++;
dwMaxValueLen++;
dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
- if (dwMaxLen > sizeof(szNameBuf)/sizeof(CHAR))
+ if (dwMaxLen > ARRAY_SIZE(szNameBuf))
{
/* Name too big: alloc a buffer for it */
if (!(lpszName = heap_alloc(dwMaxLen*sizeof(CHAR))))
int i, count;
/* trace("----- cmd='%s'\n", test->cmd); */
- MultiByteToWideChar(CP_ACP, 0, test->cmd, -1, cmdW, sizeof(cmdW)/sizeof(*cmdW));
+ MultiByteToWideChar(CP_ACP, 0, test->cmd, -1, cmdW, ARRAY_SIZE(cmdW));
argsW = cl2a = CommandLineToArgvW(cmdW, &cl2a_count);
if (argsW == NULL && cl2a_count == -1)
{
{
if (i < count)
{
- MultiByteToWideChar(CP_ACP, 0, test->args[i], -1, argW, sizeof(argW)/sizeof(*argW));
+ MultiByteToWideChar(CP_ACP, 0, test->args[i], -1, argW, ARRAY_SIZE(argW));
todo_wine_if(test->todo & (1 << (i+4)))
ok(!lstrcmpW(*argsW, argW), "%s: arg[%d] expected %s but got %s\n", test->cmd, i, wine_dbgstr_w(argW), wine_dbgstr_w(*argsW));
}
"expected NULL-terminated list of commandline arguments\n");
if (numargs == 1)
{
- GetModuleFileNameW(NULL, strW, sizeof(strW)/sizeof(*strW));
+ GetModuleFileNameW(NULL, strW, ARRAY_SIZE(strW));
ok(!lstrcmpW(args[0], strW), "wrong path to the current executable: %s instead of %s\n", wine_dbgstr_w(args[0]), wine_dbgstr_w(strW));
}
if (args) LocalFree(args);
const char* verb;
const char* params;
int todo;
- cmdline_tests_t cmd;
- cmdline_tests_t broken;
+ const char *cmd;
+ const char *broken;
} argify_tests_t;
static const argify_tests_t argify_tests[] =
* parameters string, including the trailing spaces, no matter what
* arguments have already been used.
*/
- {"Params232S", "p2 p3 p4 ", 0xc2,
- {" p2 p3 \"p2\" \"p2 p3 p4 \"",
- {"", "p2", "p3", "p2", "p2 p3 p4 ", NULL}, 0}},
+ {"Params232S", "p2 p3 p4 ", TRUE,
+ " p2 p3 \"p2\" \"p2 p3 p4 \""},
/* Unquoted argument references like %2 don't automatically quote their
* argument. Similarly, when they are quoted they don't escape the quotes
* that their argument may contain.
*/
- {"Params232S", "\"p two\" p3 p4 ", 0x3f3,
- {" p two p3 \"p two\" \"\"p two\" p3 p4 \"",
- {"", "p", "two", "p3", "p two", "p", "two p3 p4 ", NULL}, 0}},
+ {"Params232S", "\"p two\" p3 p4 ", TRUE,
+ " p two p3 \"p two\" \"\"p two\" p3 p4 \""},
/* Only single digits are supported so only %1 to %9. Shown here with %20
* because %10 is a pain.
*/
- {"Params20", "p", 0,
- {" \"p0\"",
- {"", "p0", NULL}, 0}},
+ {"Params20", "p", FALSE,
+ " \"p0\""},
/* Only (double-)quotes have a special meaning. */
- {"Params23456", "'p2 p3` p4\\ $even", 0x40,
- {" \"'p2\" \"p3`\" \"p4\\\" \"$even\" \"\"",
- {"", "'p2", "p3`", "p4\" $even \"", NULL}, 0}},
+ {"Params23456", "'p2 p3` p4\\ $even", FALSE,
+ " \"'p2\" \"p3`\" \"p4\\\" \"$even\" \"\""},
- {"Params23456", "p=2 p-3 p4\tp4\rp4\np4", 0x1c2,
- {" \"p=2\" \"p-3\" \"p4\tp4\rp4\np4\" \"\" \"\"",
- {"", "p=2", "p-3", "p4\tp4\rp4\np4", "", "", NULL}, 0}},
+ {"Params23456", "p=2 p-3 p4\tp4\rp4\np4", TRUE,
+ " \"p=2\" \"p-3\" \"p4\tp4\rp4\np4\" \"\" \"\""},
/* In unquoted strings, quotes are treated are a parameter separator just
* like spaces! However they can be doubled to get a literal quote.
* 2n quotes -> n quotes
* 2n+1 quotes -> n quotes and a parameter separator
*/
- {"Params23456789", "one\"quote \"p four\" one\"quote p7", 0xff3,
- {" \"one\" \"quote\" \"p four\" \"one\" \"quote\" \"p7\" \"\" \"\"",
- {"", "one", "quote", "p four", "one", "quote", "p7", "", "", NULL}, 0}},
+ {"Params23456789", "one\"quote \"p four\" one\"quote p7", TRUE,
+ " \"one\" \"quote\" \"p four\" \"one\" \"quote\" \"p7\" \"\" \"\""},
- {"Params23456789", "two\"\"quotes \"p three\" two\"\"quotes p5", 0xf2,
- {" \"two\"quotes\" \"p three\" \"two\"quotes\" \"p5\" \"\" \"\" \"\" \"\"",
- {"", "twoquotes p", "three twoquotes", "p5", "", "", "", "", NULL}, 0}},
+ {"Params23456789", "two\"\"quotes \"p three\" two\"\"quotes p5", TRUE,
+ " \"two\"quotes\" \"p three\" \"two\"quotes\" \"p5\" \"\" \"\" \"\" \"\""},
- {"Params23456789", "three\"\"\"quotes \"p four\" three\"\"\"quotes p6", 0xff3,
- {" \"three\"\" \"quotes\" \"p four\" \"three\"\" \"quotes\" \"p6\" \"\" \"\"",
- {"", "three\"", "quotes", "p four", "three\"", "quotes", "p6", "", "", NULL}, 0}},
+ {"Params23456789", "three\"\"\"quotes \"p four\" three\"\"\"quotes p6", TRUE,
+ " \"three\"\" \"quotes\" \"p four\" \"three\"\" \"quotes\" \"p6\" \"\" \"\""},
- {"Params23456789", "four\"\"\"\"quotes \"p three\" four\"\"\"\"quotes p5", 0xf3,
- {" \"four\"\"quotes\" \"p three\" \"four\"\"quotes\" \"p5\" \"\" \"\" \"\" \"\"",
- {"", "four\"quotes p", "three fourquotes p5 \"", "", "", "", NULL}, 0}},
+ {"Params23456789", "four\"\"\"\"quotes \"p three\" four\"\"\"\"quotes p5", TRUE,
+ " \"four\"\"quotes\" \"p three\" \"four\"\"quotes\" \"p5\" \"\" \"\" \"\" \"\""},
/* Quoted strings cannot be continued by tacking on a non space character
* either.
*/
- {"Params23456", "\"p two\"p3 \"p four\"p5 p6", 0x1f3,
- {" \"p two\" \"p3\" \"p four\" \"p5\" \"p6\"",
- {"", "p two", "p3", "p four", "p5", "p6", NULL}, 0}},
+ {"Params23456", "\"p two\"p3 \"p four\"p5 p6", TRUE,
+ " \"p two\" \"p3\" \"p four\" \"p5\" \"p6\""},
/* In quoted strings, the quotes are halved and an odd number closes the
* string. Specifically:
* 2n quotes -> n quotes
* 2n+1 quotes -> n quotes and closes the string and hence the parameter
*/
- {"Params23456789", "\"one q\"uote \"p four\" \"one q\"uote p7", 0xff3,
- {" \"one q\" \"uote\" \"p four\" \"one q\" \"uote\" \"p7\" \"\" \"\"",
- {"", "one q", "uote", "p four", "one q", "uote", "p7", "", "", NULL}, 0}},
+ {"Params23456789", "\"one q\"uote \"p four\" \"one q\"uote p7", TRUE,
+ " \"one q\" \"uote\" \"p four\" \"one q\" \"uote\" \"p7\" \"\" \"\""},
- {"Params23456789", "\"two \"\" quotes\" \"p three\" \"two \"\" quotes\" p5", 0x1ff3,
- {" \"two \" quotes\" \"p three\" \"two \" quotes\" \"p5\" \"\" \"\" \"\" \"\"",
- {"", "two ", "quotes p", "three two", " quotes", "p5", "", "", "", "", NULL}, 0}},
+ {"Params23456789", "\"two \"\" quotes\" \"p three\" \"two \"\" quotes\" p5", TRUE,
+ " \"two \" quotes\" \"p three\" \"two \" quotes\" \"p5\" \"\" \"\" \"\" \"\""},
- {"Params23456789", "\"three q\"\"\"uotes \"p four\" \"three q\"\"\"uotes p7", 0xff3,
- {" \"three q\"\" \"uotes\" \"p four\" \"three q\"\" \"uotes\" \"p7\" \"\" \"\"",
- {"", "three q\"", "uotes", "p four", "three q\"", "uotes", "p7", "", "", NULL}, 0}},
+ {"Params23456789", "\"three q\"\"\"uotes \"p four\" \"three q\"\"\"uotes p7", TRUE,
+ " \"three q\"\" \"uotes\" \"p four\" \"three q\"\" \"uotes\" \"p7\" \"\" \"\""},
- {"Params23456789", "\"four \"\"\"\" quotes\" \"p three\" \"four \"\"\"\" quotes\" p5", 0xff3,
- {" \"four \"\" quotes\" \"p three\" \"four \"\" quotes\" \"p5\" \"\" \"\" \"\" \"\"",
- {"", "four \"", "quotes p", "three four", "", "quotes p5 \"", "", "", "", NULL}, 0}},
+ {"Params23456789", "\"four \"\"\"\" quotes\" \"p three\" \"four \"\"\"\" quotes\" p5", TRUE,
+ " \"four \"\" quotes\" \"p three\" \"four \"\" quotes\" \"p5\" \"\" \"\" \"\" \"\""},
/* The quoted string rules also apply to consecutive quotes at the start
* of a parameter but don't count the opening quote!
*/
- {"Params23456789", "\"\"twoquotes \"p four\" \"\"twoquotes p7", 0xbf3,
- {" \"\" \"twoquotes\" \"p four\" \"\" \"twoquotes\" \"p7\" \"\" \"\"",
- {"", "", "twoquotes", "p four", "", "twoquotes", "p7", "", "", NULL}, 0}},
+ {"Params23456789", "\"\"twoquotes \"p four\" \"\"twoquotes p7", TRUE,
+ " \"\" \"twoquotes\" \"p four\" \"\" \"twoquotes\" \"p7\" \"\" \"\""},
- {"Params23456789", "\"\"\"three quotes\" \"p three\" \"\"\"three quotes\" p5", 0x6f3,
- {" \"\"three quotes\" \"p three\" \"\"three quotes\" \"p5\" \"\" \"\" \"\" \"\"",
- {"", "three", "quotes p", "three \"three", "quotes p5 \"", "", "", "", NULL}, 0}},
+ {"Params23456789", "\"\"\"three quotes\" \"p three\" \"\"\"three quotes\" p5", TRUE,
+ " \"\"three quotes\" \"p three\" \"\"three quotes\" \"p5\" \"\" \"\" \"\" \"\""},
- {"Params23456789", "\"\"\"\"fourquotes \"p four\" \"\"\"\"fourquotes p7", 0xbf3,
- {" \"\"\" \"fourquotes\" \"p four\" \"\"\" \"fourquotes\" \"p7\" \"\" \"\"",
- {"", "\"", "fourquotes", "p four", "\"", "fourquotes", "p7", "", "", NULL}, 0}},
+ {"Params23456789", "\"\"\"\"fourquotes \"p four\" \"\"\"\"fourquotes p7", TRUE,
+ " \"\"\" \"fourquotes\" \"p four\" \"\"\" \"fourquotes\" \"p7\" \"\" \"\""},
/* An unclosed quoted string gets lost! */
- {"Params23456", "p2 \"p3\" \"p4 is lost", 0x1c3,
- {" \"p2\" \"p3\" \"\" \"\" \"\"",
- {"", "p2", "p3", "", "", "", NULL}, 0},
- {" \"p2\" \"p3\" \"p3\" \"\" \"\"",
- {"", "p2", "p3", "p3", "", "", NULL}, 0}},
+ {"Params23456", "p2 \"p3\" \"p4 is lost", TRUE,
+ " \"p2\" \"p3\" \"\" \"\" \"\"",
+ " \"p2\" \"p3\" \"p3\" \"\" \"\""}, /* NT4/2k */
/* Backslashes have no special meaning even when preceding quotes. All
* they do is start an unquoted string.
*/
- {"Params23456", "\\\"p\\three \"pfour\\\" pfive", 0x73,
- {" \"\\\" \"p\\three\" \"pfour\\\" \"pfive\" \"\"",
- {"", "\" p\\three pfour\"", "pfive", "", NULL}, 0}},
+ {"Params23456", "\\\"p\\three \"pfour\\\" pfive", TRUE,
+ " \"\\\" \"p\\three\" \"pfour\\\" \"pfive\" \"\""},
/* Environment variables are left untouched. */
- {"Params23456", "%TMPDIR% %t %c", 0,
- {" \"%TMPDIR%\" \"%t\" \"%c\" \"\" \"\"",
- {"", "%TMPDIR%", "%t", "%c", "", "", NULL}, 0}},
+ {"Params23456", "%TMPDIR% %t %c", FALSE,
+ " \"%TMPDIR%\" \"%t\" \"%c\" \"\" \"\""},
/* %~2 is equivalent to %*. However %~3 and higher include the spaces
* before the parameter!
* (but not the previous parameter's closing quote fortunately)
*/
- {"Params2345Etc", "p2 p3 \"p4\" p5 p6 ", 0x3f3,
- {" ~2=\"p2 p3 \"p4\" p5 p6 \" ~3=\" p3 \"p4\" p5 p6 \" ~4=\" \"p4\" p5 p6 \" ~5= p5 p6 ",
- {"", "~2=p2 p3 p4 p5 p6 ", "~3= p3 p4 p5 p6 ", "~4= p4 p5 p6 ", "~5=", "p5", "p6", NULL}, 0}},
+ {"Params2345Etc", "p2 p3 \"p4\" p5 p6 ", TRUE,
+ " ~2=\"p2 p3 \"p4\" p5 p6 \" ~3=\" p3 \"p4\" p5 p6 \" ~4=\" \"p4\" p5 p6 \" ~5= p5 p6 "},
/* %~n works even if there is no nth parameter. */
- {"Params9Etc", "p2 p3 p4 p5 p6 p7 p8 ", 0x12,
- {" ~9=\" \"",
- {"", "~9= ", NULL}, 0}},
+ {"Params9Etc", "p2 p3 p4 p5 p6 p7 p8 ", TRUE,
+ " ~9=\" \""},
- {"Params9Etc", "p2 p3 p4 p5 p6 p7 ", 0x12,
- {" ~9=\"\"",
- {"", "~9=", NULL}, 0}},
+ {"Params9Etc", "p2 p3 p4 p5 p6 p7 ", TRUE,
+ " ~9=\"\""},
/* The %~n directives also transmit the tenth parameter and beyond. */
- {"Params9Etc", "p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 and beyond!", 0x12,
- {" ~9=\" p9 p10 p11 and beyond!\"",
- {"", "~9= p9 p10 p11 and beyond!", NULL}, 0}},
+ {"Params9Etc", "p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 and beyond!", TRUE,
+ " ~9=\" p9 p10 p11 and beyond!\""},
/* Bad formatting directives lose their % sign, except those followed by
* a tilde! Environment variables are not expanded but lose their % sign.
*/
- {"ParamsBad", "p2 p3 p4 p5", 0x12,
- {" \"% - %~ %~0 %~1 %~a %~* a b c TMPDIR\"",
- {"", "% - %~ %~0 %~1 %~a %~* a b c TMPDIR", NULL}, 0}},
+ {"ParamsBad", "p2 p3 p4 p5", TRUE,
+ " \"% - %~ %~0 %~1 %~a %~* a b c TMPDIR\""},
- {NULL, NULL, 0, {NULL, {NULL}, 0}}
+ {0}
};
static void test_argify(void)
{
- BOOL has_cl2a = TRUE;
char fileA[MAX_PATH], params[2*MAX_PATH+12];
INT_PTR rc;
const argify_tests_t* test;
- const cmdline_tests_t *bad;
+ const char *bad;
const char* cmd;
- unsigned i, count;
/* Test with a long parameter */
for (rc = 0; rc < MAX_PATH; rc++)
test = argify_tests;
while (test->params)
{
- bad = test->broken.cmd ? &test->broken : &test->cmd;
+ bad = test->broken ? test->broken : test->cmd;
- /* trace("***** verb='%s' params='%s'\n", test->verb, test->params); */
rc = shell_execute_ex(SEE_MASK_DOENVSUBST, test->verb, fileA, test->params, NULL, NULL);
okShell(rc > 32, "failed: rc=%lu\n", rc);
- count = 0;
- while (test->cmd.args[count])
- count++;
- /* +4 for the shlexec arguments, -1 because of the added ""
- * argument for the CommandLineToArgvW() tests.
- */
- todo_wine_if(test->todo & 0x1)
- okChildInt("argcA", 4 + count - 1);
-
cmd = getChildString("Child", "cmdlineA");
/* Our commands are such that the verb immediately precedes the
* part we are interested in.
if (cmd) cmd = strstr(cmd, test->verb);
if (cmd) cmd += strlen(test->verb);
if (!cmd) cmd = "(null)";
- todo_wine_if(test->todo & 0x2)
- okShell(!strcmp(cmd, test->cmd.cmd) || broken(!strcmp(cmd, bad->cmd)),
- "the cmdline is '%s' instead of '%s'\n", cmd, test->cmd.cmd);
-
- for (i = 0; i < count - 1; i++)
- {
- char argname[18];
- sprintf(argname, "argvA%d", 4 + i);
- todo_wine_if(test->todo & (1 << (i+4)))
- okChildStringBroken(argname, test->cmd.args[i+1], bad->args[i+1]);
- }
-
- if (has_cl2a)
- has_cl2a = test_one_cmdline(&(test->cmd));
+ todo_wine_if(test->todo)
+ okShell(!strcmp(cmd, test->cmd) || broken(!strcmp(cmd, bad)),
+ "expected '%s', got '%s'\n", cmd, test->cmd);
test++;
}
}
return;
}
- get_long_path_name(tmpdir, longtmpdir, sizeof(longtmpdir)/sizeof(*longtmpdir));
+ get_long_path_name(tmpdir, longtmpdir, ARRAY_SIZE(longtmpdir));
SetEnvironmentVariableA("urlprefix", "file:///");
test=fileurl_tests;
/* Setup the test shortcuts */
sprintf(filename, "%s\\test_shortcut_shlexec.lnk", tmpdir);
- MultiByteToWideChar(CP_ACP, 0, filename, -1, lnkfile, sizeof(lnkfile)/sizeof(*lnkfile));
+ MultiByteToWideChar(CP_ACP, 0, filename, -1, lnkfile, ARRAY_SIZE(lnkfile));
desc.description=NULL;
desc.workdir=NULL;
sprintf(filename, "%s\\test file.shlexec", tmpdir);
create_lnk(lnkfile, &desc, 0);
sprintf(filename, "%s\\test_shortcut_exe.lnk", tmpdir);
- MultiByteToWideChar(CP_ACP, 0, filename, -1, lnkfile, sizeof(lnkfile)/sizeof(*lnkfile));
+ MultiByteToWideChar(CP_ACP, 0, filename, -1, lnkfile, ARRAY_SIZE(lnkfile));
desc.description=NULL;
desc.workdir=NULL;
desc.path=argv0;
/* "c:\®" can be used in all codepages */
/* Double-null termination needed for pFrom field of SHFILEOPSTRUCT */
-static HMODULE hshell32;
-static int (WINAPI *pSHCreateDirectoryExA)(HWND, LPCSTR, LPSECURITY_ATTRIBUTES);
-static int (WINAPI *pSHCreateDirectoryExW)(HWND, LPCWSTR, LPSECURITY_ATTRIBUTES);
-static int (WINAPI *pSHFileOperationW)(LPSHFILEOPSTRUCTW);
-static DWORD_PTR (WINAPI *pSHGetFileInfoW)(LPCWSTR, DWORD , SHFILEINFOW*, UINT, UINT);
-static int (WINAPI *pSHPathPrepareForWriteA)(HWND, IUnknown*, LPCSTR, DWORD);
-static int (WINAPI *pSHPathPrepareForWriteW)(HWND, IUnknown*, LPCWSTR, DWORD);
-
-static void InitFunctionPointers(void)
-{
- hshell32 = GetModuleHandleA("shell32.dll");
- pSHCreateDirectoryExA = (void*)GetProcAddress(hshell32, "SHCreateDirectoryExA");
- pSHCreateDirectoryExW = (void*)GetProcAddress(hshell32, "SHCreateDirectoryExW");
- pSHFileOperationW = (void*)GetProcAddress(hshell32, "SHFileOperationW");
- pSHGetFileInfoW = (void*)GetProcAddress(hshell32, "SHGetFileInfoW");
- pSHPathPrepareForWriteA = (void*)GetProcAddress(hshell32, "SHPathPrepareForWriteA");
- pSHPathPrepareForWriteW = (void*)GetProcAddress(hshell32, "SHPathPrepareForWriteW");
-}
-
/* creates a file with the specified name for tests */
static void createTestFile(const CHAR *name)
{
SHFILEINFOA shfi, shfi2;
SHFILEINFOW shfiw;
char notepad[MAX_PATH];
+ HANDLE unset_icon;
/* Test whether fields of SHFILEINFOA are always cleared */
memset(&shfi, 0xcf, sizeof(shfi));
broken(shfi.dwAttributes != 0xcfcfcfcf), /* NT4 doesn't clear but sets this field */
"SHGetFileInfoA('' | 0) should not clear dwAttributes\n");
- if (pSHGetFileInfoW)
- {
- HANDLE unset_icon;
- /* Test whether fields of SHFILEINFOW are always cleared */
- memset(&shfiw, 0xcf, sizeof(shfiw));
- memset(&unset_icon, 0xcf, sizeof(unset_icon));
- rc=pSHGetFileInfoW(NULL, 0, &shfiw, sizeof(shfiw), 0);
- ok(!rc, "SHGetFileInfoW(NULL | 0) should fail\n");
- ok(shfiw.hIcon == unset_icon, "SHGetFileInfoW(NULL | 0) should not clear hIcon\n");
- ok(shfiw.szDisplayName[0] == 0xcfcf, "SHGetFileInfoW(NULL | 0) should not clear szDisplayName[0]\n");
- ok(shfiw.szTypeName[0] == 0xcfcf, "SHGetFileInfoW(NULL | 0) should not clear szTypeName[0]\n");
- ok(shfiw.iIcon == 0xcfcfcfcf, "SHGetFileInfoW(NULL | 0) should not clear iIcon\n");
- ok(shfiw.dwAttributes == 0xcfcfcfcf, "SHGetFileInfoW(NULL | 0) should not clear dwAttributes\n");
- }
- else
- win_skip("SHGetFileInfoW is not available\n");
-
+ memset(&shfiw, 0xcf, sizeof(shfiw));
+ memset(&unset_icon, 0xcf, sizeof(unset_icon));
+ rc = SHGetFileInfoW(NULL, 0, &shfiw, sizeof(shfiw), 0);
+ ok(!rc, "SHGetFileInfoW(NULL | 0) should fail\n");
+ ok(shfiw.hIcon == unset_icon, "SHGetFileInfoW(NULL | 0) should not clear hIcon\n");
+ ok(shfiw.szDisplayName[0] == 0xcfcf, "SHGetFileInfoW(NULL | 0) should not clear szDisplayName[0]\n");
+ ok(shfiw.szTypeName[0] == 0xcfcf, "SHGetFileInfoW(NULL | 0) should not clear szTypeName[0]\n");
+ ok(shfiw.iIcon == 0xcfcfcfcf, "SHGetFileInfoW(NULL | 0) should not clear iIcon\n");
+ ok(shfiw.dwAttributes == 0xcfcfcfcf, "SHGetFileInfoW(NULL | 0) should not clear dwAttributes\n");
/* Test some flag combinations that MSDN claims are not allowed,
* but which work anyway
"SHGetFileInfoA(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL), unexpected dwAttributes\n");
/* Don't release hSysImageList here (and in similar places below) because of the broken reference behaviour of XP and 2003. */
- if (!pSHGetFileInfoW)
- {
- win_skip("SHGetFileInfoW is not available\n");
- ILFree(pidList);
- return;
- }
-
memset(&shInfow, 0xcf, sizeof(shInfow));
- hSysImageList = (HIMAGELIST) pSHGetFileInfoW((const WCHAR *)pidList, 0,
- &shInfow, sizeof(shInfow),
- SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_PIDL);
- if (!hSysImageList)
- {
- win_skip("SHGetFileInfoW is not implemented\n");
- return;
- }
+ hSysImageList = (HIMAGELIST) SHGetFileInfoW((const WCHAR *)pidList, 0,
+ &shInfow, sizeof(shInfow), SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_PIDL);
ok(hSysImageList == (HIMAGELIST)small_list, "got %p expect %p\n", hSysImageList, small_list);
todo_wine ok(shInfow.hIcon == 0, "SHGetFileInfoW(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) did not clear hIcon\n");
ok(shInfow.szTypeName[0] == 0, "SHGetFileInfoW(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) did not clear szTypeName[0]\n");
/* Various suposidly invalid flag testing */
memset(&shInfow, 0xcf, sizeof(shInfow));
- hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hSysImageList = (HIMAGELIST)SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON);
ok(hSysImageList == (HIMAGELIST)small_list, "got %p expect %p\n", hSysImageList, small_list);
ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
"unexpected dwAttributes\n");
memset(&shInfow, 0xcf, sizeof(shInfow));
- hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hr = SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_ICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON);
ok(hr != 0, " SHGFI_ICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON Failed\n");
ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
todo_wine ok(shInfow.dwAttributes==0,"dwAttributes not set\n");
memset(&shInfow, 0xcf, sizeof(shInfow));
- hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hr = SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_ICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_LARGEICON);
ok(hr != 0, "SHGFI_ICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_LARGEICON Failed\n");
ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
todo_wine ok(shInfow.dwAttributes==0,"dwAttributes not set\n");
memset(&shInfow, 0xcf, sizeof(shInfow));
- hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hSysImageList = (HIMAGELIST)SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_LARGEICON);
ok(hSysImageList == (HIMAGELIST)large_list, "got %p expect %p\n", hSysImageList, small_list);
ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
"unexpected dwAttributes\n");
memset(&shInfow, 0xcf, sizeof(shInfow));
- hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hr = SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_OPENICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON);
ok(hr != 0, "SHGFI_OPENICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON Failed\n");
todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
ok(shInfow.dwAttributes==0xcfcfcfcf,"dwAttributes modified\n");
memset(&shInfow, 0xcf, sizeof(shInfow));
- hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hr = SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_SHELLICONSIZE|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON);
ok(hr != 0, "SHGFI_SHELLICONSIZE|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON Failed\n");
todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
ok(shInfow.dwAttributes==0xcfcfcfcf,"dwAttributes modified\n");
memset(&shInfow, 0xcf, sizeof(shInfow));
- hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hr = SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_SHELLICONSIZE|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON);
ok(hr != 0, "SHGFI_SHELLICONSIZE|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON Failed\n");
todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
ok(shInfow.dwAttributes==0xcfcfcfcf,"dwAttributes modified\n");
memset(&shInfow, 0xcf, sizeof(shInfow));
- hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hSysImageList = (HIMAGELIST)SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|
SHGFI_ATTRIBUTES);
ok(hSysImageList == (HIMAGELIST)small_list, "got %p expect %p\n", hSysImageList, small_list);
ok(shInfow.dwAttributes!=0xcfcfcfcf,"dwAttributes not set\n");
memset(&shInfow, 0xcf, sizeof(shInfow));
- hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hSysImageList = (HIMAGELIST)SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|
SHGFI_EXETYPE);
todo_wine ok(hSysImageList == (HIMAGELIST)small_list, "got %p expect %p\n", hSysImageList, small_list);
"unexpected dwAttributes\n");
memset(&shInfow, 0xcf, sizeof(shInfow));
- hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hr = SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_EXETYPE);
todo_wine ok(hr != 0, "SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_EXETYPE Failed\n");
todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
ok(shInfow.dwAttributes==0xcfcfcfcf,"dwAttributes modified\n");
memset(&shInfow, 0xcf, sizeof(shInfow));
- hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hr = SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_ATTRIBUTES);
ok(hr != 0, "SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_ATTRIBUTES Failed\n");
todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
ok(shInfow.dwAttributes!=0xcfcfcfcf,"dwAttributes not set\n");
memset(&shInfow, 0xcf, sizeof(shInfow));
- hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hSysImageList = (HIMAGELIST)SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|
SHGFI_ATTRIBUTES);
ok(hSysImageList == (HIMAGELIST)large_list, "got %p expect %p\n", hSysImageList, large_list);
ok(shInfow.dwAttributes!=0xcfcfcfcf,"dwAttributes not set\n");
memset(&shInfow, 0xcf, sizeof(shInfow));
- hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hSysImageList = (HIMAGELIST)SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_EXETYPE);
todo_wine ok(hSysImageList == (HIMAGELIST)large_list, "got %p expect %p\n", hSysImageList, large_list);
ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
"unexpected dwAttributes\n");
memset(&shInfow, 0xcf, sizeof(shInfow));
- hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hr = SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_EXETYPE);
todo_wine ok(hr != 0, "SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_EXETYPE Failed\n");
todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
ok(shInfow.dwAttributes==0xcfcfcfcf,"dwAttributes modified\n");
memset(&shInfow, 0xcf, sizeof(shInfow));
- hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hr = SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_ATTRIBUTES);
ok(hr != 0, "SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_ATTRIBUTES Failed\n");
todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
ok(shInfow.dwAttributes!=0xcfcfcfcf,"dwAttributes not set\n");
memset(&shInfow, 0xcf, sizeof(shInfow));
- hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hSysImageList = (HIMAGELIST)SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_SYSICONINDEX|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_SHELLICONSIZE|SHGFI_ICON);
ok(hSysImageList == (HIMAGELIST)small_list, "got %p expect %p\n", hSysImageList, small_list);
ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
DestroyIcon( shInfow.hIcon );
memset(&shInfow, 0xcf, sizeof(shInfow));
- hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+ hSysImageList = (HIMAGELIST)SHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
SHGFI_SYSICONINDEX|SHGFI_PIDL|SHGFI_SHELLICONSIZE|SHGFI_ICON);
ok(hSysImageList == (HIMAGELIST)large_list, "got %p expect %p\n", hSysImageList, small_list);
ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
ok(retval != ERROR_SUCCESS, "Unexpected ERROR_SUCCESS\n");
ok(!shfo.fAnyOperationsAborted, "Didn't expect aborted operations\n");
ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
+
+ /* test with / */
+ CreateDirectoryA("dir", NULL);
+ CreateDirectoryA("dir\\subdir", NULL);
+ createTestFile("dir\\subdir\\aa.txt");
+ shfo.pFrom = "dir/subdir/aa.txt\0";
+ shfo.pTo = "dir\\destdir/aa.txt\0";
+ shfo.fFlags = FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_SILENT | FOF_NOERRORUI;
+ retval = SHFileOperationA(&shfo);
+ if (dir_exists("dir\\destdir"))
+ {
+ ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+ ok(DeleteFileA("dir\\destdir\\aa.txt"), "Expected file to exist\n");
+ ok(RemoveDirectoryA("dir\\destdir"), "Expected dir to exist\n");
+ }
+ else
+ {
+ expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* WinXp, Win2k */);
+ }
+ ok(DeleteFileA("dir\\subdir\\aa.txt"), "Expected file to exist\n");
+ ok(RemoveDirectoryA("dir\\subdir"), "Expected dir to exist\n");
+ ok(RemoveDirectoryA("dir"), "Expected dir to exist\n");
}
/* tests the FO_MOVE action */
clean_after_shfo_tests();
init_shfo_tests();
+ /* same tests above, but with / */
+ set_curr_dir_path(from, "testdir2/*.*\0");
+ set_curr_dir_path(to, "test4.txt\0");
+ retval = SHFileOperationA(&shfo);
+ ok(retval == ERROR_SUCCESS ||
+ broken(retval == ERROR_FILE_NOT_FOUND), /* WinXp, Win2k3 */
+ "Expected ERROR_SUCCESS, got %d\n", retval);
+ if (retval == ERROR_SUCCESS)
+ {
+ ok(!shfo.fAnyOperationsAborted, "fAnyOperationsAborted %d\n", shfo.fAnyOperationsAborted);
+
+ ok(dir_exists("testdir2"), "dir should not be moved\n");
+ ok(!file_exists("testdir2\\one.txt"), "file should be moved\n");
+ ok(!dir_exists("testdir2\\nested"), "dir should be moved\n");
+ ok(!file_exists("testdir2\\nested\\two.txt"), "file should be moved\n");
+
+ ok(file_exists("test4.txt\\one.txt"), "file should exist\n");
+ ok(dir_exists("test4.txt\\nested"), "dir should exist\n");
+ ok(file_exists("test4.txt\\nested\\two.txt"), "file should exist\n");
+ }
+
+ clean_after_shfo_tests();
+ init_shfo_tests();
+
shfo.hwnd = NULL;
shfo.wFunc = FO_MOVE;
shfo.pFrom = from;
CHAR path[MAX_PATH];
int ret;
- if(!pSHCreateDirectoryExA)
- {
- win_skip("skipping SHCreateDirectoryExA tests\n");
- return;
- }
-
set_curr_dir_path(path, "testdir2\\test4.txt\0");
- ret = pSHCreateDirectoryExA(NULL, path, NULL);
+ ret = SHCreateDirectoryExA(NULL, path, NULL);
ok(ERROR_SUCCESS == ret, "SHCreateDirectoryEx failed to create directory recursively, ret = %d\n", ret);
ok(file_exists("testdir2"), "The first directory is not created\n");
ok(file_exists("testdir2\\test4.txt"), "The second directory is not created\n");
- ret = pSHCreateDirectoryExA(NULL, path, NULL);
+ ret = SHCreateDirectoryExA(NULL, path, NULL);
ok(ERROR_ALREADY_EXISTS == ret, "SHCreateDirectoryEx should fail to create existing directory, ret = %d\n", ret);
- ret = pSHCreateDirectoryExA(NULL, "c:\\testdir3", NULL);
+ ret = SHCreateDirectoryExA(NULL, "c:\\testdir3", NULL);
ok(ERROR_SUCCESS == ret, "SHCreateDirectoryEx failed to create directory, ret = %d\n", ret);
ok(file_exists("c:\\testdir3"), "The directory is not created\n");
}
CHAR UNICODE_PATH_A[MAX_PATH];
BOOL UsedDefaultChar;
- if(!pSHPathPrepareForWriteA)
- {
- win_skip("skipping SHPathPrepareForWriteA tests\n");
- return;
- }
-
/* directory exists, SHPPFW_NONE */
set_curr_dir_path(path, "testdir2\0");
- res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
+ res = SHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
/* directory exists, SHPPFW_IGNOREFILENAME */
set_curr_dir_path(path, "testdir2\\test4.txt\0");
- res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME);
+ res = SHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME);
ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
/* directory exists, SHPPFW_DIRCREATE */
set_curr_dir_path(path, "testdir2\0");
- res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE);
+ res = SHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE);
ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
/* directory exists, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE */
set_curr_dir_path(path, "testdir2\\test4.txt\0");
- res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE);
+ res = SHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE);
ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
ok(!file_exists("nonexistent\\"), "nonexistent\\ exists but shouldn't\n");
/* file exists, SHPPFW_NONE */
set_curr_dir_path(path, "test1.txt\0");
- res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
+ res = SHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY) ||
res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* WinMe */
res == HRESULT_FROM_WIN32(ERROR_INVALID_NAME), /* Vista */
"Unexpected result : 0x%08x\n", res);
/* file exists, SHPPFW_DIRCREATE */
- res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE);
+ res = SHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE);
ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY) ||
res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* WinMe */
res == HRESULT_FROM_WIN32(ERROR_INVALID_NAME), /* Vista */
/* file exists, SHPPFW_NONE, trailing \ */
set_curr_dir_path(path, "test1.txt\\\0");
- res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
+ res = SHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY) ||
res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* WinMe */
res == HRESULT_FROM_WIN32(ERROR_INVALID_NAME), /* Vista */
"Unexpected result : 0x%08x\n", res);
/* relative path exists, SHPPFW_DIRCREATE */
- res = pSHPathPrepareForWriteA(0, 0, ".\\testdir2", SHPPFW_DIRCREATE);
+ res = SHPathPrepareForWriteA(0, 0, ".\\testdir2", SHPPFW_DIRCREATE);
ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
/* relative path doesn't exist, SHPPFW_DIRCREATE -- Windows does not create the directory in this case */
- res = pSHPathPrepareForWriteA(0, 0, ".\\testdir2\\test4.txt", SHPPFW_DIRCREATE);
+ res = SHPathPrepareForWriteA(0, 0, ".\\testdir2\\test4.txt", SHPPFW_DIRCREATE);
ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res);
ok(!file_exists(".\\testdir2\\test4.txt\\"), ".\\testdir2\\test4.txt\\ exists but shouldn't\n");
/* directory doesn't exist, SHPPFW_NONE */
set_curr_dir_path(path, "nonexistent\0");
- res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
+ res = SHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res);
/* directory doesn't exist, SHPPFW_IGNOREFILENAME */
set_curr_dir_path(path, "nonexistent\\notreal\0");
- res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME);
+ res = SHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME);
ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res);
ok(!file_exists("nonexistent\\notreal"), "nonexistent\\notreal exists but shouldn't\n");
ok(!file_exists("nonexistent\\"), "nonexistent\\ exists but shouldn't\n");
/* directory doesn't exist, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE */
set_curr_dir_path(path, "testdir2\\test4.txt\\\0");
- res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE);
+ res = SHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE);
ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
ok(file_exists("testdir2\\test4.txt\\"), "testdir2\\test4.txt doesn't exist but should\n");
/* nested directory doesn't exist, SHPPFW_DIRCREATE */
set_curr_dir_path(path, "nonexistent\\notreal\0");
- res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE);
+ res = SHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE);
ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
ok(file_exists("nonexistent\\notreal"), "nonexistent\\notreal doesn't exist but should\n");
/* SHPPFW_ASKDIRCREATE, SHPPFW_NOWRITECHECK, and SHPPFW_MEDIACHECKONLY are untested */
- if(!pSHPathPrepareForWriteW)
- {
- win_skip("Skipping SHPathPrepareForWriteW tests\n");
- return;
- }
-
SetLastError(0xdeadbeef);
UsedDefaultChar = FALSE;
if (WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, UNICODE_PATH, -1, UNICODE_PATH_A, sizeof(UNICODE_PATH_A), NULL, &UsedDefaultChar) == 0)
/* unicode directory doesn't exist, SHPPFW_NONE */
RemoveDirectoryA(UNICODE_PATH_A);
- res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_NONE);
+ res = SHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_NONE);
ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == %08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res);
ok(!file_exists(UNICODE_PATH_A), "unicode path was created but shouldn't be\n");
RemoveDirectoryA(UNICODE_PATH_A);
/* unicode directory doesn't exist, SHPPFW_DIRCREATE */
- res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_DIRCREATE);
+ res = SHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_DIRCREATE);
ok(res == S_OK, "res == %08x, expected S_OK\n", res);
ok(file_exists(UNICODE_PATH_A), "unicode path should've been created\n");
/* unicode directory exists, SHPPFW_NONE */
- res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_NONE);
+ res = SHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_NONE);
ok(res == S_OK, "ret == %08x, expected S_OK\n", res);
/* unicode directory exists, SHPPFW_DIRCREATE */
- res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_DIRCREATE);
+ res = SHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_DIRCREATE);
ok(res == S_OK, "ret == %08x, expected S_OK\n", res);
RemoveDirectoryA(UNICODE_PATH_A);
}
HANDLE file;
static const WCHAR UNICODE_PATH_TO[] = {'c',':','\\',0x00ae,0x00ae,'\0'};
- if (!pSHFileOperationW)
- {
- skip("SHFileOperationW() is missing\n");
- return;
- }
-
shfoW.hwnd = NULL;
shfoW.wFunc = FO_DELETE;
shfoW.pFrom = UNICODE_PATH;
/* Try to delete a file with unicode filename */
ok(file_existsW(UNICODE_PATH), "The file does not exist\n");
- ret = pSHFileOperationW(&shfoW);
+ ret = SHFileOperationW(&shfoW);
ok(!ret, "File is not removed, ErrorCode: %d\n", ret);
ok(!file_existsW(UNICODE_PATH), "The file should have been removed\n");
createTestFileW(UNICODE_PATH);
shfoW.fFlags |= FOF_ALLOWUNDO;
ok(file_existsW(UNICODE_PATH), "The file does not exist\n");
- ret = pSHFileOperationW(&shfoW);
+ ret = SHFileOperationW(&shfoW);
ok(!ret, "File is not removed, ErrorCode: %d\n", ret);
ok(!file_existsW(UNICODE_PATH), "The file should have been removed\n");
- if(!pSHCreateDirectoryExW)
- {
- skip("Skipping SHCreateDirectoryExW tests\n");
- return;
- }
-
/* Try to delete a directory with unicode filename */
- ret = pSHCreateDirectoryExW(NULL, UNICODE_PATH, NULL);
+ ret = SHCreateDirectoryExW(NULL, UNICODE_PATH, NULL);
ok(!ret, "SHCreateDirectoryExW returned %d\n", ret);
ok(file_existsW(UNICODE_PATH), "The directory is not created\n");
shfoW.fFlags &= ~FOF_ALLOWUNDO;
- ret = pSHFileOperationW(&shfoW);
+ ret = SHFileOperationW(&shfoW);
ok(!ret, "Directory is not removed, ErrorCode: %d\n", ret);
ok(!file_existsW(UNICODE_PATH), "The directory should have been removed\n");
/* Try to trash a directory with unicode filename */
- ret = pSHCreateDirectoryExW(NULL, UNICODE_PATH, NULL);
+ ret = SHCreateDirectoryExW(NULL, UNICODE_PATH, NULL);
ok(!ret, "SHCreateDirectoryExW returned %d\n", ret);
ok(file_existsW(UNICODE_PATH), "The directory was not created\n");
shfoW.fFlags |= FOF_ALLOWUNDO;
- ret = pSHFileOperationW(&shfoW);
+ ret = SHFileOperationW(&shfoW);
ok(!ret, "Directory is not removed, ErrorCode: %d\n", ret);
ok(!file_existsW(UNICODE_PATH), "The directory should have been removed\n");
START_TEST(shlfileop)
{
- InitFunctionPointers();
-
clean_after_shfo_tests();
init_shfo_tests();
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
static HRESULT (WINAPI *pSHCreateDefaultContextMenu)(const DEFCONTEXTMENU*,REFIID,void**);
static BOOL (WINAPI *pSHGetPathFromIDListEx)(PCIDLIST_ABSOLUTE,WCHAR*,DWORD,GPFIDL_FLAGS);
+#ifdef __REACTOS__
+typedef SHFOLDERCUSTOMSETTINGSW SHFOLDERCUSTOMSETTINGS, *LPSHFOLDERCUSTOMSETTINGS;
+#endif
+static HRESULT (WINAPI *pSHGetSetFolderCustomSettings)(LPSHFOLDERCUSTOMSETTINGS,PCWSTR,DWORD);
static WCHAR *make_wstr(const char *str)
{
MAKEFUNC(SHGetItemFromObject);
MAKEFUNC(SHCreateDefaultContextMenu);
MAKEFUNC(SHGetPathFromIDListEx);
+ MAKEFUNC(SHGetSetFolderCustomSettings);
#undef MAKEFUNC
/* test named exports */
return lpszPath;
}
+static struct
+{
+ WCHAR path[MAX_PATH];
+ HRESULT hr;
+ int todo;
+} parse_tests[] = {
+ {{'c',':','\\',0}, S_OK},
+ {{'c',':','\\','\\',0}, E_INVALIDARG, 1},
+ {{'c',':','\\','f','a','k','e',0}, 0x80070002}, /* ERROR_FILE_NOT_FOUND */
+ {{'c',':','f','a','k','e',0}, E_INVALIDARG, 1},
+ {{'c',':','/',0}, E_INVALIDARG, 1},
+ {{'c',':','\\','w','i','n','d','o','w','s',0}, S_OK},
+ {{'c',':','\\','w','i','n','d','o','w','s','\\',0}, S_OK},
+ {{'c',':','\\','w','i','n','d','o','w','s','\\','.',0}, E_INVALIDARG, 1},
+ {{'c',':','\\','w','i','n','d','o','w','s','\\','.','.',0}, E_INVALIDARG, 1},
+ {{'.',0}, E_INVALIDARG, 1},
+ {{'.','.',0}, E_INVALIDARG, 1},
+ {{'t','e','s','t',0}, 0x80070002},
+ {{'t','e','s','t','\\',0}, 0x80070002},
+ {{'s','u','b','\\','d','i','r',0}, 0x80070002},
+ {{'s','u','b','/','d','i','r',0}, E_INVALIDARG, 1},
+ {{'h','t','t','p',':',0}, S_OK, 1},
+ {{'h','t','t','p',':','t','e','s','t',0}, S_OK, 1},
+ {{'h','t','t','p',':','\\','t','e','s','t',0}, S_OK, 1},
+ {{'x','x',':',0}, S_OK, 1},
+};
+
static void test_ParseDisplayName(void)
{
+ static WCHAR testdirW[] = {'p','a','r','s','e','t','e','s','t',0};
+ static WCHAR backslashW[] = {'\\',0};
+ WCHAR buffer[MAX_PATH], buffer2[MAX_PATH];
+ IShellFolder *desktop;
+ ITEMIDLIST *pidl;
HRESULT hr;
- IShellFolder *IDesktopFolder;
- static const char *cNonExistDir1A = "c:\\nonexist_subdir";
- static const char *cNonExistDir2A = "c:\\\\nonexist_subdir";
- static const char *cInetTestA = "http:\\yyy";
- static const char *cInetTest2A = "xx:yyy";
- DWORD res;
- WCHAR cTestDirW [MAX_PATH] = {0};
- ITEMIDLIST *newPIDL;
BOOL bRes;
+ int i;
- hr = SHGetDesktopFolder(&IDesktopFolder);
+ hr = SHGetDesktopFolder(&desktop);
ok(hr == S_OK, "Expected SHGetDesktopFolder to return S_OK, got 0x%08x\n", hr);
- if(hr != S_OK) return;
-
- if (pSHCreateShellItem)
- {
- if (0)
- {
- /* null name and pidl, crashes on Windows 8 */
- hr = IShellFolder_ParseDisplayName(IDesktopFolder, NULL, NULL,
- NULL, NULL, NULL, 0);
- ok(hr == E_INVALIDARG, "returned %08x, expected E_INVALIDARG\n", hr);
- }
-
- /* null name */
- newPIDL = (ITEMIDLIST*)0xdeadbeef;
- hr = IShellFolder_ParseDisplayName(IDesktopFolder,
- NULL, NULL, NULL, NULL, &newPIDL, 0);
- ok(newPIDL == 0, "expected null, got %p\n", newPIDL);
- ok(hr == E_INVALIDARG, "returned %08x, expected E_INVALIDARG\n", hr);
- }
- else
- win_skip("SHCreateShellItem requires XP SP1 or later\n");
-
- MultiByteToWideChar(CP_ACP, 0, cInetTestA, -1, cTestDirW, MAX_PATH);
- hr = IShellFolder_ParseDisplayName(IDesktopFolder, NULL, NULL, cTestDirW, NULL, &newPIDL, 0);
- todo_wine ok(hr == S_OK, "ParseDisplayName returned %08x, expected SUCCESS\n", hr);
- if (hr == S_OK)
- {
- ok(ILFindLastID(newPIDL)->mkid.abID[0] == 0x61, "Last pidl should be of type "
- "PT_IESPECIAL1, but is: %02x\n", ILFindLastID(newPIDL)->mkid.abID[0]);
- IMalloc_Free(ppM, newPIDL);
- }
- MultiByteToWideChar(CP_ACP, 0, cInetTest2A, -1, cTestDirW, MAX_PATH);
- hr = IShellFolder_ParseDisplayName(IDesktopFolder,
- NULL, NULL, cTestDirW, NULL, &newPIDL, 0);
- todo_wine ok(hr == S_OK, "ParseDisplayName returned %08x, expected SUCCESS\n", hr);
- if (hr == S_OK)
- {
- ok(ILFindLastID(newPIDL)->mkid.abID[0] == 0x61, "Last pidl should be of type "
- "PT_IESPECIAL1, but is: %02x\n", ILFindLastID(newPIDL)->mkid.abID[0]);
- IMalloc_Free(ppM, newPIDL);
- }
+ hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, NULL, NULL, &pidl, NULL);
+ ok(hr == E_INVALIDARG, "got %#x\n", hr);
- res = GetFileAttributesA(cNonExistDir1A);
- if(res != INVALID_FILE_ATTRIBUTES)
+ for (i = 0; i < ARRAY_SIZE(parse_tests); i++)
{
- skip("Test directory unexpectedly exists\n");
- goto finished;
+ hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, parse_tests[i].path, NULL, &pidl, NULL);
+todo_wine_if(parse_tests[i].todo)
+ ok(hr == parse_tests[i].hr, "%s: expected %#x, got %#x\n",
+ wine_dbgstr_w(parse_tests[i].path), parse_tests[i].hr, hr);
+ if (SUCCEEDED(hr))
+ CoTaskMemFree(pidl);
}
- MultiByteToWideChar(CP_ACP, 0, cNonExistDir1A, -1, cTestDirW, MAX_PATH);
- hr = IShellFolder_ParseDisplayName(IDesktopFolder,
- NULL, NULL, cTestDirW, NULL, &newPIDL, 0);
- ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
- "ParseDisplayName returned %08x, expected 0x80070002\n", hr);
-
- res = GetFileAttributesA(cNonExistDir2A);
- if(res != INVALID_FILE_ATTRIBUTES)
- {
- skip("Test directory unexpectedly exists\n");
- goto finished;
- }
-
- MultiByteToWideChar(CP_ACP, 0, cNonExistDir2A, -1, cTestDirW, MAX_PATH);
- hr = IShellFolder_ParseDisplayName(IDesktopFolder,
- NULL, NULL, cTestDirW, NULL, &newPIDL, 0);
- todo_wine ok(hr == E_INVALIDARG, "ParseDisplayName returned %08x, expected E_INVALIDARG\n", hr);
-
/* I thought that perhaps the DesktopFolder's ParseDisplayName would recognize the
* path corresponding to CSIDL_PERSONAL and return a CLSID_MyDocuments PIDL. Turns
* out it doesn't. The magic seems to happen in the file dialogs, then. */
- bRes = SHGetSpecialFolderPathW(NULL, cTestDirW, CSIDL_PERSONAL, FALSE);
+ bRes = SHGetSpecialFolderPathW(NULL, buffer, CSIDL_PERSONAL, FALSE);
ok(bRes, "SHGetSpecialFolderPath(CSIDL_PERSONAL) failed! %u\n", GetLastError());
- if (!bRes) goto finished;
- hr = IShellFolder_ParseDisplayName(IDesktopFolder, NULL, NULL, cTestDirW, NULL, &newPIDL, 0);
+ hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, buffer, NULL, &pidl, 0);
ok(hr == S_OK, "DesktopFolder->ParseDisplayName failed. hr = %08x.\n", hr);
- if (hr != S_OK) goto finished;
- ok(ILFindLastID(newPIDL)->mkid.abID[0] == 0x31,
+ ok(ILFindLastID(pidl)->mkid.abID[0] == 0x31,
"Last pidl should be of type PT_FOLDER, but is: %02x\n",
- ILFindLastID(newPIDL)->mkid.abID[0]);
- IMalloc_Free(ppM, newPIDL);
+ ILFindLastID(pidl)->mkid.abID[0]);
+ CoTaskMemFree(pidl);
-finished:
- IShellFolder_Release(IDesktopFolder);
+ /* Relative paths are interpreted relative to the desktop. */
+ GetTempPathW(ARRAY_SIZE(buffer), buffer);
+ GetLongPathNameW(buffer, buffer, ARRAY_SIZE(buffer));
+ SetCurrentDirectoryW(buffer);
+ CreateDirectoryW(testdirW, NULL);
+
+ hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, testdirW, NULL, &pidl, NULL);
+ ok(hr == 0x80070002, "got %#x\n", hr);
+
+ RemoveDirectoryW(testdirW);
+
+ hr = SHGetSpecialFolderPathW(NULL, buffer, CSIDL_DESKTOP, FALSE);
+ ok(hr == S_FALSE, "got %#x\n", hr);
+ SetCurrentDirectoryW(buffer);
+ CreateDirectoryW(testdirW, NULL);
+
+ hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, testdirW, NULL, &pidl, NULL);
+ ok(hr == S_OK, "got %#x\n", hr);
+
+ ok(SHGetPathFromIDListW(pidl, buffer2), "SHGetPathFromIDList failed\n");
+ lstrcatW(buffer, backslashW);
+ lstrcatW(buffer, testdirW);
+ ok(!lstrcmpW(buffer, buffer2), "expected %s, got %s\n", wine_dbgstr_w(buffer), wine_dbgstr_w(buffer2));
+
+ RemoveDirectoryW(testdirW);
+ CoTaskMemFree(pidl);
+
+ IShellFolder_Release(desktop);
}
/* creates a file with the specified name for tests */
hr = IShellFolder_GetDisplayNameOf(testIShellFolder, newPIDL, SHGDN_INFOLDER, &strret);
ok(hr == S_OK, "GetDisplayNameOf failed %08x\n", hr);
- hr = StrRetToBufW(&strret, newPIDL, tempbufW, sizeof(tempbufW)/sizeof(WCHAR));
+ hr = StrRetToBufW(&strret, newPIDL, tempbufW, ARRAY_SIZE(tempbufW));
ok (hr == S_OK, "StrRetToBufW failed! hr = %08x\n", hr);
todo_wine
ok (!lstrcmpiW(tempbufW, folderdisplayW), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW));
hr = IShellFolder_GetDisplayNameOf(testIShellFolder, newPIDL, SHGDN_INFOLDER|SHGDN_FOREDITING, &strret);
ok(hr == S_OK, "GetDisplayNameOf failed %08x\n", hr);
- hr = StrRetToBufW(&strret, newPIDL, tempbufW, sizeof(tempbufW)/sizeof(WCHAR));
+ hr = StrRetToBufW(&strret, newPIDL, tempbufW, ARRAY_SIZE(tempbufW));
ok (hr == S_OK, "StrRetToBufW failed! hr = %08x\n", hr);
todo_wine
ok (!lstrcmpiW(tempbufW, folderdisplayW), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW));
hr = IShellFolder_GetDisplayNameOf(testIShellFolder, newPIDL, SHGDN_INFOLDER|SHGDN_FORPARSING, &strret);
ok(hr == S_OK, "GetDisplayNameOf failed %08x\n", hr);
- hr = StrRetToBufW(&strret, newPIDL, tempbufW, sizeof(tempbufW)/sizeof(WCHAR));
+ hr = StrRetToBufW(&strret, newPIDL, tempbufW, ARRAY_SIZE(tempbufW));
ok (hr == S_OK, "StrRetToBufW failed! hr = %08x\n", hr);
ok (!lstrcmpiW(tempbufW, foldernameW), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW));
SHCNE_ALLEVENTS, WM_USER_NOTIFY, 1, entries);
ok(notifyID != 0, "Failed to register a window for change notifications\n");
- for(i = 0; i < sizeof(chnotify_tests) / sizeof(*chnotify_tests); ++i){
+ for (i = 0; i < ARRAY_SIZE(chnotify_tests); ++i)
+ {
exp_data = chnotify_tests + i;
exp_data->missing_events = exp_data->notify_count;
CoInitialize(NULL);
- for (i = 0; i < sizeof(folders)/sizeof(folders[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(folders); i++)
{
IShellFolder2 *folder;
ULONG sort, display;
hr = IShellFolder2_GetDefaultColumn(folder, 0, &sort, NULL);
ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
ok(sort == 123, "Unexpected default column.\n");
+
+ IShellFolder2_Release(folder);
}
CoUninitialize();
CoInitialize(NULL);
- for (i = 0; i < sizeof(folders)/sizeof(folders[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(folders); i++)
{
IShellFolder2 *folder;
GUID guid;
CoUninitialize();
}
+static void test_SHLimitInputEdit(void)
+{
+ IShellFolder *desktop;
+ HRESULT hr;
+ HWND hwnd;
+
+ hr = SHGetDesktopFolder(&desktop);
+ ok(hr == S_OK, "Failed to get desktop folder, hr %#x.\n", hr);
+
+ hr = SHLimitInputEdit(NULL, desktop);
+todo_wine
+ ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
+
+ hwnd = CreateWindowA("EDIT", NULL, WS_VISIBLE, 0, 0, 100, 30, NULL, NULL, NULL, NULL);
+ ok(hwnd != NULL, "Failed to create Edit control.\n");
+
+ hr = SHLimitInputEdit(hwnd, desktop);
+todo_wine
+ ok(hr == S_OK, "Failed to set input limits, hr %#x.\n", hr);
+
+ hr = SHLimitInputEdit(hwnd, desktop);
+todo_wine
+ ok(hr == S_OK, "Failed to set input limits, hr %#x.\n", hr);
+
+ DestroyWindow(hwnd);
+ IShellFolder_Release(desktop);
+}
+
+static void test_SHGetSetFolderCustomSettings(void)
+{
+ HRESULT hr;
+ SHFOLDERCUSTOMSETTINGS fcs;
+ WCHAR pathW[MAX_PATH];
+ WCHAR bufferW[MAX_PATH];
+ WCHAR iconpathW[MAX_PATH];
+ static const WCHAR somedirW[] = {'s','o','m','e','_','d','i','r',0};
+ static const WCHAR iconW[] = {'\\','s','o','m','e','_','i','c','o','n','.','i','c','o',0};
+ static const WCHAR desktop_iniW[] = {'\\','D','e','s','k','t','o','p','.','i','n','i',0};
+
+ if (!pSHGetSetFolderCustomSettings)
+ {
+ win_skip("SHGetSetFolderCustomSetting not exported by name (only by ordinal) for version XP/win2003\n");
+ return;
+ }
+
+ GetTempPathW(MAX_PATH, pathW);
+ lstrcatW(pathW, somedirW);
+ CreateDirectoryW(pathW, NULL);
+
+ lstrcpyW(iconpathW, pathW);
+ lstrcatW(iconpathW, iconW);
+
+ memset(&fcs, 0, sizeof(fcs));
+ fcs.dwSize = sizeof(fcs);
+ fcs.dwMask = FCSM_ICONFILE;
+ fcs.pszIconFile = iconpathW;
+
+ hr = pSHGetSetFolderCustomSettings(&fcs, pathW, FCS_FORCEWRITE); /*creates and writes to a Desktop.ini*/
+ ok(hr == S_OK, "Expected S_OK, got %#x\n", hr);
+
+ memset(&fcs, 0, sizeof(fcs));
+ fcs.dwSize = sizeof(fcs);
+ fcs.dwMask = FCSM_ICONFILE;
+ fcs.cchIconFile = MAX_PATH;
+ fcs.pszIconFile = bufferW;
+ bufferW[0] = 0;
+
+ hr = pSHGetSetFolderCustomSettings(&fcs, pathW, FCS_READ);
+ todo_wine ok(hr == S_OK, "Expected S_OK, got %#x\n", hr);
+ todo_wine ok(!lstrcmpiW(iconpathW, fcs.pszIconFile), "Expected %s, got %s\n", wine_dbgstr_w(iconpathW), wine_dbgstr_w(fcs.pszIconFile));
+
+ hr = pSHGetSetFolderCustomSettings(&fcs, NULL, FCS_READ);
+ ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
+
+ lstrcpyW(bufferW, pathW);
+ lstrcatW(bufferW, desktop_iniW);
+ DeleteFileW(bufferW);
+ RemoveDirectoryW(pathW);
+}
+
START_TEST(shlfolder)
{
init_function_pointers();
test_DataObject();
test_GetDefaultColumn();
test_GetDefaultSearchGUID();
+ test_SHLimitInputEdit();
+ test_SHGetSetFolderCustomSettings();
OleUninitialize();
}
HRESULT hr;
hr = CoCreateInstance(&CLSID_NewMenu, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk);
-todo_wine
ok(hr == S_OK, "Failed to create NewMenu object, hr %#x.\n", hr);
if (hr != S_OK)
{
ok(hr == S_OK, "Failed to get IShellExtInit, hr %#x.\n", hr);
IUnknown_Release(unk2);
+ hr = IUnknown_QueryInterface(unk, &IID_IContextMenu, (void **)&unk2);
+ ok(hr == S_OK, "Failed to get IContextMenu, hr %#x.\n", hr);
+ IUnknown_Release(unk2);
+
+ hr = IUnknown_QueryInterface(unk, &IID_IContextMenu2, (void **)&unk2);
+ ok(hr == S_OK, "Failed to get IContextMenu2, hr %#x.\n", hr);
+ IUnknown_Release(unk2);
+
hr = IUnknown_QueryInterface(unk, &IID_IContextMenu3, (void **)&unk2);
ok(hr == S_OK, "Failed to get IContextMenu3, hr %#x.\n", hr);
IUnknown_Release(unk2);
strret.uType = STRRET_WSTR;
U(strret).pOleStr = CoDupStrW("Test");
memset(buff, 0xff, sizeof(buff));
- ret = pStrRetToStrNAW(buff, sizeof(buff)/sizeof(WCHAR), &strret, NULL);
+ ret = pStrRetToStrNAW(buff, ARRAY_SIZE(buff), &strret, NULL);
ok(ret == TRUE && !strcmpW(buff, szTestW),
"STRRET_WSTR: dup failed, ret=%d\n", ret);
strret.uType = STRRET_CSTR;
lstrcpyA(U(strret).cStr, "Test");
memset(buff, 0xff, sizeof(buff));
- ret = pStrRetToStrNAW(buff, sizeof(buff)/sizeof(WCHAR), &strret, NULL);
+ ret = pStrRetToStrNAW(buff, ARRAY_SIZE(buff), &strret, NULL);
ok(ret == TRUE && !strcmpW(buff, szTestW),
"STRRET_CSTR: dup failed, ret=%d\n", ret);
U(strret).uOffset = 1;
strcpy((char*)&iidl, " Test");
memset(buff, 0xff, sizeof(buff));
- ret = pStrRetToStrNAW(buff, sizeof(buff)/sizeof(WCHAR), &strret, iidl);
+ ret = pStrRetToStrNAW(buff, ARRAY_SIZE(buff), &strret, iidl);
ok(ret == TRUE && !strcmpW(buff, szTestW),
"STRRET_OFFSET: dup failed, ret=%d\n", ret);
/* Invalid dest - should return FALSE, except NT4 does not, so we don't check. */
strret.uType = STRRET_WSTR;
U(strret).pOleStr = CoDupStrW("Test");
- pStrRetToStrNAW(NULL, sizeof(buff)/sizeof(WCHAR), &strret, NULL);
+ pStrRetToStrNAW(NULL, ARRAY_SIZE(buff), &strret, NULL);
trace("NULL dest: ret=%d\n", ret);
}
}