| /* |
| * Shell Folder stuff |
| * |
| * Copyright 1997 Marcus Meissner |
| * Copyright 1998, 1999 Juergen Schmied |
| * |
| * IShellFolder2 and related interfaces |
| * |
| */ |
| |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "debugtools.h" |
| #include "winerror.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" |
| |
| 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; |
| } |
| |
| /*********************************************************************** |
| * IShellFolder implementation |
| */ |
| |
| typedef struct |
| { |
| ICOM_VFIELD(IUnknown); |
| DWORD ref; |
| ICOM_VTABLE(IShellFolder2)* lpvtblShellFolder;; |
| ICOM_VTABLE(IPersistFolder)* lpvtblPersistFolder; |
| ICOM_VTABLE(IDropTarget)* lpvtblDropTarget; |
| |
| 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(IPersistFolder) psfvt; |
| static struct ICOM_VTABLE(IDropTarget) dtvt; |
| |
| 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)->lpvtblPersistFolder))) |
| #define _ICOM_THIS_From_IPersistFolder(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); |
| |
| /* |
| 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->lpvtblPersistFolder) |
| #define _IPersistFolder_(This) (IPersistFolder*)&(This->lpvtblPersistFolder) |
| #define _IDropTarget_(This) (IDropTarget*)&(This->lpvtblDropTarget) |
| /************************************************************************** |
| * registers clipboardformat once |
| */ |
| static void SF_RegisterClipFmt (IGenericSFImpl * This) |
| { |
| TRACE("(%p)\n", This); |
| |
| if (!This->cfShellIDList) |
| { |
| This->cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST); |
| } |
| } |
| |
| /************************************************************************** |
| * we need a seperate 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_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->lpvtblPersistFolder=&psfvt; |
| sf->lpvtblDropTarget=&dtvt; |
| 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->lpvtblPersistFolder=&psfvt; |
| sf->lpvtblDropTarget=&dtvt; |
| 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 trys to parse only it's 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 */ |
| WideCharToLocal(szTempA, szElement, lstrlenW(szElement) + 1); |
| 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 |
| { |
| hr = S_OK; |
| } |
| } |
| } |
| |
| *ppidl = pidlTemp; |
| |
| 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 |
| { |
| LPITEMIDLIST pidltemp = ILCloneFirst(pidl); |
| pShellFolder = IShellFolder_Constructor(iface, pidltemp); |
| ILFree(pidltemp); |
| } |
| |
| 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); |
| if (_ILIsFolder( *apidl)) |
| { |
| *rgfInOut &= 0xe0000177; |
| goto next; |
| } |
| else if (_ILIsValue( *apidl)) |
| { |
| *rgfInOut &= 0x40000177; |
| goto next; |
| } |
| hr = E_INVALIDARG; |
| |
| next: 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)->(%u,%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)IContextMenu_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 dw, |
| LPITEMIDLIST *pPidlOut) |
| { |
| _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface) |
| |
| FIXME("(%p)->(%u,pidl=%p,%s,%lu,%p),stub!\n", |
| This,hwndOwner,pidl,debugstr_w(lpName),dw,pPidlOut); |
| |
| return E_NOTIMPL; |
| } |
| |
| /************************************************************************** |
| * IShellFolder_fnGetFolderPath |
| */ |
| static HRESULT WINAPI IShellFolder_fnGetFolderPath(IShellFolder2 * iface, LPSTR lpszOut, DWORD dwOutSize) |
| { |
| _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface) |
| |
| TRACE("(%p)->(%p %lu)\n",This, lpszOut, dwOutSize); |
| |
| if (!lpszOut) return FALSE; |
| |
| *lpszOut=0; |
| |
| if (! This->sMyPath) return FALSE; |
| |
| lstrcpynA(lpszOut, This->sMyPath, dwOutSize); |
| |
| TRACE("-- (%p)->(return=%s)\n",This, lpszOut); |
| return TRUE; |
| } |
| |
| 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 |
| }; |
| /*********************************************************************** |
| * [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; |
| } |
| |
| *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)) |
| { |
| FIXME("IDropTarget not implemented\n"); |
| hr = E_NOTIMPL; |
| } |
| 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; |
| } |
| |
| /************************************************************************** |
| * ISF_Desktop_fnGetAttributesOf |
| */ |
| static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf(IShellFolder2 * iface,UINT cidl,LPCITEMIDLIST *apidl,DWORD *rgfInOut) |
| { |
| _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface) |
| |
| GUID const * clsid; |
| DWORD attributes; |
| 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); |
| |
| if ((clsid=_ILGetGUIDPointer(*apidl))) |
| { |
| if (IsEqualIID(clsid, &CLSID_MyComputer)) |
| { |
| *rgfInOut &= 0xb0000154; |
| goto next; |
| } |
| else if (HCR_GetFolderAttributes(clsid, &attributes)) |
| { |
| *rgfInOut &= attributes; |
| goto next; |
| } |
| else |
| { /* some shell-extension */ |
| *rgfInOut &= 0xb0000154; |
| } |
| } |
| else if (_ILIsFolder( *apidl)) |
| { |
| *rgfInOut &= 0xe0000177; |
| goto next; |
| } |
| else if (_ILIsValue( *apidl)) |
| { |
| *rgfInOut &= 0x40000177; |
| goto next; |
| } |
| hr = E_INVALIDARG; |
| |
| next: 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->lpvtblPersistFolder = &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 */ |
| |
| if (PathIsRootW(lpszDisplayName)) |
| { |
| szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH); |
| WideCharToLocal(szTempA, szElement, lstrlenW(szElement) + 1); |
| pidlTemp = _ILCreateDrive(szTempA); |
| |
| if (szNext && *szNext) |
| { |
| hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes); |
| } |
| else |
| { |
| 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)) |
| { |
| FIXME("IDropTarget not implemented\n"); |
| hr = E_NOTIMPL; |
| } |
| 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; |
| } |
| |
| /************************************************************************** |
| * ISF_MyComputer_fnGetAttributesOf |
| */ |
| static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf(IShellFolder2 * iface,UINT cidl,LPCITEMIDLIST *apidl,DWORD *rgfInOut) |
| { |
| _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface) |
| |
| GUID const * clsid; |
| DWORD attributes; |
| 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; |
| |
| *rgfInOut = 0xffffffff; |
| |
| while (cidl > 0 && *apidl) |
| { |
| pdump (*apidl); |
| |
| if (_ILIsDrive(*apidl)) |
| { |
| *rgfInOut &= 0xf0000144; |
| goto next; |
| } |
| else if ((clsid=_ILGetGUIDPointer(*apidl))) |
| { |
| if (HCR_GetFolderAttributes(clsid, &attributes)) |
| { |
| *rgfInOut &= attributes; |
| goto next; |
| } |
| } |
| hr = E_INVALIDARG; |
| |
| next: 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 ISFPersistFolder_QueryInterface( |
| IPersistFolder * iface, |
| REFIID iid, |
| LPVOID* ppvObj) |
| { |
| _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface); |
| |
| TRACE("(%p)\n", This); |
| |
| return IUnknown_QueryInterface(This->pUnkOuter, iid, ppvObj); |
| } |
| |
| /************************************************************************ |
| * ISFPersistFolder_AddRef (IUnknown) |
| * |
| */ |
| static ULONG WINAPI ISFPersistFolder_AddRef( |
| IPersistFolder * iface) |
| { |
| _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface); |
| |
| TRACE("(%p)\n", This); |
| |
| return IUnknown_AddRef(This->pUnkOuter); |
| } |
| |
| /************************************************************************ |
| * ISFPersistFolder_Release (IUnknown) |
| * |
| */ |
| static ULONG WINAPI ISFPersistFolder_Release( |
| IPersistFolder * iface) |
| { |
| _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface); |
| |
| TRACE("(%p)\n", This); |
| |
| return IUnknown_Release(This->pUnkOuter); |
| } |
| |
| /************************************************************************ |
| * ISFPersistFolder_GetClassID (IPersist) |
| */ |
| static HRESULT WINAPI ISFPersistFolder_GetClassID( |
| IPersistFolder * iface, |
| CLSID * lpClassId) |
| { |
| _ICOM_THIS_From_IPersistFolder(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 ISFPersistFolder_Initialize( |
| IPersistFolder * iface, |
| LPCITEMIDLIST pidl) |
| { |
| char sTemp[MAX_PATH]; |
| _ICOM_THIS_From_IPersistFolder(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; |
| } |
| |
| static ICOM_VTABLE(IPersistFolder) psfvt = |
| { |
| ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE |
| ISFPersistFolder_QueryInterface, |
| ISFPersistFolder_AddRef, |
| ISFPersistFolder_Release, |
| ISFPersistFolder_GetClassID, |
| ISFPersistFolder_Initialize |
| }; |
| |
| /**************************************************************************** |
| * 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 |
| }; |
| |