/* * Shell Folder stuff * * Copyright 1997 Marcus Meissner * Copyright 1998, 1999 Juergen Schmied * * IShellFolder2 and related interfaces * */ #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 "debugtools.h" DEFAULT_DEBUG_CHANNEL(shell); /*************************************************************************** * debughelper: print out the return adress * helps especially to track down unbalanced AddRef/Release */ #define MEM_DEBUG 0 #if MEM_DEBUG #define _CALL_TRACE TRACE("called from: 0x%08x\n", *( ((UINT*)&iface)-1 )); #else #define _CALL_TRACE #endif typedef struct { int colnameid; int pcsFlags; int fmt; int cxChar; } shvheader; /*************************************************************************** * GetNextElement (internal function) * * gets a part of a string till the first backslash * * PARAMETERS * pszNext [IN] string to get the element from * pszOut [IN] pointer to buffer whitch receives string * dwOut [IN] length of pszOut * * RETURNS * 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); *pszOut=0x0000; if(!pszNext || !*pszNext) return NULL; 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); } IShellFolder_Release(psfChild); } ILFree(pidlFirst); } TRACE("-- ret=0x%08lx %s\n", hr, szOut); return hr; } /*********************************************************************** * 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 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(IPersistFolder2)* lpvtblPersistFolder2; ICOM_VTABLE(IDropTarget)* lpvtblDropTarget; ICOM_VTABLE(ISFHelper)* lpvtblSFHelper; IUnknown *pUnkOuter; /* used for aggregation */ CLSID* pclsid; LPSTR sMyPath; LPITEMIDLIST absPidl; /* complete pidl */ 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(IPersistFolder2) 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)->lpvtblPersistFolder2))) #define _ICOM_THIS_From_IPersistFolder2(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->lpvtblPersistFolder2) #define _IPersistFolder_(This) (IPersistFolder*)&(This->lpvtblPersistFolder2) #define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpvtblPersistFolder2) #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)->(\n\tIID:\t%s,%p)\n",This,debugstr_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_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 (pdesktopfolder == _IShellFolder_(This)) { pdesktopfolder=NULL; TRACE("-- destroyed IShellFolder(%p) was Desktopfolder\n",This); } if(This->absPidl) SHFree(This->absPidl); if(This->sMyPath) SHFree(This->sMyPath); HeapFree(GetProcessHeap(),0,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 /************************************************************************** * IShellFolder_Constructor * * NOTES * creating undocumented ShellFS_Folder as part of an aggregation * {F3364BA0-65B9-11CE-A9BA-00AA004AE837} * * FIXME * when pUnkOuter = 0 then rrid = IID_IShellFolder is returned */ HRESULT IFSFolder_Constructor( IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv) { IGenericSFImpl * sf; HRESULT hr = S_OK; TRACE("unkOut=%p riid=%s\n",pUnkOuter, debugstr_guid(riid)); if(pUnkOuter && ! IsEqualIID(riid, &IID_IUnknown)) { hr = CLASS_E_NOAGGREGATION; /* forbidden by definition */ } else { sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl)); if (sf) { sf->ref=1; ICOM_VTBL(sf)=&unkvt; sf->lpvtblShellFolder=&sfvt; sf->lpvtblPersistFolder2=&psfvt; sf->lpvtblDropTarget=&dtvt; sf->lpvtblSFHelper=&shvt; sf->pclsid = (CLSID*)&CLSID_SFFile; sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_(sf); *ppv = _IUnknown_(sf); hr = S_OK; shell32_ObjCount++; } else { hr = E_OUTOFMEMORY; } } return hr; } /************************************************************************** * IShellFolder_Constructor * * NOTES * THIS points to the parent folder */ IShellFolder * IShellFolder_Constructor( IShellFolder2 * iface, LPITEMIDLIST pidl) { IGenericSFImpl * sf; DWORD dwSize=0; _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface) sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl)); sf->ref=1; ICOM_VTBL(sf)=&unkvt; sf->lpvtblShellFolder=&sfvt; sf->lpvtblPersistFolder2=&psfvt; sf->lpvtblDropTarget=&dtvt; sf->lpvtblSFHelper=&shvt; sf->pclsid = (CLSID*)&CLSID_SFFile; sf->pUnkOuter = _IUnknown_(sf); TRACE("(%p)->(parent=%p, pidl=%p)\n",sf,This, pidl); pdump(pidl); if(pidl && iface) /* do we have a pidl? */ { int len; sf->absPidl = ILCombine(This->absPidl, pidl); /* build a absolute pidl */ if (!_ILIsSpecialFolder(pidl)) /* only file system paths */ { if(This->sMyPath) /* get the size of the parents path */ { dwSize += strlen(This->sMyPath) ; TRACE("-- (%p)->(parent's path=%s)\n",sf, debugstr_a(This->sMyPath)); } dwSize += _ILSimpleGetText(pidl,NULL,0); /* add the size of our name*/ sf->sMyPath = SHAlloc(dwSize + 2); /* '\0' and backslash */ if(!sf->sMyPath) return NULL; *(sf->sMyPath)=0x00; if(This->sMyPath) /* if the parent has a path, get it*/ { strcpy(sf->sMyPath, This->sMyPath); PathAddBackslashA (sf->sMyPath); } len = strlen(sf->sMyPath); _ILSimpleGetText(pidl, sf->sMyPath + len, dwSize+2 - len); } TRACE("-- (%p)->(my pidl=%p, my path=%s)\n",sf, sf->absPidl,debugstr_a(sf->sMyPath)); pdump (sf->absPidl); } shell32_ObjCount++; return _IShellFolder_(sf); } /************************************************************************** * 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) _CALL_TRACE TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_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->sMyPath); 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->sMyPath, 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; IPersistFolder *pPersistFolder; LPITEMIDLIST absPidl; HRESULT hr; TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",This,pidl,pbcReserved,debugstr_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))) { absPidl = ILCombine (This->absPidl, pidl); IPersistFolder_Initialize(pPersistFolder, absPidl); IPersistFolder_Release(pPersistFolder); SHFree(absPidl); } else { return E_FAIL; } } else if(_ILIsFolder(pidl)) { LPITEMIDLIST pidltemp = ILCloneFirst(pidl); pShellFolder = IShellFolder_Constructor(iface, pidltemp); ILFree(pidltemp); } else { ERR("can't bind to a file\n"); return E_FAIL; } 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; } TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, 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) { _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface) FIXME("(%p)->(pidl=%p,%p,\n\tIID:%s,%p) stub\n", This,pidl,pbcReserved,debugstr_guid(riid),ppvOut); *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; TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n",This,lParam,pidl1,pidl2); pdump (pidl1); pdump (pidl2); 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 */ } } } TRACE("-- res=0x%08lx\n", hr); return hr; } /************************************************************************** * 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,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_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,\n\tIID:%s,%p,%p)\n", This,hwndOwner,cidl,apidl,debugstr_guid(riid),prgfInOut,ppvOut); if (ppvOut) { *ppvOut = NULL; if(IsEqualIID(riid, &IID_IContextMenu) && (cidl >= 1)) { pObj = (LPUNKNOWN)ISvItemCm_Constructor((IShellFolder*)iface, This->absPidl, apidl, cidl); hr = S_OK; } else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1)) { pObj = (LPUNKNOWN)IDataObject_Constructor (hwndOwner, This->absPidl, apidl, cidl); hr = S_OK; } else if (IsEqualIID(riid, &IID_IExtractIconA) && (cidl == 1)) { pidl = ILCombine(This->absPidl,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->sMyPath) { strcpy (szPath, This->sMyPath); /* get path to root*/ PathAddBackslashA(szPath); len = strlen(szPath); } _ILSimpleGetText(pidl, szPath + len, MAX_PATH - len); /* append my own path */ } 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_CSTRA; 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->sMyPath); PathAddBackslashA(szSrc); len = strlen (szSrc); _ILSimpleGetText(pidl, szSrc+len, MAX_PATH-len); } else { SHGetPathFromIDListA(pidl, szSrc); } /* build destination path */ strcpy(szDest, This->sMyPath); 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_CSTRA; 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_CSTRA; } 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)\n", This); return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj); } static ULONG WINAPI ISFHelper_fnAddRef( ISFHelper *iface) { _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface); TRACE("(%p)\n", This); 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->sMyPath); PathAddBackslashA(lpstrNewDir); strcat(lpstrNewDir, lpName); bRes = CreateDirectoryA(lpstrNewDir, NULL); if (bRes) { LPITEMIDLIST pidl, pidlitem; pidlitem = SHSimpleIDListFromPathA(lpstrNewDir); pidl = ILCombine(This->absPidl, 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->sMyPath); 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->absPidl, 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->absPidl, 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; isMyPath); 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 * */ IShellFolder * ISF_Desktop_Constructor() { IGenericSFImpl * sf; sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl)); sf->ref=1; ICOM_VTBL(sf)=&unkvt; sf->lpvtblShellFolder=&sfdvt; sf->absPidl=_ILCreateDesktop(); /* my qualified pidl */ sf->pUnkOuter = (IUnknown *) &sf->lpVtbl; TRACE("(%p)\n",sf); shell32_ObjCount++; return _IShellFolder_(sf); } /************************************************************************** * 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)->(\n\tIID:\t%s,%p)\n",This,debugstr_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) LPCWSTR szNext=NULL; LPITEMIDLIST pidlTemp=NULL; HRESULT hr=E_OUTOFMEMORY; 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 */ /* FIXME no real parsing implemented */ pidlTemp = _ILCreateMyComputer(); 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; HRESULT hr; TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n", This,pidl,pbcReserved,debugstr_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->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder))) { return E_INVALIDARG; } } } else { /* file system folder on the desktop */ LPITEMIDLIST deskpidl, firstpidl, completepidl; IPersistFolder * ppf; /* combine pidls */ SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, &deskpidl); firstpidl = ILCloneFirst(pidl); completepidl = ILCombine(deskpidl, firstpidl); pShellFolder = IShellFolder_Constructor(NULL, NULL); if (SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&ppf))) { 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,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_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_CSTRA; 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_CSTRA; 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_CSTRA; } 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->lpvtblPersistFolder2 = &psfvt; sf->pclsid = (CLSID*)&CLSID_SFMyComp; sf->absPidl=_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; LPITEMIDLIST pidltemp; HRESULT hr; TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n", This,pidl,pbcReserved,debugstr_guid(riid),ppvOut); if(!pidl || !ppvOut) return E_INVALIDARG; *ppvOut = NULL; if ((clsid=_ILGetGUIDPointer(pidl)) && !IsEqualIID(clsid, &CLSID_MyComputer)) { if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder))) { return E_FAIL; } } else { if (!_ILIsDrive(pidl)) return E_INVALIDARG; pidltemp = ILCloneFirst(pidl); pShellFolder = IShellFolder_Constructor(iface, pidltemp); ILFree(pidltemp); } 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,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_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,12,&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_CSTRA; 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_CSTRA; 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_CSTRA; 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 ISFPersistFolder2_QueryInterface( IPersistFolder2 * iface, REFIID iid, LPVOID* ppvObj) { _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface); TRACE("(%p)\n", This); return IUnknown_QueryInterface(This->pUnkOuter, iid, ppvObj); } /************************************************************************ * ISFPersistFolder_AddRef (IUnknown) * */ static ULONG WINAPI ISFPersistFolder2_AddRef( IPersistFolder2 * iface) { _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface); TRACE("(%p)\n", This); return IUnknown_AddRef(This->pUnkOuter); } /************************************************************************ * ISFPersistFolder_Release (IUnknown) * */ static ULONG WINAPI ISFPersistFolder2_Release( IPersistFolder2 * iface) { _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface); TRACE("(%p)\n", This); return IUnknown_Release(This->pUnkOuter); } /************************************************************************ * ISFPersistFolder_GetClassID (IPersist) */ static HRESULT WINAPI ISFPersistFolder2_GetClassID( IPersistFolder2 * iface, CLSID * lpClassId) { _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface); TRACE("(%p)\n", This); if (!lpClassId) return E_POINTER; *lpClassId = *This->pclsid; return S_OK; } /************************************************************************ * ISFPersistFolder_Initialize (IPersistFolder) * * NOTES * sMyPath is not set. Don't know how to handle in a non rooted environment. */ static HRESULT WINAPI ISFPersistFolder2_Initialize( IPersistFolder2 * iface, LPCITEMIDLIST pidl) { char sTemp[MAX_PATH]; _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface); TRACE("(%p)->(%p)\n", This, pidl); /* free the old stuff */ if(This->absPidl) { SHFree(This->absPidl); This->absPidl = NULL; } if(This->sMyPath) { SHFree(This->sMyPath); This->sMyPath = NULL; } /* set my pidl */ This->absPidl = ILClone(pidl); /* set my path */ if (SHGetPathFromIDListA(pidl, sTemp)) { This->sMyPath = SHAlloc(strlen(sTemp)+1); strcpy(This->sMyPath, sTemp); } TRACE("--(%p)->(%s)\n", This, This->sMyPath); return S_OK; } /************************************************************************** * IPersistFolder2_fnGetCurFolder */ static HRESULT WINAPI ISFPersistFolder2_fnGetCurFolder( IPersistFolder2 * iface, LPITEMIDLIST * pidl) { _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface); TRACE("(%p)->(%p)\n",This, pidl); if (!pidl) return E_POINTER; *pidl = ILClone(This->absPidl); return S_OK; } static ICOM_VTABLE(IPersistFolder2) psfvt = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE ISFPersistFolder2_QueryInterface, ISFPersistFolder2_AddRef, ISFPersistFolder2_Release, ISFPersistFolder2_GetClassID, ISFPersistFolder2_Initialize, ISFPersistFolder2_fnGetCurFolder }; /**************************************************************************** * 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 };