From 1e5ec8893db155931d6367c8860700592cc8c9fb Mon Sep 17 00:00:00 2001 From: Juergen Schmied Date: Wed, 24 Jul 2002 01:56:03 +0000 Subject: [PATCH] - Cleaned up the implementation of shell folders and put them into separate files. - Fixed some memory leaks. - Some more fixes. --- dlls/shell32/Makefile.in | 9 +- dlls/shell32/brsfolder.c | 7 +- dlls/shell32/classes.c | 33 +- dlls/shell32/dataobject.c | 14 +- dlls/shell32/debughlp.c | 20 +- dlls/shell32/enumidlist.c | 26 +- dlls/shell32/folders.c | 6 - dlls/shell32/memorystream.c | 5 - dlls/shell32/pidl.c | 57 +- dlls/shell32/shell32_main.c | 37 +- dlls/shell32/shell32_main.h | 22 +- dlls/shell32/shelllink.c | 3 - dlls/shell32/shellole.c | 50 +- dlls/shell32/shellstring.c | 39 +- dlls/shell32/shfldr.h | 48 + dlls/shell32/shfldr_desktop.c | 664 ++++++++ dlls/shell32/shfldr_fs.c | 1356 +++++++++++++++ dlls/shell32/shfldr_mycomp.c | 711 ++++++++ dlls/shell32/shlfolder.c | 3029 +++------------------------------ dlls/shell32/shlview.c | 12 +- dlls/shell32/shv_bg_cmenu.c | 5 - dlls/shell32/shv_item_cmenu.c | 4 - 22 files changed, 3200 insertions(+), 2957 deletions(-) create mode 100644 dlls/shell32/shfldr.h create mode 100644 dlls/shell32/shfldr_desktop.c create mode 100644 dlls/shell32/shfldr_fs.c create mode 100644 dlls/shell32/shfldr_mycomp.c diff --git a/dlls/shell32/Makefile.in b/dlls/shell32/Makefile.in index ed7debd186..3bf59ed61b 100644 --- a/dlls/shell32/Makefile.in +++ b/dlls/shell32/Makefile.in @@ -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 \ diff --git a/dlls/shell32/brsfolder.c b/dlls/shell32/brsfolder.c index 2b0437a382..c1dd646c88 100644 --- a/dlls/shell32/brsfolder.c +++ b/dlls/shell32/brsfolder.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 @@ -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; diff --git a/dlls/shell32/classes.c b/dlls/shell32/classes.c index 9f1af168c1..d8bc72356a 100644 --- a/dlls/shell32/classes.c +++ b/dlls/shell32/classes.c @@ -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); diff --git a/dlls/shell32/dataobject.c b/dlls/shell32/dataobject.c index 514e9117cb..ac246d3446 100644 --- a/dlls/shell32/dataobject.c +++ b/dlls/shell32/dataobject.c @@ -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 }; - diff --git a/dlls/shell32/debughlp.c b/dlls/shell32/debughlp.c index 350b9284f2..a7f6c5e330 100644 --- a/dlls/shell32/debughlp.c +++ b/dlls/shell32/debughlp.c @@ -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 { diff --git a/dlls/shell32/enumidlist.c b/dlls/shell32/enumidlist.c index 7d61cc0417..75455ac7d9 100644 --- a/dlls/shell32/enumidlist.c +++ b/dlls/shell32/enumidlist.c @@ -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; diff --git a/dlls/shell32/folders.c b/dlls/shell32/folders.c index a63fce6050..43c87731fe 100644 --- a/dlls/shell32/folders.c +++ b/dlls/shell32/folders.c @@ -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 */ }; - diff --git a/dlls/shell32/memorystream.c b/dlls/shell32/memorystream.c index 5e86162c19..d9ae48c503 100644 --- a/dlls/shell32/memorystream.c +++ b/dlls/shell32/memorystream.c @@ -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); diff --git a/dlls/shell32/pidl.c b/dlls/shell32/pidl.c index 61279aafea..863fd314ba 100644 --- a/dlls/shell32/pidl.c +++ b/dlls/shell32/pidl.c @@ -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); } /************************************************************************* diff --git a/dlls/shell32/shell32_main.c b/dlls/shell32/shell32_main.c index 7a7f9ec958..c26eb1d176 100644 --- a/dlls/shell32/shell32_main.c +++ b/dlls/shell32/shell32_main.c @@ -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; diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h index ada04a375f..a31b39ae2f 100644 --- a/dlls/shell32/shell32_main.h +++ b/dlls/shell32/shell32_main.h @@ -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 diff --git a/dlls/shell32/shelllink.c b/dlls/shell32/shelllink.c index 263b238092..32a40e621d 100644 --- a/dlls/shell32/shelllink.c +++ b/dlls/shell32/shelllink.c @@ -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); diff --git a/dlls/shell32/shellole.c b/dlls/shell32/shellole.c index d9e3d4de08..54f8bfdd2c 100644 --- a/dlls/shell32/shellole.c +++ b/dlls/shell32/shellole.c @@ -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; diff --git a/dlls/shell32/shellstring.c b/dlls/shell32/shellstring.c index 8f7e6d4d17..7c6ef1390a 100644 --- a/dlls/shell32/shellstring.c +++ b/dlls/shell32/shellstring.c @@ -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; diff --git a/dlls/shell32/shfldr.h b/dlls/shell32/shfldr.h new file mode 100644 index 0000000000..474072920b --- /dev/null +++ b/dlls/shell32/shfldr.h @@ -0,0 +1,48 @@ + +/* + * 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); diff --git a/dlls/shell32/shfldr_desktop.c b/dlls/shell32/shfldr_desktop.c new file mode 100644 index 0000000000..22564d918d --- /dev/null +++ b/dlls/shell32/shfldr_desktop.c @@ -0,0 +1,664 @@ + +/* + * 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 +#include +#include + +#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}; diff --git a/dlls/shell32/shfldr_fs.c b/dlls/shell32/shfldr_fs.c new file mode 100644 index 0000000000..0fec859dcf --- /dev/null +++ b/dlls/shell32/shfldr_fs.c @@ -0,0 +1,1356 @@ + +/* + * 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 +#include +#include + +#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 +}; diff --git a/dlls/shell32/shfldr_mycomp.c b/dlls/shell32/shfldr_mycomp.c new file mode 100644 index 0000000000..a71a716912 --- /dev/null +++ b/dlls/shell32/shfldr_mycomp.c @@ -0,0 +1,711 @@ + +/* + * 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 +#include +#include + +#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 +}; diff --git a/dlls/shell32/shlfolder.c b/dlls/shell32/shlfolder.c index e93db0234a..93a991f569 100644 --- a/dlls/shell32/shlfolder.c +++ b/dlls/shell32/shlfolder.c @@ -1,8 +1,9 @@ + /* * 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(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; isPathRoot); - 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 -}; diff --git a/dlls/shell32/shlview.c b/dlls/shell32/shlview.c index bd9085d60b..a5d5ab34f2 100644 --- a/dlls/shell32/shlview.c +++ b/dlls/shell32/shlview.c @@ -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 }; - diff --git a/dlls/shell32/shv_bg_cmenu.c b/dlls/shell32/shv_bg_cmenu.c index 9cd9e7315a..45cf52ab35 100644 --- a/dlls/shell32/shv_bg_cmenu.c +++ b/dlls/shell32/shv_bg_cmenu.c @@ -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) */ }; - diff --git a/dlls/shell32/shv_item_cmenu.c b/dlls/shell32/shv_item_cmenu.c index 63eddd4877..43b4078b5c 100644 --- a/dlls/shell32/shv_item_cmenu.c +++ b/dlls/shell32/shv_item_cmenu.c @@ -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); -- 2.32.0.93.g670b81a890