diff --git a/dlls/shell32/shfldr_desktop.c b/dlls/shell32/shfldr_desktop.c index d6ccb724396..e744fd3e710 100644 --- a/dlls/shell32/shfldr_desktop.c +++ b/dlls/shell32/shfldr_desktop.c @@ -65,6 +65,7 @@ extern HRESULT WINAPI IEParseDisplayNameWithBCW(DWORD codepage, LPCWSTR lpszDisp typedef struct { const IShellFolder2Vtbl *lpVtbl; + const IPersistVtbl *lpVtblIPersist; LONG ref; /* both paths are parsible from the desktop */ @@ -78,6 +79,11 @@ typedef struct { #define _IUnknown_(This) (IShellFolder*)&(This->lpVtbl) #define _IShellFolder_(This) (IShellFolder*)&(This->lpVtbl) +static inline IGenericSFImpl *impl_from_IPersist( IPersist *iface ) +{ + return (IGenericSFImpl *)((char*)iface - FIELD_OFFSET(IGenericSFImpl, lpVtblIPersist)); +} + static const shvheader DesktopSFHeader[] = { {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15}, {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, @@ -91,7 +97,7 @@ static const shvheader DesktopSFHeader[] = { /************************************************************************** * ISF_Desktop_fnQueryInterface * - * NOTES supports not IPersist/IPersistFolder + * NOTES supports not IPersistFolder */ static HRESULT WINAPI ISF_Desktop_fnQueryInterface( IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj) @@ -108,6 +114,10 @@ static HRESULT WINAPI ISF_Desktop_fnQueryInterface( { *ppvObj = This; } + else if (IsEqualIID (riid, &IID_IPersist)) + { + *ppvObj = &This->lpVtblIPersist; + } if (*ppvObj) { @@ -861,6 +871,42 @@ static const IShellFolder2Vtbl vt_MCFldr_ShellFolder2 = ISF_Desktop_fnMapColumnToSCID }; +/************************************************************************** + * IPersist + */ +static HRESULT WINAPI ISF_Desktop_IPersist_fnQueryInterface( + IPersist *iface, REFIID riid, LPVOID *ppvObj) +{ + IGenericSFImpl *This = impl_from_IPersist( iface ); + return IShellFolder2_QueryInterface((IShellFolder2*)This, riid, ppvObj); +} + +static ULONG WINAPI ISF_Desktop_IPersist_fnAddRef(IPersist *iface) +{ + IGenericSFImpl *This = impl_from_IPersist( iface ); + return IShellFolder2_AddRef((IShellFolder2*)This); +} + +static ULONG WINAPI ISF_Desktop_IPersist_fnRelease(IPersist *iface) +{ + IGenericSFImpl *This = impl_from_IPersist( iface ); + return IShellFolder2_Release((IShellFolder2*)This); +} + +static HRESULT WINAPI ISF_Desktop_IPersist_fnGetClassID(IPersist *iface, CLSID *clsid) +{ + *clsid = CLSID_ShellDesktop; + return S_OK; +} + +static const IPersistVtbl vt_IPersist = +{ + ISF_Desktop_IPersist_fnQueryInterface, + ISF_Desktop_IPersist_fnAddRef, + ISF_Desktop_IPersist_fnRelease, + ISF_Desktop_IPersist_fnGetClassID +}; + /************************************************************************** * ISF_Desktop_Constructor */ @@ -890,6 +936,7 @@ HRESULT WINAPI ISF_Desktop_Constructor ( sf->ref = 1; sf->lpVtbl = &vt_MCFldr_ShellFolder2; + sf->lpVtblIPersist = &vt_IPersist; sf->pidlRoot = _ILCreateDesktop(); /* my qualified pidl */ sf->sPathTarget = SHAlloc( (lstrlenW(szMyPath) + 1)*sizeof(WCHAR) ); lstrcpyW( sf->sPathTarget, szMyPath ); diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index bce7c3ebe44..560033bd113 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -2044,6 +2044,36 @@ if (0) IShellFolder_Release(desktop); } +static void test_desktop_IPersist(void) +{ + IShellFolder *desktop; + IPersist *persist; + CLSID clsid; + HRESULT hr; + + hr = SHGetDesktopFolder(&desktop); + ok(hr == S_OK, "failed %08x\n", hr); + + hr = IShellFolder_QueryInterface(desktop, &IID_IPersist, (void**)&persist); + ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* NT4, W9X */, "failed %08x\n", hr); + + if (hr == S_OK) + { + if (0) + { + /* crashes on native */ + hr = IPersist_GetClassID(persist, NULL); + } + memset(&clsid, 0, sizeof(clsid)); + hr = IPersist_GetClassID(persist, &clsid); + ok(hr == S_OK, "failed %08x\n", hr); + ok(IsEqualIID(&CLSID_ShellDesktop, &clsid), "Expected CLSID_ShellDesktop\n"); + IPersist_Release(persist); + } + + IShellFolder_Release(desktop); +} + START_TEST(shlfolder) { init_function_pointers(); @@ -2064,6 +2094,7 @@ START_TEST(shlfolder) test_SHGetFolderPathAndSubDirA(); test_LocalizedNames(); test_SHCreateShellItem(); + test_desktop_IPersist(); OleUninitialize(); }