| /* | |
| * Shell Folder stuff | |
| * | |
| * Copyright 1997 Marcus Meissner | |
| * Copyright 1998, 1999 Juergen Schmied | |
| * | |
| * IShellFolder2 and related interfaces | |
| * | |
| */ | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <stdio.h> | |
| #include "debugtools.h" | |
| #include "winerror.h" | |
| #include "winbase.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 "wine/undocshell.h" | |
| #include "shell32_main.h" | |
| #include "shresdef.h" | |
| #include "shlwapi.h" | |
| #include "shellfolder.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<dwCopy)? dwOut : dwCopy); | |
| if(*pszTail) | |
| pszTail++; | |
| else | |
| pszTail = NULL; | |
| TRACE("--(%s %s 0x%08lx %p)\n",debugstr_w(pszNext),debugstr_w(pszOut),dwOut,pszTail); | |
| return pszTail; | |
| } | |
| static HRESULT SHELL32_ParseNextElement( | |
| HWND hwndOwner, | |
| IShellFolder2 * psf, | |
| LPITEMIDLIST * pidlInOut, | |
| LPOLESTR szNext, | |
| DWORD *pEaten, | |
| DWORD *pdwAttributes) | |
| { | |
| HRESULT hr = E_OUTOFMEMORY; | |
| LPITEMIDLIST pidlOut, pidlTemp = NULL; | |
| IShellFolder *psfChild; | |
| TRACE("(%p, %p, %s)\n",psf, pidlInOut ? *pidlInOut : NULL, debugstr_w(szNext)); | |
| /* get the shellfolder for the child pidl and let it analyse further */ | |
| hr = IShellFolder_BindToObject(psf, *pidlInOut, NULL, &IID_IShellFolder, (LPVOID*)&psfChild); | |
| if (psfChild) | |
| { | |
| hr = IShellFolder_ParseDisplayName(psfChild, hwndOwner, NULL, szNext, pEaten, &pidlOut, pdwAttributes); | |
| IShellFolder_Release(psfChild); | |
| pidlTemp = ILCombine(*pidlInOut, pidlOut); | |
| if (pidlOut) | |
| ILFree(pidlOut); | |
| } | |
| ILFree(*pidlInOut); | |
| *pidlInOut = pidlTemp; | |
| TRACE("-- pidl=%p ret=0x%08lx\n", pidlInOut? *pidlInOut: NULL, hr); | |
| return hr; | |
| } | |
| /*********************************************************************** | |
| * SHELL32_CoCreateInitSF | |
| * | |
| * creates a initialized shell folder | |
| */ | |
| static HRESULT SHELL32_CoCreateInitSF ( | |
| LPITEMIDLIST pidlRoot, | |
| LPITEMIDLIST pidlChild, | |
| REFCLSID clsid, | |
| REFIID iid, | |
| LPVOID * ppvOut) | |
| { | |
| HRESULT hr; | |
| LPITEMIDLIST absPidl; | |
| IShellFolder2 *pShellFolder; | |
| IPersistFolder *pPersistFolder; | |
| TRACE("%p %p\n", pidlRoot, pidlChild); | |
| *ppvOut = NULL; | |
| /* we have to ask first for IPersistFolder, some special folders are expecting this */ | |
| hr = SHCoCreateInstance(NULL, clsid, NULL, &IID_IPersistFolder, (LPVOID*)&pPersistFolder); | |
| if (SUCCEEDED(hr)) | |
| { | |
| hr = IPersistFolder_QueryInterface(pPersistFolder, iid, (LPVOID*)&pShellFolder); | |
| if (SUCCEEDED(hr)) | |
| { | |
| absPidl = ILCombine (pidlRoot, pidlChild); | |
| hr = IPersistFolder_Initialize(pPersistFolder, absPidl); | |
| IPersistFolder_Release(pPersistFolder); | |
| SHFree(absPidl); | |
| *ppvOut = pShellFolder; | |
| } | |
| } | |
| TRACE("-- ret=0x%08lx\n", hr); | |
| return hr; | |
| } | |
| static HRESULT SHELL32_GetDisplayNameOfChild( | |
| IShellFolder2 * psf, | |
| LPCITEMIDLIST pidl, | |
| DWORD dwFlags, | |
| LPSTR szOut, | |
| DWORD dwOutLen) | |
| { | |
| LPITEMIDLIST pidlFirst, pidlNext; | |
| IShellFolder2 * psfChild; | |
| HRESULT hr = E_OUTOFMEMORY; | |
| STRRET strTemp; | |
| TRACE("(%p)->(pidl=%p 0x%08lx %p 0x%08lx)\n",psf,pidl,dwFlags,szOut, dwOutLen); | |
| pdump(pidl); | |
| if ((pidlFirst = ILCloneFirst(pidl))) | |
| { | |
| hr = IShellFolder_BindToObject(psf, pidlFirst, NULL, &IID_IShellFolder, (LPVOID*)&psfChild); | |
| if (SUCCEEDED(hr)) | |
| { | |
| pidlNext = ILGetNext(pidl); | |
| hr = IShellFolder_GetDisplayNameOf(psfChild, pidlNext, dwFlags | SHGDN_INFOLDER, &strTemp); | |
| if (SUCCEEDED(hr)) | |
| { | |
| hr = StrRetToStrNA(szOut, dwOutLen, &strTemp, pidlNext); | |
| } | |
| 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; | |
| 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)) | |
| { | |
| *ppvOut = pShellFolder; | |
| } | |
| else | |
| { | |
| IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, &IID_IShellFolder, (LPVOID)&pSubFolder); | |
| IShellFolder_Release(pShellFolder); | |
| *ppvOut = pSubFolder; | |
| } | |
| TRACE("-- (%p) returning (%p)\n",This, *ppvOut); | |
| return S_OK; | |
| } | |
| /************************************************************************** | |
| * 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 | |
| { | |
| 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 | |
| * | |
| * copys 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->sMyPath); | |
| 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; | |
| 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; | |
| } | |
| else /* go deeper */ | |
| { | |
| IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, riid, (LPVOID)&pSubFolder); | |
| IShellFolder_Release(pShellFolder); | |
| *ppvOut = pSubFolder; | |
| } | |
| TRACE("-- (%p) returning (%p)\n",This, *ppvOut); | |
| return S_OK; | |
| } | |
| /************************************************************************** | |
| * 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; | |
| 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; | |
| } | |
| else /* go deeper */ | |
| { | |
| IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, &IID_IShellFolder, (LPVOID)&pSubFolder); | |
| IShellFolder_Release(pShellFolder); | |
| *ppvOut = pSubFolder; | |
| } | |
| TRACE("-- (%p) returning (%p)\n",This, *ppvOut); | |
| return S_OK; | |
| } | |
| /************************************************************************** | |
| * 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 | |
| }; |