Commit 1e5ec889 authored by Juergen Schmied's avatar Juergen Schmied Committed by Alexandre Julliard

- Cleaned up the implementation of shell folders and put them into

separate files. - Fixed some memory leaks. - Some more fixes.
parent 75ce72ea
......@@ -26,18 +26,21 @@ C_SRCS = \
iconcache.c \
memorystream.c \
pidl.c \
shell32_main.c \
shell.c \
shell32_main.c \
shelllink.c \
shlmenu.c \
shellole.c \
shellord.c \
shellpath.c \
shellstring.c \
shellreg.c \
shellstring.c \
shfldr_desktop.c \
shfldr_fs.c \
shfldr_mycomp.c \
shlexec.c \
shlfileop.c \
shlfolder.c \
shlmenu.c \
shlview.c \
shpolicy.c \
shv_bg_cmenu.c \
......
......@@ -14,6 +14,11 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* FIXME:
* - view with root unequal desktop
* - many memory leaks
* - show only filesystem objects
*/
#include <stdlib.h>
......@@ -52,7 +57,7 @@ static void InitializeTreeView(HWND hwndParent, LPCITEMIDLIST root)
/* so far, this method doesn't work (still missing the upper level), keep the old way */
#if 0
if (root == NULL) {
if (_ILIsDesktop (root)) {
hr = SHGetDesktopFolder(&lpsf);
} else {
IShellFolder * lpsfdesktop;
......
......@@ -30,7 +30,7 @@
#include "shell32_main.h"
#include "shlguid.h"
#include "shresdef.h"
#include "wine/obj_queryassociations.h"
#include "shlwapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
......@@ -62,36 +62,24 @@ BOOL HCR_MapTypeToValue ( LPCSTR szExtension, LPSTR szFileType, DWORD len, BOOL
RegCloseKey(hkey);
TRACE("-- %s\n", szFileType );
TRACE("--UE;
} %s\n", szFileType );
return TRUE;
}
BOOL HCR_GetExecuteCommand ( LPCSTR szClass, LPCSTR szVerb, LPSTR szDest, DWORD len )
{
HKEY hkey;
char sTemp[MAX_PATH];
DWORD dwType;
BOOL ret = FALSE;
TRACE("%s %s\n",szClass, szVerb );
sprintf(sTemp, "%s\\shell\\%s\\command",szClass, szVerb);
snprintf(sTemp, MAX_PATH, "%s\\shell\\%s\\command",szClass, szVerb);
if (!RegOpenKeyExA(HKEY_CLASSES_ROOT,sTemp,0,0x02000000,&hkey))
{
if (!RegQueryValueExA(hkey, NULL, 0, &dwType, szDest, &len))
{
if (dwType == REG_EXPAND_SZ)
{
ExpandEnvironmentStringsA(szDest, sTemp, MAX_PATH);
strcpy(szDest, sTemp);
}
ret = TRUE;
}
RegCloseKey(hkey);
if (ERROR_SUCCESS == SHGetValueA(HKEY_CLASSES_ROOT, sTemp, NULL, NULL, szDest, &len)) {
TRACE("-- %s\n", debugstr_a(szDest) );
return TRUE;
}
TRACE("-- %s\n", szDest );
return ret;
return FALSE;
}
/***************************************************************************************
* HCR_GetDefaultIcon [internal]
......@@ -243,7 +231,6 @@ IQueryAssociations* IQueryAssociations_Constructor(void)
ICOM_VTBL(ei) = &qavt;
TRACE("(%p)\n",ei);
shell32_ObjCount++;
return (IQueryAssociations *)ei;
}
/**************************************************************************
......@@ -288,8 +275,6 @@ static ULONG WINAPI IQueryAssociations_fnAddRef(IQueryAssociations * iface)
TRACE("(%p)->(count=%lu)\n",This, This->ref );
shell32_ObjCount++;
return ++(This->ref);
}
/**************************************************************************
......@@ -301,8 +286,6 @@ static ULONG WINAPI IQueryAssociations_fnRelease(IQueryAssociations * iface)
TRACE("(%p)->()\n",This);
shell32_ObjCount--;
if (!--(This->ref))
{
TRACE(" destroying IExtractIcon(%p)\n",This);
......
......@@ -84,8 +84,6 @@ LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[])
{
memcpy(ef->pFmt, afmt, size);
}
shell32_ObjCount++;
}
TRACE("(%p)->(%u,%p)\n",ef, cfmt, afmt);
......@@ -123,7 +121,6 @@ static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface)
{
ICOM_THIS(IEnumFORMATETCImpl,iface);
TRACE("(%p)->(count=%lu)\n",This, This->ref);
shell32_ObjCount++;
return ++(This->ref);
}
......@@ -132,8 +129,6 @@ static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface)
ICOM_THIS(IEnumFORMATETCImpl,iface);
TRACE("(%p)->()\n",This);
shell32_ObjCount--;
if (!--(This->ref))
{
TRACE(" destroying IEnumFORMATETC(%p)\n",This);
......@@ -246,8 +241,6 @@ LPDATAOBJECT IDataObject_Constructor(HWND hwndOwner, LPITEMIDLIST pMyPidl, LPITE
InitFormatEtc(dto->pFormatEtc[0], dto->cfShellIDList, TYMED_HGLOBAL);
InitFormatEtc(dto->pFormatEtc[1], CF_HDROP, TYMED_HGLOBAL);
InitFormatEtc(dto->pFormatEtc[2], dto->cfFileName, TYMED_HGLOBAL);
shell32_ObjCount++;
}
TRACE("(%p)->(apidl=%p cidl=%u)\n",dto, apidl, cidl);
......@@ -289,10 +282,7 @@ static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID ri
static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface)
{
ICOM_THIS(IDataObjectImpl,iface);
TRACE("(%p)->(count=%lu)\n",This, This->ref);
shell32_ObjCount++;
return ++(This->ref);
}
......@@ -304,12 +294,11 @@ static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface)
ICOM_THIS(IDataObjectImpl,iface);
TRACE("(%p)->()\n",This);
shell32_ObjCount--;
if (!--(This->ref))
{
TRACE(" destroying IDataObject(%p)\n",This);
_ILFreeaPidl(This->apidl, This->cidl);
ILFree(This->pidl),
HeapFree(GetProcessHeap(),0,This);
return 0;
}
......@@ -454,4 +443,3 @@ static struct ICOM_VTABLE(IDataObject) dtovt =
IDataObject_fnDUnadvise,
IDataObject_fnEnumDAdvise
};
......@@ -127,10 +127,6 @@ REFIID _dbg_ILGetGUIDPointer(LPCITEMIDLIST pidl)
case PT_SPECIAL:
case PT_MYCOMP:
return (REFIID) &(pdata->u.mycomp.guid);
default:
TRACE("Unknown pidl type 0x%04x\n", pdata->type);
break;
}
}
return NULL;
......@@ -169,10 +165,6 @@ DWORD _dbg_ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR szOut, UINT uOutSize)
riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7] );
dwReturn = strlen (szTemp);
}
else
{
ERR("-- no text\n");
}
return dwReturn;
}
......@@ -209,7 +201,7 @@ void pdump (LPCITEMIDLIST pidl)
else if( PT_VALUE == type)
dwAttrib = pData->u.file.uFileAttribs;
MESSAGE ("-- pidl=%p size=%u type=%lx attr=0x%08lx name=%s (%s,%s)\n",
MESSAGE ("[%p] size=%04u type=%lx attr=0x%08lx name=\"%s\" (%s,%s)\n",
pidltemp, pidltemp->mkid.cb,type,dwAttrib,szName,debugstr_a(szLongName), debugstr_a(szShortName));
pidltemp = _dbg_ILGetNext(pidltemp);
......@@ -267,7 +259,7 @@ BOOL pcheck (LPCITEMIDLIST pidl)
szTemp[i+BYTES_PRINTED*3] = (c>=0x20 && c <=0x80) ? c : '.';
}
szTemp[BYTES_PRINTED*4] = 0x00;
ERR("unknown IDLIST type size=%u type=%lx\n%s\n",pidltemp->mkid.cb,type, szTemp);
ERR("unknown IDLIST %p [%p] size=%u type=%lx\n%s\n",pidl, pidltemp, pidltemp->mkid.cb,type, szTemp);
ret = FALSE;
}
}
......@@ -277,14 +269,16 @@ BOOL pcheck (LPCITEMIDLIST pidl)
return ret;
}
static char shdebugstr_buf[100];
static char shdebugstr_buf1[100];
static char shdebugstr_buf2[100];
static char * shdebugstr_buf = shdebugstr_buf1;
static struct {
REFIID riid;
char *name;
} InterfaceDesc[] = {
{&IID_IUnknown, "IID_IUnknown"},
{&IID_IClassFactory, "IID_IClassFactory"},
{&IID_IShellView, "IID_IShellView"},
{&IID_IOleCommandTarget, "IID_IOleCommandTarget"},
{&IID_IDropTarget, "IID_IDropTarget"},
......@@ -309,6 +303,8 @@ const char * shdebugstr_guid( const struct _GUID *id )
char* name = NULL;
char clsidbuf[100];
shdebugstr_buf = (shdebugstr_buf == shdebugstr_buf1) ? shdebugstr_buf2 : shdebugstr_buf1;
if (!id) {
strcpy (shdebugstr_buf, "(null)");
} else {
......
......@@ -317,9 +317,9 @@ IEnumIDList * IEnumIDList_Constructor(
IEnumIDListImpl* lpeidl;
BOOL ret = FALSE;
lpeidl = (IEnumIDListImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumIDListImpl));
TRACE("()->(%s flags=0x%08lx kind=0x%08lx)\n",debugstr_a(lpszPath),dwFlags, dwKind);
TRACE("(%p)->(%s flags=0x%08lx kind=0x%08lx)\n",lpeidl,debugstr_a(lpszPath),dwFlags, dwKind);
lpeidl = (IEnumIDListImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumIDListImpl));
if (lpeidl)
{
......@@ -341,17 +341,10 @@ IEnumIDList * IEnumIDList_Constructor(
break;
}
if(ret)
{
shell32_ObjCount++;
}
else
{
if (lpeidl)
{
HeapFree(GetProcessHeap(),0,lpeidl);
if(!ret) {
HeapFree(GetProcessHeap(),0,lpeidl);
lpeidl = NULL;
}
}
}
TRACE("-- (%p)->()\n",lpeidl);
......@@ -397,10 +390,7 @@ static ULONG WINAPI IEnumIDList_fnAddRef(
IEnumIDList * iface)
{
ICOM_THIS(IEnumIDListImpl,iface);
TRACE("(%p)->(%lu)\n",This,This->ref);
shell32_ObjCount++;
return ++(This->ref);
}
/******************************************************************************
......@@ -413,10 +403,8 @@ static ULONG WINAPI IEnumIDList_fnRelease(
TRACE("(%p)->(%lu)\n",This,This->ref);
shell32_ObjCount--;
if (!--(This->ref))
{ TRACE(" destroying IEnumIDList(%p)\n",This);
if (!--(This->ref)) {
TRACE(" destroying IEnumIDList(%p)\n",This);
DeleteList((IEnumIDList*)This);
HeapFree(GetProcessHeap(),0,This);
return 0;
......
......@@ -69,7 +69,6 @@ IExtractIconA* IExtractIconA_Constructor(LPCITEMIDLIST pidl)
pdump(pidl);
TRACE("(%p)\n",ei);
shell32_ObjCount++;
return (IExtractIconA *)ei;
}
/**************************************************************************
......@@ -111,8 +110,6 @@ static ULONG WINAPI IExtractIconA_fnAddRef(IExtractIconA * iface)
TRACE("(%p)->(count=%lu)\n",This, This->ref );
shell32_ObjCount++;
return ++(This->ref);
}
/**************************************************************************
......@@ -124,8 +121,6 @@ static ULONG WINAPI IExtractIconA_fnRelease(IExtractIconA * iface)
TRACE("(%p)->()\n",This);
shell32_ObjCount--;
if (!--(This->ref))
{ TRACE(" destroying IExtractIcon(%p)\n",This);
SHFree(This->pidl);
......@@ -340,4 +335,3 @@ static struct ICOM_VTABLE(IPersistFile) pfvt =
(void *) 0xdeadbeef /* IEIPersistFile_fnSaveCompleted */,
(void *) 0xdeadbeef /* IEIPersistFile_fnGetCurFile */
};
......@@ -96,8 +96,6 @@ HRESULT CreateStreamOnFile (LPCSTR pszFilename, IStream ** ppstm)
fstr->ref = 1;
fstr->dwLength = GetFileSize (hFile, NULL);
shell32_ObjCount++;
if (!(fstr->hMapping = CreateFileMappingA(hFile,NULL,PAGE_READONLY|SEC_COMMIT,0,0,NULL)))
{
WARN("failed to create filemap.\n");
......@@ -158,7 +156,6 @@ static ULONG WINAPI IStream_fnAddRef(IStream *iface)
TRACE("(%p)->(count=%lu)\n",This, This->ref);
shell32_ObjCount++;
return ++(This->ref);
}
......@@ -171,8 +168,6 @@ static ULONG WINAPI IStream_fnRelease(IStream *iface)
TRACE("(%p)->()\n",This);
shell32_ObjCount--;
if (!--(This->ref))
{ TRACE(" destroying SHFileStream (%p)\n",This);
......
......@@ -563,12 +563,15 @@ LPITEMIDLIST WINAPI ILGetNext(LPITEMIDLIST pidl)
{
WORD len;
TRACE("%p\n", pidl);
if(pidl)
{
len = pidl->mkid.cb;
if (len)
{
pidl = (LPITEMIDLIST) (((LPBYTE)pidl)+len);
TRACE("-- %p\n", pidl);
return pidl;
}
}
......@@ -907,40 +910,28 @@ HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int n
* FIXME
* fnGetDisplayNameOf can return different types of OLEString
*/
BOOL WINAPI SHGetPathFromIDListA (LPCITEMIDLIST pidl,LPSTR pszPath)
{ STRRET str;
BOOL WINAPI SHGetPathFromIDListA (LPCITEMIDLIST pidl, LPSTR pszPath)
{
HRESULT hr;
STRRET str;
LPSHELLFOLDER shellfolder;
TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath);
pdump(pidl);
if (!pidl) return FALSE;
pdump(pidl);
if(_ILIsDesktop(pidl))
{
SHGetSpecialFolderPathA(0, pszPath, CSIDL_DESKTOPDIRECTORY, FALSE);
}
else if (_ILIsSpecialFolder(ILFindLastID(pidl)))
{
/* we are somewhere in a special folder */
return FALSE;
}
else
{
if (SHGetDesktopFolder(&shellfolder)==S_OK)
{
if(!SUCCEEDED(IShellFolder_GetDisplayNameOf(shellfolder,pidl,SHGDN_FORPARSING,&str))) {
IShellFolder_Release(shellfolder);
return FALSE;
hr = SHGetDesktopFolder(&shellfolder);
if (SUCCEEDED (hr)) {
hr = IShellFolder_GetDisplayNameOf(shellfolder,pidl,SHGDN_FORPARSING,&str);
if(SUCCEEDED(hr)) {
StrRetToStrNA (pszPath, MAX_PATH, &str, pidl);
}
StrRetToStrNA (pszPath, MAX_PATH, &str, pidl);
IShellFolder_Release(shellfolder);
}
}
TRACE_(shell)("-- (%s)\n",pszPath);
return TRUE;
TRACE_(shell)("-- %s, 0x%08lx\n",pszPath, hr);
return SUCCEEDED(hr);
}
/*************************************************************************
* SHGetPathFromIDListW [SHELL32.@]
......@@ -1287,7 +1278,7 @@ DWORD _ILGetDrive(LPCITEMIDLIST pidl,LPSTR pOut, UINT uSize)
*/
BOOL _ILIsDesktop(LPCITEMIDLIST pidl)
{ TRACE("(%p)\n",pidl);
return ( !pidl || (pidl && pidl->mkid.cb == 0x00) );
return pidl && pidl->mkid.cb ? 0 : 1;
}
BOOL _ILIsMyComputer(LPCITEMIDLIST pidl)
......@@ -1562,12 +1553,18 @@ BOOL _ILGetFileDate (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
{
FILETIME ft,lft;
SYSTEMTIME time;
BOOL ret;
if (_ILGetFileDateTime( pidl, &ft )) {
FileTimeToLocalFileTime(&ft, &lft);
FileTimeToSystemTime (&lft, &time);
ret = GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&time, NULL, pOut, uOutSize);
} else {
pOut[0] = '\0';
ret = FALSE;
}
return ret;
if (! _ILGetFileDateTime( pidl, &ft )) return FALSE;
FileTimeToLocalFileTime(&ft, &lft);
FileTimeToSystemTime (&lft, &time);
return GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&time, NULL, pOut, uOutSize);
}
/*************************************************************************
......
......@@ -215,7 +215,7 @@ DWORD WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
IExtractIconA * pei = NULL;
LPITEMIDLIST pidlLast = NULL, pidl = NULL;
HRESULT hr = S_OK;
BOOL IconNotYetLoaded=TRUE;
BOOL IconNotYetLoaded=TRUE;
TRACE("(%s fattr=0x%lx sfi=%p(attr=0x%08lx) size=0x%x flags=0x%x)\n",
(flags & SHGFI_PIDL)? "pidl" : path, dwFileAttributes, psfi, psfi->dwAttributes, sizeofpsfi, flags);
......@@ -289,25 +289,20 @@ DWORD WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
/* translate the path into a pidl only when SHGFI_USEFILEATTRIBUTES in not specified
the pidl functions fail on not existing file names */
if (flags & SHGFI_PIDL)
{
pidl = (LPCITEMIDLIST) path;
if (!pidl )
{
ERR("pidl is null!\n");
return FALSE;
}
}
else if (!(flags & SHGFI_USEFILEATTRIBUTES))
{
hr = SHILCreateFromPathA ( path, &pidl, &dwAttributes);
/* note: the attributes in ISF::ParseDisplayName are not implemented */
if (flags & SHGFI_PIDL) {
pidl = ILClone((LPCITEMIDLIST)path);
} else if (!(flags & SHGFI_USEFILEATTRIBUTES)) {
hr = SHILCreateFromPathA(path, &pidl, &dwAttributes);
}
/* get the parent shellfolder */
if (pidl)
{
hr = SHBindToParent( pidl, &IID_IShellFolder, (LPVOID*)&psfParent, &pidlLast);
if (pidl) {
hr = SHBindToParent( pidl, &IID_IShellFolder, (LPVOID*)&psfParent, &pidlLast);
ILFree(pidl);
} else {
ERR("pidl is null!\n");
return FALSE;
}
/* get the attributes of the child */
......@@ -928,7 +923,6 @@ INT (WINAPI *pEnumMRUListA) (HANDLE hList, INT nItemPos, LPVOID lpBuffer, DW
static HINSTANCE hComctl32;
LONG shell32_ObjCount = 0;
HINSTANCE shell32_hInstance = 0;
HIMAGELIST ShellSmallIconList = 0;
HIMAGELIST ShellBigIconList = 0;
......@@ -995,15 +989,8 @@ BOOL WINAPI Shell32LibMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
case DLL_PROCESS_DETACH:
shell32_hInstance = 0;
SIC_Destroy();
FreeChangeNotifications();
/* this one is here to check if AddRef/Release is balanced */
if (shell32_ObjCount)
{
WARN("leaving with %lu objects left (memory leak)\n", shell32_ObjCount);
}
break;
}
return TRUE;
......
......@@ -24,7 +24,7 @@
#include "commctrl.h"
#include "docobj.h"
#include "undocshell.h"
#include "wine/obj_shellfolder.h"
#include "wine/obj_dataobject.h"
#include "wine/obj_contextmenu.h"
......@@ -38,7 +38,6 @@
*/
extern HMODULE huser32;
extern HINSTANCE shell32_hInstance;
extern LONG shell32_ObjCount;
extern HIMAGELIST ShellSmallIconList;
extern HIMAGELIST ShellBigIconList;
extern HDPA sic_hdpa;
......@@ -98,6 +97,7 @@ LPSHELLVIEW IShellView_Constructor(LPSHELLFOLDER);
HRESULT WINAPI IFSFolder_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
HRESULT WINAPI IShellLink_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
HRESULT WINAPI ISF_Desktop_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
HRESULT WINAPI ISF_MyComputer_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
/* kind of enumidlist */
#define EIDL_DESK 0
......@@ -195,4 +195,22 @@ inline static BOOL SHELL_OsIsUnicode(void)
return !(GetVersion() & 0x80000000);
}
#define __SHFreeAndNil(ptr) \
{\
SHFree(*ptr); \
*ptr = NULL; \
};
inline static void __SHCloneStrA(char ** target,const char * source)
{
*target = SHAlloc(strlen(source)+1); \
strcpy(*target, source); \
}
inline static void __SHCloneStrWtoA(char ** target, const WCHAR * source)
{
int len = WideCharToMultiByte(CP_ACP, 0, source, -1, NULL, 0, NULL, NULL);
*target = SHAlloc(len);
WideCharToMultiByte(CP_ACP, 0, source, -1, *target, len, NULL, NULL);
}
#endif
......@@ -991,7 +991,6 @@ HRESULT WINAPI IShellLink_Constructor (
return E_NOINTERFACE;
}
shell32_ObjCount++;
return S_OK;
}
......@@ -1042,7 +1041,6 @@ static ULONG WINAPI IShellLinkA_fnAddRef(IShellLinkA * iface)
TRACE("(%p)->(count=%lu)\n",This,This->ref);
shell32_ObjCount++;
return ++(This->ref);
}
/******************************************************************************
......@@ -1054,7 +1052,6 @@ static ULONG WINAPI IShellLinkA_fnRelease(IShellLinkA * iface)
TRACE("(%p)->(count=%lu)\n",This,This->ref);
shell32_ObjCount--;
if (!--(This->ref))
{ TRACE("-- destroying IShellLink(%p)\n",This);
......
......@@ -37,6 +37,7 @@
#include "wine/debug.h"
#include "shlwapi.h"
#include "winuser.h"
#include "debughlp.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
......@@ -57,10 +58,11 @@ IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll,
struct {
REFIID riid;
LPFNCREATEINSTANCE lpfnCI;
} InterfaceTable[4] = {
{&CLSID_ShellFSFolder, &IFSFolder_Constructor},
{&CLSID_ShellDesktop, &ISF_Desktop_Constructor},
{&CLSID_ShellLink, &IShellLink_Constructor},
} InterfaceTable[5] = {
{&CLSID_ShellFSFolder, &IFSFolder_Constructor},
{&CLSID_MyComputer, &ISF_MyComputer_Constructor},
{&CLSID_ShellDesktop, &ISF_Desktop_Constructor},
{&CLSID_ShellLink, &IShellLink_Constructor},
{NULL,NULL}
};
......@@ -137,6 +139,9 @@ LRESULT WINAPI SHCoCreateInstance(
BOOLEAN bLoadWithoutCOM = FALSE;
IClassFactory * pcf = NULL;
if(!ppv) return E_POINTER;
*ppv=NULL;
/* if the clsid is a string, convert it */
if (!clsid)
{
......@@ -145,8 +150,8 @@ LRESULT WINAPI SHCoCreateInstance(
myclsid = &iid;
}
TRACE("(%p,\n\tCLSID:\t%s, unk:%p\n\tIID:\t%s,%p)\n",
aclsid,debugstr_guid(myclsid),pUnkOuter,debugstr_guid(refiid),ppv);
TRACE("(%p,%s,unk:%p,%s,%p)\n",
aclsid,shdebugstr_guid(myclsid),pUnkOuter,shdebugstr_guid(refiid),ppv);
/* we look up the dll path in the registry */
__SHGUIDToStringW(myclsid, sClassID);
......@@ -173,11 +178,9 @@ LRESULT WINAPI SHCoCreateInstance(
TRACE("WithoutCom=%u FromShell=%u\n", bLoadWithoutCOM, bLoadFromShell32);
/* now we create a instance */
*ppv=NULL;
if (bLoadFromShell32) {
if (! SUCCEEDED(SHELL32_DllGetClassObject(myclsid, &IID_IClassFactory,(LPVOID*)&pcf))) {
ERR("LoadFromShell failed for CLSID=%s\n", debugstr_guid(myclsid));
ERR("LoadFromShell failed for CLSID=%s\n", shdebugstr_guid(myclsid));
}
} else if (bLoadWithoutCOM) {
......@@ -215,8 +218,8 @@ LRESULT WINAPI SHCoCreateInstance(
end:
if(hres!=S_OK)
{
ERR("failed (0x%08lx) to create \n\tCLSID:\t%s\n\tIID:\t%s\n",
hres, debugstr_guid(myclsid), debugstr_guid(refiid));
ERR("failed (0x%08lx) to create CLSID:%s IID:%s\n",
hres, shdebugstr_guid(myclsid), shdebugstr_guid(refiid));
ERR("class not found in registry\n");
}
......@@ -233,7 +236,7 @@ HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *pp
IClassFactory * pcf = NULL;
int i;
TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
TRACE("CLSID:%s,IID:%s\n",shdebugstr_guid(rclsid),shdebugstr_guid(iid));
if (!ppv) return E_INVALIDARG;
*ppv = NULL;
......@@ -242,12 +245,12 @@ HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *pp
for(i=0;InterfaceTable[i].riid;i++) {
if(IsEqualIID(InterfaceTable[i].riid, rclsid)) {
TRACE("index[%u]\n", i);
pcf = IDefClF_fnConstructor(InterfaceTable[i].lpfnCI, &shell32_ObjCount, NULL);
pcf = IDefClF_fnConstructor(InterfaceTable[i].lpfnCI, NULL, NULL);
}
}
if (!pcf) {
FIXME("failed for CLSID=%s\n", debugstr_guid(rclsid));
FIXME("failed for CLSID=%s\n", shdebugstr_guid(rclsid));
return CLASS_E_CLASSNOTAVAILABLE;
}
......@@ -307,8 +310,7 @@ IMalloc * ShellTaskAllocator = NULL;
*/
static HRESULT WINAPI IShellMalloc_fnQueryInterface(LPMALLOC iface, REFIID refiid, LPVOID *obj)
{
TRACE("(%s,%p)\n",debugstr_guid(refiid),obj);
TRACE("(%s,%p)\n",shdebugstr_guid(refiid),obj);
if (IsEqualIID(refiid, &IID_IUnknown) || IsEqualIID(refiid, &IID_IMalloc)) {
*obj = (LPMALLOC) &Shell_Malloc;
return S_OK;
......@@ -458,7 +460,6 @@ LPVOID WINAPI SHAlloc(DWORD len)
if (!ShellTaskAllocator) SHGetMalloc(&ppv);
ret = (LPVOID) IMalloc_Alloc(ShellTaskAllocator, len);
if(ret) ZeroMemory(ret, len); /*FIXME*/
TRACE("%lu bytes at %p\n",len, ret);
return (LPVOID)ret;
}
......@@ -484,7 +485,7 @@ void WINAPI SHFree(LPVOID pv)
DWORD WINAPI SHGetDesktopFolder(IShellFolder **psf)
{
HRESULT hres = S_OK;
TRACE("%p->(%p)\n",psf,*psf);
TRACE("\n");
if(!psf) return E_INVALIDARG;
*psf = NULL;
......@@ -493,7 +494,6 @@ DWORD WINAPI SHGetDesktopFolder(IShellFolder **psf)
TRACE("-- %p->(%p)\n",psf, *psf);
return hres;
}
/**************************************************************************
* Default ClassFactory Implementation
*
......@@ -534,7 +534,7 @@ IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll,
if (pcRefDll) InterlockedIncrement(pcRefDll);
lpclf->riidInst = riidInst;
TRACE("(%p)\n\tIID:\t%s\n",lpclf, debugstr_guid(riidInst));
TRACE("(%p)%s\n",lpclf, shdebugstr_guid(riidInst));
return (LPCLASSFACTORY)lpclf;
}
/**************************************************************************
......@@ -545,7 +545,7 @@ static HRESULT WINAPI IDefClF_fnQueryInterface(
{
ICOM_THIS(IDefClFImpl,iface);
TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid));
TRACE("(%p)->(%s)\n",This,shdebugstr_guid(riid));
*ppvObj = NULL;
......@@ -594,7 +594,7 @@ static HRESULT WINAPI IDefClF_fnCreateInstance(
{
ICOM_THIS(IDefClFImpl,iface);
TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnkOuter,debugstr_guid(riid),ppvObject);
TRACE("%p->(%p,%s,%p)\n",This,pUnkOuter,shdebugstr_guid(riid),ppvObject);
*ppvObject = NULL;
......@@ -605,7 +605,7 @@ static HRESULT WINAPI IDefClF_fnCreateInstance(
return This->lpfnCI(pUnkOuter, riid, ppvObject);
}
ERR("unknown IID requested\n\tIID:\t%s\n",debugstr_guid(riid));
ERR("unknown IID requested %s\n",shdebugstr_guid(riid));
return E_NOINTERFACE;
}
/******************************************************************************
......@@ -640,8 +640,8 @@ HRESULT WINAPI SHCreateDefClassObject(
{
IClassFactory * pcf;
TRACE("\n\tIID:\t%s %p %p %p \n\tIIDIns:\t%s\n",
debugstr_guid(riid), ppv, lpfnCI, pcRefDll, debugstr_guid(riidInst));
TRACE("%s %p %p %p %s\n",
shdebugstr_guid(riid), ppv, lpfnCI, pcRefDll, shdebugstr_guid(riidInst));
if (! IsEqualCLSID(riid, &IID_IClassFactory) ) return E_NOINTERFACE;
if (! (pcf = IDefClF_fnConstructor(lpfnCI, pcRefDll, riidInst))) return E_OUTOFMEMORY;
......
......@@ -47,7 +47,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell);
HRESULT WINAPI StrRetToStrNA (LPVOID dest, DWORD len, LPSTRRET src, const ITEMIDLIST *pidl)
{
TRACE("dest=0x%p len=0x%lx strret=0x%p pidl=%p stub\n",dest,len,src,pidl);
TRACE("dest=0x%p len=0x%lx strret=%p(%s) pidl=%p\n",
dest,len,src,
(src->uType == STRRET_WSTR) ? "STRRET_WSTR" :
(src->uType == STRRET_CSTR) ? "STRRET_CSTR" :
(src->uType == STRRET_OFFSET) ? "STRRET_OFFSET" : "STRRET_???",
pidl);
switch (src->uType)
{
......@@ -66,21 +71,23 @@ HRESULT WINAPI StrRetToStrNA (LPVOID dest, DWORD len, LPSTRRET src, const ITEMID
default:
FIXME("unknown type!\n");
if (len)
{
*(LPSTR)dest = '\0';
}
if (len) *(LPSTR)dest = '\0';
return(FALSE);
}
TRACE("-- %s\n", debugstr_a(dest) );
return S_OK;
}
/************************************************************************/
HRESULT WINAPI StrRetToStrNW (LPVOID dest1, DWORD len, LPSTRRET src, const ITEMIDLIST *pidl)
HRESULT WINAPI StrRetToStrNW (LPVOID dest, DWORD len, LPSTRRET src, const ITEMIDLIST *pidl)
{
LPWSTR dest = (LPWSTR) dest1;
TRACE("dest=0x%p len=0x%lx strret=0x%p pidl=%p stub\n",dest,len,src,pidl);
TRACE("dest=0x%p len=0x%lx strret=%p(%s) pidl=%p\n",
dest,len,src,
(src->uType == STRRET_WSTR) ? "STRRET_WSTR" :
(src->uType == STRRET_CSTR) ? "STRRET_CSTR" :
(src->uType == STRRET_OFFSET) ? "STRRET_OFFSET" : "STRRET_???",
pidl);
switch (src->uType)
{
......@@ -90,24 +97,18 @@ HRESULT WINAPI StrRetToStrNW (LPVOID dest1, DWORD len, LPSTRRET src, const ITEMI
break;
case STRRET_CSTR:
if (!MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ) && len)
dest[len-1] = 0;
if (!MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ) && len)
((LPWSTR)dest)[len-1] = 0;
break;
case STRRET_OFFSET:
if (pidl)
{
if (!MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, -1,
dest, len ) && len)
dest[len-1] = 0;
}
if (!MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, -1, dest, len ) && len)
((LPWSTR)dest)[len-1] = 0;
break;
default:
FIXME("unknown type!\n");
if (len)
{ *(LPSTR)dest = '\0';
}
if (len) *(LPWSTR)dest = '\0';
return(FALSE);
}
return S_OK;
......
/*
* Virtual Folder
* common definitions
*
* Copyright 1997 Marcus Meissner
* Copyright 1998, 1999, 2002 Juergen Schmied
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
< * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
typedef struct {
int colnameid;
int pcsFlags;
int fmt;
int cxChar;
} shvheader;
#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
LPCWSTR GetNextElementW (LPCWSTR pszNext, LPWSTR pszOut, DWORD dwOut);
HRESULT SHELL32_ParseNextElement (HWND hwndOwner, IShellFolder2 * psf, LPITEMIDLIST * pidlInOut, LPOLESTR szNext,
DWORD * pEaten, DWORD * pdwAttributes);
HRESULT SHELL32_GetItemAttributes (IShellFolder * psf, LPITEMIDLIST pidl, LPDWORD pdwAttributes);
HRESULT SHELL32_CoCreateInitSF (LPITEMIDLIST pidlRoot, LPITEMIDLIST pidlChild, REFCLSID clsid, REFIID iid,
LPVOID * ppvOut);
HRESULT SHELL32_CoCreateInitSFEx (LPITEMIDLIST pidlRoot, LPCSTR pathRoot, LPITEMIDLIST pidlChild, REFCLSID clsid,
REFIID iid, LPVOID * ppvOut);
HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTR szOut,
DWORD dwOutLen);
HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot,
LPCSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut);
HRESULT SHELL32_CompareIDs (IShellFolder * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
/*
* Virtual Desktop Folder
*
* Copyright 1997 Marcus Meissner
* Copyright 1998, 1999, 2002 Juergen Schmied
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "winerror.h"
#include "winbase.h"
#include "winreg.h"
#include "oleidl.h"
#include "shlguid.h"
#include "pidl.h"
#include "wine/obj_base.h"
#include "wine/obj_dragdrop.h"
#include "wine/obj_shellfolder.h"
#include "undocshell.h"
#include "shell32_main.h"
#include "shresdef.h"
#include "shlwapi.h"
#include "shellfolder.h"
#include "wine/debug.h"
#include "debughlp.h"
#include "shfldr.h"
WINE_DEFAULT_DEBUG_CHANNEL (shell);
/***********************************************************************
* Desktopfolder implementation
*/
typedef struct {
ICOM_VFIELD (IShellFolder2);
DWORD ref;
CLSID *pclsid;
/* both paths are parsible from the desktop */
LPSTR sPathTarget; /* complete path to target used for enumeration and ChangeNotify */
LPITEMIDLIST pidlRoot; /* absolute pidl */
int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */
UINT cfShellIDList; /* clipboardformat for IDropTarget */
BOOL fAcceptFmt; /* flag for pending Drop */
} IGenericSFImpl;
#define _IUnknown_(This) (IShellFolder*)&(This->lpVtbl)
#define _IShellFolder_(This) (IShellFolder*)&(This->lpVtbl)
HRESULT WINAPI ISF_MyComputer_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
static struct ICOM_VTABLE (IShellFolder2) vt_MCFldr_ShellFolder2;
static shvheader DesktopSFHeader[] = {
{IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
{IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
{IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
{IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12},
{IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5}
};
#define DESKTOPSHELLVIEWCOLUMNS 5
/**************************************************************************
* ISF_Desktop_Constructor
*/
HRESULT WINAPI ISF_Desktop_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
{
IGenericSFImpl *sf;
char szMyPath[MAX_PATH];
TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));
if (!ppv)
return E_POINTER;
if (pUnkOuter)
return CLASS_E_NOAGGREGATION;
if (!SHGetSpecialFolderPathA (0, szMyPath, CSIDL_DESKTOPDIRECTORY, TRUE))
return E_UNEXPECTED;
sf = (IGenericSFImpl *) LocalAlloc (GMEM_ZEROINIT, sizeof (IGenericSFImpl));
if (!sf)
return E_OUTOFMEMORY;
sf->ref = 0;
ICOM_VTBL (sf) = &vt_MCFldr_ShellFolder2;
sf->pidlRoot = _ILCreateDesktop (); /* my qualified pidl */
sf->sPathTarget = SHAlloc (strlen (szMyPath) + 1);
lstrcpyA (sf->sPathTarget, szMyPath);
if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv))) {
IUnknown_Release (_IUnknown_ (sf));
return E_NOINTERFACE;
}
TRACE ("--(%p)\n", sf);
return S_OK;
}
/**************************************************************************
* ISF_Desktop_fnQueryInterface
*
* NOTES supports not IPersist/IPersistFolder
*/
static HRESULT WINAPI ISF_Desktop_fnQueryInterface (IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);
*ppvObj = NULL;
if (IsEqualIID (riid, &IID_IUnknown) || IsEqualIID (riid, &IID_IShellFolder)
|| IsEqualIID (riid, &IID_IShellFolder2)) {
*ppvObj = This;
}
if (*ppvObj) {
IUnknown_AddRef ((IUnknown *) (*ppvObj));
TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj);
return S_OK;
}
TRACE ("-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
static ULONG WINAPI ISF_Desktop_fnAddRef (IShellFolder2 * iface)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
return ++(This->ref);
}
static ULONG WINAPI ISF_Desktop_fnRelease (IShellFolder2 * iface)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
if (!--(This->ref)) {
TRACE ("-- destroying IShellFolder(%p)\n", This);
if (This->pidlRoot)
SHFree (This->pidlRoot);
if (This->sPathTarget)
SHFree (This->sPathTarget);
LocalFree ((HLOCAL) This);
}
return This->ref;
}
/**************************************************************************
* ISF_Desktop_fnParseDisplayName
*
* NOTES
* "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
* to MyComputer
*/
static HRESULT WINAPI ISF_Desktop_fnParseDisplayName (IShellFolder2 * iface,
HWND hwndOwner,
LPBC pbcReserved,
LPOLESTR lpszDisplayName,
DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
{
ICOM_THIS (IGenericSFImpl, iface);
WCHAR szElement[MAX_PATH];
LPCWSTR szNext = NULL;
LPITEMIDLIST pidlTemp = NULL;
HRESULT hr = E_OUTOFMEMORY;
CLSID clsid;
TRACE ("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
This, hwndOwner, pbcReserved, lpszDisplayName, debugstr_w (lpszDisplayName), pchEaten, ppidl, pdwAttributes);
*ppidl = 0;
if (pchEaten)
*pchEaten = 0; /* strange but like the original */
if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':') {
szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
TRACE ("-- element: %s\n", debugstr_w (szElement));
CLSIDFromString (szElement + 2, &clsid);
pidlTemp = _ILCreate (PT_MYCOMP, &clsid, sizeof (clsid));
} else if (PathGetDriveNumberW (lpszDisplayName) >= 0) {
/* it's a filesystem path with a drive. Let MyComputer parse it */
pidlTemp = _ILCreateMyComputer ();
szNext = lpszDisplayName;
} else {
/* it's a filesystem path on the desktop. Let a FSFolder parse it */
WCHAR szCompletePath[MAX_PATH];
/* build a complete path to create a simpel pidl */
MultiByteToWideChar (CP_ACP, 0, This->sPathTarget, -1, szCompletePath, MAX_PATH);
PathAddBackslashW (szCompletePath);
lstrcatW (szCompletePath, lpszDisplayName);
pidlTemp = SHSimpleIDListFromPathW (lpszDisplayName);
szNext = lpszDisplayName;
}
if (pidlTemp) {
if (szNext && *szNext) {
hr = SHELL32_ParseNextElement (hwndOwner, iface, &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
} else {
hr = S_OK;
if (pdwAttributes && *pdwAttributes) {
SHELL32_GetItemAttributes (_IShellFolder_ (This), pidlTemp, pdwAttributes);
}
}
}
*ppidl = pidlTemp;
TRACE ("(%p)->(-- ret=0x%08lx)\n", This, hr);
return hr;
}
/**************************************************************************
* ISF_Desktop_fnEnumObjects
*/
static HRESULT WINAPI ISF_Desktop_fnEnumObjects (IShellFolder2 * iface,
HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n", This, hwndOwner, dwFlags, ppEnumIDList);
*ppEnumIDList = NULL;
*ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_DESK);
TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList);
if (!*ppEnumIDList)
return E_OUTOFMEMORY;
return S_OK;
}
/**************************************************************************
* ISF_Desktop_fnBindToObject
*/
static HRESULT WINAPI ISF_Desktop_fnBindToObject (IShellFolder2 * iface,
LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
return SHELL32_BindToChild (This->pidlRoot, This->sPathTarget, pidl, riid, ppvOut);
}
/**************************************************************************
* ISF_Desktop_fnBindToStorage
*/
static HRESULT WINAPI ISF_Desktop_fnBindToStorage (IShellFolder2 * iface,
LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
{
ICOM_THIS (IGenericSFImpl, iface);
FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
*ppvOut = NULL;
return E_NOTIMPL;
}
/**************************************************************************
* ISF_Desktop_fnCompareIDs
*/
static HRESULT WINAPI ISF_Desktop_fnCompareIDs (IShellFolder2 * iface,
LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
{
ICOM_THIS (IGenericSFImpl, iface);
int nReturn;
TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2);
nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2);
TRACE ("-- %i\n", nReturn);
return nReturn;
}
/**************************************************************************
* ISF_Desktop_fnCreateViewObject
*/
static HRESULT WINAPI ISF_Desktop_fnCreateViewObject (IShellFolder2 * iface,
HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
{
ICOM_THIS (IGenericSFImpl, iface);
LPSHELLVIEW pShellView;
HRESULT hr = E_INVALIDARG;
TRACE ("(%p)->(hwnd=0x%x,%s,%p)\n", This, hwndOwner, shdebugstr_guid (riid), ppvOut);
if (ppvOut) {
*ppvOut = NULL;
if (IsEqualIID (riid, &IID_IDropTarget)) {
WARN ("IDropTarget not implemented\n");
hr = E_NOTIMPL;
} else if (IsEqualIID (riid, &IID_IContextMenu)) {
WARN ("IContextMenu not implemented\n");
hr = E_NOTIMPL;
} else if (IsEqualIID (riid, &IID_IShellView)) {
pShellView = IShellView_Constructor ((IShellFolder *) iface);
if (pShellView) {
hr = IShellView_QueryInterface (pShellView, riid, ppvOut);
IShellView_Release (pShellView);
}
}
}
TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut);
return hr;
}
/**************************************************************************
* ISF_Desktop_fnGetAttributesOf
*/
static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf (IShellFolder2 * iface,
UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
{
ICOM_THIS (IGenericSFImpl, iface);
HRESULT hr = S_OK;
TRACE ("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut);
if ((!cidl) || (!apidl) || (!rgfInOut))
return E_INVALIDARG;
while (cidl > 0 && *apidl) {
pdump (*apidl);
SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut);
apidl++;
cidl--;
}
TRACE ("-- result=0x%08lx\n", *rgfInOut);
return hr;
}
/**************************************************************************
* ISF_Desktop_fnGetUIObjectOf
*
* PARAMETERS
* HWND hwndOwner, //[in ] Parent window for any output
* UINT cidl, //[in ] array size
* LPCITEMIDLIST* apidl, //[in ] simple pidl array
* REFIID riid, //[in ] Requested Interface
* UINT* prgfInOut, //[ ] reserved
* LPVOID* ppvObject) //[out] Resulting Interface
*
*/
static HRESULT WINAPI ISF_Desktop_fnGetUIObjectOf (IShellFolder2 * iface,
HWND hwndOwner,
UINT cidl,
LPCITEMIDLIST * apidl,
REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
{
ICOM_THIS (IGenericSFImpl, iface);
LPITEMIDLIST pidl;
IUnknown *pObj = NULL;
HRESULT hr = E_INVALIDARG;
TRACE ("(%p)->(0x%04x,%u,apidl=%p,%s,%p,%p)\n",
This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut);
if (ppvOut) {
*ppvOut = NULL;
if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1)) {
pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl);
hr = S_OK;
} else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) {
pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl);
hr = S_OK;
} else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1)) {
pidl = ILCombine (This->pidlRoot, apidl[0]);
pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
SHFree (pidl);
hr = S_OK;
} else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) {
hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj);
} else {
hr = E_NOINTERFACE;
}
if (!pObj)
hr = E_OUTOFMEMORY;
*ppvOut = pObj;
}
TRACE ("(%p)->hr=0x%08lx\n", This, hr);
return hr;
}
/**************************************************************************
* ISF_Desktop_fnGetDisplayNameOf
*
* NOTES
* special case: pidl = null gives desktop-name back
*/
DWORD WINAPI __SHGUIDToStringA (REFGUID guid, LPSTR str)
{
CHAR sFormat[52] = "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}";
return wsprintfA (str, sFormat,
guid->Data1, guid->Data2, guid->Data3,
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
}
static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf (IShellFolder2 * iface,
LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
{
ICOM_THIS (IGenericSFImpl, iface);
CHAR szPath[MAX_PATH] = "";
GUID const *clsid;
HRESULT hr = S_OK;
TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet);
pdump (pidl);
if (!strRet)
return E_INVALIDARG;
if (_ILIsDesktop (pidl)) {
if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) && (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING)) {
lstrcpyA (szPath, This->sPathTarget);
} else {
HCR_GetClassName (&CLSID_ShellDesktop, szPath, MAX_PATH);
}
} else if (_ILIsPidlSimple (pidl)) {
if ((clsid = _ILGetGUIDPointer (pidl))) {
if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING) {
int bWantsForParsing;
/*
* we can only get a filesystem path from a shellfolder if the value WantsFORPARSING in
* CLSID\\{...}\\shellfolder exists
* exception: the MyComputer folder has this keys not but like any filesystem backed
* folder it needs these behaviour
*/
if (IsEqualIID (clsid, &CLSID_MyComputer)) {
bWantsForParsing = 1;
} else {
/* get the "WantsFORPARSING" flag from the registry */
char szRegPath[100];
lstrcpyA (szRegPath, "CLSID\\");
__SHGUIDToStringA (clsid, &szRegPath[6]);
lstrcatA (szRegPath, "\\shellfolder");
bWantsForParsing =
(ERROR_SUCCESS ==
SHGetValueA (HKEY_CLASSES_ROOT, szRegPath, "WantsFORPARSING", NULL, NULL, NULL));
}
if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) && bWantsForParsing) {
/* we need the filesystem path to the destination folder. Only the folder itself can know it */
hr = SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags, szPath, MAX_PATH);
} else {
/* parsing name like ::{...} */
lstrcpyA (szPath, "::");
__SHGUIDToStringA (clsid, &szPath[2]);
}
} else {
/* user friendly name */
HCR_GetClassName (clsid, szPath, MAX_PATH);
}
} else {
/* file system folder */
_ILSimpleGetText (pidl, szPath, MAX_PATH);
}
} else {
/* a complex pidl, let the subfolder do the work */
hr = SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags, szPath, MAX_PATH);
}
if (SUCCEEDED (hr)) {
strRet->uType = STRRET_CSTR;
lstrcpynA (strRet->u.cStr, szPath, MAX_PATH);
}
TRACE ("-- (%p)->(%s,0x%08lx)\n", This, szPath, hr);
return hr;
}
/**************************************************************************
* ISF_Desktop_fnSetNameOf
* Changes the name of a file object or subfolder, possibly changing its item
* identifier in the process.
*
* PARAMETERS
* HWND hwndOwner, //[in ] Owner window for output
* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
* LPCOLESTR lpszName, //[in ] the items new display name
* DWORD dwFlags, //[in ] SHGNO formatting flags
* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
*/
static HRESULT WINAPI ISF_Desktop_fnSetNameOf (IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl, /*simple pidl */
LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
{
ICOM_THIS (IGenericSFImpl, iface);
FIXME ("(%p)->(%u,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
return E_FAIL;
}
static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID (IShellFolder2 * iface, GUID * pguid)
{
ICOM_THIS (IGenericSFImpl, iface);
FIXME ("(%p)\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI ISF_Desktop_fnEnumSearches (IShellFolder2 * iface, IEnumExtraSearch ** ppenum)
{
ICOM_THIS (IGenericSFImpl, iface);
FIXME ("(%p)\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumn (IShellFolder2 * iface,
DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)\n", This);
if (pSort)
*pSort = 0;
if (pDisplay)
*pDisplay = 0;
return S_OK;
}
static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumnState (IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)\n", This);
if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS)
return E_INVALIDARG;
*pcsFlags = DesktopSFHeader[iColumn].pcsFlags;
return S_OK;
}
static HRESULT WINAPI ISF_Desktop_fnGetDetailsEx (IShellFolder2 * iface,
LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
{
ICOM_THIS (IGenericSFImpl, iface);
FIXME ("(%p)\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf (IShellFolder2 * iface,
LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd)
{
ICOM_THIS (IGenericSFImpl, iface);
HRESULT hr = E_FAIL;
TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd);
if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS)
return E_INVALIDARG;
if (!pidl) {
psd->fmt = DesktopSFHeader[iColumn].fmt;
psd->cxChar = DesktopSFHeader[iColumn].cxChar;
psd->str.uType = STRRET_CSTR;
LoadStringA (shell32_hInstance, DesktopSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
return S_OK;
} else {
/* the data from the pidl */
switch (iColumn) {
case 0: /* name */
hr = IShellFolder_GetDisplayNameOf (iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
break;
case 1: /* size */
_ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
break;
case 2: /* type */
_ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH);
break;
case 3: /* date */
_ILGetFileDate (pidl, psd->str.u.cStr, MAX_PATH);
break;
case 4: /* attributes */
_ILGetFileAttributes (pidl, psd->str.u.cStr, MAX_PATH);
break;
}
hr = S_OK;
psd->str.uType = STRRET_CSTR;
}
return hr;
}
static HRESULT WINAPI ISF_Desktop_fnMapNameToSCID (IShellFolder2 * iface, LPCWSTR pwszName, SHCOLUMNID * pscid)
{
ICOM_THIS (IGenericSFImpl, iface);
FIXME ("(%p)\n", This);
return E_NOTIMPL;
}
static ICOM_VTABLE (IShellFolder2) vt_MCFldr_ShellFolder2 =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
ISF_Desktop_fnQueryInterface,
ISF_Desktop_fnAddRef,
ISF_Desktop_fnRelease,
ISF_Desktop_fnParseDisplayName,
ISF_Desktop_fnEnumObjects,
ISF_Desktop_fnBindToObject,
ISF_Desktop_fnBindToStorage,
ISF_Desktop_fnCompareIDs,
ISF_Desktop_fnCreateViewObject,
ISF_Desktop_fnGetAttributesOf,
ISF_Desktop_fnGetUIObjectOf,
ISF_Desktop_fnGetDisplayNameOf,
ISF_Desktop_fnSetNameOf,
/* ShellFolder2 */
ISF_Desktop_fnGetDefaultSearchGUID,
ISF_Desktop_fnEnumSearches,
ISF_Desktop_fnGetDefaultColumn,
ISF_Desktop_fnGetDefaultColumnState,
ISF_Desktop_fnGetDetailsEx,
ISF_Desktop_fnGetDetailsOf,
ISF_Desktop_fnMapNameToSCID};
/*
* file system folder
*
* Copyright 1997 Marcus Meissner
* Copyright 1998, 1999, 2002 Juergen Schmied
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "winerror.h"
#include "winbase.h"
#include "winreg.h"
#include "oleidl.h"
#include "shlguid.h"
#include "pidl.h"
#include "wine/obj_base.h"
#include "wine/obj_dragdrop.h"
#include "wine/obj_shellfolder.h"
#include "undocshell.h"
#include "shell32_main.h"
#include "shresdef.h"
#include "shlwapi.h"
#include "shellfolder.h"
#include "wine/debug.h"
#include "debughlp.h"
#include "shfldr.h"
WINE_DEFAULT_DEBUG_CHANNEL (shell);
/***********************************************************************
* IShellFolder implementation
*/
typedef struct {
ICOM_VFIELD (IUnknown);
DWORD ref;
ICOM_VTABLE (IShellFolder2) * lpvtblShellFolder;
ICOM_VTABLE (IPersistFolder3) * lpvtblPersistFolder3;
ICOM_VTABLE (IDropTarget) * lpvtblDropTarget;
ICOM_VTABLE (ISFHelper) * lpvtblSFHelper;
IUnknown *pUnkOuter; /* used for aggregation */
CLSID *pclsid;
/* both paths are parsible from the desktop */
LPSTR sPathTarget; /* complete path to target used for enumeration and ChangeNotify */
LPITEMIDLIST pidlRoot; /* absolute pidl */
int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */
UINT cfShellIDList; /* clipboardformat for IDropTarget */
BOOL fAcceptFmt; /* flag for pending Drop */
} IGenericSFImpl;
static struct ICOM_VTABLE (IUnknown) unkvt;
static struct ICOM_VTABLE (IShellFolder2) sfvt;
static struct ICOM_VTABLE (IPersistFolder3) vt_FSFldr_PersistFolder3; /* IPersistFolder3 for a FS_Folder */
static struct ICOM_VTABLE (IDropTarget) dtvt;
static struct ICOM_VTABLE (ISFHelper) shvt;
#define _IShellFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblShellFolder)))
#define _ICOM_THIS_From_IShellFolder2(class, name) class* This = (class*)(((char*)name)-_IShellFolder2_Offset);
#define _IPersistFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder3)))
#define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder2_Offset);
#define _IPersistFolder3_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder3)))
#define _ICOM_THIS_From_IPersistFolder3(class, name) class* This = (class*)(((char*)name)-_IPersistFolder3_Offset);
#define _IDropTarget_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblDropTarget)))
#define _ICOM_THIS_From_IDropTarget(class, name) class* This = (class*)(((char*)name)-_IDropTarget_Offset);
#define _ISFHelper_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblSFHelper)))
#define _ICOM_THIS_From_ISFHelper(class, name) class* This = (class*)(((char*)name)-_ISFHelper_Offset);
/*
converts This to a interface pointer
*/
#define _IUnknown_(This) (IUnknown*)&(This->lpVtbl)
#define _IShellFolder_(This) (IShellFolder*)&(This->lpvtblShellFolder)
#define _IShellFolder2_(This) (IShellFolder2*)&(This->lpvtblShellFolder)
#define _IPersist_(This) (IPersist*)&(This->lpvtblPersistFolder3)
#define _IPersistFolder_(This) (IPersistFolder*)&(This->lpvtblPersistFolder3)
#define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpvtblPersistFolder3)
#define _IPersistFolder3_(This) (IPersistFolder3*)&(This->lpvtblPersistFolder3)
#define _IDropTarget_(This) (IDropTarget*)&(This->lpvtblDropTarget)
#define _ISFHelper_(This) (ISFHelper*)&(This->lpvtblSFHelper)
/**************************************************************************
* registers clipboardformat once
*/
static void SF_RegisterClipFmt (IGenericSFImpl * This)
{
TRACE ("(%p)\n", This);
if (!This->cfShellIDList) {
This->cfShellIDList = RegisterClipboardFormatA (CFSTR_SHELLIDLIST);
}
}
/**************************************************************************
* we need a separate IUnknown to handle aggregation
* (inner IUnknown)
*/
static HRESULT WINAPI IUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPVOID * ppvObj)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);
*ppvObj = NULL;
if (IsEqualIID (riid, &IID_IUnknown))
*ppvObj = _IUnknown_ (This);
else if (IsEqualIID (riid, &IID_IShellFolder))
*ppvObj = _IShellFolder_ (This);
else if (IsEqualIID (riid, &IID_IShellFolder2))
*ppvObj = _IShellFolder_ (This);
else if (IsEqualIID (riid, &IID_IPersist))
*ppvObj = _IPersist_ (This);
else if (IsEqualIID (riid, &IID_IPersistFolder))
*ppvObj = _IPersistFolder_ (This);
else if (IsEqualIID (riid, &IID_IPersistFolder2))
*ppvObj = _IPersistFolder2_ (This);
else if (IsEqualIID (riid, &IID_IPersistFolder3))
*ppvObj = _IPersistFolder3_ (This);
else if (IsEqualIID (riid, &IID_ISFHelper))
*ppvObj = _ISFHelper_ (This);
else if (IsEqualIID (riid, &IID_IDropTarget)) {
*ppvObj = _IDropTarget_ (This);
SF_RegisterClipFmt (This);
}
if (*ppvObj) {
IUnknown_AddRef ((IUnknown *) (*ppvObj));
TRACE ("-- Interface = %p\n", *ppvObj);
return S_OK;
}
TRACE ("-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
static ULONG WINAPI IUnknown_fnAddRef (IUnknown * iface)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
return ++(This->ref);
}
static ULONG WINAPI IUnknown_fnRelease (IUnknown * iface)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
if (!--(This->ref)) {
TRACE ("-- destroying IShellFolder(%p)\n", This);
if (This->pidlRoot)
SHFree (This->pidlRoot);
if (This->sPathTarget)
SHFree (This->sPathTarget);
LocalFree ((HLOCAL) This);
return 0;
}
return This->ref;
}
static ICOM_VTABLE (IUnknown) unkvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE IUnknown_fnQueryInterface,
IUnknown_fnAddRef,
IUnknown_fnRelease,
};
static shvheader GenericSFHeader[] = {
{IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
{IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
{IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
{IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12},
{IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5}
};
#define GENERICSHELLVIEWCOLUMNS 5
/**************************************************************************
* IFSFolder_Constructor
*
* NOTES
* creating undocumented ShellFS_Folder as part of an aggregation
* {F3364BA0-65B9-11CE-A9BA-00AA004AE837}
*
*/
HRESULT WINAPI IFSFolder_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
{
IGenericSFImpl *sf;
TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));
if (pUnkOuter && !IsEqualIID (riid, &IID_IUnknown))
return CLASS_E_NOAGGREGATION;
sf = (IGenericSFImpl *) LocalAlloc (GMEM_ZEROINIT, sizeof (IGenericSFImpl));
if (!sf)
return E_OUTOFMEMORY;
sf->ref = 0;
ICOM_VTBL (sf) = &unkvt;
sf->lpvtblShellFolder = &sfvt;
sf->lpvtblPersistFolder3 = &vt_FSFldr_PersistFolder3;
sf->lpvtblDropTarget = &dtvt;
sf->lpvtblSFHelper = &shvt;
sf->pclsid = (CLSID *) & CLSID_ShellFSFolder;
sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_ (sf);
if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv))) {
IUnknown_Release (_IUnknown_ (sf));
return E_NOINTERFACE;
}
TRACE ("--%p\n", *ppv);
return S_OK;
}
/**************************************************************************
* IShellFolder_fnQueryInterface
*
* PARAMETERS
* REFIID riid [in ] Requested InterfaceID
* LPVOID* ppvObject [out] Interface* to hold the result
*/
static HRESULT WINAPI IShellFolder_fnQueryInterface (IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);
return IUnknown_QueryInterface (This->pUnkOuter, riid, ppvObj);
}
/**************************************************************************
* IShellFolder_AddRef
*/
static ULONG WINAPI IShellFolder_fnAddRef (IShellFolder2 * iface)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
return IUnknown_AddRef (This->pUnkOuter);
}
/**************************************************************************
* IShellFolder_fnRelease
*/
static ULONG WINAPI IShellFolder_fnRelease (IShellFolder2 * iface)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
return IUnknown_Release (This->pUnkOuter);
}
/**************************************************************************
* IShellFolder_fnParseDisplayName
* PARAMETERS
* HWND hwndOwner, //[in ] Parent window for any message's
* LPBC pbc, //[in ] reserved
* LPOLESTR lpszDisplayName,//[in ] "Unicode" displayname.
* ULONG* pchEaten, //[out] (unicode) characters processed
* LPITEMIDLIST* ppidl, //[out] complex pidl to item
* ULONG* pdwAttributes //[out] items attributes
*
* NOTES
* every folder tries to parse only its own (the leftmost) pidl and creates a
* subfolder to evaluate the remaining parts
* now we can parse into namespaces implemented by shell extensions
*
* behaviour on win98: lpszDisplayName=NULL -> chrash
* lpszDisplayName="" -> returns mycoputer-pidl
*
* FIXME:
* pdwAttributes: not set
* pchEaten: not set like in windows
*/
static HRESULT WINAPI
IShellFolder_fnParseDisplayName (IShellFolder2 * iface,
HWND hwndOwner,
LPBC pbcReserved,
LPOLESTR lpszDisplayName,
DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
HRESULT hr = E_OUTOFMEMORY;
LPCWSTR szNext = NULL;
WCHAR szElement[MAX_PATH];
CHAR szTempA[MAX_PATH],
szPath[MAX_PATH];
LPITEMIDLIST pidlTemp = NULL;
TRACE ("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
This, hwndOwner, pbcReserved, lpszDisplayName, debugstr_w (lpszDisplayName), pchEaten, ppidl, pdwAttributes);
if (!lpszDisplayName || !ppidl)
return E_INVALIDARG;
if (pchEaten)
*pchEaten = 0; /* strange but like the original */
if (*lpszDisplayName) {
/* get the next element */
szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
/* build the full pathname to the element */
WideCharToMultiByte (CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL);
lstrcpyA (szPath, This->sPathTarget);
PathAddBackslashA (szPath);
lstrcatA (szPath, szTempA);
/* get the pidl */
pidlTemp = SHSimpleIDListFromPathA (szPath);
if (pidlTemp) {
if (szNext && *szNext) {
/* try to analyse the next element */
hr = SHELL32_ParseNextElement (hwndOwner, iface, &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
} else {
/* it's the last element */
if (pdwAttributes && *pdwAttributes) {
SHELL32_GetItemAttributes (_IShellFolder_ (This), pidlTemp, pdwAttributes);
}
hr = S_OK;
}
}
}
if (!hr)
*ppidl = pidlTemp;
else
*ppidl = NULL;
TRACE ("(%p)->(-- pidl=%p ret=0x%08lx)\n", This, ppidl ? *ppidl : 0, hr);
return hr;
}
/**************************************************************************
* IShellFolder_fnEnumObjects
* PARAMETERS
* HWND hwndOwner, //[in ] Parent Window
* DWORD grfFlags, //[in ] SHCONTF enumeration mask
* LPENUMIDLIST* ppenumIDList //[out] IEnumIDList interface
*/
static HRESULT WINAPI
IShellFolder_fnEnumObjects (IShellFolder2 * iface, HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
TRACE ("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n", This, hwndOwner, dwFlags, ppEnumIDList);
*ppEnumIDList = IEnumIDList_Constructor (This->sPathTarget, dwFlags, EIDL_FILE);
TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList);
return *ppEnumIDList ? S_OK : E_OUTOFMEMORY;
}
/**************************************************************************
* IShellFolder_fnBindToObject
* PARAMETERS
* LPCITEMIDLIST pidl, //[in ] relative pidl to open
* LPBC pbc, //[in ] reserved
* REFIID riid, //[in ] Initial Interface
* LPVOID* ppvObject //[out] Interface*
*/
static HRESULT WINAPI
IShellFolder_fnBindToObject (IShellFolder2 * iface, LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
return SHELL32_BindToChild (This->pidlRoot, This->sPathTarget, pidl, riid, ppvOut);
}
/**************************************************************************
* IShellFolder_fnBindToStorage
* PARAMETERS
* LPCITEMIDLIST pidl, //[in ] complex pidl to store
* LPBC pbc, //[in ] reserved
* REFIID riid, //[in ] Initial storage interface
* LPVOID* ppvObject //[out] Interface* returned
*/
static HRESULT WINAPI
IShellFolder_fnBindToStorage (IShellFolder2 * iface, LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
*ppvOut = NULL;
return E_NOTIMPL;
}
/**************************************************************************
* IShellFolder_fnCompareIDs
*/
static HRESULT WINAPI
IShellFolder_fnCompareIDs (IShellFolder2 * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
int nReturn;
TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2);
nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2);
TRACE ("-- %i\n", nReturn);
return nReturn;
}
/**************************************************************************
* IShellFolder_fnCreateViewObject
*/
static HRESULT WINAPI
IShellFolder_fnCreateViewObject (IShellFolder2 * iface, HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
LPSHELLVIEW pShellView;
HRESULT hr = E_INVALIDARG;
TRACE ("(%p)->(hwnd=0x%x,%s,%p)\n", This, hwndOwner, shdebugstr_guid (riid), ppvOut);
if (ppvOut) {
*ppvOut = NULL;
if (IsEqualIID (riid, &IID_IDropTarget)) {
hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, ppvOut);
} else if (IsEqualIID (riid, &IID_IContextMenu)) {
FIXME ("IContextMenu not implemented\n");
hr = E_NOTIMPL;
} else if (IsEqualIID (riid, &IID_IShellView)) {
pShellView = IShellView_Constructor ((IShellFolder *) iface);
if (pShellView) {
hr = IShellView_QueryInterface (pShellView, riid, ppvOut);
IShellView_Release (pShellView);
}
}
}
TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut);
return hr;
}
/**************************************************************************
* IShellFolder_fnGetAttributesOf
*
* PARAMETERS
* UINT cidl, //[in ] num elements in pidl array
* LPCITEMIDLIST* apidl, //[in ] simple pidl array
* ULONG* rgfInOut) //[out] result array
*
*/
static HRESULT WINAPI
IShellFolder_fnGetAttributesOf (IShellFolder2 * iface, UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
HRESULT hr = S_OK;
TRACE ("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut);
if ((!cidl) || (!apidl) || (!rgfInOut))
return E_INVALIDARG;
while (cidl > 0 && *apidl) {
pdump (*apidl);
SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut);
apidl++;
cidl--;
}
TRACE ("-- result=0x%08lx\n", *rgfInOut);
return hr;
}
/**************************************************************************
* IShellFolder_fnGetUIObjectOf
*
* PARAMETERS
* HWND hwndOwner, //[in ] Parent window for any output
* UINT cidl, //[in ] array size
* LPCITEMIDLIST* apidl, //[in ] simple pidl array
* REFIID riid, //[in ] Requested Interface
* UINT* prgfInOut, //[ ] reserved
* LPVOID* ppvObject) //[out] Resulting Interface
*
* NOTES
* This function gets asked to return "view objects" for one or more (multiple select)
* items:
* The viewobject typically is an COM object with one of the following interfaces:
* IExtractIcon,IDataObject,IContextMenu
* In order to support icon positions in the default Listview your DataObject
* must implement the SetData method (in addition to GetData :) - the shell passes
* a barely documented "Icon positions" structure to SetData when the drag starts,
* and GetData's it if the drop is in another explorer window that needs the positions.
*/
static HRESULT WINAPI
IShellFolder_fnGetUIObjectOf (IShellFolder2 * iface,
HWND hwndOwner,
UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
LPITEMIDLIST pidl;
IUnknown *pObj = NULL;
HRESULT hr = E_INVALIDARG;
TRACE ("(%p)->(0x%04x,%u,apidl=%p,%s,%p,%p)\n",
This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut);
if (ppvOut) {
*ppvOut = NULL;
if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1)) {
pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl);
hr = S_OK;
} else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) {
pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl);
hr = S_OK;
} else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1)) {
pidl = ILCombine (This->pidlRoot, apidl[0]);
pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
SHFree (pidl);
hr = S_OK;
} else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) {
hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj);
} else {
hr = E_NOINTERFACE;
}
if (!pObj)
hr = E_OUTOFMEMORY;
*ppvOut = pObj;
}
TRACE ("(%p)->hr=0x%08lx\n", This, hr);
return hr;
}
/**************************************************************************
* IShellFolder_fnGetDisplayNameOf
* Retrieves the display name for the specified file object or subfolder
*
* PARAMETERS
* LPCITEMIDLIST pidl, //[in ] complex pidl to item
* DWORD dwFlags, //[in ] SHGNO formatting flags
* LPSTRRET lpName) //[out] Returned display name
*
* FIXME
* if the name is in the pidl the ret value should be a STRRET_OFFSET
*/
static HRESULT WINAPI
IShellFolder_fnGetDisplayNameOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
CHAR szPath[MAX_PATH] = "";
int len = 0;
BOOL bSimplePidl;
TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet);
pdump (pidl);
if (!pidl || !strRet)
return E_INVALIDARG;
bSimplePidl = _ILIsPidlSimple (pidl);
/* take names of special folders only if its only this folder */
if (_ILIsSpecialFolder (pidl)) {
if (bSimplePidl) {
_ILSimpleGetText (pidl, szPath, MAX_PATH); /* append my own path */
} else {
FIXME ("special pidl\n");
}
} else {
if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sPathTarget) {
lstrcpyA (szPath, This->sPathTarget); /* get path to root */
PathAddBackslashA (szPath);
len = lstrlenA (szPath);
}
_ILSimpleGetText (pidl, szPath + len, MAX_PATH - len); /* append my own path */
/* MSDN also mentions SHGDN_FOREDITING, which isn't defined in wine */
if (!_ILIsFolder (pidl) && !(dwFlags & SHGDN_FORPARSING) &&
((dwFlags & SHGDN_INFOLDER) || (dwFlags == SHGDN_NORMAL))) {
HKEY hKey;
DWORD dwData;
DWORD dwDataSize = sizeof (DWORD);
BOOL doHide = 0; /* The default value is FALSE (win98 at least) */
/* XXX should it do this only for known file types? -- that would make it even slower! */
/* XXX That's what the prompt says!! */
if (!RegCreateKeyExA (HKEY_CURRENT_USER,
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0)) {
if (!RegQueryValueExA (hKey, "HideFileExt", 0, 0, (LPBYTE) & dwData, &dwDataSize))
doHide = dwData;
RegCloseKey (hKey);
}
if (doHide && szPath[0] != '.')
PathRemoveExtensionA (szPath);
}
}
if ((dwFlags & SHGDN_FORPARSING) && !bSimplePidl) { /* go deeper if needed */
PathAddBackslashA (szPath);
len = lstrlenA (szPath);
if (!SUCCEEDED
(SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags | SHGDN_INFOLDER, szPath + len, MAX_PATH - len)))
return E_OUTOFMEMORY;
}
strRet->uType = STRRET_CSTR;
lstrcpynA (strRet->u.cStr, szPath, MAX_PATH);
TRACE ("-- (%p)->(%s)\n", This, szPath);
return S_OK;
}
/**************************************************************************
* IShellFolder_fnSetNameOf
* Changes the name of a file object or subfolder, possibly changing its item
* identifier in the process.
*
* PARAMETERS
* HWND hwndOwner, //[in ] Owner window for output
* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
* LPCOLESTR lpszName, //[in ] the items new display name
* DWORD dwFlags, //[in ] SHGNO formatting flags
* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
*/
static HRESULT WINAPI IShellFolder_fnSetNameOf (IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl, /*simple pidl */
LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
char szSrc[MAX_PATH],
szDest[MAX_PATH];
int len;
BOOL bIsFolder = _ILIsFolder (ILFindLastID (pidl));
TRACE ("(%p)->(%u,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
/* build source path */
if (dwFlags & SHGDN_INFOLDER) {
strcpy (szSrc, This->sPathTarget);
PathAddBackslashA (szSrc);
len = strlen (szSrc);
_ILSimpleGetText (pidl, szSrc + len, MAX_PATH - len);
} else {
SHGetPathFromIDListA (pidl, szSrc);
}
/* build destination path */
strcpy (szDest, This->sPathTarget);
PathAddBackslashA (szDest);
len = strlen (szDest);
WideCharToMultiByte (CP_ACP, 0, lpName, -1, szDest + len, MAX_PATH - len, NULL, NULL);
szDest[MAX_PATH - 1] = 0;
TRACE ("src=%s dest=%s\n", szSrc, szDest);
if (MoveFileA (szSrc, szDest)) {
if (pPidlOut)
*pPidlOut = SHSimpleIDListFromPathA (szDest);
SHChangeNotifyA (bIsFolder ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM, SHCNF_PATHA, szSrc, szDest);
return S_OK;
}
return E_FAIL;
}
static HRESULT WINAPI IShellFolder_fnGetDefaultSearchGUID (IShellFolder2 * iface, GUID * pguid)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
FIXME ("(%p)\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI IShellFolder_fnEnumSearches (IShellFolder2 * iface, IEnumExtraSearch ** ppenum)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
FIXME ("(%p)\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IShellFolder_fnGetDefaultColumn (IShellFolder2 * iface, DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
TRACE ("(%p)\n", This);
if (pSort)
*pSort = 0;
if (pDisplay)
*pDisplay = 0;
return S_OK;
}
static HRESULT WINAPI IShellFolder_fnGetDefaultColumnState (IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
TRACE ("(%p)\n", This);
if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS)
return E_INVALIDARG;
*pcsFlags = GenericSFHeader[iColumn].pcsFlags;
return S_OK;
}
static HRESULT WINAPI
IShellFolder_fnGetDetailsEx (IShellFolder2 * iface, LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
FIXME ("(%p)\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IShellFolder_fnGetDetailsOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
HRESULT hr = E_FAIL;
TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd);
if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS)
return E_INVALIDARG;
if (!pidl) {
/* the header titles */
psd->fmt = GenericSFHeader[iColumn].fmt;
psd->cxChar = GenericSFHeader[iColumn].cxChar;
psd->str.uType = STRRET_CSTR;
LoadStringA (shell32_hInstance, GenericSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
return S_OK;
} else {
/* the data from the pidl */
switch (iColumn) {
case 0: /* name */
hr = IShellFolder_GetDisplayNameOf (iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
break;
case 1: /* size */
_ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
break;
case 2: /* type */
_ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH);
break;
case 3: /* date */
_ILGetFileDate (pidl, psd->str.u.cStr, MAX_PATH);
break;
case 4: /* attributes */
_ILGetFileAttributes (pidl, psd->str.u.cStr, MAX_PATH);
break;
}
hr = S_OK;
psd->str.uType = STRRET_CSTR;
}
return hr;
}
static HRESULT WINAPI IShellFolder_fnMapNameToSCID (IShellFolder2 * iface, LPCWSTR pwszName, SHCOLUMNID * pscid)
{
_ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
FIXME ("(%p)\n", This);
return E_NOTIMPL;
}
static ICOM_VTABLE (IShellFolder2) sfvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IShellFolder_fnQueryInterface,
IShellFolder_fnAddRef,
IShellFolder_fnRelease,
IShellFolder_fnParseDisplayName,
IShellFolder_fnEnumObjects,
IShellFolder_fnBindToObject,
IShellFolder_fnBindToStorage,
IShellFolder_fnCompareIDs,
IShellFolder_fnCreateViewObject,
IShellFolder_fnGetAttributesOf,
IShellFolder_fnGetUIObjectOf,
IShellFolder_fnGetDisplayNameOf,
IShellFolder_fnSetNameOf,
/* ShellFolder2 */
IShellFolder_fnGetDefaultSearchGUID,
IShellFolder_fnEnumSearches,
IShellFolder_fnGetDefaultColumn,
IShellFolder_fnGetDefaultColumnState,
IShellFolder_fnGetDetailsEx,
IShellFolder_fnGetDetailsOf,
IShellFolder_fnMapNameToSCID
};
/****************************************************************************
* ISFHelper for IShellFolder implementation
*/
static HRESULT WINAPI ISFHelper_fnQueryInterface (ISFHelper * iface, REFIID riid, LPVOID * ppvObj)
{
_ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface);
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
return IUnknown_QueryInterface (This->pUnkOuter, riid, ppvObj);
}
static ULONG WINAPI ISFHelper_fnAddRef (ISFHelper * iface)
{
_ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface);
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
return IUnknown_AddRef (This->pUnkOuter);
}
static ULONG WINAPI ISFHelper_fnRelease (ISFHelper * iface)
{
_ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface);
TRACE ("(%p)\n", This);
return IUnknown_Release (This->pUnkOuter);
}
/****************************************************************************
* ISFHelper_fnAddFolder
*
* creates a unique folder name
*/
static HRESULT WINAPI ISFHelper_fnGetUniqueName (ISFHelper * iface, LPSTR lpName, UINT uLen)
{
_ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface)
IEnumIDList *penum;
HRESULT hr;
char szText[MAX_PATH];
char *szNewFolder = "New Folder";
TRACE ("(%p)(%s %u)\n", This, lpName, uLen);
if (uLen < strlen (szNewFolder) + 4)
return E_POINTER;
strcpy (lpName, szNewFolder);
hr = IShellFolder_fnEnumObjects (_IShellFolder2_ (This), 0,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
if (penum) {
LPITEMIDLIST pidl;
DWORD dwFetched;
int i = 1;
next:IEnumIDList_Reset (penum);
while (S_OK == IEnumIDList_Next (penum, 1, &pidl, &dwFetched) && dwFetched) {
_ILSimpleGetText (pidl, szText, MAX_PATH);
if (0 == strcasecmp (szText, lpName)) {
sprintf (lpName, "%s %d", szNewFolder, i++);
if (i > 99) {
hr = E_FAIL;
break;
}
goto next;
}
}
IEnumIDList_Release (penum);
}
return hr;
}
/****************************************************************************
* ISFHelper_fnAddFolder
*
* adds a new folder.
*/
static HRESULT WINAPI ISFHelper_fnAddFolder (ISFHelper * iface, HWND hwnd, LPCSTR lpName, LPITEMIDLIST * ppidlOut)
{
_ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface)
char lpstrNewDir[MAX_PATH];
DWORD bRes;
HRESULT hres = E_FAIL;
TRACE ("(%p)(%s %p)\n", This, lpName, ppidlOut);
strcpy (lpstrNewDir, This->sPathTarget);
PathAddBackslashA (lpstrNewDir);
strcat (lpstrNewDir, lpName);
bRes = CreateDirectoryA (lpstrNewDir, NULL);
if (bRes) {
LPITEMIDLIST pidl,
pidlitem;
pidlitem = SHSimpleIDListFromPathA (lpstrNewDir);
pidl = ILCombine (This->pidlRoot, pidlitem);
SHChangeNotifyA (SHCNE_MKDIR, SHCNF_IDLIST, pidl, NULL);
SHFree (pidl);
if (ppidlOut)
*ppidlOut = pidlitem;
hres = S_OK;
} else {
char lpstrText[128 + MAX_PATH];
char lpstrTempText[128];
char lpstrCaption[256];
/* Cannot Create folder because of permissions */
LoadStringA (shell32_hInstance, IDS_CREATEFOLDER_DENIED, lpstrTempText, sizeof (lpstrTempText));
LoadStringA (shell32_hInstance, IDS_CREATEFOLDER_CAPTION, lpstrCaption, sizeof (lpstrCaption));
sprintf (lpstrText, lpstrTempText, lpstrNewDir);
MessageBoxA (hwnd, lpstrText, lpstrCaption, MB_OK | MB_ICONEXCLAMATION);
}
return hres;
}
/****************************************************************************
* ISFHelper_fnDeleteItems
*
* deletes items in folder
*/
static HRESULT WINAPI ISFHelper_fnDeleteItems (ISFHelper * iface, UINT cidl, LPCITEMIDLIST * apidl)
{
_ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface)
int i;
char szPath[MAX_PATH];
BOOL bConfirm = TRUE;
TRACE ("(%p)(%u %p)\n", This, cidl, apidl);
/* deleting multiple items so give a slightly different warning */
if (cidl != 1) {
char tmp[8];
snprintf (tmp, sizeof (tmp), "%d", cidl);
if (!SHELL_WarnItemDelete (ASK_DELETE_MULTIPLE_ITEM, tmp))
return E_FAIL;
bConfirm = FALSE;
}
for (i = 0; i < cidl; i++) {
strcpy (szPath, This->sPathTarget);
PathAddBackslashA (szPath);
_ILSimpleGetText (apidl[i], szPath + strlen (szPath), MAX_PATH);
if (_ILIsFolder (apidl[i])) {
LPITEMIDLIST pidl;
TRACE ("delete %s\n", szPath);
if (!SHELL_DeleteDirectoryA (szPath, bConfirm)) {
TRACE ("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
return E_FAIL;
}
pidl = ILCombine (This->pidlRoot, apidl[i]);
SHChangeNotifyA (SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL);
SHFree (pidl);
} else if (_ILIsValue (apidl[i])) {
LPITEMIDLIST pidl;
TRACE ("delete %s\n", szPath);
if (!SHELL_DeleteFileA (szPath, bConfirm)) {
TRACE ("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
return E_FAIL;
}
pidl = ILCombine (This->pidlRoot, apidl[i]);
SHChangeNotifyA (SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL);
SHFree (pidl);
}
}
return S_OK;
}
/****************************************************************************
* ISFHelper_fnCopyItems
*
* copies items to this folder
*/
static HRESULT WINAPI
ISFHelper_fnCopyItems (ISFHelper * iface, IShellFolder * pSFFrom, UINT cidl, LPCITEMIDLIST * apidl)
{
int i;
IPersistFolder2 *ppf2 = NULL;
char szSrcPath[MAX_PATH],
szDstPath[MAX_PATH];
_ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface);
TRACE ("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl);
IShellFolder_QueryInterface (pSFFrom, &IID_IPersistFolder2, (LPVOID *) & ppf2);
if (ppf2) {
LPITEMIDLIST pidl;
if (SUCCEEDED (IPersistFolder2_GetCurFolder (ppf2, &pidl))) {
for (i = 0; i < cidl; i++) {
SHGetPathFromIDListA (pidl, szSrcPath);
PathAddBackslashA (szSrcPath);
_ILSimpleGetText (apidl[i], szSrcPath + strlen (szSrcPath), MAX_PATH);
strcpy (szDstPath, This->sPathTarget);
PathAddBackslashA (szDstPath);
_ILSimpleGetText (apidl[i], szDstPath + strlen (szDstPath), MAX_PATH);
MESSAGE ("would copy %s to %s\n", szSrcPath, szDstPath);
}
SHFree (pidl);
}
IPersistFolder2_Release (ppf2);
}
return S_OK;
}
static ICOM_VTABLE (ISFHelper) shvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
ISFHelper_fnQueryInterface,
ISFHelper_fnAddRef,
ISFHelper_fnRelease,
ISFHelper_fnGetUniqueName,
ISFHelper_fnAddFolder,
ISFHelper_fnDeleteItems,
ISFHelper_fnCopyItems
};
/************************************************************************
* IFSFldr_PersistFolder3_QueryInterface
*
*/
static HRESULT WINAPI IFSFldr_PersistFolder3_QueryInterface (IPersistFolder3 * iface, REFIID iid, LPVOID * ppvObj)
{
_ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
TRACE ("(%p)\n", This);
return IUnknown_QueryInterface (This->pUnkOuter, iid, ppvObj);
}
/************************************************************************
* IFSFldr_PersistFolder3_AddRef
*
*/
static ULONG WINAPI IFSFldr_PersistFolder3_AddRef (IPersistFolder3 * iface)
{
_ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
return IUnknown_AddRef (This->pUnkOuter);
}
/************************************************************************
* IFSFldr_PersistFolder3_Release
*
*/
static ULONG WINAPI IFSFldr_PersistFolder3_Release (IPersistFolder3 * iface)
{
_ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
return IUnknown_Release (This->pUnkOuter);
}
/************************************************************************
* IFSFldr_PersistFolder3_GetClassID
*/
static HRESULT WINAPI IFSFldr_PersistFolder3_GetClassID (IPersistFolder3 * iface, CLSID * lpClassId)
{
_ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
TRACE ("(%p)\n", This);
if (!lpClassId)
return E_POINTER;
*lpClassId = *This->pclsid;
return S_OK;
}
/************************************************************************
* IFSFldr_PersistFolder3_Initialize
*
* NOTES
* sPathTarget is not set. Don't know how to handle in a non rooted environment.
*/
static HRESULT WINAPI IFSFldr_PersistFolder3_Initialize (IPersistFolder3 * iface, LPCITEMIDLIST pidl)
{
char sTemp[MAX_PATH];
_ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
TRACE ("(%p)->(%p)\n", This, pidl);
if (This->pidlRoot)
SHFree (This->pidlRoot); /* free the old pidl */
This->pidlRoot = ILClone (pidl); /* set my pidl */
if (This->sPathTarget)
SHFree (This->sPathTarget);
/* set my path */
if (SHGetPathFromIDListA (pidl, sTemp)) {
This->sPathTarget = SHAlloc (strlen (sTemp) + 1);
strcpy (This->sPathTarget, sTemp);
}
TRACE ("--(%p)->(%s)\n", This, This->sPathTarget);
return S_OK;
}
/**************************************************************************
* IFSFldr_PersistFolder3_GetCurFolder
*/
static HRESULT WINAPI IFSFldr_PersistFolder3_fnGetCurFolder (IPersistFolder3 * iface, LPITEMIDLIST * pidl)
{
_ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
TRACE ("(%p)->(%p)\n", This, pidl);
if (!pidl) return E_POINTER;
*pidl = ILClone (This->pidlRoot);
return S_OK;
}
/**************************************************************************
* IFSFldr_PersistFolder3_InitializeEx
*
* FIXME: errorhandling
*/
static HRESULT WINAPI
IFSFldr_PersistFolder3_InitializeEx (IPersistFolder3 * iface,
IBindCtx * pbc, LPCITEMIDLIST pidlRoot, const PERSIST_FOLDER_TARGET_INFO * ppfti)
{
char sTemp[MAX_PATH];
_ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
TRACE ("(%p)->(%p,%p,%p)\n", This, pbc, pidlRoot, ppfti);
if (ppfti)
TRACE ("--%p %s %s 0x%08lx 0x%08x\n",
ppfti->pidlTargetFolder, debugstr_w (ppfti->szTargetParsingName),
debugstr_w (ppfti->szNetworkProvider), ppfti->dwAttributes, ppfti->csidl);
pdump (pidlRoot);
if (ppfti && ppfti->pidlTargetFolder)
pdump (ppfti->pidlTargetFolder);
if (This->pidlRoot)
__SHFreeAndNil (&This->pidlRoot); /* free the old */
if (This->sPathTarget)
__SHFreeAndNil (&This->sPathTarget);
/*
* Root path and pidl
*/
This->pidlRoot = ILClone (pidlRoot);
/*
* the target folder is spezified in csidl OR pidlTargetFolder OR szTargetParsingName
*/
if (ppfti) {
if (ppfti->csidl != -1) {
if (SHGetSpecialFolderPathA (0, sTemp, ppfti->csidl, ppfti->csidl & CSIDL_FLAG_CREATE)) {
__SHCloneStrA (&This->sPathTarget, sTemp);
}
} else if (ppfti->szTargetParsingName[0]) {
__SHCloneStrWtoA (&This->sPathTarget, ppfti->szTargetParsingName);
} else if (ppfti->pidlTargetFolder) {
if (SHGetPathFromIDListA (ppfti->pidlTargetFolder, sTemp)) {
__SHCloneStrA (&This->sPathTarget, sTemp);
}
}
}
TRACE ("--(%p)->(target=%s)\n", This, debugstr_a (This->sPathTarget));
pdump (This->pidlRoot);
return (This->sPathTarget) ? S_OK : E_FAIL;
}
static HRESULT WINAPI
IFSFldr_PersistFolder3_GetFolderTargetInfo (IPersistFolder3 * iface, PERSIST_FOLDER_TARGET_INFO * ppfti)
{
_ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
FIXME ("(%p)->(%p)\n", This, ppfti);
ZeroMemory (ppfti, sizeof (ppfti));
return E_NOTIMPL;
}
static ICOM_VTABLE (IPersistFolder3) vt_FSFldr_PersistFolder3 =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IFSFldr_PersistFolder3_QueryInterface,
IFSFldr_PersistFolder3_AddRef,
IFSFldr_PersistFolder3_Release,
IFSFldr_PersistFolder3_GetClassID,
IFSFldr_PersistFolder3_Initialize,
IFSFldr_PersistFolder3_fnGetCurFolder,
IFSFldr_PersistFolder3_InitializeEx,
IFSFldr_PersistFolder3_GetFolderTargetInfo
};
/****************************************************************************
* ISFDropTarget implementation
*/
static BOOL ISFDropTarget_QueryDrop (IDropTarget * iface, DWORD dwKeyState, LPDWORD pdwEffect)
{
DWORD dwEffect = *pdwEffect;
_ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
*pdwEffect = DROPEFFECT_NONE;
if (This->fAcceptFmt) { /* Does our interpretation of the keystate ... */
*pdwEffect = KeyStateToDropEffect (dwKeyState);
/* ... matches the desired effect ? */
if (dwEffect & *pdwEffect) {
return TRUE;
}
}
return FALSE;
}
static HRESULT WINAPI ISFDropTarget_QueryInterface (IDropTarget * iface, REFIID riid, LPVOID * ppvObj)
{
_ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
TRACE ("(%p)\n", This);
return IUnknown_QueryInterface (This->pUnkOuter, riid, ppvObj);
}
static ULONG WINAPI ISFDropTarget_AddRef (IDropTarget * iface)
{
_ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
TRACE ("(%p)\n", This);
return IUnknown_AddRef (This->pUnkOuter);
}
static ULONG WINAPI ISFDropTarget_Release (IDropTarget * iface)
{
_ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
TRACE ("(%p)\n", This);
return IUnknown_Release (This->pUnkOuter);
}
static HRESULT WINAPI
ISFDropTarget_DragEnter (IDropTarget * iface, IDataObject * pDataObject, DWORD dwKeyState, POINTL pt, DWORD * pdwEffect)
{
FORMATETC fmt;
_ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
TRACE ("(%p)->(DataObject=%p)\n", This, pDataObject);
InitFormatEtc (fmt, This->cfShellIDList, TYMED_HGLOBAL);
This->fAcceptFmt = (S_OK == IDataObject_QueryGetData (pDataObject, &fmt)) ? TRUE : FALSE;
ISFDropTarget_QueryDrop (iface, dwKeyState, pdwEffect);
return S_OK;
}
static HRESULT WINAPI ISFDropTarget_DragOver (IDropTarget * iface, DWORD dwKeyState, POINTL pt, DWORD * pdwEffect)
{
_ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
TRACE ("(%p)\n", This);
if (!pdwEffect)
return E_INVALIDARG;
ISFDropTarget_QueryDrop (iface, dwKeyState, pdwEffect);
return S_OK;
}
static HRESULT WINAPI ISFDropTarget_DragLeave (IDropTarget * iface)
{
_ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
TRACE ("(%p)\n", This);
This->fAcceptFmt = FALSE;
return S_OK;
}
static HRESULT WINAPI
ISFDropTarget_Drop (IDropTarget * iface, IDataObject * pDataObject, DWORD dwKeyState, POINTL pt, DWORD * pdwEffect)
{
_ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
FIXME ("(%p) object dropped\n", This);
return E_NOTIMPL;
}
static struct ICOM_VTABLE (IDropTarget) dtvt = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
ISFDropTarget_QueryInterface,
ISFDropTarget_AddRef,
ISFDropTarget_Release,
ISFDropTarget_DragEnter,
ISFDropTarget_DragOver,
ISFDropTarget_DragLeave,
ISFDropTarget_Drop
};
/*
* Virtual Workplace folder
*
* Copyright 1997 Marcus Meissner
* Copyright 1998, 1999, 2002 Juergen Schmied
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "winerror.h"
#include "winbase.h"
#include "winreg.h"
#include "oleidl.h"
#include "shlguid.h"
#include "pidl.h"
#include "wine/obj_base.h"
#include "wine/obj_dragdrop.h"
#include "wine/obj_shellfolder.h"
#include "undocshell.h"
#include "shell32_main.h"
#include "shresdef.h"
#include "shlwapi.h"
#include "shellfolder.h"
#include "wine/debug.h"
#include "debughlp.h"
#include "shfldr.h"
WINE_DEFAULT_DEBUG_CHANNEL (shell);
/***********************************************************************
* IShellFolder implementation
*/
typedef struct {
ICOM_VFIELD (IShellFolder2);
DWORD ref;
ICOM_VTABLE (IPersistFolder2) * lpVtblPersistFolder2;
/* both paths are parsible from the desktop */
LPITEMIDLIST pidlRoot; /* absolute pidl */
int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */
} IGenericSFImpl;
static struct ICOM_VTABLE (IShellFolder2) vt_ShellFolder2;
static struct ICOM_VTABLE (IPersistFolder2) vt_PersistFolder2;
HRESULT WINAPI ISF_MyComputer_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
#define _IPersistFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpVtblPersistFolder2)))
#define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder2_Offset);
/*
converts This to a interface pointer
*/
#define _IUnknown_(This) (IUnknown*)&(This->lpVtbl)
#define _IShellFolder_(This) (IShellFolder*)&(This->lpVtbl)
#define _IShellFolder2_(This) (IShellFolder2*)&(This->lpVtbl)
#define _IPersist_(This) (IPersist*)&(This->lpVtblPersistFolder2)
#define _IPersistFolder_(This) (IPersistFolder*)&(This->lpVtblPersistFolder2)
#define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpVtblPersistFolder2)
/***********************************************************************
* IShellFolder [MyComputer] implementation
*/
static shvheader MyComputerSFHeader[] = {
{IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
{IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
{IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
{IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
};
#define MYCOMPUTERSHELLVIEWCOLUMNS 4
/**************************************************************************
* ISF_MyComputer_Constructor
*/
HRESULT WINAPI ISF_MyComputer_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
{
IGenericSFImpl *sf;
TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));
if (!ppv)
return E_POINTER;
if (pUnkOuter)
return CLASS_E_NOAGGREGATION;
sf = (IGenericSFImpl *) LocalAlloc (GMEM_ZEROINIT, sizeof (IGenericSFImpl));
if (!sf)
return E_OUTOFMEMORY;
sf->ref = 0;
ICOM_VTBL (sf) = &vt_ShellFolder2;
sf->lpVtblPersistFolder2 = &vt_PersistFolder2;
sf->pidlRoot = _ILCreateMyComputer (); /* my qualified pidl */
if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv))) {
IUnknown_Release (_IUnknown_ (sf));
return E_NOINTERFACE;
}
TRACE ("--(%p)\n", sf);
return S_OK;
}
/**************************************************************************
* ISF_MyComputer_fnQueryInterface
*
* NOTES supports not IPersist/IPersistFolder
*/
static HRESULT WINAPI ISF_MyComputer_fnQueryInterface (IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);
*ppvObj = NULL;
if (IsEqualIID (riid, &IID_IUnknown) ||
IsEqualIID (riid, &IID_IShellFolder) || IsEqualIID (riid, &IID_IShellFolder2)) {
*ppvObj = This;
} else if (IsEqualIID (riid, &IID_IPersist) ||
IsEqualIID (riid, &IID_IPersistFolder) || IsEqualIID (riid, &IID_IPersistFolder2)) {
*ppvObj = _IPersistFolder2_ (This);
}
if (*ppvObj) {
IUnknown_AddRef ((IUnknown *) (*ppvObj));
TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj);
return S_OK;
}
TRACE ("-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
static ULONG WINAPI ISF_MyComputer_fnAddRef (IShellFolder2 * iface)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
return ++(This->ref);
}
static ULONG WINAPI ISF_MyComputer_fnRelease (IShellFolder2 * iface)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
if (!--(This->ref)) {
TRACE ("-- destroying IShellFolder(%p)\n", This);
if (This->pidlRoot)
SHFree (This->pidlRoot);
LocalFree ((HLOCAL) This);
}
return This->ref;
}
/**************************************************************************
* ISF_MyComputer_fnParseDisplayName
*/
static HRESULT WINAPI
ISF_MyComputer_fnParseDisplayName (IShellFolder2 * iface,
HWND hwndOwner,
LPBC pbcReserved,
LPOLESTR lpszDisplayName,
DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
{
ICOM_THIS (IGenericSFImpl, iface);
HRESULT hr = E_OUTOFMEMORY;
LPCWSTR szNext = NULL;
WCHAR szElement[MAX_PATH];
CHAR szTempA[MAX_PATH];
LPITEMIDLIST pidlTemp;
TRACE ("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
This, hwndOwner, pbcReserved, lpszDisplayName, debugstr_w (lpszDisplayName), pchEaten, ppidl, pdwAttributes);
*ppidl = 0;
if (pchEaten)
*pchEaten = 0; /* strange but like the original */
/* do we have an absolute path name ? */
if (PathGetDriveNumberW (lpszDisplayName) >= 0 && lpszDisplayName[2] == (WCHAR) '\\') {
szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
WideCharToMultiByte (CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL);
pidlTemp = _ILCreateDrive (szTempA);
if (szNext && *szNext) {
hr = SHELL32_ParseNextElement (hwndOwner, iface, &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
} else {
if (pdwAttributes && *pdwAttributes) {
SHELL32_GetItemAttributes (_IShellFolder_ (This), pidlTemp, pdwAttributes);
}
hr = S_OK;
}
*ppidl = pidlTemp;
}
TRACE ("(%p)->(-- ret=0x%08lx)\n", This, hr);
return hr;
}
/**************************************************************************
* ISF_MyComputer_fnEnumObjects
*/
static HRESULT WINAPI
ISF_MyComputer_fnEnumObjects (IShellFolder2 * iface, HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n", This, hwndOwner, dwFlags, ppEnumIDList);
*ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_MYCOMP);
TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList);
return (*ppEnumIDList) ? S_OK : E_OUTOFMEMORY;
}
/**************************************************************************
* ISF_MyComputer_fnBindToObject
*/
static HRESULT WINAPI
ISF_MyComputer_fnBindToObject (IShellFolder2 * iface, LPCITEMIDLIST pidl,
LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
return SHELL32_BindToChild (This->pidlRoot, NULL, pidl, riid, ppvOut);
}
/**************************************************************************
* ISF_MyComputer_fnBindToStorage
*/
static HRESULT WINAPI
ISF_MyComputer_fnBindToStorage (IShellFolder2 * iface,
LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
{
ICOM_THIS (IGenericSFImpl, iface);
FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
*ppvOut = NULL;
return E_NOTIMPL;
}
/**************************************************************************
* ISF_MyComputer_fnCompareIDs
*/
static HRESULT WINAPI
ISF_MyComputer_fnCompareIDs (IShellFolder2 * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
{
ICOM_THIS (IGenericSFImpl, iface);
int nReturn;
TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2);
nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2);
TRACE ("-- %i\n", nReturn);
return nReturn;
}
/**************************************************************************
* ISF_MyComputer_fnCreateViewObject
*/
static HRESULT WINAPI
ISF_MyComputer_fnCreateViewObject (IShellFolder2 * iface, HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
{
ICOM_THIS (IGenericSFImpl, iface);
LPSHELLVIEW pShellView;
HRESULT hr = E_INVALIDARG;
TRACE ("(%p)->(hwnd=0x%x,%s,%p)\n", This, hwndOwner, shdebugstr_guid (riid), ppvOut);
if (ppvOut) {
*ppvOut = NULL;
if (IsEqualIID (riid, &IID_IDropTarget)) {
WARN ("IDropTarget not implemented\n");
hr = E_NOTIMPL;
} else if (IsEqualIID (riid, &IID_IContextMenu)) {
WARN ("IContextMenu not implemented\n");
hr = E_NOTIMPL;
} else if (IsEqualIID (riid, &IID_IShellView)) {
pShellView = IShellView_Constructor ((IShellFolder *) iface);
if (pShellView) {
hr = IShellView_QueryInterface (pShellView, riid, ppvOut);
IShellView_Release (pShellView);
}
}
}
TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut);
return hr;
}
/**************************************************************************
* ISF_MyComputer_fnGetAttributesOf
*/
static HRESULT WINAPI
ISF_MyComputer_fnGetAttributesOf (IShellFolder2 * iface, UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
{
ICOM_THIS (IGenericSFImpl, iface);
HRESULT hr = S_OK;
TRACE ("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut);
if ((!cidl) || (!apidl) || (!rgfInOut))
return E_INVALIDARG;
while (cidl > 0 && *apidl) {
pdump (*apidl);
SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut);
apidl++;
cidl--;
}
TRACE ("-- result=0x%08lx\n", *rgfInOut);
return hr;
}
/**************************************************************************
* ISF_MyComputer_fnGetUIObjectOf
*
* PARAMETERS
* HWND hwndOwner, //[in ] Parent window for any output
* UINT cidl, //[in ] array size
* LPCITEMIDLIST* apidl, //[in ] simple pidl array
* REFIID riid, //[in ] Requested Interface
* UINT* prgfInOut, //[ ] reserved
* LPVOID* ppvObject) //[out] Resulting Interface
*
*/
static HRESULT WINAPI
ISF_MyComputer_fnGetUIObjectOf (IShellFolder2 * iface,
HWND hwndOwner,
UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
{
ICOM_THIS (IGenericSFImpl, iface);
LPITEMIDLIST pidl;
IUnknown *pObj = NULL;
HRESULT hr = E_INVALIDARG;
TRACE ("(%p)->(0x%04x,%u,apidl=%p,%s,%p,%p)\n",
This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut);
if (ppvOut) {
*ppvOut = NULL;
if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1)) {
pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl);
hr = S_OK;
} else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) {
pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl);
hr = S_OK;
} else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1)) {
pidl = ILCombine (This->pidlRoot, apidl[0]);
pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
SHFree (pidl);
hr = S_OK;
} else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) {
hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj);
} else {
hr = E_NOINTERFACE;
}
if (!pObj)
hr = E_OUTOFMEMORY;
*ppvOut = pObj;
}
TRACE ("(%p)->hr=0x%08lx\n", This, hr);
return hr;
}
/**************************************************************************
* ISF_MyComputer_fnGetDisplayNameOf
*
* NOTES
* The desktopfolder creates only complete paths (SHGDN_FORPARSING).
* SHGDN_INFOLDER makes no sense.
*/
static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
{
ICOM_THIS (IGenericSFImpl, iface);
char szPath[MAX_PATH],
szDrive[18];
int len = 0;
BOOL bSimplePidl;
TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet);
pdump (pidl);
if (!strRet)
return E_INVALIDARG;
szPath[0] = 0x00;
szDrive[0] = 0x00;
bSimplePidl = _ILIsPidlSimple (pidl);
if (_ILIsSpecialFolder (pidl)) {
/* take names of special folders only if its only this folder */
if (bSimplePidl) {
_ILSimpleGetText (pidl, szPath, MAX_PATH); /* append my own path */
} else {
FIXME ("special folder\n");
}
} else {
if (!_ILIsDrive (pidl)) {
ERR ("Wrong pidl type\n");
return E_INVALIDARG;
}
_ILSimpleGetText (pidl, szPath, MAX_PATH); /* append my own path */
/* long view "lw_name (C:)" */
if (bSimplePidl && !(dwFlags & SHGDN_FORPARSING)) {
DWORD dwVolumeSerialNumber,
dwMaximumComponetLength,
dwFileSystemFlags;
GetVolumeInformationA (szPath, szDrive, sizeof (szDrive) - 6, &dwVolumeSerialNumber,
&dwMaximumComponetLength, &dwFileSystemFlags, NULL, 0);
strcat (szDrive, " (");
strncat (szDrive, szPath, 2);
strcat (szDrive, ")");
strcpy (szPath, szDrive);
}
}
if (!bSimplePidl) { /* go deeper if needed */
PathAddBackslashA (szPath);
len = strlen (szPath);
if (!SUCCEEDED
(SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags | SHGDN_INFOLDER, szPath + len, MAX_PATH - len)))
return E_OUTOFMEMORY;
}
strRet->uType = STRRET_CSTR;
lstrcpynA (strRet->u.cStr, szPath, MAX_PATH);
TRACE ("-- (%p)->(%s)\n", This, szPath);
return S_OK;
}
/**************************************************************************
* ISF_MyComputer_fnSetNameOf
* Changes the name of a file object or subfolder, possibly changing its item
* identifier in the process.
*
* PARAMETERS
* HWND hwndOwner, //[in ] Owner window for output
* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
* LPCOLESTR lpszName, //[in ] the items new display name
* DWORD dwFlags, //[in ] SHGNO formatting flags
* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
*/
static HRESULT WINAPI ISF_MyComputer_fnSetNameOf (IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl, /*simple pidl */
LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
{
ICOM_THIS (IGenericSFImpl, iface);
FIXME ("(%p)->(%u,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
return E_FAIL;
}
static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID (IShellFolder2 * iface, GUID * pguid)
{
ICOM_THIS (IGenericSFImpl, iface);
FIXME ("(%p)\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI ISF_MyComputer_fnEnumSearches (IShellFolder2 * iface, IEnumExtraSearch ** ppenum)
{
ICOM_THIS (IGenericSFImpl, iface);
FIXME ("(%p)\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn (IShellFolder2 * iface, DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)\n", This);
if (pSort) *pSort = 0;
if (pDisplay) *pDisplay = 0;
return S_OK;
}
static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState (IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags)
{
ICOM_THIS (IGenericSFImpl, iface);
TRACE ("(%p)\n", This);
if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS) return E_INVALIDARG;
*pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
return S_OK;
}
static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx (IShellFolder2 * iface, LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
{
ICOM_THIS (IGenericSFImpl, iface);
FIXME ("(%p)\n", This);
return E_NOTIMPL;
}
/* FIXME: drive size >4GB is rolling over */
static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd)
{
ICOM_THIS (IGenericSFImpl, iface);
HRESULT hr;
TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd);
if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS)
return E_INVALIDARG;
if (!pidl) {
psd->fmt = MyComputerSFHeader[iColumn].fmt;
psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
psd->str.uType = STRRET_CSTR;
LoadStringA (shell32_hInstance, MyComputerSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
return S_OK;
} else {
char szPath[MAX_PATH];
ULARGE_INTEGER ulBytes;
psd->str.u.cStr[0] = 0x00;
psd->str.uType = STRRET_CSTR;
switch (iColumn) {
case 0: /* name */
hr = IShellFolder_GetDisplayNameOf (iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
break;
case 1: /* type */
_ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH);
break;
case 2: /* total size */
if (_ILIsDrive (pidl)) {
_ILSimpleGetText (pidl, szPath, MAX_PATH);
GetDiskFreeSpaceExA (szPath, NULL, &ulBytes, NULL);
StrFormatByteSizeA (ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
}
break;
case 3: /* free size */
if (_ILIsDrive (pidl)) {
_ILSimpleGetText (pidl, szPath, MAX_PATH);
GetDiskFreeSpaceExA (szPath, &ulBytes, NULL, NULL);
StrFormatByteSizeA (ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
}
break;
}
hr = S_OK;
}
return hr;
}
static HRESULT WINAPI ISF_MyComputer_fnMapNameToSCID (IShellFolder2 * iface, LPCWSTR pwszName, SHCOLUMNID * pscid)
{
ICOM_THIS (IGenericSFImpl, iface);
FIXME ("(%p)\n", This);
return E_NOTIMPL;
}
static ICOM_VTABLE (IShellFolder2) vt_ShellFolder2 =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
ISF_MyComputer_fnQueryInterface,
ISF_MyComputer_fnAddRef,
ISF_MyComputer_fnRelease,
ISF_MyComputer_fnParseDisplayName,
ISF_MyComputer_fnEnumObjects,
ISF_MyComputer_fnBindToObject,
ISF_MyComputer_fnBindToStorage,
ISF_MyComputer_fnCompareIDs,
ISF_MyComputer_fnCreateViewObject,
ISF_MyComputer_fnGetAttributesOf,
ISF_MyComputer_fnGetUIObjectOf,
ISF_MyComputer_fnGetDisplayNameOf,
ISF_MyComputer_fnSetNameOf,
/* ShellFolder2 */
ISF_MyComputer_fnGetDefaultSearchGUID,
ISF_MyComputer_fnEnumSearches,
ISF_MyComputer_fnGetDefaultColumn,
ISF_MyComputer_fnGetDefaultColumnState,
ISF_MyComputer_fnGetDetailsEx,
ISF_MyComputer_fnGetDetailsOf,
ISF_MyComputer_fnMapNameToSCID
};
/************************************************************************
* IMCFldr_PersistFolder2_QueryInterface
*/
static HRESULT WINAPI IMCFldr_PersistFolder2_QueryInterface (IPersistFolder2 * iface, REFIID iid, LPVOID * ppvObj)
{
_ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
TRACE ("(%p)\n", This);
return IUnknown_QueryInterface (_IUnknown_ (This), iid, ppvObj);
}
/************************************************************************
* IMCFldr_PersistFolder2_AddRef
*/
static ULONG WINAPI IMCFldr_PersistFolder2_AddRef (IPersistFolder2 * iface)
{
_ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
return IUnknown_AddRef (_IUnknown_ (This));
}
/************************************************************************
* ISFPersistFolder_Release
*/
static ULONG WINAPI IMCFldr_PersistFolder2_Release (IPersistFolder2 * iface)
{
_ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
return IUnknown_Release (_IUnknown_ (This));
}
/************************************************************************
* IMCFldr_PersistFolder2_GetClassID
*/
static HRESULT WINAPI IMCFldr_PersistFolder2_GetClassID (IPersistFolder2 * iface, CLSID * lpClassId)
{
_ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
TRACE ("(%p)\n", This);
if (!lpClassId)
return E_POINTER;
*lpClassId = CLSID_MyComputer;
return S_OK;
}
/************************************************************************
* IMCFldr_PersistFolder2_Initialize
*
* NOTES: it makes no sense to change the pidl
*/
static HRESULT WINAPI IMCFldr_PersistFolder2_Initialize (IPersistFolder2 * iface, LPCITEMIDLIST pidl)
{
_ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
TRACE ("(%p)->(%p)\n", This, pidl);
return E_NOTIMPL;
}
/**************************************************************************
* IPersistFolder2_fnGetCurFolder
*/
static HRESULT WINAPI IMCFldr_PersistFolder2_GetCurFolder (IPersistFolder2 * iface, LPITEMIDLIST * pidl)
{
_ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
TRACE ("(%p)->(%p)\n", This, pidl);
if (!pidl)
return E_POINTER;
*pidl = ILClone (This->pidlRoot);
return S_OK;
}
static ICOM_VTABLE (IPersistFolder2) vt_PersistFolder2 =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IMCFldr_PersistFolder2_QueryInterface,
IMCFldr_PersistFolder2_AddRef,
IMCFldr_PersistFolder2_Release,
IMCFldr_PersistFolder2_GetClassID,
IMCFldr_PersistFolder2_Initialize,
IMCFldr_PersistFolder2_GetCurFolder
};
/*
* Shell Folder stuff
*
* Copyright 1997 Marcus Meissner
* Copyright 1998, 1999 Juergen Schmied
* Copyright 1997 Marcus Meissner
* Copyright 1998, 1999, 2002 Juergen Schmied
*
* IShellFolder2 and related interfaces
*
......@@ -46,9 +47,9 @@
#include "shellfolder.h"
#include "wine/debug.h"
#include "debughlp.h"
#include "shfldr.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
WINE_DEFAULT_DEBUG_CHANNEL (shell);
/***************************************************************************
* debughelper: print out the return adress
......@@ -62,15 +63,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell);
#define _CALL_TRACE
#endif
typedef struct
{
int colnameid;
int pcsFlags;
int fmt;
int cxChar;
} shvheader;
/***************************************************************************
* GetNextElement (internal function)
*
......@@ -85,2820 +77,355 @@ typedef struct
* LPSTR pointer to first, not yet parsed char
*/
static LPCWSTR GetNextElementW(LPCWSTR pszNext,LPWSTR pszOut,DWORD dwOut)
{ LPCWSTR pszTail = pszNext;
DWORD dwCopy;
TRACE("(%s %p 0x%08lx)\n",debugstr_w(pszNext),pszOut,dwOut);
LPCWSTR GetNextElementW (LPCWSTR pszNext, LPWSTR pszOut, DWORD dwOut)
{
LPCWSTR pszTail = pszNext;
DWORD dwCopy;
TRACE ("(%s %p 0x%08lx)\n", debugstr_w (pszNext), pszOut, dwOut);
*pszOut=0x0000;
*pszOut = 0x0000;
if(!pszNext || !*pszNext)
return NULL;
if (!pszNext || !*pszNext)
return NULL;
while(*pszTail && (*pszTail != (WCHAR)'\\'))
pszTail++;
while (*pszTail && (*pszTail != (WCHAR) '\\'))
pszTail++;
dwCopy = (WCHAR*)pszTail - (WCHAR*)pszNext + 1;
lstrcpynW(pszOut, pszNext, (dwOut<dwCopy)? dwOut : dwCopy);
dwCopy = (WCHAR *) pszTail - (WCHAR *) pszNext + 1;
lstrcpynW (pszOut, pszNext, (dwOut < dwCopy) ? dwOut : dwCopy);
if(*pszTail)
pszTail++;
else
pszTail = NULL;
if (*pszTail)
pszTail++;
else
pszTail = NULL;
TRACE("--(%s %s 0x%08lx %p)\n",debugstr_w(pszNext),debugstr_w(pszOut),dwOut,pszTail);
return pszTail;
TRACE ("--(%s %s 0x%08lx %p)\n", debugstr_w (pszNext), debugstr_w (pszOut), dwOut, pszTail);
return pszTail;
}
static HRESULT SHELL32_ParseNextElement(
HWND hwndOwner,
IShellFolder2 * psf,
LPITEMIDLIST * pidlInOut,
LPOLESTR szNext,
DWORD *pEaten,
DWORD *pdwAttributes)
HRESULT SHELL32_ParseNextElement (HWND hwndOwner,
IShellFolder2 * psf,
LPITEMIDLIST * pidlInOut, LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes)
{
HRESULT hr = E_OUTOFMEMORY;
LPITEMIDLIST pidlOut = NULL, pidlTemp = NULL;
IShellFolder *psfChild;
TRACE("(%p, %p, %s)\n",psf, pidlInOut ? *pidlInOut : NULL, debugstr_w(szNext));
HRESULT hr = E_OUTOFMEMORY;
LPITEMIDLIST pidlOut = NULL,
pidlTemp = NULL;
IShellFolder *psfChild;
TRACE ("(%p, %p, %s)\n", psf, pidlInOut ? *pidlInOut : NULL, debugstr_w (szNext));
/* get the shellfolder for the child pidl and let it analyse further */
hr = IShellFolder_BindToObject(psf, *pidlInOut, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
/* get the shellfolder for the child pidl and let it analyse further */
hr = IShellFolder_BindToObject (psf, *pidlInOut, NULL, &IID_IShellFolder, (LPVOID *) & psfChild);
if (psfChild)
{
hr = IShellFolder_ParseDisplayName(psfChild, hwndOwner, NULL, szNext, pEaten, &pidlOut, pdwAttributes);
IShellFolder_Release(psfChild);
if (SUCCEEDED (hr)) {
hr = IShellFolder_ParseDisplayName (psfChild, hwndOwner, NULL, szNext, pEaten, &pidlOut, pdwAttributes);
IShellFolder_Release (psfChild);
pidlTemp = ILCombine(*pidlInOut, pidlOut);
pidlTemp = ILCombine (*pidlInOut, pidlOut);
if (pidlOut)
ILFree(pidlOut);
}
if (pidlOut)
ILFree (pidlOut);
}
ILFree(*pidlInOut);
*pidlInOut = pidlTemp;
ILFree (*pidlInOut);
*pidlInOut = pidlTemp;
TRACE("-- pidl=%p ret=0x%08lx\n", pidlInOut? *pidlInOut: NULL, hr);
return hr;
TRACE ("-- pidl=%p ret=0x%08lx\n", pidlInOut ? *pidlInOut : NULL, hr);
return hr;
}
/***********************************************************************
* SHELL32_CoCreateInitSF
*
* creates a initialized shell folder
* Creates a shell folder and initializes it with a pidl via IPersistFolder.
* This function is meant for virtual forders not backed by a file system
* folder.
*/
static HRESULT SHELL32_CoCreateInitSF (
LPITEMIDLIST pidlRoot,
LPITEMIDLIST pidlChild,
REFCLSID clsid,
REFIID iid,
LPVOID * ppvOut)
HRESULT SHELL32_CoCreateInitSF (LPITEMIDLIST pidlRoot,
LPITEMIDLIST pidlChild, REFCLSID clsid, REFIID iid, LPVOID * ppvOut)
{
HRESULT hr;
LPITEMIDLIST pidlAbsolute;
IPersistFolder *pPF;
HRESULT hr;
TRACE("%p %p\n", pidlRoot, pidlChild);
TRACE ("%p %p\n", pidlRoot, pidlChild);
*ppvOut = NULL;
if (SUCCEEDED ((hr = SHCoCreateInstance (NULL, clsid, NULL, iid, ppvOut)))) {
if (SUCCEEDED((hr = SHCoCreateInstance(NULL, clsid, NULL, &IID_IPersistFolder, (LPVOID*)&pPF)))) {
if(SUCCEEDED((hr = IPersistFolder_QueryInterface(pPF, iid, ppvOut)))) {
pidlAbsolute = ILCombine (pidlRoot, pidlChild);
hr = IPersistFolder_Initialize(pPF, pidlAbsolute);
IPersistFolder_Release(pPF);
SHFree(pidlAbsolute);
}
}
IPersistFolder *pPF;
TRACE("-- ret=0x%08lx\n", hr);
return hr;
}
if (SUCCEEDED ((hr = IUnknown_QueryInterface ((IUnknown *) * ppvOut, &IID_IPersistFolder, (LPVOID *) & pPF)))) {
static HRESULT SHELL32_GetDisplayNameOfChild(
IShellFolder2 * psf,
LPCITEMIDLIST pidl,
DWORD dwFlags,
LPSTR szOut,
DWORD dwOutLen)
{
LPITEMIDLIST pidlFirst, pidlNext;
IShellFolder2 * psfChild;
HRESULT hr = E_OUTOFMEMORY;
STRRET strTemp;
TRACE("(%p)->(pidl=%p 0x%08lx %p 0x%08lx)\n",psf,pidl,dwFlags,szOut, dwOutLen);
pdump(pidl);
if ((pidlFirst = ILCloneFirst(pidl)))
{
hr = IShellFolder_BindToObject(psf, pidlFirst, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
if (SUCCEEDED(hr))
{
pidlNext = ILGetNext(pidl);
hr = IShellFolder_GetDisplayNameOf(psfChild, pidlNext, dwFlags | SHGDN_INFOLDER, &strTemp);
if (SUCCEEDED(hr))
{
hr = StrRetToStrNA(szOut, dwOutLen, &strTemp, pidlNext);
}
LPITEMIDLIST pidlAbsolute;
IShellFolder_Release(psfChild);
}
ILFree(pidlFirst);
pidlAbsolute = ILCombine (pidlRoot, pidlChild);
IPersistFolder_Initialize (pPF, pidlAbsolute);
IPersistFolder_Release (pPF);
SHFree (pidlAbsolute);
}
}
TRACE("-- ret=0x%08lx %s\n", hr, szOut);
return hr;
TRACE ("-- (%p) ret=0x%08lx\n", *ppvOut, hr);
return hr;
}
/***********************************************************************
* SHELL32_GetItemAttributes
* SHELL32_CoCreateInitSFEx
*
* NOTES
* observerd values:
* folder: 0xE0000177 FILESYSTEM | HASSUBFOLDER | FOLDER
* file: 0x40000177 FILESYSTEM
* drive: 0xf0000144 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR
* mycomputer: 0xb0000154 HASSUBFOLDER | FOLDER | FILESYSANCESTOR
* (seems to be default for shell extensions if no registry entry exists)
* Creates a shell folder and initializes it with a pidl and a root folder
* via IPersistFolder3.
* This function is meant for virtual forders backed by a file system
* folder.
*
* This functions does not set flags!! It only resets flags when nessesary.
* NOTES
* pathRoot can be NULL for Folders beeing a drive.
* In this case the absolute path is build from pidlChild (eg. C:)
*/
static HRESULT SHELL32_GetItemAttributes(
IShellFolder * psf,
LPITEMIDLIST pidl,
LPDWORD pdwAttributes)
{
GUID const * clsid;
DWORD dwAttributes;
TRACE("0x%08lx\n", *pdwAttributes);
if (*pdwAttributes & (0xcff3fe88))
WARN("attribute 0x%08lx not implemented\n", *pdwAttributes);
*pdwAttributes &= ~SFGAO_LINK; /* FIXME: for native filedialogs */
if (_ILIsDrive(pidl))
{
*pdwAttributes &= 0xf0000144;
}
else if ((clsid=_ILGetGUIDPointer(pidl)))
{
if (HCR_GetFolderAttributes(clsid, &dwAttributes))
{
*pdwAttributes &= dwAttributes;
}
else
{
*pdwAttributes &= 0xb0000154;
}
}
else if (_ILGetDataPointer(pidl))
{
dwAttributes = _ILGetFileAttributes(pidl, NULL, 0);
*pdwAttributes &= ~SFGAO_FILESYSANCESTOR;
if(( SFGAO_FOLDER & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
*pdwAttributes &= ~(SFGAO_FOLDER|SFGAO_HASSUBFOLDER);
if(( SFGAO_HIDDEN & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_HIDDEN))
*pdwAttributes &= ~SFGAO_HIDDEN;
if(( SFGAO_READONLY & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_READONLY))
*pdwAttributes &= ~SFGAO_READONLY;
}
else
{
*pdwAttributes &= 0xb0000154;
}
TRACE("-- 0x%08lx\n", *pdwAttributes);
return S_OK;
}
/***********************************************************************
* IShellFolder implementation
*/
typedef struct
{
ICOM_VFIELD(IUnknown);
DWORD ref;
ICOM_VTABLE(IShellFolder2)* lpvtblShellFolder;
ICOM_VTABLE(IPersistFolder3)* lpvtblPersistFolder3;
ICOM_VTABLE(IDropTarget)* lpvtblDropTarget;
ICOM_VTABLE(ISFHelper)* lpvtblSFHelper;
IUnknown *pUnkOuter; /* used for aggregation */
CLSID* pclsid;
/* both paths are parsible from the desktop */
LPSTR sPathRoot; /* complete path used as return value */
LPSTR sPathTarget; /* complete path to target used for enumeration and ChangeNotify */
LPITEMIDLIST pidlRoot; /* absolute pidl */
LPITEMIDLIST pidlTarget; /* absolute pidl */
int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */
UINT cfShellIDList; /* clipboardformat for IDropTarget */
BOOL fAcceptFmt; /* flag for pending Drop */
} IGenericSFImpl;
static struct ICOM_VTABLE(IUnknown) unkvt;
static struct ICOM_VTABLE(IShellFolder2) sfvt;
static struct ICOM_VTABLE(IPersistFolder3) psfvt;
static struct ICOM_VTABLE(IDropTarget) dtvt;
static struct ICOM_VTABLE(ISFHelper) shvt;
static IShellFolder * ISF_MyComputer_Constructor(void);
#define _IShellFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblShellFolder)))
#define _ICOM_THIS_From_IShellFolder2(class, name) class* This = (class*)(((char*)name)-_IShellFolder2_Offset);
#define _IPersistFolder_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder3)))
#define _ICOM_THIS_From_IPersistFolder3(class, name) class* This = (class*)(((char*)name)-_IPersistFolder_Offset);
#define _IDropTarget_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblDropTarget)))
#define _ICOM_THIS_From_IDropTarget(class, name) class* This = (class*)(((char*)name)-_IDropTarget_Offset);
#define _ISFHelper_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblSFHelper)))
#define _ICOM_THIS_From_ISFHelper(class, name) class* This = (class*)(((char*)name)-_ISFHelper_Offset);
/*
converts This to a interface pointer
*/
#define _IUnknown_(This) (IUnknown*)&(This->lpVtbl)
#define _IShellFolder_(This) (IShellFolder*)&(This->lpvtblShellFolder)
#define _IShellFolder2_(This) (IShellFolder2*)&(This->lpvtblShellFolder)
#define _IPersist_(This) (IPersist*)&(This->lpvtblPersistFolder3)
#define _IPersistFolder_(This) (IPersistFolder*)&(This->lpvtblPersistFolder3)
#define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpvtblPersistFolder3)
#define _IPersistFolder3_(This) (IPersistFolder3*)&(This->lpvtblPersistFolder3)
#define _IDropTarget_(This) (IDropTarget*)&(This->lpvtblDropTarget)
#define _ISFHelper_(This) (ISFHelper*)&(This->lpvtblSFHelper)
/**************************************************************************
* registers clipboardformat once
*/
static void SF_RegisterClipFmt (IGenericSFImpl * This)
{
TRACE("(%p)\n", This);
if (!This->cfShellIDList)
{
This->cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
}
}
/**************************************************************************
* we need a separate IUnknown to handle aggregation
* (inner IUnknown)
*/
static HRESULT WINAPI IUnknown_fnQueryInterface(
IUnknown * iface,
REFIID riid,
LPVOID *ppvObj)
{
ICOM_THIS(IGenericSFImpl, iface);
_CALL_TRACE
TRACE("(%p)->(%s,%p)\n",This,shdebugstr_guid(riid),ppvObj);
*ppvObj = NULL;
if(IsEqualIID(riid, &IID_IUnknown)) *ppvObj = _IUnknown_(This);
else if(IsEqualIID(riid, &IID_IShellFolder)) *ppvObj = _IShellFolder_(This);
else if(IsEqualIID(riid, &IID_IShellFolder2)) *ppvObj = _IShellFolder_(This);
else if(IsEqualIID(riid, &IID_IPersist)) *ppvObj = _IPersist_(This);
else if(IsEqualIID(riid, &IID_IPersistFolder)) *ppvObj = _IPersistFolder_(This);
else if(IsEqualIID(riid, &IID_IPersistFolder2)) *ppvObj = _IPersistFolder2_(This);
else if(IsEqualIID(riid, &IID_IPersistFolder3)) *ppvObj = _IPersistFolder3_(This);
else if(IsEqualIID(riid, &IID_ISFHelper)) *ppvObj = _ISFHelper_(This);
else if(IsEqualIID(riid, &IID_IDropTarget))
{
*ppvObj = _IDropTarget_(This);
SF_RegisterClipFmt(This);
}
if(*ppvObj)
{
IUnknown_AddRef((IUnknown*)(*ppvObj));
TRACE("-- Interface = %p\n", *ppvObj);
return S_OK;
}
TRACE("-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
static ULONG WINAPI IUnknown_fnAddRef(IUnknown * iface)
{
ICOM_THIS(IGenericSFImpl, iface);
_CALL_TRACE
TRACE("(%p)->(count=%lu)\n",This,This->ref);
shell32_ObjCount++;
return ++(This->ref);
}
static ULONG WINAPI IUnknown_fnRelease(IUnknown * iface)
{
ICOM_THIS(IGenericSFImpl, iface);
_CALL_TRACE
TRACE("(%p)->(count=%lu)\n",This,This->ref);
shell32_ObjCount--;
if (!--(This->ref))
{
TRACE("-- destroying IShellFolder(%p)\n",This);
if(This->pidlRoot) SHFree(This->pidlRoot);
if(This->sPathRoot) SHFree(This->sPathRoot);
LocalFree((HLOCAL)This);
return 0;
}
return This->ref;
}
static ICOM_VTABLE(IUnknown) unkvt =
HRESULT SHELL32_CoCreateInitSFEx (LPITEMIDLIST pidlRoot,
LPCSTR pathRoot, LPITEMIDLIST pidlChild, REFCLSID clsid, REFIID riid, LPVOID * ppvOut)
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IUnknown_fnQueryInterface,
IUnknown_fnAddRef,
IUnknown_fnRelease,
};
HRESULT hr;
IPersistFolder3 *ppf;
static shvheader GenericSFHeader [] =
{
{ IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
{ IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
{ IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
{ IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
{ IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 }
};
#define GENERICSHELLVIEWCOLUMNS 5
/**************************************************************************
* IFSFolder_Constructor
*
* NOTES
* creating undocumented ShellFS_Folder as part of an aggregation
* {F3364BA0-65B9-11CE-A9BA-00AA004AE837}
*
*/
HRESULT WINAPI IFSFolder_Constructor(
IUnknown * pUnkOuter,
REFIID riid,
LPVOID * ppv)
{
IGenericSFImpl * sf;
TRACE("unkOut=%p %s\n",pUnkOuter, shdebugstr_guid(riid));
if(pUnkOuter && ! IsEqualIID(riid, &IID_IUnknown)) return CLASS_E_NOAGGREGATION;
sf=(IGenericSFImpl*) LocalAlloc(GMEM_ZEROINIT,sizeof(IGenericSFImpl));
if (!sf) return E_OUTOFMEMORY;
TRACE ("%p %s %p\n", pidlRoot, pathRoot, pidlChild);
sf->ref=1;
ICOM_VTBL(sf)=&unkvt;
sf->lpvtblShellFolder=&sfvt;
sf->lpvtblPersistFolder3=&psfvt;
sf->lpvtblDropTarget=&dtvt;
sf->lpvtblSFHelper=&shvt;
sf->pclsid = (CLSID*)&CLSID_ShellFSFolder;
sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_(sf);
if (SUCCEEDED ((hr = SHCoCreateInstance (NULL, &CLSID_ShellFSFolder, NULL, riid, ppvOut)))) {
if (SUCCEEDED (IUnknown_QueryInterface ((IUnknown *) * ppvOut, &IID_IPersistFolder3, (LPVOID *) & ppf))) {
PERSIST_FOLDER_TARGET_INFO ppfti;
LPITEMIDLIST pidlAbsolute;
char szDestPath[MAX_PATH];
/* we have to return the inner IUnknown */
*ppv = _IUnknown_(sf);
ZeroMemory (&ppfti, sizeof (ppfti));
shell32_ObjCount++;
TRACE("--%p\n", *ppv);
return S_OK;
}
/* combine pidls */
pidlAbsolute = ILCombine (pidlRoot, pidlChild);
/**************************************************************************
* InitializeGenericSF
*/
static HRESULT InitializeGenericSF(IGenericSFImpl * sf, LPITEMIDLIST pidlRoot, LPITEMIDLIST pidlFolder, LPCSTR sPathRoot)
{
TRACE("(%p)->(pidl=%p, path=%s)\n",sf,pidlRoot, sPathRoot);
pdump(pidlRoot);
pdump(pidlFolder);
sf->pidlRoot = ILCombine(pidlRoot, pidlFolder);
if (!_ILIsSpecialFolder(pidlFolder)) { /* only file system paths */
char sNewPath[MAX_PATH];
char * sPos;
if (sPathRoot) {
strcpy(sNewPath, sPathRoot);
if (!((sPos = PathAddBackslashA (sNewPath)))) return E_UNEXPECTED;
/* build path */
if (pathRoot) {
lstrcpyA (szDestPath, pathRoot);
PathAddBackslashA(szDestPath); /* FIXME: why have drives a backslash here ? */
} else {
sPos = sNewPath;
szDestPath[0] = '\0';
}
_ILSimpleGetText(pidlFolder, sPos, MAX_PATH - (sPos - sNewPath));
if(!((sf->sPathRoot = SHAlloc(strlen(sNewPath)+1)))) return E_OUTOFMEMORY;
strcpy(sf->sPathRoot, sNewPath);
TRACE("-- %s\n", sNewPath);
}
return S_OK;
}
/**************************************************************************
* IShellFolder_Constructor
*/
IGenericSFImpl * IShellFolder_Constructor()
{
IGenericSFImpl * sf=(IGenericSFImpl*) LocalAlloc(GMEM_ZEROINIT,sizeof(IGenericSFImpl));
sf->ref=1;
ICOM_VTBL(sf)=&unkvt;
sf->lpvtblShellFolder=&sfvt;
sf->lpvtblPersistFolder3=&psfvt;
sf->lpvtblDropTarget=&dtvt;
sf->lpvtblSFHelper=&shvt;
lstrcatA (szDestPath, _ILGetTextPointer (pidlChild));
sf->pclsid = (CLSID*)&CLSID_ShellFSFolder;
sf->pUnkOuter = _IUnknown_(sf);
/* fill the PERSIST_FOLDER_TARGET_INFO */
ppfti.dwAttributes = -1;
ppfti.csidl = -1;
MultiByteToWideChar (CP_ACP, 0, szDestPath, -1, ppfti.szTargetParsingName, MAX_PATH);
TRACE("(%p)->()\n",sf);
shell32_ObjCount++;
return sf;
IPersistFolder3_InitializeEx (ppf, NULL, pidlAbsolute, &ppfti);
IPersistFolder3_Release (ppf);
ILFree (pidlAbsolute);
}
}
TRACE ("-- (%p) ret=0x%08lx\n", *ppvOut, hr);
return hr;
}
/**************************************************************************
* IShellFolder_fnQueryInterface
/***********************************************************************
* SHELL32_BindToChild
*
* PARAMETERS
* REFIID riid [in ] Requested InterfaceID
* LPVOID* ppvObject [out] Interface* to hold the result
* Common code for IShellFolder_BindToObject.
* Creates a shell folder by binding to a root pidl.
*/
static HRESULT WINAPI IShellFolder_fnQueryInterface(
IShellFolder2 * iface,
REFIID riid,
LPVOID *ppvObj)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
_CALL_TRACE
TRACE("(%p)->(%s,%p)\n",This,shdebugstr_guid(riid),ppvObj);
return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
}
/**************************************************************************
* IShellFolder_AddRef
*/
static ULONG WINAPI IShellFolder_fnAddRef(IShellFolder2 * iface)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
_CALL_TRACE
TRACE("(%p)->(count=%lu)\n",This,This->ref);
return IUnknown_AddRef(This->pUnkOuter);
}
/**************************************************************************
* IShellFolder_fnRelease
*/
static ULONG WINAPI IShellFolder_fnRelease(IShellFolder2 * iface)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
_CALL_TRACE
TRACE("(%p)->(count=%lu)\n",This,This->ref);
return IUnknown_Release(This->pUnkOuter);
}
/**************************************************************************
* IShellFolder_fnParseDisplayName
* PARAMETERS
* HWND hwndOwner, //[in ] Parent window for any message's
* LPBC pbc, //[in ] reserved
* LPOLESTR lpszDisplayName,//[in ] "Unicode" displayname.
* ULONG* pchEaten, //[out] (unicode) characters processed
* LPITEMIDLIST* ppidl, //[out] complex pidl to item
* ULONG* pdwAttributes //[out] items attributes
*
* NOTES
* every folder tries to parse only its own (the leftmost) pidl and creates a
* subfolder to evaluate the remaining parts
* now we can parse into namespaces implemented by shell extensions
*
* behaviour on win98: lpszDisplayName=NULL -> chrash
* lpszDisplayName="" -> returns mycoputer-pidl
*
* FIXME:
* pdwAttributes: not set
* pchEaten: not set like in windows
*/
static HRESULT WINAPI IShellFolder_fnParseDisplayName(
IShellFolder2 * iface,
HWND hwndOwner,
LPBC pbcReserved,
LPOLESTR lpszDisplayName,
DWORD *pchEaten,
LPITEMIDLIST *ppidl,
DWORD *pdwAttributes)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
HRESULT hr = E_OUTOFMEMORY;
LPCWSTR szNext=NULL;
WCHAR szElement[MAX_PATH];
CHAR szTempA[MAX_PATH], szPath[MAX_PATH];
LPITEMIDLIST pidlTemp=NULL;
TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
This,hwndOwner,pbcReserved,lpszDisplayName,
debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
if (!lpszDisplayName || !ppidl) return E_INVALIDARG;
if (pchEaten) *pchEaten = 0; /* strange but like the original */
if (*lpszDisplayName)
{
/* get the next element */
szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
/* build the full pathname to the element */
WideCharToMultiByte( CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL );
strcpy(szPath, This->sPathRoot);
PathAddBackslashA(szPath);
strcat(szPath, szTempA);
/* get the pidl */
pidlTemp = SHSimpleIDListFromPathA(szPath);
if (pidlTemp)
{
/* try to analyse the next element */
if (szNext && *szNext)
{
hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
}
else
{
if (pdwAttributes && *pdwAttributes)
{
SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
/* WIN32_FIND_DATAA fd;
SHGetDataFromIDListA(_IShellFolder_(This), pidlTemp, SHGDFIL_FINDDATA, &fd, sizeof(fd));
if (!(FILE_ATTRIBUTE_DIRECTORY & fd.dwFileAttributes))
*pdwAttributes &= ~SFGAO_FOLDER;
if (FILE_ATTRIBUTE_READONLY & fd.dwFileAttributes)
*pdwAttributes &= ~(SFGAO_CANDELETE|SFGAO_CANMOVE|SFGAO_CANRENAME );
*/
}
hr = S_OK;
}
}
}
if (!hr)
*ppidl = pidlTemp;
else
*ppidl = NULL;
TRACE("(%p)->(-- pidl=%p ret=0x%08lx)\n", This, ppidl? *ppidl:0, hr);
return hr;
}
/**************************************************************************
* IShellFolder_fnEnumObjects
* PARAMETERS
* HWND hwndOwner, //[in ] Parent Window
* DWORD grfFlags, //[in ] SHCONTF enumeration mask
* LPENUMIDLIST* ppenumIDList //[out] IEnumIDList interface
*/
static HRESULT WINAPI IShellFolder_fnEnumObjects(
IShellFolder2 * iface,
HWND hwndOwner,
DWORD dwFlags,
LPENUMIDLIST* ppEnumIDList)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
*ppEnumIDList = NULL;
*ppEnumIDList = IEnumIDList_Constructor (This->sPathRoot, dwFlags, EIDL_FILE);
TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
if(!*ppEnumIDList) return E_OUTOFMEMORY;
return S_OK;
}
/**************************************************************************
* IShellFolder_fnBindToObject
* PARAMETERS
* LPCITEMIDLIST pidl, //[in ] relative pidl to open
* LPBC pbc, //[in ] reserved
* REFIID riid, //[in ] Initial Interface
* LPVOID* ppvObject //[out] Interface*
*/
static HRESULT WINAPI IShellFolder_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
GUID const * iid;
IShellFolder *pShellFolder, *pSubFolder;
IGenericSFImpl *pSFImpl;
IPersistFolder *pPersistFolder;
LPITEMIDLIST pidlRoot;
HRESULT hr;
TRACE("(%p)->(pidl=%p,%p,%s,%p)\n",This,pidl,pbcReserved,shdebugstr_guid(riid),ppvOut);
if(!pidl || !ppvOut) return E_INVALIDARG;
*ppvOut = NULL;
if ((iid=_ILGetGUIDPointer(pidl)))
{
/* we have to create a alien folder */
if ( SUCCEEDED(SHCoCreateInstance(NULL, iid, NULL, riid, (LPVOID*)&pShellFolder))
&& SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&pPersistFolder)))
{
pidlRoot = ILCombine (This->pidlRoot, pidl);
IPersistFolder_Initialize(pPersistFolder, pidlRoot);
IPersistFolder_Release(pPersistFolder);
SHFree(pidlRoot);
}
else
{
return E_FAIL;
}
}
else
{
if ((pSFImpl = IShellFolder_Constructor())) {
LPITEMIDLIST pidltemp = ILCloneFirst(pidl);
hr = InitializeGenericSF(pSFImpl, This->pidlRoot, pidltemp, This->sPathRoot);
ILFree(pidltemp);
pShellFolder = _IShellFolder_(pSFImpl);
}
}
if (_ILIsPidlSimple(pidl))
{
if(IsEqualIID(riid, &IID_IShellFolder))
{
*ppvOut = pShellFolder;
hr = S_OK;
}
else
{
hr = IShellFolder_QueryInterface(pShellFolder, riid, ppvOut);
IShellFolder_Release(pShellFolder);
}
}
else
{
hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, riid, (LPVOID)&pSubFolder);
IShellFolder_Release(pShellFolder);
*ppvOut = pSubFolder;
HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot,
LPCSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut)
{
GUID const *clsid;
IShellFolder *pSF;
HRESULT hr;
LPITEMIDLIST pidlChild;
if (!pidlRoot || !ppvOut)
return E_INVALIDARG;
*ppvOut = NULL;
pidlChild = ILCloneFirst (pidlComplete);
if ((clsid = _ILGetGUIDPointer (pidlChild))) {
/* virtual folder */
hr = SHELL32_CoCreateInitSF (pidlRoot, pidlChild, clsid, &IID_IShellFolder, (LPVOID *) & pSF);
} else {
/* file system folder */
hr = SHELL32_CoCreateInitSFEx (pidlRoot, pathRoot, pidlChild, &CLSID_ShellFSFolder, &IID_IShellFolder,
(LPVOID *) & pSF);
}
ILFree (pidlChild);
if (SUCCEEDED (hr)) {
if (_ILIsPidlSimple (pidlComplete)) {
/* no sub folders */
hr = IShellFolder_QueryInterface (pSF, riid, ppvOut);
} else {
/* go deeper */
hr = IShellFolder_BindToObject (pSF, ILGetNext (pidlComplete), NULL, riid, ppvOut);
}
IShellFolder_Release (pSF);
}
TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
TRACE ("-- returning (%p) %08lx\n", *ppvOut, hr);
return hr;
return hr;
}
/**************************************************************************
* IShellFolder_fnBindToStorage
* PARAMETERS
* LPCITEMIDLIST pidl, //[in ] complex pidl to store
* LPBC pbc, //[in ] reserved
* REFIID riid, //[in ] Initial storage interface
* LPVOID* ppvObject //[out] Interface* returned
*/
static HRESULT WINAPI IShellFolder_fnBindToStorage(
IShellFolder2 * iface,
LPCITEMIDLIST pidl,
LPBC pbcReserved,
REFIID riid,
LPVOID *ppvOut)
/***********************************************************************
* SHELL32_GetDisplayNameOfChild
*
* Retrives the display name of a child object of a shellfolder.
*
* For a pidl eg. [subpidl1][subpidl2][subpidl3]:
* - it binds to the child shellfolder [subpidl1]
* - asks it for the displayname of [subpidl2][subpidl3]
*
* Is possible the pidl is a simple pidl. In this case it asks the
* subfolder for the displayname of a empty pidl. The subfolder
* returns the own displayname eg. "::{guid}". This is used for
* virtual folders with the registry key WantsFORPARSING set.
*/
HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf,
LPCITEMIDLIST pidl, DWORD dwFlags, LPSTR szOut, DWORD dwOutLen)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n",
This,pidl,pbcReserved,shdebugstr_guid(riid),ppvOut);
LPITEMIDLIST pidlFirst;
HRESULT hr = E_OUTOFMEMORY;
*ppvOut = NULL;
return E_NOTIMPL;
}
/**************************************************************************
* IShellFolder_fnCompareIDs
*
* PARMETERS
* LPARAM lParam, //[in ] Column?
* LPCITEMIDLIST pidl1, //[in ] simple pidl
* LPCITEMIDLIST pidl2) //[in ] simple pidl
*
* NOTES
* Special case - If one of the items is a Path and the other is a File,
* always make the Path come before the File.
*
* NOTES
* use SCODE_CODE() on the return value to get the result
*/
static HRESULT WINAPI IShellFolder_fnCompareIDs(
IShellFolder2 * iface,
LPARAM lParam,
LPCITEMIDLIST pidl1,
LPCITEMIDLIST pidl2)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
CHAR szTemp1[MAX_PATH];
CHAR szTemp2[MAX_PATH];
int nReturn;
IShellFolder * psf;
HRESULT hr = E_OUTOFMEMORY;
LPCITEMIDLIST pidlTemp;
PIDLTYPE pt1, pt2;
if (TRACE_ON(shell)) {
TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n",This,lParam,pidl1,pidl2);
pdump (pidl1);
pdump (pidl2);
}
TRACE ("(%p)->(pidl=%p 0x%08lx %p 0x%08lx)\n", psf, pidl, dwFlags, szOut, dwOutLen);
pdump (pidl);
if (!pidl1 && !pidl2)
{
hr = ResultFromShort(0);
}
else if (!pidl1)
{
hr = ResultFromShort(-1);
}
else if (!pidl2)
{
hr = ResultFromShort(1);
}
else
{
LPPIDLDATA pd1, pd2;
pd1 = _ILGetDataPointer(pidl1);
pd2 = _ILGetDataPointer(pidl2);
/* compate the types. sort order is the PT_* constant */
pt1 = ( pd1 ? pd1->type: PT_DESKTOP);
pt2 = ( pd2 ? pd2->type: PT_DESKTOP);
if (pt1 != pt2)
{
hr = ResultFromShort(pt1-pt2);
}
else /* same type of pidl */
{
_ILSimpleGetText(pidl1, szTemp1, MAX_PATH);
_ILSimpleGetText(pidl2, szTemp2, MAX_PATH);
nReturn = strcasecmp(szTemp1, szTemp2);
if (nReturn == 0) /* first pidl different ? */
{
pidl1 = ILGetNext(pidl1);
if (pidl1 && pidl1->mkid.cb) /* go deeper? */
{
pidlTemp = ILCloneFirst(pidl1);
pidl2 = ILGetNext(pidl2);
hr = IShellFolder_BindToObject(iface, pidlTemp, NULL, &IID_IShellFolder, (LPVOID*)&psf);
if (SUCCEEDED(hr))
{
nReturn = IShellFolder_CompareIDs(psf, 0, pidl1, pidl2);
IShellFolder_Release(psf);
hr = ResultFromShort(nReturn);
}
ILFree(pidlTemp);
}
else /* no deeper on #1 */
{
pidl2 = ILGetNext(pidl2);
if (pidl2 && pidl2->mkid.cb) /* go deeper on #2 ? */
hr = ResultFromShort(-1); /* two different */
else
hr = ResultFromShort(nReturn); /* two equal simple pidls */
}
}
else
{
hr = ResultFromShort(nReturn); /* two different simple pidls */
}
}
}
pidlFirst = ILCloneFirst (pidl);
if (pidlFirst) {
IShellFolder2 *psfChild;
TRACE("-- res=0x%08lx\n", hr);
return hr;
}
hr = IShellFolder_BindToObject (psf, pidlFirst, NULL, &IID_IShellFolder, (LPVOID *) & psfChild);
if (SUCCEEDED (hr)) {
STRRET strTemp;
LPITEMIDLIST pidlNext = ILGetNext (pidl);
/**************************************************************************
* IShellFolder_fnCreateViewObject
*/
static HRESULT WINAPI IShellFolder_fnCreateViewObject(
IShellFolder2 * iface,
HWND hwndOwner,
REFIID riid,
LPVOID *ppvOut)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
LPSHELLVIEW pShellView;
HRESULT hr = E_INVALIDARG;
TRACE("(%p)->(hwnd=0x%x,%s,%p)\n",This,hwndOwner,shdebugstr_guid(riid),ppvOut);
if(ppvOut)
{
*ppvOut = NULL;
if(IsEqualIID(riid, &IID_IDropTarget))
{
hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, ppvOut);
}
else if(IsEqualIID(riid, &IID_IContextMenu))
{
FIXME("IContextMenu not implemented\n");
hr = E_NOTIMPL;
}
else if(IsEqualIID(riid, &IID_IShellView))
{
pShellView = IShellView_Constructor((IShellFolder*)iface);
if(pShellView)
{
hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
IShellView_Release(pShellView);
hr = IShellFolder_GetDisplayNameOf (psfChild, pidlNext, dwFlags, &strTemp);
if (SUCCEEDED (hr)) {
hr = StrRetToStrNA (szOut, dwOutLen, &strTemp, pidlNext);
}
}
}
TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
return hr;
}
/**************************************************************************
* IShellFolder_fnGetAttributesOf
*
* PARAMETERS
* UINT cidl, //[in ] num elements in pidl array
* LPCITEMIDLIST* apidl, //[in ] simple pidl array
* ULONG* rgfInOut) //[out] result array
*
*/
static HRESULT WINAPI IShellFolder_fnGetAttributesOf(
IShellFolder2 * iface,
UINT cidl,
LPCITEMIDLIST *apidl,
DWORD *rgfInOut)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
HRESULT hr = S_OK;
TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
if ( (!cidl) || (!apidl) || (!rgfInOut))
return E_INVALIDARG;
while (cidl > 0 && *apidl)
{
pdump (*apidl);
SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
apidl++;
cidl--;
}
TRACE("-- result=0x%08lx\n",*rgfInOut);
return hr;
}
/**************************************************************************
* IShellFolder_fnGetUIObjectOf
*
* PARAMETERS
* HWND hwndOwner, //[in ] Parent window for any output
* UINT cidl, //[in ] array size
* LPCITEMIDLIST* apidl, //[in ] simple pidl array
* REFIID riid, //[in ] Requested Interface
* UINT* prgfInOut, //[ ] reserved
* LPVOID* ppvObject) //[out] Resulting Interface
*
* NOTES
* This function gets asked to return "view objects" for one or more (multiple select)
* items:
* The viewobject typically is an COM object with one of the following interfaces:
* IExtractIcon,IDataObject,IContextMenu
* In order to support icon positions in the default Listview your DataObject
* must implement the SetData method (in addition to GetData :) - the shell passes
* a barely documented "Icon positions" structure to SetData when the drag starts,
* and GetData's it if the drop is in another explorer window that needs the positions.
*/
static HRESULT WINAPI IShellFolder_fnGetUIObjectOf(
IShellFolder2 * iface,
HWND hwndOwner,
UINT cidl,
LPCITEMIDLIST * apidl,
REFIID riid,
UINT * prgfInOut,
LPVOID * ppvOut)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
LPITEMIDLIST pidl;
IUnknown* pObj = NULL;
HRESULT hr = E_INVALIDARG;
TRACE("(%p)->(0x%04x,%u,apidl=%p,%s,%p,%p)\n",
This,hwndOwner,cidl,apidl,shdebugstr_guid(riid),prgfInOut,ppvOut);
if (ppvOut)
{
*ppvOut = NULL;
if(IsEqualIID(riid, &IID_IContextMenu) && (cidl >= 1))
{
pObj = (LPUNKNOWN)ISvItemCm_Constructor((IShellFolder*)iface, This->pidlRoot, apidl, cidl);
hr = S_OK;
}
else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1))
{
pObj = (LPUNKNOWN)IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl);
hr = S_OK;
}
else if (IsEqualIID(riid, &IID_IExtractIconA) && (cidl == 1))
{
pidl = ILCombine(This->pidlRoot,apidl[0]);
pObj = (LPUNKNOWN)IExtractIconA_Constructor( pidl );
SHFree(pidl);
hr = S_OK;
}
else if (IsEqualIID(riid, &IID_IDropTarget) && (cidl >= 1))
{
hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, (LPVOID*)&pObj);
}
else
{
hr = E_NOINTERFACE;
}
if(!pObj)
hr = E_OUTOFMEMORY;
*ppvOut = pObj;
}
TRACE("(%p)->hr=0x%08lx\n",This, hr);
return hr;
}
/**************************************************************************
* IShellFolder_fnGetDisplayNameOf
* Retrieves the display name for the specified file object or subfolder
*
* PARAMETERS
* LPCITEMIDLIST pidl, //[in ] complex pidl to item
* DWORD dwFlags, //[in ] SHGNO formatting flags
* LPSTRRET lpName) //[out] Returned display name
*
* FIXME
* if the name is in the pidl the ret value should be a STRRET_OFFSET
*/
#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
static HRESULT WINAPI IShellFolder_fnGetDisplayNameOf(
IShellFolder2 * iface,
LPCITEMIDLIST pidl,
DWORD dwFlags,
LPSTRRET strRet)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
CHAR szPath[MAX_PATH]= "";
int len = 0;
BOOL bSimplePidl;
TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
pdump(pidl);
if(!pidl || !strRet) return E_INVALIDARG;
bSimplePidl = _ILIsPidlSimple(pidl);
/* take names of special folders only if its only this folder */
if (_ILIsSpecialFolder(pidl))
{
if ( bSimplePidl)
{
_ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
}
}
else
{
if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sPathRoot)
{
strcpy (szPath, This->sPathRoot); /* get path to root*/
PathAddBackslashA(szPath);
len = strlen(szPath);
}
_ILSimpleGetText(pidl, szPath + len, MAX_PATH - len); /* append my own path */
/* MSDN also mentions SHGDN_FOREDITING, which isn't defined in wine */
if(!_ILIsFolder(pidl) && !(dwFlags & SHGDN_FORPARSING) &&
((dwFlags & SHGDN_INFOLDER) || (dwFlags == SHGDN_NORMAL)))
{
HKEY hKey;
DWORD dwData;
DWORD dwDataSize = sizeof(DWORD);
BOOL doHide = 0; /* The default value is FALSE (win98 at least) */
/* XXX should it do this only for known file types? -- that would make it even slower! */
/* XXX That's what the prompt says!! */
if(!RegCreateKeyExA(HKEY_CURRENT_USER,
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0))
{
if(!RegQueryValueExA(hKey, "HideFileExt", 0, 0, (LPBYTE)&dwData, &dwDataSize))
doHide = dwData;
RegCloseKey(hKey);
}
if(doHide && szPath[0]!='.') PathRemoveExtensionA(szPath);
}
}
if ( (dwFlags & SHGDN_FORPARSING) && !bSimplePidl) /* go deeper if needed */
{
PathAddBackslashA(szPath);
len = strlen(szPath);
if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath + len, MAX_PATH - len)))
return E_OUTOFMEMORY;
}
strRet->uType = STRRET_CSTR;
lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
TRACE("-- (%p)->(%s)\n", This, szPath);
return S_OK;
}
/**************************************************************************
* IShellFolder_fnSetNameOf
* Changes the name of a file object or subfolder, possibly changing its item
* identifier in the process.
*
* PARAMETERS
* HWND hwndOwner, //[in ] Owner window for output
* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
* LPCOLESTR lpszName, //[in ] the items new display name
* DWORD dwFlags, //[in ] SHGNO formatting flags
* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
*/
static HRESULT WINAPI IShellFolder_fnSetNameOf(
IShellFolder2 * iface,
HWND hwndOwner,
LPCITEMIDLIST pidl, /*simple pidl*/
LPCOLESTR lpName,
DWORD dwFlags,
LPITEMIDLIST *pPidlOut)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
char szSrc[MAX_PATH], szDest[MAX_PATH];
int len;
BOOL bIsFolder = _ILIsFolder(ILFindLastID(pidl));
TRACE("(%p)->(%u,pidl=%p,%s,%lu,%p)\n",
This,hwndOwner,pidl,debugstr_w(lpName),dwFlags,pPidlOut);
/* build source path */
if (dwFlags & SHGDN_INFOLDER)
{
strcpy(szSrc, This->sPathRoot);
PathAddBackslashA(szSrc);
len = strlen (szSrc);
_ILSimpleGetText(pidl, szSrc+len, MAX_PATH-len);
}
else
{
SHGetPathFromIDListA(pidl, szSrc);
IShellFolder_Release (psfChild);
}
ILFree (pidlFirst);
}
/* build destination path */
strcpy(szDest, This->sPathRoot);
PathAddBackslashA(szDest);
len = strlen (szDest);
WideCharToMultiByte( CP_ACP, 0, lpName, -1, szDest+len, MAX_PATH-len, NULL, NULL );
szDest[MAX_PATH-1] = 0;
TRACE("src=%s dest=%s\n", szSrc, szDest);
if ( MoveFileA(szSrc, szDest) )
{
if (pPidlOut) *pPidlOut = SHSimpleIDListFromPathA(szDest);
SHChangeNotifyA( bIsFolder?SHCNE_RENAMEFOLDER:SHCNE_RENAMEITEM, SHCNF_PATHA, szSrc, szDest);
return S_OK;
}
return E_FAIL;
}
static HRESULT WINAPI IShellFolder_fnGetDefaultSearchGUID(
IShellFolder2 * iface,
GUID *pguid)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
FIXME("(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI IShellFolder_fnEnumSearches(
IShellFolder2 * iface,
IEnumExtraSearch **ppenum)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
FIXME("(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI IShellFolder_fnGetDefaultColumn(
IShellFolder2 * iface,
DWORD dwRes,
ULONG *pSort,
ULONG *pDisplay)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
TRACE("(%p)\n",This);
if (pSort) *pSort = 0;
if (pDisplay) *pDisplay = 0;
return S_OK;
}
static HRESULT WINAPI IShellFolder_fnGetDefaultColumnState(
IShellFolder2 * iface,
UINT iColumn,
DWORD *pcsFlags)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
TRACE("(%p)\n",This);
if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
*pcsFlags = GenericSFHeader[iColumn].pcsFlags;
return S_OK;
}
static HRESULT WINAPI IShellFolder_fnGetDetailsEx(
IShellFolder2 * iface,
LPCITEMIDLIST pidl,
const SHCOLUMNID *pscid,
VARIANT *pv)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
FIXME("(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI IShellFolder_fnGetDetailsOf(
IShellFolder2 * iface,
LPCITEMIDLIST pidl,
UINT iColumn,
SHELLDETAILS *psd)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
HRESULT hr = E_FAIL;
TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
TRACE ("-- ret=0x%08lx %s\n", hr, szOut);
if (!pidl)
{
/* the header titles */
psd->fmt = GenericSFHeader[iColumn].fmt;
psd->cxChar = GenericSFHeader[iColumn].cxChar;
psd->str.uType = STRRET_CSTR;
LoadStringA(shell32_hInstance, GenericSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
return S_OK;
}
else
{
/* the data from the pidl */
switch(iColumn)
{
case 0: /* name */
hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
break;
case 1: /* size */
_ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
break;
case 2: /* type */
_ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
break;
case 3: /* date */
_ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
break;
case 4: /* attributes */
_ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
break;
}
hr = S_OK;
psd->str.uType = STRRET_CSTR;
}
return hr;
}
static HRESULT WINAPI IShellFolder_fnMapNameToSCID(
IShellFolder2 * iface,
LPCWSTR pwszName,
SHCOLUMNID *pscid)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
FIXME("(%p)\n",This);
return E_NOTIMPL;
return hr;
}
static ICOM_VTABLE(IShellFolder2) sfvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IShellFolder_fnQueryInterface,
IShellFolder_fnAddRef,
IShellFolder_fnRelease,
IShellFolder_fnParseDisplayName,
IShellFolder_fnEnumObjects,
IShellFolder_fnBindToObject,
IShellFolder_fnBindToStorage,
IShellFolder_fnCompareIDs,
IShellFolder_fnCreateViewObject,
IShellFolder_fnGetAttributesOf,
IShellFolder_fnGetUIObjectOf,
IShellFolder_fnGetDisplayNameOf,
IShellFolder_fnSetNameOf,
/* ShellFolder2 */
IShellFolder_fnGetDefaultSearchGUID,
IShellFolder_fnEnumSearches,
IShellFolder_fnGetDefaultColumn,
IShellFolder_fnGetDefaultColumnState,
IShellFolder_fnGetDetailsEx,
IShellFolder_fnGetDetailsOf,
IShellFolder_fnMapNameToSCID
};
/****************************************************************************
* ISFHelper for IShellFolder implementation
/***********************************************************************
* SHELL32_GetItemAttributes
*
* NOTES
* observerd values:
* folder: 0xE0000177 FILESYSTEM | HASSUBFOLDER | FOLDER
* file: 0x40000177 FILESYSTEM
* drive: 0xf0000144 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR
* mycomputer: 0xb0000154 HASSUBFOLDER | FOLDER | FILESYSANCESTOR
* (seems to be default for shell extensions if no registry entry exists)
*
* This functions does not set flags!! It only resets flags when nessesary.
*/
static HRESULT WINAPI ISFHelper_fnQueryInterface(
ISFHelper *iface,
REFIID riid,
LPVOID *ppvObj)
HRESULT SHELL32_GetItemAttributes (IShellFolder * psf, LPITEMIDLIST pidl, LPDWORD pdwAttributes)
{
_ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
TRACE("(%p)->(count=%lu)\n",This,This->ref);
GUID const *clsid;
DWORD dwAttributes;
return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
}
static ULONG WINAPI ISFHelper_fnAddRef(
ISFHelper *iface)
{
_ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
TRACE ("0x%08lx\n", *pdwAttributes);
TRACE("(%p)->(count=%lu)\n",This,This->ref);
if (*pdwAttributes & (0xcff3fe88))
WARN ("attribute 0x%08lx not implemented\n", *pdwAttributes);
*pdwAttributes &= ~SFGAO_LINK; /* FIXME: for native filedialogs */
return IUnknown_AddRef(This->pUnkOuter);
}
if (_ILIsDrive (pidl)) {
*pdwAttributes &= 0xf0000144;
} else if ((clsid = _ILGetGUIDPointer (pidl))) {
if (HCR_GetFolderAttributes (clsid, &dwAttributes)) {
*pdwAttributes &= dwAttributes;
} else {
*pdwAttributes &= 0xb0000154;
}
} else if (_ILGetDataPointer (pidl)) {
dwAttributes = _ILGetFileAttributes (pidl, NULL, 0);
*pdwAttributes &= ~SFGAO_FILESYSANCESTOR;
static ULONG WINAPI ISFHelper_fnRelease(
ISFHelper *iface)
{
_ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
if ((SFGAO_FOLDER & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
*pdwAttributes &= ~(SFGAO_FOLDER | SFGAO_HASSUBFOLDER);
TRACE("(%p)\n", This);
if ((SFGAO_HIDDEN & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_HIDDEN))
*pdwAttributes &= ~SFGAO_HIDDEN;
return IUnknown_Release(This->pUnkOuter);
if ((SFGAO_READONLY & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_READONLY))
*pdwAttributes &= ~SFGAO_READONLY;
} else {
*pdwAttributes &= 0xb0000154;
}
TRACE ("-- 0x%08lx\n", *pdwAttributes);
return S_OK;
}
/****************************************************************************
* ISFHelper_fnAddFolder
*
* creates a unique folder name
/***********************************************************************
* SHELL32_GetItemAttributes
*/
static HRESULT WINAPI ISFHelper_fnGetUniqueName(
ISFHelper *iface,
LPSTR lpName,
UINT uLen)
{
_ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
IEnumIDList * penum;
HRESULT hr;
char szText[MAX_PATH];
char * szNewFolder = "New Folder";
TRACE("(%p)(%s %u)\n", This, lpName, uLen);
if (uLen < strlen(szNewFolder) + 4) return E_POINTER;
strcpy(lpName, szNewFolder);
hr = IShellFolder_fnEnumObjects(_IShellFolder2_(This), 0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
if (penum)
{
LPITEMIDLIST pidl;
DWORD dwFetched;
int i=1;
next: IEnumIDList_Reset(penum);
while(S_OK == IEnumIDList_Next(penum, 1, &pidl, &dwFetched) && dwFetched)
{
_ILSimpleGetText(pidl, szText, MAX_PATH);
if (0 == strcasecmp(szText, lpName))
{
sprintf(lpName, "%s %d", szNewFolder, i++);
if (i > 99)
{
hr = E_FAIL;
break;
}
goto next;
}
}
IEnumIDList_Release(penum);
}
return hr;
HRESULT SHELL32_CompareIDs (IShellFolder * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
{
int type1,
type2;
char szTemp1[MAX_PATH];
char szTemp2[MAX_PATH];
int nReturn = 0;
LPITEMIDLIST firstpidl,
nextpidl1,
nextpidl2;
IShellFolder *psf;
// test for empty pidls
BOOL isEmpty1 = _ILIsDesktop (pidl1);
BOOL isEmpty2 = _ILIsDesktop (pidl2);
if (isEmpty1 && isEmpty2)
return 0;
if (isEmpty1)
return -1;
if (isEmpty2)
return 1;
// test for different types. Sort order is the PT_* constant */
type1 = _ILGetDataPointer (pidl1)->type;
type2 = _ILGetDataPointer (pidl2)->type;
if (type1 != type2)
return (type1 - type2);
// test for name of pidl
_ILSimpleGetText (pidl1, szTemp1, MAX_PATH);
_ILSimpleGetText (pidl2, szTemp2, MAX_PATH);
nReturn = strcasecmp (szTemp1, szTemp2);
if (nReturn != 0)
return nReturn;
// test of complex pidls
firstpidl = ILCloneFirst (pidl1);
nextpidl1 = ILGetNext (pidl1);
nextpidl2 = ILGetNext (pidl2);
// optimizing: test special cases and bind not deeper
// the deeper shellfolder would do the same
isEmpty1 = _ILIsDesktop (nextpidl1);
isEmpty2 = _ILIsDesktop (nextpidl2);
if (isEmpty1 && isEmpty2) {
nReturn = 0;
} else if (isEmpty1) {
nReturn = -1;
} else if (isEmpty2) {
nReturn = 1;
// optimizing end
} else if (SUCCEEDED (IShellFolder_BindToObject (iface, firstpidl, NULL, &IID_IShellFolder, (LPVOID *) & psf))) {
nReturn = IShellFolder_CompareIDs (psf, lParam, nextpidl1, nextpidl2);
IShellFolder_Release (psf);
}
ILFree (firstpidl);
return nReturn;
}
/****************************************************************************
* ISFHelper_fnAddFolder
*
* adds a new folder.
*/
static HRESULT WINAPI ISFHelper_fnAddFolder(
ISFHelper *iface,
HWND hwnd,
LPCSTR lpName,
LPITEMIDLIST* ppidlOut)
{
_ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
char lpstrNewDir[MAX_PATH];
DWORD bRes;
HRESULT hres = E_FAIL;
TRACE("(%p)(%s %p)\n", This, lpName, ppidlOut);
strcpy(lpstrNewDir, This->sPathRoot);
PathAddBackslashA(lpstrNewDir);
strcat(lpstrNewDir, lpName);
bRes = CreateDirectoryA(lpstrNewDir, NULL);
if (bRes)
{
LPITEMIDLIST pidl, pidlitem;
pidlitem = SHSimpleIDListFromPathA(lpstrNewDir);
pidl = ILCombine(This->pidlRoot, pidlitem);
SHChangeNotifyA(SHCNE_MKDIR, SHCNF_IDLIST, pidl, NULL);
SHFree(pidl);
if (ppidlOut) *ppidlOut = pidlitem;
hres = S_OK;
}
else
{
char lpstrText[128+MAX_PATH];
char lpstrTempText[128];
char lpstrCaption[256];
/* Cannot Create folder because of permissions */
LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_DENIED, lpstrTempText, sizeof(lpstrTempText));
LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_CAPTION, lpstrCaption, sizeof(lpstrCaption));
sprintf(lpstrText,lpstrTempText, lpstrNewDir);
MessageBoxA(hwnd,lpstrText, lpstrCaption, MB_OK | MB_ICONEXCLAMATION);
}
return hres;
}
/****************************************************************************
* ISFHelper_fnDeleteItems
*
* deletes items in folder
*/
static HRESULT WINAPI ISFHelper_fnDeleteItems(
ISFHelper *iface,
UINT cidl,
LPCITEMIDLIST* apidl)
{
_ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
int i;
char szPath[MAX_PATH];
BOOL bConfirm = TRUE;
TRACE("(%p)(%u %p)\n", This, cidl, apidl);
/* deleting multiple items so give a slightly different warning */
if(cidl != 1)
{
char tmp[8];
snprintf(tmp, sizeof(tmp), "%d", cidl);
if(!SHELL_WarnItemDelete(ASK_DELETE_MULTIPLE_ITEM, tmp))
return E_FAIL;
bConfirm = FALSE;
}
for(i=0; i< cidl; i++)
{
strcpy(szPath, This->sPathRoot);
PathAddBackslashA(szPath);
_ILSimpleGetText(apidl[i], szPath+strlen(szPath), MAX_PATH);
if (_ILIsFolder(apidl[i]))
{
LPITEMIDLIST pidl;
TRACE("delete %s\n", szPath);
if (! SHELL_DeleteDirectoryA(szPath, bConfirm))
{
TRACE("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
return E_FAIL;
}
pidl = ILCombine(This->pidlRoot, apidl[i]);
SHChangeNotifyA(SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL);
SHFree(pidl);
}
else if (_ILIsValue(apidl[i]))
{
LPITEMIDLIST pidl;
TRACE("delete %s\n", szPath);
if (! SHELL_DeleteFileA(szPath, bConfirm))
{
TRACE("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
return E_FAIL;
}
pidl = ILCombine(This->pidlRoot, apidl[i]);
SHChangeNotifyA(SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL);
SHFree(pidl);
}
}
return S_OK;
}
/****************************************************************************
* ISFHelper_fnCopyItems
*
* copies items to this folder
*/
static HRESULT WINAPI ISFHelper_fnCopyItems(
ISFHelper *iface,
IShellFolder* pSFFrom,
UINT cidl,
LPCITEMIDLIST *apidl)
{
int i;
IPersistFolder2 * ppf2=NULL;
char szSrcPath[MAX_PATH], szDstPath[MAX_PATH];
_ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
TRACE("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl);
IShellFolder_QueryInterface(pSFFrom, &IID_IPersistFolder2, (LPVOID*)&ppf2);
if (ppf2)
{
LPITEMIDLIST pidl;
if (SUCCEEDED(IPersistFolder2_GetCurFolder(ppf2, &pidl)))
{
for (i=0; i<cidl; i++)
{
SHGetPathFromIDListA(pidl, szSrcPath);
PathAddBackslashA(szSrcPath);
_ILSimpleGetText(apidl[i], szSrcPath+strlen(szSrcPath), MAX_PATH);
strcpy(szDstPath, This->sPathRoot);
PathAddBackslashA(szDstPath);
_ILSimpleGetText(apidl[i], szDstPath+strlen(szDstPath), MAX_PATH);
MESSAGE("would copy %s to %s\n", szSrcPath, szDstPath);
}
SHFree(pidl);
}
IPersistFolder2_Release(ppf2);
}
return S_OK;
}
static ICOM_VTABLE(ISFHelper) shvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
ISFHelper_fnQueryInterface,
ISFHelper_fnAddRef,
ISFHelper_fnRelease,
ISFHelper_fnGetUniqueName,
ISFHelper_fnAddFolder,
ISFHelper_fnDeleteItems,
ISFHelper_fnCopyItems,
};
/***********************************************************************
* [Desktopfolder] IShellFolder implementation
*/
static struct ICOM_VTABLE(IShellFolder2) sfdvt;
static shvheader DesktopSFHeader [] =
{
{ IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
{ IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
{ IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
{ IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
{ IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 }
};
#define DESKTOPSHELLVIEWCOLUMNS 5
/**************************************************************************
* ISF_Desktop_Constructor
*
*/
HRESULT WINAPI ISF_Desktop_Constructor (
IUnknown * pUnkOuter,
REFIID riid,
LPVOID * ppv)
{
IGenericSFImpl * sf;
TRACE("unkOut=%p %s\n",pUnkOuter, shdebugstr_guid(riid));
if(!ppv) return E_POINTER;
if(pUnkOuter ) {
FIXME("CLASS_E_NOAGGREGATION\n");
return CLASS_E_NOAGGREGATION;
}
sf=(IGenericSFImpl*) LocalAlloc(GMEM_ZEROINIT,sizeof(IGenericSFImpl));
sf->ref=1;
ICOM_VTBL(sf)=&unkvt;
sf->lpvtblShellFolder=&sfdvt;
sf->pidlRoot=_ILCreateDesktop(); /* my qualified pidl */
sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
*ppv = _IShellFolder_(sf);
shell32_ObjCount++;
TRACE("--(%p)\n",sf);
return S_OK;
}
/**************************************************************************
* ISF_Desktop_fnQueryInterface
*
* NOTES supports not IPersist/IPersistFolder
*/
static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
IShellFolder2 * iface,
REFIID riid,
LPVOID *ppvObj)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
TRACE("(%p)->(%s,%p)\n",This,shdebugstr_guid(riid),ppvObj);
*ppvObj = NULL;
if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
{
*ppvObj = _IUnknown_(This);
}
else if(IsEqualIID(riid, &IID_IShellFolder)) /*IShellFolder*/
{
*ppvObj = _IShellFolder_(This);
}
else if(IsEqualIID(riid, &IID_IShellFolder2)) /*IShellFolder2*/
{
*ppvObj = _IShellFolder_(This);
}
if(*ppvObj)
{
IUnknown_AddRef((IUnknown*)(*ppvObj));
TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
return S_OK;
}
TRACE("-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
/**************************************************************************
* ISF_Desktop_fnParseDisplayName
*
* NOTES
* "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
* to MyComputer
*/
static HRESULT WINAPI ISF_Desktop_fnParseDisplayName(
IShellFolder2 * iface,
HWND hwndOwner,
LPBC pbcReserved,
LPOLESTR lpszDisplayName,
DWORD *pchEaten,
LPITEMIDLIST *ppidl,
DWORD *pdwAttributes)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
WCHAR szElement[MAX_PATH];
LPCWSTR szNext=NULL;
LPITEMIDLIST pidlTemp=NULL;
HRESULT hr=E_OUTOFMEMORY;
CLSID clsid;
TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
This,hwndOwner,pbcReserved,lpszDisplayName,
debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
*ppidl = 0;
if (pchEaten) *pchEaten = 0; /* strange but like the original */
if(lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':') {
szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
TRACE("-- element: %s\n", debugstr_w(szElement));
CLSIDFromString(szElement+2, &clsid);
TRACE("-- %s\n", shdebugstr_guid(&clsid));
pidlTemp = _ILCreate(PT_MYCOMP, &clsid, sizeof(clsid));
} else {
pidlTemp = _ILCreateMyComputer();
/* it's a filesystem path, so we cant cut anything away */
szNext = lpszDisplayName;
}
if (szNext && *szNext)
{
hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
}
else
{
hr = S_OK;
if (pdwAttributes && *pdwAttributes)
{
SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
}
}
*ppidl = pidlTemp;
TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
return hr;
}
/**************************************************************************
* ISF_Desktop_fnEnumObjects
*/
static HRESULT WINAPI ISF_Desktop_fnEnumObjects(
IShellFolder2 * iface,
HWND hwndOwner,
DWORD dwFlags,
LPENUMIDLIST* ppEnumIDList)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
*ppEnumIDList = NULL;
*ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_DESK);
TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
if(!*ppEnumIDList) return E_OUTOFMEMORY;
return S_OK;
}
/**************************************************************************
* ISF_Desktop_fnBindToObject
*/
static HRESULT WINAPI ISF_Desktop_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
GUID const * clsid;
IShellFolder *pShellFolder, *pSubFolder;
IGenericSFImpl *pSFImpl;
HRESULT hr;
TRACE("(%p)->(pidl=%p,%p,%s,%p)\n",
This,pidl,pbcReserved,shdebugstr_guid(riid),ppvOut);
*ppvOut = NULL;
if ((clsid=_ILGetGUIDPointer(pidl)))
{
if ( IsEqualIID(clsid, &CLSID_MyComputer))
{
pShellFolder = ISF_MyComputer_Constructor();
}
else
{
/* shell extension */
if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->pidlRoot, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
{
return E_INVALIDARG;
}
}
}
else
{
/* file system folder on the desktop */
LPITEMIDLIST deskpidl, firstpidl, completepidl;
IPersistFolder * ppf;
/* combine pidls */
if ((pSFImpl = IShellFolder_Constructor())) {
pShellFolder = _IShellFolder_(pSFImpl);
if (SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&ppf))) {
SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, &deskpidl);
firstpidl = ILCloneFirst(pidl);
completepidl = ILCombine(deskpidl, firstpidl);
IPersistFolder_Initialize(ppf, completepidl);
IPersistFolder_Release(ppf);
ILFree(completepidl);
ILFree(deskpidl);
ILFree(firstpidl);
}
}
}
if (_ILIsPidlSimple(pidl)) /* no sub folders */
{
*ppvOut = pShellFolder;
hr = S_OK;
}
else /* go deeper */
{
hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, riid, (LPVOID)&pSubFolder);
IShellFolder_Release(pShellFolder);
*ppvOut = pSubFolder;
}
TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
return hr;
}
/**************************************************************************
* ISF_Desktop_fnCreateViewObject
*/
static HRESULT WINAPI ISF_Desktop_fnCreateViewObject( IShellFolder2 * iface,
HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
LPSHELLVIEW pShellView;
HRESULT hr = E_INVALIDARG;
TRACE("(%p)->(hwnd=0x%x,%s,%p)\n",This,hwndOwner,shdebugstr_guid(riid),ppvOut);
if(ppvOut)
{
*ppvOut = NULL;
if(IsEqualIID(riid, &IID_IDropTarget))
{
WARN("IDropTarget not implemented\n");
hr = E_NOTIMPL;
}
else if(IsEqualIID(riid, &IID_IContextMenu))
{
WARN("IContextMenu not implemented\n");
hr = E_NOTIMPL;
}
else if(IsEqualIID(riid, &IID_IShellView))
{
pShellView = IShellView_Constructor((IShellFolder*)iface);
if(pShellView)
{
hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
IShellView_Release(pShellView);
}
}
}
TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
return hr;
}
/**************************************************************************
* ISF_Desktop_fnGetAttributesOf
*/
static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf(
IShellFolder2 * iface,
UINT cidl,
LPCITEMIDLIST *apidl,
DWORD *rgfInOut)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
HRESULT hr = S_OK;
TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl, *rgfInOut);
if ( (!cidl) || (!apidl) || (!rgfInOut))
return E_INVALIDARG;
while (cidl > 0 && *apidl)
{
pdump (*apidl);
SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
apidl++;
cidl--;
}
TRACE("-- result=0x%08lx\n",*rgfInOut);
return hr;
}
/**************************************************************************
* ISF_Desktop_fnGetDisplayNameOf
*
* NOTES
* special case: pidl = null gives desktop-name back
*/
static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf(
IShellFolder2 * iface,
LPCITEMIDLIST pidl,
DWORD dwFlags,
LPSTRRET strRet)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
CHAR szPath[MAX_PATH]= "";
TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
pdump(pidl);
if(!strRet) return E_INVALIDARG;
if(!pidl)
{
HCR_GetClassName(&CLSID_ShellDesktop, szPath, MAX_PATH);
}
else if ( _ILIsPidlSimple(pidl) )
{
_ILSimpleGetText(pidl, szPath, MAX_PATH);
}
else
{
if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath, MAX_PATH)))
return E_OUTOFMEMORY;
}
strRet->uType = STRRET_CSTR;
lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
TRACE("-- (%p)->(%s)\n", This, szPath);
return S_OK;
}
static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID(
IShellFolder2 * iface,
GUID *pguid)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
FIXME("(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI ISF_Desktop_fnEnumSearches(
IShellFolder2 * iface,
IEnumExtraSearch **ppenum)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
FIXME("(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumn(
IShellFolder2 * iface,
DWORD dwRes,
ULONG *pSort,
ULONG *pDisplay)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
TRACE("(%p)\n",This);
if (pSort) *pSort = 0;
if (pDisplay) *pDisplay = 0;
return S_OK;
}
static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumnState(
IShellFolder2 * iface,
UINT iColumn,
DWORD *pcsFlags)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
TRACE("(%p)\n",This);
if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
*pcsFlags = DesktopSFHeader[iColumn].pcsFlags;
return S_OK;
}
static HRESULT WINAPI ISF_Desktop_fnGetDetailsEx(
IShellFolder2 * iface,
LPCITEMIDLIST pidl,
const SHCOLUMNID *pscid,
VARIANT *pv)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
FIXME("(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf(
IShellFolder2 * iface,
LPCITEMIDLIST pidl,
UINT iColumn,
SHELLDETAILS *psd)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
HRESULT hr = E_FAIL;
TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
if (!pidl)
{
psd->fmt = DesktopSFHeader[iColumn].fmt;
psd->cxChar = DesktopSFHeader[iColumn].cxChar;
psd->str.uType = STRRET_CSTR;
LoadStringA(shell32_hInstance, DesktopSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
return S_OK;
}
else
{
/* the data from the pidl */
switch(iColumn)
{
case 0: /* name */
hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
break;
case 1: /* size */
_ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
break;
case 2: /* type */
_ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
break;
case 3: /* date */
_ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
break;
case 4: /* attributes */
_ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
break;
}
hr = S_OK;
psd->str.uType = STRRET_CSTR;
}
return hr;
}
static HRESULT WINAPI ISF_Desktop_fnMapNameToSCID(
IShellFolder2 * iface,
LPCWSTR pwszName,
SHCOLUMNID *pscid)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
FIXME("(%p)\n",This);
return E_NOTIMPL;
}
static ICOM_VTABLE(IShellFolder2) sfdvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
ISF_Desktop_fnQueryInterface,
IShellFolder_fnAddRef,
IShellFolder_fnRelease,
ISF_Desktop_fnParseDisplayName,
ISF_Desktop_fnEnumObjects,
ISF_Desktop_fnBindToObject,
IShellFolder_fnBindToStorage,
IShellFolder_fnCompareIDs,
ISF_Desktop_fnCreateViewObject,
ISF_Desktop_fnGetAttributesOf,
IShellFolder_fnGetUIObjectOf,
ISF_Desktop_fnGetDisplayNameOf,
IShellFolder_fnSetNameOf,
/* ShellFolder2 */
ISF_Desktop_fnGetDefaultSearchGUID,
ISF_Desktop_fnEnumSearches,
ISF_Desktop_fnGetDefaultColumn,
ISF_Desktop_fnGetDefaultColumnState,
ISF_Desktop_fnGetDetailsEx,
ISF_Desktop_fnGetDetailsOf,
ISF_Desktop_fnMapNameToSCID
};
/***********************************************************************
* IShellFolder [MyComputer] implementation
*/
static struct ICOM_VTABLE(IShellFolder2) sfmcvt;
static shvheader MyComputerSFHeader [] =
{
{ IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
{ IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
{ IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
{ IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
};
#define MYCOMPUTERSHELLVIEWCOLUMNS 4
/**************************************************************************
* ISF_MyComputer_Constructor
*/
static IShellFolder * ISF_MyComputer_Constructor(void)
{
IGenericSFImpl * sf;
sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
sf->ref=1;
ICOM_VTBL(sf)=&unkvt;
sf->lpvtblShellFolder=&sfmcvt;
sf->lpvtblPersistFolder3 = &psfvt;
sf->pclsid = (CLSID*)&CLSID_MyComputer;
sf->pidlRoot=_ILCreateMyComputer(); /* my qualified pidl */
sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
TRACE("(%p)\n",sf);
shell32_ObjCount++;
return _IShellFolder_(sf);
}
/**************************************************************************
* ISF_MyComputer_fnParseDisplayName
*/
static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName(
IShellFolder2 * iface,
HWND hwndOwner,
LPBC pbcReserved,
LPOLESTR lpszDisplayName,
DWORD *pchEaten,
LPITEMIDLIST *ppidl,
DWORD *pdwAttributes)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
HRESULT hr = E_OUTOFMEMORY;
LPCWSTR szNext=NULL;
WCHAR szElement[MAX_PATH];
CHAR szTempA[MAX_PATH];
LPITEMIDLIST pidlTemp;
TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
This,hwndOwner,pbcReserved,lpszDisplayName,
debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
*ppidl = 0;
if (pchEaten) *pchEaten = 0; /* strange but like the original */
/* do we have an absolute path name ? */
if (PathGetDriveNumberW(lpszDisplayName) >= 0 &&
lpszDisplayName[2] == (WCHAR)'\\')
{
szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
WideCharToMultiByte( CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL );
pidlTemp = _ILCreateDrive(szTempA);
if (szNext && *szNext)
{
hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
}
else
{
if (pdwAttributes && *pdwAttributes)
{
SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
}
hr = S_OK;
}
*ppidl = pidlTemp;
}
TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
return hr;
}
/**************************************************************************
* ISF_MyComputer_fnEnumObjects
*/
static HRESULT WINAPI ISF_MyComputer_fnEnumObjects(
IShellFolder2 * iface,
HWND hwndOwner,
DWORD dwFlags,
LPENUMIDLIST* ppEnumIDList)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
*ppEnumIDList = NULL;
*ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_MYCOMP);
TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
if(!*ppEnumIDList) return E_OUTOFMEMORY;
return S_OK;
}
/**************************************************************************
* ISF_MyComputer_fnBindToObject
*/
static HRESULT WINAPI ISF_MyComputer_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
GUID const * clsid;
IShellFolder *pShellFolder, *pSubFolder;
IGenericSFImpl *pSFImpl;
LPITEMIDLIST pidltemp;
HRESULT hr;
TRACE("(%p)->(pidl=%p,%p,%s,%p)\n",
This,pidl,pbcReserved,shdebugstr_guid(riid),ppvOut);
if(!pidl || !ppvOut) return E_INVALIDARG;
*ppvOut = NULL;
if ((clsid=_ILGetGUIDPointer(pidl)) && !IsEqualIID(clsid, &CLSID_MyComputer))
{
if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->pidlRoot, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
{
return E_FAIL;
}
}
else
{
if (!_ILIsDrive(pidl)) return E_INVALIDARG;
if ((pSFImpl = IShellFolder_Constructor())) {
pidltemp = ILCloneFirst(pidl);
InitializeGenericSF(pSFImpl, This->pidlRoot, pidltemp, This->sPathRoot);
ILFree(pidltemp);
pShellFolder = _IShellFolder_(pSFImpl);
}
}
if (_ILIsPidlSimple(pidl)) /* no sub folders */
{
*ppvOut = pShellFolder;
hr = S_OK;
}
else /* go deeper */
{
hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL,
riid, (LPVOID)&pSubFolder);
IShellFolder_Release(pShellFolder);
*ppvOut = pSubFolder;
}
TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
return hr;
}
/**************************************************************************
* ISF_MyComputer_fnCreateViewObject
*/
static HRESULT WINAPI ISF_MyComputer_fnCreateViewObject( IShellFolder2 * iface,
HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
LPSHELLVIEW pShellView;
HRESULT hr = E_INVALIDARG;
TRACE("(%p)->(hwnd=0x%x,%s,%p)\n",This,hwndOwner,shdebugstr_guid(riid),ppvOut);
if(ppvOut)
{
*ppvOut = NULL;
if(IsEqualIID(riid, &IID_IDropTarget))
{
WARN("IDropTarget not implemented\n");
hr = E_NOTIMPL;
}
else if(IsEqualIID(riid, &IID_IContextMenu))
{
WARN("IContextMenu not implemented\n");
hr = E_NOTIMPL;
}
else if(IsEqualIID(riid, &IID_IShellView))
{
pShellView = IShellView_Constructor((IShellFolder*)iface);
if(pShellView)
{
hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
IShellView_Release(pShellView);
}
}
}
TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
return hr;
}
/**************************************************************************
* ISF_MyComputer_fnGetAttributesOf
*/
static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf(
IShellFolder2 * iface,
UINT cidl,
LPCITEMIDLIST *apidl,
DWORD *rgfInOut)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
HRESULT hr = S_OK;
TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
if ( (!cidl) || (!apidl) || (!rgfInOut))
return E_INVALIDARG;
while (cidl > 0 && *apidl)
{
pdump (*apidl);
SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
apidl++;
cidl--;
}
TRACE("-- result=0x%08lx\n",*rgfInOut);
return hr;
}
/**************************************************************************
* ISF_MyComputer_fnGetDisplayNameOf
*
* NOTES
* The desktopfolder creates only complete paths (SHGDN_FORPARSING).
* SHGDN_INFOLDER makes no sense.
*/
static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf(
IShellFolder2 * iface,
LPCITEMIDLIST pidl,
DWORD dwFlags,
LPSTRRET strRet)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
char szPath[MAX_PATH], szDrive[18];
int len = 0;
BOOL bSimplePidl;
TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
pdump(pidl);
if(!strRet) return E_INVALIDARG;
szPath[0]=0x00; szDrive[0]=0x00;
bSimplePidl = _ILIsPidlSimple(pidl);
if (_ILIsSpecialFolder(pidl))
{
/* take names of special folders only if its only this folder */
if ( bSimplePidl )
{
_ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
}
}
else
{
if (!_ILIsDrive(pidl))
{
ERR("Wrong pidl type\n");
return E_INVALIDARG;
}
_ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
/* long view "lw_name (C:)" */
if ( bSimplePidl && !(dwFlags & SHGDN_FORPARSING))
{
DWORD dwVolumeSerialNumber,dwMaximumComponetLength,dwFileSystemFlags;
GetVolumeInformationA(szPath,szDrive,sizeof(szDrive)-6,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
strcat (szDrive," (");
strncat (szDrive, szPath, 2);
strcat (szDrive,")");
strcpy (szPath, szDrive);
}
}
if (!bSimplePidl) /* go deeper if needed */
{
PathAddBackslashA(szPath);
len = strlen(szPath);
if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags | SHGDN_FORPARSING, szPath + len, MAX_PATH - len)))
return E_OUTOFMEMORY;
}
strRet->uType = STRRET_CSTR;
lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
TRACE("-- (%p)->(%s)\n", This, szPath);
return S_OK;
}
static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID(
IShellFolder2 * iface,
GUID *pguid)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
FIXME("(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI ISF_MyComputer_fnEnumSearches(
IShellFolder2 * iface,
IEnumExtraSearch **ppenum)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
FIXME("(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn(
IShellFolder2 * iface,
DWORD dwRes,
ULONG *pSort,
ULONG *pDisplay)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
TRACE("(%p)\n",This);
if (pSort) *pSort = 0;
if (pDisplay) *pDisplay = 0;
return S_OK;
}
static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState(
IShellFolder2 * iface,
UINT iColumn,
DWORD *pcsFlags)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
TRACE("(%p)\n",This);
if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
*pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
return S_OK;
}
static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx(
IShellFolder2 * iface,
LPCITEMIDLIST pidl,
const SHCOLUMNID *pscid,
VARIANT *pv)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
FIXME("(%p)\n",This);
return E_NOTIMPL;
}
/* FIXME: drive size >4GB is rolling over */
static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf(
IShellFolder2 * iface,
LPCITEMIDLIST pidl,
UINT iColumn,
SHELLDETAILS *psd)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
HRESULT hr;
TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
if (!pidl)
{
psd->fmt = MyComputerSFHeader[iColumn].fmt;
psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
psd->str.uType = STRRET_CSTR;
LoadStringA(shell32_hInstance, MyComputerSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
return S_OK;
}
else
{
char szPath[MAX_PATH];
ULARGE_INTEGER ulBytes;
psd->str.u.cStr[0] = 0x00;
psd->str.uType = STRRET_CSTR;
switch(iColumn)
{
case 0: /* name */
hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
break;
case 1: /* type */
_ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
break;
case 2: /* total size */
if (_ILIsDrive(pidl))
{
_ILSimpleGetText(pidl, szPath, MAX_PATH);
GetDiskFreeSpaceExA(szPath, NULL, &ulBytes, NULL);
StrFormatByteSizeA(ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
}
break;
case 3: /* free size */
if (_ILIsDrive(pidl))
{
_ILSimpleGetText(pidl, szPath, MAX_PATH);
GetDiskFreeSpaceExA(szPath, &ulBytes, NULL, NULL);
StrFormatByteSizeA(ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
}
break;
}
hr = S_OK;
}
return hr;
}
static HRESULT WINAPI ISF_MyComputer_fnMapNameToSCID(
IShellFolder2 * iface,
LPCWSTR pwszName,
SHCOLUMNID *pscid)
{
_ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
FIXME("(%p)\n",This);
return E_NOTIMPL;
}
static ICOM_VTABLE(IShellFolder2) sfmcvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IShellFolder_fnQueryInterface,
IShellFolder_fnAddRef,
IShellFolder_fnRelease,
ISF_MyComputer_fnParseDisplayName,
ISF_MyComputer_fnEnumObjects,
ISF_MyComputer_fnBindToObject,
IShellFolder_fnBindToStorage,
IShellFolder_fnCompareIDs,
ISF_MyComputer_fnCreateViewObject,
ISF_MyComputer_fnGetAttributesOf,
IShellFolder_fnGetUIObjectOf,
ISF_MyComputer_fnGetDisplayNameOf,
IShellFolder_fnSetNameOf,
/* ShellFolder2 */
ISF_MyComputer_fnGetDefaultSearchGUID,
ISF_MyComputer_fnEnumSearches,
ISF_MyComputer_fnGetDefaultColumn,
ISF_MyComputer_fnGetDefaultColumnState,
ISF_MyComputer_fnGetDetailsEx,
ISF_MyComputer_fnGetDetailsOf,
ISF_MyComputer_fnMapNameToSCID
};
/************************************************************************
* ISFPersistFolder_QueryInterface (IUnknown)
*
*/
static HRESULT WINAPI ISFPersistFolder3_QueryInterface(
IPersistFolder3 * iface,
REFIID iid,
LPVOID* ppvObj)
{
_ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
TRACE("(%p)\n", This);
return IUnknown_QueryInterface(This->pUnkOuter, iid, ppvObj);
}
/************************************************************************
* ISFPersistFolder_AddRef (IUnknown)
*
*/
static ULONG WINAPI ISFPersistFolder3_AddRef(
IPersistFolder3 * iface)
{
_ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
TRACE("(%p)->(count=%lu)\n",This,This->ref);
return IUnknown_AddRef(This->pUnkOuter);
}
/************************************************************************
* ISFPersistFolder_Release (IUnknown)
*
*/
static ULONG WINAPI ISFPersistFolder3_Release(
IPersistFolder3 * iface)
{
_ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
TRACE("(%p)->(count=%lu)\n",This,This->ref);
return IUnknown_Release(This->pUnkOuter);
}
/************************************************************************
* ISFPersistFolder_GetClassID (IPersist)
*/
static HRESULT WINAPI ISFPersistFolder3_GetClassID(
IPersistFolder3 * iface,
CLSID * lpClassId)
{
_ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
TRACE("(%p)\n", This);
if (!lpClassId) return E_POINTER;
*lpClassId = *This->pclsid;
return S_OK;
}
/************************************************************************
* ISFPersistFolder_Initialize (IPersistFolder)
*
* NOTES
* sPathRoot is not set. Don't know how to handle in a non rooted environment.
*/
static HRESULT WINAPI ISFPersistFolder3_Initialize(
IPersistFolder3 * iface,
LPCITEMIDLIST pidl)
{
char sTemp[MAX_PATH];
_ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
TRACE("(%p)->(%p)\n", This, pidl);
if(This->pidlRoot) SHFree(This->pidlRoot); /* free the old pidl */
This->pidlRoot = ILClone(pidl); /* set my pidl */
if(This->sPathRoot) SHFree(This->sPathRoot);
/* set my path */
if (SHGetPathFromIDListA(pidl, sTemp))
{
This->sPathRoot = SHAlloc(strlen(sTemp)+1);
strcpy(This->sPathRoot, sTemp);
}
TRACE("--(%p)->(%s)\n", This, This->sPathRoot);
return S_OK;
}
/**************************************************************************
* IPersistFolder2_fnGetCurFolder
*/
static HRESULT WINAPI ISFPersistFolder3_fnGetCurFolder(
IPersistFolder3 * iface,
LPITEMIDLIST * pidl)
{
_ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
TRACE("(%p)->(%p)\n",This, pidl);
if (!pidl) return E_POINTER;
*pidl = ILClone(This->pidlRoot);
return S_OK;
}
static HRESULT WINAPI ISFPersistFolder3_InitializeEx(
IPersistFolder3 * iface,
IBindCtx * pbc,
LPCITEMIDLIST pidlRoot,
const PERSIST_FOLDER_TARGET_INFO *ppfti)
{
char sTemp[MAX_PATH];
_ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
FIXME("(%p)->(%p,%p,%p)\n",This,pbc,pidlRoot,ppfti);
TRACE("--%p %s %s 0x%08lx 0x%08x\n",
ppfti->pidlTargetFolder, debugstr_w(ppfti->szTargetParsingName),
debugstr_w(ppfti->szNetworkProvider), ppfti->dwAttributes, ppfti->csidl);
pdump(pidlRoot);
if(ppfti->pidlTargetFolder) pdump(ppfti->pidlTargetFolder);
if(This->pidlRoot) SHFree(This->pidlRoot); /* free the old pidl */
if(ppfti->csidl == -1) { /* set my pidl */
This->pidlRoot = ILClone(ppfti->pidlTargetFolder);
} else {
SHGetSpecialFolderLocation(0, ppfti->csidl, &This->pidlRoot);
}
if(This->sPathRoot) SHFree(This->sPathRoot);
/* set my path */
if (SHGetPathFromIDListA(This->pidlRoot, sTemp))
{
This->sPathRoot = SHAlloc(strlen(sTemp)+1);
strcpy(This->sPathRoot, sTemp);
}
TRACE("--(%p)->(%s)\n", This, This->sPathRoot);
return S_OK;
}
static HRESULT WINAPI ISFPersistFolder3_GetFolderTargetInfo(
IPersistFolder3 *iface,
PERSIST_FOLDER_TARGET_INFO *ppfti)
{
_ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
FIXME("(%p)->(%p)\n",This,ppfti);
ZeroMemory(ppfti, sizeof(ppfti));
return E_NOTIMPL;
}
static ICOM_VTABLE(IPersistFolder3) psfvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
ISFPersistFolder3_QueryInterface,
ISFPersistFolder3_AddRef,
ISFPersistFolder3_Release,
ISFPersistFolder3_GetClassID,
ISFPersistFolder3_Initialize,
ISFPersistFolder3_fnGetCurFolder,
ISFPersistFolder3_InitializeEx,
ISFPersistFolder3_GetFolderTargetInfo
};
/****************************************************************************
* ISFDropTarget implementation
*/
static BOOL ISFDropTarget_QueryDrop(
IDropTarget *iface,
DWORD dwKeyState,
LPDWORD pdwEffect)
{
DWORD dwEffect = *pdwEffect;
_ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
*pdwEffect = DROPEFFECT_NONE;
if (This->fAcceptFmt)
{ /* Does our interpretation of the keystate ... */
*pdwEffect = KeyStateToDropEffect(dwKeyState);
/* ... matches the desired effect ? */
if (dwEffect & *pdwEffect)
{
return TRUE;
}
}
return FALSE;
}
static HRESULT WINAPI ISFDropTarget_QueryInterface(
IDropTarget *iface,
REFIID riid,
LPVOID *ppvObj)
{
_ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
TRACE("(%p)\n", This);
return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
}
static ULONG WINAPI ISFDropTarget_AddRef( IDropTarget *iface)
{
_ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
TRACE("(%p)\n", This);
return IUnknown_AddRef(This->pUnkOuter);
}
static ULONG WINAPI ISFDropTarget_Release( IDropTarget *iface)
{
_ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
TRACE("(%p)\n", This);
return IUnknown_Release(This->pUnkOuter);
}
static HRESULT WINAPI ISFDropTarget_DragEnter(
IDropTarget *iface,
IDataObject *pDataObject,
DWORD dwKeyState,
POINTL pt,
DWORD *pdwEffect)
{
FORMATETC fmt;
_ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
TRACE("(%p)->(DataObject=%p)\n",This,pDataObject);
InitFormatEtc(fmt, This->cfShellIDList, TYMED_HGLOBAL);
This->fAcceptFmt = (S_OK == IDataObject_QueryGetData(pDataObject, &fmt)) ? TRUE : FALSE;
ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
return S_OK;
}
static HRESULT WINAPI ISFDropTarget_DragOver(
IDropTarget *iface,
DWORD dwKeyState,
POINTL pt,
DWORD *pdwEffect)
{
_ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
TRACE("(%p)\n",This);
if(!pdwEffect) return E_INVALIDARG;
ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
return S_OK;
}
static HRESULT WINAPI ISFDropTarget_DragLeave(
IDropTarget *iface)
{
_ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
TRACE("(%p)\n",This);
This->fAcceptFmt = FALSE;
return S_OK;
}
static HRESULT WINAPI ISFDropTarget_Drop(
IDropTarget *iface,
IDataObject* pDataObject,
DWORD dwKeyState,
POINTL pt,
DWORD *pdwEffect)
{
_ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
FIXME("(%p) object dropped\n",This);
return E_NOTIMPL;
}
static struct ICOM_VTABLE(IDropTarget) dtvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
ISFDropTarget_QueryInterface,
ISFDropTarget_AddRef,
ISFDropTarget_Release,
ISFDropTarget_DragEnter,
ISFDropTarget_DragOver,
ISFDropTarget_DragLeave,
ISFDropTarget_Drop
};
......@@ -169,7 +169,6 @@ IShellView * IShellView_Constructor( IShellFolder * pFolder)
IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent);
TRACE("(%p)->(%p)\n",sv, pFolder);
shell32_ObjCount++;
return (IShellView *) sv;
}
......@@ -1502,7 +1501,6 @@ static ULONG WINAPI IShellView_fnAddRef(IShellView * iface)
TRACE("(%p)->(count=%lu)\n",This,This->ref);
shell32_ObjCount++;
return ++(This->ref);
}
/**********************************************************
......@@ -1514,8 +1512,6 @@ static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
TRACE("(%p)->()\n",This);
shell32_ObjCount--;
if (!--(This->ref))
{
TRACE(" destroying IShellView(%p)\n",This);
......@@ -1529,9 +1525,6 @@ static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
if (This->apidl)
SHFree(This->apidl);
if (This->pCommDlgBrowser)
ICommDlgBrowser_Release(This->pCommDlgBrowser);
HeapFree(GetProcessHeap(),0,This);
return 0;
}
......@@ -1733,7 +1726,9 @@ static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface)
}
DestroyWindow(This->hWnd);
IShellBrowser_Release(This->pShellBrowser);
if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
return S_OK;
}
......@@ -2272,4 +2267,3 @@ static struct ICOM_VTABLE(IViewObject) vovt =
ISVViewObject_SetAdvise,
ISVViewObject_GetAdvise
};
......@@ -61,7 +61,6 @@ IContextMenu *ISvBgCm_Constructor(IShellFolder* pSFParent)
if(pSFParent) IShellFolder_AddRef(pSFParent);
TRACE("(%p)->()\n",cm);
shell32_ObjCount++;
return (IContextMenu*)cm;
}
......@@ -108,7 +107,6 @@ static ULONG WINAPI ISVBgCm_fnAddRef(IContextMenu *iface)
TRACE("(%p)->(count=%lu)\n",This, This->ref);
shell32_ObjCount++;
return ++(This->ref);
}
......@@ -132,8 +130,6 @@ static ULONG WINAPI ISVBgCm_fnRelease(IContextMenu *iface)
return 0;
}
shell32_ObjCount--;
return This->ref;
}
......@@ -428,4 +424,3 @@ static struct ICOM_VTABLE(IContextMenu) cmvt =
ISVBgCm_fnHandleMenuMsg,
(void *) 0xdeadbabe /* just paranoia (IContextMenu3) */
};
......@@ -98,7 +98,6 @@ IContextMenu *ISvItemCm_Constructor(LPSHELLFOLDER pSFParent, LPCITEMIDLIST pidl,
TRACE("(%p)->()\n",cm);
shell32_ObjCount++;
return (IContextMenu*)cm;
}
......@@ -145,7 +144,6 @@ static ULONG WINAPI ISvItemCm_fnAddRef(IContextMenu *iface)
TRACE("(%p)->(count=%lu)\n",This, This->ref);
shell32_ObjCount++;
return ++(This->ref);
}
......@@ -158,8 +156,6 @@ static ULONG WINAPI ISvItemCm_fnRelease(IContextMenu *iface)
TRACE("(%p)->()\n",This);
shell32_ObjCount--;
if (!--(This->ref))
{
TRACE(" destroying IContextMenu(%p)\n",This);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment