shell32: Implement Title property using shellfolder API.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
3a42c84e0f
commit
ec42839cd6
|
@ -35,6 +35,7 @@
|
||||||
#include "debughlp.h"
|
#include "debughlp.h"
|
||||||
|
|
||||||
#include "shell32_main.h"
|
#include "shell32_main.h"
|
||||||
|
#include "pidl.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
@ -64,6 +65,8 @@ typedef struct {
|
||||||
LONG ref;
|
LONG ref;
|
||||||
VARIANT dir;
|
VARIANT dir;
|
||||||
IDispatch *application;
|
IDispatch *application;
|
||||||
|
IShellFolder2 *folder;
|
||||||
|
PIDLIST_ABSOLUTE pidl;
|
||||||
} FolderImpl;
|
} FolderImpl;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -1350,6 +1353,8 @@ static ULONG WINAPI FolderImpl_Release(Folder3 *iface)
|
||||||
|
|
||||||
if (!ref)
|
if (!ref)
|
||||||
{
|
{
|
||||||
|
ILFree(This->pidl);
|
||||||
|
IShellFolder2_Release(This->folder);
|
||||||
IDispatch_Release(This->application);
|
IDispatch_Release(This->application);
|
||||||
VariantClear(&This->dir);
|
VariantClear(&This->dir);
|
||||||
HeapFree(GetProcessHeap(), 0, This);
|
HeapFree(GetProcessHeap(), 0, This);
|
||||||
|
@ -1411,25 +1416,31 @@ static HRESULT WINAPI FolderImpl_Invoke(Folder3 *iface, DISPID dispIdMember,
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI FolderImpl_get_Title(Folder3 *iface, BSTR *pbs)
|
static HRESULT WINAPI FolderImpl_get_Title(Folder3 *iface, BSTR *title)
|
||||||
{
|
{
|
||||||
FolderImpl *This = impl_from_Folder(iface);
|
FolderImpl *This = impl_from_Folder(iface);
|
||||||
WCHAR *p;
|
PCUITEMID_CHILD last_part;
|
||||||
int len;
|
IShellFolder2 *parent;
|
||||||
|
WCHAR buffW[MAX_PATH];
|
||||||
|
SHELLDETAILS sd;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
TRACE("(%p,%p)\n", iface, pbs);
|
TRACE("(%p,%p)\n", iface, title);
|
||||||
|
|
||||||
*pbs = NULL;
|
*title = NULL;
|
||||||
|
|
||||||
if (V_VT(&This->dir) == VT_I4)
|
if (FAILED(hr = SHBindToParent(This->pidl, &IID_IShellFolder2, (void **)&parent, &last_part)))
|
||||||
{
|
return hr;
|
||||||
FIXME("special folder constants are not supported\n");
|
|
||||||
return E_NOTIMPL;
|
hr = IShellFolder2_GetDetailsOf(parent, last_part, 0, &sd);
|
||||||
}
|
IShellFolder2_Release(parent);
|
||||||
p = PathFindFileNameW(V_BSTR(&This->dir));
|
if (FAILED(hr))
|
||||||
len = lstrlenW(p);
|
return hr;
|
||||||
*pbs = SysAllocStringLen(p, p[len - 1] == '\\' ? len - 1 : len);
|
|
||||||
return *pbs ? S_OK : E_OUTOFMEMORY;
|
StrRetToBufW(&sd.str, NULL, buffW, sizeof(buffW)/sizeof(buffW[0]));
|
||||||
|
*title = SysAllocString(buffW);
|
||||||
|
|
||||||
|
return *title ? S_OK : E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI FolderImpl_get_Application(Folder3 *iface, IDispatch **disp)
|
static HRESULT WINAPI FolderImpl_get_Application(Folder3 *iface, IDispatch **disp)
|
||||||
|
@ -1623,43 +1634,33 @@ static const Folder3Vtbl FolderImpl_Vtbl = {
|
||||||
FolderImpl_put_ShowWebViewBarricade
|
FolderImpl_put_ShowWebViewBarricade
|
||||||
};
|
};
|
||||||
|
|
||||||
static HRESULT Folder_Constructor(VARIANT *dir, Folder **ppsdf)
|
static HRESULT Folder_Constructor(VARIANT *dir, IShellFolder2 *folder, LPITEMIDLIST pidl, Folder **ret)
|
||||||
{
|
{
|
||||||
FolderImpl *This;
|
FolderImpl *This;
|
||||||
HRESULT ret;
|
HRESULT hr;
|
||||||
|
|
||||||
*ppsdf = NULL;
|
*ret = NULL;
|
||||||
|
|
||||||
switch (V_VT(dir))
|
This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
|
||||||
{
|
if (!This)
|
||||||
case VT_I4:
|
return E_OUTOFMEMORY;
|
||||||
/* FIXME: add some checks */
|
|
||||||
break;
|
|
||||||
case VT_BSTR:
|
|
||||||
if (PathIsDirectoryW(V_BSTR(dir)) &&
|
|
||||||
!PathIsRelativeW(V_BSTR(dir)) &&
|
|
||||||
PathFileExistsW(V_BSTR(dir)))
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
This = HeapAlloc(GetProcessHeap(), 0, sizeof(FolderImpl));
|
|
||||||
if (!This) return E_OUTOFMEMORY;
|
|
||||||
This->Folder3_iface.lpVtbl = &FolderImpl_Vtbl;
|
This->Folder3_iface.lpVtbl = &FolderImpl_Vtbl;
|
||||||
This->ref = 1;
|
This->ref = 1;
|
||||||
|
This->folder = folder;
|
||||||
|
This->pidl = pidl;
|
||||||
IShellDispatch_Constructor(NULL, &IID_IDispatch, (void **)&This->application);
|
IShellDispatch_Constructor(NULL, &IID_IDispatch, (void **)&This->application);
|
||||||
|
|
||||||
VariantInit(&This->dir);
|
VariantInit(&This->dir);
|
||||||
ret = VariantCopy(&This->dir, dir);
|
hr = VariantCopy(&This->dir, dir);
|
||||||
if (FAILED(ret))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
HeapFree(GetProcessHeap(), 0, This);
|
HeapFree(GetProcessHeap(), 0, This);
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
*ppsdf = (Folder*)&This->Folder3_iface;
|
*ret = (Folder *)&This->Folder3_iface;
|
||||||
return ret;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI ShellDispatch_QueryInterface(IShellDispatch6 *iface,
|
static HRESULT WINAPI ShellDispatch_QueryInterface(IShellDispatch6 *iface,
|
||||||
|
@ -1796,11 +1797,53 @@ static HRESULT WINAPI ShellDispatch_get_Parent(IShellDispatch6 *iface, IDispatch
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI ShellDispatch_NameSpace(IShellDispatch6 *iface,
|
static HRESULT WINAPI ShellDispatch_NameSpace(IShellDispatch6 *iface,
|
||||||
VARIANT vDir, Folder **ppsdf)
|
VARIANT dir, Folder **ret)
|
||||||
{
|
{
|
||||||
TRACE("(%p,%p)\n", iface, ppsdf);
|
IShellFolder2 *folder;
|
||||||
|
IShellFolder *desktop;
|
||||||
|
LPITEMIDLIST pidl;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
return Folder_Constructor(&vDir, ppsdf);
|
TRACE("(%p,%s,%p)\n", iface, debugstr_variant(&dir), ret);
|
||||||
|
|
||||||
|
*ret = NULL;
|
||||||
|
|
||||||
|
switch (V_VT(&dir))
|
||||||
|
{
|
||||||
|
case VT_I2:
|
||||||
|
if (FAILED(hr = VariantChangeType(&dir, &dir, 0, VT_I4)))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
/* fallthrough */
|
||||||
|
case VT_I4:
|
||||||
|
if (FAILED(hr = SHGetFolderLocation(NULL, V_I4(&dir), NULL, 0, &pidl)))
|
||||||
|
return S_FALSE;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case VT_BSTR:
|
||||||
|
if (FAILED(hr = SHParseDisplayName(V_BSTR(&dir), NULL, &pidl, 0, NULL)))
|
||||||
|
return S_FALSE;
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARN("Ignoring directory value %s\n", debugstr_variant(&dir));
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr = SHGetDesktopFolder(&desktop)))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
if (_ILIsDesktop(pidl))
|
||||||
|
hr = IShellFolder_QueryInterface(desktop, &IID_IShellFolder2, (void **)&folder);
|
||||||
|
else
|
||||||
|
hr = IShellFolder_BindToObject(desktop, pidl, NULL, &IID_IShellFolder2, (void **)&folder);
|
||||||
|
|
||||||
|
IShellFolder_Release(desktop);
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
return S_FALSE;
|
||||||
|
|
||||||
|
return Folder_Constructor(&dir, folder, pidl, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI ShellDispatch_BrowseForFolder(IShellDispatch6 *iface,
|
static HRESULT WINAPI ShellDispatch_BrowseForFolder(IShellDispatch6 *iface,
|
||||||
|
|
|
@ -156,6 +156,7 @@ static void test_namespace(void)
|
||||||
folder = (void*)0xdeadbeef;
|
folder = (void*)0xdeadbeef;
|
||||||
r = IShellDispatch_NameSpace(sd, var, &folder);
|
r = IShellDispatch_NameSpace(sd, var, &folder);
|
||||||
if (special_folders[i] == ssfALTSTARTUP || special_folders[i] == ssfCOMMONALTSTARTUP)
|
if (special_folders[i] == ssfALTSTARTUP || special_folders[i] == ssfCOMMONALTSTARTUP)
|
||||||
|
todo_wine
|
||||||
ok(r == S_OK || broken(r == S_FALSE) /* winxp */, "Failed to get folder for index %#x, got %08x\n", special_folders[i], r);
|
ok(r == S_OK || broken(r == S_FALSE) /* winxp */, "Failed to get folder for index %#x, got %08x\n", special_folders[i], r);
|
||||||
else
|
else
|
||||||
ok(r == S_OK, "Failed to get folder for index %#x, got %08x\n", special_folders[i], r);
|
ok(r == S_OK, "Failed to get folder for index %#x, got %08x\n", special_folders[i], r);
|
||||||
|
@ -165,14 +166,11 @@ static void test_namespace(void)
|
||||||
|
|
||||||
V_VT(&var) = VT_I4;
|
V_VT(&var) = VT_I4;
|
||||||
V_I4(&var) = -1;
|
V_I4(&var) = -1;
|
||||||
folder = (void*)0xdeadbeef;
|
folder = (void *)0xdeadbeef;
|
||||||
r = IShellDispatch_NameSpace(sd, var, &folder);
|
r = IShellDispatch_NameSpace(sd, var, &folder);
|
||||||
todo_wine {
|
ok(r == S_FALSE, "Unexpected hr %#x.\n", r);
|
||||||
ok(r == S_FALSE, "expected S_FALSE, got %08x\n", r);
|
ok(folder == NULL, "Unexpected folder instance %p\n", folder);
|
||||||
ok(folder == NULL, "got %p\n", folder);
|
|
||||||
if (r == S_OK)
|
|
||||||
Folder_Release(folder);
|
|
||||||
}
|
|
||||||
V_VT(&var) = VT_I4;
|
V_VT(&var) = VT_I4;
|
||||||
V_I4(&var) = ssfPROGRAMFILES;
|
V_I4(&var) = ssfPROGRAMFILES;
|
||||||
r = IShellDispatch_NameSpace(sd, var, &folder);
|
r = IShellDispatch_NameSpace(sd, var, &folder);
|
||||||
|
@ -185,7 +183,6 @@ static void test_namespace(void)
|
||||||
ok(r == S_OK, "Failed to get folder path: %#x.\n", r);
|
ok(r == S_OK, "Failed to get folder path: %#x.\n", r);
|
||||||
|
|
||||||
r = Folder_get_Title(folder, &title);
|
r = Folder_get_Title(folder, &title);
|
||||||
todo_wine
|
|
||||||
ok(r == S_OK, "Folder::get_Title failed: %08x\n", r);
|
ok(r == S_OK, "Folder::get_Title failed: %08x\n", r);
|
||||||
if (r == S_OK)
|
if (r == S_OK)
|
||||||
{
|
{
|
||||||
|
@ -202,9 +199,7 @@ static void test_namespace(void)
|
||||||
ok(r == S_OK, "SHGetSpecialFolderLocation failed: %08x\n", r);
|
ok(r == S_OK, "SHGetSpecialFolderLocation failed: %08x\n", r);
|
||||||
r = pSHGetNameFromIDList(pidl, SIGDN_NORMALDISPLAY, &name);
|
r = pSHGetNameFromIDList(pidl, SIGDN_NORMALDISPLAY, &name);
|
||||||
ok(r == S_OK, "SHGetNameFromIDList failed: %08x\n", r);
|
ok(r == S_OK, "SHGetNameFromIDList failed: %08x\n", r);
|
||||||
todo_wine
|
ok(!lstrcmpW(title, name), "expected %s, got %s\n", wine_dbgstr_w(name), wine_dbgstr_w(title));
|
||||||
ok(!lstrcmpW(title, name), "expected %s, got %s\n",
|
|
||||||
wine_dbgstr_w(name), wine_dbgstr_w(title));
|
|
||||||
CoTaskMemFree(name);
|
CoTaskMemFree(name);
|
||||||
CoTaskMemFree(pidl);
|
CoTaskMemFree(pidl);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue