shell32: Implement Application() property for Folder and FolderItems.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
1378e623ca
commit
a05d2b76b9
@ -63,12 +63,13 @@ typedef struct {
|
|||||||
Folder3 Folder3_iface;
|
Folder3 Folder3_iface;
|
||||||
LONG ref;
|
LONG ref;
|
||||||
VARIANT dir;
|
VARIANT dir;
|
||||||
|
IDispatch *application;
|
||||||
} FolderImpl;
|
} FolderImpl;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FolderItems3 FolderItems3_iface;
|
FolderItems3 FolderItems3_iface;
|
||||||
LONG ref;
|
LONG ref;
|
||||||
VARIANT dir;
|
FolderImpl *folder;
|
||||||
WCHAR **item_filenames;
|
WCHAR **item_filenames;
|
||||||
LONG item_count;
|
LONG item_count;
|
||||||
} FolderItemsImpl;
|
} FolderItemsImpl;
|
||||||
@ -998,7 +999,7 @@ static ULONG WINAPI FolderItemsImpl_Release(FolderItems3 *iface)
|
|||||||
|
|
||||||
if (!ref)
|
if (!ref)
|
||||||
{
|
{
|
||||||
VariantClear(&This->dir);
|
Folder3_Release(&This->folder->Folder3_iface);
|
||||||
for (i = 0; i < This->item_count; i++)
|
for (i = 0; i < This->item_count; i++)
|
||||||
HeapFree(GetProcessHeap(), 0, This->item_filenames[i]);
|
HeapFree(GetProcessHeap(), 0, This->item_filenames[i]);
|
||||||
HeapFree(GetProcessHeap(), 0, This->item_filenames);
|
HeapFree(GetProcessHeap(), 0, This->item_filenames);
|
||||||
@ -1065,19 +1066,17 @@ static HRESULT WINAPI FolderItemsImpl_get_Count(FolderItems3 *iface, LONG *count
|
|||||||
|
|
||||||
TRACE("(%p,%p)\n", iface, count);
|
TRACE("(%p,%p)\n", iface, count);
|
||||||
|
|
||||||
*count = PathIsDirectoryW(V_BSTR(&This->dir)) ? This->item_count : 0;
|
*count = PathIsDirectoryW(V_BSTR(&This->folder->dir)) ? This->item_count : 0;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI FolderItemsImpl_get_Application(FolderItems3 *iface, IDispatch **ppid)
|
static HRESULT WINAPI FolderItemsImpl_get_Application(FolderItems3 *iface, IDispatch **disp)
|
||||||
{
|
{
|
||||||
FIXME("(%p,%p)\n", iface, ppid);
|
FolderItemsImpl *This = impl_from_FolderItems(iface);
|
||||||
|
|
||||||
if (!ppid)
|
TRACE("(%p,%p)\n", iface, disp);
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
*ppid = NULL;
|
return Folder3_get_Application(&This->folder->Folder3_iface, disp);
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI FolderItemsImpl_get_Parent(FolderItems3 *iface, IDispatch **ppid)
|
static HRESULT WINAPI FolderItemsImpl_get_Parent(FolderItems3 *iface, IDispatch **ppid)
|
||||||
@ -1101,7 +1100,7 @@ static HRESULT WINAPI FolderItemsImpl_Item(FolderItems3 *iface, VARIANT index, F
|
|||||||
|
|
||||||
*ppid = NULL;
|
*ppid = NULL;
|
||||||
|
|
||||||
if (!PathIsDirectoryW(V_BSTR(&This->dir)))
|
if (!PathIsDirectoryW(V_BSTR(&This->folder->dir)))
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
switch (V_VT(&index))
|
switch (V_VT(&index))
|
||||||
@ -1114,7 +1113,7 @@ static HRESULT WINAPI FolderItemsImpl_Item(FolderItems3 *iface, VARIANT index, F
|
|||||||
if (V_I4(&index) >= This->item_count || V_I4(&index) < 0)
|
if (V_I4(&index) >= This->item_count || V_I4(&index) < 0)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
if (!PathCombineW(path_str, V_BSTR(&This->dir), This->item_filenames[V_I4(&index)]))
|
if (!PathCombineW(path_str, V_BSTR(&This->folder->dir), This->item_filenames[V_I4(&index)]))
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -1129,7 +1128,7 @@ static HRESULT WINAPI FolderItemsImpl_Item(FolderItems3 *iface, VARIANT index, F
|
|||||||
if (strcmpW(V_BSTR(&index), canonicalized_index) != 0)
|
if (strcmpW(V_BSTR(&index), canonicalized_index) != 0)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
if (!PathCombineW(path_str, V_BSTR(&This->dir), V_BSTR(&index)))
|
if (!PathCombineW(path_str, V_BSTR(&This->folder->dir), V_BSTR(&index)))
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
if (!PathFileExistsW(path_str))
|
if (!PathFileExistsW(path_str))
|
||||||
@ -1138,7 +1137,7 @@ static HRESULT WINAPI FolderItemsImpl_Item(FolderItems3 *iface, VARIANT index, F
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VT_ERROR:
|
case VT_ERROR:
|
||||||
return FolderItem_Constructor(&This->dir, ppid);
|
return FolderItem_Constructor(&This->folder->dir, ppid);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
@ -1205,7 +1204,7 @@ static const FolderItems3Vtbl FolderItemsImpl_Vtbl = {
|
|||||||
FolderItemsImpl_get_Verbs
|
FolderItemsImpl_get_Verbs
|
||||||
};
|
};
|
||||||
|
|
||||||
static HRESULT FolderItems_Constructor(VARIANT *dir, FolderItems **ppfi)
|
static HRESULT FolderItems_Constructor(FolderImpl *folder, FolderItems **ppfi)
|
||||||
{
|
{
|
||||||
static const WCHAR backslash_star[] = {'\\','*',0};
|
static const WCHAR backslash_star[] = {'\\','*',0};
|
||||||
static const WCHAR dot[] = {'.',0};
|
static const WCHAR dot[] = {'.',0};
|
||||||
@ -1216,13 +1215,12 @@ static HRESULT FolderItems_Constructor(VARIANT *dir, FolderItems **ppfi)
|
|||||||
HANDLE first_file;
|
HANDLE first_file;
|
||||||
WIN32_FIND_DATAW file_info;
|
WIN32_FIND_DATAW file_info;
|
||||||
WCHAR **filenames;
|
WCHAR **filenames;
|
||||||
HRESULT ret;
|
|
||||||
|
|
||||||
TRACE("(%s,%p)\n", debugstr_variant(dir), ppfi);
|
TRACE("(%s,%p)\n", debugstr_variant(&folder->dir), ppfi);
|
||||||
|
|
||||||
*ppfi = NULL;
|
*ppfi = NULL;
|
||||||
|
|
||||||
if (V_VT(dir) == VT_I4)
|
if (V_VT(&folder->dir) == VT_I4)
|
||||||
{
|
{
|
||||||
FIXME("special folder constants are not supported\n");
|
FIXME("special folder constants are not supported\n");
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
@ -1232,17 +1230,11 @@ static HRESULT FolderItems_Constructor(VARIANT *dir, FolderItems **ppfi)
|
|||||||
if (!This) return E_OUTOFMEMORY;
|
if (!This) return E_OUTOFMEMORY;
|
||||||
This->FolderItems3_iface.lpVtbl = &FolderItemsImpl_Vtbl;
|
This->FolderItems3_iface.lpVtbl = &FolderItemsImpl_Vtbl;
|
||||||
This->ref = 1;
|
This->ref = 1;
|
||||||
|
This->folder = folder;
|
||||||
VariantInit(&This->dir);
|
Folder3_AddRef(&folder->Folder3_iface);
|
||||||
ret = VariantCopy(&This->dir, dir);
|
|
||||||
if (FAILED(ret))
|
|
||||||
{
|
|
||||||
HeapFree(GetProcessHeap(), 0, This);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
This->item_count = 0;
|
This->item_count = 0;
|
||||||
lstrcpyW(glob, V_BSTR(dir));
|
lstrcpyW(glob, V_BSTR(&folder->dir));
|
||||||
lstrcatW(glob, backslash_star);
|
lstrcatW(glob, backslash_star);
|
||||||
first_file = FindFirstFileW(glob, &file_info);
|
first_file = FindFirstFileW(glob, &file_info);
|
||||||
if (first_file != INVALID_HANDLE_VALUE)
|
if (first_file != INVALID_HANDLE_VALUE)
|
||||||
@ -1335,6 +1327,7 @@ static ULONG WINAPI FolderImpl_Release(Folder3 *iface)
|
|||||||
|
|
||||||
if (!ref)
|
if (!ref)
|
||||||
{
|
{
|
||||||
|
IDispatch_Release(This->application);
|
||||||
VariantClear(&This->dir);
|
VariantClear(&This->dir);
|
||||||
HeapFree(GetProcessHeap(), 0, This);
|
HeapFree(GetProcessHeap(), 0, This);
|
||||||
}
|
}
|
||||||
@ -1416,13 +1409,19 @@ static HRESULT WINAPI FolderImpl_get_Title(Folder3 *iface, BSTR *pbs)
|
|||||||
return *pbs ? S_OK : E_OUTOFMEMORY;
|
return *pbs ? S_OK : E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI FolderImpl_get_Application(Folder3 *iface,
|
static HRESULT WINAPI FolderImpl_get_Application(Folder3 *iface, IDispatch **disp)
|
||||||
IDispatch **ppid)
|
|
||||||
{
|
{
|
||||||
FIXME("(%p,%p)\n", iface, ppid);
|
FolderImpl *This = impl_from_Folder(iface);
|
||||||
|
|
||||||
*ppid = NULL;
|
TRACE("(%p,%p)\n", iface, disp);
|
||||||
return E_NOTIMPL;
|
|
||||||
|
if (!disp)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
*disp = This->application;
|
||||||
|
IDispatch_AddRef(*disp);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI FolderImpl_get_Parent(Folder3 *iface, IDispatch **ppid)
|
static HRESULT WINAPI FolderImpl_get_Parent(Folder3 *iface, IDispatch **ppid)
|
||||||
@ -1447,7 +1446,7 @@ static HRESULT WINAPI FolderImpl_Items(Folder3 *iface, FolderItems **ppid)
|
|||||||
|
|
||||||
TRACE("(%p,%p)\n", iface, ppid);
|
TRACE("(%p,%p)\n", iface, ppid);
|
||||||
|
|
||||||
return FolderItems_Constructor(&This->dir, ppid);
|
return FolderItems_Constructor(This, ppid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI FolderImpl_ParseName(Folder3 *iface, BSTR name, FolderItem **item)
|
static HRESULT WINAPI FolderImpl_ParseName(Folder3 *iface, BSTR name, FolderItem **item)
|
||||||
@ -1624,6 +1623,7 @@ static HRESULT Folder_Constructor(VARIANT *dir, Folder **ppsdf)
|
|||||||
if (!This) return E_OUTOFMEMORY;
|
if (!This) return E_OUTOFMEMORY;
|
||||||
This->Folder3_iface.lpVtbl = &FolderImpl_Vtbl;
|
This->Folder3_iface.lpVtbl = &FolderImpl_Vtbl;
|
||||||
This->ref = 1;
|
This->ref = 1;
|
||||||
|
IShellDispatch_Constructor(NULL, &IID_IDispatch, (void **)&This->application);
|
||||||
|
|
||||||
VariantInit(&This->dir);
|
VariantInit(&This->dir);
|
||||||
ret = VariantCopy(&This->dir, dir);
|
ret = VariantCopy(&This->dir, dir);
|
||||||
|
@ -33,6 +33,15 @@
|
|||||||
#define EXPECT_HR(hr,hr_exp) \
|
#define EXPECT_HR(hr,hr_exp) \
|
||||||
ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
|
ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
|
||||||
|
|
||||||
|
#define EXPECT_REF(obj,ref) _expect_ref((IUnknown *)obj, ref, __LINE__)
|
||||||
|
static void _expect_ref(IUnknown *obj, ULONG ref, int line)
|
||||||
|
{
|
||||||
|
ULONG rc;
|
||||||
|
IUnknown_AddRef(obj);
|
||||||
|
rc = IUnknown_Release(obj);
|
||||||
|
ok_(__FILE__,line)(rc == ref, "Unexpected refcount %d, expected %d\n", rc, ref);
|
||||||
|
}
|
||||||
|
|
||||||
static const WCHAR winetestW[] = {'w','i','n','e','t','e','s','t',0};
|
static const WCHAR winetestW[] = {'w','i','n','e','t','e','s','t',0};
|
||||||
|
|
||||||
static HRESULT (WINAPI *pSHGetFolderPathW)(HWND, int, HANDLE, DWORD, LPWSTR);
|
static HRESULT (WINAPI *pSHGetFolderPathW)(HWND, int, HANDLE, DWORD, LPWSTR);
|
||||||
@ -401,15 +410,15 @@ static void test_items(void)
|
|||||||
HRESULT r;
|
HRESULT r;
|
||||||
IShellDispatch *sd = NULL;
|
IShellDispatch *sd = NULL;
|
||||||
Folder *folder = NULL;
|
Folder *folder = NULL;
|
||||||
FolderItems *items = NULL;
|
FolderItems *items;
|
||||||
FolderItems2 *items2 = NULL;
|
FolderItems2 *items2 = NULL;
|
||||||
FolderItems3 *items3 = NULL;
|
FolderItems3 *items3 = NULL;
|
||||||
FolderItem *item = (FolderItem*)0xdeadbeef, *item2;
|
FolderItem *item = (FolderItem*)0xdeadbeef, *item2;
|
||||||
IDispatch *disp = NULL;
|
|
||||||
IUnknown *unk = NULL;
|
|
||||||
FolderItemVerbs *verbs = (FolderItemVerbs*)0xdeadbeef;
|
FolderItemVerbs *verbs = (FolderItemVerbs*)0xdeadbeef;
|
||||||
VARIANT var, int_index, str_index, str_index2;
|
VARIANT var, int_index, str_index, str_index2;
|
||||||
|
IDispatch *disp, *disp2;
|
||||||
LONG count = -1;
|
LONG count = -1;
|
||||||
|
IUnknown *unk;
|
||||||
HANDLE file;
|
HANDLE file;
|
||||||
BSTR bstr;
|
BSTR bstr;
|
||||||
char cstr[64];
|
char cstr[64];
|
||||||
@ -427,18 +436,56 @@ static void test_items(void)
|
|||||||
GetFullPathNameW(winetestW, MAX_PATH, path, NULL);
|
GetFullPathNameW(winetestW, MAX_PATH, path, NULL);
|
||||||
V_VT(&var) = VT_BSTR;
|
V_VT(&var) = VT_BSTR;
|
||||||
V_BSTR(&var) = SysAllocString(path);
|
V_BSTR(&var) = SysAllocString(path);
|
||||||
|
|
||||||
|
EXPECT_REF(sd, 1);
|
||||||
r = IShellDispatch_NameSpace(sd, var, &folder);
|
r = IShellDispatch_NameSpace(sd, var, &folder);
|
||||||
ok(r == S_OK, "IShellDispatch::NameSpace failed: %08x\n", r);
|
ok(r == S_OK, "IShellDispatch::NameSpace failed: %08x\n", r);
|
||||||
ok(!!folder, "folder is null\n");
|
ok(!!folder, "folder is null\n");
|
||||||
|
EXPECT_REF(folder, 1);
|
||||||
|
EXPECT_REF(sd, 1);
|
||||||
|
|
||||||
VariantClear(&var);
|
VariantClear(&var);
|
||||||
IShellDispatch_Release(sd);
|
|
||||||
SetCurrentDirectoryW(winetestW);
|
SetCurrentDirectoryW(winetestW);
|
||||||
GetCurrentDirectoryW(MAX_PATH, path);
|
GetCurrentDirectoryW(MAX_PATH, path);
|
||||||
GetLongPathNameW(path, cur_dir, MAX_PATH);
|
GetLongPathNameW(path, cur_dir, MAX_PATH);
|
||||||
|
|
||||||
|
/* FolderItems grabs its Folder reference */
|
||||||
|
items = NULL;
|
||||||
r = Folder_Items(folder, &items);
|
r = Folder_Items(folder, &items);
|
||||||
ok(r == S_OK, "Folder::Items failed: %08x\n", r);
|
ok(r == S_OK, "Folder::Items failed: %08x\n", r);
|
||||||
ok(!!items, "items is null\n");
|
ok(!!items, "items is null\n");
|
||||||
|
EXPECT_REF(folder, 2);
|
||||||
|
EXPECT_REF(items, 1);
|
||||||
|
|
||||||
|
unk = NULL;
|
||||||
|
r = Folder_Items(folder, (FolderItems **)&unk);
|
||||||
|
ok(r == S_OK, "Folder::Items failed: %08x\n", r);
|
||||||
|
EXPECT_REF(folder, 3);
|
||||||
|
IUnknown_Release(unk);
|
||||||
|
EXPECT_REF(folder, 2);
|
||||||
|
|
||||||
|
FolderItems_AddRef(items);
|
||||||
|
EXPECT_REF(folder, 2);
|
||||||
|
FolderItems_Release(items);
|
||||||
|
|
||||||
|
/* Application property */
|
||||||
|
disp = NULL;
|
||||||
|
EXPECT_REF(sd, 1);
|
||||||
|
r = Folder_get_Application(folder, &disp);
|
||||||
|
ok(r == S_OK, "Failed to get application %#x.\n", r);
|
||||||
|
ok(disp != (IDispatch *)sd, "Unexpected application pointer\n");
|
||||||
|
EXPECT_REF(sd, 1);
|
||||||
|
|
||||||
|
disp2 = NULL;
|
||||||
|
r = Folder_get_Application(folder, &disp2);
|
||||||
|
ok(r == S_OK, "Failed to get application %#x.\n", r);
|
||||||
|
ok(disp2 == disp, "Unexpected application pointer\n");
|
||||||
|
IDispatch_Release(disp2);
|
||||||
|
|
||||||
|
r = IDispatch_QueryInterface(disp, &IID_IShellDispatch, (void **)&disp2);
|
||||||
|
ok(r == S_OK, "Wrong instance, hr %#x.\n", r);
|
||||||
|
IDispatch_Release(disp2);
|
||||||
|
IDispatch_Release(disp);
|
||||||
|
|
||||||
if (0) /* crashes on all versions of Windows */
|
if (0) /* crashes on all versions of Windows */
|
||||||
r = FolderItems_get_Count(items, NULL);
|
r = FolderItems_get_Count(items, NULL);
|
||||||
@ -506,7 +553,6 @@ static void test_items(void)
|
|||||||
r = FolderItems_QueryInterface(items, &IID_FolderItems3, (void**)&items3);
|
r = FolderItems_QueryInterface(items, &IID_FolderItems3, (void**)&items3);
|
||||||
ok(r == S_OK, "FolderItems::QueryInterface failed: %08x\n", r);
|
ok(r == S_OK, "FolderItems::QueryInterface failed: %08x\n", r);
|
||||||
ok(!!items3, "items3 is null\n");
|
ok(!!items3, "items3 is null\n");
|
||||||
Folder_Release(folder);
|
|
||||||
|
|
||||||
count = -1;
|
count = -1;
|
||||||
r = FolderItems_get_Count(items, &count);
|
r = FolderItems_get_Count(items, &count);
|
||||||
@ -674,11 +720,13 @@ static void test_items(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
r = FolderItems_get_Application(items, &disp);
|
r = FolderItems_get_Application(items, &disp);
|
||||||
todo_wine
|
|
||||||
ok(r == S_OK, "FolderItems::get_Application failed: %08x\n", r);
|
ok(r == S_OK, "FolderItems::get_Application failed: %08x\n", r);
|
||||||
todo_wine
|
|
||||||
ok(!!disp, "disp is null\n");
|
r = Folder_get_Application(folder, &disp2);
|
||||||
if (disp) IDispatch_Release(disp);
|
ok(r == S_OK, "Failed to get application pointer, hr %#x.\n", r);
|
||||||
|
ok(disp == disp2, "Unexpected application pointer.\n");
|
||||||
|
IDispatch_Release(disp2);
|
||||||
|
IDispatch_Release(disp);
|
||||||
|
|
||||||
if (0) /* crashes on xp */
|
if (0) /* crashes on xp */
|
||||||
{
|
{
|
||||||
@ -749,8 +797,10 @@ todo_wine
|
|||||||
VariantClear(&str_index);
|
VariantClear(&str_index);
|
||||||
|
|
||||||
FolderItems_Release(items);
|
FolderItems_Release(items);
|
||||||
|
Folder_Release(folder);
|
||||||
if (items2) FolderItems2_Release(items2);
|
if (items2) FolderItems2_Release(items2);
|
||||||
if (items3) FolderItems3_Release(items3);
|
if (items3) FolderItems3_Release(items3);
|
||||||
|
IShellDispatch_Release(sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_service(void)
|
static void test_service(void)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user